Merge lp:~ossug-hychen/gnome-settings-daemon/fix-868400-oneiric into lp:ubuntu/oneiric-proposed/gnome-settings-daemon
- fix-868400-oneiric
- Merge into oneiric-proposed
Proposed by
James M. Leddy
Status: | Merged |
---|---|
Merge reported by: | Dimitri John Ledkov |
Merged at revision: | not available |
Proposed branch: | lp:~ossug-hychen/gnome-settings-daemon/fix-868400-oneiric |
Merge into: | lp:ubuntu/oneiric-proposed/gnome-settings-daemon |
Diff against target: |
1419 lines (+1348/-1) 6 files modified
.pc/52_kill_syndaemon_when_gsd_die.patch/plugins/mouse/gsd-mouse-manager.c (+1229/-0) .pc/applied-patches (+1/-0) debian/changelog (+10/-0) debian/patches/52_kill_syndaemon_when_gsd_die.patch (+76/-0) debian/patches/series (+1/-0) plugins/mouse/gsd-mouse-manager.c (+31/-1) |
To merge this branch: | bzr merge lp:~ossug-hychen/gnome-settings-daemon/fix-868400-oneiric |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Dimitri John Ledkov | Approve | ||
Marc Deslauriers | Needs Fixing | ||
Review via email: mp+117358@code.launchpad.net |
Commit message
Description of the change
SRU from Precise that ensures that there is only ever one syndaemon process running.
To post a comment you must log in.
- 185. By Hsin-Yi, Chen (hychen)
-
* To remove "[ Hsin-Yi, Chen (hychen) ]" from debian/changelog, it's redundant
* To fix typo in debian/changelog
* To revert modifications to older lines in the debian/changelog file - 186. By Hsin-Yi, Chen (hychen)
-
* To tag the patch by using DEP-3: http://
dep.debian. net/deps/ dep3/
Revision history for this message
Dimitri John Ledkov (xnox) wrote : | # |
Looks good. Uploaded.
[ubuntu/
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added directory '.pc/52_kill_syndaemon_when_gsd_die.patch' |
2 | === added file '.pc/52_kill_syndaemon_when_gsd_die.patch/.timestamp' |
3 | === added directory '.pc/52_kill_syndaemon_when_gsd_die.patch/plugins' |
4 | === added directory '.pc/52_kill_syndaemon_when_gsd_die.patch/plugins/mouse' |
5 | === added file '.pc/52_kill_syndaemon_when_gsd_die.patch/plugins/mouse/gsd-mouse-manager.c' |
6 | --- .pc/52_kill_syndaemon_when_gsd_die.patch/plugins/mouse/gsd-mouse-manager.c 1970-01-01 00:00:00 +0000 |
7 | +++ .pc/52_kill_syndaemon_when_gsd_die.patch/plugins/mouse/gsd-mouse-manager.c 2012-08-09 06:39:20 +0000 |
8 | @@ -0,0 +1,1229 @@ |
9 | +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- |
10 | + * |
11 | + * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu> |
12 | + * |
13 | + * This program is free software; you can redistribute it and/or modify |
14 | + * it under the terms of the GNU General Public License as published by |
15 | + * the Free Software Foundation; either version 2 of the License, or |
16 | + * (at your option) any later version. |
17 | + * |
18 | + * This program is distributed in the hope that it will be useful, |
19 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
20 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
21 | + * GNU General Public License for more details. |
22 | + * |
23 | + * You should have received a copy of the GNU General Public License |
24 | + * along with this program; if not, write to the Free Software |
25 | + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
26 | + * |
27 | + */ |
28 | + |
29 | +#include "config.h" |
30 | + |
31 | +#include <sys/types.h> |
32 | +#include <sys/wait.h> |
33 | +#include <stdlib.h> |
34 | +#include <stdio.h> |
35 | +#include <unistd.h> |
36 | +#include <string.h> |
37 | +#include <errno.h> |
38 | +#include <math.h> |
39 | + |
40 | +#include <locale.h> |
41 | + |
42 | +#include <glib.h> |
43 | +#include <glib/gi18n.h> |
44 | +#include <gio/gio.h> |
45 | +#include <gtk/gtk.h> |
46 | +#include <gdk/gdk.h> |
47 | +#include <gdk/gdkx.h> |
48 | +#include <gdk/gdkkeysyms.h> |
49 | +#include <X11/keysym.h> |
50 | +#include <X11/Xatom.h> |
51 | + |
52 | +#include <X11/extensions/XInput.h> |
53 | +#include <X11/extensions/XIproto.h> |
54 | + |
55 | +#include "gnome-settings-profile.h" |
56 | +#include "gsd-mouse-manager.h" |
57 | +#include "gsd-input-helper.h" |
58 | +#include "gsd-enums.h" |
59 | + |
60 | +#define GSD_MOUSE_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_MOUSE_MANAGER, GsdMouseManagerPrivate)) |
61 | + |
62 | +#define SETTINGS_MOUSE_DIR "org.gnome.settings-daemon.peripherals.mouse" |
63 | +#define SETTINGS_TOUCHPAD_DIR "org.gnome.settings-daemon.peripherals.touchpad" |
64 | + |
65 | +/* Keys for both touchpad and mouse */ |
66 | +#define KEY_LEFT_HANDED "left-handed" /* a boolean for mouse, an enum for touchpad */ |
67 | +#define KEY_MOTION_ACCELERATION "motion-acceleration" |
68 | +#define KEY_MOTION_THRESHOLD "motion-threshold" |
69 | + |
70 | +/* Touchpad settings */ |
71 | +#define KEY_TOUCHPAD_DISABLE_W_TYPING "disable-while-typing" |
72 | +#define KEY_PAD_HORIZ_SCROLL "horiz-scroll-enabled" |
73 | +#define KEY_SCROLL_METHOD "scroll-method" |
74 | +#define KEY_TAP_TO_CLICK "tap-to-click" |
75 | +#define KEY_TOUCHPAD_ENABLED "touchpad-enabled" |
76 | + |
77 | +/* Mouse settings */ |
78 | +#define KEY_LOCATE_POINTER "locate-pointer" |
79 | +#define KEY_DWELL_CLICK_ENABLED "dwell-click-enabled" |
80 | +#define KEY_SECONDARY_CLICK_ENABLED "secondary-click-enabled" |
81 | +#define KEY_MIDDLE_BUTTON_EMULATION "middle-button-enabled" |
82 | + |
83 | +struct GsdMouseManagerPrivate |
84 | +{ |
85 | + guint start_idle_id; |
86 | + GSettings *touchpad_settings; |
87 | + GSettings *mouse_settings; |
88 | + GSettings *mouse_a11y_settings; |
89 | + GdkDeviceManager *device_manager; |
90 | + guint device_added_id; |
91 | + guint device_removed_id; |
92 | + GHashTable *blacklist; |
93 | + |
94 | + gboolean mousetweaks_daemon_running; |
95 | + gboolean syndaemon_spawned; |
96 | + GPid syndaemon_pid; |
97 | + gboolean locate_pointer_spawned; |
98 | + GPid locate_pointer_pid; |
99 | +}; |
100 | + |
101 | +static void gsd_mouse_manager_class_init (GsdMouseManagerClass *klass); |
102 | +static void gsd_mouse_manager_init (GsdMouseManager *mouse_manager); |
103 | +static void gsd_mouse_manager_finalize (GObject *object); |
104 | +static void set_tap_to_click (GdkDevice *device, |
105 | + gboolean state, |
106 | + gboolean left_handed); |
107 | + |
108 | +G_DEFINE_TYPE (GsdMouseManager, gsd_mouse_manager, G_TYPE_OBJECT) |
109 | + |
110 | +static gpointer manager_object = NULL; |
111 | + |
112 | +static void |
113 | +gsd_mouse_manager_set_property (GObject *object, |
114 | + guint prop_id, |
115 | + const GValue *value, |
116 | + GParamSpec *pspec) |
117 | +{ |
118 | + switch (prop_id) { |
119 | + default: |
120 | + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
121 | + break; |
122 | + } |
123 | +} |
124 | + |
125 | +static void |
126 | +gsd_mouse_manager_get_property (GObject *object, |
127 | + guint prop_id, |
128 | + GValue *value, |
129 | + GParamSpec *pspec) |
130 | +{ |
131 | + switch (prop_id) { |
132 | + default: |
133 | + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
134 | + break; |
135 | + } |
136 | +} |
137 | + |
138 | +static GObject * |
139 | +gsd_mouse_manager_constructor (GType type, |
140 | + guint n_construct_properties, |
141 | + GObjectConstructParam *construct_properties) |
142 | +{ |
143 | + GsdMouseManager *mouse_manager; |
144 | + |
145 | + mouse_manager = GSD_MOUSE_MANAGER (G_OBJECT_CLASS (gsd_mouse_manager_parent_class)->constructor (type, |
146 | + n_construct_properties, |
147 | + construct_properties)); |
148 | + |
149 | + return G_OBJECT (mouse_manager); |
150 | +} |
151 | + |
152 | +static void |
153 | +gsd_mouse_manager_dispose (GObject *object) |
154 | +{ |
155 | + G_OBJECT_CLASS (gsd_mouse_manager_parent_class)->dispose (object); |
156 | +} |
157 | + |
158 | +static void |
159 | +gsd_mouse_manager_class_init (GsdMouseManagerClass *klass) |
160 | +{ |
161 | + GObjectClass *object_class = G_OBJECT_CLASS (klass); |
162 | + |
163 | + object_class->get_property = gsd_mouse_manager_get_property; |
164 | + object_class->set_property = gsd_mouse_manager_set_property; |
165 | + object_class->constructor = gsd_mouse_manager_constructor; |
166 | + object_class->dispose = gsd_mouse_manager_dispose; |
167 | + object_class->finalize = gsd_mouse_manager_finalize; |
168 | + |
169 | + g_type_class_add_private (klass, sizeof (GsdMouseManagerPrivate)); |
170 | +} |
171 | + |
172 | +static XDevice * |
173 | +open_gdk_device (GdkDevice *device) |
174 | +{ |
175 | + XDevice *xdevice; |
176 | + int id; |
177 | + |
178 | + g_object_get (G_OBJECT (device), "device-id", &id, NULL); |
179 | + |
180 | + gdk_error_trap_push (); |
181 | + |
182 | + xdevice = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), id); |
183 | + |
184 | + if (gdk_error_trap_pop () != 0) |
185 | + return NULL; |
186 | + |
187 | + return xdevice; |
188 | +} |
189 | + |
190 | +static gboolean |
191 | +device_is_blacklisted (GsdMouseManager *manager, |
192 | + GdkDevice *device) |
193 | +{ |
194 | + int id; |
195 | + g_object_get (G_OBJECT (device), "device-id", &id, NULL); |
196 | + if (g_hash_table_lookup (manager->priv->blacklist, GINT_TO_POINTER (id)) != NULL) { |
197 | + g_debug ("device %s (%d) is blacklisted", gdk_device_get_name (device), id); |
198 | + return TRUE; |
199 | + } |
200 | + return FALSE; |
201 | +} |
202 | + |
203 | +static void |
204 | +configure_button_layout (guchar *buttons, |
205 | + gint n_buttons, |
206 | + gboolean left_handed) |
207 | +{ |
208 | + const gint left_button = 1; |
209 | + gint right_button; |
210 | + gint i; |
211 | + |
212 | + /* if the button is higher than 2 (3rd button) then it's |
213 | + * probably one direction of a scroll wheel or something else |
214 | + * uninteresting |
215 | + */ |
216 | + right_button = MIN (n_buttons, 3); |
217 | + |
218 | + /* If we change things we need to make sure we only swap buttons. |
219 | + * If we end up with multiple physical buttons assigned to the same |
220 | + * logical button the server will complain. This code assumes physical |
221 | + * button 0 is the physical left mouse button, and that the physical |
222 | + * button other than 0 currently assigned left_button or right_button |
223 | + * is the physical right mouse button. |
224 | + */ |
225 | + |
226 | + /* check if the current mapping satisfies the above assumptions */ |
227 | + if (buttons[left_button - 1] != left_button && |
228 | + buttons[left_button - 1] != right_button) |
229 | + /* The current mapping is weird. Swapping buttons is probably not a |
230 | + * good idea. |
231 | + */ |
232 | + return; |
233 | + |
234 | + /* check if we are left_handed and currently not swapped */ |
235 | + if (left_handed && buttons[left_button - 1] == left_button) { |
236 | + /* find the right button */ |
237 | + for (i = 0; i < n_buttons; i++) { |
238 | + if (buttons[i] == right_button) { |
239 | + buttons[i] = left_button; |
240 | + break; |
241 | + } |
242 | + } |
243 | + /* swap the buttons */ |
244 | + buttons[left_button - 1] = right_button; |
245 | + } |
246 | + /* check if we are not left_handed but are swapped */ |
247 | + else if (!left_handed && buttons[left_button - 1] == right_button) { |
248 | + /* find the right button */ |
249 | + for (i = 0; i < n_buttons; i++) { |
250 | + if (buttons[i] == left_button) { |
251 | + buttons[i] = right_button; |
252 | + break; |
253 | + } |
254 | + } |
255 | + /* swap the buttons */ |
256 | + buttons[left_button - 1] = left_button; |
257 | + } |
258 | +} |
259 | + |
260 | +static gboolean |
261 | +xinput_device_has_buttons (GdkDevice *device) |
262 | +{ |
263 | + int i; |
264 | + XAnyClassInfo *class_info; |
265 | + |
266 | + /* FIXME can we use the XDevice's classes here instead? */ |
267 | + XDeviceInfo *device_info, *info; |
268 | + gint n_devices; |
269 | + int id; |
270 | + |
271 | + /* Find the XDeviceInfo for the GdkDevice */ |
272 | + g_object_get (G_OBJECT (device), "device-id", &id, NULL); |
273 | + |
274 | + device_info = XListInputDevices (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), &n_devices); |
275 | + if (device_info == NULL) |
276 | + return FALSE; |
277 | + |
278 | + info = NULL; |
279 | + for (i = 0; i < n_devices; i++) { |
280 | + if (device_info[i].id == id) { |
281 | + info = &device_info[i]; |
282 | + break; |
283 | + } |
284 | + } |
285 | + if (info == NULL) |
286 | + goto bail; |
287 | + |
288 | + class_info = info->inputclassinfo; |
289 | + for (i = 0; i < info->num_classes; i++) { |
290 | + if (class_info->class == ButtonClass) { |
291 | + XButtonInfo *button_info; |
292 | + |
293 | + button_info = (XButtonInfo *) class_info; |
294 | + if (button_info->num_buttons > 0) { |
295 | + XFreeDeviceList (device_info); |
296 | + return TRUE; |
297 | + } |
298 | + } |
299 | + |
300 | + class_info = (XAnyClassInfo *) (((guchar *) class_info) + |
301 | + class_info->length); |
302 | + } |
303 | + |
304 | +bail: |
305 | + XFreeDeviceList (device_info); |
306 | + |
307 | + return FALSE; |
308 | +} |
309 | + |
310 | +static gboolean |
311 | +touchpad_has_single_button (XDevice *device) |
312 | +{ |
313 | + Atom type, prop; |
314 | + int format; |
315 | + unsigned long nitems, bytes_after; |
316 | + unsigned char *data; |
317 | + gboolean is_single_button = FALSE; |
318 | + int rc; |
319 | + |
320 | + prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Capabilities", False); |
321 | + if (!prop) |
322 | + return FALSE; |
323 | + |
324 | + gdk_error_trap_push (); |
325 | + rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), device, prop, 0, 1, False, |
326 | + XA_INTEGER, &type, &format, &nitems, |
327 | + &bytes_after, &data); |
328 | + if (rc == Success && type == XA_INTEGER && format == 8 && nitems >= 3) |
329 | + is_single_button = (data[0] == 1 && data[1] == 0 && data[2] == 0); |
330 | + |
331 | + if (rc == Success) |
332 | + XFree (data); |
333 | + |
334 | + gdk_error_trap_pop_ignored (); |
335 | + |
336 | + return is_single_button; |
337 | +} |
338 | + |
339 | +static void |
340 | +set_left_handed (GsdMouseManager *manager, |
341 | + GdkDevice *device, |
342 | + gboolean mouse_left_handed, |
343 | + gboolean touchpad_left_handed) |
344 | +{ |
345 | + XDevice *xdevice; |
346 | + guchar *buttons; |
347 | + gsize buttons_capacity = 16; |
348 | + gboolean left_handed; |
349 | + gint n_buttons; |
350 | + const char *name; |
351 | + |
352 | + buttons = g_new (guchar, buttons_capacity); |
353 | + |
354 | + name = gdk_device_get_name (device); |
355 | + if (name != NULL && g_str_equal ("Virtual core XTEST pointer", name)) |
356 | + return; |
357 | + if (!xinput_device_has_buttons (device)) |
358 | + return; |
359 | + |
360 | + xdevice = open_gdk_device (device); |
361 | + if (xdevice == NULL) |
362 | + return; |
363 | + |
364 | + /* If the device is a touchpad, swap tap buttons |
365 | + * around too, otherwise a tap would be a right-click */ |
366 | + if (device_is_touchpad (xdevice)) { |
367 | + gboolean tap = g_settings_get_boolean (manager->priv->touchpad_settings, KEY_TAP_TO_CLICK); |
368 | + gboolean single_button = touchpad_has_single_button (xdevice); |
369 | + |
370 | + left_handed = touchpad_left_handed; |
371 | + |
372 | + if (tap && !single_button) |
373 | + set_tap_to_click (device, tap, left_handed); |
374 | + |
375 | + if (single_button) |
376 | + goto out; |
377 | + } else { |
378 | + left_handed = mouse_left_handed; |
379 | + } |
380 | + |
381 | + n_buttons = XGetDeviceButtonMapping (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, |
382 | + buttons, |
383 | + buttons_capacity); |
384 | + |
385 | + while (n_buttons > buttons_capacity) { |
386 | + buttons_capacity = n_buttons; |
387 | + buttons = (guchar *) g_realloc (buttons, |
388 | + buttons_capacity * sizeof (guchar)); |
389 | + |
390 | + n_buttons = XGetDeviceButtonMapping (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, |
391 | + buttons, |
392 | + buttons_capacity); |
393 | + } |
394 | + |
395 | + configure_button_layout (buttons, n_buttons, left_handed); |
396 | + |
397 | + XSetDeviceButtonMapping (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, buttons, n_buttons); |
398 | + |
399 | +out: |
400 | + XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice); |
401 | + g_free (buttons); |
402 | +} |
403 | + |
404 | +static void |
405 | +set_motion (GsdMouseManager *manager, |
406 | + GdkDevice *device) |
407 | +{ |
408 | + XDevice *xdevice; |
409 | + XPtrFeedbackControl feedback; |
410 | + XFeedbackState *states, *state; |
411 | + int num_feedbacks; |
412 | + int numerator, denominator; |
413 | + gfloat motion_acceleration; |
414 | + int motion_threshold; |
415 | + GSettings *settings; |
416 | + guint i; |
417 | + |
418 | + xdevice = open_gdk_device (device); |
419 | + if (xdevice == NULL) |
420 | + return; |
421 | + |
422 | + if (device_is_touchpad (xdevice)) |
423 | + settings = manager->priv->touchpad_settings; |
424 | + else |
425 | + settings = manager->priv->mouse_settings; |
426 | + |
427 | + /* Calculate acceleration */ |
428 | + motion_acceleration = g_settings_get_double (settings, KEY_MOTION_ACCELERATION); |
429 | + |
430 | + if (motion_acceleration >= 1.0) { |
431 | + /* we want to get the acceleration, with a resolution of 0.5 |
432 | + */ |
433 | + if ((motion_acceleration - floor (motion_acceleration)) < 0.25) { |
434 | + numerator = floor (motion_acceleration); |
435 | + denominator = 1; |
436 | + } else if ((motion_acceleration - floor (motion_acceleration)) < 0.5) { |
437 | + numerator = ceil (2.0 * motion_acceleration); |
438 | + denominator = 2; |
439 | + } else if ((motion_acceleration - floor (motion_acceleration)) < 0.75) { |
440 | + numerator = floor (2.0 *motion_acceleration); |
441 | + denominator = 2; |
442 | + } else { |
443 | + numerator = ceil (motion_acceleration); |
444 | + denominator = 1; |
445 | + } |
446 | + } else if (motion_acceleration < 1.0 && motion_acceleration > 0) { |
447 | + /* This we do to 1/10ths */ |
448 | + numerator = floor (motion_acceleration * 10) + 1; |
449 | + denominator= 10; |
450 | + } else { |
451 | + numerator = -1; |
452 | + denominator = -1; |
453 | + } |
454 | + |
455 | + /* And threshold */ |
456 | + motion_threshold = g_settings_get_int (settings, KEY_MOTION_THRESHOLD); |
457 | + |
458 | + /* Get the list of feedbacks for the device */ |
459 | + states = XGetFeedbackControl (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, &num_feedbacks); |
460 | + if (states == NULL) |
461 | + goto out; |
462 | + state = (XFeedbackState *) states; |
463 | + for (i = 0; i < num_feedbacks; i++) { |
464 | + if (state->class == PtrFeedbackClass) { |
465 | + /* And tell the device */ |
466 | + feedback.class = PtrFeedbackClass; |
467 | + feedback.length = sizeof (XPtrFeedbackControl); |
468 | + feedback.id = state->id; |
469 | + feedback.threshold = motion_threshold; |
470 | + feedback.accelNum = numerator; |
471 | + feedback.accelDenom = denominator; |
472 | + |
473 | + g_debug ("Setting accel %d/%d, threshold %d for device '%s'", |
474 | + numerator, denominator, motion_threshold, gdk_device_get_name (device)); |
475 | + |
476 | + XChangeFeedbackControl (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), |
477 | + xdevice, |
478 | + DvAccelNum | DvAccelDenom | DvThreshold, |
479 | + (XFeedbackControl *) &feedback); |
480 | + |
481 | + break; |
482 | + } |
483 | + state = (XFeedbackState *) ((char *) state + state->length); |
484 | + } |
485 | + |
486 | + XFreeFeedbackList (states); |
487 | + |
488 | + out: |
489 | + |
490 | + XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice); |
491 | +} |
492 | + |
493 | +static void |
494 | +set_middle_button (GsdMouseManager *manager, |
495 | + GdkDevice *device, |
496 | + gboolean middle_button) |
497 | +{ |
498 | + Atom prop; |
499 | + XDevice *xdevice; |
500 | + Atom type; |
501 | + int format; |
502 | + unsigned long nitems, bytes_after; |
503 | + unsigned char *data; |
504 | + int rc; |
505 | + |
506 | + prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), |
507 | + "Evdev Middle Button Emulation", True); |
508 | + |
509 | + if (!prop) /* no evdev devices */ |
510 | + return; |
511 | + |
512 | + xdevice = open_gdk_device (device); |
513 | + if (xdevice == NULL) |
514 | + return; |
515 | + |
516 | + gdk_error_trap_push (); |
517 | + |
518 | + rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), |
519 | + xdevice, prop, 0, 1, False, XA_INTEGER, &type, &format, |
520 | + &nitems, &bytes_after, &data); |
521 | + |
522 | + if (rc == Success && format == 8 && type == XA_INTEGER && nitems == 1) { |
523 | + data[0] = middle_button ? 1 : 0; |
524 | + |
525 | + XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), |
526 | + xdevice, prop, type, format, PropModeReplace, data, nitems); |
527 | + } |
528 | + |
529 | + if (gdk_error_trap_pop ()) |
530 | + g_warning ("Error in setting middle button emulation on \"%s\"", gdk_device_get_name (device)); |
531 | + |
532 | + if (rc == Success) |
533 | + XFree (data); |
534 | + |
535 | + XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice); |
536 | +} |
537 | + |
538 | +static int |
539 | +set_disable_w_typing (GsdMouseManager *manager, gboolean state) |
540 | +{ |
541 | + if (state && touchpad_is_present ()) { |
542 | + GError *error = NULL; |
543 | + char *args[6]; |
544 | + |
545 | + if (manager->priv->syndaemon_spawned) |
546 | + return 0; |
547 | + |
548 | + args[0] = "syndaemon"; |
549 | + args[1] = "-i"; |
550 | + args[2] = "0.5"; |
551 | + args[3] = "-K"; |
552 | + args[4] = "-R"; |
553 | + args[5] = NULL; |
554 | + |
555 | + if (!g_find_program_in_path (args[0])) |
556 | + return 0; |
557 | + |
558 | + g_spawn_async (g_get_home_dir (), args, NULL, |
559 | + G_SPAWN_SEARCH_PATH, NULL, NULL, |
560 | + &manager->priv->syndaemon_pid, &error); |
561 | + |
562 | + manager->priv->syndaemon_spawned = (error == NULL); |
563 | + |
564 | + if (error) { |
565 | + g_settings_set_boolean (manager->priv->touchpad_settings, KEY_TOUCHPAD_DISABLE_W_TYPING, FALSE); |
566 | + g_error_free (error); |
567 | + } |
568 | + } else if (manager->priv->syndaemon_spawned) { |
569 | + kill (manager->priv->syndaemon_pid, SIGHUP); |
570 | + g_spawn_close_pid (manager->priv->syndaemon_pid); |
571 | + manager->priv->syndaemon_spawned = FALSE; |
572 | + } |
573 | + |
574 | + return 0; |
575 | +} |
576 | + |
577 | +static void |
578 | +set_tap_to_click (GdkDevice *device, |
579 | + gboolean state, |
580 | + gboolean left_handed) |
581 | +{ |
582 | + int format, rc; |
583 | + unsigned long nitems, bytes_after; |
584 | + XDevice *xdevice; |
585 | + unsigned char* data; |
586 | + Atom prop, type; |
587 | + |
588 | + prop = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Tap Action", False); |
589 | + if (!prop) |
590 | + return; |
591 | + |
592 | + xdevice = open_gdk_device (device); |
593 | + if (xdevice == NULL) |
594 | + return; |
595 | + |
596 | + if (!device_is_touchpad (xdevice)) { |
597 | + XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice); |
598 | + return; |
599 | + } |
600 | + |
601 | + gdk_error_trap_push (); |
602 | + rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, prop, 0, 2, |
603 | + False, XA_INTEGER, &type, &format, &nitems, |
604 | + &bytes_after, &data); |
605 | + |
606 | + if (rc == Success && type == XA_INTEGER && format == 8 && nitems >= 7) { |
607 | + /* Set MR mapping for corner tapping on the right side*/ |
608 | + data[0] = (state) ? 2 : 0; |
609 | + data[1] = (state) ? 3 : 0; |
610 | + |
611 | + /* Set RLM mapping for 1/2/3 fingers*/ |
612 | + data[4] = (state) ? ((left_handed) ? 3 : 1) : 0; |
613 | + data[5] = (state) ? ((left_handed) ? 1 : 3) : 0; |
614 | + data[6] = (state) ? 2 : 0; |
615 | + XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, prop, XA_INTEGER, 8, |
616 | + PropModeReplace, data, nitems); |
617 | + } |
618 | + |
619 | + if (rc == Success) |
620 | + XFree (data); |
621 | + |
622 | + if (gdk_error_trap_pop ()) |
623 | + g_warning ("Error in setting tap to click on \"%s\"", gdk_device_get_name (device)); |
624 | + |
625 | + XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice); |
626 | +} |
627 | + |
628 | +static void |
629 | +set_horiz_scroll (GdkDevice *device, |
630 | + gboolean state) |
631 | +{ |
632 | + int rc; |
633 | + XDevice *xdevice; |
634 | + Atom act_type, prop_edge, prop_twofinger; |
635 | + int act_format; |
636 | + unsigned long nitems, bytes_after; |
637 | + unsigned char *data; |
638 | + |
639 | + prop_edge = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Edge Scrolling", False); |
640 | + prop_twofinger = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Two-Finger Scrolling", False); |
641 | + |
642 | + if (!prop_edge || !prop_twofinger) |
643 | + return; |
644 | + |
645 | + xdevice = open_gdk_device (device); |
646 | + if (xdevice == NULL) |
647 | + return; |
648 | + |
649 | + if (!device_is_touchpad (xdevice)) { |
650 | + XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice); |
651 | + return; |
652 | + } |
653 | + |
654 | + gdk_error_trap_push (); |
655 | + rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, |
656 | + prop_edge, 0, 1, False, |
657 | + XA_INTEGER, &act_type, &act_format, &nitems, |
658 | + &bytes_after, &data); |
659 | + if (rc == Success && act_type == XA_INTEGER && |
660 | + act_format == 8 && nitems >= 2) { |
661 | + data[1] = (state && data[0]); |
662 | + XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, |
663 | + prop_edge, XA_INTEGER, 8, |
664 | + PropModeReplace, data, nitems); |
665 | + } |
666 | + |
667 | + XFree (data); |
668 | + |
669 | + rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, |
670 | + prop_twofinger, 0, 1, False, |
671 | + XA_INTEGER, &act_type, &act_format, &nitems, |
672 | + &bytes_after, &data); |
673 | + if (rc == Success && act_type == XA_INTEGER && |
674 | + act_format == 8 && nitems >= 2) { |
675 | + data[1] = (state && data[0]); |
676 | + XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, |
677 | + prop_twofinger, XA_INTEGER, 8, |
678 | + PropModeReplace, data, nitems); |
679 | + } |
680 | + |
681 | + if (gdk_error_trap_pop ()) |
682 | + g_warning ("Error in setting horiz scroll on \"%s\"", gdk_device_get_name (device)); |
683 | + |
684 | + if (rc == Success) |
685 | + XFree (data); |
686 | + |
687 | + XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice); |
688 | + |
689 | +} |
690 | + |
691 | +static void |
692 | +set_edge_scroll (GdkDevice *device, |
693 | + GsdTouchpadScrollMethod method) |
694 | +{ |
695 | + int rc; |
696 | + XDevice *xdevice; |
697 | + Atom act_type, prop_edge, prop_twofinger; |
698 | + int act_format; |
699 | + unsigned long nitems, bytes_after; |
700 | + unsigned char *data; |
701 | + |
702 | + prop_edge = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Edge Scrolling", False); |
703 | + prop_twofinger = XInternAtom (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), "Synaptics Two-Finger Scrolling", False); |
704 | + |
705 | + if (!prop_edge || !prop_twofinger) |
706 | + return; |
707 | + |
708 | + xdevice = open_gdk_device (device); |
709 | + if (xdevice == NULL) |
710 | + return; |
711 | + |
712 | + if (!device_is_touchpad (xdevice)) { |
713 | + XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice); |
714 | + return; |
715 | + } |
716 | + |
717 | + gdk_error_trap_push (); |
718 | + rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, |
719 | + prop_edge, 0, 1, False, |
720 | + XA_INTEGER, &act_type, &act_format, &nitems, |
721 | + &bytes_after, &data); |
722 | + if (rc == Success && act_type == XA_INTEGER && |
723 | + act_format == 8 && nitems >= 2) { |
724 | + data[0] = (method == GSD_TOUCHPAD_SCROLL_METHOD_EDGE_SCROLLING) ? 1 : 0; |
725 | + XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, |
726 | + prop_edge, XA_INTEGER, 8, |
727 | + PropModeReplace, data, nitems); |
728 | + } |
729 | + |
730 | + XFree (data); |
731 | + |
732 | + rc = XGetDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, |
733 | + prop_twofinger, 0, 1, False, |
734 | + XA_INTEGER, &act_type, &act_format, &nitems, |
735 | + &bytes_after, &data); |
736 | + if (rc == Success && act_type == XA_INTEGER && |
737 | + act_format == 8 && nitems >= 2) { |
738 | + data[0] = (method == GSD_TOUCHPAD_SCROLL_METHOD_TWO_FINGER_SCROLLING) ? 1 : 0; |
739 | + XChangeDeviceProperty (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice, |
740 | + prop_twofinger, XA_INTEGER, 8, |
741 | + PropModeReplace, data, nitems); |
742 | + } |
743 | + |
744 | + if (gdk_error_trap_pop ()) |
745 | + g_warning ("Error in setting edge scroll on \"%s\"", gdk_device_get_name (device)); |
746 | + |
747 | + if (rc == Success) |
748 | + XFree (data); |
749 | + |
750 | + XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice); |
751 | +} |
752 | + |
753 | +static void |
754 | +set_touchpad_disabled (GdkDevice *device) |
755 | +{ |
756 | + int id; |
757 | + XDevice *xdevice; |
758 | + |
759 | + g_object_get (G_OBJECT (device), "device-id", &id, NULL); |
760 | + |
761 | + g_debug ("Trying to set device disabled for \"%s\" (%d)", gdk_device_get_name (device), id); |
762 | + |
763 | + xdevice = open_gdk_device (device); |
764 | + if (xdevice == NULL) |
765 | + return; |
766 | + |
767 | + if (!device_is_touchpad (xdevice)) { |
768 | + XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice); |
769 | + return; |
770 | + } |
771 | + |
772 | + if (set_device_enabled (id, FALSE) == FALSE) |
773 | + g_warning ("Error disabling device \"%s\" (%d)", gdk_device_get_name (device), id); |
774 | + else |
775 | + g_debug ("Disabled device \"%s\" (%d)", gdk_device_get_name (device), id); |
776 | + |
777 | + XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice); |
778 | +} |
779 | + |
780 | +static void |
781 | +set_touchpad_enabled (int id) |
782 | +{ |
783 | + XDevice *xdevice; |
784 | + |
785 | + g_debug ("Trying to set device enabled for %d", id); |
786 | + |
787 | + gdk_error_trap_push (); |
788 | + xdevice = XOpenDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), id); |
789 | + if (gdk_error_trap_pop () != 0) |
790 | + return; |
791 | + |
792 | + if (!device_is_touchpad (xdevice)) { |
793 | + XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice); |
794 | + return; |
795 | + } |
796 | + |
797 | + if (set_device_enabled (id, TRUE) == FALSE) |
798 | + g_warning ("Error enabling device \"%d\"", id); |
799 | + else |
800 | + g_debug ("Enabled device %d", id); |
801 | + |
802 | + XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice); |
803 | +} |
804 | + |
805 | +static void |
806 | +set_locate_pointer (GsdMouseManager *manager, |
807 | + gboolean state) |
808 | +{ |
809 | + if (state) { |
810 | + GError *error = NULL; |
811 | + char *args[2]; |
812 | + |
813 | + if (manager->priv->locate_pointer_spawned) |
814 | + return; |
815 | + |
816 | + args[0] = LIBEXECDIR "/gsd-locate-pointer"; |
817 | + args[1] = NULL; |
818 | + |
819 | + g_spawn_async (NULL, args, NULL, |
820 | + 0, NULL, NULL, |
821 | + &manager->priv->locate_pointer_pid, &error); |
822 | + |
823 | + manager->priv->locate_pointer_spawned = (error == NULL); |
824 | + |
825 | + if (error) { |
826 | + g_settings_set_boolean (manager->priv->mouse_settings, KEY_LOCATE_POINTER, FALSE); |
827 | + g_error_free (error); |
828 | + } |
829 | + |
830 | + } else if (manager->priv->locate_pointer_spawned) { |
831 | + kill (manager->priv->locate_pointer_pid, SIGHUP); |
832 | + g_spawn_close_pid (manager->priv->locate_pointer_pid); |
833 | + manager->priv->locate_pointer_spawned = FALSE; |
834 | + } |
835 | +} |
836 | + |
837 | +static void |
838 | +set_mousetweaks_daemon (GsdMouseManager *manager, |
839 | + gboolean dwell_click_enabled, |
840 | + gboolean secondary_click_enabled) |
841 | +{ |
842 | + GError *error = NULL; |
843 | + gchar *comm; |
844 | + gboolean run_daemon = dwell_click_enabled || secondary_click_enabled; |
845 | + |
846 | + if (run_daemon || manager->priv->mousetweaks_daemon_running) |
847 | + comm = g_strdup_printf ("mousetweaks %s", |
848 | + run_daemon ? "" : "-s"); |
849 | + else |
850 | + return; |
851 | + |
852 | + if (run_daemon) |
853 | + manager->priv->mousetweaks_daemon_running = TRUE; |
854 | + |
855 | + if (! g_spawn_command_line_async (comm, &error)) { |
856 | + if (error->code == G_SPAWN_ERROR_NOENT && run_daemon) { |
857 | + GtkWidget *dialog; |
858 | + |
859 | + if (dwell_click_enabled) { |
860 | + g_settings_set_boolean (manager->priv->mouse_a11y_settings, |
861 | + KEY_DWELL_CLICK_ENABLED, FALSE); |
862 | + } else if (secondary_click_enabled) { |
863 | + g_settings_set_boolean (manager->priv->mouse_a11y_settings, |
864 | + KEY_SECONDARY_CLICK_ENABLED, FALSE); |
865 | + } |
866 | + |
867 | + dialog = gtk_message_dialog_new (NULL, 0, |
868 | + GTK_MESSAGE_WARNING, |
869 | + GTK_BUTTONS_OK, |
870 | + _("Could not enable mouse accessibility features")); |
871 | + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), |
872 | + _("Mouse accessibility requires Mousetweaks " |
873 | + "to be installed on your system.")); |
874 | + gtk_window_set_title (GTK_WINDOW (dialog), _("Universal Access")); |
875 | + gtk_window_set_icon_name (GTK_WINDOW (dialog), |
876 | + "preferences-desktop-accessibility"); |
877 | + gtk_dialog_run (GTK_DIALOG (dialog)); |
878 | + gtk_widget_destroy (dialog); |
879 | + } |
880 | + g_error_free (error); |
881 | + } |
882 | + g_free (comm); |
883 | +} |
884 | + |
885 | +static gboolean |
886 | +get_touchpad_handedness (GsdMouseManager *manager, gboolean mouse_left_handed) |
887 | +{ |
888 | + switch (g_settings_get_enum (manager->priv->touchpad_settings, KEY_LEFT_HANDED)) { |
889 | + case GSD_TOUCHPAD_HANDEDNESS_RIGHT: |
890 | + return FALSE; |
891 | + case GSD_TOUCHPAD_HANDEDNESS_LEFT: |
892 | + return TRUE; |
893 | + case GSD_TOUCHPAD_HANDEDNESS_MOUSE: |
894 | + return mouse_left_handed; |
895 | + default: |
896 | + g_assert_not_reached (); |
897 | + } |
898 | +} |
899 | + |
900 | +static void |
901 | +set_mouse_settings (GsdMouseManager *manager, |
902 | + GdkDevice *device) |
903 | +{ |
904 | + gboolean mouse_left_handed, touchpad_left_handed; |
905 | + |
906 | + mouse_left_handed = g_settings_get_boolean (manager->priv->mouse_settings, KEY_LEFT_HANDED); |
907 | + touchpad_left_handed = get_touchpad_handedness (manager, mouse_left_handed); |
908 | + set_left_handed (manager, device, mouse_left_handed, touchpad_left_handed); |
909 | + |
910 | + set_motion (manager, device); |
911 | + set_middle_button (manager, device, g_settings_get_boolean (manager->priv->mouse_settings, KEY_MIDDLE_BUTTON_EMULATION)); |
912 | + |
913 | + set_tap_to_click (device, g_settings_get_boolean (manager->priv->touchpad_settings, KEY_TAP_TO_CLICK), touchpad_left_handed); |
914 | + set_edge_scroll (device, g_settings_get_enum (manager->priv->touchpad_settings, KEY_SCROLL_METHOD)); |
915 | + set_horiz_scroll (device, g_settings_get_boolean (manager->priv->touchpad_settings, KEY_PAD_HORIZ_SCROLL)); |
916 | + if (g_settings_get_boolean (manager->priv->touchpad_settings, KEY_TOUCHPAD_ENABLED) == FALSE) |
917 | + set_touchpad_disabled (device); |
918 | +} |
919 | + |
920 | +static void |
921 | +mouse_callback (GSettings *settings, |
922 | + const gchar *key, |
923 | + GsdMouseManager *manager) |
924 | +{ |
925 | + GList *devices, *l; |
926 | + |
927 | + if (g_str_equal (key, KEY_DWELL_CLICK_ENABLED) || |
928 | + g_str_equal (key, KEY_SECONDARY_CLICK_ENABLED)) { |
929 | + set_mousetweaks_daemon (manager, |
930 | + g_settings_get_boolean (settings, KEY_DWELL_CLICK_ENABLED), |
931 | + g_settings_get_boolean (settings, KEY_SECONDARY_CLICK_ENABLED)); |
932 | + return; |
933 | + } else if (g_str_equal (key, KEY_LOCATE_POINTER)) { |
934 | + set_locate_pointer (manager, g_settings_get_boolean (settings, KEY_LOCATE_POINTER)); |
935 | + return; |
936 | + } |
937 | + |
938 | + devices = gdk_device_manager_list_devices (manager->priv->device_manager, GDK_DEVICE_TYPE_SLAVE); |
939 | + |
940 | + for (l = devices; l != NULL; l = l->next) { |
941 | + GdkDevice *device = l->data; |
942 | + |
943 | + if (device_is_blacklisted (manager, device)) |
944 | + return; |
945 | + |
946 | + if (g_str_equal (key, KEY_LEFT_HANDED)) { |
947 | + gboolean mouse_left_handed; |
948 | + mouse_left_handed = g_settings_get_boolean (settings, KEY_LEFT_HANDED); |
949 | + set_left_handed (manager, device, mouse_left_handed, get_touchpad_handedness (manager, mouse_left_handed)); |
950 | + } else if (g_str_equal (key, KEY_MOTION_ACCELERATION) || |
951 | + g_str_equal (key, KEY_MOTION_THRESHOLD)) { |
952 | + set_motion (manager, device); |
953 | + } else if (g_str_equal (key, KEY_MIDDLE_BUTTON_EMULATION)) { |
954 | + set_middle_button (manager, device, g_settings_get_boolean (settings, KEY_MIDDLE_BUTTON_EMULATION)); |
955 | + } |
956 | + } |
957 | + g_list_free (devices); |
958 | +} |
959 | + |
960 | +static void |
961 | +touchpad_callback (GSettings *settings, |
962 | + const gchar *key, |
963 | + GsdMouseManager *manager) |
964 | +{ |
965 | + GList *devices, *l; |
966 | + |
967 | + if (g_str_equal (key, KEY_TOUCHPAD_DISABLE_W_TYPING)) { |
968 | + set_disable_w_typing (manager, g_settings_get_boolean (manager->priv->touchpad_settings, key)); |
969 | + return; |
970 | + } |
971 | + |
972 | + devices = gdk_device_manager_list_devices (manager->priv->device_manager, GDK_DEVICE_TYPE_SLAVE); |
973 | + |
974 | + for (l = devices; l != NULL; l = l->next) { |
975 | + GdkDevice *device = l->data; |
976 | + |
977 | + g_message ("checking on device %s", gdk_device_get_name (device)); |
978 | + |
979 | + if (device_is_blacklisted (manager, device)) |
980 | + return; |
981 | + |
982 | + if (g_str_equal (key, KEY_TAP_TO_CLICK)) { |
983 | + set_tap_to_click (device, g_settings_get_boolean (settings, key), |
984 | + g_settings_get_boolean (manager->priv->touchpad_settings, KEY_LEFT_HANDED)); |
985 | + } else if (g_str_equal (key, KEY_SCROLL_METHOD)) { |
986 | + set_edge_scroll (device, g_settings_get_enum (settings, key)); |
987 | + set_horiz_scroll (device, g_settings_get_boolean (settings, KEY_PAD_HORIZ_SCROLL)); |
988 | + } else if (g_str_equal (key, KEY_PAD_HORIZ_SCROLL)) { |
989 | + set_horiz_scroll (device, g_settings_get_boolean (settings, key)); |
990 | + } else if (g_str_equal (key, KEY_TOUCHPAD_ENABLED)) { |
991 | + if (g_settings_get_boolean (settings, key) == FALSE) |
992 | + set_touchpad_disabled (device); |
993 | + else |
994 | + set_touchpad_enabled (gdk_x11_device_get_id (device)); |
995 | + } else if (g_str_equal (key, KEY_MOTION_ACCELERATION) || |
996 | + g_str_equal (key, KEY_MOTION_THRESHOLD)) { |
997 | + set_motion (manager, device); |
998 | + } else if (g_str_equal (key, KEY_LEFT_HANDED)) { |
999 | + gboolean mouse_left_handed; |
1000 | + mouse_left_handed = g_settings_get_boolean (manager->priv->mouse_settings, KEY_LEFT_HANDED); |
1001 | + set_left_handed (manager, device, mouse_left_handed, get_touchpad_handedness (manager, mouse_left_handed)); |
1002 | + } |
1003 | + } |
1004 | + g_list_free (devices); |
1005 | + |
1006 | + if (g_str_equal (key, KEY_TOUCHPAD_ENABLED) && |
1007 | + g_settings_get_boolean (settings, key)) { |
1008 | + devices = get_disabled_devices (manager->priv->device_manager); |
1009 | + for (l = devices; l != NULL; l = l->next) { |
1010 | + int device_id; |
1011 | + |
1012 | + device_id = GPOINTER_TO_INT (l->data); |
1013 | + set_touchpad_enabled (device_id); |
1014 | + } |
1015 | + g_list_free (devices); |
1016 | + } |
1017 | +} |
1018 | + |
1019 | +static void |
1020 | +device_added_cb (GdkDeviceManager *device_manager, |
1021 | + GdkDevice *device, |
1022 | + GsdMouseManager *manager) |
1023 | +{ |
1024 | + if (gdk_device_get_source (device) == GDK_SOURCE_MOUSE) { |
1025 | + if (run_custom_command (device, COMMAND_DEVICE_ADDED) == FALSE) { |
1026 | + set_mouse_settings (manager, device); |
1027 | + } else { |
1028 | + int id; |
1029 | + g_object_get (G_OBJECT (device), "device-id", &id, NULL); |
1030 | + g_hash_table_insert (manager->priv->blacklist, |
1031 | + GINT_TO_POINTER (id), GINT_TO_POINTER (1)); |
1032 | + } |
1033 | + |
1034 | + /* If a touchpad was to appear... */ |
1035 | + set_disable_w_typing (manager, g_settings_get_boolean (manager->priv->touchpad_settings, KEY_TOUCHPAD_DISABLE_W_TYPING)); |
1036 | + } |
1037 | +} |
1038 | + |
1039 | +static void |
1040 | +device_removed_cb (GdkDeviceManager *device_manager, |
1041 | + GdkDevice *device, |
1042 | + GsdMouseManager *manager) |
1043 | +{ |
1044 | + if (gdk_device_get_source (device) == GDK_SOURCE_MOUSE) { |
1045 | + int id; |
1046 | + |
1047 | + run_custom_command (device, COMMAND_DEVICE_REMOVED); |
1048 | + |
1049 | + g_object_get (G_OBJECT (device), "device-id", &id, NULL); |
1050 | + g_hash_table_remove (manager->priv->blacklist, |
1051 | + GINT_TO_POINTER (id)); |
1052 | + |
1053 | + /* If a touchpad was to disappear... */ |
1054 | + set_disable_w_typing (manager, g_settings_get_boolean (manager->priv->touchpad_settings, KEY_TOUCHPAD_DISABLE_W_TYPING)); |
1055 | + } |
1056 | +} |
1057 | + |
1058 | +static void |
1059 | +set_devicepresence_handler (GsdMouseManager *manager) |
1060 | +{ |
1061 | + GdkDeviceManager *device_manager; |
1062 | + |
1063 | + device_manager = gdk_display_get_device_manager (gdk_display_get_default ()); |
1064 | + |
1065 | + manager->priv->device_added_id = g_signal_connect (G_OBJECT (device_manager), "device-added", |
1066 | + G_CALLBACK (device_added_cb), manager); |
1067 | + manager->priv->device_removed_id = g_signal_connect (G_OBJECT (device_manager), "device-removed", |
1068 | + G_CALLBACK (device_removed_cb), manager); |
1069 | + manager->priv->device_manager = device_manager; |
1070 | +} |
1071 | + |
1072 | +static void |
1073 | +gsd_mouse_manager_init (GsdMouseManager *manager) |
1074 | +{ |
1075 | + manager->priv = GSD_MOUSE_MANAGER_GET_PRIVATE (manager); |
1076 | + manager->priv->blacklist = g_hash_table_new (g_direct_hash, g_direct_equal); |
1077 | +} |
1078 | + |
1079 | +static gboolean |
1080 | +gsd_mouse_manager_idle_cb (GsdMouseManager *manager) |
1081 | +{ |
1082 | + GList *devices, *l; |
1083 | + |
1084 | + gnome_settings_profile_start (NULL); |
1085 | + |
1086 | + set_devicepresence_handler (manager); |
1087 | + |
1088 | + manager->priv->mouse_settings = g_settings_new (SETTINGS_MOUSE_DIR); |
1089 | + g_signal_connect (manager->priv->mouse_settings, "changed", |
1090 | + G_CALLBACK (mouse_callback), manager); |
1091 | + |
1092 | + manager->priv->mouse_a11y_settings = g_settings_new ("org.gnome.desktop.a11y.mouse"); |
1093 | + g_signal_connect (manager->priv->mouse_a11y_settings, "changed", |
1094 | + G_CALLBACK (mouse_callback), manager); |
1095 | + |
1096 | + manager->priv->touchpad_settings = g_settings_new (SETTINGS_TOUCHPAD_DIR); |
1097 | + g_signal_connect (manager->priv->touchpad_settings, "changed", |
1098 | + G_CALLBACK (touchpad_callback), manager); |
1099 | + |
1100 | + manager->priv->syndaemon_spawned = FALSE; |
1101 | + |
1102 | + set_locate_pointer (manager, g_settings_get_boolean (manager->priv->mouse_settings, KEY_LOCATE_POINTER)); |
1103 | + set_mousetweaks_daemon (manager, |
1104 | + g_settings_get_boolean (manager->priv->mouse_a11y_settings, KEY_DWELL_CLICK_ENABLED), |
1105 | + g_settings_get_boolean (manager->priv->mouse_a11y_settings, KEY_SECONDARY_CLICK_ENABLED)); |
1106 | + set_disable_w_typing (manager, g_settings_get_boolean (manager->priv->touchpad_settings, KEY_TOUCHPAD_DISABLE_W_TYPING)); |
1107 | + |
1108 | + devices = gdk_device_manager_list_devices (manager->priv->device_manager, GDK_DEVICE_TYPE_SLAVE); |
1109 | + for (l = devices; l != NULL; l = l->next) { |
1110 | + GdkDevice *device = l->data; |
1111 | + |
1112 | + if (run_custom_command (device, COMMAND_DEVICE_PRESENT) == FALSE) { |
1113 | + set_mouse_settings (manager, device); |
1114 | + } else { |
1115 | + int id; |
1116 | + g_object_get (G_OBJECT (device), "device-id", &id, NULL); |
1117 | + g_hash_table_insert (manager->priv->blacklist, |
1118 | + GINT_TO_POINTER (id), GINT_TO_POINTER (1)); |
1119 | + } |
1120 | + } |
1121 | + g_list_free (devices); |
1122 | + |
1123 | + if (g_settings_get_boolean (manager->priv->touchpad_settings, KEY_TOUCHPAD_ENABLED)) { |
1124 | + devices = get_disabled_devices (manager->priv->device_manager); |
1125 | + for (l = devices; l != NULL; l = l->next) { |
1126 | + int device_id; |
1127 | + |
1128 | + device_id = GPOINTER_TO_INT (l->data); |
1129 | + set_touchpad_enabled (device_id); |
1130 | + } |
1131 | + g_list_free (devices); |
1132 | + } |
1133 | + |
1134 | + gnome_settings_profile_end (NULL); |
1135 | + |
1136 | + manager->priv->start_idle_id = 0; |
1137 | + |
1138 | + return FALSE; |
1139 | +} |
1140 | + |
1141 | +gboolean |
1142 | +gsd_mouse_manager_start (GsdMouseManager *manager, |
1143 | + GError **error) |
1144 | +{ |
1145 | + gnome_settings_profile_start (NULL); |
1146 | + |
1147 | + if (!supports_xinput_devices ()) { |
1148 | + g_debug ("XInput is not supported, not applying any settings"); |
1149 | + return TRUE; |
1150 | + } |
1151 | + |
1152 | + manager->priv->start_idle_id = g_idle_add ((GSourceFunc) gsd_mouse_manager_idle_cb, manager); |
1153 | + |
1154 | + gnome_settings_profile_end (NULL); |
1155 | + |
1156 | + return TRUE; |
1157 | +} |
1158 | + |
1159 | +void |
1160 | +gsd_mouse_manager_stop (GsdMouseManager *manager) |
1161 | +{ |
1162 | + GsdMouseManagerPrivate *p = manager->priv; |
1163 | + |
1164 | + g_debug ("Stopping mouse manager"); |
1165 | + |
1166 | + if (p->device_manager != NULL) { |
1167 | + g_signal_handler_disconnect (p->device_manager, p->device_added_id); |
1168 | + g_signal_handler_disconnect (p->device_manager, p->device_removed_id); |
1169 | + p->device_manager = NULL; |
1170 | + } |
1171 | + |
1172 | + if (p->mouse_a11y_settings != NULL) { |
1173 | + g_object_unref (p->mouse_a11y_settings); |
1174 | + p->mouse_a11y_settings = NULL; |
1175 | + } |
1176 | + |
1177 | + if (p->mouse_settings != NULL) { |
1178 | + g_object_unref (p->mouse_settings); |
1179 | + p->mouse_settings = NULL; |
1180 | + } |
1181 | + |
1182 | + if (p->touchpad_settings != NULL) { |
1183 | + g_object_unref (p->touchpad_settings); |
1184 | + p->touchpad_settings = NULL; |
1185 | + } |
1186 | + |
1187 | + set_locate_pointer (manager, FALSE); |
1188 | +} |
1189 | + |
1190 | +static void |
1191 | +gsd_mouse_manager_finalize (GObject *object) |
1192 | +{ |
1193 | + GsdMouseManager *mouse_manager; |
1194 | + |
1195 | + g_return_if_fail (object != NULL); |
1196 | + g_return_if_fail (GSD_IS_MOUSE_MANAGER (object)); |
1197 | + |
1198 | + mouse_manager = GSD_MOUSE_MANAGER (object); |
1199 | + |
1200 | + g_return_if_fail (mouse_manager->priv != NULL); |
1201 | + |
1202 | + if (mouse_manager->priv->blacklist != NULL) |
1203 | + g_hash_table_destroy (mouse_manager->priv->blacklist); |
1204 | + |
1205 | + if (mouse_manager->priv->start_idle_id != 0) |
1206 | + g_source_remove (mouse_manager->priv->start_idle_id); |
1207 | + |
1208 | + if (mouse_manager->priv->device_manager != NULL) { |
1209 | + g_signal_handler_disconnect (mouse_manager->priv->device_manager, mouse_manager->priv->device_added_id); |
1210 | + g_signal_handler_disconnect (mouse_manager->priv->device_manager, mouse_manager->priv->device_removed_id); |
1211 | + } |
1212 | + |
1213 | + if (mouse_manager->priv->mouse_settings != NULL) |
1214 | + g_object_unref (mouse_manager->priv->mouse_settings); |
1215 | + |
1216 | + if (mouse_manager->priv->mouse_a11y_settings != NULL) |
1217 | + g_object_unref (mouse_manager->priv->mouse_a11y_settings); |
1218 | + |
1219 | + if (mouse_manager->priv->touchpad_settings != NULL) |
1220 | + g_object_unref (mouse_manager->priv->touchpad_settings); |
1221 | + |
1222 | + G_OBJECT_CLASS (gsd_mouse_manager_parent_class)->finalize (object); |
1223 | +} |
1224 | + |
1225 | +GsdMouseManager * |
1226 | +gsd_mouse_manager_new (void) |
1227 | +{ |
1228 | + if (manager_object != NULL) { |
1229 | + g_object_ref (manager_object); |
1230 | + } else { |
1231 | + manager_object = g_object_new (GSD_TYPE_MOUSE_MANAGER, NULL); |
1232 | + g_object_add_weak_pointer (manager_object, |
1233 | + (gpointer *) &manager_object); |
1234 | + } |
1235 | + |
1236 | + return GSD_MOUSE_MANAGER (manager_object); |
1237 | +} |
1238 | |
1239 | === modified file '.pc/applied-patches' |
1240 | --- .pc/applied-patches 2012-06-18 12:32:40 +0000 |
1241 | +++ .pc/applied-patches 2012-08-09 06:39:20 +0000 |
1242 | @@ -15,3 +15,4 @@ |
1243 | 50_add_dell_backlight.patch |
1244 | 51_always_lock_screen_on_suspend.patch |
1245 | git_xrandr_explicitly_set_clone_state.patch |
1246 | +52_kill_syndaemon_when_gsd_die.patch |
1247 | |
1248 | === modified file 'debian/changelog' |
1249 | --- debian/changelog 2012-06-18 12:32:40 +0000 |
1250 | +++ debian/changelog 2012-08-09 06:39:20 +0000 |
1251 | @@ -1,3 +1,13 @@ |
1252 | +gnome-settings-daemon (3.2.2-0ubuntu2.3) oneiric-proposed; urgency=low |
1253 | + |
1254 | + * debian/patches/52_kill_syndaemon_when_gsd_die.patch: |
1255 | + - Ensure that a spawned syndaemon gets killed when settings-daemon exists |
1256 | + due to a crash, a keyboard interrupt, etc. This avoids having multiple |
1257 | + syndaemons run at the same time, which can lead to the trackpad be |
1258 | + unexpected disabled. (LP: #868400) |
1259 | + |
1260 | + -- Hsin-Yi Chen (hychen) <hychen@ubuntu.com> Thu, 09 Aug 2012 14:28:59 +0800 |
1261 | + |
1262 | gnome-settings-daemon (3.2.2-0ubuntu2.2) oneiric-proposed; urgency=low |
1263 | |
1264 | [ Hsin-Yi, Chen (hychen) ] |
1265 | |
1266 | === added file 'debian/patches/52_kill_syndaemon_when_gsd_die.patch' |
1267 | --- debian/patches/52_kill_syndaemon_when_gsd_die.patch 1970-01-01 00:00:00 +0000 |
1268 | +++ debian/patches/52_kill_syndaemon_when_gsd_die.patch 2012-08-09 06:39:20 +0000 |
1269 | @@ -0,0 +1,76 @@ |
1270 | +From: Hsin-Yi Chen (hychen) <hychen@ubuntu.com> |
1271 | +Description: Ensure that a spawned syndaemon gets killed when |
1272 | + settings-daemon exists due to a crash, a keyboard interrupt, etc. |
1273 | + This avoids having multiple syndaemons run at the same time, which |
1274 | + can lead to the trackpad malfunctioning. |
1275 | +Origin: upstream, http://git.gnome.org/browse/gnome-settings-daemon/commit/?id=31aa30a0207b9de77706f03dacb8d914c959d3a6 |
1276 | +Author: Martin Pitt <martin.pitt@ubuntu.com> |
1277 | +Forwarded: not-needed |
1278 | +Bug: https://bugzilla.gnome.org/668667 |
1279 | +Bug-Ubuntu: https://launchpad.net/bugs/868400 |
1280 | + |
1281 | +Index: fix-868400-oneiric/plugins/mouse/gsd-mouse-manager.c |
1282 | +=================================================================== |
1283 | +--- fix-868400-oneiric.orig/plugins/mouse/gsd-mouse-manager.c 2012-07-25 15:27:51.745956000 +0800 |
1284 | ++++ fix-868400-oneiric/plugins/mouse/gsd-mouse-manager.c 2012-07-25 15:31:29.608752850 +0800 |
1285 | +@@ -28,6 +28,9 @@ |
1286 | + #include <string.h> |
1287 | + #include <errno.h> |
1288 | + #include <math.h> |
1289 | ++#ifdef __linux |
1290 | ++#include <sys/prctl.h> |
1291 | ++#endif |
1292 | + |
1293 | + #include <locale.h> |
1294 | + |
1295 | +@@ -527,6 +530,26 @@ |
1296 | + XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice); |
1297 | + } |
1298 | + |
1299 | ++/* Ensure that syndaemon dies together with us, to avoid running several of |
1300 | ++ * them */ |
1301 | ++static void |
1302 | ++setup_syndaemon (gpointer user_data) |
1303 | ++{ |
1304 | ++#ifdef __linux |
1305 | ++ prctl (PR_SET_PDEATHSIG, SIGHUP); |
1306 | ++#endif |
1307 | ++} |
1308 | ++ |
1309 | ++static void |
1310 | ++syndaemon_died (GPid pid, gint status, gpointer user_data) |
1311 | ++{ |
1312 | ++ GsdMouseManager *manager = GSD_MOUSE_MANAGER (user_data); |
1313 | ++ |
1314 | ++ g_debug ("syndaemon stopped with status %i", status); |
1315 | ++ g_spawn_close_pid (pid); |
1316 | ++ manager->priv->syndaemon_spawned = FALSE; |
1317 | ++} |
1318 | ++ |
1319 | + static int |
1320 | + set_disable_w_typing (GsdMouseManager *manager, gboolean state) |
1321 | + { |
1322 | +@@ -547,15 +570,22 @@ |
1323 | + if (!g_find_program_in_path (args[0])) |
1324 | + return 0; |
1325 | + |
1326 | ++ /* we must use G_SPAWN_DO_NOT_REAP_CHILD to avoid |
1327 | ++ * double-forking, otherwise syndaemon will immediately get |
1328 | ++ * killed again through (PR_SET_PDEATHSIG when the intermediate |
1329 | ++ * process dies */ |
1330 | + g_spawn_async (g_get_home_dir (), args, NULL, |
1331 | +- G_SPAWN_SEARCH_PATH, NULL, NULL, |
1332 | ++ G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD, setup_syndaemon, NULL, |
1333 | + &manager->priv->syndaemon_pid, &error); |
1334 | + |
1335 | + manager->priv->syndaemon_spawned = (error == NULL); |
1336 | + |
1337 | + if (error) { |
1338 | ++ g_warning ("Failed to launch syndaemon: %s", error->message); |
1339 | + g_settings_set_boolean (manager->priv->touchpad_settings, KEY_TOUCHPAD_DISABLE_W_TYPING, FALSE); |
1340 | + g_error_free (error); |
1341 | ++ } else { |
1342 | ++ g_child_watch_add (manager->priv->syndaemon_pid, syndaemon_died, manager); |
1343 | + } |
1344 | + } else if (manager->priv->syndaemon_spawned) { |
1345 | + kill (manager->priv->syndaemon_pid, SIGHUP); |
1346 | |
1347 | === modified file 'debian/patches/series' |
1348 | --- debian/patches/series 2012-06-18 12:32:40 +0000 |
1349 | +++ debian/patches/series 2012-08-09 06:39:20 +0000 |
1350 | @@ -15,3 +15,4 @@ |
1351 | 50_add_dell_backlight.patch |
1352 | 51_always_lock_screen_on_suspend.patch |
1353 | git_xrandr_explicitly_set_clone_state.patch |
1354 | +52_kill_syndaemon_when_gsd_die.patch |
1355 | |
1356 | === modified file 'plugins/mouse/gsd-mouse-manager.c' |
1357 | --- plugins/mouse/gsd-mouse-manager.c 2011-11-10 12:15:05 +0000 |
1358 | +++ plugins/mouse/gsd-mouse-manager.c 2012-08-09 06:39:20 +0000 |
1359 | @@ -28,6 +28,9 @@ |
1360 | #include <string.h> |
1361 | #include <errno.h> |
1362 | #include <math.h> |
1363 | +#ifdef __linux |
1364 | +#include <sys/prctl.h> |
1365 | +#endif |
1366 | |
1367 | #include <locale.h> |
1368 | |
1369 | @@ -527,6 +530,26 @@ |
1370 | XCloseDevice (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), xdevice); |
1371 | } |
1372 | |
1373 | +/* Ensure that syndaemon dies together with us, to avoid running several of |
1374 | + * them */ |
1375 | +static void |
1376 | +setup_syndaemon (gpointer user_data) |
1377 | +{ |
1378 | +#ifdef __linux |
1379 | + prctl (PR_SET_PDEATHSIG, SIGHUP); |
1380 | +#endif |
1381 | +} |
1382 | + |
1383 | +static void |
1384 | +syndaemon_died (GPid pid, gint status, gpointer user_data) |
1385 | +{ |
1386 | + GsdMouseManager *manager = GSD_MOUSE_MANAGER (user_data); |
1387 | + |
1388 | + g_debug ("syndaemon stopped with status %i", status); |
1389 | + g_spawn_close_pid (pid); |
1390 | + manager->priv->syndaemon_spawned = FALSE; |
1391 | +} |
1392 | + |
1393 | static int |
1394 | set_disable_w_typing (GsdMouseManager *manager, gboolean state) |
1395 | { |
1396 | @@ -547,15 +570,22 @@ |
1397 | if (!g_find_program_in_path (args[0])) |
1398 | return 0; |
1399 | |
1400 | + /* we must use G_SPAWN_DO_NOT_REAP_CHILD to avoid |
1401 | + * double-forking, otherwise syndaemon will immediately get |
1402 | + * killed again through (PR_SET_PDEATHSIG when the intermediate |
1403 | + * process dies */ |
1404 | g_spawn_async (g_get_home_dir (), args, NULL, |
1405 | - G_SPAWN_SEARCH_PATH, NULL, NULL, |
1406 | + G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD, setup_syndaemon, NULL, |
1407 | &manager->priv->syndaemon_pid, &error); |
1408 | |
1409 | manager->priv->syndaemon_spawned = (error == NULL); |
1410 | |
1411 | if (error) { |
1412 | + g_warning ("Failed to launch syndaemon: %s", error->message); |
1413 | g_settings_set_boolean (manager->priv->touchpad_settings, KEY_TOUCHPAD_DISABLE_W_TYPING, FALSE); |
1414 | g_error_free (error); |
1415 | + } else { |
1416 | + g_child_watch_add (manager->priv->syndaemon_pid, syndaemon_died, manager); |
1417 | } |
1418 | } else if (manager->priv->syndaemon_spawned) { |
1419 | kill (manager->priv->syndaemon_pid, SIGHUP); |
A few comments:
1- Please tag your patch using DEP-3: http:// dep.debian. net/deps/ dep3/ git.gnome. org/browse/ gnome-settings- daemon/ commit/ ?id=31aa30a0207 b9de77706f03dac b8d914c959d3a6
- Add link to upstream commit: http://
- Add link to upstream bug
- Add link to ubuntu bug
- etc.
2- Please remove "[ Hsin-Yi, Chen (hychen) ]" from debian/changelog, it's redundant
3- Please fix typo in changelog
4- Please revert modifications to older lines in the debian/changelog file
Thanks!