Only grab the mouse buttons that need to be grabbed. (#2290)

This is a followup to #2049. While we had fixed that bug by only grabbing
buttons 4 and 5 if there is a whole-window binding for that button, this
did not consider buttons higher than 5 as found on many mice.

Therefore, we now ditch the special handling for scrollwheel buttons and
instead do the same for all buttons higher than 3.

fixes #2271
This commit is contained in:
Ingo Bürk 2016-04-13 19:45:57 +02:00 committed by Michael Stapelberg
parent 0060586190
commit 83c8740bf1
5 changed files with 51 additions and 34 deletions

View File

@ -104,10 +104,10 @@ CommandResult *run_binding(Binding *bind, Con *con);
bool load_keymap(void); bool load_keymap(void);
/** /**
* Returns true if the current config has any binding to a scroll wheel button * Returns a list of buttons that should be grabbed on a window.
* (4 or 5) which is a whole-window binding. * This list will always contain 13, all higher buttons will only be returned
* We need this to figure out whether we should grab all buttons or just 1-3 * if there is a whole-window binding for it on some window in the current
* when managing a window. See #2049. * config.
* * The list is terminated by a 0.
*/ */
bool bindings_should_grab_scrollwheel_buttons(void); int *bindings_get_buttons_to_grab(void);

View File

@ -171,4 +171,4 @@ void xcb_remove_property_atom(xcb_connection_t *conn, xcb_window_t window, xcb_a
* Grab the specified buttons on a window when managing it. * Grab the specified buttons on a window when managing it.
* *
*/ */
void xcb_grab_buttons(xcb_connection_t *conn, xcb_window_t window, bool bind_scrollwheel); void xcb_grab_buttons(xcb_connection_t *conn, xcb_window_t window, int *buttons);

View File

@ -152,7 +152,7 @@ void grab_all_keys(xcb_connection_t *conn) {
* *
*/ */
void regrab_all_buttons(xcb_connection_t *conn) { void regrab_all_buttons(xcb_connection_t *conn) {
bool grab_scrollwheel = bindings_should_grab_scrollwheel_buttons(); int *buttons = bindings_get_buttons_to_grab();
xcb_grab_server(conn); xcb_grab_server(conn);
Con *con; Con *con;
@ -161,9 +161,10 @@ void regrab_all_buttons(xcb_connection_t *conn) {
continue; continue;
xcb_ungrab_button(conn, XCB_BUTTON_INDEX_ANY, con->window->id, XCB_BUTTON_MASK_ANY); xcb_ungrab_button(conn, XCB_BUTTON_INDEX_ANY, con->window->id, XCB_BUTTON_MASK_ANY);
xcb_grab_buttons(conn, con->window->id, grab_scrollwheel); xcb_grab_buttons(conn, con->window->id, buttons);
} }
FREE(buttons);
xcb_ungrab_server(conn); xcb_ungrab_server(conn);
} }
@ -811,15 +812,30 @@ bool load_keymap(void) {
} }
/* /*
* Returns true if the current config has any binding to a scroll wheel button * Returns a list of buttons that should be grabbed on a window.
* (4 or 5) which is a whole-window binding. * This list will always contain 13, all higher buttons will only be returned
* We need this to figure out whether we should grab all buttons or just 1-3 * if there is a whole-window binding for it on some window in the current
* when managing a window. See #2049. * config.
* * The list is terminated by a 0.
*/ */
bool bindings_should_grab_scrollwheel_buttons(void) { int *bindings_get_buttons_to_grab(void) {
/* Let's make the reasonable assumption that there's no more than 25
* buttons. */
int num_max = 25;
int buffer[num_max];
int num = 0;
/* We always return buttons 1 through 3. */
buffer[num++] = 1;
buffer[num++] = 2;
buffer[num++] = 3;
Binding *bind; Binding *bind;
TAILQ_FOREACH(bind, bindings, bindings) { TAILQ_FOREACH(bind, bindings, bindings) {
if (num + 1 == num_max)
break;
/* We are only interested in whole window mouse bindings. */ /* We are only interested in whole window mouse bindings. */
if (bind->input_type != B_MOUSE || !bind->whole_window) if (bind->input_type != B_MOUSE || !bind->whole_window)
continue; continue;
@ -831,11 +847,18 @@ bool bindings_should_grab_scrollwheel_buttons(void) {
continue; continue;
} }
/* If the binding is for either scrollwheel button, we need to grab everything. */ /* Avoid duplicates. */
if (button == 4 || button == 5) { for (int i = 0; i < num_max; i++) {
return true; if (buffer[i] == button)
} continue;
} }
return false; buffer[num++] = button;
}
buffer[num++] = 0;
int *buttons = scalloc(num, sizeof(int));
memcpy(buttons, buffer, num * sizeof(int));
return buttons;
} }

View File

@ -170,7 +170,9 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
cwindow->id = window; cwindow->id = window;
cwindow->depth = get_visual_depth(attr->visual); cwindow->depth = get_visual_depth(attr->visual);
xcb_grab_buttons(conn, window, bindings_should_grab_scrollwheel_buttons()); int *buttons = bindings_get_buttons_to_grab();
xcb_grab_buttons(conn, window, buttons);
FREE(buttons);
/* update as much information as possible so far (some replies may be NULL) */ /* update as much information as possible so far (some replies may be NULL) */
window_update_class(cwindow, xcb_get_property_reply(conn, class_cookie, NULL), true); window_update_class(cwindow, xcb_get_property_reply(conn, class_cookie, NULL), true);

View File

@ -346,20 +346,12 @@ release_grab:
* Grab the specified buttons on a window when managing it. * Grab the specified buttons on a window when managing it.
* *
*/ */
void xcb_grab_buttons(xcb_connection_t *conn, xcb_window_t window, bool bind_scrollwheel) { void xcb_grab_buttons(xcb_connection_t *conn, xcb_window_t window, int *buttons) {
uint8_t buttons[3]; int i = 0;
int num = 0; while (buttons[i] > 0) {
if (bind_scrollwheel) {
buttons[num++] = XCB_BUTTON_INDEX_ANY;
} else {
buttons[num++] = XCB_BUTTON_INDEX_1;
buttons[num++] = XCB_BUTTON_INDEX_2;
buttons[num++] = XCB_BUTTON_INDEX_3;
}
for (int i = 0; i < num; i++) {
xcb_grab_button(conn, false, window, XCB_EVENT_MASK_BUTTON_PRESS, XCB_GRAB_MODE_SYNC, xcb_grab_button(conn, false, window, XCB_EVENT_MASK_BUTTON_PRESS, XCB_GRAB_MODE_SYNC,
XCB_GRAB_MODE_ASYNC, root, XCB_NONE, buttons[i], XCB_BUTTON_MASK_ANY); XCB_GRAB_MODE_ASYNC, root, XCB_NONE, buttons[i], XCB_BUTTON_MASK_ANY);
i++;
} }
} }