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:
parent
0060586190
commit
83c8740bf1
|
@ -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 1–3, 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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 1–3, 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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
18
src/xcb.c
18
src/xcb.c
|
@ -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++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue