1 /* Written for XI1 by Nikolas Doerfler <doerflen@in.tum.de> (c) 2008 *
2 * Rewritten for XI2 by Florian Echtler <echtler@in.tum.de> (c) 2009 */
4 #include <GL/freeglut.h>
6 #include "../fg_internal.h"
8 #if HAVE_X11_EXTENSIONS_XINPUT2_H
14 #include <X11/extensions/XInput2.h>
16 /* import function from freeglut_main.c */
17 extern int fgPlatformGetModifiers( int state );
19 /* extension opcode for XInput */
23 * \brief Sets window up for XI2 events.
25 void fgRegisterDevices( Display* dpy, Window* win ) {
28 unsigned char flags[2] = { 0, 0 };
31 /*Display* dpy = fgDisplay.pDisplay.Display;
32 Window* win = glutGetXWindow();*/
34 /* get XInput extension opcode */
35 if (!XQueryExtension( dpy, "XInputExtension", &xi_opcode, &event, &error )) { xi_opcode = -1; }
37 /* Select for motion events */
38 mask.deviceid = XIAllMasterDevices;
42 XISetMask(mask.mask, XI_Enter);
43 XISetMask(mask.mask, XI_Motion);
44 XISetMask(mask.mask, XI_ButtonPress);
45 XISetMask(mask.mask, XI_ButtonRelease);
46 XISetMask(mask.mask, XI_Leave);
47 /*XISetMask(mask.mask, XI_KeyPress);
48 XISetMask(mask.mask, XI_KeyRelease);
49 XISetMask(mask.mask, XI_DeviceChanged);
50 XISetMask(mask.mask, XI_RawEvent);
51 XISetMask(mask.mask, XI_FocusIn);
52 XISetMask(mask.mask, XI_FocusOut);
53 XISetMask(mask.mask, XI_HierarchyChanged);*/
55 XISelectEvents( dpy, *win, &mask, 1 );
59 void fgPrintXILeaveEvent(XILeaveEvent* event)
65 printf(" windows: root 0x%lx event 0x%lx child 0x%ld\n",
66 event->root, event->event, event->child);
69 case NotifyNormal: mode = "NotifyNormal"; break;
70 case NotifyGrab: mode = "NotifyGrab"; break;
71 case NotifyUngrab: mode = "NotifyUngrab"; break;
72 case NotifyWhileGrabbed: mode = "NotifyWhileGrabbed"; break;
74 switch (event->detail)
76 case NotifyAncestor: detail = "NotifyAncestor"; break;
77 case NotifyVirtual: detail = "NotifyVirtual"; break;
78 case NotifyInferior: detail = "NotifyInferior"; break;
79 case NotifyNonlinear: detail = "NotifyNonlinear"; break;
80 case NotifyNonlinearVirtual: detail = "NotifyNonlinearVirtual"; break;
81 case NotifyPointer: detail = "NotifyPointer"; break;
82 case NotifyPointerRoot: detail = "NotifyPointerRoot"; break;
83 case NotifyDetailNone: detail = "NotifyDetailNone"; break;
85 printf(" mode: %s (detail %s)\n", mode, detail);
86 printf(" flags: %s %s\n", event->focus ? "[focus]" : "",
87 event->same_screen ? "[same screen]" : "");
89 for (i = 0; i < event->buttons.mask_len * 8; i++)
90 if (XIMaskIsSet(event->buttons.mask, i))
94 printf(" modifiers: locked 0x%x latched 0x%x base 0x%x\n",
95 event->mods.locked, event->mods.latched,
97 printf(" group: locked 0x%x latched 0x%x base 0x%x\n",
98 event->group.locked, event->group.latched,
101 printf(" root x/y: %.2f / %.2f\n", event->root_x, event->root_y);
102 printf(" event x/y: %.2f / %.2f\n", event->event_x, event->event_y);
107 void fgPrintXIDeviceEvent(XIDeviceEvent* event)
112 printf(" device: %d (%d)\n", event->deviceid, event->sourceid);
113 printf(" detail: %d\n", event->detail);
115 for (i = 0; i < event->buttons.mask_len * 8; i++)
116 if (XIMaskIsSet(event->buttons.mask, i))
120 printf(" modifiers: locked 0x%x latched 0x%x base 0x%x\n",
121 event->mods.locked, event->mods.latched,
123 printf(" group: locked 0x%x latched 0x%x base 0x%x\n",
124 event->group.locked, event->group.latched,
126 printf(" valuators:");
128 val = event->valuators.values;
129 for (i = 0; i < event->valuators.mask_len * 8; i++)
130 if (XIMaskIsSet(event->valuators.mask, i))
131 printf(" %d: %.2f", i, *val++);
134 printf(" windows: root 0x%lx event 0x%lx child 0x%ld\n",
135 event->root, event->event, event->child);
136 printf(" root x/y: %.2f / %.2f\n", event->root_x, event->root_y);
137 printf(" event x/y: %.2f / %.2f\n", event->event_x, event->event_y);
143 * \brief This function is called when an Extension Event is received
144 * and calls the corresponding callback functions for these events.
146 void fgHandleExtensionEvents( XEvent* base_ev ) {
149 XGenericEventCookie* cookie = (XGenericEventCookie*)&(base_ev->xcookie);
151 if ( XGetEventData( fgDisplay.pDisplay.Display, cookie ) && (cookie->type == GenericEvent) && (cookie->extension == xi_opcode) ) {
153 XIDeviceEvent* event = (XIDeviceEvent*)(cookie->data);
154 /*printf("XI2 event type: %d - %d\n", cookie->evtype, event->type );*/
156 SFG_Window* window = fgWindowByHandle( event->event );
159 switch (cookie->evtype) {
163 fgState.Modifiers = fgPlatformGetModifiers( ((XIEnterEvent*)event)->mods.base );
164 INVOKE_WCB( *window, MultiEntry, (
166 (event->evtype == XI_Enter ? GLUT_ENTERED : GLUT_LEFT)
169 fgPrintXILeaveEvent((XILeaveEvent*)event);
174 case XI_ButtonRelease:
175 fgState.Modifiers = fgPlatformGetModifiers( event->mods.base );
176 INVOKE_WCB( *window, MultiButton, (
181 (event->evtype == XI_ButtonPress ? GLUT_DOWN : GLUT_UP)
183 INVOKE_WCB( *window, Mouse, (
185 (event->evtype == XI_ButtonPress ? GLUT_DOWN : GLUT_UP),
192 fgState.Modifiers = fgPlatformGetModifiers( event->mods.base );
193 for (i = 0; i < event->buttons.mask_len; i++) if (event->buttons.mask[i]) button = 1;
195 INVOKE_WCB( *window, MultiMotion, ( event->deviceid, event->event_x, event->event_y ) );
196 INVOKE_WCB( *window, Motion, ( event->event_x, event->event_y ) );
198 INVOKE_WCB( *window, MultiPassive, ( event->deviceid, event->event_x, event->event_y ) );
199 INVOKE_WCB( *window, Passive, ( event->event_x, event->event_y ) );
202 fgPrintXIDeviceEvent(event);
208 fgWarning( "Unknown XI2 device event:" );
209 fgPrintXIDeviceEvent( event );
213 fgState.Modifiers = INVALID_MODIFIERS;
215 XFreeEventData( fgDisplay.pDisplay.Display, cookie );