Merge lp:~albertomilone/unity-settings-daemon/lp1287341-14.10 into lp:unity-settings-daemon/14.04
- lp1287341-14.10
- Merge into 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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Sebastien Bacher | Approve | ||
Review via email:
|
Commit message
Description of the change
To post a comment you must log in.
- 4048. By Alberto Milone
-
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 |
let's sru that one