test_xi2.c revision 0309d3b3
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 29extern void print_classes_xi2(Display*, XIAnyClassInfo **classes, 30 int num_classes); 31 32static 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 44static 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 91static 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 99static 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 145static 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 171static 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 221static 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} 238void 239test_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 282static 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 317int 318test_xi2(Display *display, 319 int argc, 320 char *argv[], 321 char *name, 322 char *desc) 323{ 324 XIEventMask mask; 325 Window win; 326 int deviceid = -1; 327 int rc; 328 329 rc = list(display, argc, argv, name, desc); 330 if (rc != EXIT_SUCCESS) 331 return rc; 332 333 if (argc >= 1) { 334 XIDeviceInfo *info; 335 info = xi2_find_device_info(display, argv[0]); 336 deviceid = info->deviceid; 337 } 338 win = create_win(display); 339 340 /* Select for motion events */ 341 mask.deviceid = (deviceid == -1) ? XIAllDevices : deviceid; 342 mask.mask_len = XIMaskLen(XI_LASTEVENT); 343 mask.mask = calloc(mask.mask_len, sizeof(char)); 344 XISetMask(mask.mask, XI_ButtonPress); 345 XISetMask(mask.mask, XI_ButtonRelease); 346 XISetMask(mask.mask, XI_KeyPress); 347 XISetMask(mask.mask, XI_KeyRelease); 348 XISetMask(mask.mask, XI_Motion); 349 XISetMask(mask.mask, XI_DeviceChanged); 350 XISetMask(mask.mask, XI_Enter); 351 XISetMask(mask.mask, XI_Leave); 352 XISetMask(mask.mask, XI_FocusIn); 353 XISetMask(mask.mask, XI_FocusOut); 354#ifdef HAVE_XI22 355 XISetMask(mask.mask, XI_TouchBegin); 356 XISetMask(mask.mask, XI_TouchUpdate); 357 XISetMask(mask.mask, XI_TouchEnd); 358#endif 359 if (mask.deviceid == XIAllDevices) 360 XISetMask(mask.mask, XI_HierarchyChanged); 361 XISetMask(mask.mask, XI_PropertyEvent); 362 XISelectEvents(display, win, &mask, 1); 363 XMapWindow(display, win); 364 XSync(display, False); 365 366 { 367 XIGrabModifiers modifiers[] = {{0, 0}, {0, 0x10}, {0, 0x1}, {0, 0x11}}; 368 int nmods = sizeof(modifiers)/sizeof(modifiers[0]); 369 370 mask.deviceid = 2; 371 memset(mask.mask, 0, mask.mask_len); 372 XISetMask(mask.mask, XI_KeyPress); 373 XISetMask(mask.mask, XI_KeyRelease); 374 XISetMask(mask.mask, XI_ButtonPress); 375 XISetMask(mask.mask, XI_ButtonRelease); 376 XISetMask(mask.mask, XI_Motion); 377 XIGrabButton(display, 2, 1, win, None, GrabModeAsync, GrabModeAsync, 378 False, &mask, nmods, modifiers); 379 XIGrabKeycode(display, 3, 24 /* q */, win, GrabModeAsync, GrabModeAsync, 380 False, &mask, nmods, modifiers); 381 XIUngrabButton(display, 3, 1, win, nmods - 2, &modifiers[2]); 382 XIUngrabKeycode(display, 3, 24 /* q */, win, nmods - 2, &modifiers[2]); 383 } 384 385 mask.deviceid = (deviceid == -1) ? XIAllMasterDevices : deviceid; 386 memset(mask.mask, 0, mask.mask_len); 387 XISetMask(mask.mask, XI_RawKeyPress); 388 XISetMask(mask.mask, XI_RawKeyRelease); 389 XISetMask(mask.mask, XI_RawButtonPress); 390 XISetMask(mask.mask, XI_RawButtonRelease); 391 XISetMask(mask.mask, XI_RawMotion); 392#ifdef HAVE_XI22 393 XISetMask(mask.mask, XI_RawTouchBegin); 394 XISetMask(mask.mask, XI_RawTouchUpdate); 395 XISetMask(mask.mask, XI_RawTouchEnd); 396#endif 397 XISelectEvents(display, DefaultRootWindow(display), &mask, 1); 398 399 free(mask.mask); 400 401 { 402 XEvent event; 403 XMaskEvent(display, ExposureMask, &event); 404 XSelectInput(display, win, 0); 405 } 406 407 /* 408 test_sync_grab(display, win); 409 */ 410 411 while(1) 412 { 413 XEvent ev; 414 XGenericEventCookie *cookie = (XGenericEventCookie*)&ev.xcookie; 415 XNextEvent(display, (XEvent*)&ev); 416 417 if (XGetEventData(display, cookie) && 418 cookie->type == GenericEvent && 419 cookie->extension == xi_opcode) 420 { 421 printf("EVENT type %d (%s)\n", cookie->evtype, type_to_name(cookie->evtype)); 422 switch (cookie->evtype) 423 { 424 case XI_DeviceChanged: 425 print_devicechangedevent(display, cookie->data); 426 break; 427 case XI_HierarchyChanged: 428 print_hierarchychangedevent(cookie->data); 429 break; 430 case XI_RawKeyPress: 431 case XI_RawKeyRelease: 432 case XI_RawButtonPress: 433 case XI_RawButtonRelease: 434 case XI_RawMotion: 435 case XI_RawTouchBegin: 436 case XI_RawTouchUpdate: 437 case XI_RawTouchEnd: 438 print_rawevent(cookie->data); 439 break; 440 case XI_Enter: 441 case XI_Leave: 442 case XI_FocusIn: 443 case XI_FocusOut: 444 print_enterleave(cookie->data); 445 break; 446 case XI_PropertyEvent: 447 print_propertyevent(display, cookie->data); 448 break; 449 default: 450 print_deviceevent(cookie->data); 451 break; 452 } 453 } 454 455 XFreeEventData(display, cookie); 456 } 457 458 XDestroyWindow(display, win); 459 460 return EXIT_SUCCESS; 461} 462