]> diplodocus.org Git - xorg-xinput/blob - src/test_xi2.c
b64368e2df3ff2976d96cfbb3a22c29f662475c4
[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 #if HAVE_XI21
57 case XI_ButtonPress:
58 case XI_ButtonRelease:
59 case XI_Motion:
60 printf(" flags: %s\n", (event->flags & XIPointerEmulated) ? "emulated" : "");
61 break;
62 #endif
63 }
64
65 printf(" root: %.2f/%.2f\n", event->root_x, event->root_y);
66 printf(" event: %.2f/%.2f\n", event->event_x, event->event_y);
67
68 printf(" buttons:");
69 for (i = 0; i < event->buttons.mask_len * 8; i++)
70 if (XIMaskIsSet(event->buttons.mask, i))
71 printf(" %d", i);
72 printf("\n");
73
74 printf(" modifiers: locked %#x latched %#x base %#x effective: %#x\n",
75 event->mods.locked, event->mods.latched,
76 event->mods.base, event->mods.effective);
77 printf(" group: locked %#x latched %#x base %#x effective: %#x\n",
78 event->group.locked, event->group.latched,
79 event->group.base, event->group.effective);
80 printf(" valuators:\n");
81
82 val = event->valuators.values;
83 for (i = 0; i < event->valuators.mask_len * 8; i++)
84 if (XIMaskIsSet(event->valuators.mask, i))
85 printf(" %i: %.2f\n", i, *val++);
86
87 printf(" windows: root 0x%lx event 0x%lx child 0x%lx\n",
88 event->root, event->event, event->child);
89 }
90
91 static void print_devicechangedevent(Display *dpy, XIDeviceChangedEvent *event)
92 {
93 printf(" device: %d (%d)\n", event->deviceid, event->sourceid);
94 printf(" reason: %s\n", (event->reason == XISlaveSwitch) ? "SlaveSwitch" :
95 "DeviceChanged");
96 print_classes_xi2(dpy, event->classes, event->num_classes);
97 }
98
99 static void print_hierarchychangedevent(XIHierarchyEvent *event)
100 {
101 int i;
102 printf(" Changes happened: %s %s %s %s %s %s %s %s\n",
103 (event->flags & XIMasterAdded) ? "[new master]" : "",
104 (event->flags & XIMasterRemoved) ? "[master removed]" : "",
105 (event->flags & XISlaveAdded) ? "[new slave]" : "",
106 (event->flags & XISlaveRemoved) ? "[slave removed]" : "",
107 (event->flags & XISlaveAttached) ? "[slave attached]" : "",
108 (event->flags & XISlaveDetached) ? "[slave detached]" : "",
109 (event->flags & XIDeviceEnabled) ? "[device enabled]" : "",
110 (event->flags & XIDeviceDisabled) ? "[device disabled]" : "");
111
112 for (i = 0; i < event->num_info; i++)
113 {
114 char *use = "<undefined>";
115 switch(event->info[i].use)
116 {
117 case XIMasterPointer: use = "master pointer"; break;
118 case XIMasterKeyboard: use = "master keyboard"; break;
119 case XISlavePointer: use = "slave pointer"; break;
120 case XISlaveKeyboard: use = "slave keyboard"; break;
121 case XIFloatingSlave: use = "floating slave"; break;
122 break;
123 }
124
125 printf(" device %d [%s (%d)] is %s\n",
126 event->info[i].deviceid,
127 use,
128 event->info[i].attachment,
129 (event->info[i].enabled) ? "enabled" : "disabled");
130 if (event->info[i].flags)
131 {
132 printf(" changes: %s %s %s %s %s %s %s %s\n",
133 (event->info[i].flags & XIMasterAdded) ? "[new master]" : "",
134 (event->info[i].flags & XIMasterRemoved) ? "[master removed]" : "",
135 (event->info[i].flags & XISlaveAdded) ? "[new slave]" : "",
136 (event->info[i].flags & XISlaveRemoved) ? "[slave removed]" : "",
137 (event->info[i].flags & XISlaveAttached) ? "[slave attached]" : "",
138 (event->info[i].flags & XISlaveDetached) ? "[slave detached]" : "",
139 (event->info[i].flags & XIDeviceEnabled) ? "[device enabled]" : "",
140 (event->info[i].flags & XIDeviceDisabled) ? "[device disabled]" : "");
141 }
142 }
143 }
144
145 static void print_rawevent(XIRawEvent *event)
146 {
147 int i;
148 double *val, *raw_val;
149
150 printf(" device: %d (%d)\n", event->deviceid, event->sourceid);
151 printf(" detail: %d\n", event->detail);
152 printf(" valuators:\n");
153 #if HAVE_XI21
154 switch(event->evtype) {
155 case XI_RawButtonPress:
156 case XI_RawButtonRelease:
157 case XI_RawMotion:
158 printf(" flags: %s\n", (event->flags & XIPointerEmulated) ? "emulated" : "");
159 break;
160 }
161 #endif
162
163 val = event->valuators.values;
164 raw_val = event->raw_values;
165 for (i = 0; i < event->valuators.mask_len * 8; i++)
166 if (XIMaskIsSet(event->valuators.mask, i))
167 printf(" %2d: %.2f (%.2f)\n", i, *val++, *raw_val++);
168 printf("\n");
169 }
170
171 static void print_enterleave(XILeaveEvent* event)
172 {
173 char *mode = "<undefined>",
174 *detail = "<undefined>";
175 int i;
176
177 printf(" device: %d (%d)\n", event->deviceid, event->sourceid);
178 printf(" windows: root 0x%lx event 0x%lx child 0x%ld\n",
179 event->root, event->event, event->child);
180 switch(event->mode)
181 {
182 case XINotifyNormal: mode = "NotifyNormal"; break;
183 case XINotifyGrab: mode = "NotifyGrab"; break;
184 case XINotifyUngrab: mode = "NotifyUngrab"; break;
185 case XINotifyWhileGrabbed: mode = "NotifyWhileGrabbed"; break;
186 case XINotifyPassiveGrab: mode = "NotifyPassiveGrab"; break;
187 case XINotifyPassiveUngrab:mode = "NotifyPassiveUngrab"; break;
188 }
189 switch (event->detail)
190 {
191 case XINotifyAncestor: detail = "NotifyAncestor"; break;
192 case XINotifyVirtual: detail = "NotifyVirtual"; break;
193 case XINotifyInferior: detail = "NotifyInferior"; break;
194 case XINotifyNonlinear: detail = "NotifyNonlinear"; break;
195 case XINotifyNonlinearVirtual: detail = "NotifyNonlinearVirtual"; break;
196 case XINotifyPointer: detail = "NotifyPointer"; break;
197 case XINotifyPointerRoot: detail = "NotifyPointerRoot"; break;
198 case XINotifyDetailNone: detail = "NotifyDetailNone"; break;
199 }
200 printf(" mode: %s (detail %s)\n", mode, detail);
201 printf(" flags: %s %s\n", event->focus ? "[focus]" : "",
202 event->same_screen ? "[same screen]" : "");
203 printf(" buttons:");
204 for (i = 0; i < event->buttons.mask_len * 8; i++)
205 if (XIMaskIsSet(event->buttons.mask, i))
206 printf(" %d", i);
207 printf("\n");
208
209 printf(" modifiers: locked %#x latched %#x base %#x effective: %#x\n",
210 event->mods.locked, event->mods.latched,
211 event->mods.base, event->mods.effective);
212 printf(" group: locked %#x latched %#x base %#x effective: %#x\n",
213 event->group.locked, event->group.latched,
214 event->group.base, event->group.effective);
215
216 printf(" root x/y: %.2f / %.2f\n", event->root_x, event->root_y);
217 printf(" event x/y: %.2f / %.2f\n", event->event_x, event->event_y);
218
219 }
220
221 static void print_propertyevent(Display *display, XIPropertyEvent* event)
222 {
223 char *changed;
224 char *name;
225
226 if (event->what == XIPropertyDeleted)
227 changed = "deleted";
228 else if (event->what == XIPropertyCreated)
229 changed = "created";
230 else
231 changed = "modified";
232 name = XGetAtomName(display, event->property);
233 printf(" property: %ld '%s'\n", event->property, name);
234 printf(" changed: %s\n", changed);
235
236 XFree(name);
237 }
238 void
239 test_sync_grab(Display *display, Window win)
240 {
241 int loop = 3;
242 int rc;
243 XIEventMask mask;
244
245 /* Select for motion events */
246 mask.deviceid = XIAllDevices;
247 mask.mask_len = 2;
248 mask.mask = calloc(2, sizeof(char));
249 XISetMask(mask.mask, XI_ButtonPress);
250
251 if ((rc = XIGrabDevice(display, 2, win, CurrentTime, None, GrabModeSync,
252 GrabModeAsync, False, &mask)) != GrabSuccess)
253 {
254 fprintf(stderr, "Grab failed with %d\n", rc);
255 return;
256 }
257 free(mask.mask);
258
259 XSync(display, True);
260 XIAllowEvents(display, 2, SyncPointer, CurrentTime);
261 XFlush(display);
262
263 printf("Holding sync grab for %d button presses.\n", loop);
264
265 while(loop--)
266 {
267 XIEvent ev;
268
269 XNextEvent(display, (XEvent*)&ev);
270 if (ev.type == GenericEvent && ev.extension == xi_opcode )
271 {
272 XIDeviceEvent *event = (XIDeviceEvent*)&ev;
273 print_deviceevent(event);
274 XIAllowEvents(display, 2, SyncPointer, CurrentTime);
275 }
276 }
277
278 XIUngrabDevice(display, 2, CurrentTime);
279 printf("Done\n");
280 }
281
282 static const char* type_to_name(int evtype)
283 {
284 const char *name;
285
286 switch(evtype) {
287 case XI_DeviceChanged: name = "DeviceChanged"; break;
288 case XI_KeyPress: name = "KeyPress"; break;
289 case XI_KeyRelease: name = "KeyRelease"; break;
290 case XI_ButtonPress: name = "ButtonPress"; break;
291 case XI_ButtonRelease: name = "ButtonRelease"; break;
292 case XI_Motion: name = "Motion"; break;
293 case XI_Enter: name = "Enter"; break;
294 case XI_Leave: name = "Leave"; break;
295 case XI_FocusIn: name = "FocusIn"; break;
296 case XI_FocusOut: name = "FocusOut"; break;
297 case XI_HierarchyChanged: name = "HierarchyChanged"; break;
298 case XI_PropertyEvent: name = "PropertyEvent"; break;
299 case XI_RawKeyPress: name = "RawKeyPress"; break;
300 case XI_RawKeyRelease: name = "RawKeyRelease"; break;
301 case XI_RawButtonPress: name = "RawButtonPress"; break;
302 case XI_RawButtonRelease: name = "RawButtonRelease"; break;
303 case XI_RawMotion: name = "RawMotion"; break;
304 case XI_TouchBegin: name = "TouchBegin"; break;
305 case XI_TouchUpdate: name = "TouchUpdate"; break;
306 case XI_TouchEnd: name = "TouchEnd"; break;
307 case XI_RawTouchBegin: name = "RawTouchBegin"; break;
308 case XI_RawTouchUpdate: name = "RawTouchUpdate"; break;
309 case XI_RawTouchEnd: name = "RawTouchEnd"; break;
310 default:
311 name = "unknown event type"; break;
312 }
313 return name;
314 }
315
316
317 int
318 test_xi2(Display *display,
319 int argc,
320 char *argv[],
321 char *name,
322 char *desc)
323 {
324 XIEventMask mask[2];
325 XIEventMask *m;
326 Window win;
327 int deviceid = -1;
328 int rc;
329
330 setlinebuf(stdout);
331
332 rc = list(display, argc, argv, name, desc);
333 if (rc != EXIT_SUCCESS)
334 return rc;
335
336 if (argc >= 1) {
337 XIDeviceInfo *info;
338 info = xi2_find_device_info(display, argv[0]);
339 deviceid = info->deviceid;
340 }
341 win = create_win(display);
342
343 /* Select for motion events */
344 m = &mask[0];
345 m->deviceid = (deviceid == -1) ? XIAllDevices : deviceid;
346 m->mask_len = XIMaskLen(XI_LASTEVENT);
347 m->mask = calloc(m->mask_len, sizeof(char));
348 XISetMask(m->mask, XI_ButtonPress);
349 XISetMask(m->mask, XI_ButtonRelease);
350 XISetMask(m->mask, XI_KeyPress);
351 XISetMask(m->mask, XI_KeyRelease);
352 XISetMask(m->mask, XI_Motion);
353 XISetMask(m->mask, XI_DeviceChanged);
354 XISetMask(m->mask, XI_Enter);
355 XISetMask(m->mask, XI_Leave);
356 XISetMask(m->mask, XI_FocusIn);
357 XISetMask(m->mask, XI_FocusOut);
358 #ifdef HAVE_XI22
359 XISetMask(m->mask, XI_TouchBegin);
360 XISetMask(m->mask, XI_TouchUpdate);
361 XISetMask(m->mask, XI_TouchEnd);
362 #endif
363 if (m->deviceid == XIAllDevices)
364 XISetMask(m->mask, XI_HierarchyChanged);
365 XISetMask(m->mask, XI_PropertyEvent);
366 XISelectEvents(display, win, m, 1);
367 XMapWindow(display, win);
368 XSync(display, False);
369
370 m = &mask[1];
371 m->deviceid = (deviceid == -1) ? XIAllMasterDevices : deviceid;
372 m->mask_len = XIMaskLen(XI_LASTEVENT);
373 m->mask = calloc(m->mask_len, sizeof(char));
374 XISetMask(m->mask, XI_RawKeyPress);
375 XISetMask(m->mask, XI_RawKeyRelease);
376 XISetMask(m->mask, XI_RawButtonPress);
377 XISetMask(m->mask, XI_RawButtonRelease);
378 XISetMask(m->mask, XI_RawMotion);
379 #ifdef HAVE_XI22
380 XISetMask(m->mask, XI_RawTouchBegin);
381 XISetMask(m->mask, XI_RawTouchUpdate);
382 XISetMask(m->mask, XI_RawTouchEnd);
383 #endif
384 XISelectEvents(display, DefaultRootWindow(display), m, 1);
385
386 free(mask[0].mask);
387 free(mask[1].mask);
388
389 {
390 XEvent event;
391 XMaskEvent(display, ExposureMask, &event);
392 XSelectInput(display, win, 0);
393 }
394
395 /*
396 test_sync_grab(display, win);
397 */
398
399 while(1)
400 {
401 XEvent ev;
402 XGenericEventCookie *cookie = (XGenericEventCookie*)&ev.xcookie;
403 XNextEvent(display, (XEvent*)&ev);
404
405 if (XGetEventData(display, cookie) &&
406 cookie->type == GenericEvent &&
407 cookie->extension == xi_opcode)
408 {
409 printf("EVENT type %d (%s)\n", cookie->evtype, type_to_name(cookie->evtype));
410 switch (cookie->evtype)
411 {
412 case XI_DeviceChanged:
413 print_devicechangedevent(display, cookie->data);
414 break;
415 case XI_HierarchyChanged:
416 print_hierarchychangedevent(cookie->data);
417 break;
418 case XI_RawKeyPress:
419 case XI_RawKeyRelease:
420 case XI_RawButtonPress:
421 case XI_RawButtonRelease:
422 case XI_RawMotion:
423 case XI_RawTouchBegin:
424 case XI_RawTouchUpdate:
425 case XI_RawTouchEnd:
426 print_rawevent(cookie->data);
427 break;
428 case XI_Enter:
429 case XI_Leave:
430 case XI_FocusIn:
431 case XI_FocusOut:
432 print_enterleave(cookie->data);
433 break;
434 case XI_PropertyEvent:
435 print_propertyevent(display, cookie->data);
436 break;
437 default:
438 print_deviceevent(cookie->data);
439 break;
440 }
441 }
442
443 XFreeEventData(display, cookie);
444 }
445
446 XDestroyWindow(display, win);
447
448 return EXIT_SUCCESS;
449 }