From 25c6ebbb2c70af7f268036b10dcd8d4a965c34c3 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 9 Dec 2009 00:03:13 +0000 Subject: [PATCH] x11: Discard the LeaveNotify for off-stage ButtonRelease MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the user presses a button on a pointer device and then moves out the Stage X11 will emit the following events: LeaveNotify ➔ MotionNotify ... ➔ ButtonRelease ➔ LeaveNotify The second LeaveNotify differs from the first by the state field. Unfortunately, ClutterCrossingEvent doesn't have a modifier_state field like other events, so we cannot provide a way for programmatically distinguishing them from a Clutter perspective. This is also an X11-ism we might not even want to replicate on every backend with sane enter/leave semantics. For this reason we should check inside the X11 event processing if the pointer device has already left the Stage and ignore the second LeaveNotify. --- clutter/x11/clutter-event-x11.c | 58 +++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/clutter/x11/clutter-event-x11.c b/clutter/x11/clutter-event-x11.c index 6a1eab79e..549fef008 100644 --- a/clutter/x11/clutter-event-x11.c +++ b/clutter/x11/clutter-event-x11.c @@ -417,6 +417,7 @@ event_translate (ClutterBackend *backend, gboolean res, not_yet_handled = FALSE; Window xwindow, stage_xwindow; ClutterDeviceManager *manager; + ClutterInputDevice *device; backend_x11 = CLUTTER_BACKEND_X11 (backend); @@ -674,12 +675,11 @@ event_translate (ClutterBackend *backend, { if (!clutter_x11_has_xinput ()) { + device = clutter_device_manager_get_device (manager, 0); + /* Regular X event */ switch (xevent->type) { - /* KeyPress / KeyRelease should reside here if XInput - * worked properly - */ case ButtonPress: switch (xevent->xbutton.button) { @@ -702,8 +702,7 @@ event_translate (ClutterBackend *backend, event->scroll.x = xevent->xbutton.x; event->scroll.y = xevent->xbutton.y; event->scroll.modifier_state = xevent->xbutton.state; - event->scroll.device = - clutter_device_manager_get_device (manager, 0); + event->scroll.device = device; break; default: @@ -713,8 +712,7 @@ event_translate (ClutterBackend *backend, event->button.y = xevent->xbutton.y; event->button.modifier_state = xevent->xbutton.state; event->button.button = xevent->xbutton.button; - event->button.device = - clutter_device_manager_get_device (manager, 0); + event->button.device = device; break; } @@ -738,8 +736,7 @@ event_translate (ClutterBackend *backend, event->button.y = xevent->xbutton.y; event->button.modifier_state = xevent->xbutton.state; event->button.button = xevent->xbutton.button; - event->button.device = - clutter_device_manager_get_device (manager, 0); + event->button.device = device; break; case MotionNotify: @@ -748,8 +745,7 @@ event_translate (ClutterBackend *backend, event->motion.x = xevent->xmotion.x; event->motion.y = xevent->xmotion.y; event->motion.modifier_state = xevent->xmotion.state; - event->motion.device = - clutter_device_manager_get_device (manager, 0); + event->motion.device = device; break; case EnterNotify: @@ -760,25 +756,35 @@ event_translate (ClutterBackend *backend, event->motion.x = xevent->xcrossing.x; event->motion.y = xevent->xcrossing.y; event->motion.modifier_state = xevent->xcrossing.state; - event->motion.device = - clutter_device_manager_get_device (manager, 0); + event->motion.source = CLUTTER_ACTOR (stage); + event->motion.device = device; /* we know that we are entering the stage here */ - _clutter_input_device_set_stage (event->motion.device, stage); + _clutter_input_device_set_stage (device, stage); CLUTTER_NOTE (EVENT, "Entering the stage"); break; case LeaveNotify: + if (device->stage == NULL) + { + CLUTTER_NOTE (EVENT, + "Discarding LeaveNotify for ButtonRelease " + "event off-stage"); + res = FALSE; + break; + } + event->crossing.type = event->type = CLUTTER_LEAVE; event->crossing.time = xevent->xcrossing.time; event->crossing.x = xevent->xcrossing.x; event->crossing.y = xevent->xcrossing.y; - event->crossing.device = - clutter_device_manager_get_device (manager, 0); + event->crossing.source = CLUTTER_ACTOR (stage); + event->crossing.device = device; /* we know that we are leaving the stage here */ - _clutter_input_device_set_stage (event->crossing.device, NULL); - CLUTTER_NOTE (EVENT, "Leaving the stage"); + _clutter_input_device_set_stage (device, NULL); + CLUTTER_NOTE (EVENT, "Leaving the stage (time:%u)", + event->crossing.time); break; default: @@ -804,6 +810,8 @@ event_translate (ClutterBackend *backend, { XDeviceButtonEvent *xbev = (XDeviceButtonEvent *) xevent; + device = _clutter_x11_get_device_for_xid (xbev->deviceid); + CLUTTER_NOTE (EVENT, "XINPUT Button press event for %li at %d, %d", xbev->deviceid, @@ -831,8 +839,7 @@ event_translate (ClutterBackend *backend, event->scroll.x = xbev->x; event->scroll.y = xbev->y; event->scroll.modifier_state = xbev->state; - event->scroll.device = - _clutter_x11_get_device_for_xid (xbev->deviceid); + event->scroll.device = device; break; default: @@ -842,8 +849,7 @@ event_translate (ClutterBackend *backend, event->button.y = xbev->y; event->button.modifier_state = xbev->state; event->button.button = xbev->button; - event->button.device = - _clutter_x11_get_device_for_xid (xbev->deviceid); + event->button.device = device; break; } @@ -853,6 +859,8 @@ event_translate (ClutterBackend *backend, { XDeviceButtonEvent *xbev = (XDeviceButtonEvent *)xevent; + device = _clutter_x11_get_device_for_xid (xbev->deviceid); + CLUTTER_NOTE (EVENT, "XINPUT Button release event for %li at %d, %d", xbev->deviceid, xbev->x, @@ -873,12 +881,14 @@ event_translate (ClutterBackend *backend, event->button.y = xbev->y; event->button.modifier_state = xbev->state; event->button.button = xbev->button; - event->button.device = _clutter_x11_get_device_for_xid (xbev->deviceid); + event->button.device = device; } else if (xevent->type == motion_notify) { XDeviceMotionEvent *xmev = (XDeviceMotionEvent *)xevent; + device = _clutter_x11_get_device_for_xid (xmev->deviceid); + CLUTTER_NOTE(EVENT, "XINPUT Motion event for %li at %d, %d", xmev->deviceid, xmev->x, @@ -889,7 +899,7 @@ event_translate (ClutterBackend *backend, event->motion.x = xmev->x; event->motion.y = xmev->y; event->motion.modifier_state = xmev->state; - event->motion.device = _clutter_x11_get_device_for_xid (xmev->deviceid); + event->motion.device = device; } #if 0 /* the Xinput handling of key presses/releases disabled for now since