]> code.delx.au - spectrwm/blobdiff - spectrwm.c
ad yuri to copyrights
[spectrwm] / spectrwm.c
index fe6868495d01b4412f98756a88ad4a500da9bc98..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-2014 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
@@ -333,6 +334,8 @@ 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;
@@ -402,6 +405,7 @@ char                 *bar_format = NULL;
 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;
@@ -625,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)
@@ -653,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;
 };
 
@@ -678,6 +685,7 @@ struct quirk {
 #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);
@@ -883,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,
@@ -891,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,
@@ -1119,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);
@@ -1166,6 +1179,7 @@ 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 *);
@@ -4035,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;
 
@@ -4048,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);
@@ -4063,9 +4080,22 @@ cyclerg(struct swm_region *r, union arg *args)
        if (rr == NULL)
                return;
 
-       focus_region(rr);
-       center_pointer(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");
 }
 
@@ -4388,7 +4418,8 @@ focus(struct swm_region *r, union arg *args)
                } while (winfocus && (ICONIC(winfocus) ||
                    winfocus->id == cur_focus->transient ||
                    (cur_focus->transient != XCB_WINDOW_NONE &&
-                   winfocus->transient == cur_focus->transient)));
+                   winfocus->transient == cur_focus->transient) ||
+                   (winfocus->quirks & SWM_Q_NOFOCUSCYCLE)));
                break;
        case SWM_ARG_ID_FOCUSNEXT:
                if (cur_focus == NULL)
@@ -4404,7 +4435,8 @@ focus(struct swm_region *r, union arg *args)
                } while (winfocus && (ICONIC(winfocus) ||
                    winfocus->id == cur_focus->transient ||
                    (cur_focus->transient != XCB_WINDOW_NONE &&
-                   winfocus->transient == cur_focus->transient)));
+                   winfocus->transient == cur_focus->transient) ||
+                   (winfocus->quirks & SWM_Q_NOFOCUSCYCLE)));
                break;
        case SWM_ARG_ID_FOCUSMAIN:
                if (cur_focus == NULL)
@@ -4644,7 +4676,7 @@ update_floater(struct ws_win *win)
 
                win->g = r->g;
 
-               if (bar_enabled && ws->bar_enabled) {
+               if (bar_enabled && ws->bar_enabled && !maximize_hide_bar) {
                        if (!bar_at_bottom)
                                Y(win) += bar_height;
                        HEIGHT(win) -= bar_height;
@@ -4939,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--;
@@ -4989,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--;
@@ -6695,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} },
@@ -6703,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} },
@@ -6798,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)
@@ -7228,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)
@@ -7466,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);
@@ -7478,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);
@@ -7675,6 +7746,7 @@ const char *quirkname[] = {
        "OBEYAPPFOCUSREQ",
        "IGNOREPID",
        "IGNORESPAWNWS",
+       "NOFOCUSCYCLE",
 };
 
 /* SWM_Q_DELIM: retain '|' for back compat for now (2009-08-11) */
@@ -7990,6 +8062,7 @@ enum {
        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,
@@ -8163,6 +8236,9 @@ setconfvalue(const char *selector, const char *value, int flags)
        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);
                if (region_padding < 0)
@@ -8284,11 +8360,55 @@ 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)
 {
@@ -8534,9 +8654,12 @@ struct config_option configopt[] = {
        { "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 },
@@ -8702,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);
@@ -9615,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) {