Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name csd_mouse-manager.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/plugins/mouse -fcoverage-compilation-dir=/rootdir/plugins/mouse -resource-dir /usr/lib/llvm-19/lib/clang/19 -D HAVE_CONFIG_H -I . -I ../.. -I ../../cafe-settings-daemon -I ../../plugins/common/ -D CAFE_SETTINGS_LOCALEDIR="/usr/share/locale" -D LIBEXECDIR="/usr/libexec" -I /usr/include/ctk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -D PIC -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2025-10-08-073341-64186-1 -x c csd_mouse-manager.c
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
84struct 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
98typedef enum {
99 TOUCHPAD_HANDEDNESS_RIGHT,
100 TOUCHPAD_HANDEDNESS_LEFT,
101 TOUCHPAD_HANDEDNESS_MOUSE
102} TouchpadHandedness;
103
104typedef enum {
105 ACCEL_PROFILE_DEFAULT,
106 ACCEL_PROFILE_ADAPTIVE,
107 ACCEL_PROFILE_FLAT
108} AccelProfile;
109
110static void csd_mouse_manager_finalize (GObject *object);
111static void set_mouse_settings (CsdMouseManager *manager);
112static 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
120G_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
122static gpointer manager_object = NULL((void*)0);
123
124static void
125csd_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
132static void
133configure_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
189static gboolean
190xinput_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
211static Atom
212property_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
217static void *
218get_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
253static void
254change_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
286static gboolean
287touchpad_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
317static gboolean
318property_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
354static void
355property_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
395static void
396touchpad_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
418static void
419set_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
494static void
495set_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
528static void
529set_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
540static void
541set_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
559static CdkFilterReturn
560devicepresence_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
580static void
581set_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
602static void
603set_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
695static void
696set_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
774static void
775set_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
784static void
785set_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
801static void
802set_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
847static void
848set_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
879static void
880set_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
890static void
891set_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
907static gboolean
908have_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
919static void
920set_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
959static void
960set_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
980static void
981set_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
991static void
992set_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
1055static void
1056set_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
1065static void
1066set_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
1081static gboolean
1082get_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
1097static void
1098set_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
1155static void
1156set_tap_to_click_libinput (XDeviceInfo *device_info,
1157 gboolean state)
1158{
1159 touchpad_set_bool (device_info, "libinput Tapping Enabled", 0, state);
1160}
1161
1162static void
1163set_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
1178static void
1179set_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
1200static void
1201set_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
1247static void
1248set_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
1298static void
1299set_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
1310static void
1311set_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
1329static void
1330set_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
1382static void
1383set_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
1391static void
1392set_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
1402static void
1403set_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
1420static void
1421set_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
1430static void
1431set_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
1499static void
1500set_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
1510static void
1511set_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
1526static void
1527set_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
1560static void
1561set_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
1576static void
1577set_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 */
1610static void
1611set_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
1666static void
1667set_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
1686static void
1687mouse_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
1718static void
1719touchpad_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
1754static void
1755csd_mouse_manager_init (CsdMouseManager *manager)
1756{
1757 manager->priv = csd_mouse_manager_get_instance_private (manager);
1758}
1759
1760static gboolean
1761csd_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
1793gboolean
1794csd_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
1811void
1812csd_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
1833static void
1834csd_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
1848CsdMouseManager *
1849csd_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}