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