Skip to content

Commit

Permalink
Only honor FFP in reaction to pointer motion events
Browse files Browse the repository at this point in the history
It appears that unmapping windows might generate undesirable enter
notify events. It can lead a very nasty bug where the focus constantly
switches between two desktops ad infinitum (cf. baskerville#268).
  • Loading branch information
baskerville committed Jun 9, 2015
1 parent c9925de commit 8821c69
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 7 deletions.
2 changes: 1 addition & 1 deletion bspwm.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ void setup(void)

void register_events(void)
{
uint32_t values[] = {ROOT_EVENT_MASK};
uint32_t values[] = {ROOT_EVENT_MASK | (focus_follows_pointer ? FFP_MASK : 0)};
xcb_generic_error_t *e = xcb_request_check(dpy, xcb_change_window_attributes_checked(dpy, root, XCB_CW_EVENT_MASK, values));
if (e != NULL) {
xcb_disconnect(dpy);
Expand Down
1 change: 1 addition & 0 deletions bspwm.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

#define ROOT_EVENT_MASK (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY)
#define CLIENT_EVENT_MASK (XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_FOCUS_CHANGE)
#define FFP_MASK (XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW)

xcb_connection_t *dpy;
int default_screen, screen_width, screen_height;
Expand Down
57 changes: 55 additions & 2 deletions events.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ void handle_event(xcb_generic_event_t *evt)
case XCB_ENTER_NOTIFY:
enter_notify(evt);
break;
case XCB_LEAVE_NOTIFY:
leave_notify(evt);
break;
case XCB_MOTION_NOTIFY:
motion_notify(evt);
break;
case XCB_FOCUS_IN:
focus_in(evt);
break;
Expand Down Expand Up @@ -317,15 +323,62 @@ void enter_notify(xcb_generic_event_t *evt)

if (e->mode != XCB_NOTIFY_MODE_NORMAL ||
(mon->desk->focus != NULL &&
mon->desk->focus->client->window == win))
mon->desk->focus->client->window == win)) {
return;
}

uint32_t values[] = {CLIENT_EVENT_MASK|FFP_MASK|XCB_EVENT_MASK_POINTER_MOTION};
xcb_change_window_attributes(dpy, win, XCB_CW_EVENT_MASK, values);
}

void leave_notify(xcb_generic_event_t *evt)
{
xcb_leave_notify_event_t *e = (xcb_leave_notify_event_t *) evt;
xcb_window_t win = e->event;

PRINTF("leave notify %X %d %d\n", win, e->mode, e->detail);

if (e->mode != XCB_NOTIFY_MODE_NORMAL) {
return;
}

uint32_t values[] = {CLIENT_EVENT_MASK|FFP_MASK};
xcb_change_window_attributes(dpy, win, XCB_CW_EVENT_MASK, values);
}

void motion_notify(xcb_generic_event_t *evt)
{
PUTS("motion notify");

xcb_motion_notify_event_t *e = (xcb_motion_notify_event_t *) evt;
xcb_window_t win = e->event;

int dtime = e->time - last_motion_time;
if (dtime > 1000) {
last_motion_time = e->time;
last_motion_x = e->event_x;
last_motion_y = e->event_y;
return;
}

int mdist = abs(e->event_x - last_motion_x) + abs(e->event_y - last_motion_y);
if (mdist < 10) {
return;
}

bool pfm_backup = pointer_follows_monitor;
bool pff_backup = pointer_follows_focus;
auto_raise = false;
pointer_follows_monitor = false;
pointer_follows_focus = false;
if (!window_focus(win)) {
coordinates_t loc;
if (locate_window(win, &loc)) {
if (loc.node != mon->desk->focus) {
focus_node(loc.monitor, loc.desktop, loc.node);
uint32_t values[] = {CLIENT_EVENT_MASK|FFP_MASK};
xcb_change_window_attributes(dpy, win, XCB_CW_EVENT_MASK, values);
}
} else {
xcb_point_t pt = {e->root_x, e->root_y};
monitor_t *m = monitor_from_point(pt);
if (m != NULL && m != mon) {
Expand Down
2 changes: 2 additions & 0 deletions events.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ void property_notify(xcb_generic_event_t *evt);
void client_message(xcb_generic_event_t *evt);
void focus_in(xcb_generic_event_t *evt);
void enter_notify(xcb_generic_event_t *evt);
void leave_notify(xcb_generic_event_t *evt);
void motion_notify(xcb_generic_event_t *evt);
void handle_state(monitor_t *m, desktop_t *d, node_t *n, xcb_atom_t state, unsigned int action);
void process_error(xcb_generic_event_t *evt);

Expand Down
12 changes: 8 additions & 4 deletions messages.c
Original file line number Diff line number Diff line change
Expand Up @@ -1015,12 +1015,16 @@ int set_setting(coordinates_t loc, char *name, char *value)
bool b;
if (parse_bool(value, &b) && b != focus_follows_pointer) {
focus_follows_pointer = b;
for (monitor_t *m = mon_head; m != NULL; m = m->next)
for (desktop_t *d = m->desk_head; d != NULL; d = d->next)
uint32_t root_values[] = {ROOT_EVENT_MASK | (focus_follows_pointer ? FFP_MASK : 0)};
uint32_t client_values[] = {CLIENT_EVENT_MASK | (focus_follows_pointer ? FFP_MASK : 0)};
xcb_change_window_attributes(dpy, root, XCB_CW_EVENT_MASK, root_values);
for (monitor_t *m = mon_head; m != NULL; m = m->next) {
for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) {
uint32_t values[] = {CLIENT_EVENT_MASK | (focus_follows_pointer ? XCB_EVENT_MASK_ENTER_WINDOW : 0)};
xcb_change_window_attributes(dpy, n->client->window, XCB_CW_EVENT_MASK, values);
xcb_change_window_attributes(dpy, n->client->window, XCB_CW_EVENT_MASK, client_values);
}
}
}
return MSG_SUCCESS;
} else {
return MSG_FAILURE;
Expand Down

0 comments on commit 8821c69

Please sign in to comment.