Line |
Branch |
Exec |
Source |
1 |
|
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- |
2 |
|
|
* |
3 |
|
|
* Copyright 2015 Red Hat, Inc, |
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, see <http://www.gnu.org/licenses/>. |
17 |
|
|
* |
18 |
|
|
* Author: Felipe Borges <feborges@redhat.com> |
19 |
|
|
*/ |
20 |
|
|
|
21 |
|
|
#include <gdk/x11/gdkx.h> |
22 |
|
|
#include <X11/Xatom.h> |
23 |
|
|
#include <X11/extensions/XInput2.h> |
24 |
|
|
|
25 |
|
|
#include "cc-mouse-caps-helper.h" |
26 |
|
|
|
27 |
|
|
static gboolean |
28 |
|
✗ |
touchpad_check_capabilities_x11 (gboolean *have_two_finger_scrolling, |
29 |
|
|
gboolean *have_edge_scrolling, |
30 |
|
|
gboolean *have_tap_to_click) |
31 |
|
|
{ |
32 |
|
|
GdkDisplay *gdisplay; |
33 |
|
|
Display *display; |
34 |
|
✗ |
g_autoptr(GList) devicelist = NULL; |
35 |
|
|
GList *l; |
36 |
|
|
Atom realtype, prop_scroll_methods, prop_tapping_enabled; |
37 |
|
|
int realformat; |
38 |
|
|
unsigned long nitems, bytes_after; |
39 |
|
|
unsigned char *data; |
40 |
|
|
|
41 |
|
✗ |
gdisplay = gdk_display_get_default (); |
42 |
|
✗ |
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); |
43 |
|
✗ |
prop_scroll_methods = XInternAtom (display, "libinput Scroll Methods Available", False); |
44 |
|
✗ |
prop_tapping_enabled = XInternAtom (display, "libinput Tapping Enabled", False); |
45 |
|
✗ |
if (!prop_scroll_methods || !prop_tapping_enabled) |
46 |
|
✗ |
return FALSE; |
47 |
|
|
|
48 |
|
✗ |
*have_two_finger_scrolling = FALSE; |
49 |
|
✗ |
*have_edge_scrolling = FALSE; |
50 |
|
✗ |
*have_tap_to_click = FALSE; |
51 |
|
|
|
52 |
|
✗ |
gdk_x11_display_error_trap_push (gdisplay); |
53 |
|
|
|
54 |
|
✗ |
devicelist = gdk_seat_get_devices (gdk_display_get_default_seat (gdk_display_get_default ()), |
55 |
|
|
GDK_SEAT_CAPABILITY_ALL_POINTING); |
56 |
|
✗ |
for (l = devicelist; l != NULL; l = l->next) { |
57 |
|
✗ |
GdkDevice *device = l->data; |
58 |
|
✗ |
if (gdk_device_get_source (device) != GDK_SOURCE_TOUCHPAD) |
59 |
|
✗ |
continue; |
60 |
|
|
|
61 |
|
|
/* xorg-x11-drv-libinput */ |
62 |
|
✗ |
if ((XIGetProperty (display, gdk_x11_device_get_id (device), prop_scroll_methods, |
63 |
|
|
0, 2, False, XA_INTEGER, &realtype, &realformat, &nitems, |
64 |
|
✗ |
&bytes_after, &data) == Success) && (realtype != None)) { |
65 |
|
|
/* Property data is booleans for two-finger, edge, on-button scroll available. */ |
66 |
|
|
|
67 |
|
✗ |
if (data[0]) |
68 |
|
✗ |
*have_two_finger_scrolling = TRUE; |
69 |
|
|
|
70 |
|
✗ |
if (data[1]) |
71 |
|
✗ |
*have_edge_scrolling = TRUE; |
72 |
|
|
|
73 |
|
✗ |
XFree (data); |
74 |
|
|
} |
75 |
|
|
|
76 |
|
✗ |
if ((XIGetProperty (display, gdk_x11_device_get_id (device), prop_tapping_enabled, |
77 |
|
|
0, 1, False, XA_INTEGER, &realtype, &realformat, &nitems, |
78 |
|
✗ |
&bytes_after, &data) == Success) && (realtype != None)) { |
79 |
|
|
/* Property data is boolean for tapping enabled. */ |
80 |
|
✗ |
*have_tap_to_click = TRUE; |
81 |
|
|
|
82 |
|
✗ |
XFree (data); |
83 |
|
|
} |
84 |
|
|
} |
85 |
|
|
|
86 |
|
✗ |
gdk_x11_display_error_trap_pop_ignored (gdisplay); |
87 |
|
|
|
88 |
|
✗ |
return TRUE; |
89 |
|
|
} |
90 |
|
|
|
91 |
|
|
gboolean |
92 |
|
✗ |
cc_touchpad_check_capabilities (gboolean *have_two_finger_scrolling, |
93 |
|
|
gboolean *have_edge_scrolling, |
94 |
|
|
gboolean *have_tap_to_click) |
95 |
|
|
{ |
96 |
|
✗ |
if (GDK_IS_X11_DISPLAY (gdk_display_get_default ())) |
97 |
|
✗ |
return touchpad_check_capabilities_x11 (have_two_finger_scrolling, |
98 |
|
|
have_edge_scrolling, |
99 |
|
|
have_tap_to_click); |
100 |
|
|
/* else we unconditionally show all touchpad knobs */ |
101 |
|
✗ |
*have_two_finger_scrolling = TRUE; |
102 |
|
✗ |
*have_edge_scrolling = TRUE; |
103 |
|
✗ |
*have_tap_to_click = TRUE; |
104 |
|
✗ |
return FALSE; |
105 |
|
|
} |
106 |
|
|
|
107 |
|
|
gboolean |
108 |
|
✗ |
cc_synaptics_check (void) |
109 |
|
|
{ |
110 |
|
|
GdkDisplay *gdisplay; |
111 |
|
|
Display *display; |
112 |
|
✗ |
g_autoptr(GList) devicelist = NULL; |
113 |
|
|
GList *l; |
114 |
|
|
Atom prop, realtype; |
115 |
|
|
int realformat; |
116 |
|
|
unsigned long nitems, bytes_after; |
117 |
|
|
unsigned char *data; |
118 |
|
✗ |
gboolean have_synaptics = FALSE; |
119 |
|
|
|
120 |
|
✗ |
if (!GDK_IS_X11_DISPLAY (gdk_display_get_default ())) |
121 |
|
✗ |
return FALSE; |
122 |
|
|
|
123 |
|
✗ |
gdisplay = gdk_display_get_default (); |
124 |
|
✗ |
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); |
125 |
|
✗ |
prop = XInternAtom (display, "Synaptics Capabilities", False); |
126 |
|
|
|
127 |
|
✗ |
gdk_x11_display_error_trap_push (gdisplay); |
128 |
|
|
|
129 |
|
✗ |
devicelist = gdk_seat_get_devices (gdk_display_get_default_seat (gdk_display_get_default ()), |
130 |
|
|
GDK_SEAT_CAPABILITY_ALL_POINTING); |
131 |
|
✗ |
for (l = devicelist; l != NULL; l = l->next) { |
132 |
|
✗ |
GdkDevice *device = l->data; |
133 |
|
|
|
134 |
|
✗ |
if ((XIGetProperty (display, gdk_x11_device_get_id (device), prop, |
135 |
|
|
0, 2, False, XA_INTEGER, &realtype, &realformat, &nitems, |
136 |
|
✗ |
&bytes_after, &data) == Success) && (realtype != None)) { |
137 |
|
✗ |
have_synaptics = TRUE; |
138 |
|
✗ |
XFree (data); |
139 |
|
|
} |
140 |
|
|
|
141 |
|
✗ |
if (have_synaptics) |
142 |
|
✗ |
break; |
143 |
|
|
} |
144 |
|
|
|
145 |
|
✗ |
gdk_x11_display_error_trap_pop_ignored (gdisplay); |
146 |
|
|
|
147 |
|
✗ |
return have_synaptics; |
148 |
|
|
} |
149 |
|
|
|