#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>
+/* convert the XInput button state mask to the regular X mouse event button mask */
+#define BUTTON_MASK(xistate) ((xistate) << 8)
+
/* import function from freeglut_main.c */
extern int fgPlatformGetModifiers( int state );
printf(" device: %d (%d)\n", event->deviceid, event->sourceid);
printf(" detail: %d\n", event->detail);
printf(" buttons:");
- for (i = 0; i < event->buttons.mask_len * 8; i++)
- if (XIMaskIsSet(event->buttons.mask, i))
- printf(" %d", i);
+ for (i = 0; i < event->buttons.mask_len * 8; i++)
+ if (XIMaskIsSet(event->buttons.mask, i))
+ printf(" %d", i);
printf("\n");
printf(" modifiers: locked 0x%x latched 0x%x base 0x%x\n",
*/
void fgHandleExtensionEvents( XEvent* base_ev )
{
- XEvent std_ev; /* standard single-pointer event to be added to the event queue */
- int i, button = 0;
- XGenericEventCookie* cookie = (XGenericEventCookie*)&(base_ev->xcookie);
-
- /* initialize the generic fields from base_ev */
- std_ev.xany = base_ev->xany;
-
- if ( XGetEventData( fgDisplay.pDisplay.Display, cookie ) && (cookie->type == GenericEvent) && (cookie->extension == xi_opcode) ) {
-
- XIDeviceEvent* event = (XIDeviceEvent*)(cookie->data);
- XIEnterEvent *evcross;
- /*printf("XI2 event type: %d - %d\n", cookie->evtype, event->type );*/
-
- SFG_Window* window = fgWindowByHandle( event->event );
- if (!window) return;
-
- switch (cookie->evtype) {
- case XI_Enter:
- case XI_Leave:
- evcross = (XIEnterEvent*)event;
-
- fgState.Modifiers = fgPlatformGetModifiers( evcross->mods.base );
- INVOKE_WCB( *window, MultiEntry, (
- event->deviceid,
- (event->evtype == XI_Enter ? GLUT_ENTERED : GLUT_LEFT)
- ));
- #if _DEBUG
- fgPrintXILeaveEvent((XILeaveEvent*)event);
- #endif
-
- /* Also process the standard crossing event */
- std_ev.type = evcross->evtype == XI_Enter ? EnterNotify : LeaveNotify;
- std_ev.xcrossing.window = evcross->event;
- std_ev.xcrossing.root = evcross->root;
- std_ev.xcrossing.subwindow = evcross->child;
- std_ev.xcrossing.x = evcross->event_x;
- std_ev.xcrossing.y = evcross->event_y;
- std_ev.xcrossing.x_root = evcross->root_x;
- std_ev.xcrossing.y_root = evcross->root_y;
- std_ev.xcrossing.mode = evcross->mode;
- std_ev.xcrossing.detail = evcross->detail;
- std_ev.xcrossing.same_screen = evcross->same_screen;
- std_ev.xcrossing.focus = evcross->focus;
- std_ev.xcrossing.state = *(unsigned int*)evcross->buttons.mask;
-
- XPutBackEvent(fgDisplay.pDisplay.Display, &std_ev);
- break;
-
- case XI_ButtonPress:
- case XI_ButtonRelease:
- fgState.Modifiers = fgPlatformGetModifiers( event->mods.base );
- INVOKE_WCB( *window, MultiButton, (
- event->deviceid,
- event->event_x,
- event->event_y,
- event->detail-1,
- (event->evtype == XI_ButtonPress ? GLUT_DOWN : GLUT_UP)
- ));
-
- /* Also process the standard button event */
- std_ev.type = event->evtype == XI_ButtonPress ? ButtonPress : ButtonRelease;
- std_ev.xbutton.window = event->event;
- std_ev.xbutton.root = event->root;
- std_ev.xbutton.subwindow = event->child;
- std_ev.xbutton.x = event->event_x;
- std_ev.xbutton.y = event->event_y;
- std_ev.xbutton.x_root = event->root_x;
- std_ev.xbutton.y_root = event->root_y;
- std_ev.xbutton.state = *(unsigned int*)event->buttons.mask;
- std_ev.xbutton.button = event->detail;
-
- XPutBackEvent(fgDisplay.pDisplay.Display, &std_ev);
- break;
-
- case XI_Motion:
- fgState.Modifiers = fgPlatformGetModifiers( event->mods.base );
- for (i = 0; i < event->buttons.mask_len; i++) {
- if (event->buttons.mask[i]) {
- button = 1;
- }
- }
- if (button) {
- INVOKE_WCB( *window, MultiMotion, ( event->deviceid, event->event_x, event->event_y ) );
- } else {
- INVOKE_WCB( *window, MultiPassive, ( event->deviceid, event->event_x, event->event_y ) );
- }
- #if _DEBUG
- fgPrintXIDeviceEvent(event);
- #endif
-
- /* Also process the standard motion event */
- std_ev.type = MotionNotify;
- std_ev.xmotion.window = event->event;
- std_ev.xmotion.root = event->root;
- std_ev.xmotion.subwindow = event->child;
- std_ev.xmotion.time = event->time;
- std_ev.xmotion.x = event->event_x;
- std_ev.xmotion.y = event->event_y;
- std_ev.xmotion.x_root = event->root_x;
- std_ev.xmotion.y_root = event->root_y;
- std_ev.xmotion.state = *(unsigned int*)event->buttons.mask;
- std_ev.xmotion.is_hint = NotifyNormal;
-
- XPutBackEvent(fgDisplay.pDisplay.Display, &std_ev);
- break;
-
- default:
- #if _DEBUG
- fgWarning( "Unknown XI2 device event:" );
- fgPrintXIDeviceEvent( event );
- #endif
- break;
- }
- fgState.Modifiers = INVALID_MODIFIERS;
- }
- XFreeEventData( fgDisplay.pDisplay.Display, cookie );
+ XEvent std_ev; /* standard single-pointer event to be added to the event queue */
+ int i, button = 0;
+ XGenericEventCookie* cookie = (XGenericEventCookie*)&(base_ev->xcookie);
+
+ /* initialize the generic fields from base_ev */
+ std_ev.xany = base_ev->xany;
+
+ if ( XGetEventData( fgDisplay.pDisplay.Display, cookie ) && (cookie->type == GenericEvent) && (cookie->extension == xi_opcode) ) {
+
+ XIDeviceEvent* event = (XIDeviceEvent*)(cookie->data);
+ XIEnterEvent *evcross;
+ /*printf("XI2 event type: %d - %d\n", cookie->evtype, event->type );*/
+
+ SFG_Window* window = fgWindowByHandle( event->event );
+ if (!window) return;
+
+ switch (cookie->evtype) {
+ case XI_Enter:
+ case XI_Leave:
+ evcross = (XIEnterEvent*)event;
+
+ fgState.Modifiers = fgPlatformGetModifiers( evcross->mods.base );
+ INVOKE_WCB( *window, MultiEntry, (
+ event->deviceid,
+ (event->evtype == XI_Enter ? GLUT_ENTERED : GLUT_LEFT)
+ ));
+ #if _DEBUG
+ fgPrintXILeaveEvent((XILeaveEvent*)event);
+ #endif
+
+ /* Also process the standard crossing event */
+ std_ev.type = evcross->evtype == XI_Enter ? EnterNotify : LeaveNotify;
+ std_ev.xcrossing.window = evcross->event;
+ std_ev.xcrossing.root = evcross->root;
+ std_ev.xcrossing.subwindow = evcross->child;
+ std_ev.xcrossing.x = evcross->event_x;
+ std_ev.xcrossing.y = evcross->event_y;
+ std_ev.xcrossing.x_root = evcross->root_x;
+ std_ev.xcrossing.y_root = evcross->root_y;
+ std_ev.xcrossing.mode = evcross->mode;
+ std_ev.xcrossing.detail = evcross->detail;
+ std_ev.xcrossing.same_screen = evcross->same_screen;
+ std_ev.xcrossing.focus = evcross->focus;
+ std_ev.xcrossing.state = BUTTON_MASK(*(unsigned int*)evcross->buttons.mask);
+
+ XPutBackEvent(fgDisplay.pDisplay.Display, &std_ev);
+ break;
+
+ case XI_ButtonPress:
+ case XI_ButtonRelease:
+ fgState.Modifiers = fgPlatformGetModifiers( event->mods.base );
+ INVOKE_WCB( *window, MultiButton, (
+ event->deviceid,
+ event->event_x,
+ event->event_y,
+ event->detail-1,
+ (event->evtype == XI_ButtonPress ? GLUT_DOWN : GLUT_UP)
+ ));
+
+ /* Also process the standard button event */
+ std_ev.type = event->evtype == XI_ButtonPress ? ButtonPress : ButtonRelease;
+ std_ev.xbutton.window = event->event;
+ std_ev.xbutton.root = event->root;
+ std_ev.xbutton.subwindow = event->child;
+ std_ev.xbutton.x = event->event_x;
+ std_ev.xbutton.y = event->event_y;
+ std_ev.xbutton.x_root = event->root_x;
+ std_ev.xbutton.y_root = event->root_y;
+ std_ev.xbutton.state = BUTTON_MASK(*(unsigned int*)event->buttons.mask);
+ std_ev.xbutton.button = event->detail;
+
+ XPutBackEvent(fgDisplay.pDisplay.Display, &std_ev);
+ break;
+
+ case XI_Motion:
+ fgState.Modifiers = fgPlatformGetModifiers( event->mods.base );
+ for (i = 0; i < event->buttons.mask_len; i++) {
+ if (event->buttons.mask[i]) {
+ button = 1;
+ }
+ }
+ if (button) {
+ INVOKE_WCB( *window, MultiMotion, ( event->deviceid, event->event_x, event->event_y ) );
+ } else {
+ INVOKE_WCB( *window, MultiPassive, ( event->deviceid, event->event_x, event->event_y ) );
+ }
+ #if _DEBUG
+ fgPrintXIDeviceEvent(event);
+ #endif
+
+ /* Also process the standard motion event */
+ std_ev.type = MotionNotify;
+ std_ev.xmotion.window = event->event;
+ std_ev.xmotion.root = event->root;
+ std_ev.xmotion.subwindow = event->child;
+ std_ev.xmotion.time = event->time;
+ std_ev.xmotion.x = event->event_x;
+ std_ev.xmotion.y = event->event_y;
+ std_ev.xmotion.x_root = event->root_x;
+ std_ev.xmotion.y_root = event->root_y;
+ std_ev.xmotion.state = BUTTON_MASK(*(unsigned int*)event->buttons.mask);
+ std_ev.xmotion.is_hint = NotifyNormal;
+
+ XPutBackEvent(fgDisplay.pDisplay.Display, &std_ev);
+ break;
+
+ default:
+ #if _DEBUG
+ fgWarning( "Unknown XI2 device event:" );
+ fgPrintXIDeviceEvent( event );
+ #endif
+ break;
+ }
+ fgState.Modifiers = INVALID_MODIFIERS;
+ }
+ XFreeEventData( fgDisplay.pDisplay.Display, cookie );
}
#endif