Changeset View
Changeset View
Standalone View
Standalone View
kcms/touchpadx/src/backends/x11/xlibnotifications.cpp
- This file was added.
1 | /* | ||||
---|---|---|---|---|---|
2 | * Copyright (C) 2013 Alexander Mezin <mezin.alexander@gmail.com> | ||||
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 Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||||
17 | */ | ||||
18 | | ||||
19 | #include "xlibnotifications.h" | ||||
20 | | ||||
21 | #include <cstring> | ||||
22 | | ||||
23 | #include <X11/Xlib.h> | ||||
24 | #include <X11/Xlib-xcb.h> | ||||
25 | #include <X11/extensions/XI.h> | ||||
26 | #include <X11/extensions/XI2proto.h> | ||||
27 | #include <X11/extensions/XInput2.h> | ||||
28 | | ||||
29 | XlibNotifications::XlibNotifications(Display *display, int device) | ||||
30 | : m_display(display), m_device(device) | ||||
31 | { | ||||
32 | m_connection = XGetXCBConnection(display); | ||||
33 | | ||||
34 | m_notifier = new QSocketNotifier(xcb_get_file_descriptor(m_connection), | ||||
35 | QSocketNotifier::Read, this); | ||||
36 | | ||||
37 | xcb_query_extension_cookie_t inputExtCookie = | ||||
38 | xcb_query_extension(m_connection, std::strlen(INAME), INAME); | ||||
39 | QScopedPointer<xcb_query_extension_reply_t, QScopedPointerPodDeleter> | ||||
40 | inputExt(xcb_query_extension_reply(m_connection, inputExtCookie, 0)); | ||||
41 | if (!inputExt) { | ||||
42 | return; | ||||
43 | } | ||||
44 | m_inputOpcode = inputExt->major_opcode; | ||||
45 | | ||||
46 | const xcb_setup_t *setup = xcb_get_setup(m_connection); | ||||
47 | xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup); | ||||
48 | xcb_screen_t *screen = iter.data; | ||||
49 | | ||||
50 | m_inputWindow = xcb_generate_id(m_connection); | ||||
51 | xcb_create_window(m_connection, 0, m_inputWindow, screen->root, 0, 0, 1, 1, | ||||
52 | 0, XCB_WINDOW_CLASS_INPUT_ONLY, 0, 0, 0); | ||||
53 | xcb_flush(m_connection); | ||||
54 | | ||||
55 | XIEventMask masks[2]; | ||||
56 | | ||||
57 | unsigned char touchpadMask[] = { 0, 0, 0, 0 }; | ||||
58 | masks[0].deviceid = device; | ||||
59 | masks[0].mask = touchpadMask; | ||||
60 | masks[0].mask_len = sizeof(touchpadMask); | ||||
61 | XISetMask(touchpadMask, XI_PropertyEvent); | ||||
62 | | ||||
63 | unsigned char allMask[] = { 0, 0, 0, 0 }; | ||||
64 | masks[1].deviceid = XIAllDevices; | ||||
65 | masks[1].mask = allMask; | ||||
66 | masks[1].mask_len = sizeof(allMask); | ||||
67 | XISetMask(allMask, XI_HierarchyChanged); | ||||
68 | | ||||
69 | XISelectEvents(display, XDefaultRootWindow(display), masks, | ||||
70 | sizeof(masks) / sizeof(XIEventMask)); | ||||
71 | XFlush(display); | ||||
72 | | ||||
73 | connect(m_notifier, SIGNAL(activated(int)), SLOT(processEvents())); | ||||
74 | m_notifier->setEnabled(true); | ||||
75 | } | ||||
76 | | ||||
77 | void XlibNotifications::processEvents() | ||||
78 | { | ||||
79 | while (XPending(m_display)) { | ||||
80 | XEvent event; | ||||
81 | XNextEvent(m_display, &event); | ||||
82 | processEvent(&event); | ||||
83 | } | ||||
84 | } | ||||
85 | | ||||
86 | struct XEventDataDeleter | ||||
87 | { | ||||
88 | XEventDataDeleter(Display *display, XGenericEventCookie *cookie) | ||||
89 | : m_display(display), m_cookie(cookie) | ||||
90 | { | ||||
91 | XGetEventData(m_display, m_cookie); | ||||
92 | } | ||||
93 | | ||||
94 | ~XEventDataDeleter() | ||||
95 | { | ||||
96 | if (m_cookie->data) { | ||||
97 | XFreeEventData(m_display, m_cookie); | ||||
98 | } | ||||
99 | } | ||||
100 | | ||||
101 | Display *m_display; | ||||
102 | XGenericEventCookie *m_cookie; | ||||
103 | }; | ||||
104 | | ||||
105 | void XlibNotifications::processEvent(XEvent *event) | ||||
106 | { | ||||
107 | if (event->xcookie.type != GenericEvent) { | ||||
108 | return; | ||||
109 | } | ||||
110 | if (event->xcookie.extension != m_inputOpcode) { | ||||
111 | return; | ||||
112 | } | ||||
113 | | ||||
114 | if (event->xcookie.evtype == XI_PropertyEvent) { | ||||
115 | XEventDataDeleter helper(m_display, &event->xcookie); | ||||
116 | if (!event->xcookie.data) { | ||||
117 | return; | ||||
118 | } | ||||
119 | | ||||
120 | XIPropertyEvent *propEvent = | ||||
121 | reinterpret_cast<XIPropertyEvent *>(event->xcookie.data); | ||||
122 | Q_EMIT propertyChanged(propEvent->property); | ||||
123 | } else if (event->xcookie.evtype == XI_HierarchyChanged) { | ||||
124 | XEventDataDeleter helper(m_display, &event->xcookie); | ||||
125 | if (!event->xcookie.data) { | ||||
126 | return; | ||||
127 | } | ||||
128 | | ||||
129 | XIHierarchyEvent *hierarchyEvent = | ||||
130 | reinterpret_cast<XIHierarchyEvent *>(event->xcookie.data); | ||||
131 | for (uint16_t i = 0; i < hierarchyEvent->num_info; i++) { | ||||
132 | if (hierarchyEvent->info[i].deviceid == m_device) { | ||||
133 | if (hierarchyEvent->info[i].flags & XISlaveRemoved) { | ||||
134 | Q_EMIT touchpadDetached(); | ||||
135 | return; | ||||
136 | } | ||||
137 | } | ||||
138 | if (hierarchyEvent->info[i].use != XISlavePointer) { | ||||
139 | continue; | ||||
140 | } | ||||
141 | if (hierarchyEvent->info[i].flags & | ||||
142 | (XIDeviceEnabled | XIDeviceDisabled)) | ||||
143 | { | ||||
144 | Q_EMIT devicePlugged(hierarchyEvent->info[i].deviceid); | ||||
145 | } | ||||
146 | } | ||||
147 | } | ||||
148 | } | ||||
149 | | ||||
150 | XlibNotifications::~XlibNotifications() | ||||
151 | { | ||||
152 | xcb_destroy_window(m_connection, m_inputWindow); | ||||
153 | xcb_flush(m_connection); | ||||
154 | } | ||||
155 | | ||||
156 | #include "moc_xlibnotifications.cpp" |