From 6bfebaaf6bf3078dd08f01e605801579a44d54f6 Mon Sep 17 00:00:00 2001 From: Bastien Dejean Date: Sat, 2 Mar 2013 19:39:16 +0100 Subject: [PATCH] Focus follows pointer rewrite --- TODO.md | 1 - bspwm.c | 8 ++++++-- bspwm.h | 5 ++--- events.c | 18 ++++++++++-------- events.h | 2 +- tree.c | 16 ++++------------ window.c | 20 ++++++++++++++++++++ window.h | 4 +++- 8 files changed, 46 insertions(+), 28 deletions(-) diff --git a/TODO.md b/TODO.md index 499ddab..cae6f28 100644 --- a/TODO.md +++ b/TODO.md @@ -1,4 +1,3 @@ -- Rewrite `focus_follows_pointer` by using a root sized input only window mapped and unmapped via enter notify events. - Rewrite `find_neighbor` based on the distances between the windows sides (more intuitive). - Focus history. - Command line completion for *bspc*. diff --git a/bspwm.c b/bspwm.c index 60e9c24..736ee25 100644 --- a/bspwm.c +++ b/bspwm.c @@ -62,6 +62,11 @@ void setup(void) screen_height = screen->height_in_pixels; root_depth = screen->root_depth; + uint32_t mask = XCB_CW_EVENT_MASK; + uint32_t values[] = {XCB_EVENT_MASK_POINTER_MOTION}; + motion_recorder = xcb_generate_id(dpy); + xcb_create_window(dpy, XCB_COPY_FROM_PARENT, motion_recorder, root, 0, 0, screen_width, screen_height, 0, XCB_WINDOW_CLASS_INPUT_ONLY, XCB_COPY_FROM_PARENT, mask, values); + xcb_atom_t net_atoms[] = {ewmh->_NET_SUPPORTED, ewmh->_NET_DESKTOP_NAMES, ewmh->_NET_NUMBER_OF_DESKTOPS, @@ -124,8 +129,6 @@ void setup(void) ewmh_update_current_desktop(); rule_head = rule_tail = NULL; frozen_pointer = make_pointer_state(); - last_focused_window = XCB_NONE; - save_pointer_position(&last_pointer_position); split_mode = MODE_AUTOMATIC; visible = true; exit_status = 0; @@ -240,6 +243,7 @@ int main(int argc, char *argv[]) if (status_fifo != NULL) fclose(status_fifo); xcb_ewmh_connection_wipe(ewmh); + xcb_destroy_window(dpy, motion_recorder); free(ewmh); xcb_flush(dpy); xcb_disconnect(dpy); diff --git a/bspwm.h b/bspwm.h index b350b48..fd6c69c 100644 --- a/bspwm.h +++ b/bspwm.h @@ -5,7 +5,7 @@ #define ROOT_EVENT_MASK (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY) #define CLIENT_EVENT_MASK (XCB_EVENT_MASK_PROPERTY_CHANGE) -#define CLIENT_EVENT_MASK_FFP (XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_POINTER_MOTION) +#define CLIENT_EVENT_MASK_FFP (XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_ENTER_WINDOW) xcb_connection_t *dpy; int default_screen, screen_width, screen_height; @@ -31,8 +31,7 @@ rule_t *rule_head; rule_t *rule_tail; pointer_state_t *frozen_pointer; -xcb_window_t last_focused_window; -xcb_point_t last_pointer_position; +xcb_window_t motion_recorder; xcb_atom_t compton_shadow; int exit_status; diff --git a/events.c b/events.c index bd29a19..0c04ba3 100644 --- a/events.c +++ b/events.c @@ -39,7 +39,7 @@ void handle_event(xcb_generic_event_t *evt) enter_notify(evt); break; case XCB_MOTION_NOTIFY: - motion_notify(evt); + motion_notify(); break; default: break; @@ -234,20 +234,22 @@ void enter_notify(xcb_generic_event_t *evt) PRINTF("enter notify %X %d %d\n", win, e->mode, e->detail); if (e->mode != XCB_NOTIFY_MODE_NORMAL - || (last_pointer_position.x = e->root_x && last_pointer_position.y == e->root_y)) + || (mon->desk->focus != NULL && mon->desk->focus->client->window == win)) return; - window_focus(win); + enable_motion_recorder(); } -void motion_notify(xcb_generic_event_t *evt) +void motion_notify(void) { - xcb_motion_notify_event_t *e = (xcb_motion_notify_event_t *) evt; - xcb_window_t win = e->event; + PUTS("motion notify"); - PRINTF("motion notify %X\n", win); + disable_motion_recorder(); - window_focus(win); + xcb_window_t win = XCB_NONE; + get_pointed_window(&win); + if (win != XCB_NONE) + window_focus(win); } void handle_state(monitor_t *m, desktop_t *d, node_t *n, xcb_atom_t state, unsigned int action) diff --git a/events.h b/events.h index 6f61ad5..9bb3493 100644 --- a/events.h +++ b/events.h @@ -12,7 +12,7 @@ void configure_request(xcb_generic_event_t *); void client_message(xcb_generic_event_t *); void property_notify(xcb_generic_event_t *); void enter_notify(xcb_generic_event_t *); -void motion_notify(xcb_generic_event_t *); +void motion_notify(void); void handle_state(monitor_t *, desktop_t *, node_t *, xcb_atom_t, unsigned int); void grab_pointer(pointer_action_t); void track_pointer(int, int); diff --git a/tree.c b/tree.c index 8e6901c..dc27a74 100644 --- a/tree.c +++ b/tree.c @@ -196,8 +196,6 @@ void arrange(monitor_t *m, desktop_t *d) rect.y += m->top_padding + wg; rect.width -= m->left_padding + m->right_padding + wg; rect.height -= m->top_padding + m->bottom_padding + wg; - if (focus_follows_pointer) - save_pointer_position(&last_pointer_position); apply_layout(m, d, d->root, rect, rect); } @@ -389,16 +387,10 @@ void focus_node(monitor_t *m, desktop_t *d, node_t *n, bool is_mapped) } if (focus_follows_pointer) { - save_pointer_position(&last_pointer_position); - if (n != mon->desk->focus) { - if (last_focused_window != XCB_NONE) { - uint32_t values[] = {CLIENT_EVENT_MASK_FFP}; - xcb_change_window_attributes(dpy, last_focused_window, XCB_CW_EVENT_MASK, values); - } - uint32_t values[] = {CLIENT_EVENT_MASK}; - xcb_change_window_attributes(dpy, n->client->window, XCB_CW_EVENT_MASK, values); - last_focused_window = n->client->window; - } + xcb_window_t win = XCB_NONE; + get_pointed_window(&win); + if (win != n->client->window) + enable_motion_recorder(); } if (!is_tiled(n->client)) { diff --git a/window.c b/window.c index 31401fb..a791950 100644 --- a/window.c +++ b/window.c @@ -421,6 +421,15 @@ void save_pointer_position(xcb_point_t *pos) } } +void get_pointed_window(xcb_window_t *win) +{ + xcb_query_pointer_reply_t *qpr = xcb_query_pointer_reply(dpy, xcb_query_pointer(dpy, root), NULL); + if (qpr != NULL) { + *win = qpr->child; + free(qpr); + } +} + void window_focus(xcb_window_t win) { window_location_t loc; @@ -500,3 +509,14 @@ void toggle_visibility(void) if (visible) update_current(); } + +void enable_motion_recorder(void) +{ + window_raise(motion_recorder); + window_show(motion_recorder); +} + +void disable_motion_recorder(void) +{ + window_hide(motion_recorder); +} diff --git a/window.h b/window.h index d4aa963..cb72b12 100644 --- a/window.h +++ b/window.h @@ -34,10 +34,12 @@ void window_lower(xcb_window_t); void window_set_visibility(xcb_window_t, bool); void window_hide(xcb_window_t); void window_show(xcb_window_t); +void enable_motion_recorder(void); +void disable_motion_recorder(void); void toggle_visibility(void); uint32_t get_border_color(client_t *, bool, bool); void update_floating_rectangle(client_t *); -void save_pointer_position(xcb_point_t *); +void get_pointed_window(xcb_window_t *); void list_windows(char *); #endif