From 4b7d3bbe7cff255375de3aea4f358fd19725c1c9 Mon Sep 17 00:00:00 2001 From: David Reveman Date: Wed, 30 Jul 2008 15:54:17 -0400 Subject: [PATCH] Add initial pointer grab support. Passive pointer grabs are currently disabled. --- hw/dmx/dmxcursor.c | 15 ++ hw/dmx/dmxcursor.h | 3 +- hw/dmx/dmxextension.c | 30 ++- hw/dmx/dmxgrab.c | 389 +++++++++++++++++++++++++++++++----- hw/dmx/dmxgrab.h | 11 + hw/dmx/dmxinput.h | 38 ++++ hw/dmx/dmxscrinit.c | 2 + hw/dmx/input/dmxbackend.c | 183 ++++++++++++++++- hw/dmx/input/dmxbackend.h | 18 ++ hw/dmx/input/dmxcommon.c | 49 +++-- hw/dmx/input/dmxinputinit.c | 201 ++++++++++++++++--- hw/dmx/input/dmxinputinit.h | 23 +++ 12 files changed, 847 insertions(+), 115 deletions(-) diff --git a/hw/dmx/dmxcursor.c b/hw/dmx/dmxcursor.c index 2f71057cc..8a46132c1 100644 --- a/hw/dmx/dmxcursor.c +++ b/hw/dmx/dmxcursor.c @@ -84,6 +84,7 @@ #include "dmxlog.h" #include "dmxprop.h" #include "dmxinput.h" +#include "dmxgrab.h" #include "mipointer.h" #include "windowstr.h" @@ -117,6 +118,9 @@ Bool dmxInitCursor(ScreenPtr pScreen) if (!dixRequestPrivate(pScreen, sizeof(dmxCursorPrivRec))) return FALSE; + if (!dixRequestPrivate (dmxDevicePrivateKey, sizeof(dmxDevicePrivRec))) + return FALSE; + return TRUE; } @@ -804,11 +808,22 @@ dmxSetCursor (DeviceIntPtr pDev, static Bool dmxDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScr) { + dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDev); + + DMX_WRAP (ActivateGrab, dmxActivatePointerGrab, pDevPriv, + &pDev->deviceGrab); + DMX_WRAP (DeactivateGrab, dmxDeactivatePointerGrab, pDevPriv, + &pDev->deviceGrab); + return TRUE; } static void dmxDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScr) { + dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDev); + + DMX_UNWRAP (ActivateGrab, pDevPriv, &pDev->deviceGrab); + DMX_UNWRAP (DeactivateGrab, pDevPriv, &pDev->deviceGrab); } miPointerSpriteFuncRec dmxPointerSpriteFuncs = diff --git a/hw/dmx/dmxcursor.h b/hw/dmx/dmxcursor.h index ae3676a4e..8132b1e7b 100644 --- a/hw/dmx/dmxcursor.h +++ b/hw/dmx/dmxcursor.h @@ -61,6 +61,7 @@ extern void dmxBECreateCursor(ScreenPtr pScreen, CursorPtr pCursor); extern Bool dmxBEFreeCursor(ScreenPtr pScreen, CursorPtr pCursor); #define DMX_GET_CURSOR_PRIV(_pCursor, _pScreen) ((dmxCursorPrivPtr) \ - dixLookupPrivate(&(_pCursor)->devPrivates, CursorScreenKey(_pScreen))) + ((dmxCursorPrivPtr)dixLookupPrivate(&(_pCursor)->devPrivates, \ + CursorScreenKey(_pScreen)))) #endif /* DMXCURSOR_H */ diff --git a/hw/dmx/dmxextension.c b/hw/dmx/dmxextension.c index 424268d74..bb1b3cd16 100644 --- a/hw/dmx/dmxextension.c +++ b/hw/dmx/dmxextension.c @@ -58,6 +58,7 @@ #include "dmxrandr.h" #endif #include "dmxinput.h" +#include "dmxgrab.h" #include "dmxsync.h" #include "dmxscrinit.h" #include "input/dmxinputinit.h" @@ -71,6 +72,10 @@ #include "cursorstr.h" #include "propertyst.h" +#ifdef PANORAMIX +#include "panoramiXsrv.h" +#endif + #define dmxErrorSet(set, error, name, fmt, ...) \ if (set) (*set) (error, name, fmt, ##__VA_ARGS__) @@ -324,6 +329,14 @@ static void dmxAdjustCursorBoundaries(void) } } +static void dmxBERestorePassiveGrab(pointer value, XID id, pointer closure) +{ + DMXInputInfo *dmxInput = (DMXInputInfo *) closure; + GrabPtr pGrab = value; + + dmxBEAddPassiveGrab (dmxInput, pGrab); +} + /** Add an input with the specified attributes. If the input is added, * the physical id is returned in \a deviceId. */ int dmxAddInput(DMXInputAttributesPtr attr, int *id) @@ -340,6 +353,21 @@ int dmxAddInput(DMXInputAttributesPtr attr, int *id) /* Adjust the cursor boundaries */ dmxAdjustCursorBoundaries(); + if (attr->inputType == 2) + { + int i, j; + + for (i = 0; i < dmxNumInputs; i++) + if (attr->physicalScreen == dmxInputs[i].scrnIdx) + break; + + for (j = currentMaxClients; --j >= 0; ) + if (clients[j]) + FindClientResourcesByType(clients[j], RT_PASSIVEGRAB, + dmxBERestorePassiveGrab, + (pointer) &dmxInputs[i]); + } + /* Force completion of the changes */ dmxSync(NULL, TRUE); } @@ -454,8 +482,6 @@ void dmxUpdateScreenResources(ScreenPtr pScreen, int x, int y, int w, int h) } #ifdef PANORAMIX -#include "panoramiXsrv.h" - /** Change the "screen" window attributes by resizing the actual window * on the back-end display (if necessary). */ static void dmxConfigureScreenWindow(int idx, diff --git a/hw/dmx/dmxgrab.c b/hw/dmx/dmxgrab.c index 78064dcc5..c2bcf3615 100644 --- a/hw/dmx/dmxgrab.c +++ b/hw/dmx/dmxgrab.c @@ -28,113 +28,392 @@ #endif #include "dmx.h" +#include "dmxinput.h" #include "dmxgrab.h" +#include "windowstr.h" + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +unsigned long DMX_PASSIVEGRAB; + static int (*dmxSaveProcVector[256]) (ClientPtr); -static int -dmxProcGrabPointer (ClientPtr client) +void +dmxBEAddPassiveGrab (DMXInputInfo *dmxInput, + GrabPtr pGrab) { - int err; - REQUEST(xGrabPointerReq); + WindowPtr pWin = pGrab->window; + WindowPtr pConfineTo = pGrab->confineTo; - (void) stuff; + if (dixLookupResource ((pointer *) &pGrab, + pGrab->resource, + DMX_PASSIVEGRAB, + serverClient, + DixReadAccess) != Success) + return; - err = (*dmxSaveProcVector[X_GrabPointer]) (client); - if (err != Success) - return err; +#ifdef PANORAMIX + if (!noPanoramiXExtension) + { + PanoramiXRes *win, *confineToWin; - return err; + if (!(win = (PanoramiXRes *)SecurityLookupIDByType( + serverClient, pWin->drawable.id, XRT_WINDOW, + DixGetAttrAccess)) || + dixLookupWindow (&pWin, + win->info[dmxInput->scrnIdx].id, + serverClient, + DixGetAttrAccess) != Success) + return; + + if (pGrab->confineTo) + if (!(confineToWin = (PanoramiXRes *)SecurityLookupIDByType( + serverClient, pGrab->confineTo->drawable.id, XRT_WINDOW, + DixGetAttrAccess)) || + dixLookupWindow (&pConfineTo, + confineToWin->info[dmxInput->scrnIdx].id, + serverClient, + DixGetAttrAccess) != Success) + return; + } + else +#endif + if (dmxInput->scrnIdx != pWin->drawable.pScreen->myNum) + return; + + (*dmxInput->grabButton) (dmxInput, + pGrab->device, + pGrab->modifierDevice, + pWin, + pConfineTo, + pGrab->detail.exact, + pGrab->modifiersDetail.exact, + pGrab->cursor); } static int -dmxProcUngrabPointer (ClientPtr client) +dmxFreePassiveGrab (pointer value, + XID id) { - int err; - REQUEST(xResourceReq); + GrabPtr pGrab = (GrabPtr) value; - (void) stuff; +#ifdef PANORAMIX + PanoramiXRes *win = NULL; +#endif - err = (*dmxSaveProcVector[X_UngrabPointer]) (client); - if (err != Success) - return err; + WindowPtr pWin = pGrab->window; + int i; - return err; +#ifdef PANORAMIX + if (!noPanoramiXExtension) + { + if (!(win = (PanoramiXRes *)SecurityLookupIDByType( + serverClient, pWin->drawable.id, XRT_WINDOW, + DixGetAttrAccess))) + return Success; + } +#endif + + for (i = 0; i < dmxNumInputs; i++) + { + DMXInputInfo *dmxInput = &dmxInputs[i]; + + if (dmxInput->detached) + continue; + + if (dmxInput->scrnIdx < 0) + continue; + + if (!dmxInput->ungrabButton) + continue; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) + dixLookupWindow (&pWin, + win->info[dmxInput->scrnIdx].id, + serverClient, + DixGetAttrAccess); + else +#endif + if (dmxInput->scrnIdx != pWin->drawable.pScreen->myNum) + continue; + + (*dmxInput->ungrabButton) (dmxInput, + pGrab->device, + pGrab->modifierDevice, + pWin, + pGrab->detail.exact, + pGrab->modifiersDetail.exact); + } + + return Success; +} + +static void +dmxGrabPointer (DeviceIntPtr pDev, + GrabPtr pGrab) +{ + +#ifdef PANORAMIX + PanoramiXRes *win = NULL, *confineToWin = NULL; +#endif + + WindowPtr pWin, pConfineTo = NULL; + int i; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) + { + if (!(win = (PanoramiXRes *)SecurityLookupIDByType( + serverClient, pGrab->window->drawable.id, XRT_WINDOW, + DixGetAttrAccess))) + return; + if (pGrab->confineTo) + if (!(confineToWin = (PanoramiXRes *)SecurityLookupIDByType( + serverClient, pGrab->confineTo->drawable.id, + XRT_WINDOW, DixGetAttrAccess))) + return; + } +#endif + + for (i = 0; i < dmxNumInputs; i++) + { + DMXInputInfo *dmxInput = &dmxInputs[i]; + + if (dmxInput->detached) + continue; + + if (dmxInput->scrnIdx < 0) + continue; + + if (!dmxInput->grabPointer) + continue; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) + { + dixLookupWindow (&pWin, + win->info[dmxInput->scrnIdx].id, + serverClient, + DixGetAttrAccess); + if (confineToWin) + dixLookupWindow (&pConfineTo, + confineToWin->info[dmxInput->scrnIdx].id, + serverClient, + DixGetAttrAccess); + } + else +#endif + if (dmxInput->scrnIdx != pWin->drawable.pScreen->myNum) + continue; + + (*dmxInput->grabPointer) (dmxInput, + pDev, + pWin, + pConfineTo, + pGrab->cursor); + } +} + +static void +dmxUngrabPointer (DeviceIntPtr pDev, + GrabPtr pGrab) +{ + +#ifdef PANORAMIX + PanoramiXRes *win = NULL; +#endif + + WindowPtr pWin; + int i; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) + { + if (!(win = (PanoramiXRes *)SecurityLookupIDByType( + serverClient, pGrab->window->drawable.id, XRT_WINDOW, + DixGetAttrAccess))) + return; + } +#endif + + for (i = 0; i < dmxNumInputs; i++) + { + DMXInputInfo *dmxInput = &dmxInputs[i]; + + if (dmxInput->detached) + continue; + + if (dmxInput->scrnIdx < 0) + continue; + + if (!dmxInput->ungrabPointer) + continue; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) + { + dixLookupWindow (&pWin, + win->info[dmxInput->scrnIdx].id, + serverClient, + DixGetAttrAccess); + } + else +#endif + if (dmxInput->scrnIdx != pWin->drawable.pScreen->myNum) + continue; + + (*dmxInput->ungrabPointer) (dmxInput, pDev, pWin); + } +} + +void +dmxActivatePointerGrab (DeviceIntPtr pDev, + GrabPtr pGrab, + TimeStamp time, + Bool autoGrab) +{ + dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDev); + + dmxGrabPointer (pDev, pGrab); + + DMX_UNWRAP (ActivateGrab, pDevPriv, &pDev->deviceGrab); + (*pDev->deviceGrab.ActivateGrab) (pDev, pGrab, time, autoGrab); + DMX_WRAP (ActivateGrab, dmxActivatePointerGrab, pDevPriv, + &pDev->deviceGrab); +} + +void +dmxDeactivatePointerGrab (DeviceIntPtr pDev) +{ + dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDev); + GrabPtr pGrab = pDev->deviceGrab.grab; + + DMX_UNWRAP (DeactivateGrab, pDevPriv, &pDev->deviceGrab); + (*pDev->deviceGrab.DeactivateGrab) (pDev); + DMX_WRAP (DeactivateGrab, dmxDeactivatePointerGrab, pDevPriv, + &pDev->deviceGrab); + + dmxUngrabPointer (pDev, pGrab); } static int dmxProcGrabButton (ClientPtr client) { - int err; - REQUEST(xGrabButtonReq); + GrabPtr pGrab; - (void) stuff; +#ifdef PANORAMIX + PanoramiXRes *win = NULL, *confineToWin = NULL; +#endif + + WindowPtr pWin, pConfineTo = NULL; + int i, err; + REQUEST(xGrabButtonReq); err = (*dmxSaveProcVector[X_GrabButton]) (client); if (err != Success) return err; - return err; -} + return Success; /* PASSIVE GRABS DISABLED */ -static int -dmxProcUngrabButton (ClientPtr client) -{ - int err; - REQUEST(xUngrabButtonReq); + dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess); + pGrab = wPassiveGrabs (pWin); - (void) stuff; + pConfineTo = pGrab->confineTo; - err = (*dmxSaveProcVector[X_UngrabButton]) (client); - if (err != Success) - return err; +#ifdef PANORAMIX + if (!noPanoramiXExtension) + { + if (!(win = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->grabWindow, XRT_WINDOW, DixSetAttrAccess))) + return Success; + if (pConfineTo) + if (!(confineToWin = (PanoramiXRes *)SecurityLookupIDByType( + client, stuff->confineTo, XRT_WINDOW, DixSetAttrAccess))) + return Success; + } +#endif - return err; + for (i = 0; i < dmxNumInputs; i++) + { + DMXInputInfo *dmxInput = &dmxInputs[i]; + + if (dmxInput->detached) + continue; + + if (dmxInput->scrnIdx < 0) + continue; + + if (!dmxInput->grabButton) + continue; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) + { + dixLookupWindow (&pWin, + win->info[dmxInput->scrnIdx].id, + client, + DixSetAttrAccess); + if (confineToWin) + dixLookupWindow (&pConfineTo, + confineToWin->info[dmxInput->scrnIdx].id, + client, + DixSetAttrAccess); + } + else +#endif + if (dmxInput->scrnIdx != pWin->drawable.pScreen->myNum) + continue; + + (*dmxInput->grabButton) (dmxInput, + pGrab->device, + pGrab->modifierDevice, + pWin, + pConfineTo, + pGrab->detail.exact, + pGrab->modifiersDetail.exact, + pGrab->cursor); + } + + AddResource (pGrab->resource, DMX_PASSIVEGRAB, pGrab); + + return Success; } static int dmxProcChangeActivePointerGrab (ClientPtr client) { - int err; - REQUEST(xChangeActivePointerGrabReq); - - (void) stuff; + DeviceIntPtr pDev; + GrabPtr pGrab; + int err; err = (*dmxSaveProcVector[X_ChangeActivePointerGrab]) (client); if (err != Success) return err; - return err; -} + pDev = PickPointer (client); + pGrab = pDev->deviceGrab.grab; + if (pGrab) + dmxGrabPointer (pDev, pGrab); -static int -dmxProcAllowEvents (ClientPtr client) -{ - int err; - REQUEST(xAllowEventsReq); - - (void) stuff; - - err = (*dmxSaveProcVector[X_AllowEvents]) (client); - if (err != Success) - return err; - - return err; + return Success; } void dmxInitGrabs (void) { int i; + DMX_PASSIVEGRAB = CreateNewResourceType (dmxFreePassiveGrab); + for (i = 0; i < 256; i++) dmxSaveProcVector[i] = ProcVector[i]; - ProcVector[X_GrabPointer] = dmxProcGrabPointer; - ProcVector[X_UngrabPointer] = dmxProcUngrabPointer; ProcVector[X_GrabButton] = dmxProcGrabButton; - ProcVector[X_UngrabButton] = dmxProcUngrabButton; ProcVector[X_ChangeActivePointerGrab] = dmxProcChangeActivePointerGrab; - ProcVector[X_AllowEvents] = dmxProcAllowEvents; } void dmxResetGrabs (void) diff --git a/hw/dmx/dmxgrab.h b/hw/dmx/dmxgrab.h index 20fa20638..4a2f96c3c 100644 --- a/hw/dmx/dmxgrab.h +++ b/hw/dmx/dmxgrab.h @@ -26,6 +26,17 @@ #ifndef DMXGRAB_H #define DMXGRAB_H +#include "dmxinput.h" + +extern void dmxBEAddPassiveGrab (DMXInputInfo *dmxInput, + GrabPtr pGrab); + +extern void dmxActivatePointerGrab (DeviceIntPtr pDev, + GrabPtr pGrab, + TimeStamp time, + Bool autoGrab); +extern void dmxDeactivatePointerGrab (DeviceIntPtr pDev); + extern void dmxInitGrabs (void); extern void dmxResetGrabs (void); diff --git a/hw/dmx/dmxinput.h b/hw/dmx/dmxinput.h index 6bf067098..c7c59cc25 100644 --- a/hw/dmx/dmxinput.h +++ b/hw/dmx/dmxinput.h @@ -47,6 +47,18 @@ #ifndef DMXINPUT_H #define DMXINPUT_H +extern DevPrivateKey dmxDevicePrivateKey; + +/** Device private area. */ +typedef struct _dmxDevicePriv { + void (*ActivateGrab) (DeviceIntPtr, GrabPtr, TimeStamp, Bool); + void (*DeactivateGrab) (DeviceIntPtr); +} dmxDevicePrivRec, *dmxDevicePrivPtr; + +#define DMX_GET_DEVICE_PRIV(_pDev) \ + ((dmxDevicePrivPtr)dixLookupPrivate(&(_pDev)->devPrivates, \ + dmxDevicePrivateKey)) + #define DMX_XINPUT_EVENT_NUM 18 /** Maximum number of file descriptors for SIGIO handling */ @@ -67,6 +79,28 @@ typedef enum { typedef void (*ProcessInputEventsProc)(struct _DMXInputInfo *); typedef void (*UpdateWindowInfoProc)(struct _DMXInputInfo *, DMXUpdateType, WindowPtr); +typedef void (*GrabButtonProc)(struct _DMXInputInfo *, + DeviceIntPtr pDevice, + DeviceIntPtr pModDevice, + WindowPtr pWindow, + WindowPtr pConfineTo, + int button, + int modifiers, + CursorPtr pCursor); +typedef void (*UngrabButtonProc)(struct _DMXInputInfo *, + DeviceIntPtr pDevice, + DeviceIntPtr pModDevice, + WindowPtr pWindow, + int button, + int modifiers); +typedef void (*GrabPointerProc) (struct _DMXInputInfo *, + DeviceIntPtr pDevice, + WindowPtr pWindow, + WindowPtr pConfineTo, + CursorPtr pCursor); +typedef void (*UngrabPointerProc) (struct _DMXInputInfo *, + DeviceIntPtr pDevice, + WindowPtr pWindow); /** An opaque structure that is only exposed in the dmx/input layer. */ typedef struct _DMXLocalInputInfo *DMXLocalInputInfoPtr; @@ -103,6 +137,10 @@ struct _DMXInputInfo { ProcessInputEventsProc processInputEvents; UpdateWindowInfoProc updateWindowInfo; + GrabButtonProc grabButton; + UngrabButtonProc ungrabButton; + GrabPointerProc grabPointer; + UngrabPointerProc ungrabPointer; /* Local input information */ dmxSigioState sigioState; /**< Current stat */ diff --git a/hw/dmx/dmxscrinit.c b/hw/dmx/dmxscrinit.c index b83b4934b..9e77ed2b4 100644 --- a/hw/dmx/dmxscrinit.c +++ b/hw/dmx/dmxscrinit.c @@ -146,6 +146,8 @@ static int dmxScreenPrivateKeyIndex; DevPrivateKey dmxScreenPrivateKey = &dmxScreenPrivateKeyIndex; /**< Private index for Screens */ static int dmxColormapPrivateKeyIndex; DevPrivateKey dmxColormapPrivateKey = &dmxColormapPrivateKeyIndex; /**< Private index for Colormaps */ +static int dmxDevicePrivateKeyIndex; +DevPrivateKey dmxDevicePrivateKey = &dmxDevicePrivateKeyIndex; /**< Private index for Devices */ #ifdef RENDER static int dmxPictPrivateKeyIndex; DevPrivateKey dmxPictPrivateKey = &dmxPictPrivateKeyIndex; /**< Private index for Picts */ diff --git a/hw/dmx/input/dmxbackend.c b/hw/dmx/input/dmxbackend.c index 4c9ae14f2..01ef1756b 100644 --- a/hw/dmx/input/dmxbackend.c +++ b/hw/dmx/input/dmxbackend.c @@ -47,6 +47,7 @@ #include "dmxcommon.h" #include "dmxconsole.h" #include "dmxcursor.h" +#include "dmxwindow.h" #include "dmxprop.h" #include "dmxsync.h" #include "dmxxlibio.h" @@ -193,10 +194,11 @@ static Bool inputEventPredicate (Display *xdisplay, XDeviceMotionEvent *dmev = (XDeviceMotionEvent *) X; XMotionEvent *mev = (XMotionEvent *) data->X; - mev->type = MotionNotify; - mev->x = dmev->x; - mev->y = dmev->y; - mev->state = dmev->state; + mev->type = MotionNotify; + mev->x = dmev->x; + mev->y = dmev->y; + mev->state = dmev->state; + mev->window = dmev->window; } break; case XI_DeviceButtonPress: { XDeviceButtonEvent *dbev = (XDeviceButtonEvent *) X; @@ -207,6 +209,7 @@ static Bool inputEventPredicate (Display *xdisplay, bev->x = dbev->x; bev->y = dbev->y; bev->state = dbev->state; + bev->window = dbev->window; } break; case XI_DeviceButtonRelease: { XDeviceButtonEvent *dbev = (XDeviceButtonEvent *) X; @@ -217,6 +220,7 @@ static Bool inputEventPredicate (Display *xdisplay, bev->x = dbev->x; bev->y = dbev->y; bev->state = dbev->state; + bev->window = dbev->window; } break; case XI_DeviceKeyPress: { XDeviceKeyEvent *dkev = (XDeviceKeyEvent *) X; @@ -684,6 +688,177 @@ void dmxBackendProcessInput(pointer private) } } +void dmxBackendGrabButton(DevicePtr pDev, + DevicePtr pModDev, + WindowPtr pWindow, + WindowPtr pConfineTo, + int button, + int modifiers, + CursorPtr pCursor) +{ + GETPRIVFROMPDEV; + GETDMXINPUTFROMPRIV; + ScreenPtr pScreen = screenInfo.screens[dmxInput->scrnIdx]; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + Window confineTo = None; + Cursor cursor = None; + + if (pConfineTo) + confineTo = (DMX_GET_WINDOW_PRIV (pConfineTo))->window; + + if (pCursor) + cursor = (DMX_GET_CURSOR_PRIV (pCursor, pScreen))->cursor; + + if (dmxLocal->deviceId >= 0) + { + XDevice *modDev = NULL; + + if (pModDev) + modDev = ((DMXLocalInputInfoPtr) pModDev->devicePrivate)->device; + + /* this is really useless as XGrabDeviceButton doesn't allow us + to specify a confineTo window or cursor */ + XLIB_PROLOGUE (dmxScreen); + XGrabDeviceButton (dmxScreen->beDisplay, + dmxLocal->device, + button, + modifiers, + modDev, + (DMX_GET_WINDOW_PRIV (pWindow))->window, + TRUE, + 0, + NULL, + GrabModeAsync, + GrabModeAsync); + XLIB_EPILOGUE (dmxScreen); + } + else + { + XLIB_PROLOGUE (dmxScreen); + XGrabButton (dmxScreen->beDisplay, + button, + modifiers, + (DMX_GET_WINDOW_PRIV (pWindow))->window, + TRUE, + 0, + GrabModeAsync, + GrabModeAsync, + confineTo, + cursor); + XLIB_EPILOGUE (dmxScreen); + } +} + +void dmxBackendUngrabButton(DevicePtr pDev, + DevicePtr pModDev, + WindowPtr pWindow, + int button, + int modifiers) +{ + GETPRIVFROMPDEV; + GETDMXINPUTFROMPRIV; + ScreenPtr pScreen = screenInfo.screens[dmxInput->scrnIdx]; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + + if (dmxLocal->deviceId >= 0) + { + XDevice *modDev = NULL; + + if (pModDev) + modDev = ((DMXLocalInputInfoPtr) pModDev->devicePrivate)->device; + + XLIB_PROLOGUE (dmxScreen); + XUngrabDeviceButton (dmxScreen->beDisplay, + dmxLocal->device, + button, + modifiers, + modDev, + (DMX_GET_WINDOW_PRIV (pWindow))->window); + XLIB_EPILOGUE (dmxScreen); + } + else + { + XLIB_PROLOGUE (dmxScreen); + XUngrabButton (dmxScreen->beDisplay, + button, + modifiers, + (DMX_GET_WINDOW_PRIV (pWindow))->window); + XLIB_EPILOGUE (dmxScreen); + } +} + +void dmxBackendGrabPointer(DevicePtr pDev, + WindowPtr pWindow, + WindowPtr pConfineTo, + CursorPtr pCursor) +{ + GETPRIVFROMPDEV; + GETDMXINPUTFROMPRIV; + ScreenPtr pScreen = screenInfo.screens[dmxInput->scrnIdx]; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + Window confineTo = None; + Cursor cursor = None; + + if (pConfineTo) + confineTo = (DMX_GET_WINDOW_PRIV (pConfineTo))->window; + + if (pCursor) + cursor = (DMX_GET_CURSOR_PRIV (pCursor, pScreen))->cursor; + + if (dmxLocal->deviceId >= 0) + { + XLIB_PROLOGUE (dmxScreen); + XExtendedGrabDevice (dmxScreen->beDisplay, + dmxLocal->device, + (DMX_GET_WINDOW_PRIV (pWindow))->window, + GrabModeAsync, + TRUE, + confineTo, + cursor, + 0, + NULL, + 0, + NULL); + XLIB_EPILOGUE (dmxScreen); + } + else + { + XLIB_PROLOGUE (dmxScreen); + XGrabPointer (dmxScreen->beDisplay, + (DMX_GET_WINDOW_PRIV (pWindow))->window, + TRUE, + 0, + GrabModeAsync, + GrabModeAsync, + confineTo, + cursor, + CurrentTime); + XLIB_EPILOGUE (dmxScreen); + } +} + +void dmxBackendUngrabPointer(DevicePtr pDev, + WindowPtr pWindow) +{ + GETPRIVFROMPDEV; + GETDMXINPUTFROMPRIV; + ScreenPtr pScreen = screenInfo.screens[dmxInput->scrnIdx]; + DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; + + if (dmxLocal->deviceId >= 0) + { + XLIB_PROLOGUE (dmxScreen); + XUngrabDevice (dmxScreen->beDisplay, dmxLocal->device, CurrentTime); + XLIB_EPILOGUE (dmxScreen); + } + else + { + XLIB_PROLOGUE (dmxScreen); + XUngrabPointer (dmxScreen->beDisplay, CurrentTime); + XLIB_EPILOGUE (dmxScreen); + } +} + static void dmxBackendComputeCenter(myPrivate *priv) { int centerX; diff --git a/hw/dmx/input/dmxbackend.h b/hw/dmx/input/dmxbackend.h index da90ca468..4107e2b9f 100644 --- a/hw/dmx/input/dmxbackend.h +++ b/hw/dmx/input/dmxbackend.h @@ -52,6 +52,24 @@ extern void dmxBackendCollectEvents(DevicePtr pDev, extern void dmxBackendProcessInput(pointer private); extern int dmxBackendFunctions(pointer private, DMXFunctionType function); extern void dmxBackendUpdatePosition(pointer private, int x, int y); +extern void dmxBackendGrabButton(DevicePtr pDev, + DevicePtr pModDev, + WindowPtr pWindow, + WindowPtr pConfineTo, + int button, + int modifiers, + CursorPtr pCursor); +extern void dmxBackendUngrabButton(DevicePtr pDev, + DevicePtr pModDev, + WindowPtr pWindow, + int button, + int modifiers); +extern void dmxBackendGrabPointer(DevicePtr pDevice, + WindowPtr pWindow, + WindowPtr pConfineTo, + CursorPtr pCursor); +extern void dmxBackendUngrabPointer(DevicePtr pDevice, + WindowPtr pWindow); extern void dmxBackendKbdOff(DevicePtr pDev); #endif diff --git a/hw/dmx/input/dmxcommon.c b/hw/dmx/input/dmxcommon.c index 7e62934f1..bbbabccd0 100644 --- a/hw/dmx/input/dmxcommon.c +++ b/hw/dmx/input/dmxcommon.c @@ -296,17 +296,21 @@ int dmxCommonKbdOn(DevicePtr pDev) { XEventClass cls[3]; - if (!(priv->xi = XOpenDevice (priv->display, dmxLocal->deviceId))) { + if (!(dmxLocal->device = XOpenDevice (priv->display, + dmxLocal->deviceId))) { dmxLog(dmxWarning, "Cannot open %s device (id=%d) on %s\n", dmxLocal->deviceName ? dmxLocal->deviceName : "(unknown)", dmxLocal->deviceId, dmxInput->name); return -1; } - DeviceKeyPress (priv->xi, dmxInput->event[XI_DeviceKeyPress], cls[0]); - DeviceKeyRelease (priv->xi, dmxInput->event[XI_DeviceKeyRelease], + DeviceKeyPress (dmxLocal->device, + dmxInput->event[XI_DeviceKeyPress], + cls[0]); + DeviceKeyRelease (dmxLocal->device, + dmxInput->event[XI_DeviceKeyRelease], cls[1]); - DeviceStateNotify (priv->xi, + DeviceStateNotify (dmxLocal->device, dmxInput->event[XI_DeviceStateNotify], cls[2]); @@ -315,8 +319,8 @@ int dmxCommonKbdOn(DevicePtr pDev) XLIB_EPILOGUE (priv->be); XLIB_PROLOGUE (priv->be); - XSetInputFocus(priv->display, priv->window, RevertToPointerRoot, - CurrentTime); + XSetDeviceFocus(priv->display, dmxLocal->device, priv->window, + RevertToPointerRoot, CurrentTime); XLIB_EPILOGUE (priv->be); } else @@ -338,10 +342,10 @@ int dmxCommonKbdOn(DevicePtr pDev) void dmxCommonKbdOff(DevicePtr pDev) { GETPRIVFROMPDEV; - if (priv->xi) + if (dmxLocal->device) { - XCloseDevice(priv->display, priv->xi); - priv->xi = NULL; + XCloseDevice(priv->display, dmxLocal->device); + dmxLocal->device = NULL; } else { @@ -531,27 +535,32 @@ int dmxCommonMouOn(DevicePtr pDev) if (priv->be && dmxLocal->deviceId >= 0) { - XEventClass cls[4]; + XEventClass cls[5]; - if (!(priv->xi = XOpenDevice (priv->display, dmxLocal->deviceId))) { + if (!(dmxLocal->device = XOpenDevice (priv->display, + dmxLocal->deviceId))) { dmxLog(dmxWarning, "Cannot open %s device (id=%d) on %s\n", dmxLocal->deviceName ? dmxLocal->deviceName : "(unknown)", dmxLocal->deviceId, dmxInput->name); return -1; } - DeviceMotionNotify (priv->xi, dmxInput->event[XI_DeviceMotionNotify], + DeviceMotionNotify (dmxLocal->device, + dmxInput->event[XI_DeviceMotionNotify], cls[0]); - DeviceButtonPress (priv->xi, dmxInput->event[XI_DeviceButtonPress], + DeviceButtonPress (dmxLocal->device, + dmxInput->event[XI_DeviceButtonPress], cls[1]); - DeviceButtonRelease (priv->xi, dmxInput->event[XI_DeviceButtonRelease], + DeviceButtonRelease (dmxLocal->device, + dmxInput->event[XI_DeviceButtonRelease], cls[2]); - DeviceStateNotify (priv->xi, + DeviceButtonPressGrab (dmxLocal->device, 0, cls[3]); + DeviceStateNotify (dmxLocal->device, dmxInput->event[XI_DeviceStateNotify], - cls[3]); + cls[4]); XLIB_PROLOGUE (priv->be); - XSelectExtensionEvent(priv->display, priv->window, cls, 4); + XSelectExtensionEvent(priv->display, priv->window, cls, 5); XLIB_EPILOGUE (priv->be); } else @@ -585,10 +594,10 @@ void dmxCommonMouOff(DevicePtr pDev) GETPRIVFROMPDEV; GETDMXINPUTFROMPRIV; - if (priv->xi) + if (dmxLocal->device) { - XCloseDevice(priv->display, priv->xi); - priv->xi = NULL; + XCloseDevice(priv->display, dmxLocal->device); + dmxLocal->device = NULL; } else { diff --git a/hw/dmx/input/dmxinputinit.c b/hw/dmx/input/dmxinputinit.c index 42ad51f37..536a1a739 100644 --- a/hw/dmx/input/dmxinputinit.c +++ b/hw/dmx/input/dmxinputinit.c @@ -106,6 +106,8 @@ static DMXLocalInputInfoRec DMXBackendMou = { dmxCommonMouOn, dmxCommonMouOff, dmxBackendUpdatePosition, NULL, NULL, NULL, dmxBackendCollectEvents, dmxBackendProcessInput, dmxBackendFunctions, NULL, + dmxBackendGrabButton, dmxBackendUngrabButton, + dmxBackendGrabPointer, dmxBackendUngrabPointer, dmxCommonMouCtrl }; @@ -117,6 +119,8 @@ static DMXLocalInputInfoRec DMXBackendKbd = { dmxCommonKbdOn, dmxBackendKbdOff, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, + NULL, NULL, NULL, dmxCommonKbdCtrl, dmxCommonKbdBell }; @@ -126,7 +130,10 @@ static DMXLocalInputInfoRec DMXConsoleMou = { dmxConsoleInit, dmxConsoleReInit, NULL, dmxConsoleMouGetInfo, dmxCommonMouOn, dmxCommonMouOff, dmxConsoleUpdatePosition, NULL, NULL, NULL, - dmxConsoleCollectEvents, NULL, dmxConsoleFunctions, dmxConsoleUpdateInfo, + dmxConsoleCollectEvents, NULL, + dmxConsoleFunctions, dmxConsoleUpdateInfo, + NULL, NULL, + NULL, NULL, dmxCommonMouCtrl }; @@ -137,8 +144,10 @@ static DMXLocalInputInfoRec DMXConsoleKbd = { dmxConsoleInit, dmxConsoleReInit, NULL, dmxConsoleKbdGetInfo, dmxCommonKbdOn, dmxCommonKbdOff, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, dmxCommonKbdCtrl, dmxCommonKbdBell + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, + NULL, NULL, + dmxCommonKbdCtrl, dmxCommonKbdBell }; static DMXLocalInputInfoRec DMXCommonOth = { @@ -159,8 +168,10 @@ static DMXLocalInputInfoRec DMXLocalDevices[] = { kbdLinuxInit, NULL, NULL, kbdLinuxGetInfo, kbdLinuxOn, kbdLinuxOff, NULL, kbdLinuxVTPreSwitch, kbdLinuxVTPostSwitch, kbdLinuxVTSwitch, - kbdLinuxRead, NULL, NULL, NULL, - NULL, kbdLinuxCtrl, kbdLinuxBell + kbdLinuxRead, NULL, NULL, NULL, NULL, + NULL, NULL, + NULL, NULL, + kbdLinuxCtrl, kbdLinuxBell }, { "ms", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, @@ -189,8 +200,10 @@ static DMXLocalInputInfoRec DMXLocalDevices[] = { kbdUSBInit, NULL, NULL, kbdUSBGetInfo, kbdUSBOn, usbOff, NULL, NULL, NULL, NULL, - kbdUSBRead, NULL, NULL, NULL, - NULL, kbdUSBCtrl + kbdUSBRead, NULL, NULL, NULL, NULL, + NULL, NULL, + NULL, NULL, + kbdUSBCtrl }, { "usb-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, @@ -575,6 +588,145 @@ static void dmxProcessInputEvents(DMXInputInfo *dmxInput) } } +static void dmxGrabButton(DMXInputInfo *dmxInput, + DeviceIntPtr pDevice, + DeviceIntPtr pModDevice, + WindowPtr pWindow, + WindowPtr pConfineTo, + int button, + int modifiers, + CursorPtr pCursor) +{ + int i, j; + + for (i = 0; i < dmxInput->numDevs; i++) + { + DevicePtr pDev = &dmxInput->devs[i]->pDevice->public; + + if (dmxInput->devs[i]->pDevice->u.master != pDevice) + continue; + + if (!dmxInput->devs[i]->grab_button) + continue; + + if (modifiers & AnyModifier) + { + (*dmxInput->devs[i]->grab_button) (pDev, + NULL, + pWindow, + pConfineTo, + button, + modifiers, + pCursor); + } + else + { + for (j = 0; j < dmxInput->numDevs; j++) + { + DevicePtr pModDev = &dmxInput->devs[j]->pDevice->public; + + if (dmxInput->devs[j]->pDevice->u.master == pModDevice) + (*dmxInput->devs[i]->grab_button) (pDev, + pModDev, + pWindow, + pConfineTo, + button, + modifiers, + pCursor); + } + } + } +} + +static void dmxUngrabButton(DMXInputInfo *dmxInput, + DeviceIntPtr pDevice, + DeviceIntPtr pModDevice, + WindowPtr pWindow, + int button, + int modifiers) +{ + int i, j; + + for (i = 0; i < dmxInput->numDevs; i++) + { + DevicePtr pDev = &dmxInput->devs[i]->pDevice->public; + + if (dmxInput->devs[i]->pDevice->u.master != pDevice) + continue; + + if (!dmxInput->devs[i]->ungrab_button) + continue; + + if (modifiers == AnyModifier) + { + (*dmxInput->devs[i]->ungrab_button) (pDev, + NULL, + pWindow, + button, + modifiers); + } + else + { + for (j = 0; j < dmxInput->numDevs; j++) + { + DevicePtr pModDev = &dmxInput->devs[j]->pDevice->public; + + if (dmxInput->devs[j]->pDevice->u.master == pModDevice) + (*dmxInput->devs[i]->ungrab_button) (pDev, + pModDev, + pWindow, + button, + modifiers); + } + } + } +} + +static void dmxGrabPointer (DMXInputInfo *dmxInput, + DeviceIntPtr pDevice, + WindowPtr pWindow, + WindowPtr pConfineTo, + CursorPtr pCursor) +{ + int i; + + for (i = 0; i < dmxInput->numDevs; i++) + { + DevicePtr pDev = &dmxInput->devs[i]->pDevice->public; + + if (dmxInput->devs[i]->pDevice->u.master != pDevice) + continue; + + if (!dmxInput->devs[i]->grab_pointer) + continue; + + (*dmxInput->devs[i]->grab_pointer) (pDev, + pWindow, + pConfineTo, + pCursor); + } +} + +static void dmxUngrabPointer (DMXInputInfo *dmxInput, + DeviceIntPtr pDevice, + WindowPtr pWindow) +{ + int i; + + for (i = 0; i < dmxInput->numDevs; i++) + { + DevicePtr pDev = &dmxInput->devs[i]->pDevice->public; + + if (dmxInput->devs[i]->pDevice->u.master != pDevice) + continue; + + if (!dmxInput->devs[i]->ungrab_pointer) + continue; + + (*dmxInput->devs[i]->ungrab_pointer) (pDev, pWindow); + } +} + static void dmxUpdateWindowInformation(DMXInputInfo *dmxInput, DMXUpdateType type, WindowPtr pWindow) @@ -1112,6 +1264,10 @@ void dmxInputInit(DMXInputInfo *dmxInput) } dmxInput->processInputEvents = dmxProcessInputEvents; + dmxInput->grabButton = dmxGrabButton; + dmxInput->ungrabButton = dmxUngrabButton; + dmxInput->grabPointer = dmxGrabPointer; + dmxInput->ungrabPointer = dmxUngrabPointer; dmxInput->detached = False; RegisterBlockAndWakeupHandlers(dmxBlockHandler, @@ -1290,28 +1446,7 @@ DMXInputInfo *dmxInputLocateId(int id) return NULL; } -static int dmxInputAttachNew(DMXInputInfo *dmxInput, int *id) -{ - int i; - - dmxInputInit(dmxInput); - - for (i = 0; i < dmxInput->numDevs; i++) { - DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i]; - - if (ActivateDevice(dmxLocal->pDevice) != Success || - EnableDevice(dmxLocal->pDevice) != TRUE) { - ErrorF ("[dmx] couldn't add or enable device\n"); - return BadImplementation; - } - } - - if (id && dmxInput->devs) *id = dmxInput->devs[0]->pDevice->id; - dmxInputLogDevices(); - return 0; -} - -static int dmxInputAttachOld(DMXInputInfo *dmxInput, int *id) +static int dmxInputAttach(DMXInputInfo *dmxInput, int *id) { int i; @@ -1344,7 +1479,7 @@ int dmxInputAttachConsole(const char *name, int isCore, int *id) && !strcmp(dmxInput->name, name)) { /* Found match */ dmxLogInput(dmxInput, "Reattaching detached console input\n"); - return dmxInputAttachOld(dmxInput, id); + return dmxInputAttach(dmxInput, id); } } @@ -1352,7 +1487,7 @@ int dmxInputAttachConsole(const char *name, int isCore, int *id) dmxInput = dmxConfigAddInput(xstrdup(name), isCore); dmxInput->freename = TRUE; dmxLogInput(dmxInput, "Attaching new console input\n"); - return dmxInputAttachNew(dmxInput, id); + return dmxInputAttach(dmxInput, id); } int dmxInputAttachBackend(int physicalScreen, int isCore, int *id) @@ -1370,7 +1505,7 @@ int dmxInputAttachBackend(int physicalScreen, int isCore, int *id) dmxScreen = &dmxScreens[physicalScreen]; if (!dmxScreen->beDisplay) return BadAccess; /* Screen detached */ dmxLogInput(dmxInput, "Reattaching detached backend input\n"); - return dmxInputAttachOld(dmxInput, id); + return dmxInputAttach(dmxInput, id); } } /* No match found */ @@ -1380,5 +1515,5 @@ int dmxInputAttachBackend(int physicalScreen, int isCore, int *id) dmxInput->freename = TRUE; dmxInput->scrnIdx = physicalScreen; dmxLogInput(dmxInput, "Attaching new backend input\n"); - return dmxInputAttachNew(dmxInput, id); + return dmxInputAttach(dmxInput, id); } diff --git a/hw/dmx/input/dmxinputinit.h b/hw/dmx/input/dmxinputinit.h index 5c3b6f17c..2b67195db 100644 --- a/hw/dmx/input/dmxinputinit.h +++ b/hw/dmx/input/dmxinputinit.h @@ -165,6 +165,24 @@ typedef void (*dmxCollectEventsProcPtr)(DevicePtr, typedef void (*dmxProcessInputProcPtr)(pointer); typedef void (*dmxUpdateInfoProcPtr)(pointer, DMXUpdateType, WindowPtr); typedef int (*dmxFunctionsProcPtr)(pointer, DMXFunctionType); +typedef void (*dmxGrabButtonProcPtr)(DevicePtr, + DevicePtr, + WindowPtr, + WindowPtr, + int, + int, + CursorPtr); +typedef void (*dmxUngrabButtonProcPtr)(DevicePtr, + DevicePtr, + WindowPtr, + int, + int); +typedef void (*dmxGrabPointerProcPtr) (DevicePtr, + WindowPtr, + WindowPtr, + CursorPtr); +typedef void (*dmxUngrabPointerProcPtr) (DevicePtr, + WindowPtr); typedef void (*dmxKBCtrlProcPtr)(DevicePtr, KeybdCtrl *ctrl); typedef void (*dmxMCtrlProcPtr)(DevicePtr, PtrCtrl *ctrl); @@ -223,6 +241,10 @@ typedef struct _DMXLocalInputInfo { dmxFunctionsProcPtr functions; dmxUpdateInfoProcPtr update_info; /**< Update window layout * information */ + dmxGrabButtonProcPtr grab_button; /**< Grab button */ + dmxUngrabButtonProcPtr ungrab_button; /**< Ungrab button */ + dmxGrabPointerProcPtr grab_pointer; /**< Grab pointer */ + dmxUngrabPointerProcPtr ungrab_pointer; /**< Ungrab pointer */ dmxMCtrlProcPtr mCtrl; /**< Pointer control */ dmxKBCtrlProcPtr kCtrl; /**< Keyboard control */ @@ -268,6 +290,7 @@ typedef struct _DMXLocalInputInfo { long attached; /**< the master device this device * is attached to */ + XDevice *device; char state[32]; /**< Key/Button state */ } DMXLocalInputInfoRec;