File: | plugins/mouse/csd_mouse-manager.c |
Warning: | line 205, column 30 Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu> |
3 | * |
4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License as published by |
6 | * the Free Software Foundation; either version 2 of the License, or |
7 | * (at your option) any later version. |
8 | * |
9 | * This program is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | * GNU General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU General Public License |
15 | * along with this program; if not, write to the Free Software |
16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. |
17 | * |
18 | */ |
19 | |
20 | #include "config.h" |
21 | |
22 | #include <sys/types.h> |
23 | #include <sys/wait.h> |
24 | #include <stdlib.h> |
25 | #include <stdio.h> |
26 | #include <unistd.h> |
27 | #include <string.h> |
28 | #include <errno(*__errno_location ()).h> |
29 | #include <math.h> |
30 | |
31 | #include <locale.h> |
32 | |
33 | #include <glib.h> |
34 | #include <glib/gi18n.h> |
35 | #include <ctk/ctk.h> |
36 | #include <cdk/cdk.h> |
37 | #include <cdk/cdkx.h> |
38 | #include <cdk/cdkkeysyms.h> |
39 | #include <X11/keysym.h> |
40 | #include <X11/Xatom.h> |
41 | #include <X11/extensions/XInput.h> |
42 | #include <X11/extensions/XIproto.h> |
43 | |
44 | #include <gio/gio.h> |
45 | |
46 | #include "cafe-settings-profile.h" |
47 | #include "csd_mouse-manager.h" |
48 | #include "csd_input-helper.h" |
49 | |
50 | /* Keys with same names for both touchpad and mouse */ |
51 | #define KEY_LEFT_HANDED"left-handed" "left-handed" /* a boolean for mouse, an enum for touchpad */ |
52 | #define KEY_MOTION_ACCELERATION"motion-acceleration" "motion-acceleration" |
53 | #define KEY_MOTION_THRESHOLD"motion-threshold" "motion-threshold" |
54 | #define KEY_ACCEL_PROFILE"accel-profile" "accel-profile" |
55 | |
56 | /* Mouse settings */ |
57 | #define CAFE_MOUSE_SCHEMA"org.cafe.peripherals-mouse" "org.cafe.peripherals-mouse" |
58 | #define KEY_MOUSE_LOCATE_POINTER"locate-pointer" "locate-pointer" |
59 | #define KEY_MIDDLE_BUTTON_EMULATION"middle-button-enabled" "middle-button-enabled" |
60 | |
61 | /* Touchpad settings */ |
62 | #define CAFE_TOUCHPAD_SCHEMA"org.cafe.peripherals-touchpad" "org.cafe.peripherals-touchpad" |
63 | #define KEY_TOUCHPAD_DISABLE_W_TYPING"disable-while-typing" "disable-while-typing" |
64 | #define KEY_TOUCHPAD_TWO_FINGER_CLICK"two-finger-click" "two-finger-click" |
65 | #define KEY_TOUCHPAD_THREE_FINGER_CLICK"three-finger-click" "three-finger-click" |
66 | #define KEY_TOUCHPAD_NATURAL_SCROLL"natural-scroll" "natural-scroll" |
67 | #define KEY_TOUCHPAD_TAP_TO_CLICK"tap-to-click" "tap-to-click" |
68 | #define KEY_TOUCHPAD_ONE_FINGER_TAP"tap-button-one-finger" "tap-button-one-finger" |
69 | #define KEY_TOUCHPAD_TWO_FINGER_TAP"tap-button-two-finger" "tap-button-two-finger" |
70 | #define KEY_TOUCHPAD_THREE_FINGER_TAP"tap-button-three-finger" "tap-button-three-finger" |
71 | #define KEY_VERT_EDGE_SCROLL"vertical-edge-scrolling" "vertical-edge-scrolling" |
72 | #define KEY_HORIZ_EDGE_SCROLL"horizontal-edge-scrolling" "horizontal-edge-scrolling" |
73 | #define KEY_VERT_TWO_FINGER_SCROLL"vertical-two-finger-scrolling" "vertical-two-finger-scrolling" |
74 | #define KEY_HORIZ_TWO_FINGER_SCROLL"horizontal-two-finger-scrolling" "horizontal-two-finger-scrolling" |
75 | #define KEY_TOUCHPAD_ENABLED"touchpad-enabled" "touchpad-enabled" |
76 | |
77 | |
78 | #if 0 /* FIXME need to fork (?) mousetweaks for this to work */ |
79 | #define CAFE_MOUSE_A11Y_SCHEMA "org.cafe.accessibility-mouse" |
80 | #define KEY_MOUSE_A11Y_DWELL_ENABLE "dwell-enable" |
81 | #define KEY_MOUSE_A11Y_DELAY_ENABLE "delay-enable" |
82 | #endif |
83 | |
84 | struct CsdMouseManagerPrivate |
85 | { |
86 | GSettings *settings_mouse; |
87 | GSettings *settings_touchpad; |
88 | |
89 | #if 0 /* FIXME need to fork (?) mousetweaks for this to work */ |
90 | gboolean mousetweaks_daemon_running; |
91 | #endif |
92 | gboolean syndaemon_spawned; |
93 | GPid syndaemon_pid; |
94 | gboolean locate_pointer_spawned; |
95 | GPid locate_pointer_pid; |
96 | }; |
97 | |
98 | typedef enum { |
99 | TOUCHPAD_HANDEDNESS_RIGHT, |
100 | TOUCHPAD_HANDEDNESS_LEFT, |
101 | TOUCHPAD_HANDEDNESS_MOUSE |
102 | } TouchpadHandedness; |
103 | |
104 | typedef enum { |
105 | ACCEL_PROFILE_DEFAULT, |
106 | ACCEL_PROFILE_ADAPTIVE, |
107 | ACCEL_PROFILE_FLAT |
108 | } AccelProfile; |
109 | |
110 | static void csd_mouse_manager_finalize (GObject *object); |
111 | static void set_mouse_settings (CsdMouseManager *manager); |
112 | static void set_tap_to_click_synaptics (XDeviceInfo *device_info, |
113 | gboolean state, |
114 | gboolean left_handed, |
115 | gint one_finger_tap, |
116 | gint two_finger_tap, |
117 | gint three_finger_tap); |
118 | |
119 | |
120 | G_DEFINE_TYPE_WITH_PRIVATE (CsdMouseManager, csd_mouse_manager, G_TYPE_OBJECT)static void csd_mouse_manager_init (CsdMouseManager *self); static void csd_mouse_manager_class_init (CsdMouseManagerClass *klass ); static GType csd_mouse_manager_get_type_once (void); static gpointer csd_mouse_manager_parent_class = ((void*)0); static gint CsdMouseManager_private_offset; static void csd_mouse_manager_class_intern_init (gpointer klass) { csd_mouse_manager_parent_class = g_type_class_peek_parent (klass); if (CsdMouseManager_private_offset != 0) g_type_class_adjust_private_offset (klass, &CsdMouseManager_private_offset); csd_mouse_manager_class_init ((CsdMouseManagerClass*) klass); } __attribute__ ((__unused__ )) static inline gpointer csd_mouse_manager_get_instance_private (CsdMouseManager *self) { return (((gpointer) ((guint8*) (self ) + (glong) (CsdMouseManager_private_offset)))); } GType csd_mouse_manager_get_type (void) { static GType static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer), "Expression evaluates to false"); (void) ( 0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0)) ; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id ) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (*(&static_g_define_type_id)) gapg_temp_newval; __typeof__ ((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id ); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5) ; gapg_temp_newval; })) && g_once_init_enter_pointer ( &static_g_define_type_id)); })) ) { GType g_define_type_id = csd_mouse_manager_get_type_once (); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer) , "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id ) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer ((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id )); })) ; } return static_g_define_type_id; } __attribute__ ( (__noinline__)) static GType csd_mouse_manager_get_type_once ( void) { GType g_define_type_id = g_type_register_static_simple (((GType) ((20) << (2))), g_intern_static_string ("CsdMouseManager" ), sizeof (CsdMouseManagerClass), (GClassInitFunc)(void (*)(void )) csd_mouse_manager_class_intern_init, sizeof (CsdMouseManager ), (GInstanceInitFunc)(void (*)(void)) csd_mouse_manager_init , (GTypeFlags) 0); { {{ CsdMouseManager_private_offset = g_type_add_instance_private (g_define_type_id, sizeof (CsdMouseManagerPrivate)); };} } return g_define_type_id; } |
121 | |
122 | static gpointer manager_object = NULL((void*)0); |
123 | |
124 | static void |
125 | csd_mouse_manager_class_init (CsdMouseManagerClass *klass) |
126 | { |
127 | GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((klass)), (((GType) ((20) << (2)))))))); |
128 | |
129 | object_class->finalize = csd_mouse_manager_finalize; |
130 | } |
131 | |
132 | static void |
133 | configure_button_layout (guchar *buttons, |
134 | gint n_buttons, |
135 | gboolean left_handed) |
136 | { |
137 | const gint left_button = 1; |
138 | gint right_button; |
139 | gint i; |
140 | |
141 | /* if the button is higher than 2 (3rd button) then it's |
142 | * probably one direction of a scroll wheel or something else |
143 | * uninteresting |
144 | */ |
145 | right_button = MIN (n_buttons, 3)(((n_buttons) < (3)) ? (n_buttons) : (3)); |
146 | |
147 | /* If we change things we need to make sure we only swap buttons. |
148 | * If we end up with multiple physical buttons assigned to the same |
149 | * logical button the server will complain. This code assumes physical |
150 | * button 0 is the physical left mouse button, and that the physical |
151 | * button other than 0 currently assigned left_button or right_button |
152 | * is the physical right mouse button. |
153 | */ |
154 | |
155 | /* check if the current mapping satisfies the above assumptions */ |
156 | if (buttons[left_button - 1] != left_button && |
157 | buttons[left_button - 1] != right_button) |
158 | /* The current mapping is weird. Swapping buttons is probably not a |
159 | * good idea. |
160 | */ |
161 | return; |
162 | |
163 | /* check if we are left_handed and currently not swapped */ |
164 | if (left_handed && buttons[left_button - 1] == left_button) { |
165 | /* find the right button */ |
166 | for (i = 0; i < n_buttons; i++) { |
167 | if (buttons[i] == right_button) { |
168 | buttons[i] = left_button; |
169 | break; |
170 | } |
171 | } |
172 | /* swap the buttons */ |
173 | buttons[left_button - 1] = right_button; |
174 | } |
175 | /* check if we are not left_handed but are swapped */ |
176 | else if (!left_handed && buttons[left_button - 1] == right_button) { |
177 | /* find the right button */ |
178 | for (i = 0; i < n_buttons; i++) { |
179 | if (buttons[i] == left_button) { |
180 | buttons[i] = right_button; |
181 | break; |
182 | } |
183 | } |
184 | /* swap the buttons */ |
185 | buttons[left_button - 1] = left_button; |
186 | } |
187 | } |
188 | |
189 | static gboolean |
190 | xinput_device_has_buttons (XDeviceInfo *device_info) |
191 | { |
192 | int i; |
193 | XAnyClassInfo *class_info; |
194 | |
195 | class_info = device_info->inputclassinfo; |
196 | for (i = 0; i < device_info->num_classes; i++) { |
197 | if (class_info->class == ButtonClass1) { |
198 | XButtonInfo *button_info; |
199 | |
200 | button_info = (XButtonInfo *) class_info; |
201 | if (button_info->num_buttons > 0) |
202 | return TRUE(!(0)); |
203 | } |
204 | |
205 | class_info = (XAnyClassInfo *) (((guchar *) class_info) + |
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption | |
206 | class_info->length); |
207 | } |
208 | return FALSE(0); |
209 | } |
210 | |
211 | static Atom |
212 | property_from_name (const char *property_name) |
213 | { |
214 | return XInternAtom (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), property_name, True1); |
215 | } |
216 | |
217 | static void * |
218 | get_property (XDevice *device, |
219 | const gchar *property, |
220 | Atom type, |
221 | int format, |
222 | gulong nitems) |
223 | { |
224 | CdkDisplay *display; |
225 | gulong nitems_ret, bytes_after_ret; |
226 | int rc, format_ret; |
227 | Atom property_atom, type_ret; |
228 | guchar *data = NULL((void*)0); |
229 | |
230 | property_atom = property_from_name (property); |
231 | if (!property_atom) |
232 | return NULL((void*)0); |
233 | |
234 | display = cdk_display_get_default (); |
235 | |
236 | cdk_x11_display_error_trap_push (display); |
237 | |
238 | rc = XGetDeviceProperty (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device, property_atom, |
239 | 0, 10, False0, type, &type_ret, &format_ret, |
240 | &nitems_ret, &bytes_after_ret, &data); |
241 | |
242 | cdk_x11_display_error_trap_pop_ignored (display); |
243 | |
244 | if (rc == Success0 && type_ret == type && format_ret == format && nitems_ret >= nitems) |
245 | return data; |
246 | |
247 | if (data) |
248 | XFree (data); |
249 | |
250 | return NULL((void*)0); |
251 | } |
252 | |
253 | static void |
254 | change_property (XDevice *device, |
255 | const gchar *property, |
256 | Atom type, |
257 | int format, |
258 | void *data, |
259 | gulong nitems) |
260 | { |
261 | CdkDisplay *display; |
262 | Atom property_atom; |
263 | guchar *data_ret; |
264 | |
265 | property_atom = property_from_name (property); |
266 | if (!property_atom) |
267 | return; |
268 | |
269 | data_ret = get_property (device, property, type, format, nitems); |
270 | if (!data_ret) |
271 | return; |
272 | |
273 | display = cdk_display_get_default (); |
274 | |
275 | cdk_x11_display_error_trap_push (display); |
276 | |
277 | XChangeDeviceProperty (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device, |
278 | property_atom, type, format, |
279 | PropModeReplace0, data, nitems); |
280 | |
281 | cdk_x11_display_error_trap_pop_ignored (display); |
282 | |
283 | XFree (data_ret); |
284 | } |
285 | |
286 | static gboolean |
287 | touchpad_has_single_button (XDevice *device) |
288 | { |
289 | Atom type, prop; |
290 | CdkDisplay *display; |
291 | int format; |
292 | unsigned long nitems, bytes_after; |
293 | unsigned char *data; |
294 | gboolean is_single_button = FALSE(0); |
295 | int rc; |
296 | |
297 | prop = property_from_name ("Synaptics Capabilities"); |
298 | if (!prop) |
299 | return FALSE(0); |
300 | |
301 | display = cdk_display_get_default (); |
302 | cdk_x11_display_error_trap_push (display); |
303 | rc = XGetDeviceProperty (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device, prop, 0, 1, False0, |
304 | XA_INTEGER((Atom) 19), &type, &format, &nitems, |
305 | &bytes_after, &data); |
306 | if (rc == Success0 && type == XA_INTEGER((Atom) 19) && format == 8 && nitems >= 3) |
307 | is_single_button = (data[0] == 1 && data[1] == 0 && data[2] == 0); |
308 | |
309 | if (rc == Success0) |
310 | XFree (data); |
311 | |
312 | cdk_x11_display_error_trap_pop_ignored (display); |
313 | |
314 | return is_single_button; |
315 | } |
316 | |
317 | static gboolean |
318 | property_exists_on_device (XDeviceInfo *device_info, |
319 | const char *property_name) |
320 | { |
321 | XDevice *device; |
322 | int rc; |
323 | Atom type, prop; |
324 | CdkDisplay *display; |
325 | int format; |
326 | unsigned long nitems, bytes_after; |
327 | unsigned char *data; |
328 | |
329 | prop = property_from_name (property_name); |
330 | if (!prop) |
331 | return FALSE(0); |
332 | |
333 | display = cdk_display_get_default (); |
334 | |
335 | cdk_x11_display_error_trap_push (display); |
336 | device = XOpenDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device_info->id); |
337 | if ((cdk_x11_display_error_trap_pop (display) != 0) || (device == NULL((void*)0))) |
338 | return FALSE(0); |
339 | |
340 | cdk_x11_display_error_trap_push (display); |
341 | rc = XGetDeviceProperty (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), |
342 | device, prop, 0, 1, False0, XA_INTEGER((Atom) 19), &type, &format, |
343 | &nitems, &bytes_after, &data); |
344 | |
345 | if (rc == Success0) |
346 | XFree (data); |
347 | |
348 | XCloseDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device); |
349 | cdk_x11_display_error_trap_pop_ignored (display); |
350 | |
351 | return rc == Success0; |
352 | } |
353 | |
354 | static void |
355 | property_set_bool (XDeviceInfo *device_info, |
356 | XDevice *device, |
357 | const char *property_name, |
358 | int property_index, |
359 | gboolean enabled) |
360 | { |
361 | int rc; |
362 | unsigned long nitems, bytes_after; |
363 | unsigned char *data; |
364 | int act_format; |
365 | Atom act_type, property; |
366 | CdkDisplay *display; |
367 | |
368 | property = property_from_name (property_name); |
369 | if (!property) |
370 | return; |
371 | |
372 | display = cdk_display_get_default (); |
373 | |
374 | cdk_x11_display_error_trap_push (display); |
375 | rc = XGetDeviceProperty (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device, |
376 | property, 0, 1, False0, |
377 | XA_INTEGER((Atom) 19), &act_type, &act_format, &nitems, |
378 | &bytes_after, &data); |
379 | |
380 | if (rc == Success0 && act_type == XA_INTEGER((Atom) 19) && act_format == 8 && nitems > property_index) { |
381 | data[property_index] = enabled ? 1 : 0; |
382 | XChangeDeviceProperty (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device, |
383 | property, XA_INTEGER((Atom) 19), 8, |
384 | PropModeReplace0, data, nitems); |
385 | } |
386 | |
387 | if (rc == Success0) |
388 | XFree (data); |
389 | |
390 | if (cdk_x11_display_error_trap_pop (display)) { |
391 | g_warning ("Error while setting %s on \"%s\"", property_name, device_info->name); |
392 | } |
393 | } |
394 | |
395 | static void |
396 | touchpad_set_bool (XDeviceInfo *device_info, |
397 | const char *property_name, |
398 | int property_index, |
399 | gboolean enabled) |
400 | { |
401 | XDevice *device; |
402 | CdkDisplay *display; |
403 | |
404 | device = device_is_touchpad (device_info); |
405 | if (device == NULL((void*)0)) { |
406 | return; |
407 | } |
408 | |
409 | property_set_bool (device_info, device, property_name, property_index, enabled); |
410 | |
411 | display = cdk_display_get_default (); |
412 | |
413 | cdk_x11_display_error_trap_push (display); |
414 | XCloseDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device); |
415 | cdk_x11_display_error_trap_pop_ignored (display); |
416 | } |
417 | |
418 | static void |
419 | set_left_handed_legacy_driver (CsdMouseManager *manager, |
420 | XDeviceInfo *device_info, |
421 | gboolean mouse_left_handed, |
422 | gboolean touchpad_left_handed) |
423 | { |
424 | XDevice *device; |
425 | CdkDisplay *display; |
426 | guchar *buttons; |
427 | gsize buttons_capacity = 16; |
428 | gint n_buttons; |
429 | gboolean left_handed; |
430 | |
431 | if ((device_info->use == IsXPointer0) || |
432 | (device_info->use == IsXKeyboard1) || |
433 | (g_strcmp0 ("Virtual core XTEST pointer", device_info->name) == 0) || |
434 | (!xinput_device_has_buttons (device_info))) |
435 | return; |
436 | |
437 | /* If the device is a touchpad, swap tap buttons |
438 | * around too, otherwise a tap would be a right-click */ |
439 | device = device_is_touchpad (device_info); |
440 | display = cdk_display_get_default (); |
441 | |
442 | if (device != NULL((void*)0)) { |
443 | gboolean tap = g_settings_get_boolean (manager->priv->settings_touchpad, KEY_TOUCHPAD_TAP_TO_CLICK"tap-to-click"); |
444 | gboolean single_button = touchpad_has_single_button (device); |
445 | |
446 | left_handed = touchpad_left_handed; |
447 | |
448 | if (tap && !single_button) { |
449 | gint one_finger_tap = g_settings_get_int (manager->priv->settings_touchpad, KEY_TOUCHPAD_ONE_FINGER_TAP"tap-button-one-finger"); |
450 | gint two_finger_tap = g_settings_get_int (manager->priv->settings_touchpad, KEY_TOUCHPAD_TWO_FINGER_TAP"tap-button-two-finger"); |
451 | gint three_finger_tap = g_settings_get_int (manager->priv->settings_touchpad, KEY_TOUCHPAD_THREE_FINGER_TAP"tap-button-three-finger"); |
452 | set_tap_to_click_synaptics (device_info, tap, left_handed, one_finger_tap, two_finger_tap, three_finger_tap); |
453 | } |
454 | |
455 | XCloseDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device); |
456 | |
457 | if (single_button) |
458 | return; |
459 | } else { |
460 | left_handed = mouse_left_handed; |
461 | } |
462 | |
463 | cdk_x11_display_error_trap_push (display); |
464 | |
465 | device = XOpenDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device_info->id); |
466 | if ((cdk_x11_display_error_trap_pop (display) != 0) || |
467 | (device == NULL((void*)0))) |
468 | return; |
469 | |
470 | buttons = g_new (guchar, buttons_capacity)((guchar *) g_malloc_n ((buttons_capacity), sizeof (guchar))); |
471 | |
472 | n_buttons = XGetDeviceButtonMapping (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device, |
473 | buttons, |
474 | buttons_capacity); |
475 | |
476 | while (n_buttons > buttons_capacity) { |
477 | buttons_capacity = n_buttons; |
478 | buttons = (guchar *) g_realloc (buttons, |
479 | buttons_capacity * sizeof (guchar)); |
480 | |
481 | n_buttons = XGetDeviceButtonMapping (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device, |
482 | buttons, |
483 | buttons_capacity); |
484 | } |
485 | |
486 | configure_button_layout (buttons, n_buttons, left_handed); |
487 | |
488 | XSetDeviceButtonMapping (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device, buttons, n_buttons); |
489 | XCloseDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device); |
490 | |
491 | g_free (buttons); |
492 | } |
493 | |
494 | static void |
495 | set_left_handed_libinput (XDeviceInfo *device_info, |
496 | gboolean mouse_left_handed, |
497 | gboolean touchpad_left_handed) |
498 | { |
499 | XDevice *device; |
500 | CdkDisplay *display; |
501 | gboolean want_lefthanded; |
502 | |
503 | device = device_is_touchpad (device_info); |
504 | display = cdk_display_get_default (); |
505 | |
506 | if (device == NULL((void*)0)) { |
507 | cdk_x11_display_error_trap_push (display); |
508 | device = XOpenDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device_info->id); |
509 | if ((cdk_x11_display_error_trap_pop (display) != 0) || (device == NULL((void*)0))) |
510 | return; |
511 | |
512 | want_lefthanded = mouse_left_handed; |
513 | } else { |
514 | /* touchpad device is already open after |
515 | * return from device_is_touchpad function |
516 | */ |
517 | want_lefthanded = touchpad_left_handed; |
518 | } |
519 | |
520 | property_set_bool (device_info, device, "libinput Left Handed Enabled", 0, want_lefthanded); |
521 | |
522 | cdk_x11_display_error_trap_push (display); |
523 | XCloseDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device); |
524 | cdk_x11_display_error_trap_pop_ignored (display); |
525 | |
526 | } |
527 | |
528 | static void |
529 | set_left_handed (CsdMouseManager *manager, |
530 | XDeviceInfo *device_info, |
531 | gboolean mouse_left_handed, |
532 | gboolean touchpad_left_handed) |
533 | { |
534 | if (property_exists_on_device (device_info, "libinput Left Handed Enabled")) |
535 | set_left_handed_libinput (device_info, mouse_left_handed, touchpad_left_handed); |
536 | else |
537 | set_left_handed_legacy_driver (manager, device_info, mouse_left_handed, touchpad_left_handed); |
538 | } |
539 | |
540 | static void |
541 | set_left_handed_all (CsdMouseManager *manager, |
542 | gboolean mouse_left_handed, |
543 | gboolean touchpad_left_handed) |
544 | { |
545 | XDeviceInfo *device_info; |
546 | gint n_devices; |
547 | gint i; |
548 | |
549 | device_info = XListInputDevices (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), &n_devices); |
550 | |
551 | for (i = 0; i < n_devices; i++) { |
552 | set_left_handed (manager, &device_info[i], mouse_left_handed, touchpad_left_handed); |
553 | } |
554 | |
555 | if (device_info != NULL((void*)0)) |
556 | XFreeDeviceList (device_info); |
557 | } |
558 | |
559 | static CdkFilterReturn |
560 | devicepresence_filter (CdkXEvent *xevent, |
561 | CdkEvent *event G_GNUC_UNUSED__attribute__ ((__unused__)), |
562 | gpointer data) |
563 | { |
564 | XEvent *xev = (XEvent *) xevent; |
565 | G_GNUC_UNUSED__attribute__ ((__unused__)) XEventClass class_presence; |
566 | int xi_presence; |
567 | |
568 | DevicePresence (cdk_x11_get_default_xdisplay (), xi_presence, class_presence){ xi_presence = _XiGetDevicePresenceNotifyEvent(cdk_x11_get_default_xdisplay ()); class_presence = (0x10000 | 0); }; |
569 | |
570 | if (xev->type == xi_presence) |
571 | { |
572 | XDevicePresenceNotifyEvent *dpn = (XDevicePresenceNotifyEvent *) xev; |
573 | if (dpn->devchange == DeviceEnabled2) |
574 | set_mouse_settings ((CsdMouseManager *) data); |
575 | } |
576 | |
577 | return CDK_FILTER_CONTINUE; |
578 | } |
579 | |
580 | static void |
581 | set_devicepresence_handler (CsdMouseManager *manager) |
582 | { |
583 | CdkDisplay *cdk_display; |
584 | Display *display; |
585 | XEventClass class_presence; |
586 | G_GNUC_UNUSED__attribute__ ((__unused__)) int xi_presence; |
587 | |
588 | cdk_display = cdk_display_get_default (); |
589 | display = cdk_x11_get_default_xdisplay (); |
590 | |
591 | cdk_x11_display_error_trap_push (cdk_display); |
592 | DevicePresence (display, xi_presence, class_presence){ xi_presence = _XiGetDevicePresenceNotifyEvent(display); class_presence = (0x10000 | 0); }; |
593 | XSelectExtensionEvent (display, |
594 | RootWindow (display, DefaultScreen (display))((&((_XPrivDisplay)(display))->screens[(((_XPrivDisplay )(display))->default_screen)])->root), |
595 | &class_presence, 1); |
596 | |
597 | cdk_display_flush (cdk_display); |
598 | if (!cdk_x11_display_error_trap_pop (cdk_display)) |
599 | cdk_window_add_filter (NULL((void*)0), devicepresence_filter, manager); |
600 | } |
601 | |
602 | static void |
603 | set_motion_legacy_driver (CsdMouseManager *manager, |
604 | XDeviceInfo *device_info) |
605 | { |
606 | XDevice *device; |
607 | CdkDisplay *display; |
608 | XPtrFeedbackControl feedback; |
609 | XFeedbackState *states, *state; |
610 | gint num_feedbacks, i; |
611 | GSettings *settings; |
612 | gdouble motion_acceleration; |
613 | gint motion_threshold; |
614 | gint numerator, denominator; |
615 | |
616 | device = device_is_touchpad (device_info); |
617 | display = cdk_display_get_default (); |
618 | |
619 | if (device != NULL((void*)0)) { |
620 | settings = manager->priv->settings_touchpad; |
621 | } else { |
622 | cdk_x11_display_error_trap_push (display); |
623 | device = XOpenDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device_info->id); |
624 | if ((cdk_x11_display_error_trap_pop (display) != 0) || (device == NULL((void*)0))) |
625 | return; |
626 | |
627 | settings = manager->priv->settings_mouse; |
628 | } |
629 | |
630 | /* Calculate acceleration */ |
631 | motion_acceleration = g_settings_get_double (settings, KEY_MOTION_ACCELERATION"motion-acceleration"); |
632 | if (motion_acceleration >= 1.0) { |
633 | /* we want to get the acceleration, with a resolution of 0.5 |
634 | */ |
635 | if ((motion_acceleration - floor (motion_acceleration)) < 0.25) { |
636 | numerator = floor (motion_acceleration); |
637 | denominator = 1; |
638 | } else if ((motion_acceleration - floor (motion_acceleration)) < 0.5) { |
639 | numerator = ceil (2.0 * motion_acceleration); |
640 | denominator = 2; |
641 | } else if ((motion_acceleration - floor (motion_acceleration)) < 0.75) { |
642 | numerator = floor (2.0 *motion_acceleration); |
643 | denominator = 2; |
644 | } else { |
645 | numerator = ceil (motion_acceleration); |
646 | denominator = 1; |
647 | } |
648 | } else if (motion_acceleration < 1.0 && motion_acceleration > 0) { |
649 | /* This we do to 1/10ths */ |
650 | numerator = floor (motion_acceleration * 10) + 1; |
651 | denominator= 10; |
652 | } else { |
653 | numerator = -1; |
654 | denominator = -1; |
655 | } |
656 | |
657 | /* And threshold */ |
658 | motion_threshold = g_settings_get_int (settings, KEY_MOTION_THRESHOLD"motion-threshold"); |
659 | |
660 | /* Get the list of feedbacks for the device */ |
661 | states = XGetFeedbackControl (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device, &num_feedbacks); |
662 | if (states == NULL((void*)0)) { |
663 | XCloseDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device); |
664 | return; |
665 | } |
666 | |
667 | state = (XFeedbackState *) states; |
668 | for (i = 0; i < num_feedbacks; i++) { |
669 | if (state->class == PtrFeedbackClass1) { |
670 | /* And tell the device */ |
671 | feedback.class = PtrFeedbackClass1; |
672 | feedback.length = sizeof (XPtrFeedbackControl); |
673 | feedback.id = state->id; |
674 | feedback.threshold = motion_threshold; |
675 | feedback.accelNum = numerator; |
676 | feedback.accelDenom = denominator; |
677 | |
678 | g_debug ("Setting accel %d/%d, threshold %d for device '%s'", |
679 | numerator, denominator, motion_threshold, device_info->name); |
680 | |
681 | XChangeFeedbackControl (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), |
682 | device, |
683 | DvAccelNum(1L << 0) | DvAccelDenom(1L << 1) | DvThreshold(1L << 2), |
684 | (XFeedbackControl *) &feedback); |
685 | break; |
686 | } |
687 | |
688 | state = (XFeedbackState *) ((char *) state + state->length); |
689 | } |
690 | |
691 | XFreeFeedbackList (states); |
692 | XCloseDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device); |
693 | } |
694 | |
695 | static void |
696 | set_motion_libinput (CsdMouseManager *manager, |
697 | XDeviceInfo *device_info) |
698 | { |
699 | XDevice *device; |
700 | CdkDisplay *display; |
701 | Atom prop; |
702 | Atom type; |
703 | Atom float_type; |
704 | int format, rc; |
705 | unsigned long nitems, bytes_after; |
706 | GSettings *settings; |
707 | union { |
708 | unsigned char *c; |
709 | long *l; |
710 | } data; |
711 | gfloat accel; |
712 | gfloat motion_acceleration; |
713 | |
714 | float_type = property_from_name ("FLOAT"); |
715 | if (!float_type) |
716 | return; |
717 | |
718 | prop = property_from_name ("libinput Accel Speed"); |
719 | if (!prop) { |
720 | return; |
721 | } |
722 | |
723 | device = device_is_touchpad (device_info); |
724 | display = cdk_display_get_default (); |
725 | |
726 | if (device != NULL((void*)0)) { |
727 | settings = manager->priv->settings_touchpad; |
728 | } else { |
729 | cdk_x11_display_error_trap_push (display); |
730 | device = XOpenDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device_info->id); |
731 | if ((cdk_x11_display_error_trap_pop (display) != 0) || (device == NULL((void*)0))) |
732 | return; |
733 | |
734 | settings = manager->priv->settings_mouse; |
735 | } |
736 | |
737 | /* Calculate acceleration */ |
738 | motion_acceleration = g_settings_get_double (settings, KEY_MOTION_ACCELERATION"motion-acceleration"); |
739 | |
740 | /* panel gives us a range of 1.0-10.0, map to libinput's [-1, 1] |
741 | * |
742 | * oldrange = (oldmax - oldmin) |
743 | * newrange = (newmax - newmin) |
744 | * |
745 | * mapped = (value - oldmin) * newrange / oldrange + oldmin |
746 | */ |
747 | |
748 | if (motion_acceleration == -1.0) /* unset */ |
749 | accel = 0.0; |
750 | else |
751 | accel = (motion_acceleration - 1.0) * 2.0 / 9.0 - 1; |
752 | |
753 | cdk_x11_display_error_trap_push (display); |
754 | rc = XGetDeviceProperty (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), |
755 | device, prop, 0, 1, False0, float_type, &type, &format, |
756 | &nitems, &bytes_after, &data.c); |
757 | |
758 | if (rc == Success0 && type == float_type && format == 32 && nitems >= 1) { |
759 | *(float *) data.l = accel; |
760 | XChangeDeviceProperty (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), |
761 | device, prop, float_type, 32, PropModeReplace0, data.c, nitems); |
762 | } |
763 | |
764 | if (rc == Success0) { |
765 | XFree (data.c); |
766 | } |
767 | |
768 | XCloseDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device); |
769 | if (cdk_x11_display_error_trap_pop (display)) { |
770 | g_warning ("Error while setting accel speed on \"%s\"", device_info->name); |
771 | } |
772 | } |
773 | |
774 | static void |
775 | set_motion (CsdMouseManager *manager, |
776 | XDeviceInfo *device_info) |
777 | { |
778 | if (property_exists_on_device (device_info, "libinput Accel Speed")) |
779 | set_motion_libinput (manager, device_info); |
780 | else |
781 | set_motion_legacy_driver (manager, device_info); |
782 | } |
783 | |
784 | static void |
785 | set_motion_all (CsdMouseManager *manager) |
786 | { |
787 | XDeviceInfo *device_info; |
788 | gint n_devices; |
789 | gint i; |
790 | |
791 | device_info = XListInputDevices (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), &n_devices); |
792 | |
793 | for (i = 0; i < n_devices; i++) { |
794 | set_motion (manager, &device_info[i]); |
795 | } |
796 | |
797 | if (device_info != NULL((void*)0)) |
798 | XFreeDeviceList (device_info); |
799 | } |
800 | |
801 | static void |
802 | set_middle_button_evdev (XDeviceInfo *device_info, |
803 | gboolean middle_button) |
804 | { |
805 | CdkDisplay *display; |
806 | XDevice *device; |
807 | Atom prop; |
808 | Atom type; |
809 | int format, rc; |
810 | unsigned long nitems, bytes_after; |
811 | unsigned char *data; |
812 | |
813 | prop = property_from_name ("Evdev Middle Button Emulation"); |
814 | |
815 | if (!prop) /* no evdev devices */ |
816 | return; |
817 | |
818 | display = cdk_display_get_default (); |
819 | |
820 | cdk_x11_display_error_trap_push (display); |
821 | |
822 | device = XOpenDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device_info->id); |
823 | if ((cdk_x11_display_error_trap_pop (display) != 0) || |
824 | (device == NULL((void*)0))) |
825 | return; |
826 | |
827 | cdk_x11_display_error_trap_push (display); |
828 | rc = XGetDeviceProperty (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), |
829 | device, prop, 0, 1, False0, XA_INTEGER((Atom) 19), &type, &format, |
830 | &nitems, &bytes_after, &data); |
831 | |
832 | if (rc == Success0 && format == 8 && type == XA_INTEGER((Atom) 19) && nitems == 1) { |
833 | data[0] = middle_button ? 1 : 0; |
834 | XChangeDeviceProperty (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), |
835 | device, prop, type, format, PropModeReplace0, data, nitems); |
836 | } |
837 | |
838 | if (rc == Success0) |
839 | XFree (data); |
840 | |
841 | XCloseDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device); |
842 | if (cdk_x11_display_error_trap_pop (display)) { |
843 | g_warning ("Error in setting middle button emulation on \"%s\"", device_info->name); |
844 | } |
845 | } |
846 | |
847 | static void |
848 | set_middle_button_libinput (XDeviceInfo *device_info, |
849 | gboolean middle_button) |
850 | { |
851 | XDevice *device; |
852 | CdkDisplay *display; |
853 | |
854 | /* touchpad devices are excluded as the old code |
855 | * only applies to evdev devices |
856 | */ |
857 | device = device_is_touchpad (device_info); |
858 | display = cdk_display_get_default (); |
859 | |
860 | if (device != NULL((void*)0)) { |
861 | cdk_x11_display_error_trap_push (display); |
862 | XCloseDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device); |
863 | cdk_x11_display_error_trap_pop_ignored (display); |
864 | return; |
865 | } |
866 | |
867 | cdk_x11_display_error_trap_push (display); |
868 | device = XOpenDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device_info->id); |
869 | if ((cdk_x11_display_error_trap_pop (display) != 0) || (device == NULL((void*)0))) |
870 | return; |
871 | |
872 | property_set_bool (device_info, device, "libinput Middle Emulation Enabled", 0, middle_button); |
873 | |
874 | cdk_x11_display_error_trap_push (display); |
875 | XCloseDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device); |
876 | cdk_x11_display_error_trap_pop_ignored (display); |
877 | } |
878 | |
879 | static void |
880 | set_middle_button (XDeviceInfo *device_info, |
881 | gboolean middle_button) |
882 | { |
883 | if (property_from_name ("Evdev Middle Button Emulation")) |
884 | set_middle_button_evdev (device_info, middle_button); |
885 | |
886 | if (property_from_name ("libinput Middle Emulation Enabled")) |
887 | set_middle_button_libinput (device_info, middle_button); |
888 | } |
889 | |
890 | static void |
891 | set_middle_button_all (gboolean middle_button) |
892 | { |
893 | XDeviceInfo *device_info; |
894 | gint n_devices; |
895 | gint i; |
896 | |
897 | device_info = XListInputDevices (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), &n_devices); |
898 | |
899 | for (i = 0; i < n_devices; i++) { |
900 | set_middle_button (&device_info[i], middle_button); |
901 | } |
902 | |
903 | if (device_info != NULL((void*)0)) |
904 | XFreeDeviceList (device_info); |
905 | } |
906 | |
907 | static gboolean |
908 | have_program_in_path (const char *name) |
909 | { |
910 | gchar *path; |
911 | gboolean result; |
912 | |
913 | path = g_find_program_in_path (name); |
914 | result = (path != NULL((void*)0)); |
915 | g_free (path); |
916 | return result; |
917 | } |
918 | |
919 | static void |
920 | set_disable_w_typing_synaptics (CsdMouseManager *manager, |
921 | gboolean state) |
922 | { |
923 | if (state && touchpad_is_present ()) { |
924 | GError *error = NULL((void*)0); |
925 | char *args[6]; |
926 | |
927 | if (manager->priv->syndaemon_spawned) |
928 | return; |
929 | |
930 | args[0] = "syndaemon"; |
931 | args[1] = "-i"; |
932 | args[2] = "0.5"; |
933 | args[3] = "-K"; |
934 | args[4] = "-R"; |
935 | args[5] = NULL((void*)0); |
936 | |
937 | if (!have_program_in_path (args[0])) |
938 | return; |
939 | |
940 | g_spawn_async (g_get_home_dir (), args, NULL((void*)0), |
941 | G_SPAWN_SEARCH_PATH, NULL((void*)0), NULL((void*)0), |
942 | &manager->priv->syndaemon_pid, &error); |
943 | |
944 | manager->priv->syndaemon_spawned = (error == NULL((void*)0)); |
945 | |
946 | if (error) { |
947 | g_settings_set_boolean (manager->priv->settings_touchpad, KEY_TOUCHPAD_DISABLE_W_TYPING"disable-while-typing", FALSE(0)); |
948 | g_error_free (error); |
949 | } |
950 | |
951 | } else if (manager->priv->syndaemon_spawned) |
952 | { |
953 | kill (manager->priv->syndaemon_pid, SIGHUP1); |
954 | g_spawn_close_pid (manager->priv->syndaemon_pid); |
955 | manager->priv->syndaemon_spawned = FALSE(0); |
956 | } |
957 | } |
958 | |
959 | static void |
960 | set_disable_w_typing_libinput (CsdMouseManager *manager G_GNUC_UNUSED__attribute__ ((__unused__)), |
961 | gboolean state) |
962 | { |
963 | XDeviceInfo *device_info; |
964 | gint n_devices; |
965 | gint i; |
966 | |
967 | /* This is only called once for synaptics but for libinput |
968 | * we need to loop through the list of devices |
969 | */ |
970 | device_info = XListInputDevices (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), &n_devices); |
971 | |
972 | for (i = 0; i < n_devices; i++) { |
973 | touchpad_set_bool (&device_info[i], "libinput Disable While Typing Enabled", 0, state); |
974 | } |
975 | |
976 | if (device_info != NULL((void*)0)) |
977 | XFreeDeviceList (device_info); |
978 | } |
979 | |
980 | static void |
981 | set_disable_w_typing (CsdMouseManager *manager, |
982 | gboolean state) |
983 | { |
984 | if (property_from_name ("Synaptics Off")) |
985 | set_disable_w_typing_synaptics (manager, state); |
986 | |
987 | if (property_from_name ("libinput Disable While Typing Enabled")) |
988 | set_disable_w_typing_libinput (manager, state); |
989 | } |
990 | |
991 | static void |
992 | set_accel_profile_libinput (CsdMouseManager *manager, |
993 | XDeviceInfo *device_info) |
994 | { |
995 | XDevice *device; |
996 | CdkDisplay *display; |
997 | GSettings *settings; |
998 | guchar *available, *defaults, *values; |
999 | |
1000 | display = cdk_display_get_default (); |
1001 | |
1002 | device = device_is_touchpad (device_info); |
1003 | |
1004 | if (device != NULL((void*)0)) { |
1005 | settings = manager->priv->settings_touchpad; |
1006 | } else { |
1007 | cdk_x11_display_error_trap_push (display); |
1008 | device = XOpenDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device_info->id); |
1009 | if ((cdk_x11_display_error_trap_pop (display) != 0) || (device == NULL((void*)0))) |
1010 | return; |
1011 | |
1012 | settings = manager->priv->settings_mouse; |
1013 | } |
1014 | |
1015 | available = get_property (device, "libinput Accel Profiles Available", XA_INTEGER((Atom) 19), 8, 2); |
1016 | if (!available) |
1017 | return; |
1018 | XFree (available); |
1019 | |
1020 | defaults = get_property (device, "libinput Accel Profile Enabled Default", XA_INTEGER((Atom) 19), 8, 2); |
1021 | if (!defaults) |
1022 | return; |
1023 | |
1024 | values = get_property (device, "libinput Accel Profile Enabled", XA_INTEGER((Atom) 19), 8, 2); |
1025 | if (!values) { |
1026 | XFree (defaults); |
1027 | return; |
1028 | } |
1029 | |
1030 | /* 2 boolean values (8 bit, 0 or 1), in order "adaptive", "flat". */ |
1031 | switch (g_settings_get_enum (settings, KEY_ACCEL_PROFILE"accel-profile")) { |
1032 | case ACCEL_PROFILE_ADAPTIVE: |
1033 | values[0] = 1; /* enable adaptive */ |
1034 | values[1] = 0; /* disable flat */ |
1035 | break; |
1036 | case ACCEL_PROFILE_FLAT: |
1037 | values[0] = 0; /* disable adaptive */ |
1038 | values[1] = 1; /* enable flat */ |
1039 | break; |
1040 | case ACCEL_PROFILE_DEFAULT: |
1041 | default: |
1042 | values[0] = defaults[0]; |
1043 | values[1] = defaults[1]; |
1044 | break; |
1045 | } |
1046 | |
1047 | change_property (device, "libinput Accel Profile Enabled", XA_INTEGER((Atom) 19), 8, values, 2); |
1048 | |
1049 | XCloseDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device); |
1050 | |
1051 | XFree (defaults); |
1052 | XFree (values); |
1053 | } |
1054 | |
1055 | static void |
1056 | set_accel_profile (CsdMouseManager *manager, |
1057 | XDeviceInfo *device_info) |
1058 | { |
1059 | if (property_exists_on_device (device_info, "libinput Accel Profile Enabled")) |
1060 | set_accel_profile_libinput (manager, device_info); |
1061 | |
1062 | /* TODO: Add acceleration profiles for synaptics/legacy drivers */ |
1063 | } |
1064 | |
1065 | static void |
1066 | set_accel_profile_all (CsdMouseManager *manager) |
1067 | { |
1068 | int numdevices, i; |
1069 | XDeviceInfo *devicelist = XListInputDevices (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), &numdevices); |
1070 | |
1071 | if (devicelist == NULL((void*)0)) |
1072 | return; |
1073 | |
1074 | for (i = 0; i < numdevices; i++) { |
1075 | set_accel_profile (manager, &devicelist[i]); |
1076 | } |
1077 | |
1078 | XFreeDeviceList (devicelist); |
1079 | } |
1080 | |
1081 | static gboolean |
1082 | get_touchpad_handedness (CsdMouseManager *manager, |
1083 | gboolean mouse_left_handed) |
1084 | { |
1085 | switch (g_settings_get_enum (manager->priv->settings_touchpad, KEY_LEFT_HANDED"left-handed")) { |
1086 | case TOUCHPAD_HANDEDNESS_RIGHT: |
1087 | return FALSE(0); |
1088 | case TOUCHPAD_HANDEDNESS_LEFT: |
1089 | return TRUE(!(0)); |
1090 | case TOUCHPAD_HANDEDNESS_MOUSE: |
1091 | return mouse_left_handed; |
1092 | default: |
1093 | g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "csd_mouse-manager.c" , 1093, ((const char*) (__func__)), ((void*)0)); } while (0); |
1094 | } |
1095 | } |
1096 | |
1097 | static void |
1098 | set_tap_to_click_synaptics (XDeviceInfo *device_info, |
1099 | gboolean state, |
1100 | gboolean left_handed, |
1101 | gint one_finger_tap, |
1102 | gint two_finger_tap, |
1103 | gint three_finger_tap) |
1104 | { |
1105 | XDevice *device; |
1106 | CdkDisplay *display; |
1107 | int format, rc; |
1108 | unsigned long nitems, bytes_after; |
1109 | unsigned char* data; |
1110 | Atom prop, type; |
1111 | |
1112 | prop = property_from_name ("Synaptics Tap Action"); |
1113 | |
1114 | if (!prop) |
1115 | return; |
1116 | |
1117 | device = device_is_touchpad (device_info); |
1118 | if (device == NULL((void*)0)) { |
1119 | return; |
1120 | } |
1121 | |
1122 | display = cdk_display_get_default (); |
1123 | |
1124 | cdk_x11_display_error_trap_push (display); |
1125 | rc = XGetDeviceProperty (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device, prop, 0, 2, |
1126 | False0, XA_INTEGER((Atom) 19), &type, &format, &nitems, |
1127 | &bytes_after, &data); |
1128 | |
1129 | if (one_finger_tap > 3 || one_finger_tap < 1) |
1130 | one_finger_tap = 1; |
1131 | if (two_finger_tap > 3 || two_finger_tap < 1) |
1132 | two_finger_tap = 3; |
1133 | if (three_finger_tap > 3 || three_finger_tap < 1) |
1134 | three_finger_tap = 2; |
1135 | |
1136 | if (rc == Success0 && type == XA_INTEGER((Atom) 19) && format == 8 && nitems >= 7) |
1137 | { |
1138 | /* Set RLM mapping for 1/2/3 fingers*/ |
1139 | data[4] = (state) ? ((left_handed) ? (4-one_finger_tap) : one_finger_tap) : 0; |
1140 | data[5] = (state) ? ((left_handed) ? (4-two_finger_tap) : two_finger_tap) : 0; |
1141 | data[6] = (state) ? three_finger_tap : 0; |
1142 | XChangeDeviceProperty (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device, prop, XA_INTEGER((Atom) 19), 8, |
1143 | PropModeReplace0, data, nitems); |
1144 | } |
1145 | |
1146 | if (rc == Success0) |
1147 | XFree (data); |
1148 | |
1149 | XCloseDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device); |
1150 | if (cdk_x11_display_error_trap_pop (display)) { |
1151 | g_warning ("Error in setting tap to click on \"%s\"", device_info->name); |
1152 | } |
1153 | } |
1154 | |
1155 | static void |
1156 | set_tap_to_click_libinput (XDeviceInfo *device_info, |
1157 | gboolean state) |
1158 | { |
1159 | touchpad_set_bool (device_info, "libinput Tapping Enabled", 0, state); |
1160 | } |
1161 | |
1162 | static void |
1163 | set_tap_to_click (XDeviceInfo *device_info, |
1164 | gboolean state, |
1165 | gboolean left_handed, |
1166 | gint one_finger_tap, |
1167 | gint two_finger_tap, |
1168 | gint three_finger_tap) |
1169 | { |
1170 | if (property_from_name ("Synaptics Tap Action")) |
1171 | set_tap_to_click_synaptics (device_info, state, left_handed, |
1172 | one_finger_tap, two_finger_tap, three_finger_tap); |
1173 | |
1174 | if (property_from_name ("libinput Tapping Enabled")) |
1175 | set_tap_to_click_libinput (device_info, state); |
1176 | } |
1177 | |
1178 | static void |
1179 | set_tap_to_click_all (CsdMouseManager *manager) |
1180 | { |
1181 | int numdevices, i; |
1182 | XDeviceInfo *devicelist = XListInputDevices (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), &numdevices); |
1183 | |
1184 | if (devicelist == NULL((void*)0)) |
1185 | return; |
1186 | |
1187 | gboolean state = g_settings_get_boolean (manager->priv->settings_touchpad, KEY_TOUCHPAD_TAP_TO_CLICK"tap-to-click"); |
1188 | gboolean left_handed = get_touchpad_handedness (manager, g_settings_get_boolean (manager->priv->settings_mouse, KEY_LEFT_HANDED"left-handed")); |
1189 | gint one_finger_tap = g_settings_get_int (manager->priv->settings_touchpad, KEY_TOUCHPAD_ONE_FINGER_TAP"tap-button-one-finger"); |
1190 | gint two_finger_tap = g_settings_get_int (manager->priv->settings_touchpad, KEY_TOUCHPAD_TWO_FINGER_TAP"tap-button-two-finger"); |
1191 | gint three_finger_tap = g_settings_get_int (manager->priv->settings_touchpad, KEY_TOUCHPAD_THREE_FINGER_TAP"tap-button-three-finger"); |
1192 | |
1193 | for (i = 0; i < numdevices; i++) { |
1194 | set_tap_to_click (&devicelist[i], state, left_handed, one_finger_tap, two_finger_tap, three_finger_tap); |
1195 | } |
1196 | |
1197 | XFreeDeviceList (devicelist); |
1198 | } |
1199 | |
1200 | static void |
1201 | set_click_actions_synaptics (XDeviceInfo *device_info, |
1202 | gint enable_two_finger_click, |
1203 | gint enable_three_finger_click) |
1204 | { |
1205 | XDevice *device; |
1206 | int format, rc; |
1207 | unsigned long nitems, bytes_after; |
1208 | unsigned char* data; |
1209 | Atom prop, type; |
1210 | CdkDisplay *display; |
1211 | |
1212 | prop = property_from_name ("Synaptics Click Action"); |
1213 | if (!prop) |
1214 | return; |
1215 | |
1216 | device = device_is_touchpad (device_info); |
1217 | if (device == NULL((void*)0)) { |
1218 | return; |
1219 | } |
1220 | |
1221 | g_debug ("setting click action to click on %s", device_info->name); |
1222 | |
1223 | display = cdk_display_get_default (); |
1224 | |
1225 | cdk_x11_display_error_trap_push (display); |
1226 | rc = XGetDeviceProperty (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device, prop, 0, 2, |
1227 | False0, XA_INTEGER((Atom) 19), &type, &format, &nitems, |
1228 | &bytes_after, &data); |
1229 | |
1230 | if (rc == Success0 && type == XA_INTEGER((Atom) 19) && format == 8 && nitems >= 3) { |
1231 | data[0] = 1; |
1232 | data[1] = enable_two_finger_click; |
1233 | data[2] = enable_three_finger_click; |
1234 | XChangeDeviceProperty (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device, prop, |
1235 | XA_INTEGER((Atom) 19), 8, PropModeReplace0, data, nitems); |
1236 | } |
1237 | |
1238 | if (rc == Success0) |
1239 | XFree (data); |
1240 | |
1241 | XCloseDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device); |
1242 | if (cdk_x11_display_error_trap_pop (display)) { |
1243 | g_warning ("Error in setting click actions on \"%s\"", device_info->name); |
1244 | } |
1245 | } |
1246 | |
1247 | static void |
1248 | set_click_actions_libinput (XDeviceInfo *device_info, |
1249 | gint enable_two_finger_click, |
1250 | gint enable_three_finger_click) |
1251 | { |
1252 | XDevice *device; |
1253 | int format, rc; |
1254 | unsigned long nitems, bytes_after; |
1255 | unsigned char *data; |
1256 | Atom prop, type; |
1257 | gboolean want_clickfinger; |
1258 | gboolean want_softwarebuttons; |
1259 | CdkDisplay *display; |
1260 | |
1261 | prop = property_from_name ("libinput Click Method Enabled"); |
1262 | if (!prop) |
1263 | return; |
1264 | |
1265 | device = device_is_touchpad (device_info); |
1266 | if (device == NULL((void*)0)) { |
1267 | return; |
1268 | } |
1269 | |
1270 | g_debug ("setting click action to click on %s", device_info->name); |
1271 | |
1272 | want_clickfinger = enable_two_finger_click || enable_three_finger_click; |
1273 | want_softwarebuttons = !want_clickfinger; |
1274 | |
1275 | display = cdk_display_get_default (); |
1276 | |
1277 | cdk_x11_display_error_trap_push (display); |
1278 | rc = XGetDeviceProperty (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device, prop, 0, 2, |
1279 | False0, XA_INTEGER((Atom) 19), &type, &format, &nitems, |
1280 | &bytes_after, &data); |
1281 | |
1282 | if (rc == Success0 && type == XA_INTEGER((Atom) 19) && format == 8 && nitems >= 2) { |
1283 | data[0] = want_softwarebuttons; |
1284 | data[1] = want_clickfinger; |
1285 | XChangeDeviceProperty (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device, prop, |
1286 | XA_INTEGER((Atom) 19), 8, PropModeReplace0, data, nitems); |
1287 | } |
1288 | |
1289 | if (rc == Success0) |
1290 | XFree (data); |
1291 | |
1292 | XCloseDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device); |
1293 | if (cdk_x11_display_error_trap_pop (display)) { |
1294 | g_warning ("Error in setting click actions on \"%s\"", device_info->name); |
1295 | } |
1296 | } |
1297 | |
1298 | static void |
1299 | set_click_actions (XDeviceInfo *device_info, |
1300 | gint enable_two_finger_click, |
1301 | gint enable_three_finger_click) |
1302 | { |
1303 | if (property_from_name ("Synaptics Click Action")) |
1304 | set_click_actions_synaptics (device_info, enable_two_finger_click, enable_three_finger_click); |
1305 | |
1306 | if (property_from_name ("libinput Click Method Enabled")) |
1307 | set_click_actions_libinput (device_info, enable_two_finger_click, enable_three_finger_click); |
1308 | } |
1309 | |
1310 | static void |
1311 | set_click_actions_all (CsdMouseManager *manager) |
1312 | { |
1313 | int numdevices, i; |
1314 | XDeviceInfo *devicelist = XListInputDevices (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), &numdevices); |
1315 | |
1316 | if (devicelist == NULL((void*)0)) |
1317 | return; |
1318 | |
1319 | gint enable_two_finger_click = g_settings_get_int (manager->priv->settings_touchpad, KEY_TOUCHPAD_TWO_FINGER_CLICK"two-finger-click"); |
1320 | gint enable_three_finger_click = g_settings_get_int (manager->priv->settings_touchpad, KEY_TOUCHPAD_THREE_FINGER_CLICK"three-finger-click"); |
1321 | |
1322 | for (i = 0; i < numdevices; i++) { |
1323 | set_click_actions (&devicelist[i], enable_two_finger_click, enable_three_finger_click); |
1324 | } |
1325 | |
1326 | XFreeDeviceList (devicelist); |
1327 | } |
1328 | |
1329 | static void |
1330 | set_natural_scroll_synaptics (XDeviceInfo *device_info, |
1331 | gboolean natural_scroll) |
1332 | { |
1333 | XDevice *device; |
1334 | int format, rc; |
1335 | unsigned long nitems, bytes_after; |
1336 | unsigned char* data; |
1337 | glong *ptr; |
1338 | Atom prop, type; |
1339 | CdkDisplay *display; |
1340 | |
1341 | prop = property_from_name ("Synaptics Scrolling Distance"); |
1342 | if (!prop) |
1343 | return; |
1344 | |
1345 | device = device_is_touchpad (device_info); |
1346 | if (device == NULL((void*)0)) { |
1347 | return; |
1348 | } |
1349 | |
1350 | g_debug ("Trying to set %s for \"%s\"", natural_scroll ? "natural (reverse) scroll" : "normal scroll", device_info->name); |
1351 | |
1352 | display = cdk_display_get_default (); |
1353 | |
1354 | cdk_x11_display_error_trap_push (display); |
1355 | rc = XGetDeviceProperty (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device, prop, 0, 2, |
1356 | False0, XA_INTEGER((Atom) 19), &type, &format, &nitems, |
1357 | &bytes_after, &data); |
1358 | |
1359 | if (rc == Success0 && type == XA_INTEGER((Atom) 19) && format == 32 && nitems >= 2) { |
1360 | ptr = (glong *) data; |
1361 | if (natural_scroll) { |
1362 | ptr[0] = -abs(ptr[0]); |
1363 | ptr[1] = -abs(ptr[1]); |
1364 | } else { |
1365 | ptr[0] = abs(ptr[0]); |
1366 | ptr[1] = abs(ptr[1]); |
1367 | } |
1368 | |
1369 | XChangeDeviceProperty (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device, prop, |
1370 | XA_INTEGER((Atom) 19), 32, PropModeReplace0, data, nitems); |
1371 | } |
1372 | |
1373 | if (rc == Success0) |
1374 | XFree (data); |
1375 | |
1376 | XCloseDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device); |
1377 | if (cdk_x11_display_error_trap_pop (display)) { |
1378 | g_warning ("Error in setting natural scroll on \"%s\"", device_info->name); |
1379 | } |
1380 | } |
1381 | |
1382 | static void |
1383 | set_natural_scroll_libinput (XDeviceInfo *device_info, |
1384 | gboolean natural_scroll) |
1385 | { |
1386 | g_debug ("Trying to set %s for \"%s\"", natural_scroll ? "natural (reverse) scroll" : "normal scroll", device_info->name); |
1387 | |
1388 | touchpad_set_bool (device_info, "libinput Natural Scrolling Enabled", 0, natural_scroll); |
1389 | } |
1390 | |
1391 | static void |
1392 | set_natural_scroll (XDeviceInfo *device_info, |
1393 | gboolean natural_scroll) |
1394 | { |
1395 | if (property_from_name ("Synaptics Scrolling Distance")) |
1396 | set_natural_scroll_synaptics (device_info, natural_scroll); |
1397 | |
1398 | if (property_from_name ("libinput Natural Scrolling Enabled")) |
1399 | set_natural_scroll_libinput (device_info, natural_scroll); |
1400 | } |
1401 | |
1402 | static void |
1403 | set_natural_scroll_all (CsdMouseManager *manager) |
1404 | { |
1405 | int numdevices, i; |
1406 | XDeviceInfo *devicelist = XListInputDevices (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), &numdevices); |
1407 | |
1408 | if (devicelist == NULL((void*)0)) |
1409 | return; |
1410 | |
1411 | gboolean natural_scroll = g_settings_get_boolean (manager->priv->settings_touchpad, KEY_TOUCHPAD_NATURAL_SCROLL"natural-scroll"); |
1412 | |
1413 | for (i = 0; i < numdevices; i++) { |
1414 | set_natural_scroll (&devicelist[i], natural_scroll); |
1415 | } |
1416 | |
1417 | XFreeDeviceList (devicelist); |
1418 | } |
1419 | |
1420 | static void |
1421 | set_scrolling_synaptics (XDeviceInfo *device_info, |
1422 | GSettings *settings) |
1423 | { |
1424 | touchpad_set_bool (device_info, "Synaptics Edge Scrolling", 0, g_settings_get_boolean (settings, KEY_VERT_EDGE_SCROLL"vertical-edge-scrolling")); |
1425 | touchpad_set_bool (device_info, "Synaptics Edge Scrolling", 1, g_settings_get_boolean (settings, KEY_HORIZ_EDGE_SCROLL"horizontal-edge-scrolling")); |
1426 | touchpad_set_bool (device_info, "Synaptics Two-Finger Scrolling", 0, g_settings_get_boolean (settings, KEY_VERT_TWO_FINGER_SCROLL"vertical-two-finger-scrolling")); |
1427 | touchpad_set_bool (device_info, "Synaptics Two-Finger Scrolling", 1, g_settings_get_boolean (settings, KEY_HORIZ_TWO_FINGER_SCROLL"horizontal-two-finger-scrolling")); |
1428 | } |
1429 | |
1430 | static void |
1431 | set_scrolling_libinput (XDeviceInfo *device_info, |
1432 | GSettings *settings) |
1433 | { |
1434 | XDevice *device; |
1435 | int format, rc; |
1436 | unsigned long nitems, bytes_after; |
1437 | unsigned char *data; |
1438 | Atom prop, type; |
1439 | gboolean want_edge, want_2fg; |
1440 | CdkDisplay *display; |
1441 | gboolean want_horiz; |
1442 | |
1443 | prop = property_from_name ("libinput Scroll Method Enabled"); |
1444 | if (!prop) |
1445 | return; |
1446 | |
1447 | device = device_is_touchpad (device_info); |
1448 | if (device == NULL((void*)0)) { |
1449 | return; |
1450 | } |
1451 | |
1452 | want_2fg = g_settings_get_boolean (settings, KEY_VERT_TWO_FINGER_SCROLL"vertical-two-finger-scrolling"); |
1453 | want_edge = g_settings_get_boolean (settings, KEY_VERT_EDGE_SCROLL"vertical-edge-scrolling"); |
1454 | |
1455 | /* libinput only allows for one scroll method at a time. |
1456 | * If both are set, pick 2fg scrolling. |
1457 | */ |
1458 | if (want_2fg) |
1459 | want_edge = FALSE(0); |
1460 | |
1461 | g_debug ("setting scroll method on %s", device_info->name); |
1462 | |
1463 | display = cdk_display_get_default (); |
1464 | |
1465 | cdk_x11_display_error_trap_push (display); |
1466 | rc = XGetDeviceProperty (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device, prop, 0, 2, |
1467 | False0, XA_INTEGER((Atom) 19), &type, &format, &nitems, |
1468 | &bytes_after, &data); |
1469 | |
1470 | if (rc == Success0 && type == XA_INTEGER((Atom) 19) && format == 8 && nitems >= 3) { |
1471 | data[0] = want_2fg; |
1472 | data[1] = want_edge; |
1473 | XChangeDeviceProperty (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device, |
1474 | prop, XA_INTEGER((Atom) 19), 8, PropModeReplace0, data, nitems); |
1475 | } |
1476 | |
1477 | if (rc == Success0) |
1478 | XFree (data); |
1479 | |
1480 | XCloseDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device); |
1481 | if (cdk_x11_display_error_trap_pop (display)) { |
1482 | g_warning ("Error in setting scroll method on \"%s\"", device_info->name); |
1483 | } |
1484 | |
1485 | /* Horizontal scrolling is handled by xf86-input-libinput and |
1486 | * there's only one bool. Pick the one matching the scroll method |
1487 | * we picked above. |
1488 | */ |
1489 | if (want_2fg) |
1490 | want_horiz = g_settings_get_boolean (settings, KEY_HORIZ_TWO_FINGER_SCROLL"horizontal-two-finger-scrolling"); |
1491 | else if (want_edge) |
1492 | want_horiz = g_settings_get_boolean (settings, KEY_HORIZ_EDGE_SCROLL"horizontal-edge-scrolling"); |
1493 | else |
1494 | return; |
1495 | |
1496 | touchpad_set_bool (device_info, "libinput Horizontal Scroll Enabled", 0, want_horiz); |
1497 | } |
1498 | |
1499 | static void |
1500 | set_scrolling (XDeviceInfo *device_info, |
1501 | GSettings *settings) |
1502 | { |
1503 | if (property_from_name ("Synaptics Edge Scrolling")) |
1504 | set_scrolling_synaptics (device_info, settings); |
1505 | |
1506 | if (property_from_name ("libinput Scroll Method Enabled")) |
1507 | set_scrolling_libinput (device_info, settings); |
1508 | } |
1509 | |
1510 | static void |
1511 | set_scrolling_all (GSettings *settings) |
1512 | { |
1513 | int numdevices, i; |
1514 | XDeviceInfo *devicelist = XListInputDevices (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), &numdevices); |
1515 | |
1516 | if (devicelist == NULL((void*)0)) |
1517 | return; |
1518 | |
1519 | for (i = 0; i < numdevices; i++) { |
1520 | set_scrolling (&devicelist[i], settings); |
1521 | } |
1522 | |
1523 | XFreeDeviceList (devicelist); |
1524 | } |
1525 | |
1526 | static void |
1527 | set_touchpad_enabled (XDeviceInfo *device_info, |
1528 | gboolean state) |
1529 | { |
1530 | XDevice *device; |
1531 | Atom prop_enabled; |
1532 | CdkDisplay *display; |
1533 | unsigned char data = state; |
1534 | |
1535 | prop_enabled = property_from_name ("Device Enabled"); |
1536 | if (!prop_enabled) |
1537 | return; |
1538 | |
1539 | device = device_is_touchpad (device_info); |
1540 | if (device == NULL((void*)0)) { |
1541 | return; |
1542 | } |
1543 | |
1544 | display = cdk_display_get_default (); |
1545 | |
1546 | cdk_x11_display_error_trap_push (display); |
1547 | XChangeDeviceProperty (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device, |
1548 | prop_enabled, XA_INTEGER((Atom) 19), 8, |
1549 | PropModeReplace0, &data, 1); |
1550 | |
1551 | XCloseDevice (CDK_DISPLAY_XDISPLAY (display)(cdk_x11_display_get_xdisplay (display)), device); |
1552 | cdk_display_flush (display); |
1553 | if (cdk_x11_display_error_trap_pop (display)) { |
1554 | g_warning ("Error %s device \"%s\"", |
1555 | (state) ? "enabling" : "disabling", |
1556 | device_info->name); |
1557 | } |
1558 | } |
1559 | |
1560 | static void |
1561 | set_touchpad_enabled_all (gboolean state) |
1562 | { |
1563 | int numdevices, i; |
1564 | XDeviceInfo *devicelist = XListInputDevices (CDK_DISPLAY_XDISPLAY (cdk_display_get_default ())(cdk_x11_display_get_xdisplay (cdk_display_get_default ())), &numdevices); |
1565 | |
1566 | if (devicelist == NULL((void*)0)) |
1567 | return; |
1568 | |
1569 | for (i = 0; i < numdevices; i++) { |
1570 | set_touchpad_enabled (&devicelist[i], state); |
1571 | } |
1572 | |
1573 | XFreeDeviceList (devicelist); |
1574 | } |
1575 | |
1576 | static void |
1577 | set_locate_pointer (CsdMouseManager *manager, |
1578 | gboolean state) |
1579 | { |
1580 | if (state) { |
1581 | GError *error = NULL((void*)0); |
1582 | char *args[2]; |
1583 | |
1584 | if (manager->priv->locate_pointer_spawned) |
1585 | return; |
1586 | |
1587 | args[0] = LIBEXECDIR"/usr/libexec" "/csd_locate-pointer"; |
1588 | args[1] = NULL((void*)0); |
1589 | |
1590 | g_spawn_async (NULL((void*)0), args, NULL((void*)0), |
1591 | 0, NULL((void*)0), NULL((void*)0), |
1592 | &manager->priv->locate_pointer_pid, &error); |
1593 | |
1594 | manager->priv->locate_pointer_spawned = (error == NULL((void*)0)); |
1595 | |
1596 | if (error) { |
1597 | g_settings_set_boolean (manager->priv->settings_mouse, KEY_MOUSE_LOCATE_POINTER"locate-pointer", FALSE(0)); |
1598 | g_error_free (error); |
1599 | } |
1600 | |
1601 | } |
1602 | else if (manager->priv->locate_pointer_spawned) { |
1603 | kill (manager->priv->locate_pointer_pid, SIGHUP1); |
1604 | g_spawn_close_pid (manager->priv->locate_pointer_pid); |
1605 | manager->priv->locate_pointer_spawned = FALSE(0); |
1606 | } |
1607 | } |
1608 | |
1609 | #if 0 /* FIXME need to fork (?) mousetweaks for this to work */ |
1610 | static void |
1611 | set_mousetweaks_daemon (CsdMouseManager *manager, |
1612 | gboolean dwell_enable, |
1613 | gboolean delay_enable) |
1614 | { |
1615 | GError *error = NULL((void*)0); |
1616 | gchar *comm; |
1617 | gboolean run_daemon = dwell_enable || delay_enable; |
1618 | |
1619 | if (run_daemon || manager->priv->mousetweaks_daemon_running) |
1620 | comm = g_strdup_printf ("mousetweaks %s", |
1621 | run_daemon ? "" : "-s"); |
1622 | else |
1623 | return; |
1624 | |
1625 | if (run_daemon) |
1626 | manager->priv->mousetweaks_daemon_running = TRUE(!(0)); |
1627 | |
1628 | |
1629 | if (! g_spawn_command_line_async (comm, &error)) { |
1630 | if (error->code == G_SPAWN_ERROR_NOENT && |
1631 | (dwell_enable || delay_enable)) { |
1632 | CtkWidget *dialog; |
1633 | |
1634 | GSettings *settings; |
1635 | settings = g_settings_new (CAFE_MOUSE_A11Y_SCHEMA); |
1636 | if (dwell_enable) |
1637 | g_settings_set_boolean (settings, |
1638 | CAFE_MOUSE_A11Y_KEY_DWELL_ENABLE, |
1639 | FALSE(0)); |
1640 | else if (delay_enable) |
1641 | g_settings_set_boolean (settings, |
1642 | CAFE_MOUSE_A11Y_KEY_DELAY_ENABLE, |
1643 | FALSE(0)); |
1644 | g_object_unref (settings); |
1645 | |
1646 | dialog = ctk_message_dialog_new (NULL((void*)0), 0, |
1647 | CTK_MESSAGE_WARNING, |
1648 | CTK_BUTTONS_OK, |
1649 | _("Could not enable mouse accessibility features")gettext ("Could not enable mouse accessibility features")); |
1650 | ctk_message_dialog_format_secondary_text (CTK_MESSAGE_DIALOG (dialog)((((CtkMessageDialog*) (void *) g_type_check_instance_cast (( GTypeInstance*) ((dialog)), ((ctk_message_dialog_get_type ()) ))))), |
1651 | _("Mouse accessibility requires Mousetweaks "gettext ("Mouse accessibility requires Mousetweaks " "to be installed on your system." ) |
1652 | "to be installed on your system.")gettext ("Mouse accessibility requires Mousetweaks " "to be installed on your system." )); |
1653 | ctk_window_set_title (CTK_WINDOW (dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((dialog)), ((ctk_window_get_type ())))))), |
1654 | _("Mouse Preferences")gettext ("Mouse Preferences")); |
1655 | ctk_window_set_icon_name (CTK_WINDOW (dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((dialog)), ((ctk_window_get_type ())))))), |
1656 | "input-mouse"); |
1657 | ctk_dialog_run (CTK_DIALOG (dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((dialog)), ((ctk_dialog_get_type ()))))))); |
1658 | ctk_widget_destroy (dialog); |
1659 | } |
1660 | g_error_free (error); |
1661 | } |
1662 | g_free (comm); |
1663 | } |
1664 | #endif /* set_mousetweaks_daemon */ |
1665 | |
1666 | static void |
1667 | set_mouse_settings (CsdMouseManager *manager) |
1668 | { |
1669 | gboolean mouse_left_handed = g_settings_get_boolean (manager->priv->settings_mouse, KEY_LEFT_HANDED"left-handed"); |
1670 | gboolean touchpad_left_handed = get_touchpad_handedness (manager, mouse_left_handed); |
1671 | set_left_handed_all (manager, mouse_left_handed, touchpad_left_handed); |
1672 | |
1673 | set_motion_all (manager); |
1674 | set_middle_button_all (g_settings_get_boolean (manager->priv->settings_mouse, KEY_MIDDLE_BUTTON_EMULATION"middle-button-enabled")); |
1675 | |
1676 | set_disable_w_typing (manager, g_settings_get_boolean (manager->priv->settings_touchpad, KEY_TOUCHPAD_DISABLE_W_TYPING"disable-while-typing")); |
1677 | |
1678 | set_tap_to_click_all (manager); |
1679 | set_click_actions_all (manager); |
1680 | set_scrolling_all (manager->priv->settings_touchpad); |
1681 | set_natural_scroll_all (manager); |
1682 | set_touchpad_enabled_all (g_settings_get_boolean (manager->priv->settings_touchpad, KEY_TOUCHPAD_ENABLED"touchpad-enabled")); |
1683 | set_accel_profile_all (manager); |
1684 | } |
1685 | |
1686 | static void |
1687 | mouse_callback (GSettings *settings, |
1688 | const gchar *key, |
1689 | CsdMouseManager *manager) |
1690 | { |
1691 | if (g_strcmp0 (key, KEY_LEFT_HANDED"left-handed") == 0) { |
1692 | gboolean mouse_left_handed = g_settings_get_boolean (settings, key); |
1693 | gboolean touchpad_left_handed = get_touchpad_handedness (manager, mouse_left_handed); |
1694 | set_left_handed_all (manager, mouse_left_handed, touchpad_left_handed); |
1695 | } else if ((g_strcmp0 (key, KEY_MOTION_ACCELERATION"motion-acceleration") == 0) |
1696 | || (g_strcmp0 (key, KEY_MOTION_THRESHOLD"motion-threshold") == 0)) { |
1697 | set_motion_all (manager); |
1698 | } else if (g_strcmp0 (key, KEY_ACCEL_PROFILE"accel-profile") == 0) { |
1699 | set_accel_profile_all (manager); |
1700 | } else if (g_strcmp0 (key, KEY_MIDDLE_BUTTON_EMULATION"middle-button-enabled") == 0) { |
1701 | set_middle_button_all (g_settings_get_boolean (settings, key)); |
1702 | } else if (g_strcmp0 (key, KEY_MOUSE_LOCATE_POINTER"locate-pointer") == 0) { |
1703 | set_locate_pointer (manager, g_settings_get_boolean (settings, key)); |
1704 | #if 0 /* FIXME need to fork (?) mousetweaks for this to work */ |
1705 | } else if (g_strcmp0 (key, KEY_MOUSE_A11Y_DWELL_ENABLE) == 0) { |
1706 | set_mousetweaks_daemon (manager, |
1707 | g_settings_get_boolean (settings, key), |
1708 | g_settings_get_boolean (settings, KEY_MOUSE_A11Y_DELAY_ENABLE, NULL((void*)0))); |
1709 | } |
1710 | } else if (g_strcmp0 (key, KEY_MOUSE_A11Y_DELAY_ENABLE) == 0) { |
1711 | set_mousetweaks_daemon (manager, |
1712 | g_settings_get_boolean (settings, KEY_MOUSE_A11Y_DWELL_ENABLE, NULL((void*)0)), |
1713 | g_settings_get_boolean (settings, key)); |
1714 | #endif |
1715 | } |
1716 | } |
1717 | |
1718 | static void |
1719 | touchpad_callback (GSettings *settings, |
1720 | const gchar *key, |
1721 | CsdMouseManager *manager) |
1722 | { |
1723 | if (g_strcmp0 (key, KEY_TOUCHPAD_DISABLE_W_TYPING"disable-while-typing") == 0) { |
1724 | set_disable_w_typing (manager, g_settings_get_boolean (settings, key)); |
1725 | } else if (g_strcmp0 (key, KEY_LEFT_HANDED"left-handed") == 0) { |
1726 | gboolean mouse_left_handed = g_settings_get_boolean (manager->priv->settings_mouse, key); |
1727 | gboolean touchpad_left_handed = get_touchpad_handedness (manager, mouse_left_handed); |
1728 | set_left_handed_all (manager, mouse_left_handed, touchpad_left_handed); |
1729 | } else if ((g_strcmp0 (key, KEY_TOUCHPAD_TAP_TO_CLICK"tap-to-click") == 0) |
1730 | || (g_strcmp0 (key, KEY_TOUCHPAD_ONE_FINGER_TAP"tap-button-one-finger") == 0) |
1731 | || (g_strcmp0 (key, KEY_TOUCHPAD_TWO_FINGER_TAP"tap-button-two-finger") == 0) |
1732 | || (g_strcmp0 (key, KEY_TOUCHPAD_THREE_FINGER_TAP"tap-button-three-finger") == 0)) { |
1733 | set_tap_to_click_all (manager); |
1734 | } else if ((g_strcmp0 (key, KEY_TOUCHPAD_TWO_FINGER_CLICK"two-finger-click") == 0) |
1735 | || (g_strcmp0 (key, KEY_TOUCHPAD_THREE_FINGER_CLICK"three-finger-click") == 0)) { |
1736 | set_click_actions_all (manager); |
1737 | } else if ((g_strcmp0 (key, KEY_VERT_EDGE_SCROLL"vertical-edge-scrolling") == 0) |
1738 | || (g_strcmp0 (key, KEY_HORIZ_EDGE_SCROLL"horizontal-edge-scrolling") == 0) |
1739 | || (g_strcmp0 (key, KEY_VERT_TWO_FINGER_SCROLL"vertical-two-finger-scrolling") == 0) |
1740 | || (g_strcmp0 (key, KEY_HORIZ_TWO_FINGER_SCROLL"horizontal-two-finger-scrolling") == 0)) { |
1741 | set_scrolling_all (manager->priv->settings_touchpad); |
1742 | } else if (g_strcmp0 (key, KEY_TOUCHPAD_NATURAL_SCROLL"natural-scroll") == 0) { |
1743 | set_natural_scroll_all (manager); |
1744 | } else if (g_strcmp0 (key, KEY_TOUCHPAD_ENABLED"touchpad-enabled") == 0) { |
1745 | set_touchpad_enabled_all (g_settings_get_boolean (settings, key)); |
1746 | } else if ((g_strcmp0 (key, KEY_MOTION_ACCELERATION"motion-acceleration") == 0) |
1747 | || (g_strcmp0 (key, KEY_MOTION_THRESHOLD"motion-threshold") == 0)) { |
1748 | set_motion_all (manager); |
1749 | } else if (g_strcmp0 (key, KEY_ACCEL_PROFILE"accel-profile") == 0) { |
1750 | set_accel_profile_all (manager); |
1751 | } |
1752 | } |
1753 | |
1754 | static void |
1755 | csd_mouse_manager_init (CsdMouseManager *manager) |
1756 | { |
1757 | manager->priv = csd_mouse_manager_get_instance_private (manager); |
1758 | } |
1759 | |
1760 | static gboolean |
1761 | csd_mouse_manager_idle_cb (CsdMouseManager *manager) |
1762 | { |
1763 | cafe_settings_profile_start (NULL); |
1764 | |
1765 | manager->priv->settings_mouse = g_settings_new (CAFE_MOUSE_SCHEMA"org.cafe.peripherals-mouse"); |
1766 | manager->priv->settings_touchpad = g_settings_new (CAFE_TOUCHPAD_SCHEMA"org.cafe.peripherals-touchpad"); |
1767 | |
1768 | g_signal_connect (manager->priv->settings_mouse, "changed",g_signal_connect_data ((manager->priv->settings_mouse), ("changed"), (((GCallback) (mouse_callback))), (manager), (( void*)0), (GConnectFlags) 0) |
1769 | G_CALLBACK (mouse_callback), manager)g_signal_connect_data ((manager->priv->settings_mouse), ("changed"), (((GCallback) (mouse_callback))), (manager), (( void*)0), (GConnectFlags) 0); |
1770 | g_signal_connect (manager->priv->settings_touchpad, "changed",g_signal_connect_data ((manager->priv->settings_touchpad ), ("changed"), (((GCallback) (touchpad_callback))), (manager ), ((void*)0), (GConnectFlags) 0) |
1771 | G_CALLBACK (touchpad_callback), manager)g_signal_connect_data ((manager->priv->settings_touchpad ), ("changed"), (((GCallback) (touchpad_callback))), (manager ), ((void*)0), (GConnectFlags) 0); |
1772 | |
1773 | manager->priv->syndaemon_spawned = FALSE(0); |
1774 | |
1775 | set_devicepresence_handler (manager); |
1776 | |
1777 | set_mouse_settings (manager); |
1778 | set_locate_pointer (manager, g_settings_get_boolean (manager->priv->settings_mouse, KEY_MOUSE_LOCATE_POINTER"locate-pointer")); |
1779 | |
1780 | #if 0 /* FIXME need to fork (?) mousetweaks for this to work */ |
1781 | set_mousetweaks_daemon (manager, |
1782 | g_settings_get_boolean (manager->priv->settings_mouse_a11y, |
1783 | KEY_MOUSE_A11Y_DWELL_ENABLE), |
1784 | g_settings_get_boolean (manager->priv->settings_mouse_a11y, |
1785 | KEY_MOUSE_A11Y_DELAY_ENABLE)); |
1786 | #endif |
1787 | |
1788 | cafe_settings_profile_end (NULL); |
1789 | |
1790 | return FALSE(0); |
1791 | } |
1792 | |
1793 | gboolean |
1794 | csd_mouse_manager_start (CsdMouseManager *manager, |
1795 | GError **error G_GNUC_UNUSED__attribute__ ((__unused__))) |
1796 | { |
1797 | cafe_settings_profile_start (NULL); |
1798 | |
1799 | if (!supports_xinput_devices ()) { |
1800 | g_debug ("XInput is not supported, not applying any settings"); |
1801 | return TRUE(!(0)); |
1802 | } |
1803 | |
1804 | g_idle_add ((GSourceFunc) csd_mouse_manager_idle_cb, manager); |
1805 | |
1806 | cafe_settings_profile_end (NULL); |
1807 | |
1808 | return TRUE(!(0)); |
1809 | } |
1810 | |
1811 | void |
1812 | csd_mouse_manager_stop (CsdMouseManager *manager) |
1813 | { |
1814 | CsdMouseManagerPrivate *p = manager->priv; |
1815 | |
1816 | g_debug ("Stopping mouse manager"); |
1817 | |
1818 | if (p->settings_mouse != NULL((void*)0)) { |
1819 | g_object_unref(p->settings_mouse); |
1820 | p->settings_mouse = NULL((void*)0); |
1821 | } |
1822 | |
1823 | if (p->settings_touchpad != NULL((void*)0)) { |
1824 | g_object_unref(p->settings_touchpad); |
1825 | p->settings_touchpad = NULL((void*)0); |
1826 | } |
1827 | |
1828 | set_locate_pointer (manager, FALSE(0)); |
1829 | |
1830 | cdk_window_remove_filter (NULL((void*)0), devicepresence_filter, manager); |
1831 | } |
1832 | |
1833 | static void |
1834 | csd_mouse_manager_finalize (GObject *object) |
1835 | { |
1836 | CsdMouseManager *mouse_manager; |
1837 | |
1838 | g_return_if_fail (object != NULL)do { if ((object != ((void*)0))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "object != NULL") ; return; } } while (0); |
1839 | g_return_if_fail (CSD_IS_MOUSE_MANAGER (object))do { if (((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance *) ((object)); GType __t = ((csd_mouse_manager_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0) ); else __r = g_type_check_instance_is_a (__inst, __t); __r; } )))))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "CSD_IS_MOUSE_MANAGER (object)"); return ; } } while (0); |
1840 | |
1841 | mouse_manager = CSD_MOUSE_MANAGER (object)((((CsdMouseManager*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((object)), ((csd_mouse_manager_get_type ())))))); |
1842 | |
1843 | g_return_if_fail (mouse_manager->priv != NULL)do { if ((mouse_manager->priv != ((void*)0))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "mouse_manager->priv != NULL" ); return; } } while (0); |
1844 | |
1845 | G_OBJECT_CLASS (csd_mouse_manager_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((csd_mouse_manager_parent_class)), (((GType) ((20) << (2))))))))->finalize (object); |
1846 | } |
1847 | |
1848 | CsdMouseManager * |
1849 | csd_mouse_manager_new (void) |
1850 | { |
1851 | if (manager_object != NULL((void*)0)) { |
1852 | g_object_ref (manager_object)((__typeof__ (manager_object)) (g_object_ref) (manager_object )); |
1853 | } else { |
1854 | manager_object = g_object_new (CSD_TYPE_MOUSE_MANAGER(csd_mouse_manager_get_type ()), NULL((void*)0)); |
1855 | g_object_add_weak_pointer (manager_object, |
1856 | (gpointer *) &manager_object); |
1857 | } |
1858 | |
1859 | return CSD_MOUSE_MANAGER (manager_object)((((CsdMouseManager*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((manager_object)), ((csd_mouse_manager_get_type ())))))); |
1860 | } |