Bug Summary

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

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 -fcoverage-compilation-dir=/rootdir/plugins/mouse -resource-dir /usr/lib/llvm-16/lib/clang/16 -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/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-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/plugins/mouse -ferror-limit 19 -fgnuc-version=4.2.1 -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.core.SizeofPtr -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/2024-01-21-115953-65501-1 -x c csd_mouse-manager.c
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
85struct 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
99typedef enum {
100 TOUCHPAD_HANDEDNESS_RIGHT,
101 TOUCHPAD_HANDEDNESS_LEFT,
102 TOUCHPAD_HANDEDNESS_MOUSE
103} TouchpadHandedness;
104
105typedef enum {
106 ACCEL_PROFILE_DEFAULT,
107 ACCEL_PROFILE_ADAPTIVE,
108 ACCEL_PROFILE_FLAT
109} AccelProfile;
110
111static void csd_mouse_manager_finalize (GObject *object);
112static void set_mouse_settings (CsdMouseManager *manager);
113static 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
121G_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
123static gpointer manager_object = NULL((void*)0);
124
125static void
126csd_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
133static void
134configure_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
190static gboolean
191xinput_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
212static Atom
213property_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
218static void *
219get_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
254static void
255change_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
287static gboolean
288touchpad_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
318static gboolean
319property_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
355static void
356property_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
396static void
397touchpad_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
419static void
420set_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
495static void
496set_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
529static void
530set_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
541static void
542set_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
560static CdkFilterReturn
561devicepresence_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
581static void
582set_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
603static void
604set_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
696static void
697set_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
775static void
776set_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
785static void
786set_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
802static void
803set_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
848static void
849set_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
880static void
881set_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
891static void
892set_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
908static gboolean
909have_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
920static void
921set_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
960static void
961set_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
981static void
982set_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
992static void
993set_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
1056static void
1057set_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
1066static void
1067set_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
1082static gboolean
1083get_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
1098static void
1099set_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
1156static void
1157set_tap_to_click_libinput (XDeviceInfo *device_info,
1158 gboolean state)
1159{
1160 touchpad_set_bool (device_info, "libinput Tapping Enabled", 0, state);
1161}
1162
1163static void
1164set_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
1179static void
1180set_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
1201static void
1202set_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
1248static void
1249set_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
1299static void
1300set_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
1311static void
1312set_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
1330static void
1331set_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
1383static void
1384set_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
1392static void
1393set_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
1403static void
1404set_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
1421static void
1422set_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
1431static void
1432set_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
1500static void
1501set_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
1511static void
1512set_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
1527static void
1528set_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
1561static void
1562set_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
1577static void
1578set_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 */
1611static void
1612set_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
1667static void
1668set_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
1687static void
1688mouse_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
1719static void
1720touchpad_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
1755static void
1756csd_mouse_manager_init (CsdMouseManager *manager)
1757{
1758 manager->priv = csd_mouse_manager_get_instance_private (manager);
1759}
1760
1761static gboolean
1762csd_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
1794gboolean
1795csd_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
1812void
1813csd_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
1834static void
1835csd_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
1849CsdMouseManager *
1850csd_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}