Index: Source/x11/GNUmakefile =================================================================== --- Source/x11/GNUmakefile (revision 31820) +++ Source/x11/GNUmakefile (working copy) @@ -53,6 +53,7 @@ XGServerWindow.m \ XGDragView.m \ XIMInputServer.m \ +XGXI.m \ XWindowBuffer.m\ XGGLFormat.m\ XGGLContext.m Index: Source/x11/XGServerWindow.m =================================================================== --- Source/x11/XGServerWindow.m (revision 31820) +++ Source/x11/XGServerWindow.m (working copy) @@ -1979,6 +1979,16 @@ | VisibilityChangeMask ); +#ifdef USE_XINPUT + { + int n; + for (n = 0; n < _num_xidevs; n++) + { + [_xidevs[n] selectXExtensionEventForWindow:window->ident]; + } + } +#endif + /* * Initial attributes for any GNUstep window tell Window Maker not to * create an app icon for us. Index: Source/x11/XGServer.m =================================================================== --- Source/x11/XGServer.m (revision 31820) +++ Source/x11/XGServer.m (working copy) @@ -68,6 +68,10 @@ #include "x11/XGOpenGL.h" #endif +#ifdef USE_XINPUT +#include "x11/XGXI.h" +#endif + #include #include #include @@ -453,6 +457,60 @@ [self _setupRootWindow]; inputServer = [[XIMInputServer allocWithZone: [self zone]] initWithDelegate: nil display: dpy name: @"XIM"]; + +#ifdef USE_XINPUT + { + int xi_opcode; + int event, error; + + if (!XQueryExtension(dpy, "XInputExtension", &xi_opcode, &event, &error)) { + NSLog(@"X Input extension not available.\n"); + return self; + } + else + { + /* store version FIXME + XExtensionVersion *version; + version = XGetExtensionVersion(dpy, INAME); + */ + } + + int n; + id dev; + + _xidev_info_list = XListInputDevices(dpy, &_num_xidevs); + + _xidevs = malloc(sizeof(void *) * _num_xidevs); + memset(_xidevs, 0, _num_xidevs * sizeof(void *)); + + procXInputEvent = malloc(sizeof(void *) * _num_xidevs); + memset(procXInputEvent, 0, _num_xidevs * sizeof(void *)); + + for (n = 0; n < _num_xidevs; n++) + { + if (_xidev_info_list[n].id != 13) continue; + + dev = [[GSInputDevice alloc] initWithDeviceInfo:&_xidev_info_list[n] + displayServer:self + proximity:YES]; + if (dev) + { + _xidevs[n] = dev; + NSLog(@"add device %@",[dev name]); + /* bleh */ + [dev setScreenSize:NSMakeSize(DisplayWidth(dpy, screen_number),DisplayHeight(dpy, screen_number))]; + procXInputEvent[n] = (BOOL (*)(id, SEL, XEvent*))[dev methodForSelector:@selector(processEvent:)]; + } + else + { + _xidevs[n] = nil; + procXInputEvent[n] = 0; + } + } + + } +#endif + return self; } @@ -478,6 +536,20 @@ - (void) dealloc { NSDebugLog(@"Destroying X11 Server"); +#ifdef USE_XINPUT + XFreeDeviceList(_xidev_info_list); + { + int n; + for (n = 0; n < _num_xidevs; n++) + { + DESTROY(_xidevs[n]); + } + + } + free(_xidevs); + free(procXInputEvent); +#endif + DESTROY(inputServer); [self _destroyServerWindows]; NSFreeMapTable(screenList); Index: Source/x11/XGServerEvent.m =================================================================== --- Source/x11/XGServerEvent.m (revision 31820) +++ Source/x11/XGServerEvent.m (working copy) @@ -59,6 +59,12 @@ #include #include +#if USE_XINPUT +#include +#include "x11/XGXI.h" +#endif + + #if LIB_FOUNDATION_LIBRARY # include #elif defined(NeXT_PDO) @@ -299,6 +305,8 @@ { XNextEvent(dpy, &xEvent); +//NSLog(@"%d", xEvent.type); + #ifdef USE_XIM if (XFilterEvent(&xEvent, None)) { @@ -307,7 +315,24 @@ } #endif +#ifdef USE_XINPUT + { + int n; + for (n = 0; n < _num_xidevs; n++) + { + if (_xidevs[n] && procXInputEvent[n](_xidevs[n], procSel, &xEvent)) + { +// NSLog(@"%@ proceed",[_xidevs[n] name]); + goto processed_xinput_event; + } + } + (*procEvent)(self, procSel, &xEvent); +processed_xinput_event:; + } + +#else (*procEvent)(self, procSel, &xEvent); +#endif } } @@ -2604,3 +2629,28 @@ @end +#ifdef USE_XINPUT address@hidden XGServer (XInput) +- (NSArray *) inputDevices; +- (unsigned int) processModifierFlags:(unsigned int)state; +- (void) sendXInputEvent:(NSEvent *)e; address@hidden + address@hidden XGServer (XInput) +- (unsigned int) processModifierFlags:(unsigned int)state +{ + return process_modifier_flags(state); +} + +- (NSArray *) inputDevices +{ + return [NSArray arrayWithObjects:_xidevs count:_num_xidevs]; +} + +- (void) sendXInputEvent:(NSEvent *)e +{ + [event_queue addObject: e]; +} address@hidden +#endif + Index: Source/x11/XGXI.m =================================================================== --- Source/x11/XGXI.m (revision 0) +++ Source/x11/XGXI.m (revision 0) @@ -0,0 +1,700 @@ +/* + Copyright (C) 2004 Free Software Foundation, Inc. + + Author: Banlu Kemiyatorn + + This file is part of GNUstep. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include "x11/XGServer.h" +#include "x11/XGXI.h" + address@hidden GSInputDevice + +#define GS_XINPUT_DEVICE_INVALID_TYPE -1 + +static int _gsMotionType = GS_XINPUT_DEVICE_INVALID_TYPE; +static int _gsButtonPressType = GS_XINPUT_DEVICE_INVALID_TYPE; +static int _gsButtonReleaseType = GS_XINPUT_DEVICE_INVALID_TYPE; +static int _gsKeyPressType = GS_XINPUT_DEVICE_INVALID_TYPE; +static int _gsKeyReleaseType = GS_XINPUT_DEVICE_INVALID_TYPE; +static int _gsProximityInType = GS_XINPUT_DEVICE_INVALID_TYPE; +static int _gsProximityOutType = GS_XINPUT_DEVICE_INVALID_TYPE; + +- (id) initWithDeviceInfo:(void *)info + displayServer:(GSDisplayServer *)server + proximity:(BOOL)willHandleProximity +{ + XAnyClassPtr any; + XValuatorInfoPtr viptr; + XAxisInfoPtr aiptr; + XButtonInfoPtr biptr; + + + dinfo = (XDeviceInfo *)info; + __server = server; + getState = (unsigned int (*)(id, SEL, unsigned int))[server methodForSelector:@selector(processModifierFlags:)]; + + Display *dpy = [__server xDisplay]; + XInputClassInfo *cinfo; + int n,m; + + xdevice = XOpenDevice(dpy, dinfo->id); + use = dinfo->use; + _name = [[NSString alloc] initWithCString:dinfo->name]; + + + /* FIXME */ + if (!xdevice) + { + RELEASE(self); + return nil; + } + + NSLog(@"initializing %@",_name); + + deviceID = dinfo->id; + + any = (XAnyClassPtr) (dinfo->inputclassinfo); + + for (n=0; n < dinfo->num_classes; n++) + { + switch (any->class) + { + case KeyClass: + break; + case ButtonClass: + biptr = (XButtonInfoPtr) any; + if (buttonStates) + { + NSLog(@"eh... why many button class info?"); + } + else + { + num_buttons = biptr->num_buttons; + buttonStates = malloc(sizeof(gs_input_device_state_t) * num_buttons); + bzero(buttonStates, sizeof(gs_input_device_state_t) * num_buttons); + for (m = 0; m < num_buttons; m++) + { + buttonStates[m].clickTime = 300; + buttonStates[m].clickSlip = 8; + /* FIXME then initialize all neccessary informations */ + } + + } + break; + case ValuatorClass: + viptr = (XValuatorInfoPtr) any; + aiptr = (XAxisInfoPtr) ((char *) viptr + sizeof (XValuatorInfo)); + + /* x y axes */ + area.origin.x = aiptr->min_value; + area.size.width = aiptr->max_value - area.origin.x; + aiptr++; + area.origin.y = aiptr->min_value; + area.size.height = aiptr->max_value - area.origin.y; + /* pressure */ + aiptr++; + pressure.location = aiptr->min_value; + pressure.length = aiptr->max_value - pressure.location; + /* tilt */ + aiptr++; + tiltArea.origin.x = aiptr->min_value; + tiltArea.size.width = aiptr->max_value - tiltArea.origin.x; + aiptr++; + tiltArea.origin.y = aiptr->min_value; + tiltArea.size.height = aiptr->max_value - tiltArea.origin.y; + + break; + default: + break; + } + any = (XAnyClassPtr) ((char *) any + any->length); + } + + for(cinfo = xdevice->classes, n = 0, nevent = 0; n < xdevice->num_classes && nevent < GS_XINPUT_DEVICE_MAX_CLASSES; n++,cinfo++) + { + switch (cinfo->input_class) + { + case KeyClass: + NSLog(@"KeyClass"); + DeviceKeyPress(xdevice, _gsKeyPressType, eventList[nevent]); + nevent++; + + DeviceButtonPressGrab(xdevice, 0, eventList[nevent]); + nevent++; + + DeviceKeyRelease(xdevice, _gsKeyReleaseType, eventList[nevent]); + nevent++; + break; + case ButtonClass: + NSLog(@"ButtonClass"); + DeviceButtonPress(xdevice, _gsButtonPressType, eventList[nevent]); + nevent++; + DeviceButtonRelease(xdevice, _gsButtonReleaseType, eventList[nevent]); + nevent++; + break; + case ValuatorClass: + NSLog(@"ValuatorClass"); + DeviceMotionNotify(xdevice, _gsMotionType, eventList[nevent]); + nevent++; + break; + case FeedbackClass: + NSLog(@"FeedbackClass"); + break; + case ProximityClass: + NSLog(@"ProximityClass"); + if (willHandleProximity) + { + _handleProx = YES; + ProximityIn(xdevice, _gsProximityInType, eventList[nevent]); + nevent++; + ProximityOut(xdevice, _gsProximityOutType, eventList[nevent]); + nevent++; + } + break; + case FocusClass: + NSLog(@"FocusClass"); + break; + case OtherClass: + NSLog(@"OtherClass"); + break; + default: + NSLog(@"Unknown XInput class %x",cinfo->input_class); + } + } + + + NSLog(@"..registered %d events",nevent); + return self; +} + +- (void) dealloc +{ + RELEASE(_name); + if (xdevice) + { + XCloseDevice([__server xDisplay],xdevice); + } + if (buttonStates) + { + free(buttonStates); + } + [super dealloc]; +} + +- (void) selectXExtensionEventForWindow:(Window)win +{ + Display *dpy = [__server xDisplay]; + if (XSelectExtensionEvent(dpy, win, eventList, nevent)) + { + NSLog(@"Cannot select extended events for win %d.",win); + } + else NSLog(@"window %d enable> %@",win,_name); +} + +- (NSString *) description +{ + return [NSString stringWithFormat:@"%d : %@ frame:%@ pressure:%@ tilt:%@",[self deviceID],[self name],NSStringFromRect(area),NSStringFromRange(pressure),NSStringFromRect(tiltArea)]; +} + +- (int) deviceID +{ + return xdevice->device_id; +} + +- (NSString *) name +{ + return _name; +} + +- (BOOL) isExtensionDevice +{ + return (use == IsXExtensionDevice); +} + +- (BOOL) isPointer +{ + return (use == IsXPointer); +} + +- (BOOL) isKeyboard +{ + return (use == IsXKeyboard); +} + +- (BOOL) hasButton +{ +} + +- (int) numberOfButtons +{ +} + +- (BOOL) hasKey +{ +} + +- (int) numberOfKeys +{ +} + +- (int) minKeycode +{ +} + +- (int) maxKeycode +{ +} + +- (void) setHandleProximity:(BOOL)prox +{ + _handleProx = prox; +} + +- (BOOL) willHandleProximity +{ + return _handleProx; +} + + +- (BOOL) hasAxis +{ +} + +- (int) numberOfAxes +{ +} + +- (BOOL) isRelative +{ +} + +- (int) motionBuffer +{ +} + +- (int) minValueForAxis:(int)axis +{ +} + +- (int) maxValueForAxis:(int)axis +{ +} + +- (int) resolutionForAxis:(int)axis +{ +} + +- (void) setScreenSize:(NSSize)size +{ + screenSize = size; + resV = NSHeight(area)/screenSize.height; + resH = NSWidth(area)/screenSize.width; +} + +- (NSSize) screenSize +{ + return screenSize; +} + +- (BOOL) processEvent:(XEvent *) event +{ + unsigned int state; + unsigned int eventFlags = 0; + NSEventType eventType; + NSPoint eventLocation; + float press; + NSEvent *nsevent; + float deltaX,deltaY; + NSGraphicsContext *context; + context = GSCurrentContext(); + +#define MOTIONSTATES buttonStates[motion->button] +#define BUTTONSTATES buttonStates[button->button] + + /** DEVICE MOTION **/ + if (event->type == _gsMotionType) + { + + XDeviceMotionEvent *motion = (XDeviceMotionEvent *)event; + + if (motion->deviceid != deviceID) + { + return NO; + } + + if (gswindow == 0 || lastWindow != motion->window) + { + gswindow = [XGServer _windowForXWindow:motion->window]; + } + + if (gswindow == 0) + { + return YES; + } + + state = motion->state; + lastMotionTime = motion->time; + + if (state & Button1Mask) + { + eventType = NSLeftMouseDragged; + } + else if (state & Button2Mask) + { + eventType = NSRightMouseDragged; + } + else if (state & Button3Mask) + { + eventType = NSOtherMouseDragged; + } + else + { + eventType = NSMouseMoved; + } + + if (state & ShiftMask) + { + eventFlags = NSShiftKeyMask; + } + if (state & LockMask) + { + eventFlags |= NSAlphaShiftKeyMask; + } + if (state & ControlMask) + { + eventFlags |= NSControlKeyMask; + } + if (state & Mod1Mask) + { + eventFlags |= NSAlternateKeyMask; + } + + eventLocation.x = (float)motion->axis_data[0]/resH - NSMinX(gswindow->xframe); + eventLocation.y = (screenSize.height - (float)motion->axis_data[1]/resV) - (screenSize.height - (motion->y_root - motion->y + NSHeight(gswindow->xframe))); + + deltaX = - eventLocation.x; + deltaY = - eventLocation.y; + eventLocation = NSMakePoint(motion->x, + NSHeight(gswindow->xframe) - motion->y); + deltaX += eventLocation.x; + deltaY += eventLocation.y; + + press = (float)motion->axis_data[2]; + /* a work-around to solve some problem drivers */ + if (press > pressure.length + pressure.location) + { + pressure.location += press - (pressure.length + pressure.location); + } + else if (press < pressure.location) + { + pressure.location = press; + } + press = (press - pressure.location)/pressure.length; + + nsevent = [NSEvent mouseEventWithType: eventType + location: eventLocation + modifierFlags: eventFlags + timestamp: motion->time + windowNumber: gswindow->number + context: context + eventNumber: motion->serial + clickCount: clickCount + pressure: press + buttonNumber: 0 + deltaX: eventLocation.x - lastLocation.x + deltaY: eventLocation.y - lastLocation.y + deltaZ: press - lastPressure]; + + lastLocation = eventLocation; + lastPressure = press; + + [__server sendXInputEvent:nsevent]; + + return YES; + } + else if (event->type == MotionNotify && lastMotionTime == event->xmotion.time) + { + /* filter a consequence motion event */ + return YES; + } + /** DEVICE PRESS **/ + else if (event->type == _gsButtonPressType) + { + /* + NSLog(@"Tablet Button Press"); + */ + + XDeviceButtonEvent *button = (XDeviceButtonEvent *)event; + + if (button->deviceid != deviceID) + { + return NO; + } + + /* FIXME add a way to destroy lastWindow value */ + if (gswindow == 0 || lastWindow != button->window) + { + gswindow = [XGServer _windowForXWindow:button->window]; + } + + if (gswindow == 0) + { + /* simply ignore the event and for the rest + * if receiving window isn't found. + */ + return YES; + } + + state = button->state; + lastButtonTime = button->time; + + /* convert point from device's geometry to the receiving window */ + eventLocation.x = (float)button->axis_data[0]/resH - NSMinX(gswindow->xframe); + eventLocation.y = (screenSize.height - (float)button->axis_data[1]/resV) - (screenSize.height - (button->y_root - button->y + NSHeight(gswindow->xframe))); + deltaX = - eventLocation.x; + deltaY = - eventLocation.y; + eventLocation = NSMakePoint(button->x, + NSHeight(gswindow->xframe) - button->y); + deltaX += eventLocation.x; + deltaY += eventLocation.y; + + + if (button->time >= BUTTONSTATES.lastClick + BUTTONSTATES.clickTime) + { + clickCount = 1; + } + else if (button->window != BUTTONSTATES.lastClickWindow) + { + clickCount = 1; + } + else if ( + fabsf(BUTTONSTATES.lastClickPoint.x - eventLocation.x) + < BUTTONSTATES.clickSlip && + fabsf(BUTTONSTATES.lastClickPoint.y - eventLocation.y) + < BUTTONSTATES.clickSlip) + { + clickCount++; + } + + BUTTONSTATES.lastClick = button->time; + BUTTONSTATES.lastClickWindow = button->window; + BUTTONSTATES.lastClickPoint = eventLocation; + + if (button->button == 1) + { + eventType = NSLeftMouseDown; + } + else if (button->button == 3) + { + eventType = NSRightMouseDown; + } + else + { + eventType = NSOtherMouseDown; + } + + if (state & ShiftMask) + { + eventFlags = NSShiftKeyMask; + } + if (state & LockMask) + { + eventFlags |= NSAlphaShiftKeyMask; + } + if (state & ControlMask) + { + eventFlags |= NSControlKeyMask; + } + if (state & Mod1Mask) + { + eventFlags |= NSAlternateKeyMask; + } + + press = (float)button->axis_data[2]; + /* a work-around to solve some problem drivers */ + if (press > pressure.length + pressure.location) + { + pressure.location += press - (pressure.length + pressure.location); + } + else if (press < pressure.location) + { + pressure.location = press; + } + press = (press - pressure.location)/pressure.length; + + nsevent = [NSEvent mouseEventWithType: eventType + location: eventLocation + modifierFlags: eventFlags + timestamp: button->time + windowNumber: gswindow->number + context: context + eventNumber: button->serial + clickCount: clickCount + pressure: press + buttonNumber: 0 + deltaX: eventLocation.x - lastLocation.x + deltaY: eventLocation.y - lastLocation.y + deltaZ: press - lastPressure]; + + lastLocation = eventLocation; + lastPressure = press; + + [__server sendXInputEvent:nsevent]; + + return YES; + } + else if (event->type == ButtonPress && lastButtonTime == event->xbutton.time) + { + /* filter a consequence button press event */ + return YES; + } + /** DEVICE RELEASE **/ + else if (event->type == _gsButtonReleaseType) + { + /* + NSLog(@"Tablet Button Release"); + */ + + XDeviceButtonEvent *button = (XDeviceButtonEvent *)event; + + if (button->deviceid != deviceID) + { + return NO; + } + + if (gswindow == 0 || lastWindow != button->window) + { + gswindow = [XGServer _windowForXWindow:button->window]; + } + + if (gswindow == 0) + { + /* ignore */ + return YES; + } + + state = button->state; + lastButtonTime = button->time; + + eventLocation.x = (float)button->axis_data[0]/resH - NSMinX(gswindow->xframe); + eventLocation.y = (screenSize.height - (float)button->axis_data[1]/resV) - (screenSize.height - (button->y_root - button->y + NSHeight(gswindow->xframe))); + deltaX = - eventLocation.x; + deltaY = - eventLocation.y; + eventLocation = NSMakePoint(button->x, + NSHeight(gswindow->xframe) - button->y); + deltaX += eventLocation.x; + deltaY += eventLocation.y; + + if (button->button == 1) + { + eventType = NSLeftMouseUp; + } + else if (button->button == 3) + { + eventType = NSRightMouseUp; + } + else + { + eventType = NSOtherMouseUp; + } + + if (state & ShiftMask) + { + eventFlags = NSShiftKeyMask; + } + if (state & LockMask) + { + eventFlags |= NSAlphaShiftKeyMask; + } + if (state & ControlMask) + { + eventFlags |= NSControlKeyMask; + } + if (state & Mod1Mask) + { + eventFlags |= NSAlternateKeyMask; + } + + + press = (float)button->axis_data[2]; + if (press > pressure.length + pressure.location) + { + pressure.location += press - (pressure.length + pressure.location); + } + else if (press < pressure.location) + { + pressure.location = press; + } + press = (press - pressure.location)/pressure.length; + + nsevent = [NSEvent mouseEventWithType: eventType + location: eventLocation + modifierFlags: eventFlags + timestamp: button->time + windowNumber: gswindow->number + context: context + eventNumber: button->serial + clickCount: clickCount + pressure: press + buttonNumber: 0 + deltaX: eventLocation.x - lastLocation.x + deltaY: eventLocation.y - lastLocation.y + deltaZ: press - lastPressure]; + + lastLocation = eventLocation; + lastPressure = press; + + [__server sendXInputEvent:nsevent]; + + return YES; + } + else if (event->type == ButtonRelease && lastButtonTime == event->xbutton.time) + { + /* filter a consequence button release event */ + return YES; + } +#if 0 + else if (event->type == _gsKeyPressType) + { + return NO; + } + else if (event->type == _gsKeyReleaseType) + { + return; + } +#endif + else if (event->type == _gsProximityInType) + { + XProximityInEvent *prox = (XProximityInEvent *)event; + NSLog(@"Device %d Prox In",prox->deviceid); + return YES; + } + else if (event->type == _gsProximityOutType) + { + XProximityOutEvent *prox = (XProximityOutEvent *)event; + NSLog(@"Device %d Prox Out",prox->deviceid); + return YES; + } + else + return NO; +} address@hidden + + Index: config.h.in =================================================================== --- config.h.in (revision 31820) +++ config.h.in (working copy) @@ -126,6 +126,9 @@ /* Define to enable XIM support */ #undef USE_XIM +/* Define to enable XInput support */ +#undef USE_XINPUT + /* Define if you have X11 XRender extension */ #undef XRENDER Index: configure.ac =================================================================== --- configure.ac (revision 31820) +++ configure.ac (working copy) @@ -285,6 +285,21 @@ fi #-------------------------------------------------------------------- +# XInput support +#-------------------------------------------------------------------- +AC_ARG_ENABLE(xinput, + [ --disable-xinput Disable XInput support],, + enable_xinput=yes) + +PKG_XI=no +PKG_CHECK_MODULES(XI, xi, have_xi=yes, have_xi=no) + +if test "x$enable_xinput" = "xyes"; then + XI_LIBS="-lXi" + AC_DEFINE(USE_XINPUT,1,[Define to enable XInput support]) +fi + +#-------------------------------------------------------------------- # Functions #-------------------------------------------------------------------- AC_HAVE_FUNCS(usleep) @@ -594,6 +609,9 @@ if test "$ac_cv_lib_Xext" = no; then AC_MSG_ERROR([libXext not found - required for building x11 server]) fi + if test "x$enable_xinput" = "xyes"; then + LIBS="$LIBS $XI_LIBS" + fi if test "x$WITH_GLX" = "xyes"; then LIBS="$LIBS $GLX_LIBS" CPPFLAGS="$CPPFLAGS $GLX_CFLAGS" Index: Headers/x11/XGXI.h =================================================================== --- Headers/x11/XGXI.h (revision 0) +++ Headers/x11/XGXI.h (revision 0) @@ -0,0 +1,134 @@ +/* + Copyright (C) 2004 Free Software Foundation, Inc. + + Author: Banlu Kemiyatorn + + This file is part of GNUstep. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef XGXI_h +#define XGXI_h + +#include +#include +#include +#include "config.h" +#include "x11/XGServerWindow.h" + +#define GS_XINPUT_DEVICE_MAX_CLASSES 13 + +typedef struct _gs_input_device_state_t +{ + Time lastClick; + NSPoint lastClickPoint; + Window lastClickWindow; + + Time clickTime; + float clickSlip; +} gs_input_device_state_t; + address@hidden XGServer; + address@hidden GSInputDevice : NSObject +{ address@hidden + int num_buttons; + gs_input_device_state_t *buttonStates; + + /* generic time */ + Time lastButtonTime; + Time lastMotionTime; + NSPoint lastLocation; + + int clickCount; + address@hidden + BOOL _isEnable; + + XGServer *__server; + unsigned int (*getState)(id, SEL, unsigned int); + Window lastWindow; + gswindow_device_t *gswindow; + + BOOL _handleProx; + + NSSize screenSize; + + NSRect area; + NSRect tiltArea; + NSRange pressure; + + float lastPressure; + + float resV,resH; + + NSString *_name; + int use; + XID deviceID; + XDeviceInfo *dinfo; + XDevice *xdevice; + XEventClass eventList[GS_XINPUT_DEVICE_MAX_CLASSES]; + int nevent; +} + +- (id) initWithDeviceInfo:(void *)info + displayServer:(GSDisplayServer *)server + proximity:(BOOL)willHandleProximity; +- (NSString *) description; +- (int) deviceID; +- (NSString *) name; +- (BOOL) isExtensionDevice; +- (BOOL) isPointer; +- (BOOL) isKeyboard; +- (BOOL) hasButton; +- (int) numberOfButtons; +- (BOOL) hasKey; +- (int) numberOfKeys; +- (int) minKeycode; +- (int) maxKeycode; +- (void) setHandleProximity:(BOOL)prox; +- (BOOL) willHandleProximity; +- (BOOL) hasAxis; +- (int) numberOfAxes; +- (BOOL) isRelative; +- (int) motionBuffer; +- (int) minValueForAxis:(int)axis; +- (int) maxValueForAxis:(int)axis; +- (int) resolutionForAxis:(int)axis; +- (BOOL) isEnable; +- (void) setEnable:(BOOL)enable; + +- (void) setScreenSize:(NSSize)size; +- (NSSize) screenSize; + +- (Time) lastClick; +- (Time) lastTime; address@hidden + address@hidden GSInputDevice (XInput) +- (void) selectXExtensionEventForWindow:(Window)win; +- (NSEvent*) mouseEventForXDeviceMotionEvent: (XDeviceMotionEvent *)motion + modifierFlags: (unsigned int)flags + windowDevice: (gswindow_device_t *)gswindow + context: (NSGraphicsContext*)context + clickCount: (int)clickNum + buttonNumber: (int)buttonNum; address@hidden + + +#endif + Index: Headers/x11/XGServer.h =================================================================== --- Headers/x11/XGServer.h (revision 31820) +++ Headers/x11/XGServer.h (working copy) @@ -35,6 +35,11 @@ #include #include "x11/XGGeneric.h" +#ifdef USE_XINPUT +#include address@hidden GSInputDevice; +#endif + /* * Enumerated type to say how we should draw pixels to the X display - used * to select different drawing mechanisms to try to optimise. @@ -56,6 +61,12 @@ Window grabWindow; struct XGGeneric generic; id inputServer; +#ifdef USE_XINPUT + XDeviceInfo *_xidev_info_list; + int _num_xidevs; + GSInputDevice **_xidevs; + BOOL (**procXInputEvent)(id, SEL, XEvent *); +#endif } + (Display*) currentXDisplay;