Asynchronous pointer grabbing.

This commit is contained in:
David Reveman 2008-08-01 21:53:25 -04:00
parent c3f40d7171
commit b94d36eb95
7 changed files with 211 additions and 82 deletions

View file

@ -127,6 +127,33 @@ dmxScreenEventCheckInput (ScreenPtr pScreen,
return FALSE;
}
Bool
dmxScreenReplyCheckInput (ScreenPtr pScreen,
unsigned int request,
xcb_generic_reply_t *reply)
{
int i;
for (i = 0; i < dmxNumInputs; i++)
{
DMXInputInfo *dmxInput = &dmxInputs[i];
if (dmxInput->scrnIdx != pScreen->myNum)
continue;
if (dmxInput->detached)
continue;
if (!dmxInput->screenReplyCheck)
continue;
if ((*dmxInput->screenReplyCheck) (dmxInput, request, reply))
return TRUE;
}
return FALSE;
}
int
NewInputDeviceRequest (InputOption *options, DeviceIntPtr *pdev)
{

View file

@ -76,6 +76,9 @@ typedef enum {
typedef Bool (*ScreenEventCheckProc)(struct _DMXInputInfo *,
xcb_generic_event_t *);
typedef Bool (*ScreenReplyCheckProc)(struct _DMXInputInfo *,
unsigned int request,
xcb_generic_reply_t *);
typedef void (*ProcessInputEventsProc)(struct _DMXInputInfo *);
typedef void (*UpdateWindowInfoProc)(struct _DMXInputInfo *,
DMXUpdateType, WindowPtr);
@ -136,6 +139,7 @@ struct _DMXInputInfo {
* draw in console */
ScreenEventCheckProc screenEventCheck;
ScreenReplyCheckProc screenReplyCheck;
ProcessInputEventsProc processInputEvents;
UpdateWindowInfoProc updateWindowInfo;
GrabButtonProc grabButton;
@ -185,6 +189,9 @@ extern void dmxInputLogDevices(void);
extern void dmxUpdateWindowInfo(DMXUpdateType type, WindowPtr pWindow);
extern Bool dmxScreenEventCheckInput (ScreenPtr pScreen,
xcb_generic_event_t *event);
extern Bool dmxScreenReplyCheckInput (ScreenPtr pScreen,
unsigned int request,
xcb_generic_reply_t *reply);
/* These functions are defined in input/dmxeq.c */
extern Bool dmxeqInitialized(void);

View file

@ -813,7 +813,8 @@ dmxBEDispatch (ScreenPtr pScreen)
if (reply)
rep = (xcb_generic_reply_t *) reply;
if (!dmxScreenReplyCheckSync (pScreen, head->sequence, rep))
if (!dmxScreenReplyCheckSync (pScreen, head->sequence, rep) &&
!dmxScreenReplyCheckInput (pScreen, head->sequence, rep))
{
/* error response */
if (rep->response_type == 0)

View file

@ -50,6 +50,7 @@
#include "dmxwindow.h"
#include "dmxprop.h"
#include "dmxsync.h"
#include "dmxscrinit.h"
#include "dmxxlibio.h"
#include "dmxcb.h" /* For dmxGlobalWidth and dmxGlobalHeight */
#include "dmxevents.h" /* For dmxGetGlobalPosition */
@ -551,6 +552,66 @@ dmxBackendPointerEventCheck (DevicePtr pDev,
return TRUE;
}
/* not in xcb-xinput yet */
#define DMX_XCB_INPUT_EXTENDED_GRAB_DEVICE 45
typedef struct dmx_xcb_input_extended_grab_device_request_t {
uint8_t major_opcode;
uint8_t minor_opcode;
uint16_t length;
xcb_window_t grab_window;
xcb_timestamp_t time;
uint8_t deviceid;
uint8_t device_mode;
uint8_t owner_events;
uint8_t pad0;
xcb_window_t confine_to;
xcb_cursor_t cursor;
uint16_t event_count;
uint16_t generic_event_count;
} dmx_xcb_input_extended_grab_device_request_t;
Bool
dmxBackendPointerReplyCheck (DevicePtr pDev,
unsigned int request,
xcb_generic_reply_t *reply)
{
GETDMXLOCALFROMPDEV;
if (request == dmxLocal->grab.sequence)
{
xcb_grab_status_t status = XCB_GRAB_STATUS_FROZEN;
if (reply->response_type == 1)
{
if (dmxLocal->deviceId >= 0)
{
xcb_input_grab_device_reply_t *xgrab =
(xcb_input_grab_device_reply_t *) reply;
status = xgrab->status;
}
else
{
xcb_grab_pointer_reply_t *xgrab =
(xcb_grab_pointer_reply_t *) reply;
status = xgrab->status;
}
}
if (status == XCB_GRAB_STATUS_SUCCESS)
{
/* TODO: track state of grabs */
}
dmxLocal->grab.sequence = 0;
return TRUE;
}
return FALSE;
}
Bool
dmxBackendKeyboardEventCheck (DevicePtr pDev,
xcb_generic_event_t *event)
@ -580,8 +641,8 @@ dmxBackendKeyboardEventCheck (DevicePtr pDev,
(xcb_keymap_notify_event_t *) event;
char state[32];
memcpy (state, xkeymap->keys, 31);
state[31] = 0;
state[0] = 0;
memcpy (&state[1], xkeymap->keys, 31);
dmxUpdateKeyState (pKeyDev, state);
} break;
@ -699,6 +760,7 @@ void dmxBackendGrabButton(DevicePtr pDev,
GETDMXINPUTFROMPRIV;
ScreenPtr pScreen = screenInfo.screens[dmxInput->scrnIdx];
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
Window window = (DMX_GET_WINDOW_PRIV (pWindow))->window;
Window confineTo = None;
Cursor cursor = None;
@ -710,41 +772,38 @@ void dmxBackendGrabButton(DevicePtr pDev,
if (dmxLocal->deviceId >= 0)
{
XDevice *modDev = NULL;
int id = dmxLocal->deviceId;
int modId = 0;
if (pModDev)
modDev = ((DMXLocalInputInfoPtr) pModDev->devicePrivate)->device;
modId = ((DMXLocalInputInfoPtr) pModDev->devicePrivate)->deviceId;
/* 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);
xcb_input_grab_device_button (dmxScreen->connection,
window,
id,
modId,
0,
modifiers,
XCB_GRAB_MODE_ASYNC,
XCB_GRAB_MODE_ASYNC,
button,
TRUE,
NULL);
}
else
{
XLIB_PROLOGUE (dmxScreen);
XGrabButton (dmxScreen->beDisplay,
button,
modifiers,
(DMX_GET_WINDOW_PRIV (pWindow))->window,
TRUE,
0,
GrabModeAsync,
GrabModeAsync,
confineTo,
cursor);
XLIB_EPILOGUE (dmxScreen);
xcb_grab_button (dmxScreen->connection,
TRUE,
window,
0,
XCB_GRAB_MODE_ASYNC,
XCB_GRAB_MODE_ASYNC,
confineTo,
cursor,
button,
modifiers);
}
}
@ -758,31 +817,29 @@ void dmxBackendUngrabButton(DevicePtr pDev,
GETDMXINPUTFROMPRIV;
ScreenPtr pScreen = screenInfo.screens[dmxInput->scrnIdx];
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
Window window = (DMX_GET_WINDOW_PRIV (pWindow))->window;
if (dmxLocal->deviceId >= 0)
{
XDevice *modDev = NULL;
int id = dmxLocal->deviceId;
int modId = 0;
if (pModDev)
modDev = ((DMXLocalInputInfoPtr) pModDev->devicePrivate)->device;
modId = ((DMXLocalInputInfoPtr) pModDev->devicePrivate)->deviceId;
XLIB_PROLOGUE (dmxScreen);
XUngrabDeviceButton (dmxScreen->beDisplay,
dmxLocal->device,
button,
modifiers,
modDev,
(DMX_GET_WINDOW_PRIV (pWindow))->window);
XLIB_EPILOGUE (dmxScreen);
xcb_input_ungrab_device_button (dmxScreen->connection,
window,
modifiers,
modId,
button,
id);
}
else
{
XLIB_PROLOGUE (dmxScreen);
XUngrabButton (dmxScreen->beDisplay,
button,
modifiers,
(DMX_GET_WINDOW_PRIV (pWindow))->window);
XLIB_EPILOGUE (dmxScreen);
xcb_ungrab_button (dmxScreen->connection,
button,
window,
modifiers);
}
}
@ -795,6 +852,7 @@ void dmxBackendGrabPointer(DevicePtr pDev,
GETDMXINPUTFROMPRIV;
ScreenPtr pScreen = screenInfo.screens[dmxInput->scrnIdx];
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
Window window = (DMX_GET_WINDOW_PRIV (pWindow))->window;
Window confineTo = None;
Cursor cursor = None;
@ -806,34 +864,43 @@ void dmxBackendGrabPointer(DevicePtr pDev,
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);
dmx_xcb_input_extended_grab_device_request_t grab = {
.grab_window = window,
.deviceid = dmxLocal->deviceId,
.device_mode = XCB_GRAB_MODE_ASYNC,
.owner_events = TRUE,
.confine_to = confineTo,
.cursor = cursor
};
xcb_protocol_request_t request = {
1,
&xcb_input_id,
DMX_XCB_INPUT_EXTENDED_GRAB_DEVICE,
FALSE
};
struct iovec vector = { &grab, sizeof (grab) };
dmxLocal->grab.sequence =
xcb_send_request (dmxScreen->connection,
0,
&vector,
&request);
}
else
{
XLIB_PROLOGUE (dmxScreen);
XGrabPointer (dmxScreen->beDisplay,
(DMX_GET_WINDOW_PRIV (pWindow))->window,
TRUE,
0,
GrabModeAsync,
GrabModeAsync,
confineTo,
cursor,
CurrentTime);
XLIB_EPILOGUE (dmxScreen);
dmxLocal->grab.sequence =
xcb_grab_pointer (dmxScreen->connection,
TRUE,
window,
0,
XCB_GRAB_MODE_ASYNC,
XCB_GRAB_MODE_ASYNC,
confineTo,
cursor,
0).sequence;
}
dmxAddSequence (&dmxScreen->request, dmxLocal->grab.sequence);
}
void dmxBackendUngrabPointer(DevicePtr pDev,
@ -846,15 +913,13 @@ void dmxBackendUngrabPointer(DevicePtr pDev,
if (dmxLocal->deviceId >= 0)
{
XLIB_PROLOGUE (dmxScreen);
XUngrabDevice (dmxScreen->beDisplay, dmxLocal->device, CurrentTime);
XLIB_EPILOGUE (dmxScreen);
xcb_input_ungrab_device (dmxScreen->connection,
0,
dmxLocal->deviceId);
}
else
{
XLIB_PROLOGUE (dmxScreen);
XUngrabPointer (dmxScreen->beDisplay, CurrentTime);
XLIB_EPILOGUE (dmxScreen);
xcb_ungrab_pointer (dmxScreen->connection, 0);
}
}

View file

@ -54,6 +54,9 @@ extern int dmxBackendFunctions(pointer private, DMXFunctionType function);
extern void dmxBackendUpdatePosition(pointer private, int x, int y);
extern Bool dmxBackendPointerEventCheck(DevicePtr pDev,
xcb_generic_event_t *event);
extern Bool dmxBackendPointerReplyCheck(DevicePtr pDev,
unsigned int request,
xcb_generic_reply_t *reply);
extern Bool dmxBackendKeyboardEventCheck(DevicePtr pDev,
xcb_generic_event_t *event);
extern void dmxBackendGrabButton(DevicePtr pDev,

View file

@ -106,7 +106,7 @@ static DMXLocalInputInfoRec DMXBackendMou = {
dmxCommonMouOn, dmxCommonMouOff, dmxBackendUpdatePosition,
NULL, NULL, NULL,
NULL, dmxBackendProcessInput, dmxBackendFunctions, NULL,
dmxBackendPointerEventCheck,
dmxBackendPointerEventCheck, dmxBackendPointerReplyCheck,
dmxBackendGrabButton, dmxBackendUngrabButton,
dmxBackendGrabPointer, dmxBackendUngrabPointer,
dmxCommonMouCtrl
@ -120,7 +120,7 @@ static DMXLocalInputInfoRec DMXBackendKbd = {
dmxCommonKbdOn, dmxBackendKbdOff, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
dmxBackendKeyboardEventCheck,
dmxBackendKeyboardEventCheck, NULL,
NULL, NULL,
NULL, NULL,
NULL, dmxCommonKbdCtrl, dmxCommonKbdBell
@ -134,7 +134,7 @@ static DMXLocalInputInfoRec DMXConsoleMou = {
NULL, NULL, NULL,
dmxConsoleCollectEvents, NULL,
dmxConsoleFunctions, dmxConsoleUpdateInfo,
NULL,
NULL, NULL,
NULL, NULL,
NULL, NULL,
dmxCommonMouCtrl
@ -148,7 +148,7 @@ static DMXLocalInputInfoRec DMXConsoleKbd = {
dmxCommonKbdOn, dmxCommonKbdOff, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL,
NULL, NULL,
NULL, NULL,
NULL, NULL,
dmxCommonKbdCtrl, dmxCommonKbdBell
@ -173,7 +173,7 @@ static DMXLocalInputInfoRec DMXLocalDevices[] = {
kbdLinuxOn, kbdLinuxOff, NULL,
kbdLinuxVTPreSwitch, kbdLinuxVTPostSwitch, kbdLinuxVTSwitch,
kbdLinuxRead, NULL, NULL, NULL, NULL,
NULL,
NULL, NULL,
NULL, NULL,
NULL, NULL,
kbdLinuxCtrl, kbdLinuxBell
@ -206,7 +206,7 @@ static DMXLocalInputInfoRec DMXLocalDevices[] = {
kbdUSBOn, usbOff, NULL,
NULL, NULL, NULL,
kbdUSBRead, NULL, NULL, NULL, NULL,
NULL,
NULL, NULL,
NULL, NULL,
NULL, NULL,
kbdUSBCtrl
@ -595,6 +595,26 @@ static Bool dmxScreenEventCheck(DMXInputInfo *dmxInput,
return FALSE;
}
static Bool dmxScreenReplyCheck(DMXInputInfo *dmxInput,
unsigned int request,
xcb_generic_reply_t *reply)
{
int i;
for (i = 0; i < dmxInput->numDevs; i++)
{
DevicePtr pDev = &dmxInput->devs[i]->pDevice->public;
if (!dmxInput->devs[i]->reply_check)
continue;
if ((*dmxInput->devs[i]->reply_check) (pDev, request, reply))
return TRUE;
}
return FALSE;
}
static void dmxProcessInputEvents(DMXInputInfo *dmxInput)
{
int i;
@ -1245,6 +1265,7 @@ void dmxInputInit(DMXInputInfo *dmxInput)
}
dmxInput->screenEventCheck = dmxScreenEventCheck;
dmxInput->screenReplyCheck = dmxScreenReplyCheck;
dmxInput->processInputEvents = dmxProcessInputEvents;
dmxInput->grabButton = dmxGrabButton;
dmxInput->ungrabButton = dmxUngrabButton;

View file

@ -167,6 +167,9 @@ typedef void (*dmxUpdateInfoProcPtr)(pointer, DMXUpdateType, WindowPtr);
typedef int (*dmxFunctionsProcPtr)(pointer, DMXFunctionType);
typedef Bool (*dmxEventCheckProc)(DevicePtr,
xcb_generic_event_t *);
typedef Bool (*dmxReplyCheckProc)(DevicePtr,
unsigned int,
xcb_generic_reply_t *);
typedef void (*dmxGrabButtonProcPtr)(DevicePtr,
DevicePtr,
WindowPtr,
@ -244,6 +247,7 @@ typedef struct _DMXLocalInputInfo {
dmxUpdateInfoProcPtr update_info; /**< Update window layout
* information */
dmxEventCheckProc event_check; /**< Event check */
dmxReplyCheckProc reply_check; /**< Reply check */
dmxGrabButtonProcPtr grab_button; /**< Grab button */
dmxUngrabButtonProcPtr ungrab_button; /**< Ungrab button */
dmxGrabPointerProcPtr grab_pointer; /**< Grab pointer */
@ -296,6 +300,7 @@ typedef struct _DMXLocalInputInfo {
XDevice *device;
char state[32]; /**< Key/Button state */
char keysbuttons[32];
xcb_void_cookie_t grab;
} DMXLocalInputInfoRec;
extern DMXLocalInputInfoPtr dmxLocalCorePointer, dmxLocalCoreKeyboard;