]> diplodocus.org Git - xorg-xinput/blob - src/test_xi2.c
92c88dae11becde69c74875e8d48a1a5f0cfb27a
[xorg-xinput] / src / test_xi2.c
1 /*
2 * Copyright © 2009 Red Hat, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 */
24
25
26 #include "xinput.h"
27 #include <string.h>
28
29 extern void print_classes_xi2(Display*, XIAnyClassInfo **classes,
30 int num_classes);
31
32 static Window create_win(Display *dpy)
33 {
34 Window win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 200,
35 200, 0, 0, WhitePixel(dpy, 0));
36 Window subwindow = XCreateSimpleWindow(dpy, win, 50, 50, 50, 50, 0, 0,
37 BlackPixel(dpy, 0));
38
39 XMapWindow(dpy, subwindow);
40 XSelectInput(dpy, win, ExposureMask);
41 return win;
42 }
43
44 static void print_deviceevent(XIDeviceEvent* event)
45 {
46 double *val;
47 int i;
48
49 printf(" device: %d (%d)\n", event->deviceid, event->sourceid);
50 printf(" detail: %d\n", event->detail);
51 switch(event->evtype) {
52 case XI_KeyPress:
53 case XI_KeyRelease:
54 printf(" flags: %s\n", (event->flags & XIKeyRepeat) ? "repeat" : "");
55 break;
56 case XI_ButtonPress:
57 case XI_ButtonRelease:
58 case XI_Motion:
59 printf(" flags: %s\n", (event->flags & XIPointerEmulated) ? "emulated" : "");
60 break;
61 }
62
63 printf(" root: %.2f/%.2f\n", event->root_x, event->root_y);
64 printf(" event: %.2f/%.2f\n", event->event_x, event->event_y);
65
66 printf(" buttons:");
67 for (i = 0; i < event->buttons.mask_len * 8; i++)
68 if (XIMaskIsSet(event->buttons.mask, i))
69 printf(" %d", i);
70 printf("\n");
71
72 printf(" modifiers: locked %#x latched %#x base %#x effective: %#x\n",
73 event->mods.locked, event->mods.latched,
74 event->mods.base, event->mods.effective);
75 printf(" group: locked %#x latched %#x base %#x effective: %#x\n",
76 event->group.locked, event->group.latched,
77 event->group.base, event->group.effective);
78 printf(" valuators:\n");
79
80 val = event->valuators.values;
81 for (i = 0; i < event->valuators.mask_len * 8; i++)
82 if (XIMaskIsSet(event->valuators.mask, i))
83 printf(" %i: %.2f\n", i, *val++);
84
85 printf(" windows: root 0x%lx event 0x%lx child 0x%lx\n",
86 event->root, event->event, event->child);
87 }
88
89 static void print_devicechangedevent(Display *dpy, XIDeviceChangedEvent *event)
90 {
91 printf(" device: %d (%d)\n", event->deviceid, event->sourceid);
92 printf(" reason: %s\n", (event->reason == XISlaveSwitch) ? "SlaveSwitch" :
93 "DeviceChanged");
94 print_classes_xi2(dpy, event->classes, event->num_classes);
95 }
96
97 static void print_hierarchychangedevent(XIHierarchyEvent *event)
98 {
99 int i;
100 printf(" Changes happened: %s %s %s %s %s %s %s %s\n",
101 (event->flags & XIMasterAdded) ? "[new master]" : "",
102 (event->flags & XIMasterRemoved) ? "[master removed]" : "",
103 (event->flags & XISlaveAdded) ? "[new slave]" : "",
104 (event->flags & XISlaveRemoved) ? "[slave removed]" : "",
105 (event->flags & XISlaveAttached) ? "[slave attached]" : "",
106 (event->flags & XISlaveDetached) ? "[slave detached]" : "",
107 (event->flags & XIDeviceEnabled) ? "[device enabled]" : "",
108 (event->flags & XIDeviceDisabled) ? "[device disabled]" : "");
109
110 for (i = 0; i < event->num_info; i++)
111 {
112 char *use = "<undefined>";
113 switch(event->info[i].use)
114 {
115 case XIMasterPointer: use = "master pointer"; break;
116 case XIMasterKeyboard: use = "master keyboard"; break;
117 case XISlavePointer: use = "slave pointer"; break;
118 case XISlaveKeyboard: use = "slave keyboard"; break;
119 case XIFloatingSlave: use = "floating slave"; break;
120 break;
121 }
122
123 printf(" device %d [%s (%d)] is %s\n",
124 event->info[i].deviceid,
125 use,
126 event->info[i].attachment,
127 (event->info[i].enabled) ? "enabled" : "disabled");
128 if (event->info[i].flags)
129 {
130 printf(" changes: %s %s %s %s %s %s %s %s\n",
131 (event->info[i].flags & XIMasterAdded) ? "[new master]" : "",
132 (event->info[i].flags & XIMasterRemoved) ? "[master removed]" : "",
133 (event->info[i].flags & XISlaveAdded) ? "[new slave]" : "",
134 (event->info[i].flags & XISlaveRemoved) ? "[slave removed]" : "",
135 (event->info[i].flags & XISlaveAttached) ? "[slave attached]" : "",
136 (event->info[i].flags & XISlaveDetached) ? "[slave detached]" : "",
137 (event->info[i].flags & XIDeviceEnabled) ? "[device enabled]" : "",
138 (event->info[i].flags & XIDeviceDisabled) ? "[device disabled]" : "");
139 }
140 }
141 }
142
143 static void print_rawevent(XIRawEvent *event)
144 {
145 int i;
146 double *val, *raw_val;
147
148 printf(" device: %d\n", event->deviceid);
149 printf(" detail: %d\n", event->detail);
150 printf(" valuators:\n");
151
152 val = event->valuators.values;
153 raw_val = event->raw_values;
154 for (i = 0; i < event->valuators.mask_len * 8; i++)
155 if (XIMaskIsSet(event->valuators.mask, i))
156 printf(" %2d: %.2f (%.2f)\n", i, *val++, *raw_val++);
157 printf("\n");
158 }
159
160 static void print_enterleave(XILeaveEvent* event)
161 {
162 char *mode = "<undefined>",
163 *detail = "<undefined>";
164 int i;
165
166 printf(" device: %d (%d)\n", event->deviceid, event->sourceid);
167 printf(" windows: root 0x%lx event 0x%lx child 0x%ld\n",
168 event->root, event->event, event->child);
169 switch(event->mode)
170 {
171 case XINotifyNormal: mode = "NotifyNormal"; break;
172 case XINotifyGrab: mode = "NotifyGrab"; break;
173 case XINotifyUngrab: mode = "NotifyUngrab"; break;
174 case XINotifyWhileGrabbed: mode = "NotifyWhileGrabbed"; break;
175 case XINotifyPassiveGrab: mode = "NotifyPassiveGrab"; break;
176 case XINotifyPassiveUngrab:mode = "NotifyPassiveUngrab"; break;
177 }
178 switch (event->detail)
179 {
180 case XINotifyAncestor: detail = "NotifyAncestor"; break;
181 case XINotifyVirtual: detail = "NotifyVirtual"; break;
182 case XINotifyInferior: detail = "NotifyInferior"; break;
183 case XINotifyNonlinear: detail = "NotifyNonlinear"; break;
184 case XINotifyNonlinearVirtual: detail = "NotifyNonlinearVirtual"; break;
185 case XINotifyPointer: detail = "NotifyPointer"; break;
186 case XINotifyPointerRoot: detail = "NotifyPointerRoot"; break;
187 case XINotifyDetailNone: detail = "NotifyDetailNone"; break;
188 }
189 printf(" mode: %s (detail %s)\n", mode, detail);
190 printf(" flags: %s %s\n", event->focus ? "[focus]" : "",
191 event->same_screen ? "[same screen]" : "");
192 printf(" buttons:");
193 for (i = 0; i < event->buttons.mask_len * 8; i++)
194 if (XIMaskIsSet(event->buttons.mask, i))
195 printf(" %d", i);
196 printf("\n");
197
198 printf(" modifiers: locked %#x latched %#x base %#x effective: %#x\n",
199 event->mods.locked, event->mods.latched,
200 event->mods.base, event->mods.effective);
201 printf(" group: locked %#x latched %#x base %#x effective: %#x\n",
202 event->group.locked, event->group.latched,
203 event->group.base, event->group.effective);
204
205 printf(" root x/y: %.2f / %.2f\n", event->root_x, event->root_y);
206 printf(" event x/y: %.2f / %.2f\n", event->event_x, event->event_y);
207
208 }
209
210 static void print_propertyevent(Display *display, XIPropertyEvent* event)
211 {
212 char *changed;
213 char *name;
214
215 if (event->what == XIPropertyDeleted)
216 changed = "deleted";
217 else if (event->what == XIPropertyCreated)
218 changed = "created";
219 else
220 changed = "modified";
221 name = XGetAtomName(display, event->property);
222 printf(" property: %ld '%s'\n", event->property, name);
223 printf(" changed: %s\n", changed);
224
225 XFree(name);
226 }
227 void
228 test_sync_grab(Display *display, Window win)
229 {
230 int loop = 3;
231 int rc;
232 XIEventMask mask;
233
234 /* Select for motion events */
235 mask.deviceid = XIAllDevices;
236 mask.mask_len = 2;
237 mask.mask = calloc(2, sizeof(char));
238 XISetMask(mask.mask, XI_ButtonPress);
239
240 if ((rc = XIGrabDevice(display, 2, win, CurrentTime, None, GrabModeSync,
241 GrabModeAsync, False, &mask)) != GrabSuccess)
242 {
243 fprintf(stderr, "Grab failed with %d\n", rc);
244 return;
245 }
246 free(mask.mask);
247
248 XSync(display, True);
249 XIAllowEvents(display, 2, SyncPointer, CurrentTime);
250 XFlush(display);
251
252 printf("Holding sync grab for %d button presses.\n", loop);
253
254 while(loop--)
255 {
256 XIEvent ev;
257
258 XNextEvent(display, (XEvent*)&ev);
259 if (ev.type == GenericEvent && ev.extension == xi_opcode )
260 {
261 XIDeviceEvent *event = (XIDeviceEvent*)&ev;
262 print_deviceevent(event);
263 XIAllowEvents(display, 2, SyncPointer, CurrentTime);
264 }
265 }
266
267 XIUngrabDevice(display, 2, CurrentTime);
268 printf("Done\n");
269 }
270
271 static const char* type_to_name(int evtype)
272 {
273 const char *name;
274
275 switch(evtype) {
276 case XI_DeviceChanged: name = "DeviceChanged"; break;
277 case XI_KeyPress: name = "KeyPress"; break;
278 case XI_KeyRelease: name = "KeyRelease"; break;
279 case XI_ButtonPress: name = "ButtonPress"; break;
280 case XI_ButtonRelease: name = "ButtonRelease"; break;
281 case XI_Motion: name = "Motion"; break;
282 case XI_Enter: name = "Enter"; break;
283 case XI_Leave: name = "Leave"; break;
284 case XI_FocusIn: name = "FocusIn"; break;
285 case XI_FocusOut: name = "FocusOut"; break;
286 case XI_HierarchyChanged: name = "HierarchyChanged"; break;
287 case XI_PropertyEvent: name = "PropertyEvent"; break;
288 case XI_RawKeyPress: name = "RawKeyPress"; break;
289 case XI_RawKeyRelease: name = "RawKeyRelease"; break;
290 case XI_RawButtonPress: name = "RawButtonPress"; break;
291 case XI_RawButtonRelease: name = "RawButtonRelease"; break;
292 case XI_RawMotion: name = "RawMotion"; break;
293 default:
294 name = "unknown event type"; break;
295 }
296 return name;
297 }
298
299
300 int
301 test_xi2(Display *display,
302 int argc,
303 char *argv[],
304 char *name,
305 char *desc)
306 {
307 XIEventMask mask;
308 Window win;
309 int deviceid = -1;
310
311 list(display, argc, argv, name, desc);
312 if (argc >= 1) {
313 XIDeviceInfo *info;
314 info = xi2_find_device_info(display, argv[0]);
315 deviceid = info->deviceid;
316 }
317 win = create_win(display);
318
319 /* Select for motion events */
320 mask.deviceid = (deviceid == -1) ? XIAllDevices : deviceid;
321 mask.mask_len = XIMaskLen(XI_RawMotion);
322 mask.mask = calloc(mask.mask_len, sizeof(char));
323 XISetMask(mask.mask, XI_ButtonPress);
324 XISetMask(mask.mask, XI_ButtonRelease);
325 XISetMask(mask.mask, XI_KeyPress);
326 XISetMask(mask.mask, XI_KeyRelease);
327 XISetMask(mask.mask, XI_Motion);
328 XISetMask(mask.mask, XI_DeviceChanged);
329 XISetMask(mask.mask, XI_Enter);
330 XISetMask(mask.mask, XI_Leave);
331 XISetMask(mask.mask, XI_FocusIn);
332 XISetMask(mask.mask, XI_FocusOut);
333 if (mask.deviceid == XIAllDevices)
334 XISetMask(mask.mask, XI_HierarchyChanged);
335 XISetMask(mask.mask, XI_PropertyEvent);
336 XISelectEvents(display, win, &mask, 1);
337 XMapWindow(display, win);
338 XSync(display, False);
339
340 {
341 XIGrabModifiers modifiers[] = {{0, 0}, {0, 0x10}, {0, 0x1}, {0, 0x11}};
342 int nmods = sizeof(modifiers)/sizeof(modifiers[0]);
343
344 mask.deviceid = 2;
345 memset(mask.mask, 0, mask.mask_len);
346 XISetMask(mask.mask, XI_KeyPress);
347 XISetMask(mask.mask, XI_KeyRelease);
348 XISetMask(mask.mask, XI_ButtonPress);
349 XISetMask(mask.mask, XI_ButtonRelease);
350 XISetMask(mask.mask, XI_Motion);
351 XIGrabButton(display, 2, 1, win, None, GrabModeAsync, GrabModeAsync,
352 False, &mask, nmods, modifiers);
353 XIGrabKeycode(display, 3, 24 /* q */, win, GrabModeAsync, GrabModeAsync,
354 False, &mask, nmods, modifiers);
355 XIUngrabButton(display, 3, 1, win, nmods - 2, &modifiers[2]);
356 XIUngrabKeycode(display, 3, 24 /* q */, win, nmods - 2, &modifiers[2]);
357 }
358
359 mask.deviceid = (deviceid == -1) ? XIAllMasterDevices : deviceid;
360 memset(mask.mask, 0, mask.mask_len);
361 XISetMask(mask.mask, XI_RawKeyPress);
362 XISetMask(mask.mask, XI_RawKeyRelease);
363 XISetMask(mask.mask, XI_RawButtonPress);
364 XISetMask(mask.mask, XI_RawButtonRelease);
365 XISetMask(mask.mask, XI_RawMotion);
366 XISelectEvents(display, DefaultRootWindow(display), &mask, 1);
367
368 free(mask.mask);
369
370 {
371 XEvent event;
372 XMaskEvent(display, ExposureMask, &event);
373 XSelectInput(display, win, 0);
374 }
375
376 /*
377 test_sync_grab(display, win);
378 */
379
380 while(1)
381 {
382 XEvent ev;
383 XGenericEventCookie *cookie = (XGenericEventCookie*)&ev.xcookie;
384 XNextEvent(display, (XEvent*)&ev);
385
386 if (XGetEventData(display, cookie) &&
387 cookie->type == GenericEvent &&
388 cookie->extension == xi_opcode)
389 {
390 printf("EVENT type %d (%s)\n", cookie->evtype, type_to_name(cookie->evtype));
391 switch (cookie->evtype)
392 {
393 case XI_DeviceChanged:
394 print_devicechangedevent(display, cookie->data);
395 break;
396 case XI_HierarchyChanged:
397 print_hierarchychangedevent(cookie->data);
398 break;
399 case XI_RawKeyPress:
400 case XI_RawKeyRelease:
401 case XI_RawButtonPress:
402 case XI_RawButtonRelease:
403 case XI_RawMotion:
404 print_rawevent(cookie->data);
405 break;
406 case XI_Enter:
407 case XI_Leave:
408 case XI_FocusIn:
409 case XI_FocusOut:
410 print_enterleave(cookie->data);
411 break;
412 case XI_PropertyEvent:
413 print_propertyevent(display, cookie->data);
414 break;
415 default:
416 print_deviceevent(cookie->data);
417 break;
418 }
419 }
420
421 XFreeEventData(display, cookie);
422 }
423
424 XDestroyWindow(display, win);
425
426 return EXIT_SUCCESS;
427 }