dwm

Mahdi's build of dwm
git clone git://mahdi.pw/dwm.git
Log | Files | Refs | README | LICENSE

commit 1afeee85838fab506a47bea3830eed8e4d715d60
parent bd464e94f36a05777abfc7022bda89f7698b5a26
Author: Mahdi Mirzade <me@mahdym.ir>
Date:   Thu, 24 Mar 2022 00:33:40 +0430

attachaside -> attachbottom, more functions

Diffstat:
Dconfig.def.h | 210-------------------------------------------------------------------------------
Aconfig.h | 229+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdwm.c | 319++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Dpatches/dwm-attachaside-6.3.diff | 92-------------------------------------------------------------------------------
Apatches/dwm-attachbottom-20201227-61bb8b2.diff | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apatches/dwm-movestack-20211115-a786211.diff | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apatches/dwm-placemouse-6.3.diff | 259+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apatches/dwm-warp-6.2.diff | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8 files changed, 1001 insertions(+), 328 deletions(-)

diff --git a/config.def.h b/config.def.h @@ -1,210 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -/* Load XF86 Multimedia Keybinds */ -#include <X11/XF86keysym.h> - -/* appearance */ -static const char *fonts[] = { "monospace:size=8", "ubvazir:size=8" }; -static const unsigned int borderpx = 4; /* border pixel of windows */ -static const unsigned int gappx = 5; /* gaps between windows */ -static const unsigned int snap = 32; /* snap pixel */ -static const unsigned int systraypinning= 0; /* 0: sloppy systray follows selected monitor, 0: pin systray to monitor X */ -static const unsigned int systrayonleft = 0; /* 0: systray in the right corner, >0: systray on left of status text */ -static const unsigned int systrayspacing= 2; /* systray spacing */ -static const int systraypinningfailfirst= 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/ -static const int showsystray = 1; /* 0 means no systray */ -static const int swallowfloating = 0; /* 1 means swallow floating windows by default */ -static const int showbar = 1; /* 0 means no bar */ -static const int topbar = 1; /* 0 means bottom bar */ -static const int barheight = 20; /* 0 means that dwm will calculate bar height, >= 1 means dwm will user_bh as bar height */ -static const int hidevacanttags = 1; /* 1 means hide empty tags / 0: show every tag */ -static const int hidetagindicator = 1; /* 1 means hide default top-left square-shaped tag indicator */ -static const int centeredwindowname = 0; /* 1 means center the WM_NAME of the currently selected window on the status bar */ -static const unsigned int colorfultag = 1; /* 0 means use SchemeSel for selected tag */ -static char fgcolor[] = "#D8DEE9"; -static char bgcolor[] = "#2E3440"; -static char color0[] = "#3B4252"; -static char color1[] = "#BF616A"; -static char color2[] = "#A3BE8C"; -static char color3[] = "#EBCB8B"; -static char color4[] = "#81A1C1"; -static char color5[] = "#B48EAD"; -static char color6[] = "#88C0D0"; -static char color7[] = "#E5E9F0"; -static char color8[] = "#4C566A"; -static char color9[] = "#BF616A"; -static char color10[] = "#A3BE8C"; -static char color11[] = "#EBCB8B"; -static char color12[] = "#81A1C1"; -static char color13[] = "#B48EAD"; -static char color14[] = "#8FBCBB"; -static char color15[] = "#ECEFF4"; -static const char *colors[][3] = { - /* fg bg border */ - [SchemeNorm] = { color7, bgcolor, bgcolor }, - [SchemeSel] = { fgcolor, color0, color0 }, - [SchemeTag] = { color0, bgcolor, bgcolor }, - [SchemeTag1] = { color1, bgcolor, bgcolor }, - [SchemeTag2] = { color2, bgcolor, bgcolor }, - [SchemeTag3] = { color3, bgcolor, bgcolor }, - [SchemeTag4] = { color4, bgcolor, bgcolor }, - [SchemeTag5] = { color5, bgcolor, bgcolor }, - [SchemeTag6] = { color6, bgcolor, bgcolor }, - [SchemeTag7] = { color9, bgcolor, bgcolor }, - [SchemeTag8] = { color10, bgcolor, bgcolor }, - [SchemeTag9] = { color11, bgcolor, bgcolor }, - [SchemeLayout] = { color12, bgcolor, bgcolor }, - -}; - - -/* tagging */ -static const char *tags[] = { "𐎠", "𐎡", "𐎢", "𐎣", "𐎤", "𐎥", "𐎦", "𐎧", "𐎨" }; -//static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; - -static const int tagschemes[] = { SchemeTag1, SchemeTag2, SchemeTag3, - SchemeTag4, SchemeTag5, SchemeTag6, - SchemeTag7, SchemeTag8, SchemeTag9, -}; - -static const char *tagsel[][2] = { - { color1, bgcolor }, - { color2, bgcolor }, - { color3, bgcolor }, - { color4, bgcolor }, - { color5, bgcolor }, - { color6, bgcolor }, - { color9, bgcolor }, - { color10, bgcolor }, - { color11, bgcolor }, -}; - -static const unsigned int ulinepad = 5; /* horizontal padding between the underline and tag */ -static const unsigned int ulinestroke = 1; /* thickness / height of the underline */ -static const unsigned int ulinevoffset = 1; /* how far above the bottom of the bar the line should appear */ -static const int ulineall = 0; /* 1 to show underline on all tags, 0 for just the active ones */ - -static const Rule rules[] = { - /* xprop(1): - * WM_CLASS(STRING) = instance, class - * WM_NAME(STRING) = title - */ - /* class instance title tags mask isfloating isterminal noswallow monitor */ - { "Gimp", NULL, NULL, 0, 1, 0, 0, -1 }, - { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1, -1 }, - { "st-256color",NULL, NULL, 0, 0, 1, 0, -1 }, - { "st-float", NULL, NULL, 0, 1, 1, 0, -1 }, - { NULL, NULL, "Event Tester", 0, 0, 0, 1, -1 }, /* xev */ -}; - -/* layout(s) */ -static const float mfact = 0.5; /* factor of master area size [0.05..0.95] */ -static const int nmaster = 1; /* number of clients in master area */ -static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */ -static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ - -static const Layout layouts[] = { - /* symbol arrange function */ - { "[]=", tile }, /* first entry is default */ - { "><>", NULL }, /* no layout function means floating behavior */ - { "[M]", monocle }, - { NULL, NULL }, -}; - -/* key definitions */ -#define MODKEY Mod4Mask -#define TAGKEYS(KEY,TAG) \ - { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ - { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ - { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ - { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, \ - { Mod1Mask, KEY, focusnthmon, {.i = TAG } }, \ - { Mod1Mask|ShiftMask, KEY, tagnthmon, {.i = TAG } }, - -/* helper for spawning shell commands in the pre dwm-5.0 fashion */ -#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } - -/* commands */ -static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ -static const char *dmenucmd[] = { "dmenu_run", "-i", "-c", "-l", "20", "-bw", "4", NULL }; -static const char *termcmd[] = { "st", NULL }; - -static Key keys[] = { - /* modifier key function argument */ - { MODKEY, XK_c, spawn, {.v = dmenucmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, - { MODKEY, XK_b, togglebar, {0} }, - { MODKEY, XK_j, focusstack, {.i = +1 } }, - { MODKEY, XK_k, focusstack, {.i = -1 } }, - { MODKEY, XK_i, incnmaster, {.i = +1 } }, - { MODKEY, XK_d, incnmaster, {.i = -1 } }, - { MODKEY, XK_h, setmfact, {.f = -0.05} }, - { MODKEY, XK_l, setmfact, {.f = +0.05} }, - { MODKEY, XK_Return, zoom, {0} }, - { MODKEY, XK_Tab, view, {0} }, - { MODKEY|ShiftMask, XK_c, killclient, {0} }, - { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, - { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, - { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, - { MODKEY|ControlMask, XK_comma, cyclelayout, {.i = -1 } }, - { MODKEY|ControlMask, XK_period, cyclelayout, {.i = +1 } }, - { MODKEY, XK_space, setlayout, {0} }, - { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, - { MODKEY|ShiftMask, XK_f, togglefullscr, {0} }, - { MODKEY, XK_s, togglesticky, {0} }, - { MODKEY, XK_0, view, {.ui = ~0 } }, - { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, - { MODKEY, XK_comma, focusmon, {.i = -1 } }, - { MODKEY, XK_period, focusmon, {.i = +1 } }, - { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, - { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, - { MODKEY, XK_F5, xrdb, {.v = NULL } }, - { MODKEY, XK_minus, setgaps, {.i = -1 } }, - { MODKEY, XK_equal, setgaps, {.i = +1 } }, - { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } }, - TAGKEYS( XK_1, 0) - TAGKEYS( XK_2, 1) - TAGKEYS( XK_3, 2) - TAGKEYS( XK_4, 3) - TAGKEYS( XK_5, 4) - TAGKEYS( XK_6, 5) - TAGKEYS( XK_7, 6) - TAGKEYS( XK_8, 7) - TAGKEYS( XK_9, 8) - { MODKEY|ShiftMask, XK_r, quit, {1} }, - { MODKEY|ShiftMask, XK_q, quit, {0} }, - { MODKEY, XK_w, spawn, SHCMD("st -c \"st-float\" -g \"80x24+400+150\" -e sh -c \"set-bg -s\"") }, - { MODKEY|ShiftMask, XK_t, spawn, SHCMD("set-theme -s") }, - { MODKEY|ControlMask, XK_l, spawn, SHCMD("lock") }, - { MODKEY, XK_period, spawn, SHCMD("emoji") }, - { 0, XK_Print, spawn, SHCMD("screenshot") }, - { ShiftMask, XK_Print, spawn, SHCMD("screenshot -t 5") }, - { ControlMask, XK_Print, spawn, SHCMD("screenshot -s yes") }, - { ControlMask|ShiftMask, XK_Print, spawn, SHCMD("screenshot -s yes -t 5") }, - { 0, XF86XK_WebCam, spawn, SHCMD("webcam") }, - { 0, XF86XK_MonBrightnessUp, spawn, SHCMD("backlight up") }, - { 0, XF86XK_MonBrightnessDown, spawn, SHCMD("backlight down") }, - { 0, XF86XK_AudioRaiseVolume, spawn, SHCMD("volume up") }, - { 0, XF86XK_AudioLowerVolume, spawn, SHCMD("volume down") }, - { 0, XF86XK_AudioMute, spawn, SHCMD("volume mute") }, - -}; - -/* button definitions */ -/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ -static Button buttons[] = { - /* click event mask button function argument */ - { ClkTagBar, MODKEY, Button1, tag, {0} }, - { ClkTagBar, MODKEY, Button3, toggletag, {0} }, - { ClkWinTitle, 0, Button2, zoom, {0} }, - { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, - { ClkClientWin, MODKEY, Button1, movemouse, {0} }, - { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, - { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, - { ClkTagBar, 0, Button1, view, {0} }, - { ClkTagBar, 0, Button3, toggleview, {0} }, - { ClkTagBar, MODKEY, Button1, tag, {0} }, - { ClkTagBar, MODKEY, Button3, toggletag, {0} }, - { ClkLtSymbol, 0, Button1, cyclelayout, {.i = +1} }, - { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, -}; diff --git a/config.h b/config.h @@ -0,0 +1,229 @@ +/* See LICENSE file for copyright and license details. */ + +/* Load essentials */ +#include <X11/XF86keysym.h> /* For XF86 multimedia binds */ + +/* appearance */ +static const char *fonts[] = { "monospace:size=8", "Vazir:size=8" }; +static const unsigned int borderpx = 2; /* border pixel of windows */ +static const unsigned int gappx = 5; /* gaps between windows */ +static const unsigned int snap = 32; /* snap pixel */ +static const unsigned int systraypinning= 0; /* 0: sloppy systray follows selected monitor, 0: pin systray to monitor X */ +static const unsigned int systrayonleft = 0; /* 0: systray in the right corner, >0: systray on left of status text */ +static const unsigned int systrayspacing= 2; /* systray spacing */ +static const int systraypinningfailfirst= 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/ +static const int showsystray = 1; /* 0 means no systray */ +static const int swallowfloating = 0; /* 1 means swallow floating windows by default */ +static const int showbar = 1; /* 0 means no bar */ +static const int topbar = 1; /* 0 means bottom bar */ +static const int barheight = 20; /* 0 means that dwm will calculate bar height, >= 1 means dwm will barheight as bar height */ +static const int hidevacanttags = 1; /* 1 means hide empty tags / 0: show every tag */ +static const int hidetagindicator = 1; /* 1 means hide default top-left square-shaped tag indicator */ +static const int centeredwindowname = 0; /* 1 means center the WM_NAME of the currently selected window on the status bar */ +static const unsigned int colorfultag = 1; /* 0 means use SchemeSel for selected tag */ +static char fgcolor[] = "#D8DEE9"; +static char bgcolor[] = "#2E3440"; +static char color0[] = "#3B4252"; +static char color1[] = "#BF616A"; +static char color2[] = "#A3BE8C"; +static char color3[] = "#EBCB8B"; +static char color4[] = "#81A1C1"; +static char color5[] = "#B48EAD"; +static char color6[] = "#88C0D0"; +static char color7[] = "#E5E9F0"; +static char color8[] = "#4C566A"; +static char color9[] = "#BF616A"; +static char color10[] = "#A3BE8C"; +static char color11[] = "#EBCB8B"; +static char color12[] = "#81A1C1"; +static char color13[] = "#B48EAD"; +static char color14[] = "#8FBCBB"; +static char color15[] = "#ECEFF4"; +static const char *colors[][3] = { + /* fg bg border */ + [SchemeNorm] = { color7, bgcolor, bgcolor }, + [SchemeSel] = { fgcolor, color0, color0 }, + [SchemeTag] = { color0, bgcolor, bgcolor }, + [SchemeTag1] = { color1, bgcolor, bgcolor }, + [SchemeTag2] = { color2, bgcolor, bgcolor }, + [SchemeTag3] = { color3, bgcolor, bgcolor }, + [SchemeTag4] = { color4, bgcolor, bgcolor }, + [SchemeTag5] = { color5, bgcolor, bgcolor }, + [SchemeTag6] = { color6, bgcolor, bgcolor }, + [SchemeTag7] = { color9, bgcolor, bgcolor }, + [SchemeTag8] = { color10, bgcolor, bgcolor }, + [SchemeTag9] = { color11, bgcolor, bgcolor }, + [SchemeLayout] = { color12, bgcolor, bgcolor }, + +}; + + +/* tagging */ +static const char *tags[] = { "𐎠", "𐎡", "𐎢", "𐎣", "𐎤", "𐎥", "𐎦", "𐎧", "𐎨" }; +//static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + +static const int tagschemes[] = { SchemeTag1, SchemeTag2, SchemeTag3, + SchemeTag4, SchemeTag5, SchemeTag6, + SchemeTag7, SchemeTag8, SchemeTag9, +}; + +static const char *tagsel[][2] = { + { color1, bgcolor }, + { color2, bgcolor }, + { color3, bgcolor }, + { color4, bgcolor }, + { color5, bgcolor }, + { color6, bgcolor }, + { color9, bgcolor }, + { color10, bgcolor }, + { color11, bgcolor }, +}; + +static const unsigned int ulinepad = 5; /* horizontal padding between the underline and tag */ +static const unsigned int ulinestroke = 1; /* thickness / height of the underline */ +static const unsigned int ulinevoffset = 1; /* how far above the bottom of the bar the line should appear */ +static const int ulineall = 0; /* 1 to show underline on all tags, 0 for just the active ones */ + +static const Rule rules[] = { + /* xprop(1): + * WM_CLASS(STRING) = instance, class + * WM_NAME(STRING) = title + */ + /* class instance title tags mask isfloating isterminal noswallow monitor */ + { "mpv", NULL, NULL, 0, 1, 0, 0, -1 }, + { "Gimp", NULL, NULL, 0, 1, 0, 0, -1 }, + { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1, -1 }, + { "st-float", NULL, NULL, 0, 1, 1, 0, -1 }, + { "st-256color",NULL, NULL, 0, 0, 1, 0, -1 }, + { NULL, NULL, "Event Tester", 0, 0, 0, 1, -1 }, /* xev */ +}; + +/* layout(s) */ +static const float mfact = 0.5; /* factor of master area size [0.05..0.95] */ +static const int nmaster = 1; /* number of clients in master area */ +static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */ +static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ + +static const Layout layouts[] = { + /* symbol arrange function */ + { "[]=", tile }, /* first entry is default */ + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, + { NULL, NULL }, +}; + +/* key definitions */ +#define MODKEY Mod4Mask +#define TAGKEYS(KEY,TAG) \ + { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ + { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, \ + { Mod1Mask, KEY, focusnthmon, {.i = TAG } }, \ + { Mod1Mask|ShiftMask, KEY, tagnthmon, {.i = TAG } }, + +/* helper for spawning shell commands in the pre dwm-5.0 fashion */ +#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } + +/* commands */ +static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ +static const char *dmenucmd[] = { "dmenu_run", "-i", "-c", "-l", "20", "-bw", "4", NULL }; +static const char *termcmd[] = { "st", NULL }; +static const char *termcmdfloat[] = { "st", "-c", "st-float", NULL }; + +static Key keys[] = { + /* modifier key function argument */ + { MODKEY, XK_a, spawn, SHCMD("dmenu_drun") }, + { MODKEY, XK_c, spawn, {.v = dmenucmd } }, + { MODKEY, XK_Return, spawn, {.v = termcmd } }, + { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmdfloat } }, + { MODKEY|ShiftMask, XK_b, spawn, SHCMD("dmenu_bar") }, + { MODKEY, XK_b, togglebar, {0} }, + { MODKEY, XK_j, focusstack, {.i = +1 } }, + { MODKEY, XK_k, focusstack, {.i = -1 } }, + { MODKEY, XK_i, incnmaster, {.i = +1 } }, + { MODKEY, XK_d, incnmaster, {.i = -1 } }, + { MODKEY, XK_h, setmfact, {.f = -0.05} }, + { MODKEY, XK_l, setmfact, {.f = +0.05} }, + { MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } }, + { MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } }, + { MODKEY, XK_space, zoom, {0} }, + { MODKEY, XK_Tab, view, {0} }, + { MODKEY|ShiftMask, XK_c, killclient, {0} }, + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, + { MODKEY|ControlMask, XK_comma, cyclelayout, {.i = -1 } }, + { MODKEY|ControlMask, XK_period, cyclelayout, {.i = +1 } }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY|ShiftMask, XK_f, togglefullscr, {0} }, + { MODKEY, XK_s, togglesticky, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, + { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, + { MODKEY, XK_comma, focusmon, {.i = -1 } }, + { MODKEY, XK_period, focusmon, {.i = +1 } }, + { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, + { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, + { MODKEY, XK_F5, xrdb, {.v = NULL } }, + { MODKEY, XK_minus, setgaps, {.i = -1 } }, + { MODKEY, XK_equal, setgaps, {.i = +1 } }, + { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } }, + TAGKEYS( XK_1, 0) + TAGKEYS( XK_2, 1) + TAGKEYS( XK_3, 2) + TAGKEYS( XK_4, 3) + TAGKEYS( XK_5, 4) + TAGKEYS( XK_6, 5) + TAGKEYS( XK_7, 6) + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) + { MODKEY|ShiftMask, XK_r, quit, {1} }, + { MODKEY|ShiftMask, XK_q, quit, {0} }, + { MODKEY, XK_w, spawn, SHCMD("st -c \"st-float\" -g \"80x24+400+150\" -e sh -c \"set-bg -s\"") }, + { MODKEY|ShiftMask, XK_t, spawn, SHCMD("set-theme -s") }, + { MODKEY|ControlMask, XK_l, spawn, SHCMD("lock") }, + { MODKEY, XK_grave, spawn, SHCMD("emoji insert") }, + { ControlMask, XK_grave, spawn, SHCMD("emoji clipboard") }, + { 0, XK_Print, spawn, SHCMD("screenshot") }, + { ShiftMask, XK_Print, spawn, SHCMD("screenshot -t 5") }, + { ControlMask, XK_Print, spawn, SHCMD("screenshot -s yes") }, + { ControlMask|ShiftMask, XK_Print, spawn, SHCMD("screenshot -s yes -t 5") }, + { 0, XF86XK_WebCam, spawn, SHCMD("webcam") }, + { 0, XF86XK_MonBrightnessUp, spawn, SHCMD("backlight up") }, + { 0, XF86XK_MonBrightnessDown, spawn, SHCMD("backlight down") }, + { 0, XF86XK_AudioRaiseVolume, spawn, SHCMD("volume up") }, + { 0, XF86XK_AudioLowerVolume, spawn, SHCMD("volume down") }, + { 0, XF86XK_AudioMute, spawn, SHCMD("volume mute") }, + +}; + +/* button definitions */ +/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ +static Button buttons[] = { + /* click event mask button function argument */ + /* placemouse options, choose which feels more natural: + * 0 - tiled position is relative to mouse cursor + * 1 - tiled postiion is relative to window center + * 2 - mouse pointer warps to window center + * + * The moveorplace uses movemouse or placemouse depending on the floating state + * of the selected client. Set up individual keybindings for the two if you want + * to control these separately (i.e. to retain the feature to move a tiled window + * into a floating position). + */ + { ClkClientWin, MODKEY, Button1, moveorplace, {.i = 1} }, + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, + { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, + { ClkTagBar, 0, Button1, view, {0} }, + { ClkTagBar, 0, Button3, toggleview, {0} }, + { ClkTagBar, MODKEY, Button1, tag, {0} }, + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, + { ClkLtSymbol, 0, Button1, cyclelayout, {.i = +1} }, + { ClkLtSymbol, 0, Button2, setlayout, {.v = &layouts[0]} }, + { ClkLtSymbol, 0, Button3, cyclelayout, {.i = -1} }, + { ClkWinTitle, 0, Button1, zoom, {0} }, + { ClkWinTitle, 0, Button2, spawn, {.v = termcmd} }, + { ClkWinTitle, 0, Button3, togglesticky, {0} }, + { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, + { ClkStatusText, 0, Button3, spawn, SHCMD("dmenu_bar") }, +}; diff --git a/dwm.c b/dwm.c @@ -58,8 +58,9 @@ #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) -#define ISVISIBLEONTAG(C, T) ((C->tags & T)) -#define ISVISIBLE(C) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags] || C->issticky) +#define INTERSECTC(x,y,w,h,z) (MAX(0, MIN((x)+(w),(z)->x+(z)->w) - MAX((x),(z)->x)) \ + * MAX(0, MIN((y)+(h),(z)->y+(z)->h) - MAX((y),(z)->y))) +#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]) || C->issticky) #define LENGTH(X) (sizeof X / sizeof X[0]) #define MOUSEMASK (BUTTONMASK|PointerMotionMask) #define WIDTH(X) ((X)->w + 2 * (X)->bw) @@ -132,7 +133,7 @@ struct Client { int basew, baseh, incw, inch, maxw, maxh, minw, minh; int bw, oldbw; unsigned int tags; - int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, issticky, isterminal, noswallow; + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, issticky, isterminal, noswallow, beingmoved; pid_t pid; Client *next; Client *snext; @@ -199,7 +200,7 @@ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interac static void arrange(Monitor *m); static void arrangemon(Monitor *m); static void attach(Client *c); -static void attachaside(Client *c); +static void attachbottom(Client *c); static void attachstack(Client *c); static void buttonpress(XEvent *e); static void checkotherwm(void); @@ -243,11 +244,13 @@ static void maprequest(XEvent *e); static void monocle(Monitor *m); static void motionnotify(XEvent *e); static void movemouse(const Arg *arg); -static Client *nexttagged(Client *c); +static void moveorplace(const Arg *arg); static Client *nexttiled(Client *c); +static void placemouse(const Arg *arg); static void pop(Client *); static void propertynotify(XEvent *e); static void quit(const Arg *arg); +static Client *recttoclient(int x, int y, int w, int h); static Monitor *recttomon(int x, int y, int w, int h); static void removesystrayicon(Client *i); static void resize(Client *c, int x, int y, int w, int h, int interact); @@ -302,6 +305,7 @@ static void updatetitle(Client *c); static void updatewindowtype(Client *c); static void updatewmhints(Client *c); static void view(const Arg *arg); +static void warp(const Client *c); static Client *wintoclient(Window w); static Monitor *wintomon(Window w); static Client *wintosystrayicon(Window w); @@ -309,6 +313,7 @@ static int xerror(Display *dpy, XErrorEvent *ee); static int xerrordummy(Display *dpy, XErrorEvent *ee); static int xerrorstart(Display *dpy, XErrorEvent *ee); static void xrdb(const Arg *arg); +static void movestack(const Arg *arg); static void zoom(const Arg *arg); static pid_t getparentprocess(pid_t p); @@ -523,14 +528,12 @@ attach(Client *c) } void -attachaside(Client *c) { - Client *at = nexttagged(c); - if(!at) { - attach(c); - return; - } - c->next = at->next; - at->next = c; +attachbottom(Client *c) +{ + Client **tc; + c->next = NULL; + for (tc = &c->mon->clients; *tc; tc = &(*tc)->next); + *tc = c; } void @@ -1241,6 +1244,7 @@ focusmon(const Arg *arg) unfocus(selmon->sel, 0); selmon = m; focus(NULL); + warp(selmon->sel); } void @@ -1256,6 +1260,7 @@ focusnthmon(const Arg *arg) unfocus(selmon->sel, 0); selmon = m; focus(NULL); + warp(selmon->sel); } void @@ -1480,6 +1485,45 @@ loadxrdb() xrdb = XrmGetStringDatabase(resm); if (xrdb != NULL) { + /* Load ^color* */ + XRDB_LOAD_COLOR("foreground", fgcolor); + XRDB_LOAD_COLOR("background", bgcolor); + XRDB_LOAD_COLOR("color0", color0); + XRDB_LOAD_COLOR("color1", color1); + XRDB_LOAD_COLOR("color2", color2); + XRDB_LOAD_COLOR("color3", color3); + XRDB_LOAD_COLOR("color4", color4); + XRDB_LOAD_COLOR("color5", color5); + XRDB_LOAD_COLOR("color6", color6); + XRDB_LOAD_COLOR("color7", color7); + XRDB_LOAD_COLOR("color8", color8); + XRDB_LOAD_COLOR("color9", color9); + XRDB_LOAD_COLOR("color10", color10); + XRDB_LOAD_COLOR("color11", color11); + XRDB_LOAD_COLOR("color12", color12); + XRDB_LOAD_COLOR("color13", color13); + XRDB_LOAD_COLOR("color14", color14); + XRDB_LOAD_COLOR("color15", color15); + /* Load ^*color* */ + XRDB_LOAD_COLOR("*foreground", fgcolor); + XRDB_LOAD_COLOR("*background", bgcolor); + XRDB_LOAD_COLOR("*color0", color0); + XRDB_LOAD_COLOR("*color1", color1); + XRDB_LOAD_COLOR("*color2", color2); + XRDB_LOAD_COLOR("*color3", color3); + XRDB_LOAD_COLOR("*color4", color4); + XRDB_LOAD_COLOR("*color5", color5); + XRDB_LOAD_COLOR("*color6", color6); + XRDB_LOAD_COLOR("*color7", color7); + XRDB_LOAD_COLOR("*color8", color8); + XRDB_LOAD_COLOR("*color9", color9); + XRDB_LOAD_COLOR("*color10", color10); + XRDB_LOAD_COLOR("*color11", color11); + XRDB_LOAD_COLOR("*color12", color12); + XRDB_LOAD_COLOR("*color13", color13); + XRDB_LOAD_COLOR("*color14", color14); + XRDB_LOAD_COLOR("*color15", color15); + /* Load ^*.color* */ XRDB_LOAD_COLOR("*.foreground", fgcolor); XRDB_LOAD_COLOR("*.background", bgcolor); XRDB_LOAD_COLOR("*.color0", color0); @@ -1556,7 +1600,7 @@ manage(Window w, XWindowAttributes *wa) c->isfloating = c->oldstate = trans != None || c->isfixed; if (c->isfloating) XRaiseWindow(dpy, c->win); - attachaside(c); + attachbottom(c); attachstack(c); XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, (unsigned char *) &(c->win), 1); @@ -1636,6 +1680,14 @@ motionnotify(XEvent *e) } void +moveorplace(const Arg *arg) { + if ((!selmon->lt[selmon->sellt]->arrange || (selmon->sel && selmon->sel->isfloating))) + movemouse(arg); + else + placemouse(arg); +} + +void movemouse(const Arg *arg) { int x, y, ocx, ocy, nx, ny; @@ -1696,16 +1748,6 @@ movemouse(const Arg *arg) } Client * -nexttagged(Client *c) { - Client *walked = c->mon->clients; - for(; - walked && (walked->isfloating || !ISVISIBLEONTAG(walked, c->tags)); - walked = walked->next - ); - return walked; -} - -Client * nexttiled(Client *c) { for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); @@ -1713,6 +1755,139 @@ nexttiled(Client *c) } void +placemouse(const Arg *arg) +{ + int x, y, px, py, ocx, ocy, nx = -9999, ny = -9999, freemove = 0; + Client *c, *r = NULL, *at, *prevr; + Monitor *m; + XEvent ev; + XWindowAttributes wa; + Time lasttime = 0; + int attachmode, prevattachmode; + attachmode = prevattachmode = -1; + + if (!(c = selmon->sel) || !c->mon->lt[c->mon->sellt]->arrange) /* no support for placemouse when floating layout is used */ + return; + if (c->isfullscreen) /* no support placing fullscreen windows by mouse */ + return; + restack(selmon); + prevr = c; + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) + return; + + c->isfloating = 0; + c->beingmoved = 1; + + XGetWindowAttributes(dpy, c->win, &wa); + ocx = wa.x; + ocy = wa.y; + + if (arg->i == 2) // warp cursor to client center + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, WIDTH(c) / 2, HEIGHT(c) / 2); + + if (!getrootptr(&x, &y)) + return; + + do { + XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); + switch (ev.type) { + case ConfigureRequest: + case Expose: + case MapRequest: + handler[ev.type](&ev); + break; + case MotionNotify: + if ((ev.xmotion.time - lasttime) <= (1000 / 60)) + continue; + lasttime = ev.xmotion.time; + + nx = ocx + (ev.xmotion.x - x); + ny = ocy + (ev.xmotion.y - y); + + if (!freemove && (abs(nx - ocx) > snap || abs(ny - ocy) > snap)) + freemove = 1; + + if (freemove) + XMoveWindow(dpy, c->win, nx, ny); + + if ((m = recttomon(ev.xmotion.x, ev.xmotion.y, 1, 1)) && m != selmon) + selmon = m; + + if (arg->i == 1) { // tiled position is relative to the client window center point + px = nx + wa.width / 2; + py = ny + wa.height / 2; + } else { // tiled position is relative to the mouse cursor + px = ev.xmotion.x; + py = ev.xmotion.y; + } + + r = recttoclient(px, py, 1, 1); + + if (!r || r == c) + break; + + attachmode = 0; // below + if (((float)(r->y + r->h - py) / r->h) > ((float)(r->x + r->w - px) / r->w)) { + if (abs(r->y - py) < r->h / 2) + attachmode = 1; // above + } else if (abs(r->x - px) < r->w / 2) + attachmode = 1; // above + + if ((r && r != prevr) || (attachmode != prevattachmode)) { + detachstack(c); + detach(c); + if (c->mon != r->mon) { + arrangemon(c->mon); + c->tags = r->mon->tagset[r->mon->seltags]; + } + + c->mon = r->mon; + r->mon->sel = r; + + if (attachmode) { + if (r == r->mon->clients) + attach(c); + else { + for (at = r->mon->clients; at->next != r; at = at->next); + c->next = at->next; + at->next = c; + } + } else { + c->next = r->next; + r->next = c; + } + + attachstack(c); + arrangemon(r->mon); + prevr = r; + prevattachmode = attachmode; + } + break; + } + } while (ev.type != ButtonRelease); + XUngrabPointer(dpy, CurrentTime); + + if ((m = recttomon(ev.xmotion.x, ev.xmotion.y, 1, 1)) && m != c->mon) { + detach(c); + detachstack(c); + arrangemon(c->mon); + c->mon = m; + c->tags = m->tagset[m->seltags]; + attach(c); + attachstack(c); + selmon = m; + } + + focus(c); + c->beingmoved = 0; + + if (nx != -9999) + resize(c, nx, ny, c->w, c->h, 0); + arrangemon(c->mon); +} + +void pop(Client *c) { detach(c); @@ -1776,6 +1951,21 @@ quit(const Arg *arg) running = 0; } +Client * +recttoclient(int x, int y, int w, int h) +{ + Client *c, *r = NULL; + int a, area = 0; + + for (c = nexttiled(selmon->clients); c; c = nexttiled(c->next)) { + if ((a = INTERSECTC(x, y, w, h, c)) > area) { + area = a; + r = c; + } + } + return r; +} + Monitor * recttomon(int x, int y, int w, int h) { @@ -1827,6 +2017,10 @@ resizeclient(Client *c, int x, int y, int w, int h) c->oldy = c->y; c->y = wc.y = y; c->oldw = c->w; c->w = wc.width = w; c->oldh = c->h; c->h = wc.height = h; + + if (c->beingmoved) + return; + wc.border_width = c->bw; if (((nexttiled(c->mon->clients) == c && !nexttiled(c->next)) || &monocle == c->mon->lt[c->mon->sellt]->arrange) @@ -1934,6 +2128,8 @@ restack(Monitor *m) } XSync(dpy, False); while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); + if (m == selmon && (m->tagset[m->seltags] & m->sel->tags) && selmon->lt[selmon->sellt] != &layouts[2]) + warp(m->sel); } void @@ -2061,7 +2257,7 @@ sendmon(Client *c, Monitor *m) detachstack(c); c->mon = m; c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ - attachaside(c); + attachbottom(c); attachstack(c); focus(NULL); arrange(NULL); @@ -2661,7 +2857,7 @@ updategeom(void) m->clients = c->next; detachstack(c); c->mon = mons; - attachaside(c); + attachbottom(c); attachstack(c); } if (m == selmon) @@ -3058,6 +3254,28 @@ swallowingclient(Window w) return NULL; } +void +warp(const Client *c) +{ + int x, y; + + if (!c) { + XWarpPointer(dpy, None, root, 0, 0, 0, 0, selmon->wx + selmon->ww/2, selmon->wy + selmon->wh/2); + return; + } + + if (!getrootptr(&x, &y) || + (x > c->x - c->bw && + y > c->y - c->bw && + x < c->x + c->w + c->bw*2 && + y < c->y + c->h + c->bw*2) || + (y > c->mon->by && y < c->mon->by + bh) || + (c->mon->topbar && !y)) + return; + + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); +} + Client * wintoclient(Window w) { @@ -3162,6 +3380,55 @@ systraytomon(Monitor *m) { } void +movestack(const Arg *arg) { + Client *c = NULL, *p = NULL, *pc = NULL, *i; + + if(arg->i > 0) { + /* find the client after selmon->sel */ + for(c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); + if(!c) + for(c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); + + } + else { + /* find the client before selmon->sel */ + for(i = selmon->clients; i != selmon->sel; i = i->next) + if(ISVISIBLE(i) && !i->isfloating) + c = i; + if(!c) + for(; i; i = i->next) + if(ISVISIBLE(i) && !i->isfloating) + c = i; + } + /* find the client before selmon->sel and c */ + for(i = selmon->clients; i && (!p || !pc); i = i->next) { + if(i->next == selmon->sel) + p = i; + if(i->next == c) + pc = i; + } + + /* swap c and selmon->sel selmon->clients in the selmon->clients list */ + if(c && c != selmon->sel) { + Client *temp = selmon->sel->next==c?selmon->sel:selmon->sel->next; + selmon->sel->next = c->next==selmon->sel?c:c->next; + c->next = temp; + + if(p && p != c) + p->next = c; + if(pc && pc != selmon->sel) + pc->next = selmon->sel; + + if(selmon->sel == selmon->clients) + selmon->clients = c; + else if(c == selmon->clients) + selmon->clients = selmon->sel; + + arrange(selmon); + } +} + +void zoom(const Arg *arg) { Client *c = selmon->sel; diff --git a/patches/dwm-attachaside-6.3.diff b/patches/dwm-attachaside-6.3.diff @@ -1,92 +0,0 @@ -diff --git a/dwm.c b/dwm.c -index 0362114..be7e7a6 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -49,7 +49,8 @@ - #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) - #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ - * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) --#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) -+#define ISVISIBLEONTAG(C, T) ((C->tags & T)) -+#define ISVISIBLE(C) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags]) - #define LENGTH(X) (sizeof X / sizeof X[0]) - #define MOUSEMASK (BUTTONMASK|PointerMotionMask) - #define WIDTH(X) ((X)->w + 2 * (X)->bw) -@@ -147,6 +148,7 @@ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interac - static void arrange(Monitor *m); - static void arrangemon(Monitor *m); - static void attach(Client *c); -+static void attachaside(Client *c); - static void attachstack(Client *c); - static void buttonpress(XEvent *e); - static void checkotherwm(void); -@@ -184,6 +186,7 @@ static void maprequest(XEvent *e); - static void monocle(Monitor *m); - static void motionnotify(XEvent *e); - static void movemouse(const Arg *arg); -+static Client *nexttagged(Client *c); - static Client *nexttiled(Client *c); - static void pop(Client *); - static void propertynotify(XEvent *e); -@@ -406,6 +409,17 @@ attach(Client *c) - } - - void -+attachaside(Client *c) { -+ Client *at = nexttagged(c); -+ if(!at) { -+ attach(c); -+ return; -+ } -+ c->next = at->next; -+ at->next = c; -+} -+ -+void - attachstack(Client *c) - { - c->snext = c->mon->stack; -@@ -1076,7 +1090,7 @@ manage(Window w, XWindowAttributes *wa) - c->isfloating = c->oldstate = trans != None || c->isfixed; - if (c->isfloating) - XRaiseWindow(dpy, c->win); -- attach(c); -+ attachaside(c); - attachstack(c); - XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); -@@ -1210,6 +1224,16 @@ movemouse(const Arg *arg) - } - - Client * -+nexttagged(Client *c) { -+ Client *walked = c->mon->clients; -+ for(; -+ walked && (walked->isfloating || !ISVISIBLEONTAG(walked, c->tags)); -+ walked = walked->next -+ ); -+ return walked; -+} -+ -+Client * - nexttiled(Client *c) - { - for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); -@@ -1434,7 +1458,7 @@ sendmon(Client *c, Monitor *m) - detachstack(c); - c->mon = m; - c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ -- attach(c); -+ attachaside(c); - attachstack(c); - focus(NULL); - arrange(NULL); -@@ -1891,7 +1915,7 @@ updategeom(void) - m->clients = c->next; - detachstack(c); - c->mon = mons; -- attach(c); -+ attachaside(c); - attachstack(c); - } - if (m == selmon) diff --git a/patches/dwm-attachbottom-20201227-61bb8b2.diff b/patches/dwm-attachbottom-20201227-61bb8b2.diff @@ -0,0 +1,67 @@ +From eea05f94baf707114ea882e8755520ba30d73cb2 Mon Sep 17 00:00:00 2001 +From: Szabolcs Szucs <contact@szabolcsszucs.com> +Date: Sat, 26 Dec 2020 21:17:40 +0100 +Subject: [PATCH] attachbottom patch + +--- + dwm.c | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +diff --git a/dwm.c b/dwm.c +index 664c527..7ee3566 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -147,6 +147,7 @@ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interac + static void arrange(Monitor *m); + static void arrangemon(Monitor *m); + static void attach(Client *c); ++static void attachbottom(Client *c); + static void attachstack(Client *c); + static void buttonpress(XEvent *e); + static void checkotherwm(void); +@@ -407,6 +408,15 @@ attach(Client *c) + c->mon->clients = c; + } + ++void ++attachbottom(Client *c) ++{ ++ Client **tc; ++ c->next = NULL; ++ for (tc = &c->mon->clients; *tc; tc = &(*tc)->next); ++ *tc = c; ++} ++ + void + attachstack(Client *c) + { +@@ -1063,7 +1073,7 @@ manage(Window w, XWindowAttributes *wa) + c->isfloating = c->oldstate = trans != None || c->isfixed; + if (c->isfloating) + XRaiseWindow(dpy, c->win); +- attach(c); ++ attachbottom(c); + attachstack(c); + XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); +@@ -1418,7 +1428,7 @@ sendmon(Client *c, Monitor *m) + detachstack(c); + c->mon = m; + c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ +- attach(c); ++ attachbottom(c); + attachstack(c); + focus(NULL); + arrange(NULL); +@@ -1900,7 +1910,7 @@ updategeom(void) + m->clients = c->next; + detachstack(c); + c->mon = mons; +- attach(c); ++ attachbottom(c); + attachstack(c); + } + if (m == selmon) +-- +2.29.2 + diff --git a/patches/dwm-movestack-20211115-a786211.diff b/patches/dwm-movestack-20211115-a786211.diff @@ -0,0 +1,95 @@ +From 9a4037dc0ef56f91c009317e78e9e3790dafbb58 Mon Sep 17 00:00:00 2001 +From: BrunoCooper17 <BrunoCooper17@outlook.com> +Date: Mon, 15 Nov 2021 14:04:53 -0600 +Subject: [PATCH] MoveStack patch + +This plugin allows you to move clients around in the stack and swap them +with the master. It emulates the behavior off mod+shift+j and mod+shift+k +in Xmonad. movestack(+1) will swap the client with the current focus with +the next client. movestack(-1) will swap the client with the current focus +with the previous client. +--- + config.def.h | 3 +++ + movestack.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 51 insertions(+) + create mode 100644 movestack.c + +diff --git a/config.def.h b/config.def.h +index a2ac963..33efa5b 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -60,6 +60,7 @@ static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() + static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; + static const char *termcmd[] = { "st", NULL }; + ++#include "movestack.c" + static Key keys[] = { + /* modifier key function argument */ + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, +@@ -71,6 +72,8 @@ static Key keys[] = { + { MODKEY, XK_d, incnmaster, {.i = -1 } }, + { MODKEY, XK_h, setmfact, {.f = -0.05} }, + { MODKEY, XK_l, setmfact, {.f = +0.05} }, ++ { MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } }, ++ { MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } }, + { MODKEY, XK_Return, zoom, {0} }, + { MODKEY, XK_Tab, view, {0} }, + { MODKEY|ShiftMask, XK_c, killclient, {0} }, +diff --git a/movestack.c b/movestack.c +new file mode 100644 +index 0000000..520f4ae +--- /dev/null ++++ b/movestack.c +@@ -0,0 +1,48 @@ ++void ++movestack(const Arg *arg) { ++ Client *c = NULL, *p = NULL, *pc = NULL, *i; ++ ++ if(arg->i > 0) { ++ /* find the client after selmon->sel */ ++ for(c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); ++ if(!c) ++ for(c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next); ++ ++ } ++ else { ++ /* find the client before selmon->sel */ ++ for(i = selmon->clients; i != selmon->sel; i = i->next) ++ if(ISVISIBLE(i) && !i->isfloating) ++ c = i; ++ if(!c) ++ for(; i; i = i->next) ++ if(ISVISIBLE(i) && !i->isfloating) ++ c = i; ++ } ++ /* find the client before selmon->sel and c */ ++ for(i = selmon->clients; i && (!p || !pc); i = i->next) { ++ if(i->next == selmon->sel) ++ p = i; ++ if(i->next == c) ++ pc = i; ++ } ++ ++ /* swap c and selmon->sel selmon->clients in the selmon->clients list */ ++ if(c && c != selmon->sel) { ++ Client *temp = selmon->sel->next==c?selmon->sel:selmon->sel->next; ++ selmon->sel->next = c->next==selmon->sel?c:c->next; ++ c->next = temp; ++ ++ if(p && p != c) ++ p->next = c; ++ if(pc && pc != selmon->sel) ++ pc->next = selmon->sel; ++ ++ if(selmon->sel == selmon->clients) ++ selmon->clients = c; ++ else if(c == selmon->clients) ++ selmon->clients = selmon->sel; ++ ++ arrange(selmon); ++ } ++} +\ No newline at end of file +-- +2.33.1 + diff --git a/patches/dwm-placemouse-6.3.diff b/patches/dwm-placemouse-6.3.diff @@ -0,0 +1,259 @@ +From 399cb51f86d259d0d15d2db767d31c9e030c0528 Mon Sep 17 00:00:00 2001 +From: Bakkeby <bakkeby@gmail.com> +Date: Mon, 10 Jan 2022 13:18:37 +0100 +Subject: [PATCH] Adding placemouse patch + +--- + config.def.h | 12 +++- + dwm.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 177 insertions(+), 1 deletion(-) + +diff --git a/config.def.h b/config.def.h +index a2ac963..caaebf6 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -105,7 +105,17 @@ static Button buttons[] = { + { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, + { ClkWinTitle, 0, Button2, zoom, {0} }, + { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, +- { ClkClientWin, MODKEY, Button1, movemouse, {0} }, ++ /* placemouse options, choose which feels more natural: ++ * 0 - tiled position is relative to mouse cursor ++ * 1 - tiled postiion is relative to window center ++ * 2 - mouse pointer warps to window center ++ * ++ * The moveorplace uses movemouse or placemouse depending on the floating state ++ * of the selected client. Set up individual keybindings for the two if you want ++ * to control these separately (i.e. to retain the feature to move a tiled window ++ * into a floating position). ++ */ ++ { ClkClientWin, MODKEY, Button1, moveorplace, {.i = 1} }, + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, + { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, + { ClkTagBar, 0, Button1, view, {0} }, +diff --git a/dwm.c b/dwm.c +index a96f33c..5d57e18 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -49,6 +49,8 @@ + #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) + #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ + * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) ++#define INTERSECTC(x,y,w,h,z) (MAX(0, MIN((x)+(w),(z)->x+(z)->w) - MAX((x),(z)->x)) \ ++ * MAX(0, MIN((y)+(h),(z)->y+(z)->h) - MAX((y),(z)->y))) + #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) + #define LENGTH(X) (sizeof X / sizeof X[0]) + #define MOUSEMASK (BUTTONMASK|PointerMotionMask) +@@ -93,6 +95,7 @@ struct Client { + int bw, oldbw; + unsigned int tags; + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; ++ int beingmoved; + Client *next; + Client *snext; + Monitor *mon; +@@ -184,10 +187,13 @@ static void maprequest(XEvent *e); + static void monocle(Monitor *m); + static void motionnotify(XEvent *e); + static void movemouse(const Arg *arg); ++static void moveorplace(const Arg *arg); + static Client *nexttiled(Client *c); ++static void placemouse(const Arg *arg); + static void pop(Client *); + static void propertynotify(XEvent *e); + static void quit(const Arg *arg); ++static Client *recttoclient(int x, int y, int w, int h); + static Monitor *recttomon(int x, int y, int w, int h); + static void resize(Client *c, int x, int y, int w, int h, int interact); + static void resizeclient(Client *c, int x, int y, int w, int h); +@@ -1136,6 +1142,14 @@ motionnotify(XEvent *e) + mon = m; + } + ++void ++moveorplace(const Arg *arg) { ++ if ((!selmon->lt[selmon->sellt]->arrange || (selmon->sel && selmon->sel->isfloating))) ++ movemouse(arg); ++ else ++ placemouse(arg); ++} ++ + void + movemouse(const Arg *arg) + { +@@ -1203,6 +1217,139 @@ nexttiled(Client *c) + return c; + } + ++void ++placemouse(const Arg *arg) ++{ ++ int x, y, px, py, ocx, ocy, nx = -9999, ny = -9999, freemove = 0; ++ Client *c, *r = NULL, *at, *prevr; ++ Monitor *m; ++ XEvent ev; ++ XWindowAttributes wa; ++ Time lasttime = 0; ++ int attachmode, prevattachmode; ++ attachmode = prevattachmode = -1; ++ ++ if (!(c = selmon->sel) || !c->mon->lt[c->mon->sellt]->arrange) /* no support for placemouse when floating layout is used */ ++ return; ++ if (c->isfullscreen) /* no support placing fullscreen windows by mouse */ ++ return; ++ restack(selmon); ++ prevr = c; ++ if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, ++ None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) ++ return; ++ ++ c->isfloating = 0; ++ c->beingmoved = 1; ++ ++ XGetWindowAttributes(dpy, c->win, &wa); ++ ocx = wa.x; ++ ocy = wa.y; ++ ++ if (arg->i == 2) // warp cursor to client center ++ XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, WIDTH(c) / 2, HEIGHT(c) / 2); ++ ++ if (!getrootptr(&x, &y)) ++ return; ++ ++ do { ++ XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); ++ switch (ev.type) { ++ case ConfigureRequest: ++ case Expose: ++ case MapRequest: ++ handler[ev.type](&ev); ++ break; ++ case MotionNotify: ++ if ((ev.xmotion.time - lasttime) <= (1000 / 60)) ++ continue; ++ lasttime = ev.xmotion.time; ++ ++ nx = ocx + (ev.xmotion.x - x); ++ ny = ocy + (ev.xmotion.y - y); ++ ++ if (!freemove && (abs(nx - ocx) > snap || abs(ny - ocy) > snap)) ++ freemove = 1; ++ ++ if (freemove) ++ XMoveWindow(dpy, c->win, nx, ny); ++ ++ if ((m = recttomon(ev.xmotion.x, ev.xmotion.y, 1, 1)) && m != selmon) ++ selmon = m; ++ ++ if (arg->i == 1) { // tiled position is relative to the client window center point ++ px = nx + wa.width / 2; ++ py = ny + wa.height / 2; ++ } else { // tiled position is relative to the mouse cursor ++ px = ev.xmotion.x; ++ py = ev.xmotion.y; ++ } ++ ++ r = recttoclient(px, py, 1, 1); ++ ++ if (!r || r == c) ++ break; ++ ++ attachmode = 0; // below ++ if (((float)(r->y + r->h - py) / r->h) > ((float)(r->x + r->w - px) / r->w)) { ++ if (abs(r->y - py) < r->h / 2) ++ attachmode = 1; // above ++ } else if (abs(r->x - px) < r->w / 2) ++ attachmode = 1; // above ++ ++ if ((r && r != prevr) || (attachmode != prevattachmode)) { ++ detachstack(c); ++ detach(c); ++ if (c->mon != r->mon) { ++ arrangemon(c->mon); ++ c->tags = r->mon->tagset[r->mon->seltags]; ++ } ++ ++ c->mon = r->mon; ++ r->mon->sel = r; ++ ++ if (attachmode) { ++ if (r == r->mon->clients) ++ attach(c); ++ else { ++ for (at = r->mon->clients; at->next != r; at = at->next); ++ c->next = at->next; ++ at->next = c; ++ } ++ } else { ++ c->next = r->next; ++ r->next = c; ++ } ++ ++ attachstack(c); ++ arrangemon(r->mon); ++ prevr = r; ++ prevattachmode = attachmode; ++ } ++ break; ++ } ++ } while (ev.type != ButtonRelease); ++ XUngrabPointer(dpy, CurrentTime); ++ ++ if ((m = recttomon(ev.xmotion.x, ev.xmotion.y, 1, 1)) && m != c->mon) { ++ detach(c); ++ detachstack(c); ++ arrangemon(c->mon); ++ c->mon = m; ++ c->tags = m->tagset[m->seltags]; ++ attach(c); ++ attachstack(c); ++ selmon = m; ++ } ++ ++ focus(c); ++ c->beingmoved = 0; ++ ++ if (nx != -9999) ++ resize(c, nx, ny, c->w, c->h, 0); ++ arrangemon(c->mon); ++} ++ + void + pop(Client *c) + { +@@ -1255,6 +1402,21 @@ quit(const Arg *arg) + running = 0; + } + ++Client * ++recttoclient(int x, int y, int w, int h) ++{ ++ Client *c, *r = NULL; ++ int a, area = 0; ++ ++ for (c = nexttiled(selmon->clients); c; c = nexttiled(c->next)) { ++ if ((a = INTERSECTC(x, y, w, h, c)) > area) { ++ area = a; ++ r = c; ++ } ++ } ++ return r; ++} ++ + Monitor * + recttomon(int x, int y, int w, int h) + { +@@ -1285,6 +1447,10 @@ resizeclient(Client *c, int x, int y, int w, int h) + c->oldy = c->y; c->y = wc.y = y; + c->oldw = c->w; c->w = wc.width = w; + c->oldh = c->h; c->h = wc.height = h; ++ ++ if (c->beingmoved) ++ return; ++ + wc.border_width = c->bw; + XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); + configure(c); +-- +2.19.1 + diff --git a/patches/dwm-warp-6.2.diff b/patches/dwm-warp-6.2.diff @@ -0,0 +1,58 @@ +diff --git a/dwm.c b/dwm.c +index 4465af1..bf74f60 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -227,6 +227,7 @@ static void updatetitle(Client *c); + static void updatewindowtype(Client *c); + static void updatewmhints(Client *c); + static void view(const Arg *arg); ++static void warp(const Client *c); + static Client *wintoclient(Window w); + static Monitor *wintomon(Window w); + static int xerror(Display *dpy, XErrorEvent *ee); +@@ -827,6 +828,7 @@ focusmon(const Arg *arg) + unfocus(selmon->sel, 0); + selmon = m; + focus(NULL); ++ warp(selmon->sel); + } + + void +@@ -1367,6 +1369,8 @@ restack(Monitor *m) + } + XSync(dpy, False); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); ++ if (m == selmon && (m->tagset[m->seltags] & m->sel->tags) && selmon->lt[selmon->sellt] != &layouts[2]) ++ warp(m->sel); + } + + void +@@ -2044,6 +2048,28 @@ view(const Arg *arg) + arrange(selmon); + } + ++void ++warp(const Client *c) ++{ ++ int x, y; ++ ++ if (!c) { ++ XWarpPointer(dpy, None, root, 0, 0, 0, 0, selmon->wx + selmon->ww/2, selmon->wy + selmon->wh/2); ++ return; ++ } ++ ++ if (!getrootptr(&x, &y) || ++ (x > c->x - c->bw && ++ y > c->y - c->bw && ++ x < c->x + c->w + c->bw*2 && ++ y < c->y + c->h + c->bw*2) || ++ (y > c->mon->by && y < c->mon->by + bh) || ++ (c->mon->topbar && !y)) ++ return; ++ ++ XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); ++} ++ + Client * + wintoclient(Window w) + {