conformal / spectrwm

A small dynamic tiling window manager for X11.
ISC License
1.33k stars 97 forks source link

Mouse button assignment #30

Closed ideasman42 closed 9 years ago

ideasman42 commented 10 years ago

Is it possible to set the mouse button used for moving and resizing windows? (it looks like they might be hard coded?)

levaidaniel commented 10 years ago

Here is a simple diff implementing this:

Basically, you can use move_button and resize_button in .spectrwm.conf, and you can specify But{1,2,3} for their parameters. I don't know, it maybe a bit messy, I'm not extra familiar with the code, but seems to do the job. Basic checks are there to prevent multiple bindings for the same mouse button. The configuration option names are ad-hoc, of course, they should be changed if they're not fitting in.

diff --git a/spectrwm.1 b/spectrwm.1
index 54b8123..8eb867e 100644
--- a/spectrwm.1
+++ b/spectrwm.1
@@ -318,6 +318,12 @@ This setting is not retained at restart.
 .It Ic modkey
 Change mod key.
 Mod1 is generally the ALT key and Mod4 is the windows key on a PC.
+.It Ic move_button
+Change mouse button used for moving windows.
+But1 is the left, But2 is the middle and But3 is the right mouse button.
+.It Ic resize_button
+Change mouse button used for resizing windows.
+But1 is the left, But2 is the middle and But3 is the right mouse button.
 .It Ic name
 Set the name of a workspace at start-of-day.
 Defined in the format ws[<idx>]:<name>, e.g. ws[1]:Console sets the name of
diff --git a/spectrwm.c b/spectrwm.c
index 3719d0d..96a6256 100644
--- a/spectrwm.c
+++ b/spectrwm.c
@@ -331,6 +331,8 @@ int                 cycle_visible = 0;
 int                    term_width = 0;
 int                    font_adjusted = 0;
 unsigned int           mod_key = MODKEY;
+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;
@@ -1109,6 +1111,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);
@@ -1156,6 +1160,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 *);
@@ -6659,6 +6664,43 @@ 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:
+                       /* Failsafe to prevent mapping the same mouse
+                        * buttons to both move and resize
+                        */
+                       if (but == mouse_button_resize)
+                               return (0);
+
+                       mouse_button_move = but;
+                       break;
+               case 1:
+                       /* Failsafe to prevent mapping the same mouse
+                        * buttons to both move and resize
+                        */
+                       if (but == mouse_button_move)
+                               return (0);
+
+                       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)
@@ -8115,6 +8157,48 @@ setconfmodkey(const char *selector, const char *value, int flags)
 }

 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)
 {
        int     first, last, i = 0, num_screens;
@@ -8366,6 +8450,8 @@ struct config_option configopt[] = {
        { "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 },
levaidaniel commented 10 years ago

Alright, I realize now that pasting the diff here was stupid enough, so you can reach it at levaidaniel/spectrwm@146ca0b

levaidaniel commented 10 years ago

Did you guys have a chance to review this?

levaidaniel commented 10 years ago

So if anyone is interested in this at all, there is an updated version of the diff that applies to master:

https://github.com/levaidaniel/sbo/blob/mystuff/mystuff/desktop/spectrwm-dev/patches/01-mouse_button_configurable.diff

ideasman42 commented 9 years ago

@levaidaniel tested the patch, The patch works quite nice but is a little problematic in that it forces you to use a temporary mouse button to swap L/R buttons. Eg:

resize_button   = But2
move_button     = But3
resize_button   = But1

Without the first assignment to button 2, the second 2 assignments fail. This could instead just ignore bad configuration (allow both to be assigned to the one mouse button). Or - it could report a warning once the config is finished reading - when there are duplicate assignments.

ideasman42 commented 9 years ago

@levaidaniel updated the patch and made a pull request. https://github.com/conformal/spectrwm/pull/86

marcopeereboom commented 9 years ago

Closed per @ideasman42