handle ButtonPress events with child != XCB_NONE (Thanks xeen)

The X11 protocol description states:

  The window the event is reported with respect to is called the event
  window. The event window is found by starting with the source window
  and looking up the hierarchy for the first window on which any client
  has selected interest in the event.

For the case of urxvt with URxvt.internalBorder > 0, urxvt sets up a
subwindow for its actual contents that is placed “in the middle” of the
urxvt window. In terms of the X11 protocol, the source window is urxvt’s
window, but urxvt does not select ButtonPress events for that.
Therefore, X11 will go up in the hierarchy and deliver the event to i3
for i3’s window decoration, even though this was not actually a click on
the decoration, but into the managed window.

Therefore, we check whether child != XCB_NONE for clicks on window
decorations and then handle them as a click inside the window.

fixes #1176
This commit is contained in:
Michael Stapelberg 2014-02-09 14:00:43 +01:00
parent 22be7bc986
commit 491274d8b3

View File

@ -311,7 +311,9 @@ done:
*/ */
int handle_button_press(xcb_button_press_event_t *event) { int handle_button_press(xcb_button_press_event_t *event) {
Con *con; Con *con;
DLOG("Button %d pressed on window 0x%08x\n", event->state, event->event); DLOG("Button %d pressed on window 0x%08x (child 0x%08x) at (%d, %d) (root %d, %d)\n",
event->state, event->event, event->child, event->event_x, event->event_y,
event->root_x, event->root_y);
last_timestamp = event->time; last_timestamp = event->time;
@ -347,6 +349,11 @@ int handle_button_press(xcb_button_press_event_t *event) {
return 0; return 0;
} }
if (event->child != XCB_NONE) {
DLOG("event->child not XCB_NONE, so this is an event which originated from a click into the application, but the application did not handle it.\n");
return route_click(con, event, mod_pressed, CLICK_INSIDE);
}
/* Check if the click was on the decoration of a child */ /* Check if the click was on the decoration of a child */
Con *child; Con *child;
TAILQ_FOREACH(child, &(con->nodes_head), nodes) { TAILQ_FOREACH(child, &(con->nodes_head), nodes) {