Skip to content

Commit

Permalink
Close distance to dev/better-event-passing
Browse files Browse the repository at this point in the history
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 <tin.svagelj@live.com>
  • Loading branch information
Caellian committed Apr 12, 2024
1 parent 391b9e8 commit 57efc63
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 54 deletions.
88 changes: 37 additions & 51 deletions src/display-x11.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand All @@ -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 */
Expand All @@ -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;
Expand Down Expand Up @@ -690,27 +678,27 @@ 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);
HANDLE_EV(border_crossing);
HANDLE_EV(damage);

// event not handled

// *consumed = false; // old behavior
// we don't want to forward majoriy of events though

return false;
}

Expand All @@ -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);
Expand Down
9 changes: 7 additions & 2 deletions src/x11.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1376,7 +1376,9 @@ int ev_to_mask(int event_type) {
}
}

void propagate_x11_event(XEvent &ev) {
void propagate_x11_event(XEvent &ev, const 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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/x11.h
Original file line number Diff line number Diff line change
Expand Up @@ -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, const void *cookie);

/// @brief Tries getting a list of windows ordered from bottom to top.
///
Expand Down

0 comments on commit 57efc63

Please sign in to comment.