]> code.delx.au - spectrwm/blobdiff - spectrwm.c
Fix mouse button grab.
[spectrwm] / spectrwm.c
index fc0dcafdcdad78aa57c8329e4aa48fda930681ba..e7ac63f392befc09dcf0b5a1ab476b2374f1103e 100644 (file)
@@ -245,8 +245,8 @@ u_int32_t           swm_debug = 0
 #define YESNO(x)               ((x) ? "yes" : "no")
 
 #define SWM_FOCUS_DEFAULT      (0)
-#define SWM_FOCUS_SYNERGY      (1)
-#define SWM_FOCUS_FOLLOW       (2)
+#define SWM_FOCUS_FOLLOW       (1)
+#define SWM_FOCUS_MANUAL       (2)
 
 #define SWM_CONF_DEFAULT       (0)
 #define SWM_CONF_KEYMAPPING    (1)
@@ -673,7 +673,6 @@ void         configurenotify(xcb_configure_notify_event_t *);
 void    configurerequest(xcb_configure_request_event_t *);
 void    constrain_window(struct ws_win *, struct swm_region *, int);
 void    destroynotify(xcb_destroy_notify_event_t *);
-void    do_sync(void);
 void    enternotify(xcb_enter_notify_event_t *);
 void    event_drain(uint8_t);
 void    event_error(xcb_generic_error_t *);
@@ -683,7 +682,9 @@ void         expose(xcb_expose_event_t *);
 struct ws_win  *find_window(xcb_window_t);
 int     floating_toggle_win(struct ws_win *);
 void    focus(struct swm_region *, union arg *);
+void    focus_flush(void);
 struct ws_win  *focus_magic(struct ws_win *);
+void    focus_win(struct ws_win *);
 #ifdef SWM_DEBUG
 void    focusin(xcb_focus_in_event_t *);
 #endif
@@ -696,11 +697,12 @@ char      *get_notify_mode_label(uint8_t);
 xcb_screen_t   *get_screen(int);
 char   *get_win_name(xcb_window_t);
 uint32_t getstate(xcb_window_t);
-void    grabbuttons(struct ws_win *, int);
+void    grabbuttons(struct ws_win *);
 void    keypress(xcb_key_press_event_t *);
 #ifdef SWM_DEBUG
 void    leavenotify(xcb_leave_notify_event_t *);
 #endif
+void    load_float_geom(struct ws_win *, struct swm_region *);
 void    map_window_raised(xcb_window_t);
 void    mapnotify(xcb_map_notify_event_t *);
 void    mappingnotify(xcb_mapping_notify_event_t *);
@@ -795,17 +797,12 @@ get_screen(int screen)
 }
 
 void
-do_sync(void)
+focus_flush(void)
 {
-       xcb_get_input_focus_cookie_t    c;
-       xcb_get_input_focus_reply_t     *r;
-
-       /* mimic XSync() */
-       c = xcb_get_input_focus(conn);
-       xcb_flush(conn);
-       r = xcb_get_input_focus_reply(conn, c, NULL);
-       if (r)
-               free(r);
+       if (focus_mode == SWM_FOCUS_DEFAULT)
+               event_drain(XCB_ENTER_NOTIFY);
+       else
+               xcb_flush(conn);
 }
 
 void
@@ -992,12 +989,7 @@ ewmh_set_win_fullscreen(struct ws_win *win, int fs)
                win->g = win->ws->r->g;
                win->bordered = 0;
        } else {
-               if (win->g_floatvalid) {
-                       /* refloat at last floating relative position */
-                       win->g = win->g_float;
-                       X(win) += X(win->ws->r);
-                       Y(win) += Y(win->ws->r);
-               }
+               load_float_geom(win, win->ws->r);
        }
 
        return (1);
@@ -1924,10 +1916,7 @@ bar_toggle(struct swm_region *r, union arg *args)
        /* must be after stack */
        bar_update();
 
-       if (focus_mode == SWM_FOCUS_DEFAULT)
-               event_drain(XCB_ENTER_NOTIFY);
-       else
-               xcb_flush(conn);
+       focus_flush();
 }
 
 void
@@ -2672,7 +2661,6 @@ unfocus_win(struct ws_win *win)
                win->ws->focus_prev = NULL;
        }
 
-       grabbuttons(win, 0);
        xcb_change_window_attributes(conn, win->id, XCB_CW_BORDER_PIXEL,
            &win->ws->r->s->c[SWM_S_COLOR_UNFOCUS].pixel);
        xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win->s->root,
@@ -2725,18 +2713,20 @@ focus_win(struct ws_win *win)
                cur_focus = r->focus;
                free(r);
        }
-       if ((cfw = find_window(cur_focus)) != NULL)
+
+       cfw = find_window(cur_focus);
+
+       if (cfw == win) {
+               if (win->ws->focus == win) {
+                       DNPRINTF(SWM_D_FOCUS, "focus_win: already focused; "
+                           "skipping.\n");
+                       return;
+               } else {
+                       DNPRINTF(SWM_D_FOCUS, "focus_win: already has input "
+                           "focus.\n");
+               }
+       } else
                unfocus_win(cfw);
-       else {
-#if 0
-               /* use larger hammer since the window was killed somehow */
-               TAILQ_FOREACH(cfw, &win->ws->winlist, entry)
-                       if (cfw->ws && cfw->ws->r && cfw->ws->r->s)
-                               xcb_change_window_attributes(conn, cfw->id,
-                                   XCB_CW_BORDER_PIXEL,
-                                   &cfw->ws->r->s->c[SWM_S_COLOR_UNFOCUS].pixel);
-#endif
-       }
 
        win->ws->focus = win;
 
@@ -2753,7 +2743,6 @@ focus_win(struct ws_win *win)
                if (win->java == 0)
                        xcb_set_input_focus(conn, XCB_INPUT_FOCUS_PARENT,
                            win->id, XCB_CURRENT_TIME);
-               grabbuttons(win, 1);
                xcb_change_window_attributes(conn, win->id,
                    XCB_CW_BORDER_PIXEL,
                    &win->ws->r->s->c[SWM_S_COLOR_FOCUS].pixel);
@@ -2807,7 +2796,8 @@ event_drain(uint8_t rt)
 {
        xcb_generic_event_t     *evt;
 
-       xcb_flush(conn);
+       /* ensure all pending requests have been processed before filtering. */
+       xcb_aux_sync(conn);
        while ((evt = xcb_poll_for_event(conn))) {
                if (XCB_EVENT_RESPONSE_TYPE(evt) != rt)
                        event_handle(evt);
@@ -2870,10 +2860,7 @@ switchws(struct swm_region *r, union arg *args)
                TAILQ_FOREACH(win, &old_ws->winlist, entry)
                        unmap_window(win);
 
-       if (focus_mode == SWM_FOCUS_DEFAULT)
-               event_drain(XCB_ENTER_NOTIFY);
-       else
-               xcb_flush(conn);
+       focus_flush();
 
        DNPRINTF(SWM_D_WS, "switchws: done\n");
 }
@@ -3083,10 +3070,7 @@ swapwin(struct swm_region *r, union arg *args)
 
        stack();
 
-       if (focus_mode == SWM_FOCUS_DEFAULT)
-               event_drain(XCB_ENTER_NOTIFY);
-       else
-               xcb_flush(conn);
+       focus_flush();
 }
 
 void
@@ -3300,10 +3284,7 @@ cycle_layout(struct swm_region *r, union arg *args)
        a.id = SWM_ARG_ID_FOCUSCUR;
        focus(r, &a);
 
-       if (focus_mode == SWM_FOCUS_DEFAULT)
-               event_drain(XCB_ENTER_NOTIFY);
-       else
-               xcb_flush(conn);
+       focus_flush();
 }
 
 void
@@ -3366,6 +3347,9 @@ stack(void) {
 void
 store_float_geom(struct ws_win *win, struct swm_region *r)
 {
+       if (win == NULL || r == NULL)
+               return;
+
        /* retain window geom and region geom */
        win->g_float = win->g;
        win->g_float.x -= X(r);
@@ -3377,6 +3361,25 @@ store_float_geom(struct ws_win *win, struct swm_region *r)
            win->g_float.w, win->g_float.h);
 }
 
+void
+load_float_geom(struct ws_win *win, struct swm_region *r)
+{
+       if (win == NULL || r == NULL)
+               return;
+
+       if (win->g_floatvalid) {
+               win->g = win->g_float;
+               X(win) += X(r);
+               Y(win) += Y(r);
+               DNPRINTF(SWM_D_MISC, "load_float_geom: window: 0x%x, g: (%d,%d)"
+                   "%d x %d\n", win->id, X(win), Y(win), WIDTH(win),
+                   HEIGHT(win));
+       } else {
+               DNPRINTF(SWM_D_MISC, "load_float_geom: window: 0x%x, g_float "
+                   "is not set.\n", win->id);
+       }
+}
+
 void
 stack_floater(struct ws_win *win, struct swm_region *r)
 {
@@ -3389,12 +3392,10 @@ stack_floater(struct ws_win *win, struct swm_region *r)
         * to allow windows to change their size (e.g. mplayer fs) only retrieve
         * geom on ws switches or return from max mode
         */
-       if (win->g_floatvalid && (win->floatmaxed || (r != r->ws->old_r &&
-           !(win->ewmh_flags & EWMH_F_FULLSCREEN)))) {
-               /* refloat at last floating relative position */
-               win->g = win->g_float;
-               X(win) += X(r);
-               Y(win) += Y(r);
+       if (win->floatmaxed || (r != r->ws->old_r &&
+           !(win->ewmh_flags & EWMH_F_FULLSCREEN))) {
+               /* update geometry for the new region */
+               load_float_geom(win, r);
        }
 
        win->floatmaxed = 0;
@@ -3406,7 +3407,7 @@ stack_floater(struct ws_win *win, struct swm_region *r)
                if (!win->g_floatvalid)
                        store_float_geom(win, win->ws->r);
 
-               win->g = win->ws->r->g;
+               win->g = r->g;
        }
 
        /*
@@ -3432,13 +3433,16 @@ stack_floater(struct ws_win *win, struct swm_region *r)
                HEIGHT(win) = (double)HEIGHT(r) * dialog_ratio;
        }
 
-       if (!win->manual) {
+       if (!win->manual && !(win->ewmh_flags & EWMH_F_FULLSCREEN) &&
+           !(win->quirks & SWM_Q_ANYWHERE)) {
                /*
-                * floaters and transients are auto-centred unless moved
-                * or resized
+                * floaters and transients are auto-centred unless moved,
+                * resized or ANYWHERE quirk is set.
                 */
                X(win) = X(r) + (WIDTH(r) - WIDTH(win)) /  2 - BORDER(win);
                Y(win) = Y(r) + (HEIGHT(r) - HEIGHT(win)) / 2 - BORDER(win);
+
+               store_float_geom(win, r);
        }
 
        /* keep window within region bounds */
@@ -3911,10 +3915,7 @@ send_to_ws(struct swm_region *r, union arg *args)
        stack();
        bar_update();
 
-       if (focus_mode == SWM_FOCUS_DEFAULT)
-               event_drain(XCB_ENTER_NOTIFY);
-       else
-               xcb_flush(conn);
+       focus_flush();
 }
 
 void
@@ -3944,10 +3945,7 @@ raise_toggle(struct swm_region *r, union arg *args)
        if (r->ws->always_raise == 0)
                stack();
 
-       if (focus_mode == SWM_FOCUS_DEFAULT)
-               event_drain(XCB_ENTER_NOTIFY);
-       else
-               xcb_flush(conn);
+       focus_flush();
 }
 
 void
@@ -3968,10 +3966,7 @@ iconify(struct swm_region *r, union arg *args)
        a.id = SWM_ARG_ID_FOCUSCUR;
        focus(r, &a);
 
-       if (focus_mode == SWM_FOCUS_DEFAULT)
-               event_drain(XCB_ENTER_NOTIFY);
-       else
-               xcb_flush(conn);
+       focus_flush();
 }
 
 char *
@@ -4449,13 +4444,7 @@ floating_toggle_win(struct ws_win *win)
                }
                win->floating = 0;
        } else {
-               if (win->g_floatvalid) {
-                       /* refloat at last floating relative position */
-                       X(win) = win->g_float.x + X(r);
-                       Y(win) = win->g_float.y + Y(r);
-                       WIDTH(win) = win->g_float.w;
-                       HEIGHT(win) = win->g_float.h;
-               }
+               load_float_geom(win, r);
                win->floating = 1;
        }
 
@@ -4476,6 +4465,9 @@ floating_toggle(struct swm_region *r, union arg *args)
        if (win == NULL)
                return;
 
+       if (win->ewmh_flags & EWMH_F_FULLSCREEN)
+               return;
+
        ewmh_update_win_state(win, ewmh[_NET_WM_STATE_ABOVE].atom,
            _NET_WM_STATE_TOGGLE);
 
@@ -4486,10 +4478,7 @@ floating_toggle(struct swm_region *r, union arg *args)
                focus(win->ws->r, &a);
        }
 
-       if (focus_mode == SWM_FOCUS_DEFAULT)
-               event_drain(XCB_ENTER_NOTIFY);
-       else
-               xcb_flush(conn);
+       focus_flush();
 }
 
 void
@@ -4595,10 +4584,7 @@ resize(struct ws_win *win, union arg *args)
 
        stack();
 
-       if (focus_mode == SWM_FOCUS_DEFAULT)
-               event_drain(XCB_ENTER_NOTIFY);
-       else
-               xcb_flush(conn);
+       focus_flush();
 
        switch (args->id) {
        case SWM_ARG_ID_WIDTHSHRINK:
@@ -4718,8 +4704,8 @@ resize(struct ws_win *win, union arg *args)
                        /* not free, don't sync more than 120 times / second */
                        if ((mne->time - timestamp) > (1000 / 120) ) {
                                timestamp = mne->time;
-                               do_sync();
                                update_window(win);
+                               xcb_flush(conn);
                        }
                        break;
                default:
@@ -4729,8 +4715,8 @@ resize(struct ws_win *win, union arg *args)
                free(evt);
        }
        if (timestamp) {
-               do_sync();
                update_window(win);
+               xcb_flush(conn);
        }
        store_float_geom(win,r);
 
@@ -4793,10 +4779,7 @@ move(struct ws_win *win, union arg *args)
 
        stack();
 
-       if (focus_mode == SWM_FOCUS_DEFAULT)
-               event_drain(XCB_ENTER_NOTIFY);
-       else
-               xcb_flush(conn);
+       focus_flush();
 
        move_step = 0;
        switch (args->id) {
@@ -4865,8 +4848,8 @@ move(struct ws_win *win, union arg *args)
                        /* not free, don't sync more than 120 times / second */
                        if ((mne->time - timestamp) > (1000 / 120) ) {
                                timestamp = mne->time;
-                               do_sync();
                                update_window(win);
+                               xcb_flush(conn);
                        }
                        break;
                default:
@@ -4876,8 +4859,8 @@ move(struct ws_win *win, union arg *args)
                free(evt);
        }
        if (timestamp) {
-               do_sync();
                update_window(win);
+               xcb_flush(conn);
        }
        store_float_geom(win, r);
        free(qpr);
@@ -5857,27 +5840,19 @@ grabkeys(void)
 }
 
 void
-grabbuttons(struct ws_win *win, int focused)
+grabbuttons(struct ws_win *win)
 {
        int             i;
 
        xcb_ungrab_button(conn, XCB_BUTTON_INDEX_ANY, win->id,
            XCB_BUTTON_MASK_ANY);
-       if (focused) {
-               for (i = 0; i < LENGTH(buttons); i++)
-                       if (buttons[i].action == client_click)
-                               xcb_grab_button(conn, 0, win->id,
-                                   BUTTONMASK,
-                                   XCB_GRAB_MODE_ASYNC,
-                                   XCB_GRAB_MODE_SYNC,
-                                   XCB_WINDOW_NONE,
-                                   XCB_CURSOR_NONE,
-                                   buttons[i].button,
-                                   buttons[i].mask);
-       } else
-               xcb_grab_button(conn, 0, win->id, BUTTONMASK,
-                   XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_SYNC, XCB_WINDOW_NONE,
-                   XCB_CURSOR_NONE, XCB_BUTTON_INDEX_ANY, XCB_BUTTON_MASK_ANY);
+
+       for (i = 0; i < LENGTH(buttons); i++)
+               if (buttons[i].action == client_click)
+                       xcb_grab_button(conn, 0, win->id, BUTTONMASK,
+                           XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC,
+                           XCB_WINDOW_NONE, XCB_CURSOR_NONE,
+                           buttons[i].button, buttons[i].mask);
 }
 
 const char *quirkname[] = {
@@ -6202,8 +6177,8 @@ setconfvalue(char *selector, char *value, int flags)
                        focus_mode = SWM_FOCUS_DEFAULT;
                else if (!strcmp(value, "follow_cursor"))
                        focus_mode = SWM_FOCUS_FOLLOW;
-               else if (!strcmp(value, "synergy"))
-                       focus_mode = SWM_FOCUS_SYNERGY;
+               else if (!strcmp(value, "manual"))
+                       focus_mode = SWM_FOCUS_MANUAL;
                else
                        errx(1, "focus_mode");
                break;
@@ -6457,10 +6432,7 @@ setlayout(char *selector, char *value, int flags)
                }
        }
 
-       if (focus_mode == SWM_FOCUS_DEFAULT)
-               event_drain(XCB_ENTER_NOTIFY);
-       else
-               xcb_flush(conn);
+       focus_flush();
 
        return (0);
 }
@@ -6812,11 +6784,12 @@ manage_window(xcb_window_t id)
        X(win) = win->wa->x + win->wa->border_width;
        Y(win) = win->wa->y + win->wa->border_width;
        win->bordered = 0;
-       win->g_floatvalid = 0;
        win->floatmaxed = 0;
        win->ewmh_flags = 0;
        win->s = r->s;  /* this never changes */
 
+       store_float_geom(win, r);
+
        /* Get WM_SIZE_HINTS. */
        xcb_icccm_get_wm_normal_hints_reply(conn,
            xcb_icccm_get_wm_normal_hints(conn, win->id),
@@ -6891,6 +6864,8 @@ manage_window(xcb_window_t id)
 
                /* java is retarded so treat it special */
                if (strstr(win->ch.instance_name, "sun-awt")) {
+                       DNPRINTF(SWM_D_CLASS, "manage_window: java window "
+                           "detected.\n");
                        win->java = 1;
                        border_me = 1;
                }
@@ -6923,16 +6898,16 @@ manage_window(xcb_window_t id)
                        fake_keypress(win, XK_KP_Add, XCB_MOD_MASK_SHIFT);
        }
 
-       /* Make sure window is positioned inside its region, if its active. */
-       if (win->ws->r)
-               constrain_window(win, win->ws->r, 0);
-
        if (border_me) {
                win->bordered = 1;
                X(win) -= border_width;
                Y(win) -= border_width;
        }
 
+       /* Make sure window is positioned inside its region, if its active. */
+       if (win->ws->r)
+               constrain_window(win, win->ws->r, 0);
+
        if (win->ws->r || border_me)
                update_window(win);
 
@@ -6943,7 +6918,8 @@ manage_window(xcb_window_t id)
        event_mask |= XCB_EVENT_MASK_LEAVE_WINDOW;
 #endif
 
-       xcb_change_window_attributes(conn, id, XCB_CW_EVENT_MASK, &event_mask);
+       xcb_change_window_attributes(conn, win->id, XCB_CW_EVENT_MASK,
+           &event_mask);
 
 out:
        /* Figure out where to stack the window in the workspace. */
@@ -6970,6 +6946,8 @@ out:
        /* Set initial _NET_WM_ALLOWED_ACTIONS */
        ewmh_update_actions(win);
 
+       grabbuttons(win);
+
        DNPRINTF(SWM_D_MISC, "manage_window: done. window: 0x%x, (x,y) w x h: "
            "(%d,%d) %d x %d, ws: %d, iconic: %s, transient: 0x%x\n", win->id,
            X(win), Y(win), WIDTH(win), HEIGHT(win), win->ws->idx,
@@ -7083,7 +7061,7 @@ buttonpress(xcb_button_press_event_t *e)
 {
        struct ws_win           *win;
        int                     i;
-       unsigned int            action;
+       int                     handled = 0;
 
        DNPRINTF(SWM_D_EVENT, "buttonpress: window 0x%x, detail: %u\n",
            e->event, e->detail);
@@ -7092,13 +7070,19 @@ buttonpress(xcb_button_press_event_t *e)
                return;
 
        focus_win(focus_magic(win));
-       action = client_click;
 
        for (i = 0; i < LENGTH(buttons); i++)
-               if (action == buttons[i].action && buttons[i].func &&
+               if (client_click == buttons[i].action && buttons[i].func &&
                    buttons[i].button == e->detail &&
-                   CLEANMASK(buttons[i].mask) == CLEANMASK(e->state))
+                   CLEANMASK(buttons[i].mask) == CLEANMASK(e->state)) {
                        buttons[i].func(win, &buttons[i].args);
+                       handled = 1;
+               }
+
+       if (!handled) {
+               DNPRINTF(SWM_D_EVENT, "buttonpress: passing to window\n");
+               xcb_allow_events(conn, XCB_ALLOW_REPLAY_POINTER, e->time);
+       }
 
        xcb_flush(conn);
 }
@@ -7160,6 +7144,7 @@ void
 configurerequest(xcb_configure_request_event_t *e)
 {
        struct ws_win           *win;
+       struct swm_region       *r = NULL;
        int                     new = 0, i = 0;
        uint16_t                mask = 0;
        uint32_t                wc[7] = {0};
@@ -7167,6 +7152,7 @@ configurerequest(xcb_configure_request_event_t *e)
        if ((win = find_window(e->window)) == NULL)
                if ((win = find_unmanaged_window(e->window)) == NULL)
                        new = 1;
+
 #ifdef SWM_DEBUG
        if (swm_debug & SWM_D_EVENT) {
                print_win_geom(e->window);
@@ -7227,20 +7213,24 @@ configurerequest(xcb_configure_request_event_t *e)
                        xcb_configure_window(conn, e->window, mask, wc);
        } else if ((!win->manual || win->quirks & SWM_Q_ANYWHERE) &&
            !(win->ewmh_flags & EWMH_F_FULLSCREEN)) {
-               if (e->value_mask & XCB_CONFIG_WINDOW_X) {
-                       win->g_float.x = e->x;
-                       if (win->ws->r)
-                               win->g_float.x -= X(win->ws->r);
-                       else if (win->ws->old_r)
-                               win->g_float.x -= X(win->ws->old_r);
-               }
+               if (win->ws->r)
+                       r = win->ws->r;
+               else if (win->ws->old_r)
+                       r = win->ws->old_r;
+
+               /* windows are centered unless ANYWHERE quirk is set. */
+               if (win->quirks & SWM_Q_ANYWHERE) {
+                       if (e->value_mask & XCB_CONFIG_WINDOW_X) {
+                               win->g_float.x = e->x;
+                               if (r)
+                                       win->g_float.x -= X(r);
+                       }
 
-               if (e->value_mask & XCB_CONFIG_WINDOW_Y) {
-                       win->g_float.y = e->y;
-                       if (win->ws->r)
-                               win->g_float.y -= Y(win->ws->r);
-                       else if (win->ws->old_r)
-                               win->g_float.y -= Y(win->ws->old_r);
+                       if (e->value_mask & XCB_CONFIG_WINDOW_Y) {
+                               win->g_float.y = e->y;
+                               if (r)
+                                       win->g_float.y -= Y(r);
+                       }
                }
 
                if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH)
@@ -7251,21 +7241,21 @@ configurerequest(xcb_configure_request_event_t *e)
 
                win->g_floatvalid = 1;
 
-               if (win->floating && win->ws->r) {
-                       /* window is visible and floating; update position. */
-                       win->g = win->g_float;
-                       X(win) += X(win->ws->r);
-                       Y(win) += Y(win->ws->r);
+               if (win->floating && r) {
+                       WIDTH(win) = win->g_float.w;
+                       HEIGHT(win) = win->g_float.h;
 
-                       update_window(win);
+                       stack_floater(win, win->ws->r);
+
+                       focus_flush();
                } else {
                        config_win(win, e);
+                       xcb_flush(conn);
                }
        } else {
                config_win(win, e);
+               xcb_flush(conn);
        }
-
-       xcb_flush(conn);
 }
 
 void
@@ -7311,10 +7301,7 @@ destroynotify(xcb_destroy_notify_event_t *e)
 
        stack();
 
-       if (focus_mode == SWM_FOCUS_DEFAULT)
-               event_drain(XCB_ENTER_NOTIFY);
-       else
-               xcb_flush(conn);
+       focus_flush();
 }
 
 #ifdef SWM_DEBUG
@@ -7385,31 +7372,21 @@ void
 enternotify(xcb_enter_notify_event_t *e)
 {
        struct ws_win           *win;
+
        DNPRINTF(SWM_D_FOCUS, "enternotify: window: 0x%x, mode: %s(%d), "
            "detail: %s(%d), root: 0x%x, subwindow: 0x%x, same_screen_focus: "
            "%s, state: %d\n", e->event, get_notify_mode_label(e->mode),
            e->mode, get_notify_detail_label(e->detail), e->detail, e->root,
            e->child, YESNO(e->same_screen_focus), e->state);
 
-#if 0
-       if (e->mode != XCB_NOTIFY_MODE_NORMAL) {
-               DNPRINTF(SWM_D_EVENT, "skip enternotify: generated by "
-                   "cursor grab.\n");
+       if (focus_mode == SWM_FOCUS_MANUAL &&
+           e->mode == XCB_NOTIFY_MODE_NORMAL) {
+               DNPRINTF(SWM_D_EVENT, "enternotify: manual focus; ignoring.\n");
                return;
        }
-#endif
-
-       switch (focus_mode) {
-       case SWM_FOCUS_DEFAULT:
-               break;
-       case SWM_FOCUS_FOLLOW:
-               break;
-       case SWM_FOCUS_SYNERGY:
-               break;
-       }
 
        if ((win = find_window(e->event)) == NULL) {
-               DNPRINTF(SWM_D_EVENT, "skip enternotify: window is NULL\n");
+               DNPRINTF(SWM_D_EVENT, "enternotify: window is NULL; ignoring\n");
                return;
        }
 
@@ -8114,7 +8091,6 @@ workaround(void)
        int                     i, num_screens;
        xcb_atom_t              netwmcheck;
        xcb_window_t            root, win;
-       uint32_t                wa[2];
 
        /* work around sun jdk bugs, code from wmname */
        netwmcheck = get_atom_from_string("_NET_SUPPORTING_WM_CHECK");
@@ -8124,11 +8100,9 @@ workaround(void)
                root = screens[i].root;
 
                win = xcb_generate_id(conn);
-               wa[0] = screens[i].c[SWM_S_COLOR_UNFOCUS].pixel;
-               wa[1] = screens[i].c[SWM_S_COLOR_UNFOCUS].pixel;
-               xcb_create_window(conn, XCB_COPY_FROM_PARENT, win, 0, 0, 0, 1,
-                   1, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT,
-                   XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL, wa);
+               xcb_create_window(conn, XCB_COPY_FROM_PARENT, win, root,
+                   0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
+                   XCB_COPY_FROM_PARENT, 0, NULL);
 
                xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root,
                    netwmcheck, XCB_ATOM_WINDOW, 32, 1, &win);