diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index ed99235e6..1094104bd 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -1853,6 +1853,37 @@ clutter_event_get_device (ClutterEvent *event) return NULL; } +static void +set_motion_last_actor (ClutterActor *motion_current_actor, + ClutterInputDevice *device) +{ + ClutterMainContext *context = ClutterCntx; + ClutterActor *last_actor = context->motion_last_actor; + + if (device != NULL) + last_actor = device->motion_last_actor; + + if (last_actor && last_actor != motion_current_actor) + { + g_signal_handlers_disconnect_by_func + (last_actor, + G_CALLBACK (unset_motion_last_actor), + device); + } + + if (motion_current_actor && last_actor != motion_current_actor) + { + g_signal_connect (motion_current_actor, "destroy", + G_CALLBACK (unset_motion_last_actor), + device); + } + + if (device != NULL) + device->motion_last_actor = motion_current_actor; + else + context->motion_last_actor = motion_current_actor; +} + static inline void generate_enter_leave_events (ClutterEvent *event) { @@ -1905,25 +1936,7 @@ generate_enter_leave_events (ClutterEvent *event) } } - if (last_actor && last_actor != motion_current_actor) - { - g_signal_handlers_disconnect_by_func - (last_actor, - G_CALLBACK (unset_motion_last_actor), - device); - } - - if (motion_current_actor && last_actor != motion_current_actor) - { - g_signal_connect (motion_current_actor, "destroy", - G_CALLBACK (unset_motion_last_actor), - device); - } - - if (device != NULL) - device->motion_last_actor = motion_current_actor; - else - context->motion_last_actor = motion_current_actor; + set_motion_last_actor (motion_current_actor, event->motion.device); } /** @@ -1965,8 +1978,23 @@ clutter_do_event (ClutterEvent *event) event->any.source = stage; break; - case CLUTTER_ENTER: case CLUTTER_LEAVE: + /* The source is set for generated events, not for events + * resulting from the cursor leaving the stage + */ + if (event->any.source == NULL) + { + ClutterActor *last_actor = context->motion_last_actor; + + if (event->crossing.device != NULL) + last_actor = event->crossing.device->motion_last_actor; + + event->any.source = last_actor; + + set_motion_last_actor (NULL, event->crossing.device); + } + /* flow through */ + case CLUTTER_ENTER: emit_pointer_event (event, event->crossing.device); break; diff --git a/clutter/eglx/clutter-stage-egl.c b/clutter/eglx/clutter-stage-egl.c index e3ceae98d..5add2a862 100644 --- a/clutter/eglx/clutter-stage-egl.c +++ b/clutter/eglx/clutter-stage-egl.c @@ -185,6 +185,7 @@ clutter_stage_egl_realize (ClutterActor *actor) StructureNotifyMask | FocusChangeMask | ExposureMask | + EnterWindowMask | LeaveWindowMask | PropertyChangeMask); #ifdef USE_XINPUT _clutter_x11_select_events (stage_x11->xwin); @@ -198,6 +199,7 @@ clutter_stage_egl_realize (ClutterActor *actor) PointerMotionMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | + EnterWindowMask | LeaveWindowMask | PropertyChangeMask); } diff --git a/clutter/glx/clutter-stage-glx.c b/clutter/glx/clutter-stage-glx.c index b5aa6db80..f50225a00 100644 --- a/clutter/glx/clutter-stage-glx.c +++ b/clutter/glx/clutter-stage-glx.c @@ -189,6 +189,7 @@ clutter_stage_glx_realize (ClutterActor *actor) FocusChangeMask | ExposureMask | KeyPressMask | KeyReleaseMask | + EnterWindowMask | LeaveWindowMask | PropertyChangeMask); #ifdef USE_XINPUT _clutter_x11_select_events (stage_x11->xwin); @@ -202,6 +203,7 @@ clutter_stage_glx_realize (ClutterActor *actor) PointerMotionMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | + EnterWindowMask | LeaveWindowMask | PropertyChangeMask); } diff --git a/clutter/x11/clutter-event-x11.c b/clutter/x11/clutter-event-x11.c index aed0446c6..634a3c71a 100644 --- a/clutter/x11/clutter-event-x11.c +++ b/clutter/x11/clutter-event-x11.c @@ -666,6 +666,24 @@ event_translate (ClutterBackend *backend, event->motion.y = xevent->xmotion.y; event->motion.modifier_state = xevent->xmotion.state; break; + + case EnterNotify: + /* Convert enter notifies to motion events because X + doesn't emit the corresponding motion notify */ + event->motion.type = event->type = CLUTTER_MOTION; + event->motion.time = xevent->xcrossing.time; + event->motion.x = xevent->xcrossing.x; + event->motion.y = xevent->xcrossing.y; + event->motion.modifier_state = xevent->xcrossing.state; + break; + + case LeaveNotify: + 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; + break; + default: /* ignore every other event */ res = FALSE;