220 lines
6.8 KiB
C
220 lines
6.8 KiB
C
/* Written for XI1 by Nikolas Doerfler <doerflen@in.tum.de> (c) 2008 *
|
|
* Rewritten for XI2 by Florian Echtler <echtler@in.tum.de> (c) 2009 */
|
|
|
|
#include <GL/freeglut.h>
|
|
|
|
#include "freeglut_internal.h"
|
|
|
|
#if TARGET_HOST_POSIX_X11 && HAVE_X11_EXTENSIONS_XINPUT2_H
|
|
|
|
#include <errno.h>
|
|
#include <stdarg.h>
|
|
|
|
#include <X11/Xlib.h>
|
|
#include <X11/extensions/XInput2.h>
|
|
|
|
/* import function from freeglut_main.c */
|
|
int fghGetXModifiers( int state );
|
|
|
|
/* extension opcode for XInput */
|
|
int xi_opcode = -1;
|
|
|
|
/**
|
|
* \brief Sets window up for XI2 events.
|
|
*/
|
|
void fgRegisterDevices( Display* dpy, Window* win ) {
|
|
|
|
XIEventMask mask;
|
|
unsigned char flags[2] = { 0, 0 };
|
|
int event, error;
|
|
|
|
/*Display* dpy = fgDisplay.Display;
|
|
Window* win = glutGetXWindow();*/
|
|
|
|
/* get XInput extension opcode */
|
|
if (!XQueryExtension( dpy, "XInputExtension", &xi_opcode, &event, &error )) { xi_opcode = -1; }
|
|
|
|
/* Select for motion events */
|
|
mask.deviceid = XIAllMasterDevices;
|
|
mask.mask_len = 2;
|
|
mask.mask = flags;
|
|
|
|
XISetMask(mask.mask, XI_Enter);
|
|
XISetMask(mask.mask, XI_Motion);
|
|
XISetMask(mask.mask, XI_ButtonPress);
|
|
XISetMask(mask.mask, XI_ButtonRelease);
|
|
XISetMask(mask.mask, XI_Leave);
|
|
/*XISetMask(mask.mask, XI_KeyPress);
|
|
XISetMask(mask.mask, XI_KeyRelease);
|
|
XISetMask(mask.mask, XI_DeviceChanged);
|
|
XISetMask(mask.mask, XI_RawEvent);
|
|
XISetMask(mask.mask, XI_FocusIn);
|
|
XISetMask(mask.mask, XI_FocusOut);
|
|
XISetMask(mask.mask, XI_HierarchyChanged);*/
|
|
|
|
XISelectEvents( dpy, *win, &mask, 1 );
|
|
}
|
|
|
|
|
|
void fgPrintXILeaveEvent(XILeaveEvent* event)
|
|
{
|
|
char* mode = "";
|
|
char* detail = "";
|
|
int i;
|
|
|
|
printf(" windows: root 0x%lx event 0x%lx child 0x%ld\n",
|
|
event->root, event->event, event->child);
|
|
switch(event->mode)
|
|
{
|
|
case NotifyNormal: mode = "NotifyNormal"; break;
|
|
case NotifyGrab: mode = "NotifyGrab"; break;
|
|
case NotifyUngrab: mode = "NotifyUngrab"; break;
|
|
case NotifyWhileGrabbed: mode = "NotifyWhileGrabbed"; break;
|
|
}
|
|
switch (event->detail)
|
|
{
|
|
case NotifyAncestor: detail = "NotifyAncestor"; break;
|
|
case NotifyVirtual: detail = "NotifyVirtual"; break;
|
|
case NotifyInferior: detail = "NotifyInferior"; break;
|
|
case NotifyNonlinear: detail = "NotifyNonlinear"; break;
|
|
case NotifyNonlinearVirtual: detail = "NotifyNonlinearVirtual"; break;
|
|
case NotifyPointer: detail = "NotifyPointer"; break;
|
|
case NotifyPointerRoot: detail = "NotifyPointerRoot"; break;
|
|
case NotifyDetailNone: detail = "NotifyDetailNone"; break;
|
|
}
|
|
printf(" mode: %s (detail %s)\n", mode, detail);
|
|
printf(" flags: %s %s\n", event->focus ? "[focus]" : "",
|
|
event->same_screen ? "[same screen]" : "");
|
|
printf(" buttons:");
|
|
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",
|
|
event->mods.locked, event->mods.latched,
|
|
event->mods.base);
|
|
printf(" group: locked 0x%x latched 0x%x base 0x%x\n",
|
|
event->group.locked, event->group.latched,
|
|
event->group.base);
|
|
|
|
printf(" root x/y: %.2f / %.2f\n", event->root_x, event->root_y);
|
|
printf(" event x/y: %.2f / %.2f\n", event->event_x, event->event_y);
|
|
|
|
}
|
|
|
|
|
|
void fgPrintXIDeviceEvent(XIDeviceEvent* event)
|
|
{
|
|
double *val;
|
|
int i;
|
|
|
|
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);
|
|
printf("\n");
|
|
|
|
printf(" modifiers: locked 0x%x latched 0x%x base 0x%x\n",
|
|
event->mods.locked, event->mods.latched,
|
|
event->mods.base);
|
|
printf(" group: locked 0x%x latched 0x%x base 0x%x\n",
|
|
event->group.locked, event->group.latched,
|
|
event->group.base);
|
|
printf(" valuators:");
|
|
|
|
val = event->valuators.values;
|
|
for (i = 0; i < event->valuators.mask_len * 8; i++)
|
|
if (XIMaskIsSet(event->valuators.mask, i))
|
|
printf(" %d: %.2f", i, *val++);
|
|
printf("\n");
|
|
|
|
printf(" windows: root 0x%lx event 0x%lx child 0x%ld\n",
|
|
event->root, event->event, event->child);
|
|
printf(" root x/y: %.2f / %.2f\n", event->root_x, event->root_y);
|
|
printf(" event x/y: %.2f / %.2f\n", event->event_x, event->event_y);
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* \brief This function is called when an Extension Event is received
|
|
* and calls the corresponding callback functions for these events.
|
|
*/
|
|
void fgHandleExtensionEvents( XEvent* base_ev ) {
|
|
|
|
int i, button = 0;
|
|
XGenericEventCookie* cookie = (XGenericEventCookie*)&(base_ev->xcookie);
|
|
|
|
if ( XGetEventData( fgDisplay.Display, cookie ) && (cookie->type == GenericEvent) && (cookie->extension == xi_opcode) ) {
|
|
|
|
XIDeviceEvent* event = (XIDeviceEvent*)(cookie->data);
|
|
/*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:
|
|
fgState.Modifiers = fghGetXModifiers( ((XIEnterEvent*)event)->mods.base );
|
|
INVOKE_WCB( *window, MultiEntry, (
|
|
event->deviceid,
|
|
(event->evtype == XI_Enter ? GLUT_ENTERED : GLUT_LEFT)
|
|
));
|
|
#if _DEBUG
|
|
fgPrintXILeaveEvent((XILeaveEvent*)event);
|
|
#endif
|
|
break;
|
|
|
|
case XI_ButtonPress:
|
|
case XI_ButtonRelease:
|
|
fgState.Modifiers = fghGetXModifiers( 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)
|
|
));
|
|
INVOKE_WCB( *window, Mouse, (
|
|
(event->detail)-1,
|
|
(event->evtype == XI_ButtonPress ? GLUT_DOWN : GLUT_UP),
|
|
event->event_x,
|
|
event->event_y
|
|
));
|
|
break;
|
|
|
|
case XI_Motion:
|
|
fgState.Modifiers = fghGetXModifiers( 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 ) );
|
|
INVOKE_WCB( *window, Motion, ( event->event_x, event->event_y ) );
|
|
} else {
|
|
INVOKE_WCB( *window, MultiPassive, ( event->deviceid, event->event_x, event->event_y ) );
|
|
INVOKE_WCB( *window, Passive, ( event->event_x, event->event_y ) );
|
|
}
|
|
#if _DEBUG
|
|
fgPrintXIDeviceEvent(event);
|
|
#endif
|
|
break;
|
|
|
|
default:
|
|
#if _DEBUG
|
|
fgWarning( "Unknown XI2 device event:" );
|
|
fgPrintXIDeviceEvent( event );
|
|
#endif
|
|
break;
|
|
}
|
|
fgState.Modifiers = INVALID_MODIFIERS;
|
|
}
|
|
XFreeEventData( fgDisplay.Display, cookie );
|
|
}
|
|
|
|
#endif
|
|
|