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