From b27fbaf53e4ba0ac7bc3da78bd6b1d26349d9f7c Mon Sep 17 00:00:00 2001 From: David Reveman Date: Tue, 11 Nov 2008 10:47:29 -0500 Subject: [PATCH] Keep track of input focus and pointer location. --- hw/dmx/dmxinput.c | 131 ++++++++++++++++++++++++++++++++++++++++++---- hw/dmx/dmxinput.h | 1 + 2 files changed, 123 insertions(+), 9 deletions(-) diff --git a/hw/dmx/dmxinput.c b/hw/dmx/dmxinput.c index 96e3b036f..776282051 100644 --- a/hw/dmx/dmxinput.c +++ b/hw/dmx/dmxinput.c @@ -47,11 +47,12 @@ #include #include -#define DMX_KEYBOARD_EVENT_MASK \ - (KeyPressMask | KeyReleaseMask | KeymapStateMask) +#define DMX_KEYBOARD_EVENT_MASK \ + (KeyPressMask | KeyReleaseMask | KeymapStateMask | FocusChangeMask) -#define DMX_POINTER_EVENT_MASK \ - (ButtonPressMask | ButtonReleaseMask | PointerMotionMask) +#define DMX_POINTER_EVENT_MASK \ + (ButtonPressMask | ButtonReleaseMask | PointerMotionMask | \ + LeaveWindowMask) static EventListPtr dmxEvents = NULL; @@ -555,6 +556,27 @@ typedef struct dmx_xcb_input_extended_grab_device_request_t { uint16_t generic_event_count; } dmx_xcb_input_extended_grab_device_request_t; +#define DMX_XCB_INPUT_DEVICE_LEAVE_NOTIFY 17 + +typedef struct dmx_xcb_input_device_state_notify_event_t { + uint8_t response_type; + uint8_t detail; + uint16_t sequence; + xcb_timestamp_t time; + xcb_window_t root; + xcb_window_t event; + xcb_window_t child; + int16_t root_x; + int16_t root_y; + int16_t event_x; + int16_t event_y; + uint16_t state; + uint8_t mode; + uint8_t device_id; +} dmx_xcb_input_device_state_notify_event_t; + +typedef xcb_input_focus_in_event_t dmx_xcb_input_focus_out_event_t; + static void dmxDeviceGrabKeyboard (DeviceIntPtr pDevice, WindowPtr pWindow) @@ -802,6 +824,23 @@ dmxDevicePointerReplyCheck (DeviceIntPtr pDevice, return FALSE; } +static void +dmxDevicePointerActivate (DeviceIntPtr pDevice) +{ + dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice); + + if (pDevPriv->active) + return; + + pDevPriv->active = TRUE; +} + +static void +dmxDevicePointerDeactivate (DeviceIntPtr pDevice) +{ + DMX_GET_DEVICE_PRIV (pDevice)->active = FALSE; +} + static void dmxUpdateSpriteFromEvent (DeviceIntPtr pDevice, xcb_window_t event, @@ -859,6 +898,7 @@ dmxUpdateSpriteFromEvent (DeviceIntPtr pDevice, y += pWin->drawable.y; } + dmxDevicePointerActivate (pDevice); dmxEndFakeMotion (&dmxScreen->input); dmxBEDnDSpriteUpdate (pScreen, event, rootX, rootY); dmxUpdateSpritePosition (pDevice, x, y); @@ -901,6 +941,13 @@ dmxDevicePointerEventCheck (DeviceIntPtr pDevice, xbutton->detail, type); } break; + case XCB_LEAVE_NOTIFY: { + xcb_leave_notify_event_t *xcrossing = + (xcb_leave_notify_event_t *) event; + + if (xcrossing->detail != XCB_NOTIFY_DETAIL_INFERIOR) + dmxDevicePointerDeactivate (pButtonDev); + } break; default: if (id < 0) return FALSE; @@ -983,6 +1030,16 @@ dmxDevicePointerEventCheck (DeviceIntPtr pDevice, memcpy (&pDevPriv->keysbuttons[4], xstate->buttons, 28); dmxUpdateButtonState (pButtonDev, pDevPriv->keysbuttons); } break; + case DMX_XCB_INPUT_DEVICE_LEAVE_NOTIFY: { + dmx_xcb_input_device_state_notify_event_t *xcrossing = + (dmx_xcb_input_device_state_notify_event_t *) event; + + if (id != (xcrossing->device_id & DEVICE_BITS)) + return FALSE; + + if (xcrossing->detail != XCB_NOTIFY_DETAIL_INFERIOR) + dmxDevicePointerDeactivate (pButtonDev); + } break; default: return FALSE; } @@ -991,6 +1048,23 @@ dmxDevicePointerEventCheck (DeviceIntPtr pDevice, return TRUE; } +static void +dmxDeviceKeyboardActivate (DeviceIntPtr pDevice) +{ + dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice); + + if (pDevPriv->active) + return; + + pDevPriv->active = TRUE; +} + +static void +dmxDeviceKeyboardDeactivate (DeviceIntPtr pDevice) +{ + DMX_GET_DEVICE_PRIV (pDevice)->active = FALSE; +} + static void dmxUpdateKeyStateFromEvent (DeviceIntPtr pDevice, xcb_window_t event, @@ -1106,6 +1180,18 @@ dmxDeviceKeyboardEventCheck (DeviceIntPtr pDevice, xmapping->first_keycode, xmapping->count); } break; + case XCB_FOCUS_IN: { + xcb_focus_in_event_t *xfocus = (xcb_focus_in_event_t *) event; + + if (xfocus->detail != XCB_NOTIFY_DETAIL_INFERIOR) + dmxDeviceKeyboardActivate (pKeyDev); + } break; + case XCB_FOCUS_OUT: { + xcb_focus_out_event_t *xfocus = (xcb_focus_out_event_t *) event; + + if (xfocus->detail != XCB_NOTIFY_DETAIL_INFERIOR) + dmxDeviceKeyboardDeactivate (pKeyDev); + } break; default: if (id < 0) return FALSE; @@ -1184,6 +1270,26 @@ dmxDeviceKeyboardEventCheck (DeviceIntPtr pDevice, xmapping->first_keycode, xmapping->count); } break; + case XCB_INPUT_FOCUS_IN: { + xcb_input_focus_in_event_t *xfocus = + (xcb_input_focus_in_event_t *) event; + + if (id != (xfocus->device_id & DEVICE_BITS)) + return FALSE; + + if (xfocus->detail != XCB_NOTIFY_DETAIL_INFERIOR) + dmxDeviceKeyboardActivate (pKeyDev); + } break; + case XCB_INPUT_FOCUS_OUT: { + dmx_xcb_input_focus_out_event_t *xfocus = + (dmx_xcb_input_focus_out_event_t *) event; + + if (id != (xfocus->device_id & DEVICE_BITS)) + return FALSE; + + if (xfocus->detail != XCB_NOTIFY_DETAIL_INFERIOR) + dmxDeviceKeyboardDeactivate (pKeyDev); + } break; default: return FALSE; } @@ -1333,7 +1439,7 @@ dmxKeyboardOn (DeviceIntPtr pDevice) if (pDevPriv->deviceId >= 0) { - XEventClass cls[3]; + XEventClass cls[5]; int type; pDevPriv->device = XOpenDevice (dmxScreen->beDisplay, @@ -1349,10 +1455,12 @@ dmxKeyboardOn (DeviceIntPtr pDevice) DeviceKeyPress (pDevPriv->device, type, cls[0]); DeviceKeyRelease (pDevPriv->device, type, cls[1]); DeviceStateNotify (pDevPriv->device, type, cls[2]); + DeviceFocusIn (pDevPriv->device, type, cls[3]); + DeviceFocusOut (pDevPriv->device, type, cls[4]); XLIB_PROLOGUE (dmxScreen); XSelectExtensionEvent (dmxScreen->beDisplay, dmxScreen->rootWin, - cls, 3); + cls, 5); XLIB_EPILOGUE (dmxScreen); } else @@ -1483,11 +1591,12 @@ static int dmxPointerOn (DeviceIntPtr pDevice) { dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice); - DMXScreenInfo *dmxScreen = (DMXScreenInfo *) pDevPriv->dmxInput; + DMXInputInfo *dmxInput = pDevPriv->dmxInput; + DMXScreenInfo *dmxScreen = (DMXScreenInfo *) dmxInput; if (pDevPriv->deviceId >= 0) { - XEventClass cls[5]; + XEventClass cls[6]; int type; pDevPriv->device = XOpenDevice (dmxScreen->beDisplay, @@ -1505,9 +1614,12 @@ dmxPointerOn (DeviceIntPtr pDevice) DeviceButtonPressGrab (pDevPriv->device, type, cls[3]); DeviceStateNotify (pDevPriv->device, type, cls[4]); + cls[5] = (pDevPriv->device->device_id << 8) | + (dmxInput->eventBase + DMX_XCB_INPUT_DEVICE_LEAVE_NOTIFY); + XLIB_PROLOGUE (dmxScreen); XSelectExtensionEvent (dmxScreen->beDisplay, dmxScreen->rootWin, - cls, 5); + cls, 6); XLIB_EPILOGUE (dmxScreen); } else @@ -1665,6 +1777,7 @@ dmxAddInputDevice (DMXInputInfo *dmxInput, pDevPriv->masterId = masterId; pDevPriv->device = NULL; pDevPriv->fakeGrab = xFalse; + pDevPriv->active = xFalse; pDevPriv->EventCheck = EventCheck; pDevPriv->ReplyCheck = ReplyCheck; diff --git a/hw/dmx/dmxinput.h b/hw/dmx/dmxinput.h index e6bb24959..42ae3beb2 100644 --- a/hw/dmx/dmxinput.h +++ b/hw/dmx/dmxinput.h @@ -40,6 +40,7 @@ typedef struct _dmxDevicePriv { KeyCode *keycode; xcb_void_cookie_t grab; Bool fakeGrab; + Bool active; Bool (*EventCheck) (DeviceIntPtr, xcb_generic_event_t *); Bool (*ReplyCheck) (DeviceIntPtr, unsigned int, xcb_generic_reply_t *);