]> code.delx.au - spectrwm/blobdiff - spectrwm.c
ad yuri to copyrights
[spectrwm] / spectrwm.c
index 83b31a0ebc46c4995f6b3105f52ee47c0c3c38e6..03c6259e4d889416ee46721eb2c7b378c93ac4fb 100644 (file)
@@ -1,14 +1,15 @@
 /*
- * Copyright (c) 2009-2012 Marco Peereboom <marco@peereboom.us>
+ * Copyright (c) 2009-2015 Marco Peereboom <marco@peereboom.us>
  * Copyright (c) 2009-2011 Ryan McBride <mcbride@countersiege.com>
  * Copyright (c) 2009 Darrin Chandler <dwchandler@stilyagin.com>
  * Copyright (c) 2009 Pierre-Yves Ritschard <pyr@spootnik.org>
  * Copyright (c) 2010 Tuukka Kataja <stuge@xor.fi>
  * Copyright (c) 2011 Jason L. Wright <jason@thought.net>
- * Copyright (c) 2011-2013 Reginald Kennedy <rk@rejii.com>
+ * Copyright (c) 2011-2015 Reginald Kennedy <rk@rejii.com>
  * Copyright (c) 2011-2012 Lawrence Teo <lteo@lteo.net>
  * Copyright (c) 2011-2012 Tiago Cunha <tcunha@gmx.com>
- * Copyright (c) 2012-2013 David Hill <dhill@mindcry.org>
+ * Copyright (c) 2012-2015 David Hill <dhill@mindcry.org>
+ * Copyright (c) 2014-2015 Yuri D'Elia <yuri.delia@eurac.edu>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
 #include <ctype.h>
 #include <err.h>
 #include <errno.h>
+#include <poll.h>
 #include <fcntl.h>
 #include <locale.h>
 #include <paths.h>
 #include <pwd.h>
 #include <regex.h>
 #include <signal.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -114,9 +117,9 @@ static const char   *buildstr = SPECTRWM_BUILDSTR;
 static const char      *buildstr = SPECTRWM_VERSION;
 #endif
 
-#if !defined(__CYGWIN__) /* cygwin chokes on xrandr stuff */
+#if !defined(__CYGWIN__) /* cygwin chokes on randr stuff */
 #  if RANDR_MAJOR < 1
-#    error XRandR versions less than 1.0 are not supported
+#    error RandR versions less than 1.0 are not supported
 #endif
 
 #  if RANDR_MAJOR >= 1
@@ -316,9 +319,8 @@ volatile sig_atomic_t   running = 1;
 volatile sig_atomic_t   restart_wm = 0;
 xcb_timestamp_t                last_event_time = 0;
 int                    outputs = 0;
-int                    other_wm;
-int                    xrandr_support;
-int                    xrandr_eventbase;
+bool                   randr_support;
+int                    randr_eventbase;
 unsigned int           numlockmask = 0;
 
 Display                        *display;
@@ -326,11 +328,14 @@ xcb_connection_t  *conn;
 xcb_key_symbols_t      *syms;
 
 int                    boundary_width = 50;
-int                    cycle_empty = 0;
-int                    cycle_visible = 0;
+bool                   cycle_empty = false;
+bool                   cycle_visible = false;
 int                    term_width = 0;
 int                    font_adjusted = 0;
 unsigned int           mod_key = MODKEY;
+bool                   warp_pointer = false;
+unsigned int           mouse_button_move = XCB_BUTTON_INDEX_1;
+unsigned int           mouse_button_resize = XCB_BUTTON_INDEX_3;
 
 /* dmenu search */
 struct swm_region      *search_r;
@@ -389,42 +394,46 @@ int                bar_pipe[2];
 char            bar_ext[SWM_BAR_MAX];
 char            bar_ext_buf[SWM_BAR_MAX];
 char            bar_vertext[SWM_BAR_MAX];
-int             bar_version = 0;
-int             bar_enabled = 1;
+bool            bar_version = false;
+bool            bar_enabled = true;
 int             bar_border_width = 1;
-int             bar_at_bottom = 0;
-int             bar_extra = 0;
-int             bar_verbose = 1;
+bool            bar_at_bottom = false;
+bool            bar_extra = false;
 int             bar_height = 0;
 int             bar_justify = SWM_BAR_JUSTIFY_LEFT;
 char            *bar_format = NULL;
-int             stack_enabled = 1;
-int             clock_enabled = 1;
-int             iconic_enabled = 0;
-int             urgent_enabled = 0;
+bool            stack_enabled = true;
+bool            clock_enabled = true;
+bool            iconic_enabled = false;
+bool            maximize_hide_bar = false;
+bool            urgent_enabled = false;
+bool            urgent_collapse = false;
 char           *clock_format = NULL;
-int             window_class_enabled = 0;
-int             window_instance_enabled = 0;
-int             window_name_enabled = 0;
+bool            window_class_enabled = false;
+bool            window_instance_enabled = false;
+bool            window_name_enabled = false;
 int             focus_mode = SWM_FOCUS_DEFAULT;
 int             focus_close = SWM_STACK_BELOW;
-int             focus_close_wrap = 1;
+bool            focus_close_wrap = true;
 int             focus_default = SWM_STACK_TOP;
 int             spawn_position = SWM_STACK_TOP;
-int             disable_border = 0;
+bool            disable_border = false;
 int             border_width = 1;
 int             region_padding = 0;
 int             tile_gap = 0;
-int             java_workaround = 1;
-int             verbose_layout = 0;
+bool            java_workaround = true;
+bool            verbose_layout = false;
+#ifdef SWM_DEBUG
 time_t          time_started;
+#endif
 pid_t           bar_pid;
 XFontSet        bar_fs;
 XFontSetExtents        *bar_fs_extents;
 XftFont                *bar_font;
-int             bar_font_legacy = 1;
+bool            bar_font_legacy = true;
 char           *bar_fonts;
 XftColor        bar_font_color;
+XftColor        search_font_color;
 struct passwd  *pwd;
 char           *startup_exception;
 unsigned int    nr_exceptions = 0;
@@ -466,17 +475,17 @@ struct ws_win {
        struct ws_win           *focus_child;   /* focus on child transient */
        struct swm_geometry     g;              /* current geometry */
        struct swm_geometry     g_float;        /* region coordinates */
-       int                     g_floatvalid;   /* g_float geometry validity */
-       int                     mapped;
-       int                     bordered;
+       bool                    g_floatvalid;   /* g_float geometry validity */
+       bool                    mapped;
+       bool                    bordered;
        uint32_t                ewmh_flags;
        int                     font_size_boundary[SWM_MAX_FONT_STEPS];
        int                     font_steps;
        int                     last_inc;
-       int                     can_delete;
-       int                     take_focus;
-       int                     java;
-       unsigned long           quirks;
+       bool                    can_delete;
+       bool                    take_focus;
+       bool                    java;
+       uint32_t                quirks;
        struct workspace        *ws;    /* always valid */
        struct swm_screen       *s;     /* always valid, never changes */
        xcb_size_hints_t        sh;
@@ -533,8 +542,8 @@ struct layout {
 struct workspace {
        int                     idx;            /* workspace index */
        char                    *name;          /* workspace name */
-       int                     always_raise;   /* raise windows on focus */
-       int                     bar_enabled;    /* bar visibility */
+       bool                    always_raise;   /* raise windows on focus */
+       bool                    bar_enabled;    /* bar visibility */
        struct layout           *cur_layout;    /* current layout handlers */
        struct ws_win           *focus;         /* may be NULL */
        struct ws_win           *focus_prev;    /* may be NULL */
@@ -552,11 +561,11 @@ struct workspace {
                                int horizontal_msize;
                                int horizontal_mwin;
                                int horizontal_stacks;
-                               int horizontal_flip;
+                               bool horizontal_flip;
                                int vertical_msize;
                                int vertical_mwin;
                                int vertical_stacks;
-                               int vertical_flip;
+                               bool vertical_flip;
        } l_state;
 };
 
@@ -572,7 +581,9 @@ enum {
        SWM_S_COLOR_BAR_BORDER_UNFOCUS,
        SWM_S_COLOR_BAR_FONT,
        SWM_S_COLOR_FOCUS,
+       SWM_S_COLOR_FOCUS_MAXIMIZED,
        SWM_S_COLOR_UNFOCUS,
+       SWM_S_COLOR_UNFOCUS_MAXIMIZED,
        SWM_S_COLOR_MAX
 };
 
@@ -592,6 +603,7 @@ struct swm_screen {
        struct {
                uint32_t        pixel;
                char            *name;
+               int             manual;
        } c[SWM_S_COLOR_MAX];
 
        xcb_gcontext_t          bar_gc;
@@ -617,6 +629,7 @@ union arg {
 #define SWM_ARG_ID_FLIPLAYOUT  (24)
 #define SWM_ARG_ID_STACKRESET  (30)
 #define SWM_ARG_ID_STACKINIT   (31)
+#define SWM_ARG_ID_STACKBALANCE        (32)
 #define SWM_ARG_ID_CYCLEWS_UP  (40)
 #define SWM_ARG_ID_CYCLEWS_DOWN        (41)
 #define SWM_ARG_ID_CYCLERG_UP  (42)
@@ -645,6 +658,8 @@ union arg {
 #define SWM_ARG_ID_LOWER       (106)
 #define SWM_ARG_ID_BAR_TOGGLE  (110)
 #define SWM_ARG_ID_BAR_TOGGLE_WS       (111)
+#define SWM_ARG_ID_CYCLERG_MOVE_UP     (112)
+#define SWM_ARG_ID_CYCLERG_MOVE_DOWN   (113)
        char                    **argv;
 };
 
@@ -657,7 +672,8 @@ struct quirk {
        regex_t                 regex_class;
        regex_t                 regex_instance;
        regex_t                 regex_name;
-       unsigned long           quirk;
+       uint32_t                quirk;
+       int                     ws;             /* Initial workspace. */
 #define SWM_Q_FLOAT            (1<<0)  /* float this window */
 #define SWM_Q_TRANSSZ          (1<<1)  /* transiend window size too small */
 #define SWM_Q_ANYWHERE         (1<<2)  /* don't position this window */
@@ -666,6 +682,10 @@ struct quirk {
 #define SWM_Q_FOCUSPREV                (1<<5)  /* focus on caller */
 #define SWM_Q_NOFOCUSONMAP     (1<<6)  /* Don't focus on window when mapped. */
 #define SWM_Q_FOCUSONMAP_SINGLE        (1<<7)  /* Only focus if single win of type. */
+#define SWM_Q_OBEYAPPFOCUSREQ  (1<<8)  /* Focus when applications ask. */
+#define SWM_Q_IGNOREPID                (1<<9)  /* Ignore PID when determining ws. */
+#define SWM_Q_IGNORESPAWNWS    (1<<10) /* Ignore _SWM_WS when managing win. */
+#define SWM_Q_NOFOCUSCYCLE     (1<<11) /* Remove from normal focus cycle. */
 };
 TAILQ_HEAD(quirk_list, quirk);
 struct quirk_list              quirks = TAILQ_HEAD_INITIALIZER(quirks);
@@ -871,6 +891,8 @@ enum keyfuncid {
        KF_RG_9,
        KF_RG_NEXT,
        KF_RG_PREV,
+       KF_RG_MOVE_NEXT,
+       KF_RG_MOVE_PREV,
        KF_SCREEN_NEXT,
        KF_SCREEN_PREV,
        KF_SEARCH_WIN,
@@ -879,6 +901,7 @@ enum keyfuncid {
        KF_STACK_INC,
        KF_STACK_DEC,
        KF_STACK_RESET,
+       KF_STACK_BALANCE,
        KF_SWAP_MAIN,
        KF_SWAP_NEXT,
        KF_SWAP_PREV,
@@ -956,6 +979,7 @@ void         bar_window_name(char *, size_t, struct swm_region *);
 void    bar_window_state(char *, size_t, struct swm_region *);
 void    bar_workspace_name(char *, size_t, struct swm_region *);
 void    buttonpress(xcb_button_press_event_t *);
+void    center_pointer(struct swm_region *);
 void    check_conn(void);
 void    clear_keys(void);
 int     clear_maximized(struct workspace *);
@@ -966,7 +990,7 @@ void         configurenotify(xcb_configure_notify_event_t *);
 void    configurerequest(xcb_configure_request_event_t *);
 void    config_win(struct ws_win *, xcb_configure_request_event_t *);
 void    constrain_window(struct ws_win *, struct swm_geometry *, int *);
-int     count_win(struct workspace *, int);
+int     count_win(struct workspace *, bool);
 void    cursors_cleanup(void);
 void    cursors_load(void);
 void    custom_region(const char *);
@@ -1025,18 +1049,20 @@ int      get_region_index(struct swm_region *);
 xcb_screen_t   *get_screen(int);
 int     get_screen_count(void);
 #ifdef SWM_DEBUG
+char   *get_source_type_label(uint32_t);
 char   *get_stack_mode_name(uint8_t);
 #endif
 int32_t         get_swm_ws(xcb_window_t);
+bool    get_urgent(struct ws_win *);
 char   *get_win_name(xcb_window_t);
 uint8_t         get_win_state(xcb_window_t);
 void    get_wm_protocols(struct ws_win *);
-int     get_ws_idx(xcb_window_t);
+int     get_ws_idx(struct ws_win *);
 void    grabbuttons(struct ws_win *);
 void    grabkeys(void);
 void    grab_windows(void);
 void    iconify(struct swm_region *, union arg *);
-int     isxlfd(char *);
+bool    isxlfd(char *);
 void    keypress(xcb_key_press_event_t *);
 int     key_cmp(struct key *, struct key *);
 void    key_insert(unsigned int, KeySym, enum keyfuncid, const char *);
@@ -1050,7 +1076,8 @@ void       kill_refs(struct ws_win *);
 void    leavenotify(xcb_leave_notify_event_t *);
 #endif
 void    load_float_geom(struct ws_win *);
-struct ws_win  *manage_window(xcb_window_t, int);
+void    lower_window(struct ws_win *);
+struct ws_win  *manage_window(xcb_window_t, int, bool);
 void    map_window(struct ws_win *);
 void    mapnotify(xcb_map_notify_event_t *);
 void    mappingnotify(xcb_mapping_notify_event_t *);
@@ -1063,7 +1090,7 @@ uint32_t name_to_pixel(int, const char *);
 void    name_workspace(struct swm_region *, union arg *);
 void    new_region(struct swm_screen *, int, int, int, int);
 int     parsekeys(const char *, unsigned int, unsigned int *, KeySym *);
-int     parsequirks(const char *, unsigned long *);
+int     parsequirks(const char *, uint32_t *, int *);
 int     parse_rgb(const char *, uint16_t *, uint16_t *, uint16_t *);
 void    pressbutton(struct swm_region *, union arg *);
 void    priorws(struct swm_region *, union arg *);
@@ -1072,10 +1099,10 @@ void     print_win_geom(xcb_window_t);
 #endif
 void    propertynotify(xcb_property_notify_event_t *);
 void    quirk_free(struct quirk *);
-void    quirk_insert(const char *, const char *, const char *,unsigned long);
+void    quirk_insert(const char *, const char *, const char *, uint32_t, int);
 void    quirk_remove(struct quirk *);
 void    quirk_replace(struct quirk *, const char *, const char *, const char *,
-            unsigned long);
+            uint32_t, int);
 void    quit(struct swm_region *, union arg *);
 void    raise_toggle(struct swm_region *, union arg *);
 void    raise_window(struct ws_win *);
@@ -1087,7 +1114,7 @@ void       resize_step(struct swm_region *, union arg *);
 void    restart(struct swm_region *, union arg *);
 struct swm_region      *root_to_region(xcb_window_t, int);
 void    screenchange(xcb_randr_screen_change_notify_event_t *);
-void    scan_xrandr(int);
+void    scan_randr(int);
 void    search_do_resp(void);
 void    search_resp_name_workspace(const char *, size_t);
 void    search_resp_search_window(const char *);
@@ -1103,6 +1130,8 @@ int        setautorun(const char *, const char *, int);
 int     setconfbinding(const char *, const char *, int);
 int     setconfcolor(const char *, const char *, int);
 int     setconfmodkey(const char *, const char *, int);
+int     setconfmousebuttonmove(const char *, const char *, int);
+int     setconfmousebuttonresize(const char *, const char *, int);
 int     setconfquirk(const char *, const char *, int);
 int     setconfregion(const char *, const char *, int);
 int     setconfspawn(const char *, const char *, int);
@@ -1110,7 +1139,7 @@ int        setconfvalue(const char *, const char *, int);
 void    setkeybinding(unsigned int, KeySym, enum keyfuncid, const char *);
 int     setkeymapping(const char *, const char *, int);
 int     setlayout(const char *, const char *, int);
-void    setquirk(const char *, const char *, const char *,unsigned long);
+void    setquirk(const char *, const char *, const char *, uint32_t, int);
 void    setscreencolor(const char *, int, int);
 void    setspawn(const char *, const char *, int);
 void    setup_ewmh(void);
@@ -1125,7 +1154,7 @@ void       shutdown_cleanup(void);
 void    sighdlr(int);
 void    socket_setnonblock(int);
 void    sort_windows(struct ws_win_list *);
-void    spawn(int, union arg *, int);
+void    spawn(int, union arg *, bool);
 void    spawn_custom(struct swm_region *, union arg *, const char *);
 int     spawn_expand(struct swm_region *, union arg *, const char *, char ***);
 void    spawn_insert(const char *, const char *, int);
@@ -1134,7 +1163,7 @@ void       spawn_remove(struct spawn_prog *);
 void    spawn_replace(struct spawn_prog *, const char *, const char *, int);
 void    spawn_select(struct swm_region *, union arg *, const char *, int *);
 void    stack_config(struct swm_region *, union arg *);
-void    stack_master(struct workspace *, struct swm_geometry *, int, int);
+void    stack_master(struct workspace *, struct swm_geometry *, int, bool);
 void    store_float_geom(struct ws_win *);
 char   *strdupsafe(const char *);
 void    swapwin(struct swm_region *, union arg *);
@@ -1150,14 +1179,16 @@ void     unmap_window(struct ws_win *);
 void    updatenumlockmask(void);
 void    update_floater(struct ws_win *);
 void    update_modkey(unsigned int);
+unsigned char  update_mousebutton(unsigned char, unsigned int);
 void    update_win_stacking(struct ws_win *);
 void    update_window(struct ws_win *);
+void    update_window_color(struct ws_win *);
 void    update_wm_state(struct  ws_win *win);
 void    validate_spawns(void);
 int     validate_win(struct ws_win *);
 int     validate_ws(struct workspace *);
 void    version(struct swm_region *, union arg *);
-void    win_to_ws(struct ws_win *, int, int);
+void    win_to_ws(struct ws_win *, int, bool);
 pid_t   window_get_pid(xcb_window_t);
 void    wkill(struct swm_region *, union arg *);
 void    update_ws_stack(struct workspace *);
@@ -1360,9 +1391,9 @@ get_wm_protocols(struct ws_win *win) {
            &wpr, NULL)) {
                for (i = 0; i < (int)wpr.atoms_len; i++) {
                        if (wpr.atoms[i] == a_takefocus)
-                               win->take_focus = 1;
+                               win->take_focus = true;
                        if (wpr.atoms[i] == a_delete)
-                               win->can_delete = 1;
+                               win->can_delete = true;
                }
                xcb_icccm_get_wm_protocols_reply_wipe(&wpr);
        }
@@ -1632,6 +1663,8 @@ ewmh_apply_flags(struct ws_win *win, uint32_t pending)
                                        ws->focus_pending = win;
                        }
                }
+
+               update_window_color(win);
                raise_window(win);
        }
 
@@ -1894,24 +1927,13 @@ name_to_pixel(int sidx, const char *colorname)
 void
 setscreencolor(const char *val, int i, int c)
 {
-       int     num_screens;
+       if (i < 0 || i >= get_screen_count())
+               return;
 
-       num_screens = get_screen_count();
-       if (i > 0 && i <= num_screens) {
-               screens[i - 1].c[c].pixel = name_to_pixel(i - 1, val);
-               free(screens[i - 1].c[c].name);
-               if ((screens[i - 1].c[c].name = strdup(val)) == NULL)
-                       err(1, "strdup");
-       } else if (i == -1) {
-               for (i = 0; i < num_screens; i++) {
-                       screens[i].c[c].pixel = name_to_pixel(0, val);
-                       free(screens[i].c[c].name);
-                       if ((screens[i].c[c].name = strdup(val)) == NULL)
-                               err(1, "strdup");
-               }
-       } else
-               errx(1, "invalid screen index: %d out of bounds (maximum %d)",
-                   i, num_screens);
+       screens[i].c[c].pixel = name_to_pixel(i, val);
+       free(screens[i].c[c].name);
+       if ((screens[i].c[c].name = strdup(val)) == NULL)
+               err(1, "strdup");
 }
 
 void
@@ -2107,7 +2129,7 @@ bar_extra_stop(void)
                bar_pid = 0;
        }
        strlcpy(bar_ext, "", sizeof bar_ext);
-       bar_extra = 0;
+       bar_extra = false;
 }
 
 void
@@ -2163,37 +2185,47 @@ bar_window_name(char *s, size_t sz, struct swm_region *r)
        free(title);
 }
 
+bool
+get_urgent(struct ws_win *win)
+{
+       xcb_icccm_wm_hints_t            hints;
+       xcb_get_property_cookie_t       c;
+       bool                            urgent = false;
+
+       if (win) {
+               c = xcb_icccm_get_wm_hints(conn, win->id);
+               if (xcb_icccm_get_wm_hints_reply(conn, c, &hints, NULL))
+                       urgent = xcb_icccm_wm_hints_get_urgency(&hints);
+       }
+
+       return urgent;
+}
+
 void
 bar_urgent(char *s, size_t sz)
 {
        struct ws_win           *win;
        int                     i, j, num_screens;
-       int                     urgent[SWM_WS_MAX];
+       bool                    urgent[SWM_WS_MAX];
        char                    b[8];
-       xcb_get_property_cookie_t       c;
-       xcb_icccm_wm_hints_t    hints;
 
        for (i = 0; i < workspace_limit; i++)
-               urgent[i] = 0;
+               urgent[i] = false;
 
        num_screens = get_screen_count();
        for (i = 0; i < num_screens; i++)
                for (j = 0; j < workspace_limit; j++)
-                       TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry) {
-                               c = xcb_icccm_get_wm_hints(conn, win->id);
-                               if (xcb_icccm_get_wm_hints_reply(conn, c,
-                                   &hints, NULL) == 0)
-                                       continue;
-                               if (hints.flags & XCB_ICCCM_WM_HINT_X_URGENCY)
-                                       urgent[j] = 1;
-                       }
+                       TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry)
+                               if (get_urgent(win))
+                                       urgent[j] = true;
 
        for (i = 0; i < workspace_limit; i++) {
-               if (urgent[i])
+               if (urgent[i]) {
                        snprintf(b, sizeof b, "%d ", i + 1);
-               else
-                       snprintf(b, sizeof b, "- ");
-               strlcat(s, b, sz);
+                       strlcat(s, b, sz);
+               } else if (!urgent_collapse) {
+                       strlcat(s, "- ", sz);
+               }
        }
 }
 
@@ -2485,7 +2517,7 @@ bar_extra_update(void)
 {
        size_t          len;
        char            b[SWM_BAR_MAX];
-       int             changed = 0;
+       bool            changed = false;
 
        if (!bar_extra)
                return changed;
@@ -2507,7 +2539,7 @@ bar_extra_update(void)
                                /* Append new output to bar. */
                                strlcat(bar_ext, b, sizeof(bar_ext));
 
-                               changed = 1;
+                               changed = true;
                        } else {
                                /* Buffer output. */
                                strlcat(bar_ext_buf, b, sizeof(bar_ext_buf));
@@ -2518,7 +2550,7 @@ bar_extra_update(void)
        if (errno != EAGAIN) {
                warn("bar_action failed");
                bar_extra_stop();
-               changed = 1;
+               changed = true;
        }
 
        return changed;
@@ -2542,7 +2574,7 @@ bar_toggle(struct swm_region *r, union arg *args)
                if (bar_enabled)
                        r->ws->bar_enabled = !r->ws->bar_enabled;
                else
-                       bar_enabled = r->ws->bar_enabled = 1;
+                       bar_enabled = r->ws->bar_enabled = true;
                break;
        case SWM_ARG_ID_BAR_TOGGLE:
                bar_enabled = !bar_enabled;
@@ -2574,7 +2606,7 @@ bar_extra_setup(void)
        /* do this here because the conf file is in memory */
        if (!bar_extra && bar_argv[0]) {
                /* launch external status app */
-               bar_extra = 1;
+               bar_extra = true;
                if (pipe(bar_pipe) == -1)
                        err(1, "pipe error");
                socket_setnonblock(bar_pipe[0]);
@@ -2615,7 +2647,7 @@ kill_bar_extra_atexit(void)
                kill(bar_pid, SIGTERM);
 }
 
-int
+bool
 isxlfd(char *s)
 {
        int      count = 0;
@@ -2718,6 +2750,12 @@ xft_init(struct swm_region *r)
            DefaultColormap(display, r->s->idx), &color, &bar_font_color))
                warn("Xft error: unable to allocate color.");
 
+       PIXEL_TO_XRENDERCOLOR(r->s->c[SWM_S_COLOR_BAR].pixel, color);
+
+       if (!XftColorAllocValue(display, DefaultVisual(display, r->s->idx),
+           DefaultColormap(display, r->s->idx), &color, &search_font_color))
+               warn("Xft error: unable to allocate color.");
+
        bar_height = bar_font->height + 2 * bar_border_width;
 
        if (bar_height < 1)
@@ -2765,11 +2803,18 @@ bar_setup(struct swm_region *r)
            XCB_COPY_FROM_PARENT, XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL
            | XCB_CW_EVENT_MASK, wa);
 
+       /* Stack bar window above region window to start. */
+       wa[0] = r->id;
+       wa[1] = XCB_STACK_MODE_ABOVE;
+
+       xcb_configure_window(conn, r->bar->id, XCB_CONFIG_WINDOW_SIBLING |
+           XCB_CONFIG_WINDOW_STACK_MODE, wa);
+
        r->bar->buffer = xcb_generate_id(conn);
        xcb_create_pixmap(conn, screen->root_depth, r->bar->buffer, r->bar->id,
            WIDTH(r->bar), HEIGHT(r->bar));
 
-       if (xrandr_support)
+       if (randr_support)
                xcb_randr_select_input(conn, r->bar->id,
                    XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE);
 
@@ -2959,7 +3004,7 @@ config_win(struct ws_win *win, xcb_configure_request_event_t *ev)
 }
 
 int
-count_win(struct workspace *ws, int count_transient)
+count_win(struct workspace *ws, bool count_transient)
 {
        struct ws_win           *win;
        int                     count = 0;
@@ -2987,14 +3032,74 @@ quit(struct swm_region *r, union arg *args)
        running = 0;
 }
 
+void
+lower_window(struct ws_win *win)
+{
+       struct ws_win           *target = NULL;
+       struct workspace        *ws;
+
+       if (win == NULL)
+               return;
+
+       ws = win->ws;
+
+       DNPRINTF(SWM_D_EVENT, "lower_window: win %#x\n", win->id);
+
+       TAILQ_FOREACH(target, &ws->stack, stack_entry) {
+               if (target == win || ICONIC(target))
+                       continue;
+               if (ws->cur_layout == &layouts[SWM_MAX_STACK])
+                       break;
+               if (TRANS(win)) {
+                       if (win->transient == target->transient)
+                               continue;
+                       if (win->transient == target->id)
+                               break;
+               }
+               if (FULLSCREEN(target))
+                       continue;
+               if (FULLSCREEN(win))
+                       break;
+               if (MAXIMIZED(target))
+                       continue;
+               if (MAXIMIZED(win))
+                       break;
+               if (ABOVE(target) || TRANS(target))
+                       continue;
+               if (ABOVE(win) || TRANS(win))
+                       break;
+       }
+
+       /* Change stack position. */
+       TAILQ_REMOVE(&ws->stack, win, stack_entry);
+       if (target)
+               TAILQ_INSERT_BEFORE(target, win, stack_entry);
+       else
+               TAILQ_INSERT_TAIL(&ws->stack, win, stack_entry);
+
+       update_win_stacking(win);
+
+#ifdef SWM_DEBUG
+       if (swm_debug & SWM_D_STACK) {
+               DPRINTF("=== stacking order (top down) === \n");
+               TAILQ_FOREACH(target, &ws->stack, stack_entry) {
+                       DPRINTF("win %#x, fs: %s, maximized: %s, above: %s, "
+                           "iconic: %s\n", target->id, YESNO(FULLSCREEN(target)),
+                           YESNO(MAXIMIZED(target)), YESNO(ABOVE(target)),
+                           YESNO(ICONIC(target)));
+               }
+       }
+#endif
+       DNPRINTF(SWM_D_EVENT, "lower_window: done\n");
+}
+
 void
 raise_window(struct ws_win *win)
 {
        struct ws_win           *target = NULL;
-       struct swm_region       *r;
        struct workspace        *ws;
 
-       if (win == NULL || (r = win->ws->r) == NULL)
+       if (win == NULL)
                return;
        ws = win->ws;
 
@@ -3016,23 +3121,25 @@ raise_window(struct ws_win *win)
                        break;
                if (MAXIMIZED(target))
                        continue;
-               if (ABOVE(win) || TRANS(win))
+               if (ABOVE(win) || TRANS(win) ||
+                   (win->ws->focus == win && ws->always_raise))
                        break;
                if (!ABOVE(target) && !TRANS(target))
                        break;
        }
 
-       if (target != NULL) {
-               /* Change stack position. */
-               TAILQ_REMOVE(&ws->stack, win, stack_entry);
+       TAILQ_REMOVE(&ws->stack, win, stack_entry);
+       if (target)
                TAILQ_INSERT_BEFORE(target, win, stack_entry);
-               update_win_stacking(win);
-       }
+       else
+               TAILQ_INSERT_TAIL(&ws->stack, win, stack_entry);
+
+       update_win_stacking(win);
 
 #ifdef SWM_DEBUG
        if (swm_debug & SWM_D_STACK) {
                DPRINTF("=== stacking order (top down) === \n");
-               TAILQ_FOREACH(target, &r->ws->stack, stack_entry) {
+               TAILQ_FOREACH(target, &ws->stack, stack_entry) {
                        DPRINTF("win %#x, fs: %s, maximized: %s, above: %s, "
                            "iconic: %s\n", target->id, YESNO(FULLSCREEN(target)),
                            YESNO(MAXIMIZED(target)), YESNO(ABOVE(target)),
@@ -3054,10 +3161,14 @@ update_win_stacking(struct ws_win *win)
                return;
 
        sibling = TAILQ_NEXT(win, stack_entry);
-       if (sibling != NULL && FLOATING(win) == FLOATING(sibling))
+       if (sibling != NULL && (FLOATING(win) == FLOATING(sibling) ||
+           (win->ws->always_raise && win->ws->focus == win)))
                val[0] = sibling->id;
+       else if (FLOATING(win) || (win->ws->always_raise &&
+           win->ws->focus == win))
+               val[0] = r->bar->id;
        else
-               val[0] = FLOATING(win) ? r->bar->id : r->id;
+               val[0] = r->id;
 
        DNPRINTF(SWM_D_EVENT, "update_win_stacking: %#x, sibling %#x\n",
            win->id, val[0]);
@@ -3082,7 +3193,7 @@ map_window(struct ws_win *win)
 
        xcb_map_window(conn, win->id);
        set_win_state(win, XCB_ICCCM_WM_STATE_NORMAL);
-       win->mapped = 1;
+       win->mapped = true;
 }
 
 void
@@ -3099,7 +3210,7 @@ unmap_window(struct ws_win *win)
 
        xcb_unmap_window(conn, win->id);
        set_win_state(win, XCB_ICCCM_WM_STATE_ICONIC);
-       win->mapped = 0;
+       win->mapped = false;
 }
 
 void
@@ -3192,6 +3303,26 @@ get_pointer_win(xcb_window_t root)
        return win;
 }
 
+void
+center_pointer(struct swm_region *r)
+{
+       struct ws_win                   *win;
+
+       if (!warp_pointer || r == NULL)
+               return;
+
+       win = r->ws->focus;
+
+       DNPRINTF(SWM_D_EVENT, "center_pointer: win %#x.\n", WINID(win));
+
+       if (win && win->mapped)
+               xcb_warp_pointer(conn, XCB_NONE, win->id, 0, 0, 0, 0,
+                   WIDTH(win) / 2, HEIGHT(win) / 2);
+       else
+               xcb_warp_pointer(conn, XCB_NONE, r->id, 0, 0, 0, 0,
+                   WIDTH(r) / 2, HEIGHT(r) / 2);
+}
+
 struct swm_region *
 root_to_region(xcb_window_t root, int check)
 {
@@ -3304,7 +3435,7 @@ find_window(xcb_window_t id)
 }
 
 void
-spawn(int ws_idx, union arg *args, int close_fd)
+spawn(int ws_idx, union arg *args, bool close_fd)
 {
        int                     fd;
        char                    *ret = NULL;
@@ -3468,8 +3599,11 @@ unfocus_win(struct ws_win *win)
                win->ws->focus_prev = NULL;
        }
 
-       xcb_change_window_attributes(conn, win->id, XCB_CW_BORDER_PIXEL,
-           &win->s->c[SWM_S_COLOR_UNFOCUS].pixel);
+       update_window_color(win);
+
+       /* Raise window to "top unfocused position." */
+       if (win->ws->always_raise)
+               raise_window(win);
 
        xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win->s->root,
            ewmh[_NET_ACTIVE_WINDOW].atom, XCB_ATOM_WINDOW, 32, 1, &none);
@@ -3480,19 +3614,13 @@ unfocus_win(struct ws_win *win)
 void
 focus_win(struct ws_win *win)
 {
-       struct ws_win                   *cfw = NULL, *parent = NULL, *w;
+       struct ws_win                   *cfw = NULL, *parent = NULL, *w, *tmpw;
        struct workspace                *ws;
        xcb_get_input_focus_reply_t     *gifr;
 
        DNPRINTF(SWM_D_FOCUS, "focus_win: win %#x\n", WINID(win));
 
-       if (win == NULL)
-               goto out;
-
-       if (win->ws == NULL)
-               goto out;
-
-       if (!win->mapped)
+       if (win == NULL || win->ws == NULL || !win->mapped)
                goto out;
 
        ws = win->ws;
@@ -3513,7 +3641,9 @@ focus_win(struct ws_win *win)
                                /* Change border to unfocused color. */
                                xcb_change_window_attributes(conn, cfw->id,
                                    XCB_CW_BORDER_PIXEL,
-                                   &cfw->s->c[SWM_S_COLOR_UNFOCUS].pixel);
+                                   &cfw->s->c[(MAXIMIZED(cfw) ?
+                                   SWM_S_COLOR_UNFOCUS_MAXIMIZED :
+                                   SWM_S_COLOR_UNFOCUS)].pixel);
                        } else {
                                unfocus_win(cfw);
                        }
@@ -3559,9 +3689,6 @@ focus_win(struct ws_win *win)
                                client_msg(win, a_takefocus, last_event_time);
                }
 
-               xcb_change_window_attributes(conn, win->id, XCB_CW_BORDER_PIXEL,
-                   &win->s->c[SWM_S_COLOR_FOCUS].pixel);
-
                if (ws->cur_layout->flags & SWM_L_MAPONFOCUS ||
                    ws->always_raise) {
                        /* If a parent exists, map it first. */
@@ -3570,20 +3697,25 @@ focus_win(struct ws_win *win)
                                map_window(parent);
 
                                /* Map siblings next. */
-                               TAILQ_FOREACH(w, &ws->winlist, entry)
+                               TAILQ_FOREACH_SAFE(w, &ws->stack, stack_entry,
+                                   tmpw)
                                        if (w != win && !ICONIC(w) &&
-                                           win->transient == parent->id)
+                                           w->transient == parent->id) {
+                                               raise_window(w);
                                                map_window(w);
+                                       }
                        }
 
                        /* Map focused window. */
                        raise_window(win);
                        map_window(win);
 
-                       /* Finally, map children of focus window. */
-                       TAILQ_FOREACH(w, &ws->winlist, entry)
-                               if (w->transient == win->id && !ICONIC(w))
+                       /* Stack any children of focus window. */
+                       TAILQ_FOREACH_SAFE(w, &ws->stack, stack_entry, tmpw)
+                               if (w->transient == win->id && !ICONIC(w)) {
+                                       raise_window(w);
                                        map_window(w);
+                               }
                } else if (tile_gap < 0 && !ABOVE(win)) {
                        /*
                         * Windows overlap in the layout.
@@ -3600,6 +3732,10 @@ focus_win(struct ws_win *win)
                    &win->id);
        }
 
+       if (cfw != win)
+               /* Update window border even if workspace is hidden. */
+               update_window_color(win);
+
 out:
        bar_draw();
 
@@ -3729,7 +3865,8 @@ switchws(struct swm_region *r, union arg *args)
        struct ws_win           *win;
        struct workspace        *new_ws, *old_ws;
        xcb_window_t            none = XCB_WINDOW_NONE;
-       int                     wsid = args->id, unmap_old = 0;
+       int                     wsid = args->id;
+       bool                    unmap_old = false;
 
        if (!(r && r->s))
                return;
@@ -3750,8 +3887,7 @@ switchws(struct swm_region *r, union arg *args)
                return;
 
        if ((win = old_ws->focus) != NULL) {
-               xcb_change_window_attributes(conn, win->id, XCB_CW_BORDER_PIXEL,
-                   &win->s->c[SWM_S_COLOR_UNFOCUS].pixel);
+               update_window_color(win);
 
                xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win->s->root,
                    ewmh[_NET_ACTIVE_WINDOW].atom, XCB_ATOM_WINDOW, 32, 1,
@@ -3762,7 +3898,7 @@ switchws(struct swm_region *r, union arg *args)
        if (other_r == NULL) {
                /* the other workspace is hidden, hide this one */
                old_ws->r = NULL;
-               unmap_old = 1;
+               unmap_old = true;
        } else {
                /* the other ws is visible in another region, exchange them */
                other_r->ws_prior = new_ws;
@@ -3808,6 +3944,7 @@ switchws(struct swm_region *r, union arg *args)
 
        ewmh_update_current_desktop();
 
+       center_pointer(r);
        focus_flush();
        new_ws->state = SWM_WS_STATE_MAPPED;
 
@@ -3819,8 +3956,7 @@ cyclews(struct swm_region *r, union arg *args)
 {
        union                   arg a;
        struct swm_screen       *s = r->s;
-       int                     cycle_all = 0;
-       int                     move = 0;
+       bool                    cycle_all = false, mv = false;
 
        DNPRINTF(SWM_D_WS, "cyclews: id: %d, screen[%d]:%dx%d+%d+%d, ws: %d\n",
            args->id, r->s->idx, WIDTH(r), HEIGHT(r), X(r), Y(r), r->ws->idx);
@@ -3830,19 +3966,19 @@ cyclews(struct swm_region *r, union arg *args)
        do {
                switch (args->id) {
                case SWM_ARG_ID_CYCLEWS_MOVE_UP:
-                       move = 1;
+                       mv = true;
                        /* FALLTHROUGH */
                case SWM_ARG_ID_CYCLEWS_UP_ALL:
-                       cycle_all = 1;
+                       cycle_all = true;
                        /* FALLTHROUGH */
                case SWM_ARG_ID_CYCLEWS_UP:
                        a.id = (a.id < workspace_limit - 1) ? a.id + 1 : 0;
                        break;
                case SWM_ARG_ID_CYCLEWS_MOVE_DOWN:
-                       move = 1;
+                       mv = true;
                        /* FALLTHROUGH */
                case SWM_ARG_ID_CYCLEWS_DOWN_ALL:
-                       cycle_all = 1;
+                       cycle_all = true;
                        /* FALLTHROUGH */
                case SWM_ARG_ID_CYCLEWS_DOWN:
                        a.id = (a.id > 0) ? a.id - 1 : workspace_limit - 1;
@@ -3857,7 +3993,7 @@ cyclews(struct swm_region *r, union arg *args)
                if (!cycle_visible && s->ws[a.id].r != NULL)
                        continue;
 
-               if (move)
+               if (mv)
                        send_to_ws(r, &a);
 
                switchws(r, &a);
@@ -3905,6 +4041,7 @@ focusrg(struct swm_region *r, union arg *args)
                return;
 
        focus_region(rr);
+       center_pointer(rr);
        focus_flush();
        DNPRINTF(SWM_D_FOCUS, "focusrg: done\n");
 }
@@ -3912,6 +4049,7 @@ focusrg(struct swm_region *r, union arg *args)
 void
 cyclerg(struct swm_region *r, union arg *args)
 {
+       union arg               a;
        struct swm_region       *rr = NULL;
        int                     i, num_screens;
 
@@ -3925,11 +4063,13 @@ cyclerg(struct swm_region *r, union arg *args)
 
        switch (args->id) {
        case SWM_ARG_ID_CYCLERG_UP:
+       case SWM_ARG_ID_CYCLERG_MOVE_UP:
                rr = TAILQ_NEXT(r, entry);
                if (rr == NULL)
                        rr = TAILQ_FIRST(&screens[i].rl);
                break;
        case SWM_ARG_ID_CYCLERG_DOWN:
+       case SWM_ARG_ID_CYCLERG_MOVE_DOWN:
                rr = TAILQ_PREV(r, swm_region_list, entry);
                if (rr == NULL)
                        rr = TAILQ_LAST(&screens[i].rl, swm_region_list);
@@ -3940,8 +4080,22 @@ cyclerg(struct swm_region *r, union arg *args)
        if (rr == NULL)
                return;
 
-       focus_region(rr);
-       focus_flush();
+       switch (args->id) {
+       case SWM_ARG_ID_CYCLERG_UP:
+       case SWM_ARG_ID_CYCLERG_DOWN:
+               focus_region(rr);
+               center_pointer(rr);
+               focus_flush();
+               break;
+       case SWM_ARG_ID_CYCLERG_MOVE_UP:
+       case SWM_ARG_ID_CYCLERG_MOVE_DOWN:
+               a.id = rr->ws->idx;
+               switchws(r, &a);
+               break;
+       default:
+               return;
+       };
+
        DNPRINTF(SWM_D_FOCUS, "cyclerg: done\n");
 }
 
@@ -4074,6 +4228,7 @@ swapwin(struct swm_region *r, union arg *args)
        ewmh_update_client_list();
 
        stack();
+       center_pointer(r);
        focus_flush();
 out:
        DNPRINTF(SWM_D_MOVE, "swapwin: done\n");
@@ -4227,22 +4382,25 @@ focus(struct swm_region *r, union arg *args)
        struct workspace        *ws = NULL;
        union arg               a;
        int                     i;
-       xcb_icccm_wm_hints_t    hints;
 
        if (!(r && r->ws))
                goto out;
 
-       DNPRINTF(SWM_D_FOCUS, "focus: id: %d\n", args->id);
-
        cur_focus = r->ws->focus;
        ws = r->ws;
        wl = &ws->winlist;
 
+       DNPRINTF(SWM_D_FOCUS, "focus: id: %d, cur_focus: %#x\n", args->id,
+           WINID(cur_focus));
+
        /* Make sure an uniconified window has focus, if one exists. */
        if (cur_focus == NULL) {
                cur_focus = TAILQ_FIRST(wl);
                while (cur_focus != NULL && ICONIC(cur_focus))
                        cur_focus = TAILQ_NEXT(cur_focus, entry);
+
+               DNPRINTF(SWM_D_FOCUS, "focus: new cur_focus: %#x\n",
+                   WINID(cur_focus));
        }
 
        switch (args->id) {
@@ -4257,8 +4415,11 @@ focus(struct swm_region *r, union arg *args)
                                winfocus = TAILQ_LAST(wl, ws_win_list);
                        if (winfocus == cur_focus)
                                break;
-               } while (winfocus != NULL &&
-                   (ICONIC(winfocus) || winfocus->id == cur_focus->transient));
+               } while (winfocus && (ICONIC(winfocus) ||
+                   winfocus->id == cur_focus->transient ||
+                   (cur_focus->transient != XCB_WINDOW_NONE &&
+                   winfocus->transient == cur_focus->transient) ||
+                   (winfocus->quirks & SWM_Q_NOFOCUSCYCLE)));
                break;
        case SWM_ARG_ID_FOCUSNEXT:
                if (cur_focus == NULL)
@@ -4271,8 +4432,11 @@ focus(struct swm_region *r, union arg *args)
                                winfocus = TAILQ_FIRST(wl);
                        if (winfocus == cur_focus)
                                break;
-               } while (winfocus != NULL &&
-                   (ICONIC(winfocus) || winfocus->id == cur_focus->transient));
+               } while (winfocus && (ICONIC(winfocus) ||
+                   winfocus->id == cur_focus->transient ||
+                   (cur_focus->transient != XCB_WINDOW_NONE &&
+                   winfocus->transient == cur_focus->transient) ||
+                   (winfocus->quirks & SWM_Q_NOFOCUSCYCLE)));
                break;
        case SWM_ARG_ID_FOCUSMAIN:
                if (cur_focus == NULL)
@@ -4292,27 +4456,26 @@ focus(struct swm_region *r, union arg *args)
                                head = TAILQ_FIRST(&r->s->ws[(ws->idx + i) %
                                    workspace_limit].winlist);
 
-                       while (head != NULL &&
-                           (head = TAILQ_NEXT(head, entry)) != NULL) {
+                       while (head) {
                                if (head == cur_focus) {
-                                       winfocus = cur_focus;
-                                       break;
-                               }
-                               if (xcb_icccm_get_wm_hints_reply(conn,
-                                   xcb_icccm_get_wm_hints(conn, head->id),
-                                   &hints, NULL) != 0 &&
-                                   xcb_icccm_wm_hints_get_urgency(&hints)) {
+                                       if (i > 0) {
+                                               winfocus = cur_focus;
+                                               break;
+                                       }
+                               } else if (get_urgent(head)) {
                                        winfocus = head;
                                        break;
                                }
+
+                               head = TAILQ_NEXT(head, entry);
                        }
 
-                       if (winfocus != NULL)
+                       if (winfocus)
                                break;
                }
 
                /* Switch ws if new focus is on a different ws. */
-               if (winfocus != NULL && winfocus->ws != ws) {
+               if (winfocus && winfocus->ws != ws) {
                        a.id = winfocus->ws->idx;
                        switchws(r, &a);
                }
@@ -4325,6 +4488,7 @@ focus(struct swm_region *r, union arg *args)
                stack();
 
        focus_win(get_focus_magic(winfocus));
+       center_pointer(r);
        focus_flush();
 
 out:
@@ -4352,6 +4516,7 @@ cycle_layout(struct swm_region *r, union arg *args)
 
        focus_win(get_region_focus(r));
 
+       center_pointer(r);
        focus_flush();
 }
 
@@ -4373,6 +4538,7 @@ stack_config(struct swm_region *r, union arg *args)
                stack();
        bar_draw();
 
+       center_pointer(r);
        focus_flush();
 }
 
@@ -4452,7 +4618,7 @@ store_float_geom(struct ws_win *win)
        win->g_float = win->g;
        win->g_float.x -= X(win->ws->r);
        win->g_float.y -= Y(win->ws->r);
-       win->g_floatvalid = 1;
+       win->g_floatvalid = true;
        DNPRINTF(SWM_D_MISC, "store_float_geom: win %#x, g: (%d,%d)"
            " %d x %d, g_float: (%d,%d) %d x %d\n", win->id, X(win), Y(win),
            WIDTH(win), HEIGHT(win), win->g_float.x, win->g_float.y,
@@ -4494,13 +4660,15 @@ update_floater(struct ws_win *win)
 
        DNPRINTF(SWM_D_MISC, "update_floater: win %#x\n", win->id);
 
+       win->bordered = true;
+
        if (FULLSCREEN(win)) {
                /* _NET_WM_FULLSCREEN: fullscreen without border. */
                if (!win->g_floatvalid)
                        store_float_geom(win);
 
                win->g = r->g;
-               win->bordered = 0;
+               win->bordered = false;
        } else if (MAXIMIZED(win)) {
                /* Maximize: like a single stacked window. */
                if (!win->g_floatvalid)
@@ -4508,15 +4676,12 @@ update_floater(struct ws_win *win)
 
                win->g = r->g;
 
-               if (bar_enabled && ws->bar_enabled) {
-                       win->bordered = 1;
+               if (bar_enabled && ws->bar_enabled && !maximize_hide_bar) {
                        if (!bar_at_bottom)
                                Y(win) += bar_height;
                        HEIGHT(win) -= bar_height;
                } else if (disable_border) {
-                       win->bordered = 0;
-               } else {
-                       win->bordered = 1;
+                       win->bordered = false;
                }
 
                if (win->bordered) {
@@ -4532,7 +4697,7 @@ update_floater(struct ws_win *win)
                if ((win->quirks & SWM_Q_FULLSCREEN) &&
                    WIDTH(win) >= WIDTH(r) && HEIGHT(win) >= HEIGHT(r)) {
                        /* Remove border for FULLSCREEN quirk. */
-                       win->bordered = 0;
+                       win->bordered = false;
                } else if (!MANUAL(win)) {
                        if (TRANS(win) && (win->quirks & SWM_Q_TRANSSZ)) {
                                /* Adjust size on TRANSSZ quirk. */
@@ -4596,7 +4761,7 @@ adjust_font(struct ws_win *win)
        tmp = (g)->h; (g)->h = (g)->w; (g)->w = tmp;    \
 } while (0)
 void
-stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip)
+stack_master(struct workspace *ws, struct swm_geometry *g, int rot, bool flip)
 {
        struct swm_geometry     win_g, r_g = *g;
        struct ws_win           *win;
@@ -4604,14 +4769,14 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip)
        int                     w_inc = 1, h_inc, w_base = 1, h_base;
        int                     hrh, extra = 0, h_slice, last_h = 0;
        int                     split, colno, winno, mwin, msize, mscale;
-       int                     remain, missing, v_slice, reconfigure = 0;
-       int                     bordered = 1;
+       int                     remain, missing, v_slice;
+       bool                    bordered = true, reconfigure = false;
 
        DNPRINTF(SWM_D_STACK, "stack_master: workspace: %d, rot: %s, "
            "flip: %s\n", ws->idx, YESNO(rot), YESNO(flip));
 
        /* Prepare tiling variables, if needed. */
-       if ((winno = count_win(ws, 0)) > 0) {
+       if ((winno = count_win(ws, false)) > 0) {
                /* Find first tiled window. */
                TAILQ_FOREACH(win, &ws->winlist, entry)
                        if (!FLOATING(win) && !ICONIC(win))
@@ -4737,18 +4902,18 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip)
                        win_g.y += last_h + 2 * border_width + tile_gap;
 
                if (disable_border && !(bar_enabled && ws->bar_enabled) &&
-                   winno == 1){
-                       bordered = 0;
+                   winno == 1) {
+                       bordered = false;
                        win_g.w += 2 * border_width;
                        win_g.h += 2 * border_width;
                } else {
-                       bordered = 1;
+                       bordered = true;
                }
 
                if (rot) {
                        if (X(win) != win_g.y || Y(win) != win_g.x ||
                            WIDTH(win) != win_g.h || HEIGHT(win) != win_g.w) {
-                               reconfigure = 1;
+                               reconfigure = true;
                                X(win) = win_g.y;
                                Y(win) = win_g.x;
                                WIDTH(win) = win_g.h;
@@ -4757,7 +4922,7 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip)
                } else {
                        if (X(win) != win_g.x || Y(win) != win_g.y ||
                            WIDTH(win) != win_g.w || HEIGHT(win) != win_g.h) {
-                               reconfigure = 1;
+                               reconfigure = true;
                                X(win) = win_g.x;
                                Y(win) = win_g.y;
                                WIDTH(win) = win_g.w;
@@ -4766,7 +4931,7 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip)
                }
 
                if (bordered != win->bordered) {
-                       reconfigure = 1;
+                       reconfigure = true;
                        win->bordered = bordered;
                }
 
@@ -4806,6 +4971,9 @@ vertical_config(struct workspace *ws, int id)
                ws->l_state.vertical_mwin = 1;
                ws->l_state.vertical_stacks = 1;
                break;
+       case SWM_ARG_ID_STACKBALANCE:
+               ws->l_state.vertical_msize = SWM_V_SLICE / (ws->l_state.vertical_stacks + 1);
+               break;
        case SWM_ARG_ID_MASTERSHRINK:
                if (ws->l_state.vertical_msize > 1)
                        ws->l_state.vertical_msize--;
@@ -4856,6 +5024,9 @@ horizontal_config(struct workspace *ws, int id)
                ws->l_state.horizontal_msize = SWM_H_SLICE / 2;
                ws->l_state.horizontal_stacks = 1;
                break;
+       case SWM_ARG_ID_STACKBALANCE:
+               ws->l_state.horizontal_msize = SWM_H_SLICE / (ws->l_state.horizontal_stacks + 1);
+               break;
        case SWM_ARG_ID_MASTERSHRINK:
                if (ws->l_state.horizontal_msize > 1)
                        ws->l_state.horizontal_msize--;
@@ -4899,7 +5070,7 @@ void
 max_stack(struct workspace *ws, struct swm_geometry *g)
 {
        struct swm_geometry     gg = *g;
-       struct ws_win           *w, *win = NULL, *parent = NULL;
+       struct ws_win           *w, *win = NULL, *parent = NULL, *tmpw;
        int                     winno;
 
        DNPRINTF(SWM_D_STACK, "max_stack: workspace: %d\n", ws->idx);
@@ -4907,8 +5078,8 @@ max_stack(struct workspace *ws, struct swm_geometry *g)
        if (ws == NULL)
                return;
 
-       winno = count_win(ws, 0);
-       if (winno == 0 && count_win(ws, 1) == 0)
+       winno = count_win(ws, false);
+       if (winno == 0 && count_win(ws, true) == 0)
                return;
 
        /* Figure out which top level window should be visible. */
@@ -4950,30 +5121,33 @@ max_stack(struct workspace *ws, struct swm_geometry *g)
                if (X(w) != gg.x || Y(w) != gg.y || WIDTH(w) != gg.w ||
                    HEIGHT(w) != gg.h) {
                        w->g = gg;
-                       if (bar_enabled && ws->bar_enabled){
-                               w->bordered = 1;
-                       } else {
-                               w->bordered = 0;
+
+                       if (disable_border && !(bar_enabled && ws->bar_enabled)) {
+                               w->bordered = false;
                                WIDTH(w) += 2 * border_width;
                                HEIGHT(w) += 2 * border_width;
+                       } else {
+                               w->bordered = true;
                        }
 
                        update_window(w);
                }
        }
 
-       if (TRANS(win)) {
-               parent = find_window(win->transient);
+       /* If transient, stack parent and its children. */
+       if (TRANS(win) && (parent = find_window(win->transient))) {
                raise_window(parent);
 
-               TAILQ_FOREACH(w, &ws->stack, stack_entry)
+               TAILQ_FOREACH_SAFE(w, &ws->stack, stack_entry, tmpw)
                        if (w->transient == parent->id)
                                raise_window(w);
        }
 
+       /* Make sure focus window is on top. */
        raise_window(win);
 
-       TAILQ_FOREACH(w, &ws->stack, stack_entry)
+       /* Stack any children of focus window. */
+       TAILQ_FOREACH_SAFE(w, &ws->stack, stack_entry, tmpw)
                if (w->transient == win->id)
                        raise_window(w);
 
@@ -5046,12 +5220,16 @@ send_to_ws(struct swm_region *r, union arg *args)
        if (win->ws->idx == wsid)
                return;
 
-       win_to_ws(win, wsid, 1);
+       win_to_ws(win, wsid, true);
 
-       /* Set window to be focus on target ws. */
+       /* Set new focus on target ws. */
        if (focus_mode != SWM_FOCUS_FOLLOW) {
+               win->ws->focus_prev = win->ws->focus;
                win->ws->focus = win;
                win->ws->focus_pending = NULL;
+
+               if (win->ws->focus_prev)
+                       update_window_color(win->ws->focus_prev);
        }
 
        DNPRINTF(SWM_D_STACK, "send_to_ws: focus_pending: %#x, focus: %#x, "
@@ -5063,7 +5241,7 @@ send_to_ws(struct swm_region *r, union arg *args)
        ewmh_apply_flags(win, win->ewmh_flags & ~EWMH_F_MAXIMIZED);
        ewmh_update_wm_state(win);
 
-       /* Restack and set new focus. */
+       /* Restack and set new focus on current ws. */
        if (FLOATING(win))
                load_float_geom(win);
 
@@ -5079,11 +5257,12 @@ send_to_ws(struct swm_region *r, union arg *args)
                }
        }
 
+       center_pointer(r);
        focus_flush();
 }
 
 void
-win_to_ws(struct ws_win *win, int wsid, int unfocus)
+win_to_ws(struct ws_win *win, int wsid, bool unfocus)
 {
        struct ws_win           *parent;
        struct workspace        *ws, *nws, *pws;
@@ -5191,7 +5370,7 @@ pressbutton(struct swm_region *r, union arg *args)
 void
 raise_toggle(struct swm_region *r, union arg *args)
 {
-       /* suppress unused warning since var is needed */
+       /* Suppress warning. */
        (void)args;
 
        if (r == NULL || r->ws == NULL)
@@ -5202,9 +5381,8 @@ raise_toggle(struct swm_region *r, union arg *args)
 
        r->ws->always_raise = !r->ws->always_raise;
 
-       /* bring floaters back to top */
-       if (!r->ws->always_raise)
-               stack();
+       /* Update focused win stacking order based on new always_raise value. */
+       raise_window(r->ws->focus);
 
        focus_flush();
 }
@@ -5213,7 +5391,8 @@ void
 iconify(struct swm_region *r, union arg *args)
 {
        struct ws_win           *w;
-       /* suppress unused warning since var is needed */
+
+       /* Suppress warning. */
        (void)args;
 
        if ((w = r->ws->focus) == NULL)
@@ -5380,7 +5559,8 @@ search_win(struct swm_region *r, union arg *args)
        struct ws_win           *win = NULL;
        struct search_window    *sw = NULL;
        xcb_window_t            w;
-       uint32_t                wa[2];
+       uint32_t                wa[3];
+       xcb_screen_t            *screen;
        int                     i, width, height;
        char                    s[8];
        FILE                    *lfile;
@@ -5401,6 +5581,9 @@ search_win(struct swm_region *r, union arg *args)
        if ((lfile = fdopen(select_list_pipe[1], "w")) == NULL)
                return;
 
+       if ((screen = get_screen(r->s->idx)) == NULL)
+               errx(1, "ERROR: can't get screen %d.", r->s->idx);
+
        TAILQ_INIT(&search_wl);
 
        i = 1;
@@ -5424,6 +5607,7 @@ search_win(struct swm_region *r, union arg *args)
                w = xcb_generate_id(conn);
                wa[0] = r->s->c[SWM_S_COLOR_FOCUS].pixel;
                wa[1] = r->s->c[SWM_S_COLOR_UNFOCUS].pixel;
+               wa[2] = screen->default_colormap;
 
                if (bar_font_legacy) {
                        XmbTextExtents(bar_fs, s, len, &l_ibox, &l_lbox);
@@ -5436,10 +5620,10 @@ search_win(struct swm_region *r, union arg *args)
                        height = bar_font->height + 4;
                }
 
-               xcb_create_window(conn, XCB_COPY_FROM_PARENT, w, win->id, 0, 0,
+               xcb_create_window(conn, screen->root_depth, w, win->id, 0, 0,
                    width, height, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT,
-                   XCB_COPY_FROM_PARENT, XCB_CW_BACK_PIXEL |
-                   XCB_CW_BORDER_PIXEL, wa);
+                   screen->root_visual, XCB_CW_BACK_PIXEL |
+                   XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP, wa);
 
                xcb_map_window(conn, w);
 
@@ -5464,7 +5648,7 @@ search_win(struct swm_region *r, union arg *args)
                            DefaultVisual(display, r->s->idx),
                            DefaultColormap(display, r->s->idx));
 
-                       XftDrawStringUtf8(draw, &bar_font_color, bar_font, 2,
+                       XftDrawStringUtf8(draw, &search_font_color, bar_font, 2,
                            (HEIGHT(r->bar) + bar_font->height) / 2 -
                            bar_font->descent, (FcChar8 *)s, len);
 
@@ -5555,7 +5739,7 @@ ewmh_update_desktop_names(void)
                        ++len;
                }
 
-               if((name_list = calloc(sizeof(char *), len)) == NULL)
+               if((name_list = calloc(len, sizeof(char))) == NULL)
                        err(1, "update_desktop_names: calloc: failed to "
                            "allocate memory.");
 
@@ -5638,7 +5822,7 @@ ewmh_update_client_list(void)
                if (count == 0)
                        continue;
 
-               wins = calloc(sizeof(xcb_window_t), count);
+               wins = calloc(count, sizeof(xcb_window_t));
                if (wins == NULL)
                        err(1, "ewmh_update_client_list: calloc: failed to "
                            "allocate memory.");
@@ -5673,7 +5857,7 @@ ewmh_update_desktops(void)
        int                     num_screens, i, j;
        uint32_t                *vals;
 
-       vals = calloc(sizeof(uint32_t), workspace_limit * 2);
+       vals = calloc(workspace_limit * 2, sizeof(uint32_t));
        if (vals == NULL)
                err(1, "ewmh_update_desktops: calloc: failed to allocate "
                    "memory.");
@@ -5889,6 +6073,7 @@ maximize_toggle(struct swm_region *r, union arg *args)
        if (w == w->ws->focus)
                focus_win(w);
 
+       center_pointer(r);
        focus_flush();
        DNPRINTF(SWM_D_MISC, "maximize_toggle: done\n");
 }
@@ -5920,6 +6105,7 @@ floating_toggle(struct swm_region *r, union arg *args)
        if (w == w->ws->focus)
                focus_win(w);
 
+       center_pointer(r);
        focus_flush();
        DNPRINTF(SWM_D_MISC, "floating_toggle: done\n");
 }
@@ -6011,6 +6197,24 @@ constrain_window(struct ws_win *win, struct swm_geometry *b, int *opts)
        }
 }
 
+void
+update_window_color(struct ws_win *win)
+{
+       uint32_t        *pixel;
+
+       if (WS_FOCUSED(win->ws) && win->ws->focus == win)
+               pixel = MAXIMIZED(win) ?
+                   &win->s->c[SWM_S_COLOR_FOCUS_MAXIMIZED].pixel :
+                   &win->s->c[SWM_S_COLOR_FOCUS].pixel;
+       else
+               pixel = MAXIMIZED(win) ?
+                   &win->s->c[SWM_S_COLOR_UNFOCUS_MAXIMIZED].pixel :
+                   &win->s->c[SWM_S_COLOR_UNFOCUS].pixel;
+
+       xcb_change_window_attributes(conn, win->id,
+           XCB_CW_BORDER_PIXEL, pixel);
+}
+
 void
 update_window(struct ws_win *win)
 {
@@ -6042,12 +6246,13 @@ resize(struct ws_win *win, union arg *args)
        struct swm_region       *r = NULL;
        struct swm_geometry     g;
        int                     resize_stp = 0;
-       int                     top = 0, left = 0, resizing;
+       int                     top = 0, left = 0;
        int                     dx, dy;
        xcb_cursor_t                    cursor;
        xcb_query_pointer_reply_t       *xpr = NULL;
        xcb_generic_event_t             *evt;
        xcb_motion_notify_event_t       *mne;
+       bool                    resizing;
 
        if (win == NULL)
                return;
@@ -6143,12 +6348,12 @@ resize(struct ws_win *win, union arg *args)
            XCB_CURRENT_TIME),
 
        xcb_flush(conn);
-       resizing = 1;
+       resizing = true;
        while (resizing && (evt = xcb_wait_for_event(conn))) {
                switch (XCB_EVENT_RESPONSE_TYPE(evt)) {
                case XCB_BUTTON_RELEASE:
                        DNPRINTF(SWM_D_EVENT, "resize: BUTTON_RELEASE\n");
-                       resizing = 0;
+                       resizing = false;
                        break;
                case XCB_MOTION_NOTIFY:
                        mne = (xcb_motion_notify_event_t *)evt;
@@ -6249,6 +6454,7 @@ resize_step(struct swm_region *r, union arg *args)
                return;
 
        resize(win, args);
+       center_pointer(r);
        focus_flush();
 }
 
@@ -6267,7 +6473,7 @@ regionize(struct ws_win *win, int x, int y)
                if (clear_maximized(r->ws) > 0)
                        stack();
 
-               win_to_ws(win, r->ws->idx, 0);
+               win_to_ws(win, r->ws->idx, false);
 
                /* Set focus on new ws. */
                unfocus_win(r->ws->focus);
@@ -6285,10 +6491,11 @@ move(struct ws_win *win, union arg *args)
 {
        struct swm_region               *r;
        xcb_timestamp_t                 timestamp = 0;
-       int                             move_stp = 0, moving, restack = 0;
+       int                             move_stp = 0;
        xcb_query_pointer_reply_t       *qpr = NULL;
        xcb_generic_event_t             *evt;
        xcb_motion_notify_event_t       *mne;
+       bool                            moving, restack = false;
 
        if (win == NULL)
                return;
@@ -6308,7 +6515,7 @@ move(struct ws_win *win, union arg *args)
 
        if (!(ABOVE(win) || TRANS(win)) || MAXIMIZED(win)) {
                store_float_geom(win);
-               restack = 1;
+               restack = true;
        }
 
        ewmh_apply_flags(win, (win->ewmh_flags | SWM_F_MANUAL | EWMH_F_ABOVE) &
@@ -6372,12 +6579,12 @@ move(struct ws_win *win, union arg *args)
            SWM_CW_SOFTBOUNDARY);
        update_window(win);
        xcb_flush(conn);
-       moving = 1;
+       moving = true;
        while (moving && (evt = xcb_wait_for_event(conn))) {
                switch (XCB_EVENT_RESPONSE_TYPE(evt)) {
                case XCB_BUTTON_RELEASE:
                        DNPRINTF(SWM_D_EVENT, "move: BUTTON_RELEASE\n");
-                       moving = 0;
+                       moving = false;
                        break;
                case XCB_MOTION_NOTIFY:
                        mne = (xcb_motion_notify_event_t *)evt;
@@ -6447,6 +6654,7 @@ move_step(struct swm_region *r, union arg *args)
                return;
 
        move(win, args);
+       center_pointer(r);
        focus_flush();
 }
 
@@ -6525,6 +6733,8 @@ struct keyfunc {
        { "rg_9",               focusrg,        {.id = 8} },
        { "rg_next",            cyclerg,        {.id = SWM_ARG_ID_CYCLERG_UP} },
        { "rg_prev",            cyclerg,        {.id = SWM_ARG_ID_CYCLERG_DOWN} },
+       { "rg_move_next",       cyclerg,        {.id = SWM_ARG_ID_CYCLERG_MOVE_UP} },
+       { "rg_move_prev",       cyclerg,        {.id = SWM_ARG_ID_CYCLERG_MOVE_DOWN} },
        { "screen_next",        cyclerg,        {.id = SWM_ARG_ID_CYCLERG_UP} },
        { "screen_prev",        cyclerg,        {.id = SWM_ARG_ID_CYCLERG_DOWN} },
        { "search_win",         search_win,     {0} },
@@ -6533,6 +6743,7 @@ struct keyfunc {
        { "stack_inc",          stack_config,   {.id = SWM_ARG_ID_STACKINC} },
        { "stack_dec",          stack_config,   {.id = SWM_ARG_ID_STACKDEC} },
        { "stack_reset",        stack_config,   {.id = SWM_ARG_ID_STACKRESET} },
+       { "stack_balance",      stack_config,   {.id = SWM_ARG_ID_STACKBALANCE} },
        { "swap_main",          swapwin,        {.id = SWM_ARG_ID_SWAPMAIN} },
        { "swap_next",          swapwin,        {.id = SWM_ARG_ID_SWAPNEXT} },
        { "swap_prev",          swapwin,        {.id = SWM_ARG_ID_SWAPPREV} },
@@ -6628,6 +6839,31 @@ update_modkey(unsigned int mod)
                        buttons[i].mask = mod;
 }
 
+unsigned char
+update_mousebutton(unsigned char type, unsigned int but)
+{
+       int                     i;
+
+       switch (type) {
+               case 0:
+                       mouse_button_move = but;
+                       break;
+               case 1:
+                       mouse_button_resize = but;
+                       break;
+       }
+
+       for (i = 0; i < LENGTH(buttons); i++) {
+               if (buttons[i].func == move)
+                       buttons[i].button = mouse_button_move;
+
+               if (buttons[i].func == resize)
+                       buttons[i].button = mouse_button_resize;
+       }
+
+       return(1);
+}
+
 int
 spawn_expand(struct swm_region *r, union arg *args, const char *spawn_name,
     char ***ret_args)
@@ -6683,11 +6919,21 @@ spawn_expand(struct swm_region *r, union arg *args, const char *spawn_name,
                            strdup(r->s->c[SWM_S_COLOR_FOCUS].name))
                            == NULL)
                                err(1, "spawn_custom color focus");
+               } else if (strcasecmp(ap, "$color_focus_maximized") == 0) {
+                       if ((real_args[c] =
+                           strdup(r->s->c[SWM_S_COLOR_FOCUS_MAXIMIZED].name))
+                           == NULL)
+                               err(1, "spawn_custom color focus maximized");
                } else if (strcasecmp(ap, "$color_unfocus") == 0) {
                        if ((real_args[c] =
                            strdup(r->s->c[SWM_S_COLOR_UNFOCUS].name))
                            == NULL)
                                err(1, "spawn_custom color unfocus");
+               } else if (strcasecmp(ap, "$color_unfocus_maximized") == 0) {
+                       if ((real_args[c] =
+                           strdup(r->s->c[SWM_S_COLOR_UNFOCUS_MAXIMIZED].name))
+                           == NULL)
+                               err(1, "spawn_custom color unfocus maximized");
                } else if (strcasecmp(ap, "$region_index") == 0) {
                        if (asprintf(&real_args[c], "%d",
                            get_region_index(r) + 1) < 1)
@@ -6731,7 +6977,7 @@ spawn_custom(struct swm_region *r, union arg *args, const char *spawn_name)
                return;
        a.argv = real_args;
        if (fork() == 0)
-               spawn(r->ws->idx, &a, 1);
+               spawn(r->ws->idx, &a, true);
 
        for (i = 0; i < spawn_argc; i++)
                free(real_args[i]);
@@ -6768,7 +7014,7 @@ spawn_select(struct swm_region *r, union arg *args, const char *spawn_name,
                        err(1, "dup2");
                close(select_list_pipe[1]);
                close(select_resp_pipe[0]);
-               spawn(r->ws->idx, &a, 0);
+               spawn(r->ws->idx, &a, false);
                break;
        default: /* parent */
                close(select_list_pipe[0]);
@@ -6784,8 +7030,8 @@ spawn_select(struct swm_region *r, union arg *args, const char *spawn_name,
 /* Argument tokenizer. */
 char *
 argsep(char **sp) {
-       int                     single_quoted = 0, double_quoted = 0;
        char                    *arg, *cp, *next;
+       bool                    single_quoted = false, double_quoted = false;
 
        if (*sp == NULL)
                return NULL;
@@ -6831,7 +7077,7 @@ void
 spawn_insert(const char *name, const char *args, int flags)
 {
        struct spawn_prog       *sp;
-       char                    *arg, *dup, *ptr;
+       char                    *arg, *cp, *ptr;
 
        DNPRINTF(SWM_D_SPAWN, "spawn_insert: %s[%s]\n", name, args);
 
@@ -6844,7 +7090,7 @@ spawn_insert(const char *name, const char *args, int flags)
                err(1, "spawn_insert: strdup");
 
        /* Convert the arguments to an argument list. */
-       if ((ptr = dup = strdup(args)) == NULL)
+       if ((ptr = cp = strdup(args)) == NULL)
                err(1, "spawn_insert: strdup");
        while ((arg = argsep(&ptr)) != NULL) {
                /* Null argument; skip it. */
@@ -6858,7 +7104,7 @@ spawn_insert(const char *name, const char *args, int flags)
                if ((sp->argv[sp->argc - 1] = strdup(arg)) == NULL)
                        err(1, "spawn_insert: strdup");
        }
-       free(dup);
+       free(cp);
 
        sp->flags = flags;
 
@@ -7048,6 +7294,8 @@ parsekeys(const char *keystr, unsigned int currmod, unsigned int *mod, KeySym *k
                        *mod |= XCB_MOD_MASK_3;
                else if (strncmp(name, "Mod4", SWM_MODNAME_SIZE) == 0)
                        *mod |= XCB_MOD_MASK_4;
+               else if (strncmp(name, "Mod5", SWM_MODNAME_SIZE) == 0)
+                       *mod |= XCB_MOD_MASK_5;
                else if (strncasecmp(name, "SHIFT", SWM_MODNAME_SIZE) == 0)
                        *mod |= XCB_MOD_MASK_SHIFT;
                else if (strncasecmp(name, "CONTROL", SWM_MODNAME_SIZE) == 0)
@@ -7286,6 +7534,8 @@ setup_keys(void)
        setkeybinding(MODKEY,           XK_KP_Up,       KF_RG_8,        NULL);
        setkeybinding(MODKEY,           XK_KP_Prior,    KF_RG_9,        NULL);
        setkeybinding(MODKEY_SHIFT,     XK_Right,       KF_RG_NEXT,     NULL);
+       setkeybinding(MODKEY,           XK_c,           KF_RG_MOVE_NEXT,NULL);
+       setkeybinding(MODKEY_SHIFT,     XK_c,           KF_RG_MOVE_PREV,NULL);
        setkeybinding(MODKEY_SHIFT,     XK_Left,        KF_RG_PREV,     NULL);
        setkeybinding(MODKEY,           XK_f,           KF_SEARCH_WIN,  NULL);
        setkeybinding(MODKEY,           XK_slash,       KF_SEARCH_WORKSPACE,NULL);
@@ -7298,6 +7548,7 @@ setup_keys(void)
        setkeybinding(MODKEY_SHIFT,     XK_comma,       KF_STACK_INC,   NULL);
        setkeybinding(MODKEY_SHIFT,     XK_period,      KF_STACK_DEC,   NULL);
        setkeybinding(MODKEY_SHIFT,     XK_space,       KF_STACK_RESET, NULL);
+       setkeybinding(MODKEY_SHIFT,     XK_h,           KF_STACK_BALANCE, NULL);
        setkeybinding(MODKEY,           XK_Return,      KF_SWAP_MAIN,   NULL);
        setkeybinding(MODKEY_SHIFT,     XK_j,           KF_SWAP_NEXT,   NULL);
        setkeybinding(MODKEY_SHIFT,     XK_k,           KF_SWAP_PREV,   NULL);
@@ -7492,12 +7743,16 @@ const char *quirkname[] = {
        "FOCUSPREV",
        "NOFOCUSONMAP",
        "FOCUSONMAP_SINGLE",
+       "OBEYAPPFOCUSREQ",
+       "IGNOREPID",
+       "IGNORESPAWNWS",
+       "NOFOCUSCYCLE",
 };
 
-/* SWM_Q_WS: retain '|' for back compat for now (2009-08-11) */
-#define SWM_Q_WS               "\n|+ \t"
+/* SWM_Q_DELIM: retain '|' for back compat for now (2009-08-11) */
+#define SWM_Q_DELIM            "\n|+ \t"
 int
-parsequirks(const char *qstr, unsigned long *quirk)
+parsequirks(const char *qstr, uint32_t *quirk, int *ws)
 {
        char                    *str, *cp, *name;
        int                     i;
@@ -7510,9 +7765,16 @@ parsequirks(const char *qstr, unsigned long *quirk)
 
        cp = str;
        *quirk = 0;
-       while ((name = strsep(&cp, SWM_Q_WS)) != NULL) {
+       while ((name = strsep(&cp, SWM_Q_DELIM)) != NULL) {
                if (cp)
-                       cp += (long)strspn(cp, SWM_Q_WS);
+                       cp += (long)strspn(cp, SWM_Q_DELIM);
+
+               if (sscanf(name, "WS[%d]", ws) == 1) {
+                       if (*ws > 0)
+                               *ws -= 1;
+                       continue;
+               }
+
                for (i = 0; i < LENGTH(quirkname); i++) {
                        if (strncasecmp(name, quirkname[i],
                            SWM_QUIRK_LEN) == 0) {
@@ -7541,14 +7803,14 @@ parsequirks(const char *qstr, unsigned long *quirk)
 
 void
 quirk_insert(const char *class, const char *instance, const char *name,
-    unsigned long quirk)
+    uint32_t quirk, int ws)
 {
        struct quirk            *qp;
-       int                     failed = 0;
        char                    *str;
+       bool                    failed = false;
 
        DNPRINTF(SWM_D_QUIRK, "quirk_insert: class: %s, instance: %s, name: %s,"
-           " value: %lu\n", class, instance, name, quirk);
+           " value: %u, ws: %d\n", class, instance, name, quirk, ws);
 
        if ((qp = malloc(sizeof *qp)) == NULL)
                err(1, "quirk_insert: malloc");
@@ -7565,7 +7827,7 @@ quirk_insert(const char *class, const char *instance, const char *name,
        if (regcomp(&qp->regex_class, str, REG_EXTENDED | REG_NOSUB)) {
                add_startup_exception("regex failed to compile quirk 'class' "
                    "field: %s", class);
-               failed = 1;
+               failed = true;
        }
        DNPRINTF(SWM_D_QUIRK, "quirk_insert: compiled: %s\n", str);
        free(str);
@@ -7575,7 +7837,7 @@ quirk_insert(const char *class, const char *instance, const char *name,
        if (regcomp(&qp->regex_instance, str, REG_EXTENDED | REG_NOSUB)) {
                add_startup_exception("regex failed to compile quirk 'instance'"
                    " field: %s", instance);
-               failed = 1;
+               failed = true;
        }
        DNPRINTF(SWM_D_QUIRK, "quirk_insert: compiled: %s\n", str);
        free(str);
@@ -7585,7 +7847,7 @@ quirk_insert(const char *class, const char *instance, const char *name,
        if (regcomp(&qp->regex_name, str, REG_EXTENDED | REG_NOSUB)) {
                add_startup_exception("regex failed to compile quirk 'name' "
                    "field: %s", name);
-               failed = 1;
+               failed = true;
        }
        DNPRINTF(SWM_D_QUIRK, "quirk_insert: compiled: %s\n", str);
        free(str);
@@ -7595,6 +7857,7 @@ quirk_insert(const char *class, const char *instance, const char *name,
                quirk_free(qp);
        } else {
                qp->quirk = quirk;
+               qp->ws = ws;
                TAILQ_INSERT_TAIL(&quirks, qp, entry);
        }
        DNPRINTF(SWM_D_QUIRK, "quirk_insert: leave\n");
@@ -7603,7 +7866,7 @@ quirk_insert(const char *class, const char *instance, const char *name,
 void
 quirk_remove(struct quirk *qp)
 {
-       DNPRINTF(SWM_D_QUIRK, "quirk_remove: %s:%s [%lu]\n", qp->class,
+       DNPRINTF(SWM_D_QUIRK, "quirk_remove: %s:%s [%u]\n", qp->class,
            qp->name, qp->quirk);
 
        TAILQ_REMOVE(&quirks, qp, entry);
@@ -7626,43 +7889,44 @@ quirk_free(struct quirk *qp)
 
 void
 quirk_replace(struct quirk *qp, const char *class, const char *instance,
-    const char *name, unsigned long quirk)
+    const char *name, uint32_t quirk, int ws)
 {
-       DNPRINTF(SWM_D_QUIRK, "quirk_replace: %s:%s:%s [%lu]\n", qp->class,
-           qp->instance, qp->name, qp->quirk);
+       DNPRINTF(SWM_D_QUIRK, "quirk_replace: %s:%s:%s [%u], ws: %d\n", qp->class,
+           qp->instance, qp->name, qp->quirk, qp->ws);
 
        quirk_remove(qp);
-       quirk_insert(class, instance, name, quirk);
+       quirk_insert(class, instance, name, quirk, ws);
 
        DNPRINTF(SWM_D_QUIRK, "quirk_replace: leave\n");
 }
 
 void
 setquirk(const char *class, const char *instance, const char *name,
-    unsigned long quirk)
+    uint32_t quirk, int ws)
 {
        struct quirk            *qp;
 
-       DNPRINTF(SWM_D_QUIRK, "setquirk: enter %s:%s:%s [%lu]\n", class,
-           instance, name, quirk);
+       DNPRINTF(SWM_D_QUIRK, "setquirk: enter %s:%s:%s [%u], ws: %d\n", class,
+           instance, name, quirk, ws);
 
        /* Remove/replace existing quirk. */
        TAILQ_FOREACH(qp, &quirks, entry) {
                if (strcmp(qp->class, class) == 0 &&
                    strcmp(qp->instance, instance) == 0 &&
                    strcmp(qp->name, name) == 0) {
-                       if (quirk == 0)
+                       if (quirk == 0 && ws == -1)
                                quirk_remove(qp);
                        else
-                               quirk_replace(qp, class, instance, name, quirk);
+                               quirk_replace(qp, class, instance, name, quirk,
+                                   ws);
                        DNPRINTF(SWM_D_QUIRK, "setquirk: leave\n");
                        return;
                }
        }
 
-       /* Only insert if quirk is not NONE. */
-       if (quirk)
-               quirk_insert(class, instance, name, quirk);
+       /* Only insert if quirk is not NONE or forced ws is set. */
+       if (quirk || ws != -1)
+               quirk_insert(class, instance, name, quirk, ws);
 
        DNPRINTF(SWM_D_QUIRK, "setquirk: leave\n");
 }
@@ -7688,8 +7952,8 @@ setconfquirk(const char *selector, const char *value, int flags)
 {
        char                    *str, *cp, *class;
        char                    *instance = NULL, *name = NULL;
-       int                     retval, count = 0;
-       unsigned long           qrks;
+       int                     retval, count = 0, ws = -1;
+       uint32_t                qrks;
 
        /* suppress unused warning since var is needed */
        (void)flags;
@@ -7732,8 +7996,8 @@ setconfquirk(const char *selector, const char *value, int flags)
        DNPRINTF(SWM_D_CONF, "setconfquirk: class: %s, instance: %s, "
            "name: %s\n", class, instance, name);
 
-       if ((retval = parsequirks(value, &qrks)) == 0)
-               setquirk(class, instance, name, qrks);
+       if ((retval = parsequirks(value, &qrks, &ws)) == 0)
+               setquirk(class, instance, name, qrks, ws);
 
        free(str);
        return (retval);
@@ -7742,19 +8006,32 @@ setconfquirk(const char *selector, const char *value, int flags)
 void
 setup_quirks(void)
 {
-       setquirk("MPlayer",             "xv",           ".*",   SWM_Q_FLOAT | SWM_Q_FULLSCREEN | SWM_Q_FOCUSPREV);
-       setquirk("OpenOffice.org 3.2",  "VCLSalFrame",  ".*",   SWM_Q_FLOAT);
-       setquirk("Firefox-bin",         "firefox-bin",  ".*",   SWM_Q_TRANSSZ);
-       setquirk("Firefox",             "Dialog",       ".*",   SWM_Q_FLOAT);
-       setquirk("Gimp",                "gimp",         ".*",   SWM_Q_FLOAT | SWM_Q_ANYWHERE);
-       setquirk("XTerm",               "xterm",        ".*",   SWM_Q_XTERM_FONTADJ);
-       setquirk("xine",                "Xine Window",  ".*",   SWM_Q_FLOAT | SWM_Q_ANYWHERE);
-       setquirk("Xitk",                "Xitk Combo",   ".*",   SWM_Q_FLOAT | SWM_Q_ANYWHERE);
-       setquirk("xine",                "xine Panel",   ".*",   SWM_Q_FLOAT | SWM_Q_ANYWHERE);
-       setquirk("Xitk",                "Xine Window",  ".*",   SWM_Q_FLOAT | SWM_Q_ANYWHERE);
-       setquirk("xine",                "xine Video Fullscreen Window", ".*",   SWM_Q_FULLSCREEN | SWM_Q_FLOAT);
-       setquirk("pcb",                 "pcb",          ".*",   SWM_Q_FLOAT);
-       setquirk("SDL_App",             "SDL_App",      ".*",   SWM_Q_FLOAT | SWM_Q_FULLSCREEN);
+       setquirk("MPlayer",             "xv",           ".*",
+           SWM_Q_FLOAT | SWM_Q_FULLSCREEN | SWM_Q_FOCUSPREV, -1);
+       setquirk("OpenOffice.org 3.2",  "VCLSalFrame",  ".*",
+           SWM_Q_FLOAT, -1);
+       setquirk("Firefox-bin",         "firefox-bin",  ".*",
+           SWM_Q_TRANSSZ, -1);
+       setquirk("Firefox",             "Dialog",       ".*",
+           SWM_Q_FLOAT, -1);
+       setquirk("Gimp",                "gimp",         ".*",
+           SWM_Q_FLOAT | SWM_Q_ANYWHERE, -1);
+       setquirk("XTerm",               "xterm",        ".*",
+           SWM_Q_XTERM_FONTADJ, -1);
+       setquirk("xine",                "Xine Window",  ".*",
+           SWM_Q_FLOAT | SWM_Q_ANYWHERE, -1);
+       setquirk("Xitk",                "Xitk Combo",   ".*",
+           SWM_Q_FLOAT | SWM_Q_ANYWHERE, -1);
+       setquirk("xine",                "xine Panel",   ".*",
+           SWM_Q_FLOAT | SWM_Q_ANYWHERE, -1);
+       setquirk("Xitk",                "Xine Window",  ".*",
+           SWM_Q_FLOAT | SWM_Q_ANYWHERE, -1);
+       setquirk("xine",                "xine Video Fullscreen Window", ".*",
+           SWM_Q_FULLSCREEN | SWM_Q_FLOAT, -1);
+       setquirk("pcb",                 "pcb",          ".*",
+           SWM_Q_FLOAT, -1);
+       setquirk("SDL_App",             "SDL_App",      ".*",
+           SWM_Q_FLOAT | SWM_Q_FULLSCREEN, -1);
 }
 
 /* conf file stuff */
@@ -7784,6 +8061,8 @@ enum {
        SWM_S_FOCUS_DEFAULT,
        SWM_S_FOCUS_MODE,
        SWM_S_ICONIC_ENABLED,
+       SWM_S_JAVA_WORKAROUND,
+       SWM_S_MAXIMIZE_HIDE_BAR,
        SWM_S_REGION_PADDING,
        SWM_S_SPAWN_ORDER,
        SWM_S_SPAWN_TERM,
@@ -7792,8 +8071,10 @@ enum {
        SWM_S_STACK_ENABLED,
        SWM_S_TERM_WIDTH,
        SWM_S_TILE_GAP,
+       SWM_S_URGENT_COLLAPSE,
        SWM_S_URGENT_ENABLED,
        SWM_S_VERBOSE_LAYOUT,
+       SWM_S_WARP_POINTER,
        SWM_S_WINDOW_CLASS_ENABLED,
        SWM_S_WINDOW_INSTANCE_ENABLED,
        SWM_S_WINDOW_NAME_ENABLED,
@@ -7815,7 +8096,7 @@ setconfvalue(const char *selector, const char *value, int flags)
                        err(1, "setconfvalue: bar_action");
                break;
        case SWM_S_BAR_AT_BOTTOM:
-               bar_at_bottom = atoi(value);
+               bar_at_bottom = (atoi(value) != 0);
                break;
        case SWM_S_BAR_BORDER_WIDTH:
                bar_border_width = atoi(value);
@@ -7826,7 +8107,7 @@ setconfvalue(const char *selector, const char *value, int flags)
                /* No longer needed; leave to not break old conf files. */
                break;
        case SWM_S_BAR_ENABLED:
-               bar_enabled = atoi(value);
+               bar_enabled = (atoi(value) != 0);
                break;
        case SWM_S_BAR_ENABLED_WS:
                ws_id = atoi(selector) - 1;
@@ -7837,7 +8118,7 @@ setconfvalue(const char *selector, const char *value, int flags)
                num_screens = get_screen_count();
                for (i = 0; i < num_screens; i++) {
                        ws = (struct workspace *)&screens[i].ws;
-                       ws[ws_id].bar_enabled = atoi(value);
+                       ws[ws_id].bar_enabled = (atoi(value) != 0);
                }
                break;
        case SWM_S_BAR_FONT:
@@ -7859,7 +8140,7 @@ setconfvalue(const char *selector, const char *value, int flags)
                        if (*b == '\0')
                                continue;
                        if (!isxlfd(b)) {
-                               bar_font_legacy = 0;
+                               bar_font_legacy = false;
                                break;
                        }
                }
@@ -7892,7 +8173,7 @@ setconfvalue(const char *selector, const char *value, int flags)
                        boundary_width = 0;
                break;
        case SWM_S_CLOCK_ENABLED:
-               clock_enabled = atoi(value);
+               clock_enabled = (atoi(value) != 0);
                break;
        case SWM_S_CLOCK_FORMAT:
 #ifndef SWM_DENY_CLOCK_FORMAT
@@ -7902,10 +8183,10 @@ setconfvalue(const char *selector, const char *value, int flags)
 #endif
                break;
        case SWM_S_CYCLE_EMPTY:
-               cycle_empty = atoi(value);
+               cycle_empty = (atoi(value) != 0);
                break;
        case SWM_S_CYCLE_VISIBLE:
-               cycle_visible = atoi(value);
+               cycle_visible = (atoi(value) != 0);
                break;
        case SWM_S_DIALOG_RATIO:
                dialog_ratio = atof(value);
@@ -7913,7 +8194,7 @@ setconfvalue(const char *selector, const char *value, int flags)
                        dialog_ratio = .6;
                break;
        case SWM_S_DISABLE_BORDER:
-               disable_border = atoi(value);
+               disable_border = (atoi(value) != 0);
                break;
        case SWM_S_FOCUS_CLOSE:
                if (strcmp(value, "first") == 0)
@@ -7928,7 +8209,7 @@ setconfvalue(const char *selector, const char *value, int flags)
                        errx(1, "focus_close");
                break;
        case SWM_S_FOCUS_CLOSE_WRAP:
-               focus_close_wrap = atoi(value);
+               focus_close_wrap = (atoi(value) != 0);
                break;
        case SWM_S_FOCUS_DEFAULT:
                if (strcmp(value, "last") == 0)
@@ -7950,7 +8231,13 @@ setconfvalue(const char *selector, const char *value, int flags)
                        errx(1, "focus_mode");
                break;
        case SWM_S_ICONIC_ENABLED:
-               iconic_enabled = atoi(value);
+               iconic_enabled = (atoi(value) != 0);
+               break;
+       case SWM_S_JAVA_WORKAROUND:
+               java_workaround = (atoi(value) != 0);
+               break;
+       case SWM_S_MAXIMIZE_HIDE_BAR:
+               maximize_hide_bar = atoi(value);
                break;
        case SWM_S_REGION_PADDING:
                region_padding = atoi(value);
@@ -7980,7 +8267,7 @@ setconfvalue(const char *selector, const char *value, int flags)
                /* No longer needed; leave to not break old conf files. */
                break;
        case SWM_S_STACK_ENABLED:
-               stack_enabled = atoi(value);
+               stack_enabled = (atoi(value) != 0);
                break;
        case SWM_S_TERM_WIDTH:
                term_width = atoi(value);
@@ -7990,11 +8277,14 @@ setconfvalue(const char *selector, const char *value, int flags)
        case SWM_S_TILE_GAP:
                tile_gap = atoi(value);
                break;
+       case SWM_S_URGENT_COLLAPSE:
+               urgent_collapse = (atoi(value) != 0);
+               break;
        case SWM_S_URGENT_ENABLED:
-               urgent_enabled = atoi(value);
+               urgent_enabled = (atoi(value) != 0);
                break;
        case SWM_S_VERBOSE_LAYOUT:
-               verbose_layout = atoi(value);
+               verbose_layout = (atoi(value) != 0);
                for (i = 0; layouts[i].l_stack != NULL; i++) {
                        if (verbose_layout)
                                layouts[i].l_string = fancy_stacker;
@@ -8002,14 +8292,17 @@ setconfvalue(const char *selector, const char *value, int flags)
                                layouts[i].l_string = plain_stacker;
                }
                break;
+       case SWM_S_WARP_POINTER:
+               warp_pointer = (atoi(value) != 0);
+               break;
        case SWM_S_WINDOW_CLASS_ENABLED:
-               window_class_enabled = atoi(value);
+               window_class_enabled = (atoi(value) != 0);
                break;
        case SWM_S_WINDOW_INSTANCE_ENABLED:
-               window_instance_enabled = atoi(value);
+               window_instance_enabled = (atoi(value) != 0);
                break;
        case SWM_S_WINDOW_NAME_ENABLED:
-               window_name_enabled = atoi(value);
+               window_name_enabled = (atoi(value) != 0);
                break;
        case SWM_S_WORKSPACE_LIMIT:
                workspace_limit = atoi(value);
@@ -8067,17 +8360,94 @@ setconfmodkey(const char *selector, const char *value, int flags)
                update_modkey(XCB_MOD_MASK_3);
        else if (strncasecmp(value, "Mod4", strlen("Mod4")) == 0)
                update_modkey(XCB_MOD_MASK_4);
+       else if (strncasecmp(value, "Mod5", strlen("Mod5")) == 0)
+               update_modkey(XCB_MOD_MASK_5);
        else
                return (1);
        return (0);
 }
 
+int
+setconfmousebuttonmove(const char *selector, const char *value, int flags)
+{
+       /* suppress unused warnings since vars are needed */
+       (void)selector;
+       (void)flags;
+
+       if (strncasecmp(value, "But1", strlen("But1")) == 0) {
+               if (!update_mousebutton(0, XCB_BUTTON_INDEX_1))
+                       return (1);
+       } else if (strncasecmp(value, "But2", strlen("But2")) == 0) {
+               if (!update_mousebutton(0, XCB_BUTTON_INDEX_2))
+                       return (1);
+       } else if (strncasecmp(value, "But3", strlen("But3")) == 0) {
+               if (!update_mousebutton(0, XCB_BUTTON_INDEX_3))
+                       return (1);
+       } else
+               return (1);
+       return (0);
+}
+
+int
+setconfmousebuttonresize(const char *selector, const char *value, int flags)
+{
+       /* suppress unused warnings since vars are needed */
+       (void)selector;
+       (void)flags;
+
+       if (strncasecmp(value, "But1", strlen("But1")) == 0) {
+               if (!update_mousebutton(1, XCB_BUTTON_INDEX_1))
+                       return (1);
+       } else if (strncasecmp(value, "But2", strlen("But2")) == 0) {
+               if (!update_mousebutton(1, XCB_BUTTON_INDEX_2))
+                       return (1);
+       } else if (strncasecmp(value, "But3", strlen("But3")) == 0) {
+               if (!update_mousebutton(1, XCB_BUTTON_INDEX_3))
+                       return (1);
+       } else
+               return (1);
+       return (0);
+}
+
 int
 setconfcolor(const char *selector, const char *value, int flags)
 {
-       setscreencolor(value,
-           (selector == NULL || strlen(selector) == 0) ? -1 : atoi(selector),
-           flags);
+       int     first, last, i = 0, num_screens;
+
+       num_screens = get_screen_count();
+
+       /* conf screen indices begin at 1; treat vals <= 0 as 'all screens.' */
+       if (selector == NULL || strlen(selector) == 0 ||
+           (last = atoi(selector) - 1) < 0) {
+               first = 0;
+               last = num_screens - 1;
+       } else {
+               first = last;
+       }
+
+       if (last >= num_screens) {
+               add_startup_exception("invalid screen index: %d out of bounds "
+                   "(maximum %d)", last + 1, num_screens);
+               return (1);
+       }
+
+       for (i = first; i <= last; ++i) {
+               setscreencolor(value, i, flags);
+
+               /*
+                * When setting focus/unfocus colors, we need to also
+                * set maximize colors to match if they haven't been customized.
+                */
+               if (flags == SWM_S_COLOR_FOCUS &&
+                   !screens[i].c[SWM_S_COLOR_FOCUS_MAXIMIZED].manual)
+                       setscreencolor(value, i, SWM_S_COLOR_FOCUS_MAXIMIZED);
+               else if (flags == SWM_S_COLOR_UNFOCUS &&
+                   !screens[i].c[SWM_S_COLOR_UNFOCUS_MAXIMIZED].manual)
+                       setscreencolor(value, i, SWM_S_COLOR_UNFOCUS_MAXIMIZED);
+
+               screens[i].c[flags].manual = 1;
+       }
+
        return (0);
 }
 
@@ -8143,7 +8513,7 @@ setautorun(const char *selector, const char *value, int flags)
        a.argv[argc] = NULL;
 
        if ((pid = fork()) == 0) {
-               spawn(ws_id, &a, 1);
+               spawn(ws_id, &a, true);
                /* NOTREACHED */
                _exit(1);
        }
@@ -8167,10 +8537,11 @@ setautorun(const char *selector, const char *value, int flags)
 int
 setlayout(const char *selector, const char *value, int flags)
 {
-       int                     ws_id, i, x, mg, ma, si, ar, f = 0;
+       struct workspace        *ws;
+       int                     ws_id, i, x, mg, ma, si, ar;
        int                     st = SWM_V_STACK, num_screens;
        char                    s[1024];
-       struct workspace        *ws;
+       bool                    f = false;
 
        /* suppress unused warnings since vars are needed */
        (void)selector;
@@ -8193,12 +8564,12 @@ setlayout(const char *selector, const char *value, int flags)
                st = SWM_V_STACK;
        else if (strcasecmp(s, "vertical_flip") == 0) {
                st = SWM_V_STACK;
-               f = 1;
+               f = true;
        } else if (strcasecmp(s, "horizontal") == 0)
                st = SWM_H_STACK;
        else if (strcasecmp(s, "horizontal_flip") == 0) {
                st = SWM_H_STACK;
-               f = 1;
+               f = true;
        } else if (strcasecmp(s, "fullscreen") == 0)
                st = SWM_MAX_STACK;
        else
@@ -8211,7 +8582,7 @@ setlayout(const char *selector, const char *value, int flags)
                ws = (struct workspace *)&screens[i].ws;
                ws[ws_id].cur_layout = &layouts[st];
 
-               ws[ws_id].always_raise = ar;
+               ws[ws_id].always_raise = (ar != 0);
                if (st == SWM_MAX_STACK)
                        continue;
 
@@ -8220,32 +8591,26 @@ setlayout(const char *selector, const char *value, int flags)
                        ws[ws_id].cur_layout->l_config(&ws[ws_id],
                            mg >= 0 ?  SWM_ARG_ID_MASTERGROW :
                            SWM_ARG_ID_MASTERSHRINK);
-                       stack();
                }
                /* master add */
                for (x = 0; x < abs(ma); x++) {
                        ws[ws_id].cur_layout->l_config(&ws[ws_id],
                            ma >= 0 ?  SWM_ARG_ID_MASTERADD :
                            SWM_ARG_ID_MASTERDEL);
-                       stack();
                }
                /* stack inc */
                for (x = 0; x < abs(si); x++) {
                        ws[ws_id].cur_layout->l_config(&ws[ws_id],
                            si >= 0 ?  SWM_ARG_ID_STACKINC :
                            SWM_ARG_ID_STACKDEC);
-                       stack();
                }
                /* Apply flip */
                if (f) {
                        ws[ws_id].cur_layout->l_config(&ws[ws_id],
                            SWM_ARG_ID_FLIPLAYOUT);
-                       stack();
                }
        }
 
-       focus_flush();
-
        return (0);
 }
 
@@ -8276,7 +8641,9 @@ struct config_option configopt[] = {
        { "clock_enabled",              setconfvalue,   SWM_S_CLOCK_ENABLED },
        { "clock_format",               setconfvalue,   SWM_S_CLOCK_FORMAT },
        { "color_focus",                setconfcolor,   SWM_S_COLOR_FOCUS },
+       { "color_focus_maximized",      setconfcolor,   SWM_S_COLOR_FOCUS_MAXIMIZED },
        { "color_unfocus",              setconfcolor,   SWM_S_COLOR_UNFOCUS },
+       { "color_unfocus_maximized",    setconfcolor,   SWM_S_COLOR_UNFOCUS_MAXIMIZED },
        { "cycle_empty",                setconfvalue,   SWM_S_CYCLE_EMPTY },
        { "cycle_visible",              setconfvalue,   SWM_S_CYCLE_VISIBLE },
        { "dialog_ratio",               setconfvalue,   SWM_S_DIALOG_RATIO },
@@ -8286,9 +8653,13 @@ struct config_option configopt[] = {
        { "focus_default",              setconfvalue,   SWM_S_FOCUS_DEFAULT },
        { "focus_mode",                 setconfvalue,   SWM_S_FOCUS_MODE },
        { "iconic_enabled",             setconfvalue,   SWM_S_ICONIC_ENABLED },
+       { "java_workaround",            setconfvalue,   SWM_S_JAVA_WORKAROUND },
+       { "maximize_hide_bar",          setconfvalue,   SWM_S_MAXIMIZE_HIDE_BAR },
        { "keyboard_mapping",           setkeymapping,  0 },
        { "layout",                     setlayout,      0 },
        { "modkey",                     setconfmodkey,  0 },
+       { "move_button",                setconfmousebuttonmove, 0 },
+       { "resize_button",              setconfmousebuttonresize, 0 },
        { "program",                    setconfspawn,   0 },
        { "quirk",                      setconfquirk,   0 },
        { "region",                     setconfregion,  0 },
@@ -8302,8 +8673,10 @@ struct config_option configopt[] = {
        { "tile_gap",                   setconfvalue,   SWM_S_TILE_GAP },
        { "title_class_enabled",        setconfvalue,   SWM_S_WINDOW_CLASS_ENABLED }, /* For backwards compat. */
        { "title_name_enabled",         setconfvalue,   SWM_S_WINDOW_INSTANCE_ENABLED }, /* For backwards compat. */
+       { "urgent_collapse",            setconfvalue,   SWM_S_URGENT_COLLAPSE },
        { "urgent_enabled",             setconfvalue,   SWM_S_URGENT_ENABLED },
        { "verbose_layout",             setconfvalue,   SWM_S_VERBOSE_LAYOUT },
+       { "warp_pointer",               setconfvalue,   SWM_S_WARP_POINTER },
        { "window_class_enabled",       setconfvalue,   SWM_S_WINDOW_CLASS_ENABLED },
        { "window_instance_enabled",    setconfvalue,   SWM_S_WINDOW_INSTANCE_ENABLED },
        { "window_name_enabled",        setconfvalue,   SWM_S_WINDOW_NAME_ENABLED },
@@ -8329,7 +8702,7 @@ add_startup_exception(const char *fmt, ...)
                return;
 
        /* force bar to be enabled due to exception */
-       bar_enabled = 1;
+       bar_enabled = true;
 
        va_start(ap, fmt);
        _add_startup_exception(fmt, ap);
@@ -8452,6 +8825,12 @@ conf_load(const char *filename, int keymapping)
        if (line)
                free(line);
        fclose(config);
+
+       if (mouse_button_move == mouse_button_resize) {
+               add_startup_exception("%s: move and resize mouse buttons match",
+                   filename);
+       }
+
        DNPRINTF(SWM_D_CONF, "conf_load: end\n");
 
        return (0);
@@ -8585,13 +8964,16 @@ get_swm_ws(xcb_window_t id)
 }
 
 int
-get_ws_idx(xcb_window_t id)
+get_ws_idx(struct ws_win *win)
 {
        xcb_get_property_reply_t        *gpr;
        int                     ws_idx = -1;
 
+       if (win == NULL)
+               return -1;
+
        gpr = xcb_get_property_reply(conn,
-               xcb_get_property(conn, 0, id, ewmh[_NET_WM_DESKTOP].atom,
+               xcb_get_property(conn, 0, win->id, ewmh[_NET_WM_DESKTOP].atom,
                    XCB_ATOM_CARDINAL, 0, 1),
                NULL);
        if (gpr) {
@@ -8600,20 +8982,20 @@ get_ws_idx(xcb_window_t id)
                free(gpr);
        }
 
-       if (ws_idx == -1)
-               if ((ws_idx = get_swm_ws(id)) != -1)
-                       xcb_delete_property(conn, id, a_swm_ws);
+       if (ws_idx == -1 && !(win->quirks & SWM_Q_IGNORESPAWNWS))
+               ws_idx = get_swm_ws(win->id);
 
        if (ws_idx > workspace_limit - 1 || ws_idx < -1)
                ws_idx = -1;
 
-       DNPRINTF(SWM_D_PROP, "get_ws_idx: win %#x, ws_idx: %d\n", id, ws_idx);
+       DNPRINTF(SWM_D_PROP, "get_ws_idx: win %#x, ws_idx: %d\n", win->id,
+           ws_idx);
 
        return ws_idx;
 }
 
 struct ws_win *
-manage_window(xcb_window_t id, int mapped)
+manage_window(xcb_window_t id, int spawn_pos, bool mapped)
 {
        struct ws_win           *win, *ww;
        struct swm_region       *r;
@@ -8622,7 +9004,7 @@ manage_window(xcb_window_t id, int mapped)
        xcb_get_geometry_reply_t        *gr;
        xcb_window_t            trans = XCB_WINDOW_NONE;
        uint32_t                i, wa[2], new_flags;
-       int                     ws_idx;
+       int                     ws_idx, force_ws = -1;
        char                    *class, *instance, *name;
 
        if ((win = find_window(id)) != NULL) {
@@ -8667,7 +9049,7 @@ manage_window(xcb_window_t id, int mapped)
        HEIGHT(win) = gr->height;
        X(win) = gr->x + gr->border_width - border_width;
        Y(win) = gr->y + gr->border_width - border_width;
-       win->bordered = 1;
+       win->bordered = true;
        win->mapped = mapped;
        win->s = r->s;  /* this never changes */
 
@@ -8706,32 +9088,6 @@ manage_window(xcb_window_t id, int mapped)
        /* Get WM_PROTOCOLS. */
        get_wm_protocols(win);
 
-       /* Figure out which workspace the window belongs to. */
-       if ((p = find_pid(window_get_pid(win->id))) != NULL) {
-               win->ws = &r->s->ws[p->ws];
-               TAILQ_REMOVE(&pidlist, p, entry);
-               free(p);
-               p = NULL;
-       } else if ((ws_idx = get_ws_idx(win->id)) != -1 &&
-           !TRANS(win)) {
-               /* _SWM_WS is set; use that. */
-               win->ws = &r->s->ws[ws_idx];
-       } else if (trans && (ww = find_window(trans)) != NULL) {
-               /* Launch transients in the same ws as parent. */
-               win->ws = ww->ws;
-       } else {
-               win->ws = r->ws;
-       }
-
-       /* Set the _NET_WM_DESKTOP atom. */
-       DNPRINTF(SWM_D_PROP, "manage_window: set _NET_WM_DESKTOP: %d\n",
-           win->ws->idx);
-       xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win->id,
-           ewmh[_NET_WM_DESKTOP].atom, XCB_ATOM_CARDINAL, 32, 1, &win->ws->idx);
-
-       /* WS must already be set for this to work. */
-       store_float_geom(win);
-
        /* Set initial quirks based on EWMH. */
        ewmh_autoquirk(win);
 
@@ -8750,7 +9106,7 @@ manage_window(xcb_window_t id, int mapped)
        /* java is retarded so treat it special */
        if (strstr(instance, "sun-awt")) {
                DNPRINTF(SWM_D_CLASS, "manage_window: java window detected.\n");
-               win->java = 1;
+               win->java = true;
        }
 
        TAILQ_FOREACH(qp, &quirks, entry) {
@@ -8758,9 +9114,11 @@ manage_window(xcb_window_t id, int mapped)
                    regexec(&qp->regex_instance, instance, 0, NULL, 0) == 0 &&
                    regexec(&qp->regex_name, name, 0, NULL, 0) == 0) {
                        DNPRINTF(SWM_D_CLASS, "manage_window: matched "
-                           "quirk: %s:%s:%s mask: %#lx\n", qp->class,
-                           qp->instance, qp->name, qp->quirk);
+                           "quirk: %s:%s:%s mask: %#x, ws: %d\n", qp->class,
+                           qp->instance, qp->name, qp->quirk, qp->ws);
                        win->quirks = qp->quirk;
+                       if (qp->ws >= 0 && qp->ws < workspace_limit)
+                               force_ws = qp->ws;
                }
        }
 
@@ -8774,6 +9132,39 @@ manage_window(xcb_window_t id, int mapped)
                        fake_keypress(win, XK_KP_Add, XCB_MOD_MASK_SHIFT);
        }
 
+       /* Figure out which workspace the window belongs to. */
+       if (!(win->quirks & SWM_Q_IGNOREPID) &&
+           (p = find_pid(window_get_pid(win->id))) != NULL) {
+               win->ws = &r->s->ws[p->ws];
+               TAILQ_REMOVE(&pidlist, p, entry);
+               free(p);
+               p = NULL;
+       } else if ((ws_idx = get_ws_idx(win)) != -1 &&
+           !TRANS(win)) {
+               /* _SWM_WS is set; use that. */
+               win->ws = &r->s->ws[ws_idx];
+       } else if (trans && (ww = find_window(trans)) != NULL) {
+               /* Launch transients in the same ws as parent. */
+               win->ws = ww->ws;
+       } else {
+               win->ws = r->ws;
+       }
+
+       if (force_ws != -1)
+               win->ws = &r->s->ws[force_ws];
+
+       /* Set the _NET_WM_DESKTOP atom. */
+       DNPRINTF(SWM_D_PROP, "manage_window: set _NET_WM_DESKTOP: %d\n",
+           win->ws->idx);
+       xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win->id,
+           ewmh[_NET_WM_DESKTOP].atom, XCB_ATOM_CARDINAL, 32, 1, &win->ws->idx);
+
+       /* Remove any _SWM_WS now that we set _NET_WM_DESKTOP. */
+       xcb_delete_property(conn, win->id, a_swm_ws);
+
+       /* WS must already be set for this to work. */
+       store_float_geom(win);
+
        /* Make sure window is positioned inside its region, if its active. */
        if (win->ws->r) {
                region_containment(win, r, SWM_CW_ALLSIDES |
@@ -8782,15 +9173,15 @@ manage_window(xcb_window_t id, int mapped)
        }
 
 out:
-       /* Figure out where to stack the window in the workspace. */
+       /* Figure out where to insert the window in the workspace list. */
        if (trans && (ww = find_window(trans)))
                TAILQ_INSERT_AFTER(&win->ws->winlist, ww, win, entry);
-       else if (win->ws->focus && spawn_position == SWM_STACK_ABOVE)
+       else if (win->ws->focus && spawn_pos == SWM_STACK_ABOVE)
                TAILQ_INSERT_AFTER(&win->ws->winlist, win->ws->focus, win,
                    entry);
-       else if (win->ws->focus && spawn_position == SWM_STACK_BELOW)
+       else if (win->ws->focus && spawn_pos == SWM_STACK_BELOW)
                TAILQ_INSERT_BEFORE(win->ws->focus, win, entry);
-       else switch (spawn_position) {
+       else switch (spawn_pos) {
        default:
        case SWM_STACK_TOP:
        case SWM_STACK_ABOVE:
@@ -8803,7 +9194,8 @@ out:
 
        ewmh_update_client_list();
 
-       TAILQ_INSERT_TAIL(&win->ws->stack, win, stack_entry);
+       TAILQ_INSERT_HEAD(&win->ws->stack, win, stack_entry);
+       lower_window(win);
 
        /* Get/apply initial _NET_WM_STATE */
        ewmh_get_wm_state(win);
@@ -8952,7 +9344,7 @@ buttonpress(xcb_button_press_event_t *e)
        struct ws_win           *win = NULL;
        struct swm_region       *r, *old_r;
        int                     i;
-       int                     handled = 0;
+       bool                    handled = false;
 
        DNPRINTF(SWM_D_EVENT, "buttonpress: win (x,y): %#x (%d,%d), "
            "detail: %u, time: %u, root (x,y): %#x (%d,%d), child: %#x, "
@@ -8987,7 +9379,7 @@ buttonpress(xcb_button_press_event_t *e)
                                /* Clear bar since empty. */
                                bar_draw();
 
-                               handled = 1;
+                               handled = true;
                                goto out;
                        }
                }
@@ -9007,7 +9399,7 @@ buttonpress(xcb_button_press_event_t *e)
                    buttons[i].button == e->detail &&
                    CLEANMASK(buttons[i].mask) == CLEANMASK(e->state)) {
                        buttons[i].func(win, &buttons[i].args);
-                       handled = 1;
+                       handled = true;
                }
 
 out:
@@ -9081,13 +9473,14 @@ 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;
+       int                     i = 0;
        uint32_t                wc[7] = {0};
+       uint16_t                mask = 0;
+       bool                    new = false;
 
        if ((win = find_window(e->window)) == NULL)
                if ((win = find_unmanaged_window(e->window)) == NULL)
-                       new = 1;
+                       new = true;
 
 #ifdef SWM_DEBUG
        if (swm_debug & SWM_D_EVENT) {
@@ -9177,7 +9570,7 @@ configurerequest(xcb_configure_request_event_t *e)
                if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT)
                        win->g_float.h = e->height;
 
-               win->g_floatvalid = 1;
+               win->g_floatvalid = true;
 
                if (!MAXIMIZED(win) && !FULLSCREEN(win) &&
                    (TRANS(win) || (ABOVE(win) &&
@@ -9351,6 +9744,12 @@ enternotify(xcb_enter_notify_event_t *e)
                return;
        }
 
+       if (focus_mode != SWM_FOCUS_FOLLOW &&
+           e->mode == XCB_NOTIFY_MODE_UNGRAB) {
+               DNPRINTF(SWM_D_EVENT, "enternotify: ungrab; ignoring.\n");
+               return;
+       }
+
        last_event_time = e->time;
 
        if ((win = find_window(e->event)) == NULL) {
@@ -9370,6 +9769,13 @@ enternotify(xcb_enter_notify_event_t *e)
                        return;
                }
        } else {
+               if (e->mode == XCB_NOTIFY_MODE_NORMAL &&
+                   e->detail == XCB_NOTIFY_DETAIL_INFERIOR) {
+                       DNPRINTF(SWM_D_EVENT, "enternotify: entering from "
+                           "inferior; ignoring\n");
+                       return;
+               }
+
                focus_win(get_focus_magic(win));
        }
 
@@ -9399,7 +9805,7 @@ mapnotify(xcb_map_notify_event_t *e)
 
        DNPRINTF(SWM_D_EVENT, "mapnotify: win %#x\n", e->window);
 
-       if ((win = manage_window(e->window, 1)) == NULL)
+       if ((win = manage_window(e->window, spawn_position, true)) == NULL)
                return;
        ws = win->ws;
 
@@ -9414,13 +9820,14 @@ mapnotify(xcb_map_notify_event_t *e)
                                stack();
        }
 
-       win->mapped = 1;
+       win->mapped = true;
        set_win_state(win, XCB_ICCCM_WM_STATE_NORMAL);
 
        if (focus_mode != SWM_FOCUS_FOLLOW && WS_FOCUSED(win->ws)) {
                if (ws->focus_pending == win) {
                        focus_win(win);
                        ws->focus_pending = NULL;
+                       center_pointer(win->ws->r);
                        focus_flush();
                }
        }
@@ -9472,7 +9879,7 @@ maprequest(xcb_map_request_event_t *e)
                goto out;
        }
 
-       win = manage_window(e->window,
+       win = manage_window(e->window, spawn_position,
            (war->map_state == XCB_MAP_STATE_VIEWABLE));
        if (win == NULL)
                goto out;
@@ -9644,7 +10051,7 @@ unmapnotify(xcb_unmap_notify_event_t *e)
                return;
 
        ws = win->ws;
-       win->mapped = 0;
+       win->mapped = false;
 
        /* If win was focused, make sure to focus on something else. */
        if (win == ws->focus) {
@@ -9683,9 +10090,34 @@ unmapnotify(xcb_unmap_notify_event_t *e)
                }
        }
 
+       center_pointer(ws->r);
        focus_flush();
 }
 
+#ifdef SWM_DEBUG
+char *
+get_source_type_label(uint32_t type)
+{
+       char *label;
+
+       switch (type) {
+       case EWMH_SOURCE_TYPE_NONE:
+               label = "None";
+               break;
+       case EWMH_SOURCE_TYPE_NORMAL:
+               label = "Normal";
+               break;
+       case EWMH_SOURCE_TYPE_OTHER:
+               label = "Other";
+               break;
+       default:
+               label = "Invalid";
+       }
+
+       return label;
+}
+#endif
+
 void
 clientmessage(xcb_client_message_event_t *e)
 {
@@ -9712,8 +10144,7 @@ clientmessage(xcb_client_message_event_t *e)
                                break;
                        }
 
-               if (r && e->data.data32[0] <
-                   (uint32_t)workspace_limit) {
+               if (r && e->data.data32[0] < (uint32_t)workspace_limit) {
                        a.id = e->data.data32[0];
                        switchws(r, &a);
                        focus_flush();
@@ -9735,11 +10166,22 @@ clientmessage(xcb_client_message_event_t *e)
        }
 
        if (e->type == ewmh[_NET_ACTIVE_WINDOW].atom) {
-               DNPRINTF(SWM_D_EVENT, "clientmessage: _NET_ACTIVE_WINDOW\n");
-               if (WS_FOCUSED(win->ws))
-                       focus_win(win);
-               else
-                       win->ws->focus_pending = win;
+               DNPRINTF(SWM_D_EVENT, "clientmessage: _NET_ACTIVE_WINDOW, "
+                   "source_type: %s(%d)\n",
+                   get_source_type_label(e->data.data32[0]),
+                   e->data.data32[0]);
+
+               /*
+                * Allow focus changes that are a result of direct user
+                * action and from applications that use the old EWMH spec.
+                */
+               if (e->data.data32[0] != EWMH_SOURCE_TYPE_NORMAL ||
+                   win->quirks & SWM_Q_OBEYAPPFOCUSREQ) {
+                       if (WS_FOCUSED(win->ws))
+                               focus_win(win);
+                       else
+                               win->ws->focus_pending = win;
+               }
        } else if (e->type == ewmh[_NET_CLOSE_WINDOW].atom) {
                DNPRINTF(SWM_D_EVENT, "clientmessage: _NET_CLOSE_WINDOW\n");
                if (win->can_delete)
@@ -9785,7 +10227,7 @@ clientmessage(xcb_client_message_event_t *e)
                DNPRINTF(SWM_D_EVENT, "clientmessage: _NET_WM_DESKTOP\n");
                r = win->ws->r;
 
-               win_to_ws(win, e->data.data32[0], 1);
+               win_to_ws(win, e->data.data32[0], true);
 
                /* Restack if either the source or destination ws is mapped. */
                if (r != NULL || win->ws->r != NULL) {
@@ -9961,7 +10403,7 @@ new_region(struct swm_screen *s, int x, int y, int w, int h)
 }
 
 void
-scan_xrandr(int i)
+scan_randr(int idx)
 {
 #ifdef SWM_XRR_HAS_CRTC
        int                                             c;
@@ -9977,34 +10419,34 @@ scan_xrandr(int i)
        xcb_randr_crtc_t                                *crtc;
        xcb_screen_t                                    *screen;
 
-       DNPRINTF(SWM_D_MISC, "scan_xrandr: screen: %d\n", i);
+       DNPRINTF(SWM_D_MISC, "scan_randr: screen: %d\n", idx);
 
-       if ((screen = get_screen(i)) == NULL)
-               errx(1, "ERROR: can't get screen %d.", i);
+       if ((screen = get_screen(idx)) == NULL)
+               errx(1, "ERROR: can't get screen %d.", idx);
 
        num_screens = get_screen_count();
-       if (i >= num_screens)
-               errx(1, "scan_xrandr: invalid screen");
+       if (idx >= num_screens)
+               errx(1, "scan_randr: invalid screen");
 
        /* remove any old regions */
-       while ((r = TAILQ_FIRST(&screens[i].rl)) != NULL) {
+       while ((r = TAILQ_FIRST(&screens[idx].rl)) != NULL) {
                r->ws->old_r = r->ws->r = NULL;
                bar_cleanup(r);
                xcb_destroy_window(conn, r->id);
-               TAILQ_REMOVE(&screens[i].rl, r, entry);
-               TAILQ_INSERT_TAIL(&screens[i].orl, r, entry);
+               TAILQ_REMOVE(&screens[idx].rl, r, entry);
+               TAILQ_INSERT_TAIL(&screens[idx].orl, r, entry);
        }
        outputs = 0;
 
        /* map virtual screens onto physical screens */
 #ifdef SWM_XRR_HAS_CRTC
-       if (xrandr_support) {
+       if (randr_support) {
                src = xcb_randr_get_screen_resources_current(conn,
-                   screens[i].root);
+                   screens[idx].root);
                srr = xcb_randr_get_screen_resources_current_reply(conn, src,
                    NULL);
                if (srr == NULL) {
-                       new_region(&screens[i], 0, 0,
+                       new_region(&screens[idx], 0, 0,
                            screen->width_in_pixels,
                            screen->height_in_pixels);
                        goto out;
@@ -10024,11 +10466,11 @@ scan_xrandr(int i)
                        }
 
                        if (cir->mode == 0)
-                               new_region(&screens[i], 0, 0,
+                               new_region(&screens[idx], 0, 0,
                                    screen->width_in_pixels,
                                    screen->height_in_pixels);
                        else
-                               new_region(&screens[i],
+                               new_region(&screens[idx],
                                    cir->x, cir->y, cir->width, cir->height);
                        free(cir);
                }
@@ -10037,23 +10479,23 @@ scan_xrandr(int i)
 #endif /* SWM_XRR_HAS_CRTC */
 
        /* If detection failed, create a single region that spans the screen. */
-       if (TAILQ_EMPTY(&screens[i].rl))
-               new_region(&screens[i], 0, 0, screen->width_in_pixels,
+       if (TAILQ_EMPTY(&screens[idx].rl))
+               new_region(&screens[idx], 0, 0, screen->width_in_pixels,
                    screen->height_in_pixels);
 
 out:
        /* Cleanup unused previously visible workspaces. */
-       TAILQ_FOREACH(r, &screens[i].orl, entry) {
+       TAILQ_FOREACH(r, &screens[idx].orl, entry) {
                TAILQ_FOREACH(win, &r->ws->winlist, entry)
                        unmap_window(win);
                r->ws->state = SWM_WS_STATE_HIDDEN;
 
                /* The screen shouldn't focus on an unused region. */
-               if (screens[i].r_focus == r)
-                       screens[i].r_focus = NULL;
+               if (screens[idx].r_focus == r)
+                       screens[idx].r_focus = NULL;
        }
 
-       DNPRINTF(SWM_D_MISC, "scan_xrandr: done.\n");
+       DNPRINTF(SWM_D_MISC, "scan_randr: done.\n");
 }
 
 void
@@ -10073,7 +10515,7 @@ screenchange(xcb_randr_screen_change_notify_event_t *e)
                errx(1, "screenchange: screen not found");
 
        /* brute force for now, just re-enumerate the regions */
-       scan_xrandr(i);
+       scan_randr(i);
 
 #ifdef SWM_DEBUG
        print_win_geom(e->root);
@@ -10109,8 +10551,9 @@ grab_windows(void)
 {
        struct swm_region       *r = NULL;
        xcb_window_t            *wins = NULL, trans, *cwins = NULL;
-       int                     i, j, k, n, no, num_screens, manage, mapped;
+       int                     i, j, k, n, no, num_screens;
        uint8_t                 state;
+       bool                    manage, mapped;
 
        xcb_query_tree_cookie_t                 qtc;
        xcb_query_tree_reply_t                  *qtr;
@@ -10200,7 +10643,7 @@ grab_windows(void)
                        manage = state != XCB_ICCCM_WM_STATE_WITHDRAWN;
                        mapped = gar->map_state == XCB_MAP_STATE_VIEWABLE;
                        if (mapped || manage)
-                               manage_window(wins[j], mapped);
+                               manage_window(wins[j], SWM_STACK_TOP, mapped);
                        free(gar);
                }
                /* transient windows */
@@ -10227,7 +10670,7 @@ grab_windows(void)
                        pc = xcb_icccm_get_wm_transient_for(conn, wins[j]);
                        if (xcb_icccm_get_wm_transient_for_reply(conn, pc,
                            &trans, NULL) && manage)
-                               manage_window(wins[j], mapped);
+                               manage_window(wins[j], SWM_STACK_TOP, mapped);
                        free(gar);
                }
                free(qtr);
@@ -10252,16 +10695,16 @@ setup_screens(void)
                err(1, "setup_screens: calloc: failed to allocate memory for "
                    "screens");
 
-       /* initial Xrandr setup */
-       xrandr_support = 0;
+       /* Initial RandR setup. */
+       randr_support = false;
        qep = xcb_get_extension_data(conn, &xcb_randr_id);
        if (qep->present) {
                c = xcb_randr_query_version(conn, 1, 1);
                r = xcb_randr_query_version_reply(conn, c, NULL);
                if (r) {
                        if (r->major_version >= 1) {
-                               xrandr_support = 1;
-                               xrandr_eventbase = qep->first_event;
+                               randr_support = true;
+                               randr_eventbase = qep->first_event;
                        }
                        free(r);
                }
@@ -10282,13 +10725,16 @@ setup_screens(void)
                screens[i].root = screen->root;
 
                /* set default colors */
-               setscreencolor("red", i + 1, SWM_S_COLOR_FOCUS);
-               setscreencolor("rgb:88/88/88", i + 1, SWM_S_COLOR_UNFOCUS);
-               setscreencolor("rgb:00/80/80", i + 1, SWM_S_COLOR_BAR_BORDER);
-               setscreencolor("rgb:00/40/40", i + 1,
+               setscreencolor("red", i, SWM_S_COLOR_FOCUS);
+               setscreencolor("rgb:88/88/88", i, SWM_S_COLOR_UNFOCUS);
+               setscreencolor("rgb:00/80/80", i, SWM_S_COLOR_BAR_BORDER);
+               setscreencolor("rgb:00/40/40", i,
                    SWM_S_COLOR_BAR_BORDER_UNFOCUS);
-               setscreencolor("black", i + 1, SWM_S_COLOR_BAR);
-               setscreencolor("rgb:a0/a0/a0", i + 1, SWM_S_COLOR_BAR_FONT);
+               setscreencolor("black", i, SWM_S_COLOR_BAR);
+               setscreencolor("rgb:a0/a0/a0", i, SWM_S_COLOR_BAR_FONT);
+               setscreencolor("red", i, SWM_S_COLOR_FOCUS_MAXIMIZED);
+               setscreencolor("rgb:88/88/88", i,
+                   SWM_S_COLOR_UNFOCUS_MAXIMIZED);
 
                /* create graphics context on screen */
                screens[i].bar_gc = xcb_generate_id(conn);
@@ -10306,7 +10752,7 @@ setup_screens(void)
                        ws = &screens[i].ws[j];
                        ws->idx = j;
                        ws->name = NULL;
-                       ws->bar_enabled = 1;
+                       ws->bar_enabled = true;
                        ws->focus = NULL;
                        ws->focus_prev = NULL;
                        ws->focus_pending = NULL;
@@ -10325,9 +10771,9 @@ setup_screens(void)
                        ws->cur_layout->l_string(ws);
                }
 
-               scan_xrandr(i);
+               scan_randr(i);
 
-               if (xrandr_support)
+               if (randr_support)
                        xcb_randr_select_input(conn, screens[i].root,
                            XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE);
        }
@@ -10358,7 +10804,7 @@ setup_globals(void)
 void
 shutdown_cleanup(void)
 {
-       int i, num_screens;
+       int                     i, num_screens;
 
        /* disable alarm because the following code may not be interrupted */
        alarm(0);
@@ -10379,9 +10825,12 @@ shutdown_cleanup(void)
 
                if (screens[i].bar_gc != XCB_NONE)
                        xcb_free_gc(conn, screens[i].bar_gc);
-               if (!bar_font_legacy)
+               if (!bar_font_legacy) {
                        XftColorFree(display, DefaultVisual(display, i),
                            DefaultColormap(display, i), &bar_font_color);
+                       XftColorFree(display, DefaultVisual(display, i),
+                           DefaultColormap(display, i), &search_font_color);
+               }
        }
 
        if (bar_font_legacy)
@@ -10410,7 +10859,7 @@ event_error(xcb_generic_error_t *e)
 void
 event_handle(xcb_generic_event_t *evt)
 {
-       uint8_t type = XCB_EVENT_RESPONSE_TYPE(evt);
+       uint8_t                 type = XCB_EVENT_RESPONSE_TYPE(evt);
 
        DNPRINTF(SWM_D_EVENT, "XCB Event: %s(%d), seq %u\n",
            xcb_event_get_label(XCB_EVENT_RESPONSE_TYPE(evt)),
@@ -10458,7 +10907,7 @@ event_handle(xcb_generic_event_t *evt)
        /*EVENT(XCB_VISIBILITY_NOTIFY, );*/
 #undef EVENT
        }
-       if (type - xrandr_eventbase == XCB_RANDR_SCREEN_CHANGE_NOTIFY)
+       if (type - randr_eventbase == XCB_RANDR_SCREEN_CHANGE_NOTIFY)
                screenchange((void *)evt);
 }
 
@@ -10468,19 +10917,19 @@ main(int argc, char *argv[])
        struct swm_region       *r;
        char                    conf[PATH_MAX], *cfile = NULL;
        struct stat             sb;
-       int                     xfd, i, num_screens, startup = 1;
+       int                     xfd, i, num_screens;
        struct sigaction        sact;
        xcb_generic_event_t     *evt;
-       struct timeval          tv;
-       fd_set                  rd;
-       int                     rd_max;
-       int                     stdin_ready = 0;
        int                     num_readable;
+       struct pollfd           pfd[2];
+       bool                    stdin_ready = false, startup = true;
 
        /* suppress unused warning since var is needed */
        (void)argc;
 
+#ifdef SWM_DEBUG
        time_started = time(NULL);
+#endif
 
        start_argv = argv;
        warnx("Welcome to spectrwm V%s Build: %s", SPECTRWM_VERSION, buildstr);
@@ -10609,7 +11058,11 @@ noconfig:
                TAILQ_FOREACH(r, &screens[i].rl, entry)
                        r->ws->state = SWM_WS_STATE_MAPPED;
 
-       rd_max = xfd > STDIN_FILENO ? xfd : STDIN_FILENO;
+       memset(&pfd, 0, sizeof(pfd));
+       pfd[0].fd = xfd;
+       pfd[0].events = POLLIN;
+       pfd[1].fd = STDIN_FILENO;
+       pfd[1].events = POLLIN;
 
        while (running) {
                while ((evt = xcb_poll_for_event(conn))) {
@@ -10621,7 +11074,7 @@ noconfig:
 
                /* If just (re)started, set default focus if needed. */
                if (startup) {
-                       startup = 0;
+                       startup = false;
 
                        if (focus_mode != SWM_FOCUS_FOLLOW) {
                                r = TAILQ_FIRST(&screens[0].rl);
@@ -10633,19 +11086,11 @@ noconfig:
                        }
                }
 
-               FD_ZERO(&rd);
-
-               if (bar_extra)
-                       FD_SET(STDIN_FILENO, &rd);
-
-               FD_SET(xfd, &rd);
-               tv.tv_sec = 1;
-               tv.tv_usec = 0;
-               num_readable = select(rd_max + 1, &rd, NULL, NULL, &tv);
-               if (num_readable == -1 && errno != EINTR) {
-                       DNPRINTF(SWM_D_MISC, "select failed");
-               } else if (num_readable > 0 && FD_ISSET(STDIN_FILENO, &rd)) {
-                       stdin_ready = 1;
+               num_readable = poll(pfd, bar_extra ? 2 : 1, 1000);
+               if (num_readable == -1) {
+                       DNPRINTF(SWM_D_MISC, "poll failed: %s", strerror(errno));
+               } else if (num_readable > 0 && bar_extra && pfd[1].revents & POLLIN) {
+                       stdin_ready = true;
                }
 
                if (restart_wm)
@@ -10658,7 +11103,7 @@ noconfig:
                        goto done;
 
                if (stdin_ready) {
-                       stdin_ready = 0;
+                       stdin_ready = false;
                        bar_extra_update();
                }