From f6131609176361c3221059000c096e34366c8a67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tin=20=C5=A0vagelj?= Date: Fri, 12 Apr 2024 06:44:53 +0200 Subject: [PATCH] Close distance to dev/better-event-passing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit is final refactor commit that's fully functional and contains fixes to old bugs and previously introduced regressions. There's some extra arguments (cookie) that aren't used yet, but will be in commits that succeed this one. Signed-off-by: Tin Å vagelj --- src/display-x11.cc | 88 +++++++++++++++++++--------------------------- src/x11.cc | 9 +++-- src/x11.h | 2 +- 3 files changed, 45 insertions(+), 54 deletions(-) diff --git a/src/display-x11.cc b/src/display-x11.cc index 78a9144e6c..3dade66a66 100644 --- a/src/display-x11.cc +++ b/src/display-x11.cc @@ -234,6 +234,9 @@ bool display_output_x11::shutdown() { return true; } +void process_surface_events(conky::display_output_x11 *surface, + Display *display); + bool display_output_x11::main_loop_wait(double t) { /* wait for X event or timeout */ if (!display || !window.gc) return true; @@ -423,12 +426,11 @@ bool display_output_x11::main_loop_wait(double t) { #define EV_HANDLER(name) \ bool _conky_ev_handle_##name(conky::display_output_x11 *surface, \ Display *display, XEvent &ev, bool *consumed, \ - bool *focus) + void **cookie) #ifdef OWN_WINDOW -#ifdef BUILD_MOUSE_EVENTS #ifdef BUILD_XINPUT -EV_HANDLER(mouse_input) { +EV_HANDLER(xinput_motion) { if (ev.type != GenericEvent || ev.xcookie.extension != window.xi_opcode) return false; @@ -470,30 +472,29 @@ EV_HANDLER(mouse_input) { data->root_y < (window.y + window.height))); if (cursor_over_conky) { if (!cursor_inside) { - *consumed = llua_mouse_hook(mouse_crossing_event( + llua_mouse_hook(mouse_crossing_event( mouse_event_t::AREA_ENTER, data->root_x - window.x, data->root_y - window.x, data->root_x, data->root_y)); } cursor_inside = true; } else if (cursor_inside) { - *consumed = llua_mouse_hook(mouse_crossing_event( + llua_mouse_hook(mouse_crossing_event( mouse_event_t::AREA_LEAVE, data->root_x - window.x, data->root_y - window.x, data->root_x, data->root_y)); cursor_inside = false; } } - // TODO: Handle other events - XFreeEventData(display, &ev.xcookie); return true; } -#else /* BUILD_XINPUT */ +#endif /* BUILD_XINPUT */ EV_HANDLER(mouse_input) { if (ev.type != ButtonPress && ev.type != ButtonRelease && ev.type != MotionNotify) return false; if (ev.xany.window != window.window) return true; // Skip other windows +#ifdef BUILD_MOUSE_EVENTS switch (ev.type) { case ButtonPress: { modifier_state_t mods = x11_modifier_state(ev.xbutton.state); @@ -509,7 +510,6 @@ EV_HANDLER(mouse_input) { mouse_event_t::MOUSE_PRESS, ev.xbutton.x, ev.xbutton.y, ev.xbutton.x_root, ev.xbutton.y_root, button, mods)); } - return true; } case ButtonRelease: { /* don't report scroll release events */ @@ -520,49 +520,37 @@ EV_HANDLER(mouse_input) { *consumed = llua_mouse_hook(mouse_button_event( mouse_event_t::MOUSE_RELEASE, ev.xbutton.x, ev.xbutton.y, ev.xbutton.x_root, ev.xbutton.y_root, button, mods)); - return true; } case MotionNotify: { modifier_state_t mods = x11_modifier_state(ev.xmotion.state); *consumed = llua_mouse_hook(mouse_move_event(ev.xmotion.x, ev.xmotion.y, ev.xmotion.x_root, ev.xmotion.y_root, mods)); - return true; } - default: - return false; // unreachable } -} -#endif /* BUILD_XINPUT */ #else /* BUILD_MOUSE_EVENTS */ -EV_HANDLER(mouse_input) { - if (ev.type != ButtonPress && ev.type != ButtonRelease && - ev.type != MotionNotify) - return false; - if (ev.xany.window != window.window) return true; // Skip other windows // always propagate mouse input if not handling mouse events *consumed = false; +#endif /* BUILD_MOUSE_EVENTS */ - // don't focus if not a click - if (ev.type != ButtonPress) return true; - - // skip if not own_window if (!own_window.get(*state)) return true; - - // don't focus if normal but undecorated - if (own_window_type.get(*state) == TYPE_NORMAL && - TEST_HINT(own_window_hints.get(*state), HINT_UNDECORATED)) - return true; - - // don't force focus if desktop window - if (own_window_type.get(*state) == TYPE_DESKTOP) return true; - - // finally, else focus - *focus = true; + switch (own_window_type.get(*state)) { + case window_type::TYPE_NORMAL: + case window_type::TYPE_UTILITY: + // decorated normal windows always consume events + if (!TEST_HINT(own_window_hints.get(*state), HINT_UNDECORATED)) { + *consumed = true; + } + break; + case window_type::TYPE_DESKTOP: + // assume conky is always on bottom; nothing to propagate events to + *consumed = true; + default: + break; + } return true; } -#endif /* BUILD_MOUSE_EVENTS */ #endif /* OWN_WINDOW */ EV_HANDLER(property_notify) { if (ev.type != PropertyNotify) return false; @@ -690,16 +678,20 @@ EV_HANDLER(damage) { return false; } /// /// @return true if event should move input focus to conky bool process_event(conky::display_output_x11 *surface, Display *display, - XEvent ev, bool *consumed, bool *focus) { -#define HANDLE_EV(handler) \ - if (_conky_ev_handle_##handler(surface, display, ev, consumed, focus)) \ + XEvent ev, bool *consumed, void **cookie) { +#define HANDLE_EV(handler) \ + if (_conky_ev_handle_##handler(surface, display, ev, consumed, cookie)) \ return true +#ifdef BUILD_XINPUT + // handles enter & leave events better + HANDLE_EV(xinput_motion); +#endif /* BUILD_XINPUT */ HANDLE_EV(mouse_input); HANDLE_EV(property_notify); // only accept remaining events if they're sent to Conky. - if (ev.xany.window != window.window) return; + if (ev.xany.window != window.window) return false; HANDLE_EV(expose); HANDLE_EV(reparent); @@ -707,10 +699,6 @@ bool process_event(conky::display_output_x11 *surface, Display *display, HANDLE_EV(damage); // event not handled - - // *consumed = false; // old behavior - // we don't want to forward majoriy of events though - return false; } @@ -732,14 +720,12 @@ void process_surface_events(conky::display_output_x11 *surface, consumed. */ bool consumed = true; - bool focus = false; - process_event(surface, display, ev, &consumed, &focus); + void *cookie = nullptr; + bool handled = process_event(surface, display, ev, &consumed, &cookie); - if (!consumed) { - propagate_x11_event(ev); - } else if (focus) { - XSetInputFocus(display, window.window, RevertToParent, CurrentTime); - } + if (!consumed) { propagate_x11_event(ev, cookie); } + + if (cookie != nullptr) { free(cookie); } } DBGP2("Done processing %d events.", pending); diff --git a/src/x11.cc b/src/x11.cc index 9acdfe3c57..d6500673af 100644 --- a/src/x11.cc +++ b/src/x11.cc @@ -1376,7 +1376,9 @@ int ev_to_mask(int event_type) { } } -void propagate_x11_event(XEvent &ev) { +void propagate_x11_event(XEvent &ev, void *cookie) { + bool focus = ev.type == ButtonPress; + InputEvent *i_ev = xev_as_input_event(ev); if (i_ev == nullptr) { // Not a known input event; blindly propagating them causes loops and all @@ -1410,7 +1412,10 @@ void propagate_x11_event(XEvent &ev) { } XUngrabPointer(display, CurrentTime); - XSendEvent(display, i_ev->common.window, False, ev_to_mask(i_ev->type), &ev); + XSendEvent(display, i_ev->common.window, True, ev_to_mask(i_ev->type), &ev); + if (focus) { + XSetInputFocus(display, i_ev->common.window, RevertToParent, CurrentTime); + } } /// @brief This function returns the last descendant of a window (leaf) on the diff --git a/src/x11.h b/src/x11.h index 48ccad425a..d18dff39a4 100644 --- a/src/x11.h +++ b/src/x11.h @@ -157,7 +157,7 @@ union InputEvent { // Returns InputEvent pointer to provided XEvent is an input event; nullptr // otherwise. InputEvent *xev_as_input_event(XEvent &ev); -void propagate_x11_event(XEvent &ev); +void propagate_x11_event(XEvent &ev, void *cookie); /// @brief Tries getting a list of windows ordered from bottom to top. ///