From 521d71d4bc4ca4b06343365c71c9520b1ebfdc7f Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Mon, 1 Feb 2010 15:47:50 +0000 Subject: [PATCH] event: Unify the off-stage motion events delivery behaviour When we disable the per-actor events delivery Clutter replicates the X11 implicit soft grab for motion events with off-stage. The implicit grab is done whenever the pointer of a device leaves a window with a button still pressed; with the implicit grab in place the window still receives motion events even after the LeaveNotify - until the button is released. The implicit grab is not honoured in the per-actor event deliver case, though, so we have a mismatch between two in theory equivalent cases. Luckily, the fix is pretty trivial: when we check for a motion event with a stage set but without an actor set, and that has off-stage coordinates, we arbitrarily set the source to be the stage of the event and emit the pointer event. --- clutter/clutter-main.c | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index 1ac393e..b73a9a6 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -2240,6 +2240,17 @@ emit_keyboard_event (ClutterEvent *event) clutter_actor_event (context->keyboard_grab_actor, event, FALSE); } +static gboolean +is_off_stage (ClutterActor *stage, + gfloat x, + gfloat y) +{ + return (x < 0 || + y < 0 || + x >= clutter_actor_get_width (stage) || + y >= clutter_actor_get_height (stage)); +} + /** * clutter_do_event * @event: a #ClutterEvent. @@ -2360,10 +2371,14 @@ _clutter_process_event_details (ClutterActor *stage, */ if (event->any.source == NULL) { - /* Handle release off stage */ - if ((x >= clutter_actor_get_width (stage) || - y >= clutter_actor_get_height (stage) || - x < 0 || y < 0)) + /* emulate X11 the implicit soft grab; the implicit soft grab + * keeps relaying motion events when the stage is left with a + * pointer button pressed. since this is what happens when we + * disable per-actor motion events we need to maintain the same + * behaviour when the per-actor motion events are enabled as + * well + */ + if (is_off_stage (stage, x, y)) { if (event->type == CLUTTER_BUTTON_RELEASE) { @@ -2373,8 +2388,20 @@ _clutter_process_event_details (ClutterActor *stage, event->button.source = stage; event->button.click_count = 1; + emit_pointer_event (event, device); } + else if (event->type == CLUTTER_MOTION) + { + CLUTTER_NOTE (EVENT, + "Motion off stage received at %.2f, %2.f", + x, y); + + event->motion.source = stage; + + emit_pointer_event (event, device); + } + break; } @@ -2393,9 +2420,10 @@ _clutter_process_event_details (ClutterActor *stage, CLUTTER_PICK_REACTIVE); } - event->any.source = actor; - if (event->any.source == NULL) + if (actor == NULL) break; + + event->any.source = actor; } else { -- 2.7.4