]> git.lizzy.rs Git - bspwm.git/commitdiff
New messages: '{grab,track,ungrab}_pointer'
authorBastien Dejean <nihilhill@gmail.com>
Tue, 8 Jan 2013 14:52:20 +0000 (15:52 +0100)
committerBastien Dejean <nihilhill@gmail.com>
Tue, 8 Jan 2013 14:52:20 +0000 (15:52 +0100)
15 files changed:
README.md
bspwm.1
bspwm.c
bspwm.h
events.c
events.h
helpers.c
helpers.h
messages.c
messages.h
settings.c
settings.h
tree.c
types.h
window.c

index 939d28053f5521e364c6325e139cc193114ec11a..3aa63771804e942fbb63183667178111a344db73 100644 (file)
--- a/README.md
+++ b/README.md
@@ -131,8 +131,14 @@ The following messages are handled:
     circulate forward|backward
         Circulate the leaves in the given direction.
 
-    mouse move|resize|focus
-        Perform the given mouse action on the window under the pointer.
+    grab_pointer move|resize|focus
+        Begin the specified pointer action.
+
+    track_pointer ROOT_X ROOT_Y
+        Pass the pointer root coordinates for the current pointer action.
+
+    ungrab_pointer
+        End the current pointer action.
 
     toggle_fullscreen
         Toggle the fullscreen state of the current window.
@@ -275,8 +281,8 @@ Colors are either [X color names](http://en.wikipedia.org/wiki/X11_color_names)
     gapless_monocle
         Whether to remove gaps for tiled windows in monocle mode.
 
-    focus_follows_mouse
-        Wether to focus the window under the mouse pointer.
+    focus_follows_pointer
+        Wether to focus the window under the pointer.
 
     adaptative_raise
         Prevent floating windows from being raised when they might cover other floating windows.
diff --git a/bspwm.1 b/bspwm.1
index fc23ebf527f54056f0a220abefdeaad34d4c1c7c..6087d22c6313e1158c05602ee1b29f964ad64835 100644 (file)
--- a/bspwm.1
+++ b/bspwm.1
@@ -156,8 +156,14 @@ Focus the nearest window matching the given constraints.
 .BI circulate " forward|backward"
 Circulate the leaves in the given direction.
 .TP
-.BI mouse " move|resize|focus"
-Perform the given mouse action on the window under the pointer.
+.BI grab_pointer " move|resize|focus"
+Begin the specified pointer action.
+.TP
+.BI track_pointer " ROOT_X ROOT_Y"
+Pass the pointer root coordinates for the current pointer action.
+.TP
+.BI ungrab_pointer
+End the current pointer action.
 .TP
 .BI toggle_fullscreen
 Toggle the fullscreen state of the current window.
@@ -321,8 +327,8 @@ Whether to remove borders for tiled windows in monocle mode.
 .I gapless_monocle
 Whether to remove gaps for tiled windows in monocle mode.
 .TP
-.I focus_follows_mouse
-Wether to focus the window under the mouse pointer.
+.I focus_follows_pointer
+Wether to focus the window under the pointer.
 .TP
 .I adaptative_raise
 Prevent floating windows from being raised when they might cover other floating windows.
diff --git a/bspwm.c b/bspwm.c
index 45506740a7f8159cfde9f6c390dd2774dd4b9f43..1a095a892d2251801de91dc41db1892a89e0064e 100644 (file)
--- a/bspwm.c
+++ b/bspwm.c
@@ -117,8 +117,7 @@ void setup(void)
     ewmh_update_current_desktop();
     rule_head = rule_tail = NULL;
     frozen_pointer = make_pointer_state();
-    update_pointer_position(&pointer_position);
-    last_entered = XCB_NONE;
+    under_pointer = XCB_NONE;
     split_mode = MODE_AUTOMATIC;
     visible = true;
     exit_status = 0;
diff --git a/bspwm.h b/bspwm.h
index 685f4af5030995c4b4ad13cb370793756bf6da2b..8ff8cf0b10ffa20b6a2ae66532580400b9fcb182 100644 (file)
--- a/bspwm.h
+++ b/bspwm.h
@@ -3,8 +3,9 @@
 
 #include "types.h"
 
-#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_ENTER_WINDOW)
+#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_POINTER_MOTION)
 
 xcb_connection_t *dpy;
 int default_screen, screen_width, screen_height;
@@ -30,8 +31,7 @@ rule_t *rule_head;
 rule_t *rule_tail;
 
 pointer_state_t *frozen_pointer;
-xcb_point_t pointer_position;
-xcb_window_t last_entered;
+xcb_window_t under_pointer;
 
 int exit_status;
 
index 352882d27960b8703fdf85c3349dd0e0cf43af58..3ce285c10798c708b22a4ad3984416f925892e07 100644 (file)
--- a/events.c
+++ b/events.c
@@ -35,15 +35,9 @@ void handle_event(xcb_generic_event_t *evt)
         case XCB_PROPERTY_NOTIFY:
             property_notify(evt);
             break;
-        case XCB_ENTER_NOTIFY:
-            enter_notify(evt);
-            break;
         case XCB_MOTION_NOTIFY:
             motion_notify(evt);
             break;
-        case XCB_BUTTON_RELEASE:
-            button_release();
-            break;
         default:
             break;
     }
@@ -197,27 +191,6 @@ void property_notify(xcb_generic_event_t *evt)
     }
 }
 
-void enter_notify(xcb_generic_event_t *evt)
-{
-    xcb_enter_notify_event_t *e = (xcb_enter_notify_event_t *) evt;
-
-    PRINTF("enter notify %X %d %d\n", e->event, e->mode, e->detail);
-
-    if (!focus_follows_mouse 
-            || (e->mode != XCB_NOTIFY_MODE_NORMAL && e->detail == XCB_NOTIFY_DETAIL_INFERIOR)
-            || (pointer_position.x == e->root_x && pointer_position.y == e->root_y)
-            || last_entered == e->event)
-        return;
-
-    window_location_t loc;
-    if (locate_window(e->event, &loc)) {
-        select_monitor(loc.monitor);
-        focus_node(loc.monitor, loc.desktop, loc.node, true);
-        pointer_position = (xcb_point_t) {e->root_x, e->root_y};
-        last_entered = e->event;
-    }
-}
-
 void client_message(xcb_generic_event_t *evt)
 {
     xcb_client_message_event_t *e = (xcb_client_message_event_t *) evt;
@@ -250,9 +223,39 @@ void client_message(xcb_generic_event_t *evt)
     }
 }
 
-void mouse_do(mouse_action_t mac)
+void motion_notify(xcb_generic_event_t *evt)
+{
+    xcb_motion_notify_event_t *e = (xcb_motion_notify_event_t *) evt;
+    xcb_window_t win = e->event;
+
+    PRINTF("motion notify %X\n", win);
+
+    window_location_t loc;
+    if (locate_window(win, &loc)) {
+        if (loc.node == mon->desk->focus)
+            return;
+        select_monitor(loc.monitor);
+        select_desktop(loc.desktop);
+        focus_node(loc.monitor, loc.desktop, loc.node, true);
+    }
+}
+
+void handle_state(monitor_t *m, desktop_t *d, node_t *n, xcb_atom_t state, unsigned int action)
+{
+    if (state == ewmh->_NET_WM_STATE_FULLSCREEN) {
+        bool fs = n->client->fullscreen;
+        if (action == XCB_EWMH_WM_STATE_TOGGLE
+                || (fs && action == XCB_EWMH_WM_STATE_REMOVE)
+                || (!fs && action == XCB_EWMH_WM_STATE_ADD)) {
+            toggle_fullscreen(m, n->client);
+            arrange(m, d);
+        }
+    }
+}
+
+void grab_pointer(pointer_action_t pac)
 {
-    PRINTF("mouse action %u\n", mac);
+    PRINTF("grab pointer %u\n", pac);
 
     xcb_window_t win;
     xcb_point_t pos;
@@ -269,12 +272,12 @@ void mouse_do(mouse_action_t mac)
     window_location_t loc;
     if (locate_window(win, &loc)) {
         client_t *c = loc.node->client;
-        switch (mac)  {
-            case MOUSE_FOCUS:
+        switch (pac)  {
+            case POINTER_FOCUS:
                 focus_node(loc.monitor, loc.desktop, loc.node, true);
                 break;
-            case MOUSE_MOVE:
-            case MOUSE_RESIZE:
+            case POINTER_MOVE:
+            case POINTER_RESIZE:
                 if (is_tiled(loc.node->client)) {
                     loc.node->client->floating_rectangle = loc.node->client->tiled_rectangle;
                     toggle_floating(loc.node);
@@ -287,8 +290,8 @@ void mouse_do(mouse_action_t mac)
                 frozen_pointer->node = loc.node;
                 frozen_pointer->rectangle = c->floating_rectangle;
                 frozen_pointer->position = pos;
-                frozen_pointer->action = mac;
-                if (mac == MOUSE_RESIZE) {
+                frozen_pointer->action = pac;
+                if (pac == POINTER_RESIZE) {
                     int16_t mid_x, mid_y;
                     mid_x = c->floating_rectangle.x + (c->floating_rectangle.width / 2);
                     mid_y = c->floating_rectangle.y + (c->floating_rectangle.height / 2);
@@ -304,16 +307,13 @@ void mouse_do(mouse_action_t mac)
                             frozen_pointer->corner = TOP_LEFT;
                     }
                 }
-                xcb_grab_pointer(dpy, false, root, XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_BUTTON_RELEASE, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_NONE, XCB_NONE, XCB_CURRENT_TIME);
                 break;
         }
     }
 }
 
-void motion_notify(xcb_generic_event_t *evt)
+void track_pointer(int root_x, int root_y)
 {
-    xcb_motion_notify_event_t *e = (xcb_motion_notify_event_t *) evt;
-
     int16_t delta_x, delta_y, x, y, w, h;
     uint16_t width, height;
 
@@ -327,18 +327,16 @@ void motion_notify(xcb_generic_event_t *evt)
     x = y = 0;
     w = h = 1;
 
-    /* PRINTF("motion notify %X\n", win); */
-
-    delta_x = e->root_x - frozen_pointer->position.x;
-    delta_y = e->root_y - frozen_pointer->position.y;
+    delta_x = root_x - frozen_pointer->position.x;
+    delta_y = root_y - frozen_pointer->position.y;
 
     switch (frozen_pointer->action) {
-        case MOUSE_MOVE:
+        case POINTER_MOVE:
             x = rect.x + delta_x;
             y = rect.y + delta_y;
             window_move(win, x, y);
             break;
-        case MOUSE_RESIZE:
+        case POINTER_RESIZE:
             switch (frozen_pointer->corner) {
                 case TOP_LEFT:
                     x = rect.x + delta_x;
@@ -371,16 +369,15 @@ void motion_notify(xcb_generic_event_t *evt)
             c->floating_rectangle = (xcb_rectangle_t) {x, y, width, height};
             window_draw_border(n, d->focus == n, mon == m);
             break;
-        case MOUSE_FOCUS:
+        case POINTER_FOCUS:
             break;
     }
 }
 
-void button_release(void)
+void ungrab_pointer(void)
 {
-    PUTS("button release");
+    PUTS("ungrab pointer");
 
-    xcb_ungrab_pointer(dpy, XCB_CURRENT_TIME);
     update_floating_rectangle(frozen_pointer->node->client);
     monitor_t *m = underlying_monitor(frozen_pointer->node->client);
     if (m != NULL && m != frozen_pointer->monitor) {
@@ -388,16 +385,3 @@ void button_release(void)
         select_monitor(m);
     }
 }
-
-void handle_state(monitor_t *m, desktop_t *d, node_t *n, xcb_atom_t state, unsigned int action)
-{
-    if (state == ewmh->_NET_WM_STATE_FULLSCREEN) {
-        bool fs = n->client->fullscreen;
-        if (action == XCB_EWMH_WM_STATE_TOGGLE
-                || (fs && action == XCB_EWMH_WM_STATE_REMOVE)
-                || (!fs && action == XCB_EWMH_WM_STATE_ADD)) {
-            toggle_fullscreen(m, n->client);
-            arrange(m, d);
-        }
-    }
-}
index 3ba5a38a7c2af43a3c90d7d7cfb2bcf5fdcf819b..8f55f483a91707bf860010abb9a51caf491c1805 100644 (file)
--- a/events.h
+++ b/events.h
@@ -13,9 +13,9 @@ void client_message(xcb_generic_event_t *);
 void property_notify(xcb_generic_event_t *);
 void mapping_notify(xcb_generic_event_t *);
 void enter_notify(xcb_generic_event_t *);
-void mouse_do(mouse_action_t);
 void motion_notify(xcb_generic_event_t *);
-void button_release(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);
+void ungrab_pointer(void);
 #endif
index aad1e36db407f8063147afef57ad5f1a50ec4800..28bed8e500a4382fd96654daaf5115097651808b 100644 (file)
--- a/helpers.c
+++ b/helpers.c
@@ -51,12 +51,3 @@ uint32_t get_color(char *col)
 
     return pxl;
 }
-
-void update_pointer_position(xcb_point_t *pos)
-{
-    xcb_query_pointer_reply_t *qpr = xcb_query_pointer_reply(dpy, xcb_query_pointer(dpy, root), NULL);
-    if (qpr != NULL) {
-        *pos = (xcb_point_t) {qpr->root_x, qpr->root_y};
-        free(qpr);
-    }
-}
index 037fac3892be25ce02434091536f4179d61d8b3f..d9fe1daf07f1fe34b27b254b69219443d8df3cfe 100644 (file)
--- a/helpers.h
+++ b/helpers.h
@@ -29,6 +29,5 @@ void warn(char *, ...);
 __attribute__((noreturn))
 void err(char *, ...);
 uint32_t get_color(char *);
-void update_pointer_position(xcb_point_t *);
 
 #endif
index 7a46e32468cca90a02eb1fe1118c054f86d1cbf6..968e4b5f88967579a067b51cd0cc50f9c79b8ca3 100644 (file)
@@ -70,13 +70,26 @@ void process_message(char *msg, char *rsp)
                 rotate_tree(mon->desk->root, r);
             }
         }
-    } else if (strcmp(cmd, "mouse") == 0) {
-        char *mac = strtok(NULL, TOK_SEP);
-        if (mac != NULL) {
-            mouse_action_t a;
-            if (parse_mouse_action(mac, &a))
-                mouse_do(a);
+    } else if (strcmp(cmd, "grab_pointer") == 0) {
+        char *pac = strtok(NULL, TOK_SEP);
+        if (pac != NULL) {
+            pointer_action_t a;
+            if (parse_pointer_action(pac, &a))
+                grab_pointer(a);
         }
+    } else if (strcmp(cmd, "track_pointer") == 0) {
+        char *arg1 = strtok(NULL, TOK_SEP);
+        if (arg1 == NULL)
+            return;
+        char *arg2 = strtok(NULL, TOK_SEP);
+        if (arg2 == NULL)
+            return;
+        int root_x, root_y;
+        if (sscanf(arg1, "%i", &root_x) == 1 && sscanf(arg2, "%i", &root_y) == 1)
+            track_pointer(root_x, root_y);
+        return;
+    } else if (strcmp(cmd, "ungrab_pointer") == 0) {
+        ungrab_pointer();
     } else if (strcmp(cmd, "layout") == 0) {
         char *lyt = strtok(NULL, TOK_SEP);
         if (lyt != NULL) {
@@ -451,10 +464,19 @@ void set_setting(char *name, char *value, char *rsp)
         bool b;
         if (parse_bool(value, &b))
             gapless_monocle = b;
-    } else if (strcmp(name, "focus_follows_mouse") == 0) {
+    } else if (strcmp(name, "focus_follows_pointer") == 0) {
         bool b;
-        if (parse_bool(value, &b))
-            focus_follows_mouse = b;
+        if (parse_bool(value, &b)) {
+            if (b != focus_follows_pointer) {
+                uint32_t values[] = {(focus_follows_pointer ? CLIENT_EVENT_MASK : CLIENT_EVENT_MASK_FFP)};
+                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))
+                            xcb_change_window_attributes(dpy, n->client->window, XCB_CW_EVENT_MASK, values);
+
+            }
+            focus_follows_pointer = b;
+        }
     } else if (strcmp(name, "adaptative_raise") == 0) {
         bool b;
         if (parse_bool(value, &b))
@@ -518,8 +540,8 @@ void get_setting(char *name, char* rsp)
         snprintf(rsp, BUFSIZ, "%s", BOOLSTR(borderless_monocle));
     else if (strcmp(name, "gapless_monocle") == 0)
         snprintf(rsp, BUFSIZ, "%s", BOOLSTR(gapless_monocle));
-    else if (strcmp(name, "focus_follows_mouse") == 0)
-        snprintf(rsp, BUFSIZ, "%s", BOOLSTR(focus_follows_mouse));
+    else if (strcmp(name, "focus_follows_pointer") == 0)
+        snprintf(rsp, BUFSIZ, "%s", BOOLSTR(focus_follows_pointer));
     else if (strcmp(name, "adaptative_raise") == 0)
         snprintf(rsp, BUFSIZ, "%s", BOOLSTR(adaptative_raise));
     else if (strcmp(name, "wm_name") == 0)
@@ -699,16 +721,16 @@ bool parse_fence_move(char *s, fence_move_t *m)
     return false;
 }
 
-bool parse_mouse_action(char *s, mouse_action_t *a)
+bool parse_pointer_action(char *s, pointer_action_t *a)
 {
     if (strcmp(s, "move") == 0) {
-        *a = MOUSE_MOVE;
+        *a = POINTER_MOVE;
         return true;
     } else if (strcmp(s, "focus") == 0) {
-        *a = MOUSE_FOCUS;
+        *a = POINTER_FOCUS;
         return true;
     } else if (strcmp(s, "resize") == 0) {
-        *a = MOUSE_RESIZE;
+        *a = POINTER_RESIZE;
         return true;
     }
     return false;
index 6071d3b1bcbefb4a096791e974b2c1ad76e2d592..8f97de0a800dc6c1cb0b3fea086dd4bc488b93aa 100644 (file)
@@ -20,6 +20,6 @@ bool parse_skip_client(char *, skip_client_t *);
 bool parse_skip_desktop(char *, skip_desktop_t *);
 bool parse_rotate(char *, rotate_t *);
 bool parse_fence_move(char *, fence_move_t *);
-bool parse_mouse_action(char *, mouse_action_t *);
+bool parse_pointer_action(char *, pointer_action_t *);
 
 #endif
index c8b5f21fc9b739b035862a3a2f67c8987f492282..7a4b248481d893859818a5331e2849bb338e7ed3 100644 (file)
@@ -65,6 +65,6 @@ void load_settings(void)
 
     borderless_monocle = BORDERLESS_MONOCLE;
     gapless_monocle = GAPLESS_MONOCLE;
-    focus_follows_mouse = FOCUS_FOLLOWS_MOUSE;
+    focus_follows_pointer = FOCUS_FOLLOWS_POINTER;
     adaptative_raise = ADAPTATIVE_RAISE;
 }
index b7c270ab0c1eb10a1707fe1935db66d0a81e979a..6a144d57e9925bc0270e14e2b92937d9ba8cbd41 100644 (file)
 #define WINDOW_GAP          6
 #define SPLIT_RATIO         0.5
 
-#define BORDERLESS_MONOCLE   false
-#define GAPLESS_MONOCLE      false
-#define FOCUS_FOLLOWS_MOUSE  false
-#define ADAPTATIVE_RAISE     false
+#define BORDERLESS_MONOCLE     false
+#define GAPLESS_MONOCLE        false
+#define FOCUS_FOLLOWS_POINTER  false
+#define ADAPTATIVE_RAISE       false
 
 char focused_border_color[MAXLEN];
 char active_border_color[MAXLEN];
@@ -60,7 +60,7 @@ int window_gap;
 
 bool borderless_monocle;
 bool gapless_monocle;
-bool focus_follows_mouse;
+bool focus_follows_pointer;
 bool adaptative_raise;
 
 char wm_name[MAXLEN];
diff --git a/tree.c b/tree.c
index f79663f17a33590f53cb109ac2d1ee1df71e279e..7fef97bb19b19baa6fa17e6cdc1042232052ea26 100644 (file)
--- a/tree.c
+++ b/tree.c
@@ -178,8 +178,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_mouse)
-        update_pointer_position(&pointer_position);
     apply_layout(m, d, d->root, rect, rect);
 }
 
@@ -367,9 +365,16 @@ void focus_node(monitor_t *m, desktop_t *d, node_t *n, bool is_mapped)
             window_draw_border(d->focus, false, true);
             window_draw_border(n, true, true);
         }
-        if (focus_follows_mouse)
-            update_pointer_position(&pointer_position);
         xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, n->client->window, XCB_CURRENT_TIME);
+        if (focus_follows_pointer) {
+            if (under_pointer != XCB_NONE) {
+                uint32_t values[] = {CLIENT_EVENT_MASK_FFP};
+                xcb_change_window_attributes(dpy, under_pointer, XCB_CW_EVENT_MASK, values);
+            }
+            uint32_t values[] = {CLIENT_EVENT_MASK};
+            xcb_change_window_attributes(dpy, n->client->window, XCB_CW_EVENT_MASK, values);
+            under_pointer = n->client->window;
+        }
     }
 
     if (!is_tiled(n->client)) {
@@ -926,7 +931,7 @@ void restore(char *file_path)
         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)) {
-                    uint32_t values[] = {CLIENT_EVENT_MASK};
+                    uint32_t values[] = {(focus_follows_pointer ? CLIENT_EVENT_MASK_FFP : CLIENT_EVENT_MASK)};
                     xcb_change_window_attributes(dpy, n->client->window, XCB_CW_EVENT_MASK, values);
                     if (n->client->floating) {
                         n->vacant = true;
diff --git a/types.h b/types.h
index d1afeb4e0b66ad708cb61947ed4a269334da6096..b4840e15c3bf894b15469600b3720984067b31ee 100644 (file)
--- a/types.h
+++ b/types.h
@@ -98,10 +98,10 @@ typedef enum {
 } corner_t;
 
 typedef enum {
-    MOUSE_MOVE,
-    MOUSE_RESIZE,
-    MOUSE_FOCUS
-} mouse_action_t;
+    POINTER_MOVE,
+    POINTER_RESIZE,
+    POINTER_FOCUS
+} pointer_action_t;
 
 typedef struct {
     xcb_window_t window;
@@ -189,7 +189,7 @@ typedef struct {
 
 typedef struct {
     xcb_point_t position;
-    mouse_action_t action;
+    pointer_action_t action;
     xcb_rectangle_t rectangle;
     monitor_t *monitor;
     desktop_t *desktop;
index e6c96ffe73a72980a6d2bb69612564deb0648c14..6e5fd66a9a6ea9f831db57a8fda5c813462e099c 100644 (file)
--- a/window.c
+++ b/window.c
@@ -151,7 +151,7 @@ void manage_window(monitor_t *m, desktop_t *d, xcb_window_t win)
     if (takes_focus)
         xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, win, XCB_CURRENT_TIME);
 
-    uint32_t values[] = {CLIENT_EVENT_MASK};
+    uint32_t values[] = {(focus_follows_pointer ? CLIENT_EVENT_MASK_FFP : CLIENT_EVENT_MASK)};
     xcb_change_window_attributes(dpy, c->window, XCB_CW_EVENT_MASK, values);
 
     num_clients++;
@@ -478,16 +478,10 @@ void window_show(xcb_window_t win)
 
 void toggle_visibility(void)
 {
-    uint32_t values_off[] = {CLIENT_EVENT_MASK & ~XCB_EVENT_MASK_ENTER_WINDOW};
-    uint32_t values_on[] = {CLIENT_EVENT_MASK};
     visible = !visible;
     for (monitor_t *m = mon_head; m != NULL; m = m->next)
-        for (node_t *n = first_extrema(m->desk->root); n != NULL; n = next_leaf(n)) {
-            xcb_window_t win = n->client->window;
-            xcb_change_window_attributes(dpy, win, XCB_CW_EVENT_MASK, values_off);
-            window_set_visibility(win, visible);
-            xcb_change_window_attributes(dpy, win, XCB_CW_EVENT_MASK, values_on);
-        }
+        for (node_t *n = first_extrema(m->desk->root); n != NULL; n = next_leaf(n))
+            window_set_visibility(n->client->window, visible);
     if (visible)
         update_current();
 }