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