From 42e00819584c9cdb6f79fca317ebdb0d36902f10 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Thu, 17 Sep 2015 16:32:56 +0200 Subject: [PATCH] Fix enter/leave events on titlebars This adds a global variable that tracks the drawable that is currently under the mouse cursor. This new variable is then used so that we get consistent behavior for enter/leave signals. Such signals are now also generated when a MotionNotify event tells us that the pointer is now in a different titlebar. Before this, it was possible that we did not generate a leave event on a titlebar since the LeaveNotify contains the cursor position after the leave and we did not manage to figure out which titlebar was left. Signed-off-by: Uli Schlachter --- event.c | 63 +++++++++++++++++++++++++++++++++++++--------------- globalconf.h | 2 ++ 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/event.c b/event.c index a480c5f1c..b9b0b751e 100644 --- a/event.c +++ b/event.c @@ -411,6 +411,44 @@ event_handle_destroynotify(xcb_destroy_notify_event_t *ev) } } +/** Record that the given drawable contains the pointer. + */ +static void +event_drawable_under_mouse(lua_State *L, int ud) +{ + void *d; + + lua_pushvalue(L, ud); + d = luaA_object_ref(L, -1); + + if (d == globalconf.drawable_under_mouse) + { + /* Nothing to do */ + luaA_object_unref(L, d); + return; + } + + if (globalconf.drawable_under_mouse != NULL) + { + /* Emit leave on previous drawable */ + luaA_object_push(L, globalconf.drawable_under_mouse); + luaA_object_emit_signal(L, -1, "mouse::leave", 0); + lua_pop(L, 1); + + /* Unref the previous drawable */ + luaA_object_unref(L, globalconf.drawable_under_mouse); + globalconf.drawable_under_mouse = NULL; + } + if (d != NULL) + { + /* Reference the drawable for leave event later */ + globalconf.drawable_under_mouse = d; + + /* Emit enter */ + luaA_object_emit_signal(L, ud, "mouse::enter", 0); + } +} + /** The motion notify event handler. * \param ev The event. */ @@ -439,6 +477,7 @@ event_handle_motionnotify(xcb_motion_notify_event_t *ev) if (d) { luaA_object_push_item(L, -1, d); + event_drawable_under_mouse(L, -1); lua_pushnumber(L, x); lua_pushnumber(L, y); luaA_object_emit_signal(L, -3, "mouse::move", 2); @@ -451,6 +490,7 @@ event_handle_motionnotify(xcb_motion_notify_event_t *ev) { luaA_object_push(L, w); luaA_object_push_item(L, -1, w->drawable); + event_drawable_under_mouse(L, -1); lua_pushnumber(L, ev->event_x); lua_pushnumber(L, ev->event_y); luaA_object_emit_signal(L, -3, "mouse::move", 2); @@ -465,7 +505,6 @@ static void event_handle_leavenotify(xcb_leave_notify_event_t *ev) { lua_State *L = globalconf_get_lua_State(); - drawin_t *drawin; client_t *c; globalconf.timestamp = ev->time; @@ -477,23 +516,11 @@ event_handle_leavenotify(xcb_leave_notify_event_t *ev) { luaA_object_push(L, c); luaA_object_emit_signal(L, -1, "mouse::leave", 0); - drawable_t *d = client_get_drawable(c, ev->event_x, ev->event_y); - if (d) - { - luaA_object_push_item(L, -1, d); - luaA_object_emit_signal(L, -1, "mouse::leave", 0); - lua_pop(L, 1); - } - lua_pop(L, 1); } - if((drawin = drawin_getbywin(ev->event))) - { - luaA_object_push(L, drawin); - luaA_object_push_item(L, -1, drawin->drawable); - luaA_object_emit_signal(L, -1, "mouse::leave", 0); - lua_pop(L, 2); - } + lua_pushnil(L); + event_drawable_under_mouse(L, -1); + lua_pop(L, 1); } /** The enter notify event handler. @@ -515,7 +542,7 @@ event_handle_enternotify(xcb_enter_notify_event_t *ev) { luaA_object_push(L, drawin); luaA_object_push_item(L, -1, drawin->drawable); - luaA_object_emit_signal(L, -1, "mouse::enter", 0); + event_drawable_under_mouse(L, -1); lua_pop(L, 2); } @@ -527,7 +554,7 @@ event_handle_enternotify(xcb_enter_notify_event_t *ev) if (d) { luaA_object_push_item(L, -1, d); - luaA_object_emit_signal(L, -1, "mouse::enter", 0); + event_drawable_under_mouse(L, -1); lua_pop(L, 1); } lua_pop(L, 1); diff --git a/globalconf.h b/globalconf.h index 2139bc580..29a9d6a52 100644 --- a/globalconf.h +++ b/globalconf.h @@ -108,6 +108,8 @@ typedef struct int keygrabber; /** The mouse pointer grabber function */ int mousegrabber; + /** The drawable that currently contains the pointer */ + drawable_t *drawable_under_mouse; /** Input focus information */ struct {