From 1166acd73c1adaeb4f9605a808bacb7f38c60fc0 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Sun, 27 Jan 2019 16:21:31 +0100 Subject: [PATCH] Honor *some* Enter/Leave events with detail==Inferior Commit 19086d70fa9eb made AwesomeWM ignore all Enter/Leave events with detail==Inferior. However, when leaving a titlebar by moving the cursor into the actual client window, the corresponding event actually has detail==Inferior. The same is true for the opposite direction: Leaving a client window by entering the titlebar. Thus, this commit fixes the code to handle theses cases again. This was tested with the following in rc.lua (and with a systray icon and a client with titlebars). screen[1].mywibox:connect_signal("mouse::enter", function() print("enter mywibox") end) screen[1].mywibox:connect_signal("mouse::leave", function() print("leave mywibox") end) client.connect_signal("mouse::enter", function() print("enter client") end) client.connect_signal("mouse::leave", function() print("leave client") end) client.connect_signal("manage", function(c) local d = c:titlebar_top() d:connect_signal("mouse::enter", function() print("enter titlebar") end) d:connect_signal("mouse::leave", function() print("leave titlebar") end) end) Fixes: https://github.com/awesomeWM/awesome/pull/2611#issuecomment-457892746 Signed-off-by: Uli Schlachter --- event.c | 70 +++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 22 deletions(-) diff --git a/event.c b/event.c index 9d730ddc..ddda3a6d 100644 --- a/event.c +++ b/event.c @@ -586,24 +586,38 @@ event_handle_leavenotify(xcb_leave_notify_event_t *ev) * Ignore events with non-normal modes. Those are because a grab * activated/deactivated. Everything will be "back to normal" after the * grab. - * - * Also ignore events with detail "inferior". This means that the window was - * left for a child window, i.e. the pointer is basically still inside of - * our window. */ - if(ev->mode != XCB_NOTIFY_MODE_NORMAL || ev->detail == XCB_NOTIFY_DETAIL_INFERIOR) + if(ev->mode != XCB_NOTIFY_MODE_NORMAL) return; if((c = client_getbyframewin(ev->event))) { - luaA_object_push(L, c); - luaA_object_emit_signal(L, -1, "mouse::leave", 0); + /* The window was left in some way, so definitely no titlebar has the + * mouse cursor. + */ + lua_pushnil(L); + event_drawable_under_mouse(L, -1); + lua_pop(L, 1); + + /* If detail is inferior, it means that the cursor is now in some child + * window of our window. Thus, the titlebar was left, but now the cursor + * is in the actual child window. Thus, ignore detail=Inferior for + * leaving client windows. + */ + if(ev->detail != XCB_NOTIFY_DETAIL_INFERIOR) { + luaA_object_push(L, c); + luaA_object_emit_signal(L, -1, "mouse::leave", 0); + lua_pop(L, 1); + } + } else if(ev->detail != XCB_NOTIFY_DETAIL_INFERIOR) { + /* Some window was left. This must be a drawin. Ignore detail=Inferior, + * because this means that some child window now contains the mouse + * cursor, i.e. a systray window. Everything else is a real 'leave'. + */ + lua_pushnil(L); + event_drawable_under_mouse(L, -1); lua_pop(L, 1); } - - lua_pushnil(L); - event_drawable_under_mouse(L, -1); - lua_pop(L, 1); } /** The enter notify event handler. @@ -622,15 +636,20 @@ event_handle_enternotify(xcb_enter_notify_event_t *ev) * Ignore events with non-normal modes. Those are because a grab * activated/deactivated. Everything will be "back to normal" after the * grab. - * - * Also ignore events with detail "inferior". This means that the cursor was - * previously inside of a child window and now left that child window. For - * our purposes, the cursor was already inside our window before. */ - if(ev->mode != XCB_NOTIFY_MODE_NORMAL || ev->detail == XCB_NOTIFY_DETAIL_INFERIOR) + if(ev->mode != XCB_NOTIFY_MODE_NORMAL) return; - if((drawin = drawin_getbywin(ev->event))) + /* + * We ignore events with detail "inferior". This detail means that the + * cursor was previously inside of a child window and now left that child + * window. For our purposes, the cursor was already inside our window + * before. + * One exception are titlebars: They are not their own window, but are + * "outside of the actual client window". + */ + + if(ev->detail != XCB_NOTIFY_DETAIL_INFERIOR && (drawin = drawin_getbywin(ev->event))) { luaA_object_push(L, drawin); luaA_object_push_item(L, -1, drawin->drawable); @@ -641,18 +660,25 @@ event_handle_enternotify(xcb_enter_notify_event_t *ev) if((c = client_getbyframewin(ev->event))) { luaA_object_push(L, c); - luaA_object_emit_signal(L, -1, "mouse::enter", 0); + /* Detail=Inferior means that a child of the frame window now contains + * the mouse cursor, i.e. the actual client now has the cursor. All + * other details mean that the client itself was really left. + */ + if(ev->detail != XCB_NOTIFY_DETAIL_INFERIOR) { + luaA_object_emit_signal(L, -1, "mouse::enter", 0); + } drawable_t *d = client_get_drawable(c, ev->event_x, ev->event_y); if (d) { luaA_object_push_item(L, -1, d); - event_drawable_under_mouse(L, -1); - lua_pop(L, 1); + } else { + lua_pushnil(L); } - lua_pop(L, 1); + event_drawable_under_mouse(L, -1); + lua_pop(L, 2); } - else if (ev->event == globalconf.screen->root) { + else if (ev->detail != XCB_NOTIFY_DETAIL_INFERIOR && ev->event == globalconf.screen->root) { /* When there are multiple X screens with awesome running separate * instances, reset focus. */