From 1b45d95e269e9783f5d49a62480ded09334e70d2 Mon Sep 17 00:00:00 2001 From: Tin Date: Mon, 13 Nov 2023 11:39:13 +0100 Subject: [PATCH] Use core X11 events when Xinput is enabled There was no way to propagate move events otherwise Also, clang-format decided to kick in and reformat Xinput related code... Signed-off-by: Tin --- src/display-x11.cc | 175 +++++++++++++++++++++++---------------------- src/x11.cc | 4 +- 2 files changed, 90 insertions(+), 89 deletions(-) diff --git a/src/display-x11.cc b/src/display-x11.cc index 6f7beb21..9c2091c0 100644 --- a/src/display-x11.cc +++ b/src/display-x11.cc @@ -51,10 +51,10 @@ #endif /* BUILD_MOUSE_EVENTS */ #endif /* BUILD_X11 */ +#include #include #include #include -#include #include #include "colours.h" @@ -66,8 +66,8 @@ /* TODO: cleanup global namespace */ #ifdef BUILD_X11 -#include "x11.h" #include "logging.h" +#include "x11.h" // TODO: cleanup externs (move to conky.h ?) #ifdef OWN_WINDOW @@ -381,58 +381,61 @@ bool display_output_x11::main_loop_wait(double t) { bool consumed = false; XNextEvent(display, &ev); - + #if defined(OWN_WINDOW) && defined(BUILD_MOUSE_EVENTS) && defined(BUILD_XINPUT) - // no need to check whether these events have been consumed because - // they're global and shouldn't be propagated - if (ev.type == GenericEvent && ev.xcookie.extension == window.xi_opcode) { - if (!XGetEventData(display, &ev.xcookie)) { - NORM_ERR("unable to get XInput event data"); - continue; - } - - auto *data = reinterpret_cast(ev.xcookie.data); - - // the only way to differentiate between a scroll and move event is - // though valuators - move has first 2 set, other axis movements have other. - bool is_cursor_move = data->valuators.mask_len > 2 && - XIMaskIsSet(data->valuators.mask, 0) && XIMaskIsSet(data->valuators.mask, 1); - - if (data->evtype == XI_Motion && is_cursor_move) { - Window query_result = query_x11_window_at_pos(display, data->root_x, data->root_y); - - static bool cursor_inside = false; - if ((query_result != 0 && query_result == window.window) || - ((query_result == window.desktop || query_result == window.root || query_result == 0) && data->root_x >= window.x && data->root_x < (window.x + window.width) && - data->root_y >= window.y && data->root_y < (window.y + window.height))) { - // cursor is inside conky - - modifier_state_t mods = x11_modifier_state(data->mods.effective); - llua_mouse_hook(mouse_move_event( - data->root_x - window.x, data->root_y - window.x, - data->root_x, data->root_y, mods - )); - - if (!cursor_inside) { - 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) { - 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; - } - } - XFreeEventData(display, &ev.xcookie); + // no need to check whether these events have been consumed because + // they're global and shouldn't be propagated + if (ev.type == GenericEvent && ev.xcookie.extension == window.xi_opcode) { + if (!XGetEventData(display, &ev.xcookie)) { + NORM_ERR("unable to get XInput event data"); continue; } + + auto *data = reinterpret_cast(ev.xcookie.data); + + // the only way to differentiate between a scroll and move event is + // though valuators - move has first 2 set, other axis movements have + // other. + bool is_cursor_move = data->valuators.mask_len * 8 > 2 && + XIMaskIsSet(data->valuators.mask, 0) && + XIMaskIsSet(data->valuators.mask, 1); + for (size_t i = 2; i < data->valuators.mask_len * 8; i++) { + if (XIMaskIsSet(data->valuators.mask, i)) { + is_cursor_move = false; + break; + } + } + + if (data->evtype == XI_Motion && is_cursor_move) { + Window query_result = + query_x11_window_at_pos(display, data->root_x, data->root_y); + + static bool cursor_inside = false; + if ((query_result != 0 && query_result == window.window) || + ((query_result == window.desktop || query_result == window.root || + query_result == 0) && + data->root_x >= window.x && + data->root_x < (window.x + window.width) && + data->root_y >= window.y && + data->root_y < (window.y + window.height))) { + // cursor is inside conky + + if (!cursor_inside) { + 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) { + 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; + } + } + XFreeEventData(display, &ev.xcookie); + continue; + } #endif /* BUILD_MOUSE_EVENTS && BUILD_XINPUT */ // Any of the remaining events apply to conky window @@ -525,24 +528,21 @@ bool display_output_x11::main_loop_wait(double t) { case ButtonPress: #ifdef BUILD_MOUSE_EVENTS - { - modifier_state_t mods = x11_modifier_state(ev.xbutton.state); - if (4 <= ev.xbutton.button && ev.xbutton.button <= 7) { - scroll_direction_t direction = x11_scroll_direction(ev.xbutton.button); - consumed = llua_mouse_hook(mouse_scroll_event( - ev.xbutton.x, ev.xbutton.y, - ev.xbutton.x_root, ev.xbutton.y_root, - direction, mods - )); - } else { - mouse_button_t button = x11_mouse_button_code(ev.xbutton.button); - consumed = llua_mouse_hook(mouse_button_event( - mouse_event_t::MOUSE_PRESS, - ev.xbutton.x, ev.xbutton.y, ev.xbutton.x_root, ev.xbutton.y_root, - button, mods - )); - } + { + modifier_state_t mods = x11_modifier_state(ev.xbutton.state); + if (4 <= ev.xbutton.button && ev.xbutton.button <= 7) { + scroll_direction_t direction = + x11_scroll_direction(ev.xbutton.button); + consumed = llua_mouse_hook( + mouse_scroll_event(ev.xbutton.x, ev.xbutton.y, ev.xbutton.x_root, + ev.xbutton.y_root, direction, mods)); + } else { + mouse_button_t button = x11_mouse_button_code(ev.xbutton.button); + consumed = llua_mouse_hook(mouse_button_event( + mouse_event_t::MOUSE_PRESS, ev.xbutton.x, ev.xbutton.y, + ev.xbutton.x_root, ev.xbutton.y_root, button, mods)); } + } #endif /* BUILD_MOUSE_EVENTS */ if (own_window.get(*state)) { /* if an ordinary window with decorations */ @@ -562,10 +562,8 @@ bool display_output_x11::main_loop_wait(double t) { modifier_state_t mods = x11_modifier_state(ev.xbutton.state); mouse_button_t button = x11_mouse_button_code(ev.xbutton.button); 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 - )); + mouse_event_t::MOUSE_RELEASE, ev.xbutton.x, ev.xbutton.y, + ev.xbutton.x_root, ev.xbutton.y_root, button, mods)); } #endif /* BUILD_MOUSE_EVENTS */ if (own_window.get(*state)) { @@ -582,26 +580,28 @@ bool display_output_x11::main_loop_wait(double t) { windows below are notified for the following events as well; can't forward the event without filtering XQueryTree output. */ - case MotionNotify: - if (window.xi_opcode == 0) { - 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 - )); - } - break; + 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)); + } break; case LeaveNotify: case EnterNotify: if (window.xi_opcode == 0) { - bool not_over_conky = ev.xcrossing.x_root <= window.x || ev.xcrossing.y_root <= window.y || - ev.xcrossing.x_root >= window.x + window.width || ev.xcrossing.y_root >= window.y + window.height; + bool not_over_conky = + ev.xcrossing.x_root <= window.x || + ev.xcrossing.y_root <= window.y || + ev.xcrossing.x_root >= window.x + window.width || + ev.xcrossing.y_root >= window.y + window.height; if ((not_over_conky && ev.xcrossing.type == LeaveNotify) || (!not_over_conky && ev.xcrossing.type == EnterNotify)) { llua_mouse_hook(mouse_crossing_event( - ev.xcrossing.type == EnterNotify ? mouse_event_t::AREA_ENTER : mouse_event_t::AREA_LEAVE, - ev.xcrossing.x, ev.xcrossing.y, ev.xcrossing.x_root, ev.xcrossing.y_root - )); + ev.xcrossing.type == EnterNotify ? mouse_event_t::AREA_ENTER + : mouse_event_t::AREA_LEAVE, + ev.xcrossing.x, ev.xcrossing.y, ev.xcrossing.x_root, + ev.xcrossing.y_root)); } } // can't propagate these events in a way that makes sense for desktop @@ -616,7 +616,7 @@ bool display_output_x11::main_loop_wait(double t) { XFixesSetRegion(display, x11_stuff.part, &dev->area, 1); XFixesUnionRegion(display, x11_stuff.region2, x11_stuff.region2, x11_stuff.part); - continue; // TODO: Propagate damage + continue; // TODO: Propagate damage } #endif /* BUILD_XDAMAGE */ break; @@ -627,7 +627,8 @@ bool display_output_x11::main_loop_wait(double t) { } else { InputEvent *i_ev = xev_as_input_event(ev); if (i_ev != nullptr) { - XSetInputFocus(display, window.window, RevertToParent, i_ev->common.time); + XSetInputFocus(display, window.window, RevertToParent, + i_ev->common.time); } } } diff --git a/src/x11.cc b/src/x11.cc index 5a1674dc..0e6ae02f 100644 --- a/src/x11.cc +++ b/src/x11.cc @@ -942,7 +942,7 @@ void x11_init_window(lua::state &l, bool own) { /* it's not recommended to add event masks to special windows in X; causes a * crash */ if (own && own_window_type.get(l) != TYPE_DESKTOP) { - input_mask |= ButtonPressMask | ButtonReleaseMask; + input_mask |= PointerMotionMask | ButtonPressMask | ButtonReleaseMask; } bool xinput_ok = false; #ifdef BUILD_XINPUT @@ -975,7 +975,7 @@ void x11_init_window(lua::state &l, bool own) { } while (false); #endif /* BUILD_XINPUT */ if (!xinput_ok && own && own_window_type.get(l) != TYPE_DESKTOP) { - input_mask |= PointerMotionMask | EnterWindowMask | LeaveWindowMask; + input_mask |= EnterWindowMask | LeaveWindowMask; } #endif /* BUILD_MOUSE_EVENTS */ #endif /* OWN_WINDOW */