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);
/**
* Returns true if the current config has any binding to a scroll wheel button
* (4 or 5) which is a whole-window binding.
* We need this to figure out whether we should grab all buttons or just 1-3
* when managing a window. See #2049.
*
* Returns a list of buttons that should be grabbed on a window.
* This list will always contain 13, all higher buttons will only be returned
* if there is a whole-window binding for it on some window in the current
* 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.
*
*/
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) {
bool grab_scrollwheel = bindings_should_grab_scrollwheel_buttons();
int *buttons = bindings_get_buttons_to_grab();
xcb_grab_server(conn);
Con *con;
@ -161,9 +161,10 @@ void regrab_all_buttons(xcb_connection_t *conn) {
continue;
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);
}
@ -811,15 +812,30 @@ bool load_keymap(void) {
}
/*
* Returns true if the current config has any binding to a scroll wheel button
* (4 or 5) which is a whole-window binding.
* We need this to figure out whether we should grab all buttons or just 1-3
* when managing a window. See #2049.
*
* Returns a list of buttons that should be grabbed on a window.
* This list will always contain 13, all higher buttons will only be returned
* if there is a whole-window binding for it on some window in the current
* 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;
TAILQ_FOREACH(bind, bindings, bindings) {
if (num + 1 == num_max)
break;
/* We are only interested in whole window mouse bindings. */
if (bind->input_type != B_MOUSE || !bind->whole_window)
continue;
@ -831,11 +847,18 @@ bool bindings_should_grab_scrollwheel_buttons(void) {
continue;
}
/* If the binding is for either scrollwheel button, we need to grab everything. */
if (button == 4 || button == 5) {
return true;
}
/* Avoid duplicates. */
for (int i = 0; i < num_max; i++) {
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->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) */
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.
*
*/
void xcb_grab_buttons(xcb_connection_t *conn, xcb_window_t window, bool bind_scrollwheel) {
uint8_t buttons[3];
int num = 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++) {
void xcb_grab_buttons(xcb_connection_t *conn, xcb_window_t window, int *buttons) {
int i = 0;
while (buttons[i] > 0) {
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);
i++;
}
}