Merge lp:~albertomilone/unity-settings-daemon/lp1287341-14.10 into lp:unity-settings-daemon/14.04

Proposed by Sebastien Bacher
Status: Merged
Approved by: Sebastien Bacher
Approved revision: 4047
Merged at revision: 4041
Proposed branch: lp:~albertomilone/unity-settings-daemon/lp1287341-14.10
Merge into: lp:unity-settings-daemon/14.04
Diff against target: 381 lines (+295/-0)
4 files modified
debian/changelog (+19/-0)
plugins/common/gsd-input-helper.c (+49/-0)
plugins/common/gsd-input-helper.h (+3/-0)
plugins/xrandr/gsd-xrandr-manager.c (+224/-0)
To merge this branch: bzr merge lp:~albertomilone/unity-settings-daemon/lp1287341-14.10
Reviewer Review Type Date Requested Status
Sebastien Bacher Approve
Review via email: mp+222071@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Sebastien Bacher (seb128) wrote :

let's sru that one

review: Approve
4048. By Alberto Milone on 2014-06-05

gsd-xrandr-manager.c: do not try to map an invalid touch device on initialisation

Fixes LP: #1326636

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2014-04-14 10:13:11 +0000
3+++ debian/changelog 2014-06-05 11:56:47 +0000
4@@ -1,3 +1,22 @@
5+unity-settings-daemon (14.04.0+14.04.20140414-0ubuntu2) UNRELEASED; urgency=medium
6+
7+ [ Alberto Milone ]
8+ * gsd-xrandr-manager.c:
9+ - Add support for mapping the main touchscreen onto the laptop
10+ display (LP: #1287341).
11+ This makes sure that the input device knows exactly the area
12+ that represents the display when the screen configuration
13+ changes. Note: this doesn't cover the tablet use case.
14+ - Add support for matching displays with touch input devices
15+ according to the reported size. This is particularly
16+ useful on systems that don't use embedded display connectors
17+ i.e. all-in-one systems such as the Dell Optiplex 9030 AIO.
18+ - This work is a partial backport of the upstream work on
19+ touchscreens. When we finally sync with the upstream code
20+ we can drop this.
21+
22+ -- Alberto Milone <alberto.milone@canonical.com> Fri, 23 May 2014 12:01:11 +0200
23+
24 unity-settings-daemon (14.04.0+14.04.20140414-0ubuntu1) trusty; urgency=low
25
26 [ Dmitry Shachnev ]
27
28=== modified file 'plugins/common/gsd-input-helper.c'
29--- plugins/common/gsd-input-helper.c 2013-02-07 04:14:22 +0000
30+++ plugins/common/gsd-input-helper.c 2014-06-05 11:56:47 +0000
31@@ -34,6 +34,11 @@
32 #define INPUT_DEVICES_SCHEMA "org.gnome.settings-daemon.peripherals.input-devices"
33 #define KEY_HOTPLUG_COMMAND "hotplug-command"
34
35+#define ABS_MT_X "Abs MT Position X"
36+#define ABS_MT_Y "Abs MT Position Y"
37+#define ABS_X "Abs X"
38+#define ABS_Y "Abs Y"
39+
40 typedef gboolean (* InfoIdentifyFunc) (XDeviceInfo *device_info);
41 typedef gboolean (* DeviceIdentifyFunc) (XDevice *xdevice);
42
43@@ -571,3 +576,47 @@
44
45 return ret;
46 }
47+
48+gboolean
49+xdevice_get_dimensions (int deviceid,
50+ guint *width,
51+ guint *height)
52+{
53+ GdkDisplay *display = gdk_display_get_default ();
54+ XIDeviceInfo *info;
55+ guint *value, w, h;
56+ int i, n_info;
57+
58+ info = XIQueryDevice (GDK_DISPLAY_XDISPLAY (display), deviceid, &n_info);
59+ *width = *height = w = h = 0;
60+
61+ if (!info)
62+ return FALSE;
63+
64+ for (i = 0; i < info->num_classes; i++) {
65+ XIValuatorClassInfo *valuator_info;
66+
67+ if (info->classes[i]->type != XIValuatorClass)
68+ continue;
69+
70+ valuator_info = (XIValuatorClassInfo *) info->classes[i];
71+
72+ if (valuator_info->label == gdk_x11_get_xatom_by_name_for_display (display, ABS_X) ||
73+ valuator_info->label == gdk_x11_get_xatom_by_name_for_display (display, ABS_MT_X))
74+ value = &w;
75+ else if (valuator_info->label == gdk_x11_get_xatom_by_name_for_display (display, ABS_Y) ||
76+ valuator_info->label == gdk_x11_get_xatom_by_name_for_display (display, ABS_MT_Y))
77+ value = &h;
78+ else
79+ continue;
80+
81+ *value = (valuator_info->max - valuator_info->min) * 1000 / valuator_info->resolution;
82+ }
83+
84+ *width = w;
85+ *height = h;
86+
87+ XIFreeDeviceInfo (info);
88+
89+ return (w != 0 && h != 0);
90+}
91
92=== modified file 'plugins/common/gsd-input-helper.h'
93--- plugins/common/gsd-input-helper.h 2013-01-21 17:01:42 +0000
94+++ plugins/common/gsd-input-helper.h 2014-06-05 11:56:47 +0000
95@@ -81,6 +81,9 @@
96 GList * get_disabled_devices (GdkDeviceManager *manager);
97 char * xdevice_get_device_node (int deviceid);
98 int xdevice_get_last_tool_id (int deviceid);
99+gboolean xdevice_get_dimensions (int deviceid,
100+ guint *width,
101+ guint *height);
102
103 G_END_DECLS
104
105
106=== modified file 'plugins/xrandr/gsd-xrandr-manager.c'
107--- plugins/xrandr/gsd-xrandr-manager.c 2013-12-04 23:55:26 +0000
108+++ plugins/xrandr/gsd-xrandr-manager.c 2014-06-05 11:56:47 +0000
109@@ -127,6 +127,9 @@
110 #ifdef HAVE_WACOM
111 WacomDeviceDatabase *wacom_db;
112 #endif /* HAVE_WACOM */
113+
114+ int main_touchscreen_id;
115+ gchar *main_touchscreen_name;
116 };
117
118 static const GnomeRRRotation possible_rotations[] = {
119@@ -157,6 +160,10 @@
120
121 static FILE *log_file;
122
123+static GnomeRROutput * input_info_find_size_match (GsdXrandrManager *manager, GnomeRRScreen *rr_screen);
124+static int map_touch_to_output (GnomeRRScreen *screen, int device_id, GnomeRROutputInfo *output);
125+static void do_touchscreen_mapping (GsdXrandrManager *manager);
126+
127 static void
128 log_open (void)
129 {
130@@ -1818,6 +1825,12 @@
131 use_stored_configuration_or_auto_configure_outputs (manager, config_timestamp);
132 }
133
134+ if (priv->main_touchscreen_id != -1) {
135+ /* Set mapping of input devices onto displays */
136+ log_msg ("\nSetting touchscreen mapping on RandR event\n");
137+ do_touchscreen_mapping (manager);
138+ }
139+
140 log_close ();
141 }
142
143@@ -2033,6 +2046,206 @@
144 }
145 }
146
147+static gboolean
148+matches_name (GnomeRROutputInfo *output, GnomeRROutput *to_match)
149+{
150+ return (g_strcmp0 (gnome_rr_output_info_get_name (output),
151+ gnome_rr_output_get_name (to_match) ) == 0);
152+}
153+
154+static gint
155+monitor_for_output (GnomeRROutput *output)
156+{
157+ GdkScreen *screen = gdk_screen_get_default ();
158+ GnomeRRCrtc *crtc = gnome_rr_output_get_crtc (output);
159+ gint x, y;
160+
161+ if (!crtc)
162+ return -1;
163+
164+ gnome_rr_crtc_get_position (crtc, &x, &y);
165+
166+ return gdk_screen_get_monitor_at_point (screen, x, y);
167+}
168+
169+static gboolean
170+output_get_dimensions (GnomeRROutput *output,
171+ guint *width,
172+ guint *height)
173+{
174+ GdkScreen *screen = gdk_screen_get_default ();
175+ gint monitor_num;
176+
177+ monitor_num = monitor_for_output (output);
178+
179+ if (monitor_num < 0)
180+ return FALSE;
181+
182+ *width = gdk_screen_get_monitor_width_mm (screen, monitor_num);
183+ *height = gdk_screen_get_monitor_height_mm (screen, monitor_num);
184+ return TRUE;
185+}
186+
187+static GnomeRROutput *
188+input_info_find_size_match (GsdXrandrManager *manager, GnomeRRScreen *rr_screen)
189+{
190+ guint i, input_width, input_height, output_width, output_height;
191+ gdouble min_width_diff, min_height_diff;
192+ GnomeRROutput **outputs, *match = NULL;
193+ GsdXrandrManagerPrivate *priv = manager->priv;
194+
195+ g_return_val_if_fail (rr_screen != NULL, NULL);
196+
197+ if (!xdevice_get_dimensions (priv->main_touchscreen_id,
198+ &input_width, &input_height))
199+ return NULL;
200+
201+ /* Restrict the matches to be below a narrow percentage */
202+ min_width_diff = min_height_diff = 0.05;
203+
204+ g_debug ("Input device '%s' has %dx%d mm",
205+ priv->main_touchscreen_name, input_width, input_height);
206+
207+ outputs = gnome_rr_screen_list_outputs (rr_screen);
208+
209+ for (i = 0; outputs[i] != NULL; i++) {
210+ gdouble width_diff, height_diff;
211+ if (!output_get_dimensions (outputs[i], &output_width, &output_height))
212+ continue;
213+
214+ width_diff = ABS (1 - ((gdouble) output_width / input_width));
215+ height_diff = ABS (1 - ((gdouble) output_height / input_height));
216+
217+ g_debug ("Output '%s' has size %dx%d mm, deviation from "
218+ "input device size: %.2f width, %.2f height ",
219+ gnome_rr_output_get_name (outputs[i]),
220+ output_width, output_height, width_diff, height_diff);
221+
222+ if (width_diff <= min_width_diff && height_diff <= min_height_diff) {
223+ match = outputs[i];
224+ min_width_diff = width_diff;
225+ min_height_diff = height_diff;
226+ }
227+ }
228+
229+ if (match) {
230+ g_debug ("Output '%s' is considered a best size match (%.2f / %.2f)",
231+ gnome_rr_output_get_name (match),
232+ min_width_diff, min_height_diff);
233+ } else {
234+ g_debug ("No input/output size match was found\n");
235+ }
236+
237+ return match;
238+}
239+
240+static GnomeRROutputInfo *
241+get_mappable_output_info (GsdXrandrManager *manager, GnomeRRScreen *screen, GnomeRRConfig *config)
242+{
243+ int i;
244+ GnomeRROutputInfo **outputs = gnome_rr_config_get_outputs (config);
245+
246+ GnomeRROutput *size_match = NULL;
247+
248+ size_match = input_info_find_size_match (manager, screen);
249+
250+ for (i = 0; outputs[i] != NULL; i++) {
251+ if (is_laptop (screen, outputs[i]) || (size_match && matches_name (outputs[i], size_match)))
252+ return outputs[i];
253+ }
254+
255+ return NULL;
256+}
257+
258+static void
259+set_touchscreen_id (GsdXrandrManager *manager)
260+{
261+ GsdXrandrManagerPrivate *priv = manager->priv;
262+ XDeviceInfo *device_info;
263+ int n_devices;
264+ int i;
265+
266+ device_info = XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
267+ &n_devices);
268+ if (device_info == NULL)
269+ return;
270+
271+ for (i = 0; i < n_devices; i++) {
272+ if (device_info_is_touchscreen (&device_info[i])) {
273+ /* Let's deal only with the 1st touchscreen */
274+ priv->main_touchscreen_id = (int)device_info[i].id;
275+ priv->main_touchscreen_name = g_strdup (device_info[i].name);
276+ break;
277+ }
278+ }
279+
280+ XFreeDeviceList (device_info);
281+}
282+
283+static int
284+map_touch_to_output (GnomeRRScreen *screen, int device_id,
285+ GnomeRROutputInfo *output)
286+{
287+ int status = 0;
288+ char command[100];
289+ gchar *name = gnome_rr_output_info_get_name (output);
290+
291+ if (!name) {
292+ g_debug ("Failure to map screen with missing name");
293+ status = 1;
294+ goto out;
295+ }
296+
297+ if (gnome_rr_output_info_is_active(output)) {
298+ g_debug ("Mapping touchscreen %d onto output %s",
299+ device_id, name);
300+ sprintf (command, "xinput --map-to-output %d %s",
301+ device_id, name);
302+ status = system (command);
303+ }
304+ else {
305+ g_debug ("No need to map %d onto output %s. The output is off",
306+ device_id, name);
307+ }
308+
309+out:
310+ return (status == 0);
311+}
312+
313+static void
314+do_touchscreen_mapping (GsdXrandrManager *manager)
315+{
316+ GsdXrandrManagerPrivate *priv = manager->priv;
317+ GnomeRRScreen *screen = priv->rw_screen;
318+ GnomeRRConfig *current;
319+ GnomeRROutputInfo *laptop_output;
320+
321+ if (!supports_xinput_devices ())
322+ return;
323+
324+ current = gnome_rr_config_new_current (screen, NULL);
325+ laptop_output = get_mappable_output_info (manager, screen, current);
326+
327+ if (laptop_output == NULL) {
328+ g_debug ("No laptop screen detected");
329+ goto out;
330+ }
331+
332+ if (priv->main_touchscreen_id != -1) {
333+ /* Set initial mapping */
334+ g_debug ("Setting initial touchscreen mapping");
335+ map_touch_to_output (screen,
336+ priv->main_touchscreen_id,
337+ laptop_output);
338+ }
339+ else {
340+ g_debug ("No main touchscreen detected");
341+ }
342+
343+out:
344+ g_object_unref (current);
345+}
346+
347 gboolean
348 gsd_xrandr_manager_start (GsdXrandrManager *manager,
349 GError **error)
350@@ -2071,6 +2284,11 @@
351 if (!apply_default_configuration_from_file (manager, GDK_CURRENT_TIME))
352 apply_default_boot_configuration (manager, GDK_CURRENT_TIME);
353
354+ /* Initialise touchscreen mapping */
355+ set_touchscreen_id (manager);
356+ if (manager->priv->main_touchscreen_id != -1)
357+ do_touchscreen_mapping (manager);
358+
359 log_msg ("State of screen after initial configuration:\n");
360 log_screen (manager->priv->rw_screen);
361
362@@ -2127,6 +2345,8 @@
363 }
364 #endif /* HAVE_WACOM */
365
366+ g_free (manager->priv->main_touchscreen_name);
367+
368 log_open ();
369 log_msg ("STOPPING XRANDR PLUGIN\n------------------------------------------------------------\n");
370 log_close ();
371@@ -2149,6 +2369,10 @@
372
373 manager->priv->current_fn_f7_config = -1;
374 manager->priv->fn_f7_configs = NULL;
375+
376+ /* For touchscreen mapping */
377+ manager->priv->main_touchscreen_id = -1;
378+ manager->priv->main_touchscreen_name = NULL;
379 }
380
381 static void

Subscribers

People subscribed via source and target branches