From 1a9fcf5fdd6e9adccd46b0cec15ad57f77f5b6dd Mon Sep 17 00:00:00 2001 From: xAlpharax <42233094+xAlpharax@users.noreply.github.com> Date: Wed, 16 Aug 2023 23:49:08 +0300 Subject: Patching better gaps with fullgaps. Everything is stable in this commit. Changes to be committed: modified: config.def.h modified: config.def.h.orig modified: config.def.h.rej modified: config.h modified: drw.c modified: drw.c.orig deleted: dwm.1.orig modified: dwm.c modified: dwm.c.orig modified: dwm.c.rej renamed: patches_new/dwm-fullgaps-6.4.diff -> patches/dwm-fullgaps-6.4.diff deleted: patches/dwm-uselessgap-20211119-58414bee958f2.diff renamed: patches_new/dwm-tag-preview-6.3.diff -> patches_huge/dwm-tag-preview-6.3.diff renamed: patches_new/dwm-winicon-6.3-v2.1.diff -> patches_huge/dwm-winicon-6.3-v2.1.diff modified: patches_new/dwm-noborderflicker-20211227-8657affa2a61.diff --- config.def.h | 8 +- config.def.h.orig | 11 +- config.def.h.rej | 32 +- config.h | 173 +++++----- drw.c | 2 + drw.c.orig | 2 - dwm.1.orig | 179 ---------- dwm.c | 170 ++++++---- dwm.c.orig | 162 ++++++--- dwm.c.rej | 33 +- patches/dwm-fullgaps-6.4.diff | 94 ++++++ patches/dwm-uselessgap-20211119-58414bee958f2.diff | 101 ------ patches_huge/dwm-tag-preview-6.3.diff | 315 +++++++++++++++++ patches_huge/dwm-winicon-6.3-v2.1.diff | 371 +++++++++++++++++++++ patches_new/dwm-fullgaps-6.4.diff | 94 ------ .../dwm-noborderflicker-20211227-8657affa2a61.diff | 42 +++ patches_new/dwm-tag-preview-6.3.diff | 315 ----------------- patches_new/dwm-winicon-6.3-v2.1.diff | 371 --------------------- 18 files changed, 1189 insertions(+), 1286 deletions(-) delete mode 100644 dwm.1.orig create mode 100644 patches/dwm-fullgaps-6.4.diff delete mode 100644 patches/dwm-uselessgap-20211119-58414bee958f2.diff create mode 100644 patches_huge/dwm-tag-preview-6.3.diff create mode 100644 patches_huge/dwm-winicon-6.3-v2.1.diff delete mode 100644 patches_new/dwm-fullgaps-6.4.diff delete mode 100644 patches_new/dwm-tag-preview-6.3.diff delete mode 100644 patches_new/dwm-winicon-6.3-v2.1.diff diff --git a/config.def.h b/config.def.h index b13e2e6..6d4a67b 100644 --- a/config.def.h +++ b/config.def.h @@ -2,7 +2,7 @@ /* appearance */ static const unsigned int borderpx = 1; /* border pixel of windows */ -static const unsigned int gappx = 6; /* gaps between windows */ +static const unsigned int gappx = 5; /* gaps between windows */ static const unsigned int snap = 32; /* snap pixel */ static const int showbar = 1; /* 0 means no bar */ static const int topbar = 1; /* 0 means bottom bar */ @@ -21,6 +21,7 @@ static const char *colors[][3] = { /* tagging */ static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; +static const char *alttags[] = { "<01>", "<02>", "<03>", "<04>", "<05>" }; static const Rule rules[] = { /* xprop(1): @@ -35,7 +36,7 @@ static const Rule rules[] = { /* layout(s) */ static const float mfact = 0.55; /* 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 resizehints = 1; /* 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[] = { @@ -90,6 +91,9 @@ static const Key keys[] = { { MODKEY, XK_period, focusmon, {.i = +1 } }, { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, + { MODKEY, XK_minus, setgaps, {.i = -1 } }, + { MODKEY, XK_equal, setgaps, {.i = +1 } }, + { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } }, { MODKEY, XK_Right, viewnext, {0} }, { MODKEY, XK_Left, viewprev, {0} }, { MODKEY|ShiftMask, XK_Right, tagtonext, {0} }, diff --git a/config.def.h.orig b/config.def.h.orig index 14bcdf7..3d8ca89 100644 --- a/config.def.h.orig +++ b/config.def.h.orig @@ -2,7 +2,7 @@ /* appearance */ static const unsigned int borderpx = 1; /* border pixel of windows */ -static const unsigned int gappx = 6; /* gaps between windows */ +static const unsigned int gappx = 5; /* gaps between windows */ static const unsigned int snap = 32; /* snap pixel */ static const int showbar = 1; /* 0 means no bar */ static const int topbar = 1; /* 0 means bottom bar */ @@ -35,7 +35,7 @@ static const Rule rules[] = { /* layout(s) */ static const float mfact = 0.55; /* 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 resizehints = 1; /* 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[] = { @@ -90,6 +90,13 @@ static const Key keys[] = { { MODKEY, XK_period, focusmon, {.i = +1 } }, { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, + { MODKEY, XK_minus, setgaps, {.i = -1 } }, + { MODKEY, XK_equal, setgaps, {.i = +1 } }, + { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } }, + { MODKEY, XK_Right, viewnext, {0} }, + { MODKEY, XK_Left, viewprev, {0} }, + { MODKEY|ShiftMask, XK_Right, tagtonext, {0} }, + { MODKEY|ShiftMask, XK_Left, tagtoprev, {0} }, TAGKEYS( XK_1, 0) TAGKEYS( XK_2, 1) TAGKEYS( XK_3, 2) diff --git a/config.def.h.rej b/config.def.h.rej index f117a17..96015d4 100644 --- a/config.def.h.rej +++ b/config.def.h.rej @@ -1,19 +1,13 @@ ---- config.def.h -+++ 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} }, +--- config.def.h 2021-10-02 14:22:28.034782413 +0100 ++++ config.def.h 2021-10-02 14:22:28.044723532 +0100 +@@ -84,6 +84,10 @@ static Key keys[] = { + { MODKEY, XK_period, focusmon, {.i = +1 } }, + { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, + { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, ++ { MODKEY, XK_Right, viewnext, {0} }, ++ { MODKEY, XK_Left, viewprev, {0} }, ++ { MODKEY|ShiftMask, XK_Right, tagtonext, {0} }, ++ { MODKEY|ShiftMask, XK_Left, tagtoprev, {0} }, + TAGKEYS( XK_1, 0) + TAGKEYS( XK_2, 1) + TAGKEYS( XK_3, 2) diff --git a/config.h b/config.h index bed0136..6d4a67b 100644 --- a/config.h +++ b/config.h @@ -1,47 +1,49 @@ -/* appearance and colorscheme */ -static const unsigned int borderpx = 2; /* border pixel of windows */ -static const unsigned int snap = 4; /* snap pixel */ -static const unsigned int gappx = 4; /* tiling spacing */ -static const int showbar = 1; /* 0 means no bar */ -static const int topbar = 1; /* 0 means bottom bar */ -static const char *fonts[] = { "inconsolata:pixelsize=17" }; -static const char dmenufont[] = "inconsolata:pixelsize=17"; - -static const char col_gray1[] = "#0a001f"; // darkk purple -static const char col_gray2[] = "#6660d2"; // light purple -static const char col_cyan[] = "#ace6f0"; // light cyan - +/* See LICENSE file for copyright and license details. */ + +/* appearance */ +static const unsigned int borderpx = 1; /* border pixel of windows */ +static const unsigned int gappx = 5; /* gaps between windows */ +static const unsigned int snap = 32; /* snap pixel */ +static const int showbar = 1; /* 0 means no bar */ +static const int topbar = 1; /* 0 means bottom bar */ +static const char *fonts[] = { "monospace:size=10" }; +static const char dmenufont[] = "monospace:size=10"; +static const char col_gray1[] = "#222222"; +static const char col_gray2[] = "#444444"; +static const char col_gray3[] = "#bbbbbb"; +static const char col_gray4[] = "#eeeeee"; +static const char col_cyan[] = "#005577"; static const char *colors[][3] = { /* fg bg border */ - [SchemeNorm] = { col_cyan, col_gray1, col_gray2 }, // unselected - [SchemeSel] = { col_gray1, col_gray2, col_cyan }, // selected + [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, + [SchemeSel] = { col_gray4, col_cyan, col_cyan }, }; -/* workspaces */ +/* tagging */ static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; -static const char *alttags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; +static const char *alttags[] = { "<01>", "<02>", "<03>", "<04>", "<05>" }; static const Rule rules[] = { /* xprop(1): * WM_CLASS(STRING) = instance, class * WM_NAME(STRING) = title */ - - /* class instance title tags mask isfloating monitor */ - { NULL, NULL, NULL, 0, False, -1 }, - + /* class instance title tags mask isfloating monitor */ + { "Gimp", NULL, NULL, 0, 1, -1 }, + { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, }; -static const float mfact = 0.5; /* factor of master area size [0.05..0.95] */ +/* layout(s) */ +static const float mfact = 0.55; /* 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 resizehints = 1; /* 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 */ - { "[]=", tile }, /* first entry is default */ - { "><>", NULL }, /* no layout function means floating behavior */ - { "[M]", monocle }, + /* symbol arrange function */ + { "[]=", tile }, /* first entry is default */ + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, }; /* key definitions */ @@ -55,70 +57,73 @@ static const Layout layouts[] = { /* 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", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_cyan, "-sb", col_gray2, "-sf", col_gray1, NULL }; +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_Return, spawn, {.v = termcmd } }, - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, - { MODKEY|ShiftMask, XK_f, spawn, SHCMD("brave") }, - { MODKEY, XK_f, spawn, SHCMD("firefox") }, - { MODKEY|ShiftMask, XK_l, spawn, SHCMD("librewolf") }, - { MODKEY, XK_d, spawn, SHCMD("discord") }, - { MODKEY|ShiftMask, XK_x, spawn, SHCMD("xkill") }, - { MODKEY|ShiftMask, XK_b, spawn, SHCMD("bmenu") }, - { MODKEY, XK_q, spawn, SHCMD("pmenu") }, - - { MODKEY, XK_Tab, focusstack, {.i = +1 } }, - - { MODKEY, XK_b, togglebar, {0} }, - { MODKEY, XK_m, togglefullscr, {0} }, - { MODKEY, XK_x, killclient, {0} }, - - { MODKEY, XK_k, incnmaster, {.i = +1 } }, - { MODKEY, XK_j, incnmaster, {.i = -1 } }, - { MODKEY|ShiftMask, XK_k, movestack, {.i = +1 } }, - { MODKEY|ShiftMask, XK_j, movestack, {.i = -1 } }, - - { MODKEY, XK_h, setmfact, {.f = -0.01} }, - { MODKEY, XK_l, setmfact, {.f = +0.01} }, - - { MODKEY, XK_space, setlayout, {.v = &layouts[0]} }, - { MODKEY|ShiftMask, XK_space, setlayout, {.v = &layouts[1]} }, - { MODKEY|ControlMask, XK_space, setlayout, {.v = &layouts[2]} }, - - { MODKEY, XK_0, view, {.ui = ~0 } }, - - { MODKEY, XK_Right, viewnext, {0} }, - { MODKEY, XK_Left, viewprev, {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) +static const Key keys[] = { + /* modifier key function argument */ + { MODKEY, XK_p, 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|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} }, + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY|ShiftMask, XK_f, togglefullscr, {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_minus, setgaps, {.i = -1 } }, + { MODKEY, XK_equal, setgaps, {.i = +1 } }, + { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } }, + { MODKEY, XK_Right, viewnext, {0} }, + { MODKEY, XK_Left, viewprev, {0} }, + { MODKEY|ShiftMask, XK_Right, tagtonext, {0} }, + { MODKEY|ShiftMask, XK_Left, tagtoprev, {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_q, quit, {0} }, }; /* button definitions */ /* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ -static Button buttons[] = { +static const Button buttons[] = { /* click event mask button function argument */ - { ClkLtSymbol, 0, Button1, setlayout, {0} }, - { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, - { 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, setlayout, {0} }, + { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, + { 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} }, }; + diff --git a/drw.c b/drw.c index a58a2b4..163eb51 100644 --- a/drw.c +++ b/drw.c @@ -190,6 +190,8 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname) DefaultColormap(drw->dpy, drw->screen), clrname, dest)) die("error, cannot allocate color '%s'", clrname); + + dest->pixel |= 0xff << 24; } /* Wrapper to create color schemes. The caller has to call free(3) on the diff --git a/drw.c.orig b/drw.c.orig index 163eb51..a58a2b4 100644 --- a/drw.c.orig +++ b/drw.c.orig @@ -190,8 +190,6 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname) DefaultColormap(drw->dpy, drw->screen), clrname, dest)) die("error, cannot allocate color '%s'", clrname); - - dest->pixel |= 0xff << 24; } /* Wrapper to create color schemes. The caller has to call free(3) on the diff --git a/dwm.1.orig b/dwm.1.orig deleted file mode 100644 index 3d310ac..0000000 --- a/dwm.1.orig +++ /dev/null @@ -1,179 +0,0 @@ -.TH DWM 1 dwm\-VERSION -.SH NAME -dwm \- dynamic window manager -.SH SYNOPSIS -.B dwm -.RB [ \-v ] -.SH DESCRIPTION -dwm is a dynamic window manager for X. It manages windows in tiled, monocle -and floating layouts. Either layout can be applied dynamically, optimising the -environment for the application in use and the task performed. -.P -In tiled layouts windows are managed in a master and stacking area. The master -area on the left contains one window by default, and the stacking area on the -right contains all other windows. The number of master area windows can be -adjusted from zero to an arbitrary number. In monocle layout all windows are -maximised to the screen size. In floating layout windows can be resized and -moved freely. Dialog windows are always managed floating, regardless of the -layout applied. -.P -Windows are grouped by tags. Each window can be tagged with one or multiple -tags. Selecting certain tags displays all windows with these tags. -.P -Each screen contains a small status bar which displays all available tags, the -layout, the title of the focused window, and the text read from the root window -name property, if the screen is focused. A floating window is indicated with an -empty square and a maximised floating window is indicated with a filled square -before the windows title. The selected tags are indicated with a different -color. The tags of the focused window are indicated with a filled square in the -top left corner. The tags which are applied to one or more windows are -indicated with an empty square in the top left corner. -.P -dwm draws a small border around windows to indicate the focus state. -.SH OPTIONS -.TP -.B \-v -prints version information to stderr, then exits. -.SH USAGE -.SS Status bar -.TP -.B X root window name -is read and displayed in the status text area. It can be set with the -.BR xsetroot (1) -command. -.TP -.B Button1 -click on a tag label to display all windows with that tag, click on the layout -label toggles between tiled and floating layout. -.TP -.B Button3 -click on a tag label adds/removes all windows with that tag to/from the view. -.TP -.B Mod1\-Button1 -click on a tag label applies that tag to the focused window. -.TP -.B Mod1\-Button3 -click on a tag label adds/removes that tag to/from the focused window. -.SS Keyboard commands -.TP -.B Mod1\-Shift\-Return -Start -.BR st(1). -.TP -.B Mod1\-p -Spawn -.BR dmenu(1) -for launching other programs. -.TP -.B Mod1\-, -Focus previous screen, if any. -.TP -.B Mod1\-. -Focus next screen, if any. -.TP -.B Mod1\-Shift\-, -Send focused window to previous screen, if any. -.TP -.B Mod1\-Shift\-. -Send focused window to next screen, if any. -.TP -.B Mod1\-b -Toggles bar on and off. -.TP -.B Mod1\-t -Sets tiled layout. -.TP -.B Mod1\-f -Sets floating layout. -.TP -.B Mod1\-m -Sets monocle layout. -.TP -.B Mod1\-space -Toggles between current and previous layout. -.TP -.B Mod1\-j -Focus next window. -.TP -.B Mod1\-k -Focus previous window. -.TP -.B Mod1\-i -Increase number of windows in master area. -.TP -.B Mod1\-d -Decrease number of windows in master area. -.TP -.B Mod1\-l -Increase master area size. -.TP -.B Mod1\-h -Decrease master area size. -.TP -.B Mod1\-Return -Zooms/cycles focused window to/from master area (tiled layouts only). -.TP -.B Mod1\-Shift\-c -Close focused window. -.TP -.B Mod1\-Shift\-f -Toggle fullscreen for focused window. -.TP -.B Mod1\-Shift\-space -Toggle focused window between tiled and floating state. -.TP -.B Mod1\-Tab -Toggles to the previously selected tags. -.TP -.B Mod1\-Shift\-[1..n] -Apply nth tag to focused window. -.TP -.B Mod1\-Shift\-0 -Apply all tags to focused window. -.TP -.B Mod1\-Control\-Shift\-[1..n] -Add/remove nth tag to/from focused window. -.TP -.B Mod1\-[1..n] -View all windows with nth tag. -.TP -.B Mod1\-0 -View all windows with any tag. -.TP -.B Mod1\-Control\-[1..n] -Add/remove all windows with nth tag to/from the view. -.TP -.B Mod1\-Shift\-q -Quit dwm. -.SS Mouse commands -.TP -.B Mod1\-Button1 -Move focused window while dragging. Tiled windows will be toggled to the floating state. -.TP -.B Mod1\-Button2 -Toggles focused window between floating and tiled state. -.TP -.B Mod1\-Button3 -Resize focused window while dragging. Tiled windows will be toggled to the floating state. -.SH CUSTOMIZATION -dwm is customized by creating a custom config.h and (re)compiling the source -code. This keeps it fast, secure and simple. -.SH SEE ALSO -.BR dmenu (1), -.BR st (1) -.SH ISSUES -Java applications which use the XToolkit/XAWT backend may draw grey windows -only. The XToolkit/XAWT backend breaks ICCCM-compliance in recent JDK 1.5 and early -JDK 1.6 versions, because it assumes a reparenting window manager. Possible workarounds -are using JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or setting the -environment variable -.BR AWT_TOOLKIT=MToolkit -(to use the older Motif backend instead) or running -.B xprop -root -f _NET_WM_NAME 32a -set _NET_WM_NAME LG3D -or -.B wmname LG3D -(to pretend that a non-reparenting window manager is running that the -XToolkit/XAWT backend can recognize) or when using OpenJDK setting the environment variable -.BR _JAVA_AWT_WM_NONREPARENTING=1 . -.SH BUGS -Send all bug reports with a patch to hackers@suckless.org. diff --git a/dwm.c b/dwm.c index c5ee1d0..3f0be88 100644 --- a/dwm.c +++ b/dwm.c @@ -52,8 +52,8 @@ #define ISVISIBLE(C) ((C->tags & 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 + gappx) -#define HEIGHT(X) ((X)->h + 2 * (X)->bw + gappx) +#define WIDTH(X) ((X)->w + 2 * (X)->bw) +#define HEIGHT(X) ((X)->h + 2 * (X)->bw) #define TAGMASK ((1 << LENGTH(tags)) - 1) #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) @@ -111,6 +111,7 @@ typedef struct { void (*arrange)(Monitor *); } Layout; +typedef struct Pertag Pertag; struct Monitor { char ltsymbol[16]; float mfact; @@ -131,6 +132,7 @@ struct Monitor { Monitor *next; Window barwin; const Layout *lt[2]; + Pertag *pertag; }; typedef struct { @@ -281,6 +283,15 @@ static Window root, wmcheckwin; /* configuration, allows nested code to access above variables */ #include "config.h" +struct Pertag { + unsigned int curtag, prevtag; /* current and previous tag */ + int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */ + float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */ + unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */ + const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */ + int showbars[LENGTH(tags) + 1]; /* display bar for the current tag */ +}; + /* compile-time check if all tags fit into an unsigned int bit array. */ struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; @@ -437,7 +448,7 @@ attachstack(Client *c) void buttonpress(XEvent *e) { - unsigned int i, x, click; + unsigned int i, x, click, occ; Arg arg = {0}; Client *c; Monitor *m; @@ -451,9 +462,13 @@ buttonpress(XEvent *e) focus(NULL); } if (ev->window == selmon->barwin) { - i = x = 0; + i = x = occ = 0; + /* Bitmask of occupied tags */ + for (c = m->clients; c; c = c->next) + occ |= c->tags; + do - x += TEXTW(tags[i]); + x += TEXTW(occ & 1 << i ? alttags[i] : tags[i]); while (ev->x >= x && ++i < LENGTH(tags)); if (i < LENGTH(tags)) { click = ClkTagBar; @@ -653,6 +668,7 @@ Monitor * createmon(void) { Monitor *m; + unsigned int i; m = ecalloc(1, sizeof(Monitor)); m->tagset[0] = m->tagset[1] = 1; @@ -664,6 +680,20 @@ createmon(void) m->lt[0] = &layouts[0]; m->lt[1] = &layouts[1 % LENGTH(layouts)]; strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); + m->pertag = ecalloc(1, sizeof(Pertag)); + m->pertag->curtag = m->pertag->prevtag = 1; + + for (i = 0; i <= LENGTH(tags); i++) { + m->pertag->nmasters[i] = m->nmaster; + m->pertag->mfacts[i] = m->mfact; + + m->pertag->ltidxs[i][0] = m->lt[0]; + m->pertag->ltidxs[i][1] = m->lt[1]; + m->pertag->sellts[i] = m->sellt; + + m->pertag->showbars[i] = m->showbar; + } + return m; } @@ -722,6 +752,7 @@ drawbar(Monitor *m) int boxs = drw->fonts->h / 9; int boxw = drw->fonts->h / 6 + 2; unsigned int i, occ = 0, urg = 0; + const char *tagtext; Client *c; if (!m->showbar) @@ -741,13 +772,10 @@ drawbar(Monitor *m) } x = 0; for (i = 0; i < LENGTH(tags); i++) { - w = TEXTW(tags[i]); - drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); - drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); - if (occ & 1 << i) - drw_rect(drw, x + boxs, boxs, boxw, boxw, - m == selmon && selmon->sel && selmon->sel->tags & 1 << i, - urg & 1 << i); + tagtext = occ & 1 << i ? alttags[i] : tags[i]; + w = TEXTW(tagtext); + drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, tagtext, urg & 1 << i); x += w; } w = TEXTW(m->ltsymbol); @@ -1000,7 +1028,7 @@ grabkeys(void) void incnmaster(const Arg *arg) { - selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0); arrange(selmon); } @@ -1088,6 +1116,8 @@ manage(Window w, XWindowAttributes *wa) updatewindowtype(c); updatesizehints(c); updatewmhints(c); + c->x = c->mon->mx + (c->mon->mw - WIDTH(c)) / 2; + c->y = c->mon->my + (c->mon->mh - HEIGHT(c)) / 2; XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); grabbuttons(c, 0); if (!c->isfloating) @@ -1351,36 +1381,12 @@ void resizeclient(Client *c, int x, int y, int w, int h) { XWindowChanges wc; - unsigned int n; - unsigned int gapoffset; - unsigned int gapincr; - Client *nbc; + c->oldx = c->x; c->x = wc.x = x; + 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; wc.border_width = c->bw; - - /* Get number of clients for the client's monitor */ - for (n = 0, nbc = nexttiled(c->mon->clients); nbc; nbc = nexttiled(nbc->next), n++); - - /* Do nothing if layout is floating */ - if (c->isfloating || c->mon->lt[c->mon->sellt]->arrange == NULL) { - gapincr = gapoffset = 0; - } else { - /* Remove border and gap if layout is monocle or only one client */ - if (c->mon->lt[c->mon->sellt]->arrange == monocle || n == 1) { - gapoffset = 0; - gapincr = -2 * borderpx; - wc.border_width = 0; - } else { - gapoffset = gappx; - gapincr = 2 * gappx; - } - } - - c->oldx = c->x; c->x = wc.x = x + gapoffset; - c->oldy = c->y; c->y = wc.y = y + gapoffset; - c->oldw = c->w; c->w = wc.width = w - gapincr; - c->oldh = c->h; c->h = wc.height = h - gapincr; - XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); configure(c); XSync(dpy, False); @@ -1610,9 +1616,9 @@ void setlayout(const Arg *arg) { if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) - selmon->sellt ^= 1; + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag] ^= 1; if (arg && arg->v) - selmon->lt[selmon->sellt] = (Layout *)arg->v; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); if (selmon->sel) arrange(selmon); @@ -1631,7 +1637,7 @@ setmfact(const Arg *arg) f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; if (f < 0.05 || f > 0.95) return; - selmon->mfact = f; + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; arrange(selmon); } @@ -1826,25 +1832,25 @@ tile(Monitor *m) if (n > m->nmaster) mw = m->nmaster ? m->ww * m->mfact : 0; else - mw = m->ww; - for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) - if (i < m->nmaster) { - h = (m->wh - my) / (MIN(n, m->nmaster) - i); - resize(c, m->wx, m->wy + my, mw - (2*c->bw) + (n > 1 ? gappx : 0), h - (2*c->bw), 0); - if (my + HEIGHT(c) < m->wh) - my += HEIGHT(c); + mw = m->ww - m->gappx; + for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < m->nmaster) { + h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx; + resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0); + if (my + HEIGHT(c) + m->gappx < m->wh) + my += HEIGHT(c) + m->gappx; } else { - h = (m->wh - ty) / (n - i); - resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); - if (ty + HEIGHT(c) < m->wh) - ty += HEIGHT(c); + h = (m->wh - ty) / (n - i) - m->gappx; + resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0); + if (ty + HEIGHT(c) + m->gappx < m->wh) + ty += HEIGHT(c) + m->gappx; } } void togglebar(const Arg *arg) { - selmon->showbar = !selmon->showbar; + selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar; updatebarpos(selmon); XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); arrange(selmon); @@ -1890,9 +1896,33 @@ void toggleview(const Arg *arg) { unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); + int i; if (newtagset) { selmon->tagset[selmon->seltags] = newtagset; + + if (newtagset == ~0) { + selmon->pertag->prevtag = selmon->pertag->curtag; + selmon->pertag->curtag = 0; + } + + /* test if the user did not select the same tag */ + if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) { + selmon->pertag->prevtag = selmon->pertag->curtag; + for (i = 0; !(newtagset & 1 << i); i++) ; + selmon->pertag->curtag = i + 1; + } + + /* apply settings for this view */ + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; + selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; + + if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) + togglebar(NULL); + focus(NULL); arrange(selmon); } @@ -2189,11 +2219,37 @@ updatewmhints(Client *c) void view(const Arg *arg) { + int i; + unsigned int tmptag; + if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) return; selmon->seltags ^= 1; /* toggle sel tagset */ - if (arg->ui & TAGMASK) + if (arg->ui & TAGMASK) { selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; + selmon->pertag->prevtag = selmon->pertag->curtag; + + if (arg->ui == ~0) + selmon->pertag->curtag = 0; + else { + for (i = 0; !(arg->ui & 1 << i); i++) ; + selmon->pertag->curtag = i + 1; + } + } else { + tmptag = selmon->pertag->prevtag; + selmon->pertag->prevtag = selmon->pertag->curtag; + selmon->pertag->curtag = tmptag; + } + + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; + selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; + + if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) + togglebar(NULL); + focus(NULL); arrange(selmon); } diff --git a/dwm.c.orig b/dwm.c.orig index f4b2644..a3f15f0 100644 --- a/dwm.c.orig +++ b/dwm.c.orig @@ -52,8 +52,8 @@ #define ISVISIBLE(C) ((C->tags & 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 + gappx) -#define HEIGHT(X) ((X)->h + 2 * (X)->bw + gappx) +#define WIDTH(X) ((X)->w + 2 * (X)->bw) +#define HEIGHT(X) ((X)->h + 2 * (X)->bw) #define TAGMASK ((1 << LENGTH(tags)) - 1) #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) @@ -111,6 +111,7 @@ typedef struct { void (*arrange)(Monitor *); } Layout; +typedef struct Pertag Pertag; struct Monitor { char ltsymbol[16]; float mfact; @@ -131,6 +132,7 @@ struct Monitor { Monitor *next; Window barwin; const Layout *lt[2]; + Pertag *pertag; }; typedef struct { @@ -148,6 +150,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); @@ -280,6 +283,15 @@ static Window root, wmcheckwin; /* configuration, allows nested code to access above variables */ #include "config.h" +struct Pertag { + unsigned int curtag, prevtag; /* current and previous tag */ + int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */ + float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */ + unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */ + const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */ + int showbars[LENGTH(tags) + 1]; /* display bar for the current tag */ +}; + /* compile-time check if all tags fit into an unsigned int bit array. */ struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; @@ -417,6 +429,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) { @@ -643,6 +664,7 @@ Monitor * createmon(void) { Monitor *m; + unsigned int i; m = ecalloc(1, sizeof(Monitor)); m->tagset[0] = m->tagset[1] = 1; @@ -654,6 +676,20 @@ createmon(void) m->lt[0] = &layouts[0]; m->lt[1] = &layouts[1 % LENGTH(layouts)]; strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); + m->pertag = ecalloc(1, sizeof(Pertag)); + m->pertag->curtag = m->pertag->prevtag = 1; + + for (i = 0; i <= LENGTH(tags); i++) { + m->pertag->nmasters[i] = m->nmaster; + m->pertag->mfacts[i] = m->mfact; + + m->pertag->ltidxs[i][0] = m->lt[0]; + m->pertag->ltidxs[i][1] = m->lt[1]; + m->pertag->sellts[i] = m->sellt; + + m->pertag->showbars[i] = m->showbar; + } + return m; } @@ -990,7 +1026,7 @@ grabkeys(void) void incnmaster(const Arg *arg) { - selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0); arrange(selmon); } @@ -1078,13 +1114,15 @@ manage(Window w, XWindowAttributes *wa) updatewindowtype(c); updatesizehints(c); updatewmhints(c); + c->x = c->mon->mx + (c->mon->mw - WIDTH(c)) / 2; + c->y = c->mon->my + (c->mon->mh - HEIGHT(c)) / 2; XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); grabbuttons(c, 0); if (!c->isfloating) 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); @@ -1341,36 +1379,12 @@ void resizeclient(Client *c, int x, int y, int w, int h) { XWindowChanges wc; - unsigned int n; - unsigned int gapoffset; - unsigned int gapincr; - Client *nbc; + c->oldx = c->x; c->x = wc.x = x; + 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; wc.border_width = c->bw; - - /* Get number of clients for the client's monitor */ - for (n = 0, nbc = nexttiled(c->mon->clients); nbc; nbc = nexttiled(nbc->next), n++); - - /* Do nothing if layout is floating */ - if (c->isfloating || c->mon->lt[c->mon->sellt]->arrange == NULL) { - gapincr = gapoffset = 0; - } else { - /* Remove border and gap if layout is monocle or only one client */ - if (c->mon->lt[c->mon->sellt]->arrange == monocle || n == 1) { - gapoffset = 0; - gapincr = -2 * borderpx; - wc.border_width = 0; - } else { - gapoffset = gappx; - gapincr = 2 * gappx; - } - } - - c->oldx = c->x; c->x = wc.x = x + gapoffset; - c->oldy = c->y; c->y = wc.y = y + gapoffset; - c->oldw = c->w; c->w = wc.width = w - gapincr; - c->oldh = c->h; c->h = wc.height = h - gapincr; - XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); configure(c); XSync(dpy, False); @@ -1506,7 +1520,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); @@ -1600,9 +1614,9 @@ void setlayout(const Arg *arg) { if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) - selmon->sellt ^= 1; + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag] ^= 1; if (arg && arg->v) - selmon->lt[selmon->sellt] = (Layout *)arg->v; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); if (selmon->sel) arrange(selmon); @@ -1621,7 +1635,7 @@ setmfact(const Arg *arg) f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; if (f < 0.05 || f > 0.95) return; - selmon->mfact = f; + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; arrange(selmon); } @@ -1816,25 +1830,25 @@ tile(Monitor *m) if (n > m->nmaster) mw = m->nmaster ? m->ww * m->mfact : 0; else - mw = m->ww; - for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) - if (i < m->nmaster) { - h = (m->wh - my) / (MIN(n, m->nmaster) - i); - resize(c, m->wx, m->wy + my, mw - (2*c->bw) + (n > 1 ? gappx : 0), h - (2*c->bw), 0); - if (my + HEIGHT(c) < m->wh) - my += HEIGHT(c); + mw = m->ww - m->gappx; + for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < m->nmaster) { + h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx; + resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0); + if (my + HEIGHT(c) + m->gappx < m->wh) + my += HEIGHT(c) + m->gappx; } else { - h = (m->wh - ty) / (n - i); - resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); - if (ty + HEIGHT(c) < m->wh) - ty += HEIGHT(c); + h = (m->wh - ty) / (n - i) - m->gappx; + resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0); + if (ty + HEIGHT(c) + m->gappx < m->wh) + ty += HEIGHT(c) + m->gappx; } } void togglebar(const Arg *arg) { - selmon->showbar = !selmon->showbar; + selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar; updatebarpos(selmon); XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); arrange(selmon); @@ -1880,9 +1894,33 @@ void toggleview(const Arg *arg) { unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); + int i; if (newtagset) { selmon->tagset[selmon->seltags] = newtagset; + + if (newtagset == ~0) { + selmon->pertag->prevtag = selmon->pertag->curtag; + selmon->pertag->curtag = 0; + } + + /* test if the user did not select the same tag */ + if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) { + selmon->pertag->prevtag = selmon->pertag->curtag; + for (i = 0; !(newtagset & 1 << i); i++) ; + selmon->pertag->curtag = i + 1; + } + + /* apply settings for this view */ + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; + selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; + + if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) + togglebar(NULL); + focus(NULL); arrange(selmon); } @@ -2179,11 +2217,37 @@ updatewmhints(Client *c) void view(const Arg *arg) { + int i; + unsigned int tmptag; + if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) return; selmon->seltags ^= 1; /* toggle sel tagset */ - if (arg->ui & TAGMASK) + if (arg->ui & TAGMASK) { selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; + selmon->pertag->prevtag = selmon->pertag->curtag; + + if (arg->ui == ~0) + selmon->pertag->curtag = 0; + else { + for (i = 0; !(arg->ui & 1 << i); i++) ; + selmon->pertag->curtag = i + 1; + } + } else { + tmptag = selmon->pertag->prevtag; + selmon->pertag->prevtag = selmon->pertag->curtag; + selmon->pertag->curtag = tmptag; + } + + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; + selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; + + if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) + togglebar(NULL); + focus(NULL); arrange(selmon); } diff --git a/dwm.c.rej b/dwm.c.rej index 67e66a5..82c4872 100644 --- a/dwm.c.rej +++ b/dwm.c.rej @@ -1,11 +1,22 @@ ---- dwm.c 2022-01-07 12:42:18.000000000 +0100 -+++ dwm.c 2022-08-17 22:14:41.813809073 +0200 -@@ -1913,7 +1923,7 @@ updategeom(void) - m->clients = c->next; - detachstack(c); - c->mon = mons; -- attach(c); -+ attachbottom(c); - attachstack(c); - } - if (m == selmon) +--- dwm.c 2021-10-02 14:22:28.034782413 +0100 ++++ dwm.c 2021-10-02 14:27:54.599845767 +0100 +@@ -183,8 +183,10 @@ static void maprequest(XEvent *e); + static void monocle(Monitor *m); + static void motionnotify(XEvent *e); + static void movemouse(const Arg *arg); ++static unsigned int nexttag(void); + static Client *nexttiled(Client *c); + static void pop(Client *); ++static unsigned int prevtag(void); + static void propertynotify(XEvent *e); + static void quit(const Arg *arg); + static Monitor *recttomon(int x, int y, int w, int h); +@@ -208,6 +210,8 @@ static void sigchld(int unused); + static void spawn(const Arg *arg); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); ++static void tagtonext(const Arg *arg); ++static void tagtoprev(const Arg *arg); + static void tile(Monitor *); + static void togglebar(const Arg *arg); + static void togglefloating(const Arg *arg); diff --git a/patches/dwm-fullgaps-6.4.diff b/patches/dwm-fullgaps-6.4.diff new file mode 100644 index 0000000..dc52139 --- /dev/null +++ b/patches/dwm-fullgaps-6.4.diff @@ -0,0 +1,94 @@ +diff -up a/config.def.h b/config.def.h +--- a/config.def.h ++++ b/config.def.h +@@ -2,6 +2,7 @@ + + /* appearance */ + static const unsigned int borderpx = 1; /* border pixel of windows */ ++static const unsigned int gappx = 5; /* gaps between windows */ + static const unsigned int snap = 32; /* snap pixel */ + static const int showbar = 1; /* 0 means no bar */ + static const int topbar = 1; /* 0 means bottom bar */ +@@ -85,6 +86,9 @@ static const Key keys[] = { + { MODKEY, XK_period, focusmon, {.i = +1 } }, + { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, + { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, ++ { 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) +diff -up a/dwm.c b/dwm.c +--- a/dwm.c 2023-04-30 ++++ b/dwm.c 2023-04-30 +@@ -119,6 +119,7 @@ struct Monitor { + int by; /* bar geometry */ + int mx, my, mw, mh; /* screen size */ + int wx, wy, ww, wh; /* window area */ ++ int gappx; /* gaps between windows */ + unsigned int seltags; + unsigned int sellt; + unsigned int tagset[2]; +@@ -200,6 +201,7 @@ static void sendmon(Client *c, Monitor * + static void setclientstate(Client *c, long state); + static void setfocus(Client *c); + static void setfullscreen(Client *c, int fullscreen); ++static void setgaps(const Arg *arg); + static void setlayout(const Arg *arg); + static void setmfact(const Arg *arg); + static void setup(void); +@@ -641,6 +643,7 @@ createmon(void) + m->nmaster = nmaster; + m->showbar = showbar; + m->topbar = topbar; ++ m->gappx = gappx; + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); +@@ -1508,6 +1511,16 @@ setfullscreen(Client *c, int fullscreen) + } + + void ++setgaps(const Arg *arg) ++{ ++ if ((arg->i == 0) || (selmon->gappx + arg->i < 0)) ++ selmon->gappx = 0; ++ else ++ selmon->gappx += arg->i; ++ arrange(selmon); ++} ++ ++void + setlayout(const Arg *arg) + { + if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) +@@ -1697,18 +1710,18 @@ tile(Monitor *m) + if (n > m->nmaster) + mw = m->nmaster ? m->ww * m->mfact : 0; + else +- mw = m->ww; +- for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) +- if (i < m->nmaster) { +- h = (m->wh - my) / (MIN(n, m->nmaster) - i); +- resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); +- if (my + HEIGHT(c) < m->wh) +- my += HEIGHT(c); ++ mw = m->ww - m->gappx; ++ for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) ++ if (i < m->nmaster) { ++ h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx; ++ resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0); ++ if (my + HEIGHT(c) + m->gappx < m->wh) ++ my += HEIGHT(c) + m->gappx; + } else { +- h = (m->wh - ty) / (n - i); +- resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); +- if (ty + HEIGHT(c) < m->wh) +- ty += HEIGHT(c); ++ h = (m->wh - ty) / (n - i) - m->gappx; ++ resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0); ++ if (ty + HEIGHT(c) + m->gappx < m->wh) ++ ty += HEIGHT(c) + m->gappx; + } + } diff --git a/patches/dwm-uselessgap-20211119-58414bee958f2.diff b/patches/dwm-uselessgap-20211119-58414bee958f2.diff deleted file mode 100644 index f8a3aec..0000000 --- a/patches/dwm-uselessgap-20211119-58414bee958f2.diff +++ /dev/null @@ -1,101 +0,0 @@ -From 58414bee958f2e7ed91d6fe31f503ec4a406981b Mon Sep 17 00:00:00 2001 -From: cirala -Date: Fri, 19 Nov 2021 18:14:07 +0100 -Subject: [PATCH] Fix for dwm-uselessgap -Previous versions of the patch doubles the -gap between the master and slave stacks. - ---- - config.def.h | 3 ++- - dwm.c | 38 +++++++++++++++++++++++++++++++------- - 2 files changed, 33 insertions(+), 8 deletions(-) - -diff --git a/config.def.h b/config.def.h -index a2ac963..17a205f 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -2,6 +2,7 @@ - - /* appearance */ - static const unsigned int borderpx = 1; /* border pixel of windows */ -+static const unsigned int gappx = 6; /* gaps between windows */ - static const unsigned int snap = 32; /* snap pixel */ - static const int showbar = 1; /* 0 means no bar */ - static const int topbar = 1; /* 0 means bottom bar */ -@@ -34,7 +35,7 @@ static const Rule rules[] = { - /* layout(s) */ - static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ - static const int nmaster = 1; /* number of clients in master area */ --static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ -+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[] = { -diff --git a/dwm.c b/dwm.c -index 5e4d494..b626e89 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -52,8 +52,8 @@ - #define ISVISIBLE(C) ((C->tags & 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) --#define HEIGHT(X) ((X)->h + 2 * (X)->bw) -+#define WIDTH(X) ((X)->w + 2 * (X)->bw + gappx) -+#define HEIGHT(X) ((X)->h + 2 * (X)->bw + gappx) - #define TAGMASK ((1 << LENGTH(tags)) - 1) - #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) - -@@ -1277,12 +1277,36 @@ void - resizeclient(Client *c, int x, int y, int w, int h) - { - XWindowChanges wc; -+ unsigned int n; -+ unsigned int gapoffset; -+ unsigned int gapincr; -+ Client *nbc; - -- c->oldx = c->x; c->x = wc.x = x; -- 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; - wc.border_width = c->bw; -+ -+ /* Get number of clients for the client's monitor */ -+ for (n = 0, nbc = nexttiled(c->mon->clients); nbc; nbc = nexttiled(nbc->next), n++); -+ -+ /* Do nothing if layout is floating */ -+ if (c->isfloating || c->mon->lt[c->mon->sellt]->arrange == NULL) { -+ gapincr = gapoffset = 0; -+ } else { -+ /* Remove border and gap if layout is monocle or only one client */ -+ if (c->mon->lt[c->mon->sellt]->arrange == monocle || n == 1) { -+ gapoffset = 0; -+ gapincr = -2 * borderpx; -+ wc.border_width = 0; -+ } else { -+ gapoffset = gappx; -+ gapincr = 2 * gappx; -+ } -+ } -+ -+ c->oldx = c->x; c->x = wc.x = x + gapoffset; -+ c->oldy = c->y; c->y = wc.y = y + gapoffset; -+ c->oldw = c->w; c->w = wc.width = w - gapincr; -+ c->oldh = c->h; c->h = wc.height = h - gapincr; -+ - XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); - configure(c); - XSync(dpy, False); -@@ -1688,7 +1712,7 @@ tile(Monitor *m) - for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) - if (i < m->nmaster) { - h = (m->wh - my) / (MIN(n, m->nmaster) - i); -- resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); -+ resize(c, m->wx, m->wy + my, mw - (2*c->bw) + (n > 1 ? gappx : 0), h - (2*c->bw), 0); - if (my + HEIGHT(c) < m->wh) - my += HEIGHT(c); - } else { --- -2.33.1 - diff --git a/patches_huge/dwm-tag-preview-6.3.diff b/patches_huge/dwm-tag-preview-6.3.diff new file mode 100644 index 0000000..dbee35d --- /dev/null +++ b/patches_huge/dwm-tag-preview-6.3.diff @@ -0,0 +1,315 @@ +From 841ad7d5767f945ee9da6c5afc8cff98ca2f8231 Mon Sep 17 00:00:00 2001 +From: explosion-mental +Date: Thu, 1 Sep 2022 16:21:58 -0500 +Subject: [PATCH] [PATCH] tag previews: free() tagmap and add previewtag func + +Allows you to see the contents of an already viewed tag. So a more +accurate description would be to re-view a tag. + +Allows you to see the contents of an already viewed tag. So a more +accurate description would be to re-view a tag. + +Compatibility with the alpha patch (replacing DefaultDepth() and +DefaultVisual() with depth and visual + window masks) and hide vacants can be +achieved, I left some lines to uncomment. + +added: +* more compact structure, more probable to patch on top of other patches + or easier to patch manually (like not moving the Monitor struct..) +* create the window preview in updatebars() +* renamed switchtag() -> takepreview(), makes more sense since it's + "taking" the preview (basically a screenshot). +* option previewbar, whether to show the bar in the preview or not. +* previewtag which takes a tag (unsigned int from 0 to the last tag) and + previews it. This allows to preview tags without using the + cursor/mouse (which avoids a recursive previews preview). + adding it to the TAGKEYS macro makes more sense so I've added it + replacing (keybinding wise, not functionality) toggletag. +``` +\#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, previewtag, {.ui = TAG } }, +``` +--- + config.def.h | 4 +- + config.mk | 5 +- + dwm.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 145 insertions(+), 3 deletions(-) + +diff --git a/config.def.h b/config.def.h +index a2ac963..eb70348 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -3,6 +3,8 @@ + /* appearance */ + static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int snap = 32; /* snap pixel */ ++static const int scalepreview = 4; /* preview scaling (display w and h / scalepreview) */ ++static const int previewbar = 1; /* show the bar in the preview window */ + static const int showbar = 1; /* 0 means no bar */ + static const int topbar = 1; /* 0 means bottom bar */ + static const char *fonts[] = { "monospace:size=10" }; +@@ -50,7 +52,7 @@ static const Layout layouts[] = { + { 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} }, ++ { MODKEY|ControlMask|ShiftMask, KEY, previewtag, {.ui = TAG } }, \ + + /* helper for spawning shell commands in the pre dwm-5.0 fashion */ + #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } +diff --git a/config.mk b/config.mk +index b6eb7e0..6f5129e 100644 +--- a/config.mk ++++ b/config.mk +@@ -20,9 +20,12 @@ FREETYPEINC = /usr/include/freetype2 + # OpenBSD (uncomment) + #FREETYPEINC = ${X11INC}/freetype2 + ++# Imlib2 (tag previews) ++IMLIB2LIBS = -lImlib2 ++ + # includes and libs + INCS = -I${X11INC} -I${FREETYPEINC} +-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${IMLIB2LIBS} + + # flags + CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +diff --git a/dwm.c b/dwm.c +index a96f33c..0c0ba12 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -40,6 +40,7 @@ + #include + #endif /* XINERAMA */ + #include ++#include + + #include "drw.h" + #include "util.h" +@@ -112,6 +113,9 @@ typedef struct { + } Layout; + + struct Monitor { ++ int previewshow; ++ Window tagwin; ++ Pixmap *tagmap; + char ltsymbol[16]; + float mfact; + int nmaster; +@@ -235,6 +239,10 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); + static void zoom(const Arg *arg); + ++static void showtagpreview(unsigned int i); ++static void takepreview(void); ++static void previewtag(const Arg *arg); ++ + /* variables */ + static const char broken[] = "broken"; + static char stext[256]; +@@ -438,6 +446,11 @@ buttonpress(XEvent *e) + if (i < LENGTH(tags)) { + click = ClkTagBar; + arg.ui = 1 << i; ++ /* hide preview if we click the bar */ ++ if (selmon->previewshow) { ++ selmon->previewshow = 0; ++ XUnmapWindow(dpy, selmon->tagwin); ++ } + } else if (ev->x < x + blw) + click = ClkLtSymbol; + else if (ev->x > selmon->ww - (int)TEXTW(stext)) +@@ -498,6 +511,7 @@ void + cleanupmon(Monitor *mon) + { + Monitor *m; ++ size_t i; + + if (mon == mons) + mons = mons->next; +@@ -505,8 +519,14 @@ cleanupmon(Monitor *mon) + for (m = mons; m && m->next != mon; m = m->next); + m->next = mon->next; + } ++ for (i = 0; i < LENGTH(tags); i++) ++ if (mon->tagmap[i]) ++ XFreePixmap(dpy, mon->tagmap[i]); ++ free(mon->tagmap); + XUnmapWindow(dpy, mon->barwin); + XDestroyWindow(dpy, mon->barwin); ++ XUnmapWindow(dpy, mon->tagwin); ++ XDestroyWindow(dpy, mon->tagwin); + free(mon); + } + +@@ -641,6 +661,7 @@ createmon(void) + m->topbar = topbar; + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; ++ m->tagmap = ecalloc(LENGTH(tags), sizeof(Pixmap)); + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); + return m; + } +@@ -1125,6 +1146,36 @@ motionnotify(XEvent *e) + static Monitor *mon = NULL; + Monitor *m; + XMotionEvent *ev = &e->xmotion; ++ unsigned int i, x; ++ ++ if (ev->window == selmon->barwin) { ++ i = x = 0; ++ do ++ x += TEXTW(tags[i]); ++ while (ev->x >= x && ++i < LENGTH(tags)); ++ /* FIXME when hovering the mouse over the tags and we view the tag, ++ * the preview window get's in the preview shot */ ++ ++ if (i < LENGTH(tags)) { ++ if (selmon->previewshow != (i + 1) ++ && !(selmon->tagset[selmon->seltags] & 1 << i)) { ++ selmon->previewshow = i + 1; ++ showtagpreview(i); ++ } else if (selmon->tagset[selmon->seltags] & 1 << i) { ++ selmon->previewshow = 0; ++ XUnmapWindow(dpy, selmon->tagwin); ++ } ++ } else if (selmon->previewshow) { ++ selmon->previewshow = 0; ++ XUnmapWindow(dpy, selmon->tagwin); ++ } ++ } else if (ev->window == selmon->tagwin) { ++ selmon->previewshow = 0; ++ XUnmapWindow(dpy, selmon->tagwin); ++ } else if (selmon->previewshow) { ++ selmon->previewshow = 0; ++ XUnmapWindow(dpy, selmon->tagwin); ++ } + + if (ev->window != root) + return; +@@ -1530,6 +1581,82 @@ setmfact(const Arg *arg) + arrange(selmon); + } + ++void ++showtagpreview(unsigned int i) ++{ ++ if (!selmon->previewshow || !selmon->tagmap[i]) { ++ XUnmapWindow(dpy, selmon->tagwin); ++ return; ++ } ++ ++ XSetWindowBackgroundPixmap(dpy, selmon->tagwin, selmon->tagmap[i]); ++ XCopyArea(dpy, selmon->tagmap[i], selmon->tagwin, drw->gc, 0, 0, ++ selmon->mw / scalepreview, selmon->mh / scalepreview, ++ 0, 0); ++ XSync(dpy, False); ++ XMapRaised(dpy, selmon->tagwin); ++} ++ ++void ++takepreview(void) ++{ ++ Client *c; ++ Imlib_Image image; ++ unsigned int occ = 0, i; ++ ++ for (c = selmon->clients; c; c = c->next) ++ occ |= c->tags; ++ //occ |= c->tags == 255 ? 0 : c->tags; /* hide vacants */ ++ ++ for (i = 0; i < LENGTH(tags); i++) { ++ /* searching for tags that are occupied && selected */ ++ if (!(occ & 1 << i) || !(selmon->tagset[selmon->seltags] & 1 << i)) ++ continue; ++ ++ if (selmon->tagmap[i]) { /* tagmap exist, clean it */ ++ XFreePixmap(dpy, selmon->tagmap[i]); ++ selmon->tagmap[i] = 0; ++ } ++ ++ /* try to unmap the window so it doesn't show the preview on the preview */ ++ selmon->previewshow = 0; ++ XUnmapWindow(dpy, selmon->tagwin); ++ XSync(dpy, False); ++ ++ if (!(image = imlib_create_image(sw, sh))) { ++ fprintf(stderr, "dwm: imlib: failed to create image, skipping."); ++ continue; ++ } ++ imlib_context_set_image(image); ++ imlib_context_set_display(dpy); ++ /* uncomment if using alpha patch */ ++ //imlib_image_set_has_alpha(1); ++ //imlib_context_set_blend(0); ++ //imlib_context_set_visual(visual); ++ imlib_context_set_visual(DefaultVisual(dpy, screen)); ++ imlib_context_set_drawable(root); ++ ++ if (previewbar) ++ imlib_copy_drawable_to_image(0, selmon->wx, selmon->wy, selmon->ww, selmon->wh, 0, 0, 1); ++ else ++ imlib_copy_drawable_to_image(0, selmon->mx, selmon->my, selmon->mw ,selmon->mh, 0, 0, 1); ++ selmon->tagmap[i] = XCreatePixmap(dpy, selmon->tagwin, selmon->mw / scalepreview, selmon->mh / scalepreview, DefaultDepth(dpy, screen)); ++ imlib_context_set_drawable(selmon->tagmap[i]); ++ imlib_render_image_part_on_drawable_at_size(0, 0, selmon->mw, selmon->mh, 0, 0, selmon->mw / scalepreview, selmon->mh / scalepreview); ++ imlib_free_image(); ++ } ++} ++ ++void ++previewtag(const Arg *arg) ++{ ++ if (selmon->previewshow != (arg->ui + 1)) ++ selmon->previewshow = arg->ui + 1; ++ else ++ selmon->previewshow = 0; ++ showtagpreview(arg->ui); ++} ++ + void + setup(void) + { +@@ -1746,6 +1873,7 @@ toggleview(const Arg *arg) + unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); + + if (newtagset) { ++ takepreview(); + selmon->tagset[selmon->seltags] = newtagset; + focus(NULL); + arrange(selmon); +@@ -1811,10 +1939,18 @@ updatebars(void) + XSetWindowAttributes wa = { + .override_redirect = True, + .background_pixmap = ParentRelative, +- .event_mask = ButtonPressMask|ExposureMask ++ .event_mask = ButtonPressMask|ExposureMask|PointerMotionMask + }; ++ + XClassHint ch = {"dwm", "dwm"}; + for (m = mons; m; m = m->next) { ++ if (!m->tagwin) { ++ m->tagwin = XCreateWindow(dpy, root, m->wx, m->by + bh, m->mw / scalepreview, ++ m->mh / scalepreview, 0, DefaultDepth(dpy, screen), CopyFromParent, ++ DefaultVisual(dpy, screen), CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); ++ XDefineCursor(dpy, m->tagwin, cursor[CurNormal]->cursor); ++ XUnmapWindow(dpy, m->tagwin); ++ } + if (m->barwin) + continue; + m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), +@@ -2043,6 +2179,7 @@ view(const Arg *arg) + { + if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) + return; ++ takepreview(); + selmon->seltags ^= 1; /* toggle sel tagset */ + if (arg->ui & TAGMASK) + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; +-- +2.37.3 + diff --git a/patches_huge/dwm-winicon-6.3-v2.1.diff b/patches_huge/dwm-winicon-6.3-v2.1.diff new file mode 100644 index 0000000..4278431 --- /dev/null +++ b/patches_huge/dwm-winicon-6.3-v2.1.diff @@ -0,0 +1,371 @@ +diff --git a/config.def.h b/config.def.h +index a2ac963..322d181 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -5,6 +5,8 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int snap = 32; /* snap pixel */ + static const int showbar = 1; /* 0 means no bar */ + static const int topbar = 1; /* 0 means bottom bar */ ++#define ICONSIZE 16 /* icon size */ ++#define ICONSPACING 5 /* space between icon and title */ + static const char *fonts[] = { "monospace:size=10" }; + static const char dmenufont[] = "monospace:size=10"; + static const char col_gray1[] = "#222222"; +diff --git a/config.mk b/config.mk +index b6eb7e0..f3c01b0 100644 +--- a/config.mk ++++ b/config.mk +@@ -22,7 +22,7 @@ FREETYPEINC = /usr/include/freetype2 + + # includes and libs + INCS = -I${X11INC} -I${FREETYPEINC} +-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lXrender -lImlib2 + + # flags + CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +diff --git a/drw.c b/drw.c +index 4cdbcbe..9b474c5 100644 +--- a/drw.c ++++ b/drw.c +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + + #include "drw.h" + #include "util.h" +@@ -71,6 +72,7 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h + drw->w = w; + drw->h = h; + drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); ++ drw->picture = XRenderCreatePicture(dpy, drw->drawable, XRenderFindVisualFormat(dpy, DefaultVisual(dpy, screen)), 0, NULL); + drw->gc = XCreateGC(dpy, root, 0, NULL); + XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); + +@@ -85,14 +87,18 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h) + + drw->w = w; + drw->h = h; ++ if (drw->picture) ++ XRenderFreePicture(drw->dpy, drw->picture); + if (drw->drawable) + XFreePixmap(drw->dpy, drw->drawable); + drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); ++ drw->picture = XRenderCreatePicture(drw->dpy, drw->drawable, XRenderFindVisualFormat(drw->dpy, DefaultVisual(drw->dpy, drw->screen)), 0, NULL); + } + + void + drw_free(Drw *drw) + { ++ XRenderFreePicture(drw->dpy, drw->picture); + XFreePixmap(drw->dpy, drw->drawable); + XFreeGC(drw->dpy, drw->gc); + drw_fontset_free(drw->fonts); +@@ -236,6 +242,67 @@ drw_setscheme(Drw *drw, Clr *scm) + drw->scheme = scm; + } + ++Picture ++drw_picture_create_resized(Drw *drw, char *src, unsigned int srcw, unsigned int srch, unsigned int dstw, unsigned int dsth) { ++ Pixmap pm; ++ Picture pic; ++ GC gc; ++ ++ if (srcw <= (dstw << 1u) && srch <= (dsth << 1u)) { ++ XImage img = { ++ srcw, srch, 0, ZPixmap, src, ++ ImageByteOrder(drw->dpy), BitmapUnit(drw->dpy), BitmapBitOrder(drw->dpy), 32, ++ 32, 0, 32, ++ 0, 0, 0 ++ }; ++ XInitImage(&img); ++ ++ pm = XCreatePixmap(drw->dpy, drw->root, srcw, srch, 32); ++ gc = XCreateGC(drw->dpy, pm, 0, NULL); ++ XPutImage(drw->dpy, pm, gc, &img, 0, 0, 0, 0, srcw, srch); ++ XFreeGC(drw->dpy, gc); ++ ++ pic = XRenderCreatePicture(drw->dpy, pm, XRenderFindStandardFormat(drw->dpy, PictStandardARGB32), 0, NULL); ++ XFreePixmap(drw->dpy, pm); ++ ++ XRenderSetPictureFilter(drw->dpy, pic, FilterBilinear, NULL, 0); ++ XTransform xf; ++ xf.matrix[0][0] = (srcw << 16u) / dstw; xf.matrix[0][1] = 0; xf.matrix[0][2] = 0; ++ xf.matrix[1][0] = 0; xf.matrix[1][1] = (srch << 16u) / dsth; xf.matrix[1][2] = 0; ++ xf.matrix[2][0] = 0; xf.matrix[2][1] = 0; xf.matrix[2][2] = 65536; ++ XRenderSetPictureTransform(drw->dpy, pic, &xf); ++ } else { ++ Imlib_Image origin = imlib_create_image_using_data(srcw, srch, (DATA32 *)src); ++ if (!origin) return None; ++ imlib_context_set_image(origin); ++ imlib_image_set_has_alpha(1); ++ Imlib_Image scaled = imlib_create_cropped_scaled_image(0, 0, srcw, srch, dstw, dsth); ++ imlib_free_image_and_decache(); ++ if (!scaled) return None; ++ imlib_context_set_image(scaled); ++ imlib_image_set_has_alpha(1); ++ ++ XImage img = { ++ dstw, dsth, 0, ZPixmap, (char *)imlib_image_get_data_for_reading_only(), ++ ImageByteOrder(drw->dpy), BitmapUnit(drw->dpy), BitmapBitOrder(drw->dpy), 32, ++ 32, 0, 32, ++ 0, 0, 0 ++ }; ++ XInitImage(&img); ++ ++ pm = XCreatePixmap(drw->dpy, drw->root, dstw, dsth, 32); ++ gc = XCreateGC(drw->dpy, pm, 0, NULL); ++ XPutImage(drw->dpy, pm, gc, &img, 0, 0, 0, 0, dstw, dsth); ++ imlib_free_image_and_decache(); ++ XFreeGC(drw->dpy, gc); ++ ++ pic = XRenderCreatePicture(drw->dpy, pm, XRenderFindStandardFormat(drw->dpy, PictStandardARGB32), 0, NULL); ++ XFreePixmap(drw->dpy, pm); ++ } ++ ++ return pic; ++} ++ + void + drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) + { +@@ -379,6 +446,14 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp + return x + (render ? w : 0); + } + ++void ++drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic) ++{ ++ if (!drw) ++ return; ++ XRenderComposite(drw->dpy, PictOpOver, pic, None, drw->picture, 0, 0, 0, 0, x, y, w, h); ++} ++ + void + drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) + { +diff --git a/drw.h b/drw.h +index 4bcd5ad..71aefa2 100644 +--- a/drw.h ++++ b/drw.h +@@ -21,6 +21,7 @@ typedef struct { + int screen; + Window root; + Drawable drawable; ++ Picture picture; + GC gc; + Clr *scheme; + Fnt *fonts; +@@ -49,9 +50,12 @@ void drw_cur_free(Drw *drw, Cur *cursor); + void drw_setfontset(Drw *drw, Fnt *set); + void drw_setscheme(Drw *drw, Clr *scm); + ++Picture drw_picture_create_resized(Drw *drw, char *src, unsigned int src_w, unsigned int src_h, unsigned int dst_w, unsigned int dst_h); ++ + /* Drawing functions */ + void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); + int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); ++void drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic); + + /* Map functions */ + void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); +diff --git a/dwm.c b/dwm.c +index a96f33c..033ccec 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -28,6 +28,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -60,7 +62,7 @@ + /* enums */ + enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ + enum { SchemeNorm, SchemeSel }; /* color schemes */ +-enum { NetSupported, NetWMName, NetWMState, NetWMCheck, ++enum { NetSupported, NetWMName, NetWMIcon, NetWMState, NetWMCheck, + NetWMFullscreen, NetActiveWindow, NetWMWindowType, + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ + enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ +@@ -93,6 +95,7 @@ struct Client { + int bw, oldbw; + unsigned int tags; + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; ++ unsigned int icw, ich; Picture icon; + Client *next; + Client *snext; + Monitor *mon; +@@ -170,6 +173,7 @@ static void focusin(XEvent *e); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); + static Atom getatomprop(Client *c, Atom prop); ++static Picture geticonprop(Window w, unsigned int *icw, unsigned int *ich); + static int getrootptr(int *x, int *y); + static long getstate(Window w); + static int gettextprop(Window w, Atom atom, char *text, unsigned int size); +@@ -214,6 +218,7 @@ static void togglebar(const Arg *arg); + static void togglefloating(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); ++static void freeicon(Client *c); + static void unfocus(Client *c, int setfocus); + static void unmanage(Client *c, int destroyed); + static void unmapnotify(XEvent *e); +@@ -225,6 +230,7 @@ static void updatenumlockmask(void); + static void updatesizehints(Client *c); + static void updatestatus(void); + static void updatetitle(Client *c); ++static void updateicon(Client *c); + static void updatewindowtype(Client *c); + static void updatewmhints(Client *c); + static void view(const Arg *arg); +@@ -735,7 +741,8 @@ drawbar(Monitor *m) + if ((w = m->ww - tw - x) > bh) { + if (m->sel) { + drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); +- drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); ++ drw_text(drw, x, 0, w, bh, lrpad / 2 + (m->sel->icon ? m->sel->icw + ICONSPACING : 0), m->sel->name, 0); ++ if (m->sel->icon) drw_pic(drw, x + lrpad / 2, (bh - m->sel->ich) / 2, m->sel->icw, m->sel->ich, m->sel->icon); + if (m->sel->isfloating) + drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); + } else { +@@ -875,6 +882,67 @@ getatomprop(Client *c, Atom prop) + return atom; + } + ++static uint32_t prealpha(uint32_t p) { ++ uint8_t a = p >> 24u; ++ uint32_t rb = (a * (p & 0xFF00FFu)) >> 8u; ++ uint32_t g = (a * (p & 0x00FF00u)) >> 8u; ++ return (rb & 0xFF00FFu) | (g & 0x00FF00u) | (a << 24u); ++} ++ ++Picture ++geticonprop(Window win, unsigned int *picw, unsigned int *pich) ++{ ++ int format; ++ unsigned long n, extra, *p = NULL; ++ Atom real; ++ ++ if (XGetWindowProperty(dpy, win, netatom[NetWMIcon], 0L, LONG_MAX, False, AnyPropertyType, ++ &real, &format, &n, &extra, (unsigned char **)&p) != Success) ++ return None; ++ if (n == 0 || format != 32) { XFree(p); return None; } ++ ++ unsigned long *bstp = NULL; ++ uint32_t w, h, sz; ++ { ++ unsigned long *i; const unsigned long *end = p + n; ++ uint32_t bstd = UINT32_MAX, d, m; ++ for (i = p; i < end - 1; i += sz) { ++ if ((w = *i++) >= 16384 || (h = *i++) >= 16384) { XFree(p); return None; } ++ if ((sz = w * h) > end - i) break; ++ if ((m = w > h ? w : h) >= ICONSIZE && (d = m - ICONSIZE) < bstd) { bstd = d; bstp = i; } ++ } ++ if (!bstp) { ++ for (i = p; i < end - 1; i += sz) { ++ if ((w = *i++) >= 16384 || (h = *i++) >= 16384) { XFree(p); return None; } ++ if ((sz = w * h) > end - i) break; ++ if ((d = ICONSIZE - (w > h ? w : h)) < bstd) { bstd = d; bstp = i; } ++ } ++ } ++ if (!bstp) { XFree(p); return None; } ++ } ++ ++ if ((w = *(bstp - 2)) == 0 || (h = *(bstp - 1)) == 0) { XFree(p); return None; } ++ ++ uint32_t icw, ich; ++ if (w <= h) { ++ ich = ICONSIZE; icw = w * ICONSIZE / h; ++ if (icw == 0) icw = 1; ++ } ++ else { ++ icw = ICONSIZE; ich = h * ICONSIZE / w; ++ if (ich == 0) ich = 1; ++ } ++ *picw = icw; *pich = ich; ++ ++ uint32_t i, *bstp32 = (uint32_t *)bstp; ++ for (sz = w * h, i = 0; i < sz; ++i) bstp32[i] = prealpha(bstp[i]); ++ ++ Picture ret = drw_picture_create_resized(drw, (char *)bstp, w, h, icw, ich); ++ XFree(p); ++ ++ return ret; ++} ++ + int + getrootptr(int *x, int *y) + { +@@ -1034,6 +1102,7 @@ manage(Window w, XWindowAttributes *wa) + c->h = c->oldh = wa->height; + c->oldbw = wa->border_width; + ++ updateicon(c); + updatetitle(c); + if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { + c->mon = t->mon; +@@ -1244,6 +1313,11 @@ propertynotify(XEvent *e) + if (c == c->mon->sel) + drawbar(c->mon); + } ++ else if (ev->atom == netatom[NetWMIcon]) { ++ updateicon(c); ++ if (c == c->mon->sel) ++ drawbar(c->mon); ++ } + if (ev->atom == netatom[NetWMWindowType]) + updatewindowtype(c); + } +@@ -1560,6 +1634,7 @@ setup(void) + netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); + netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); + netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); ++ netatom[NetWMIcon] = XInternAtom(dpy, "_NET_WM_ICON", False); + netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); + netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); + netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); +@@ -1752,6 +1827,15 @@ toggleview(const Arg *arg) + } + } + ++void ++freeicon(Client *c) ++{ ++ if (c->icon) { ++ XRenderFreePicture(dpy, c->icon); ++ c->icon = None; ++ } ++} ++ + void + unfocus(Client *c, int setfocus) + { +@@ -1773,6 +1857,7 @@ unmanage(Client *c, int destroyed) + + detach(c); + detachstack(c); ++ freeicon(c); + if (!destroyed) { + wc.border_width = c->oldbw; + XGrabServer(dpy); /* avoid race conditions */ +@@ -2007,6 +2092,13 @@ updatetitle(Client *c) + strcpy(c->name, broken); + } + ++void ++updateicon(Client *c) ++{ ++ freeicon(c); ++ c->icon = geticonprop(c->win, &c->icw, &c->ich); ++} ++ + void + updatewindowtype(Client *c) + { diff --git a/patches_new/dwm-fullgaps-6.4.diff b/patches_new/dwm-fullgaps-6.4.diff deleted file mode 100644 index dc52139..0000000 --- a/patches_new/dwm-fullgaps-6.4.diff +++ /dev/null @@ -1,94 +0,0 @@ -diff -up a/config.def.h b/config.def.h ---- a/config.def.h -+++ b/config.def.h -@@ -2,6 +2,7 @@ - - /* appearance */ - static const unsigned int borderpx = 1; /* border pixel of windows */ -+static const unsigned int gappx = 5; /* gaps between windows */ - static const unsigned int snap = 32; /* snap pixel */ - static const int showbar = 1; /* 0 means no bar */ - static const int topbar = 1; /* 0 means bottom bar */ -@@ -85,6 +86,9 @@ static const Key keys[] = { - { MODKEY, XK_period, focusmon, {.i = +1 } }, - { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, - { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, -+ { 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) -diff -up a/dwm.c b/dwm.c ---- a/dwm.c 2023-04-30 -+++ b/dwm.c 2023-04-30 -@@ -119,6 +119,7 @@ struct Monitor { - int by; /* bar geometry */ - int mx, my, mw, mh; /* screen size */ - int wx, wy, ww, wh; /* window area */ -+ int gappx; /* gaps between windows */ - unsigned int seltags; - unsigned int sellt; - unsigned int tagset[2]; -@@ -200,6 +201,7 @@ static void sendmon(Client *c, Monitor * - static void setclientstate(Client *c, long state); - static void setfocus(Client *c); - static void setfullscreen(Client *c, int fullscreen); -+static void setgaps(const Arg *arg); - static void setlayout(const Arg *arg); - static void setmfact(const Arg *arg); - static void setup(void); -@@ -641,6 +643,7 @@ createmon(void) - m->nmaster = nmaster; - m->showbar = showbar; - m->topbar = topbar; -+ m->gappx = gappx; - m->lt[0] = &layouts[0]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); -@@ -1508,6 +1511,16 @@ setfullscreen(Client *c, int fullscreen) - } - - void -+setgaps(const Arg *arg) -+{ -+ if ((arg->i == 0) || (selmon->gappx + arg->i < 0)) -+ selmon->gappx = 0; -+ else -+ selmon->gappx += arg->i; -+ arrange(selmon); -+} -+ -+void - setlayout(const Arg *arg) - { - if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) -@@ -1697,18 +1710,18 @@ tile(Monitor *m) - if (n > m->nmaster) - mw = m->nmaster ? m->ww * m->mfact : 0; - else -- mw = m->ww; -- for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) -- if (i < m->nmaster) { -- h = (m->wh - my) / (MIN(n, m->nmaster) - i); -- resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); -- if (my + HEIGHT(c) < m->wh) -- my += HEIGHT(c); -+ mw = m->ww - m->gappx; -+ for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) -+ if (i < m->nmaster) { -+ h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx; -+ resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0); -+ if (my + HEIGHT(c) + m->gappx < m->wh) -+ my += HEIGHT(c) + m->gappx; - } else { -- h = (m->wh - ty) / (n - i); -- resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); -- if (ty + HEIGHT(c) < m->wh) -- ty += HEIGHT(c); -+ h = (m->wh - ty) / (n - i) - m->gappx; -+ resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0); -+ if (ty + HEIGHT(c) + m->gappx < m->wh) -+ ty += HEIGHT(c) + m->gappx; - } - } diff --git a/patches_new/dwm-noborderflicker-20211227-8657affa2a61.diff b/patches_new/dwm-noborderflicker-20211227-8657affa2a61.diff index e69de29..df2aeb3 100644 --- a/patches_new/dwm-noborderflicker-20211227-8657affa2a61.diff +++ b/patches_new/dwm-noborderflicker-20211227-8657affa2a61.diff @@ -0,0 +1,42 @@ +diff --git dwm.c dwm.c +index a96f33c..34d1321 100644 +--- dwm.c ++++ dwm.c +@@ -236,6 +236,7 @@ static int xerrorstart(Display *dpy, XErrorEvent *ee); + static void zoom(const Arg *arg); + + /* variables */ ++static Client *lastfocused = NULL; + static const char broken[] = "broken"; + static char stext[256]; + static int screen; +@@ -799,7 +800,11 @@ focus(Client *c) + detachstack(c); + attachstack(c); + grabbuttons(c, 1); ++ /* set new focused border first to avoid flickering */ + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); ++ /* lastfocused may be us if another window was unmanaged */ ++ if (lastfocused && lastfocused != c) ++ XSetWindowBorder(dpy, lastfocused->win, scheme[SchemeNorm][ColBorder].pixel); + setfocus(c); + } else { + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); +@@ -1758,7 +1763,7 @@ unfocus(Client *c, int setfocus) + if (!c) + return; + grabbuttons(c, 0); +- XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); ++ lastfocused = c; + if (setfocus) { + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); +@@ -1784,6 +1789,8 @@ unmanage(Client *c, int destroyed) + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } ++ if (lastfocused == c) ++ lastfocused = NULL; + free(c); + focus(NULL); + updateclientlist(); diff --git a/patches_new/dwm-tag-preview-6.3.diff b/patches_new/dwm-tag-preview-6.3.diff deleted file mode 100644 index dbee35d..0000000 --- a/patches_new/dwm-tag-preview-6.3.diff +++ /dev/null @@ -1,315 +0,0 @@ -From 841ad7d5767f945ee9da6c5afc8cff98ca2f8231 Mon Sep 17 00:00:00 2001 -From: explosion-mental -Date: Thu, 1 Sep 2022 16:21:58 -0500 -Subject: [PATCH] [PATCH] tag previews: free() tagmap and add previewtag func - -Allows you to see the contents of an already viewed tag. So a more -accurate description would be to re-view a tag. - -Allows you to see the contents of an already viewed tag. So a more -accurate description would be to re-view a tag. - -Compatibility with the alpha patch (replacing DefaultDepth() and -DefaultVisual() with depth and visual + window masks) and hide vacants can be -achieved, I left some lines to uncomment. - -added: -* more compact structure, more probable to patch on top of other patches - or easier to patch manually (like not moving the Monitor struct..) -* create the window preview in updatebars() -* renamed switchtag() -> takepreview(), makes more sense since it's - "taking" the preview (basically a screenshot). -* option previewbar, whether to show the bar in the preview or not. -* previewtag which takes a tag (unsigned int from 0 to the last tag) and - previews it. This allows to preview tags without using the - cursor/mouse (which avoids a recursive previews preview). - adding it to the TAGKEYS macro makes more sense so I've added it - replacing (keybinding wise, not functionality) toggletag. -``` -\#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, previewtag, {.ui = TAG } }, -``` ---- - config.def.h | 4 +- - config.mk | 5 +- - dwm.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++- - 3 files changed, 145 insertions(+), 3 deletions(-) - -diff --git a/config.def.h b/config.def.h -index a2ac963..eb70348 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -3,6 +3,8 @@ - /* appearance */ - static const unsigned int borderpx = 1; /* border pixel of windows */ - static const unsigned int snap = 32; /* snap pixel */ -+static const int scalepreview = 4; /* preview scaling (display w and h / scalepreview) */ -+static const int previewbar = 1; /* show the bar in the preview window */ - static const int showbar = 1; /* 0 means no bar */ - static const int topbar = 1; /* 0 means bottom bar */ - static const char *fonts[] = { "monospace:size=10" }; -@@ -50,7 +52,7 @@ static const Layout layouts[] = { - { 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} }, -+ { MODKEY|ControlMask|ShiftMask, KEY, previewtag, {.ui = TAG } }, \ - - /* helper for spawning shell commands in the pre dwm-5.0 fashion */ - #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } -diff --git a/config.mk b/config.mk -index b6eb7e0..6f5129e 100644 ---- a/config.mk -+++ b/config.mk -@@ -20,9 +20,12 @@ FREETYPEINC = /usr/include/freetype2 - # OpenBSD (uncomment) - #FREETYPEINC = ${X11INC}/freetype2 - -+# Imlib2 (tag previews) -+IMLIB2LIBS = -lImlib2 -+ - # includes and libs - INCS = -I${X11INC} -I${FREETYPEINC} --LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -+LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${IMLIB2LIBS} - - # flags - CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -diff --git a/dwm.c b/dwm.c -index a96f33c..0c0ba12 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -40,6 +40,7 @@ - #include - #endif /* XINERAMA */ - #include -+#include - - #include "drw.h" - #include "util.h" -@@ -112,6 +113,9 @@ typedef struct { - } Layout; - - struct Monitor { -+ int previewshow; -+ Window tagwin; -+ Pixmap *tagmap; - char ltsymbol[16]; - float mfact; - int nmaster; -@@ -235,6 +239,10 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee); - static int xerrorstart(Display *dpy, XErrorEvent *ee); - static void zoom(const Arg *arg); - -+static void showtagpreview(unsigned int i); -+static void takepreview(void); -+static void previewtag(const Arg *arg); -+ - /* variables */ - static const char broken[] = "broken"; - static char stext[256]; -@@ -438,6 +446,11 @@ buttonpress(XEvent *e) - if (i < LENGTH(tags)) { - click = ClkTagBar; - arg.ui = 1 << i; -+ /* hide preview if we click the bar */ -+ if (selmon->previewshow) { -+ selmon->previewshow = 0; -+ XUnmapWindow(dpy, selmon->tagwin); -+ } - } else if (ev->x < x + blw) - click = ClkLtSymbol; - else if (ev->x > selmon->ww - (int)TEXTW(stext)) -@@ -498,6 +511,7 @@ void - cleanupmon(Monitor *mon) - { - Monitor *m; -+ size_t i; - - if (mon == mons) - mons = mons->next; -@@ -505,8 +519,14 @@ cleanupmon(Monitor *mon) - for (m = mons; m && m->next != mon; m = m->next); - m->next = mon->next; - } -+ for (i = 0; i < LENGTH(tags); i++) -+ if (mon->tagmap[i]) -+ XFreePixmap(dpy, mon->tagmap[i]); -+ free(mon->tagmap); - XUnmapWindow(dpy, mon->barwin); - XDestroyWindow(dpy, mon->barwin); -+ XUnmapWindow(dpy, mon->tagwin); -+ XDestroyWindow(dpy, mon->tagwin); - free(mon); - } - -@@ -641,6 +661,7 @@ createmon(void) - m->topbar = topbar; - m->lt[0] = &layouts[0]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; -+ m->tagmap = ecalloc(LENGTH(tags), sizeof(Pixmap)); - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); - return m; - } -@@ -1125,6 +1146,36 @@ motionnotify(XEvent *e) - static Monitor *mon = NULL; - Monitor *m; - XMotionEvent *ev = &e->xmotion; -+ unsigned int i, x; -+ -+ if (ev->window == selmon->barwin) { -+ i = x = 0; -+ do -+ x += TEXTW(tags[i]); -+ while (ev->x >= x && ++i < LENGTH(tags)); -+ /* FIXME when hovering the mouse over the tags and we view the tag, -+ * the preview window get's in the preview shot */ -+ -+ if (i < LENGTH(tags)) { -+ if (selmon->previewshow != (i + 1) -+ && !(selmon->tagset[selmon->seltags] & 1 << i)) { -+ selmon->previewshow = i + 1; -+ showtagpreview(i); -+ } else if (selmon->tagset[selmon->seltags] & 1 << i) { -+ selmon->previewshow = 0; -+ XUnmapWindow(dpy, selmon->tagwin); -+ } -+ } else if (selmon->previewshow) { -+ selmon->previewshow = 0; -+ XUnmapWindow(dpy, selmon->tagwin); -+ } -+ } else if (ev->window == selmon->tagwin) { -+ selmon->previewshow = 0; -+ XUnmapWindow(dpy, selmon->tagwin); -+ } else if (selmon->previewshow) { -+ selmon->previewshow = 0; -+ XUnmapWindow(dpy, selmon->tagwin); -+ } - - if (ev->window != root) - return; -@@ -1530,6 +1581,82 @@ setmfact(const Arg *arg) - arrange(selmon); - } - -+void -+showtagpreview(unsigned int i) -+{ -+ if (!selmon->previewshow || !selmon->tagmap[i]) { -+ XUnmapWindow(dpy, selmon->tagwin); -+ return; -+ } -+ -+ XSetWindowBackgroundPixmap(dpy, selmon->tagwin, selmon->tagmap[i]); -+ XCopyArea(dpy, selmon->tagmap[i], selmon->tagwin, drw->gc, 0, 0, -+ selmon->mw / scalepreview, selmon->mh / scalepreview, -+ 0, 0); -+ XSync(dpy, False); -+ XMapRaised(dpy, selmon->tagwin); -+} -+ -+void -+takepreview(void) -+{ -+ Client *c; -+ Imlib_Image image; -+ unsigned int occ = 0, i; -+ -+ for (c = selmon->clients; c; c = c->next) -+ occ |= c->tags; -+ //occ |= c->tags == 255 ? 0 : c->tags; /* hide vacants */ -+ -+ for (i = 0; i < LENGTH(tags); i++) { -+ /* searching for tags that are occupied && selected */ -+ if (!(occ & 1 << i) || !(selmon->tagset[selmon->seltags] & 1 << i)) -+ continue; -+ -+ if (selmon->tagmap[i]) { /* tagmap exist, clean it */ -+ XFreePixmap(dpy, selmon->tagmap[i]); -+ selmon->tagmap[i] = 0; -+ } -+ -+ /* try to unmap the window so it doesn't show the preview on the preview */ -+ selmon->previewshow = 0; -+ XUnmapWindow(dpy, selmon->tagwin); -+ XSync(dpy, False); -+ -+ if (!(image = imlib_create_image(sw, sh))) { -+ fprintf(stderr, "dwm: imlib: failed to create image, skipping."); -+ continue; -+ } -+ imlib_context_set_image(image); -+ imlib_context_set_display(dpy); -+ /* uncomment if using alpha patch */ -+ //imlib_image_set_has_alpha(1); -+ //imlib_context_set_blend(0); -+ //imlib_context_set_visual(visual); -+ imlib_context_set_visual(DefaultVisual(dpy, screen)); -+ imlib_context_set_drawable(root); -+ -+ if (previewbar) -+ imlib_copy_drawable_to_image(0, selmon->wx, selmon->wy, selmon->ww, selmon->wh, 0, 0, 1); -+ else -+ imlib_copy_drawable_to_image(0, selmon->mx, selmon->my, selmon->mw ,selmon->mh, 0, 0, 1); -+ selmon->tagmap[i] = XCreatePixmap(dpy, selmon->tagwin, selmon->mw / scalepreview, selmon->mh / scalepreview, DefaultDepth(dpy, screen)); -+ imlib_context_set_drawable(selmon->tagmap[i]); -+ imlib_render_image_part_on_drawable_at_size(0, 0, selmon->mw, selmon->mh, 0, 0, selmon->mw / scalepreview, selmon->mh / scalepreview); -+ imlib_free_image(); -+ } -+} -+ -+void -+previewtag(const Arg *arg) -+{ -+ if (selmon->previewshow != (arg->ui + 1)) -+ selmon->previewshow = arg->ui + 1; -+ else -+ selmon->previewshow = 0; -+ showtagpreview(arg->ui); -+} -+ - void - setup(void) - { -@@ -1746,6 +1873,7 @@ toggleview(const Arg *arg) - unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); - - if (newtagset) { -+ takepreview(); - selmon->tagset[selmon->seltags] = newtagset; - focus(NULL); - arrange(selmon); -@@ -1811,10 +1939,18 @@ updatebars(void) - XSetWindowAttributes wa = { - .override_redirect = True, - .background_pixmap = ParentRelative, -- .event_mask = ButtonPressMask|ExposureMask -+ .event_mask = ButtonPressMask|ExposureMask|PointerMotionMask - }; -+ - XClassHint ch = {"dwm", "dwm"}; - for (m = mons; m; m = m->next) { -+ if (!m->tagwin) { -+ m->tagwin = XCreateWindow(dpy, root, m->wx, m->by + bh, m->mw / scalepreview, -+ m->mh / scalepreview, 0, DefaultDepth(dpy, screen), CopyFromParent, -+ DefaultVisual(dpy, screen), CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); -+ XDefineCursor(dpy, m->tagwin, cursor[CurNormal]->cursor); -+ XUnmapWindow(dpy, m->tagwin); -+ } - if (m->barwin) - continue; - m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), -@@ -2043,6 +2179,7 @@ view(const Arg *arg) - { - if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) - return; -+ takepreview(); - selmon->seltags ^= 1; /* toggle sel tagset */ - if (arg->ui & TAGMASK) - selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; --- -2.37.3 - diff --git a/patches_new/dwm-winicon-6.3-v2.1.diff b/patches_new/dwm-winicon-6.3-v2.1.diff deleted file mode 100644 index 4278431..0000000 --- a/patches_new/dwm-winicon-6.3-v2.1.diff +++ /dev/null @@ -1,371 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index a2ac963..322d181 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -5,6 +5,8 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ - static const unsigned int snap = 32; /* snap pixel */ - static const int showbar = 1; /* 0 means no bar */ - static const int topbar = 1; /* 0 means bottom bar */ -+#define ICONSIZE 16 /* icon size */ -+#define ICONSPACING 5 /* space between icon and title */ - static const char *fonts[] = { "monospace:size=10" }; - static const char dmenufont[] = "monospace:size=10"; - static const char col_gray1[] = "#222222"; -diff --git a/config.mk b/config.mk -index b6eb7e0..f3c01b0 100644 ---- a/config.mk -+++ b/config.mk -@@ -22,7 +22,7 @@ FREETYPEINC = /usr/include/freetype2 - - # includes and libs - INCS = -I${X11INC} -I${FREETYPEINC} --LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -+LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lXrender -lImlib2 - - # flags - CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -diff --git a/drw.c b/drw.c -index 4cdbcbe..9b474c5 100644 ---- a/drw.c -+++ b/drw.c -@@ -4,6 +4,7 @@ - #include - #include - #include -+#include - - #include "drw.h" - #include "util.h" -@@ -71,6 +72,7 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h - drw->w = w; - drw->h = h; - drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); -+ drw->picture = XRenderCreatePicture(dpy, drw->drawable, XRenderFindVisualFormat(dpy, DefaultVisual(dpy, screen)), 0, NULL); - drw->gc = XCreateGC(dpy, root, 0, NULL); - XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); - -@@ -85,14 +87,18 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h) - - drw->w = w; - drw->h = h; -+ if (drw->picture) -+ XRenderFreePicture(drw->dpy, drw->picture); - if (drw->drawable) - XFreePixmap(drw->dpy, drw->drawable); - drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); -+ drw->picture = XRenderCreatePicture(drw->dpy, drw->drawable, XRenderFindVisualFormat(drw->dpy, DefaultVisual(drw->dpy, drw->screen)), 0, NULL); - } - - void - drw_free(Drw *drw) - { -+ XRenderFreePicture(drw->dpy, drw->picture); - XFreePixmap(drw->dpy, drw->drawable); - XFreeGC(drw->dpy, drw->gc); - drw_fontset_free(drw->fonts); -@@ -236,6 +242,67 @@ drw_setscheme(Drw *drw, Clr *scm) - drw->scheme = scm; - } - -+Picture -+drw_picture_create_resized(Drw *drw, char *src, unsigned int srcw, unsigned int srch, unsigned int dstw, unsigned int dsth) { -+ Pixmap pm; -+ Picture pic; -+ GC gc; -+ -+ if (srcw <= (dstw << 1u) && srch <= (dsth << 1u)) { -+ XImage img = { -+ srcw, srch, 0, ZPixmap, src, -+ ImageByteOrder(drw->dpy), BitmapUnit(drw->dpy), BitmapBitOrder(drw->dpy), 32, -+ 32, 0, 32, -+ 0, 0, 0 -+ }; -+ XInitImage(&img); -+ -+ pm = XCreatePixmap(drw->dpy, drw->root, srcw, srch, 32); -+ gc = XCreateGC(drw->dpy, pm, 0, NULL); -+ XPutImage(drw->dpy, pm, gc, &img, 0, 0, 0, 0, srcw, srch); -+ XFreeGC(drw->dpy, gc); -+ -+ pic = XRenderCreatePicture(drw->dpy, pm, XRenderFindStandardFormat(drw->dpy, PictStandardARGB32), 0, NULL); -+ XFreePixmap(drw->dpy, pm); -+ -+ XRenderSetPictureFilter(drw->dpy, pic, FilterBilinear, NULL, 0); -+ XTransform xf; -+ xf.matrix[0][0] = (srcw << 16u) / dstw; xf.matrix[0][1] = 0; xf.matrix[0][2] = 0; -+ xf.matrix[1][0] = 0; xf.matrix[1][1] = (srch << 16u) / dsth; xf.matrix[1][2] = 0; -+ xf.matrix[2][0] = 0; xf.matrix[2][1] = 0; xf.matrix[2][2] = 65536; -+ XRenderSetPictureTransform(drw->dpy, pic, &xf); -+ } else { -+ Imlib_Image origin = imlib_create_image_using_data(srcw, srch, (DATA32 *)src); -+ if (!origin) return None; -+ imlib_context_set_image(origin); -+ imlib_image_set_has_alpha(1); -+ Imlib_Image scaled = imlib_create_cropped_scaled_image(0, 0, srcw, srch, dstw, dsth); -+ imlib_free_image_and_decache(); -+ if (!scaled) return None; -+ imlib_context_set_image(scaled); -+ imlib_image_set_has_alpha(1); -+ -+ XImage img = { -+ dstw, dsth, 0, ZPixmap, (char *)imlib_image_get_data_for_reading_only(), -+ ImageByteOrder(drw->dpy), BitmapUnit(drw->dpy), BitmapBitOrder(drw->dpy), 32, -+ 32, 0, 32, -+ 0, 0, 0 -+ }; -+ XInitImage(&img); -+ -+ pm = XCreatePixmap(drw->dpy, drw->root, dstw, dsth, 32); -+ gc = XCreateGC(drw->dpy, pm, 0, NULL); -+ XPutImage(drw->dpy, pm, gc, &img, 0, 0, 0, 0, dstw, dsth); -+ imlib_free_image_and_decache(); -+ XFreeGC(drw->dpy, gc); -+ -+ pic = XRenderCreatePicture(drw->dpy, pm, XRenderFindStandardFormat(drw->dpy, PictStandardARGB32), 0, NULL); -+ XFreePixmap(drw->dpy, pm); -+ } -+ -+ return pic; -+} -+ - void - drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) - { -@@ -379,6 +446,14 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp - return x + (render ? w : 0); - } - -+void -+drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic) -+{ -+ if (!drw) -+ return; -+ XRenderComposite(drw->dpy, PictOpOver, pic, None, drw->picture, 0, 0, 0, 0, x, y, w, h); -+} -+ - void - drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) - { -diff --git a/drw.h b/drw.h -index 4bcd5ad..71aefa2 100644 ---- a/drw.h -+++ b/drw.h -@@ -21,6 +21,7 @@ typedef struct { - int screen; - Window root; - Drawable drawable; -+ Picture picture; - GC gc; - Clr *scheme; - Fnt *fonts; -@@ -49,9 +50,12 @@ void drw_cur_free(Drw *drw, Cur *cursor); - void drw_setfontset(Drw *drw, Fnt *set); - void drw_setscheme(Drw *drw, Clr *scm); - -+Picture drw_picture_create_resized(Drw *drw, char *src, unsigned int src_w, unsigned int src_h, unsigned int dst_w, unsigned int dst_h); -+ - /* Drawing functions */ - void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); - int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); -+void drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic); - - /* Map functions */ - void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); -diff --git a/dwm.c b/dwm.c -index a96f33c..033ccec 100644 ---- a/dwm.c -+++ b/dwm.c -@@ -28,6 +28,8 @@ - #include - #include - #include -+#include -+#include - #include - #include - #include -@@ -60,7 +62,7 @@ - /* enums */ - enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ - enum { SchemeNorm, SchemeSel }; /* color schemes */ --enum { NetSupported, NetWMName, NetWMState, NetWMCheck, -+enum { NetSupported, NetWMName, NetWMIcon, NetWMState, NetWMCheck, - NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ - enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ -@@ -93,6 +95,7 @@ struct Client { - int bw, oldbw; - unsigned int tags; - int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; -+ unsigned int icw, ich; Picture icon; - Client *next; - Client *snext; - Monitor *mon; -@@ -170,6 +173,7 @@ static void focusin(XEvent *e); - static void focusmon(const Arg *arg); - static void focusstack(const Arg *arg); - static Atom getatomprop(Client *c, Atom prop); -+static Picture geticonprop(Window w, unsigned int *icw, unsigned int *ich); - static int getrootptr(int *x, int *y); - static long getstate(Window w); - static int gettextprop(Window w, Atom atom, char *text, unsigned int size); -@@ -214,6 +218,7 @@ static void togglebar(const Arg *arg); - static void togglefloating(const Arg *arg); - static void toggletag(const Arg *arg); - static void toggleview(const Arg *arg); -+static void freeicon(Client *c); - static void unfocus(Client *c, int setfocus); - static void unmanage(Client *c, int destroyed); - static void unmapnotify(XEvent *e); -@@ -225,6 +230,7 @@ static void updatenumlockmask(void); - static void updatesizehints(Client *c); - static void updatestatus(void); - static void updatetitle(Client *c); -+static void updateicon(Client *c); - static void updatewindowtype(Client *c); - static void updatewmhints(Client *c); - static void view(const Arg *arg); -@@ -735,7 +741,8 @@ drawbar(Monitor *m) - if ((w = m->ww - tw - x) > bh) { - if (m->sel) { - drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); -- drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); -+ drw_text(drw, x, 0, w, bh, lrpad / 2 + (m->sel->icon ? m->sel->icw + ICONSPACING : 0), m->sel->name, 0); -+ if (m->sel->icon) drw_pic(drw, x + lrpad / 2, (bh - m->sel->ich) / 2, m->sel->icw, m->sel->ich, m->sel->icon); - if (m->sel->isfloating) - drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); - } else { -@@ -875,6 +882,67 @@ getatomprop(Client *c, Atom prop) - return atom; - } - -+static uint32_t prealpha(uint32_t p) { -+ uint8_t a = p >> 24u; -+ uint32_t rb = (a * (p & 0xFF00FFu)) >> 8u; -+ uint32_t g = (a * (p & 0x00FF00u)) >> 8u; -+ return (rb & 0xFF00FFu) | (g & 0x00FF00u) | (a << 24u); -+} -+ -+Picture -+geticonprop(Window win, unsigned int *picw, unsigned int *pich) -+{ -+ int format; -+ unsigned long n, extra, *p = NULL; -+ Atom real; -+ -+ if (XGetWindowProperty(dpy, win, netatom[NetWMIcon], 0L, LONG_MAX, False, AnyPropertyType, -+ &real, &format, &n, &extra, (unsigned char **)&p) != Success) -+ return None; -+ if (n == 0 || format != 32) { XFree(p); return None; } -+ -+ unsigned long *bstp = NULL; -+ uint32_t w, h, sz; -+ { -+ unsigned long *i; const unsigned long *end = p + n; -+ uint32_t bstd = UINT32_MAX, d, m; -+ for (i = p; i < end - 1; i += sz) { -+ if ((w = *i++) >= 16384 || (h = *i++) >= 16384) { XFree(p); return None; } -+ if ((sz = w * h) > end - i) break; -+ if ((m = w > h ? w : h) >= ICONSIZE && (d = m - ICONSIZE) < bstd) { bstd = d; bstp = i; } -+ } -+ if (!bstp) { -+ for (i = p; i < end - 1; i += sz) { -+ if ((w = *i++) >= 16384 || (h = *i++) >= 16384) { XFree(p); return None; } -+ if ((sz = w * h) > end - i) break; -+ if ((d = ICONSIZE - (w > h ? w : h)) < bstd) { bstd = d; bstp = i; } -+ } -+ } -+ if (!bstp) { XFree(p); return None; } -+ } -+ -+ if ((w = *(bstp - 2)) == 0 || (h = *(bstp - 1)) == 0) { XFree(p); return None; } -+ -+ uint32_t icw, ich; -+ if (w <= h) { -+ ich = ICONSIZE; icw = w * ICONSIZE / h; -+ if (icw == 0) icw = 1; -+ } -+ else { -+ icw = ICONSIZE; ich = h * ICONSIZE / w; -+ if (ich == 0) ich = 1; -+ } -+ *picw = icw; *pich = ich; -+ -+ uint32_t i, *bstp32 = (uint32_t *)bstp; -+ for (sz = w * h, i = 0; i < sz; ++i) bstp32[i] = prealpha(bstp[i]); -+ -+ Picture ret = drw_picture_create_resized(drw, (char *)bstp, w, h, icw, ich); -+ XFree(p); -+ -+ return ret; -+} -+ - int - getrootptr(int *x, int *y) - { -@@ -1034,6 +1102,7 @@ manage(Window w, XWindowAttributes *wa) - c->h = c->oldh = wa->height; - c->oldbw = wa->border_width; - -+ updateicon(c); - updatetitle(c); - if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { - c->mon = t->mon; -@@ -1244,6 +1313,11 @@ propertynotify(XEvent *e) - if (c == c->mon->sel) - drawbar(c->mon); - } -+ else if (ev->atom == netatom[NetWMIcon]) { -+ updateicon(c); -+ if (c == c->mon->sel) -+ drawbar(c->mon); -+ } - if (ev->atom == netatom[NetWMWindowType]) - updatewindowtype(c); - } -@@ -1560,6 +1634,7 @@ setup(void) - netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); - netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); - netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); -+ netatom[NetWMIcon] = XInternAtom(dpy, "_NET_WM_ICON", False); - netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); - netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); - netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); -@@ -1752,6 +1827,15 @@ toggleview(const Arg *arg) - } - } - -+void -+freeicon(Client *c) -+{ -+ if (c->icon) { -+ XRenderFreePicture(dpy, c->icon); -+ c->icon = None; -+ } -+} -+ - void - unfocus(Client *c, int setfocus) - { -@@ -1773,6 +1857,7 @@ unmanage(Client *c, int destroyed) - - detach(c); - detachstack(c); -+ freeicon(c); - if (!destroyed) { - wc.border_width = c->oldbw; - XGrabServer(dpy); /* avoid race conditions */ -@@ -2007,6 +2092,13 @@ updatetitle(Client *c) - strcpy(c->name, broken); - } - -+void -+updateicon(Client *c) -+{ -+ freeicon(c); -+ c->icon = geticonprop(c->win, &c->icw, &c->ich); -+} -+ - void - updatewindowtype(Client *c) - { -- cgit v1.2.3