1
0
mirror of https://github.com/tiyn/dwm.git synced 2025-10-15 20:31:18 +02:00

85 Commits

Author SHA1 Message Date
037b9cf74d added systray patch to Readme 2023-10-13 04:41:07 +02:00
1901bd5482 added systray patch 2023-10-13 04:39:14 +02:00
26d21333e3 added systray patch 2023-10-13 04:28:19 +02:00
3beddc02ad added statusallmons to master 2023-10-13 03:21:24 +02:00
60f78e1cac added statusallmons to master 2023-10-13 02:35:20 +02:00
6df99308c1 added statusallmons 2023-10-13 02:32:28 +02:00
3547e19c2c pushing config.h too 2023-08-14 02:47:12 +02:00
2b1a66653d hotkey changed 2023-04-05 03:48:15 +02:00
c6a2e45ba3 cleanup: unused programs removed 2023-01-11 01:40:33 +01:00
17c777a9ac cleanup: unused services and readme 2023-01-11 01:39:09 +01:00
40315fc237 readme: updated with guide link 2022-11-20 14:31:22 +01:00
TiynGER
00ee4b8ce3 master: fixing minor mergeconflict in Readme 2020-12-27 18:55:47 +01:00
TiynGER
e4fd77302c bottomstack: added and applied bottomstack 2020-12-27 18:54:38 +01:00
TiynGER
6658ba76bc bottomstack: added and applied bottomstack 2020-12-27 18:43:52 +01:00
Marten
ce693a4872 Update README.md 2020-11-02 20:15:20 +01:00
TiynGER
fbf5d9caed changing colors 2020-05-30 19:56:00 +02:00
TiynGER
b032290d42 changing colors 2020-05-30 19:55:38 +02:00
TiynGER
6a06afc78c changing colors 2020-05-30 19:54:55 +02:00
TiynGER
cd37e83e8b new colors new symbols soon 2020-05-30 18:10:23 +02:00
TiynGER
33d3e50efd Merge remote-tracking branch 'origin/statuscmd' 2020-05-30 18:03:56 +02:00
TiynGER
444722a469 Merge remote-tracking branch 'origin/pertag' 2020-05-30 18:03:50 +02:00
TiynGER
99187318cf Merge remote-tracking branch 'origin/noborder' 2020-05-30 18:03:45 +02:00
TiynGER
a4474f29ad Merge remote-tracking branch 'origin/center' 2020-05-30 18:03:35 +02:00
TiynGER
abf9180efe Merge branch 'deck' 2020-05-30 18:03:25 +02:00
TiynGER
9b2cb71c00 Merge branch 'alttagsdecoration' 2020-05-30 18:03:18 +02:00
TiynGER
1e28cca03d new icons 2020-05-29 17:33:58 +02:00
TiynGER
ced44422e9 new icons 2020-05-29 17:32:39 +02:00
TiynGER
b1d1ff8e46 alttagsdecoration added 2020-05-29 16:56:54 +02:00
TiynGER
5a92ec4807 update config 2020-05-29 16:53:56 +02:00
TiynGER
116548d4a1 removing alpha patch 2020-05-29 14:12:14 +02:00
tiyn
fbd7aa1468 firefox better now 2020-05-28 21:03:11 +00:00
TiynGER
2ab6d4df92 fixing layouts 2020-05-28 02:15:58 +02:00
TiynGER
9228d0d79f Merge branch 'config' of ssh+git://github/tiynger/dwm into config 2020-05-28 01:48:41 +02:00
TiynGER
0da1eba5da statuscmd added 2020-05-28 01:48:32 +02:00
TiynGER
848eb29268 adding statuscmd patch 2020-05-28 01:41:44 +02:00
Marten Kante
8c87d02376 Update README.md 2020-05-14 19:20:17 +00:00
TiynGER
b5bb901fea shortcuts specified in readme 2020-05-10 00:20:55 +02:00
TiynGER
ce8e36d874 removing a bunch of shortcuts 2020-05-10 00:03:08 +02:00
TiynGER
8fc905a914 disabled alpha tmp 2020-04-18 22:23:36 +02:00
TiynGER
e173a53c7f update readme 2020-04-07 22:32:13 +02:00
TiynGER
0edb06f677 new config 2020-04-07 22:27:48 +02:00
TiynGER
7be627aa05 patching actualfullscreen 2020-04-07 22:13:03 +02:00
TiynGER
0e09a836d3 rm config.h 2020-04-07 22:09:01 +02:00
TiynGER
9170e1e2f2 missing 2020-04-07 22:07:27 +02:00
TiynGER
a3cbe17ccf firefox 2020-04-06 19:08:23 +02:00
TiynGER
e94c3b8bcd lets try qutebrowser 2020-04-06 01:34:20 +02:00
TiynGER
2af267744c making Monocle the default layout 2020-04-05 00:12:36 +02:00
TiynGER
483b197eb5 new color 2020-04-02 01:23:47 +02:00
TiynGER
da3b3a372c its preview time 2020-03-31 20:20:57 +02:00
TiynGER
f0d878b8a2 formatting readme 2020-03-31 15:15:25 +02:00
TiynGER
92abb3b304 update readme 2020-03-31 11:06:24 +02:00
TiynGER
3807c7106d update readme 2020-03-31 10:37:20 +02:00
TiynGER
37fa8a2f71 updates for new deck layout 2020-03-31 10:20:57 +02:00
TiynGER
9ea35a00a9 new option 2020-03-31 10:20:02 +02:00
TiynGER
e2877b3a04 patching deck 2020-03-31 10:18:52 +02:00
TiynGER
8c92c1941d updating readme 2020-03-31 10:13:48 +02:00
TiynGER
685c69599e new config for new patch 2020-03-31 10:12:04 +02:00
TiynGER
137c32d0f2 applying center patch 2020-03-31 10:06:48 +02:00
TiynGER
2314f013d8 updating readme 2020-03-31 10:05:22 +02:00
TiynGER
b1d4290a00 update readme 2020-03-31 09:57:22 +02:00
TiynGER
f06f83bd57 adding pertag patch 2020-03-31 09:51:29 +02:00
TiynGER
90d5ce64d7 fixing font for emojis 2020-03-30 21:19:19 +02:00
TiynGER
eb0271878b monitor keys added 2020-03-30 17:13:55 +02:00
TiynGER
c98f008b1e thats the right one 2020-03-30 15:14:18 +02:00
TiynGER
2f3fee8373 that was the wrong branch 2020-03-30 15:13:51 +02:00
TiynGER
8faebad8c2 update readme 2020-03-30 15:12:45 +02:00
TiynGER
c40dc12e8c enabling 0 tag 2020-03-29 22:05:42 +02:00
TiynGER
fb9efccff1 minor changes to config.h 2020-03-29 21:57:52 +02:00
Marten Kante
08c631234c Update README.md 2020-03-29 17:30:57 +02:00
TiynGER
4c2c587c0a adding README 2020-03-29 16:23:15 +02:00
TiynGER
1eb5dafe1d removing unneeded line 2020-03-29 16:21:22 +02:00
TiynGER
643db6de4c toggle floating added 2020-03-29 16:19:37 +02:00
TiynGER
d4c979c649 new font 2020-03-29 11:34:27 +02:00
TiynGER
d1fb53de7d enable color emojis 2020-03-29 11:23:44 +02:00
TiynGER
9e0818634f new border 2020-03-29 00:31:40 +01:00
TiynGER
ed5afc2a28 minor fixes in shortcuts 2020-03-29 00:28:34 +01:00
TiynGER
71a8ed6bb0 friendship with cyan over, orange is my new best friend 2020-03-29 00:21:38 +01:00
TiynGER
66c73c08ab change colors 2020-03-29 00:07:43 +01:00
TiynGER
b7c7db8d3d bigger? 2020-03-28 23:46:13 +01:00
TiynGER
fd23800043 maybe inconsolata 2020-03-28 23:42:18 +01:00
TiynGER
5e34669153 no emoji font 2020-03-28 23:36:49 +01:00
TiynGER
a862f85599 emoji font 2020-03-28 23:34:46 +01:00
TiynGER
eb34580110 changing font 2020-03-28 23:29:31 +01:00
Marten Kante
41598088e8 Delete README 2020-03-28 23:16:11 +01:00
TiynGER
bd524f38f4 adding config 2020-03-28 20:15:02 +01:00
15 changed files with 2374 additions and 93 deletions

3
.gitignore vendored
View File

@@ -1,3 +0,0 @@
*.o
dwm
config.h

60
README.md Normal file
View File

@@ -0,0 +1,60 @@
# dwm
This is my patched version of dwm. The base version is directly from
suckless.org.
This belongs to my larbs installation script and depends heavily on its scripts
and programs.
It is supposed to work in the environment after the larbs-base-installation.
This is my patched version of dwm. The base version is directly from suckless.org.
This repository is set up according to the
[suckless entry of my wiki](https://github.com/tiyn/wiki/blob/master/wiki/linux/suckless.md).
## Patches
The list below shows the currently applied patches to the master branch.
- dwm-actualfullscreen-20191112-cb3f58a.diff (enables true fullscreen)
- dwm-alttagsdecoration-2020010304-cb3f58a.diff (enables different icons for tags with windows)
- dwm-bottomstack-20160719-56a31dc.diff (adds bottomstack and bottomstackhorizontal layout)
- dwm-center-6.1.diff (adds ability to center floating windows at launch)
- dwm-deck-6.0.diff (adds deck layout)
- dwm-noborder-6.2.diff (removes border if there is only one window)
- dwm-pertag-20170513-ceac8c9.diff (allows having a layout/mwfact/barpos/nmaster per tag)
- dwm-statusallmons-6.2.diff (display statusbar on every monitors)
- dwm-statuscmd-6.2.diff (enables dwmblocks compatibility)
- dwm-systray-6.2.diff (adds systray to statusbar)
## Hotkeys
There are various shortcuts and hotkeys used in this version. Included in my
build are the following.
| ModKey | Shift | Key | Function |
| ------ | ----- | --- | -------- |
| Super | | h | (Tiling/Deck) Focus window higher in stack than current |
| Super | | j | (Tiling/Deck) Focus window lower in stack than current |
| Super | | k | (Tiling/Deck) Focus window higher in stack than current |
| Super | | l | (Tiling/Deck) Focus window lower in stack than current |
| Super | | 0 | Show all tags |
| Super | | 1/2/.../9 | Show tag 1/2/.../9 |
| Super | | . | Show monitor lower in stack |
| Super | | , | Show monitor higher in stack |
| Super | Shift | Escape | Quit dwm |
| Super | Shift | b | Toggle dwmbar |
| Super | Shift | c | Enable deck(/card) layout |
| Super | Shift | d | Toggle floating/tiled for selected window |
| Super | Shift | f | Toggle fullscreen |
| Super | Shift | h | (Tiling/Deck) Make current window the master window |
| Super | Shift | j | (Tiling/Deck) Make current window the master window |
| Super | Shift | k | (Tiling/Deck) Make current window the master window |
| Super | Shift | m | Enable monocle layout |
| Super | Shift | o | (Tiling/Deck) Increase master window size |
| Super | Shift | q | Close current window |
| Super | Shift | t | Enable tiling layout |
| Super | Shift | u | Enable bottomstack layout |
| Super | Shift | v | Enable bottomstackhorizontal layout |
| Super | Shift | z | (Tiling/Deck) Decrease master window size |
| Super | Shift | 0 | Add current window to all tag |
| Super | Shift | 1/2/.../9 | Add current window to tag 1/2/.../9 |
| Super | Shift | . | Add to monitor lower in stack |
| Super | Shift | , | Add to monitor higher in stack |

View File

@@ -1,50 +1,61 @@
/* See LICENSE file for copyright and license details. */
/* for media keys */
#include <X11/XF86keysym.h>
/* appearance */
static const unsigned int borderpx = 1; /* border pixel of windows */
static const unsigned int snap = 32; /* snap pixel */
static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */
static const unsigned int systrayspacing = 2; /* systray spacing */
static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/
static const int showsystray = 1; /* 0 means no systray */
static const int 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 normbgcolor[] = "#0e0f14";
static const char normbordercolor[] = "#363b47";
static const char normfgcolor[] = "#dfdfdf";
static const char selfgcolor[] = "#eeeeee";
static const char selbordercolor[] = "#555a63";
static const char selbgcolor[] = "#282828";
static const char *colors[][3] = {
/* fg bg border */
[SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
[SchemeSel] = { col_gray4, col_cyan, col_cyan },
[SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor },
[SchemeSel] = { selfgcolor, selbgcolor, selbordercolor },
};
/* tagging */
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
static const char *tags[] = { "", "", "", "", "", "", "", "", "" };
static const char *alttags[] = { "", "", "", "", "", "", "", "", "" };
static const Rule rules[] = {
/* xprop(1):
* WM_CLASS(STRING) = instance, class
* WM_NAME(STRING) = title
*/
/* class instance title tags mask isfloating monitor */
{ "Gimp", NULL, NULL, 0, 1, -1 },
{ "Firefox", NULL, NULL, 1 << 8, 0, -1 },
/* class instance title tags mask iscentered isfloating monitor */
{ NULL, "origin.exe", NULL, 0, 0, 1, -1 },
};
/* layout(s) */
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
static const float mfact = 0.5; /* factor of master area size [0.05..0.95] */
static const int nmaster = 1; /* number of clients in master area */
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
static const Layout layouts[] = {
/* symbol arrange function */
{ "[]=", tile }, /* first entry is default */
{ "><>", NULL }, /* no layout function means floating behavior */
{ "[M]", monocle },
{ "M", monocle },
{ "T", tile }, /* first entry is default */
{ "D", deck },
{ "B", bstack },
{ "=", bstackhoriz },
{ "F", NULL }, /* no layout function means floating behavior */
};
/* key definitions */
#define MODKEY Mod1Mask
#define MODKEY Mod4Mask
#define TAGKEYS(KEY,TAG) \
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
{ MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
@@ -56,34 +67,38 @@ static const Layout layouts[] = {
/* 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_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
static const char *termcmd[] = { "st", NULL };
static const char *dmenucmd[] = { "dmenu_run", "-c", "-l", "20", NULL };
static 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|ShiftMask, XK_Escape, quit, {0} },
{ MODKEY|ShiftMask, XK_b, togglebar, {0} },
{ MODKEY|ShiftMask, XK_c, setlayout, {.v = &layouts[2]} },
{ MODKEY|ShiftMask, XK_d, togglefloating, {0} },
{ MODKEY|ShiftMask, XK_f, togglefullscr, {0} },
{ MODKEY, XK_h, focusstack, {.i = -1 } },
{ MODKEY|ShiftMask, XK_h, zoom, {0} },
{ MODKEY, XK_j, focusstack, {.i = +1 } },
{ MODKEY|ShiftMask, XK_j, zoom, {0} },
{ MODKEY, XK_k, focusstack, {.i = -1 } },
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
{ MODKEY, XK_Return, zoom, {0} },
{ MODKEY, XK_Tab, view, {0} },
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
{ MODKEY, XK_space, setlayout, {0} },
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
{ MODKEY|ShiftMask, XK_k, zoom, {0} },
{ MODKEY, XK_l, focusstack, {.i = +1 } },
{ MODKEY|ShiftMask, XK_m, setlayout, {.v = &layouts[0]} },
{ MODKEY|ShiftMask, XK_o, setmfact, {.f = +0.05} },
{ MODKEY|ShiftMask, XK_q, killclient, {0} },
{ MODKEY|ShiftMask, XK_t, setlayout, {.v = &layouts[1]} },
{ MODKEY|ShiftMask, XK_u, setlayout, {.v = &layouts[3]} },
{ MODKEY|ShiftMask, XK_v, setlayout, {.v = &layouts[4]} },
{ MODKEY|ShiftMask, XK_z, setmfact, {.f = -0.05} },
{ 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|ShiftMask, XK_o, incnmaster, {.i = +1 } },
//{ MODKEY|ShiftMask, XK_z, incnmaster, {.i = -1 } },
//{ MODKEY, XK_space, setlayout, {0} },
TAGKEYS( XK_1, 0)
TAGKEYS( XK_2, 1)
TAGKEYS( XK_3, 2)
@@ -93,7 +108,6 @@ static Key keys[] = {
TAGKEYS( XK_7, 6)
TAGKEYS( XK_8, 7)
TAGKEYS( XK_9, 8)
{ MODKEY|ShiftMask, XK_q, quit, {0} },
};
/* button definitions */
@@ -103,7 +117,9 @@ static Button buttons[] = {
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
{ ClkWinTitle, 0, Button2, zoom, {0} },
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
{ ClkStatusText, 0, Button1, sigdwmblocks, {.i = 1} },
{ ClkStatusText, 0, Button2, sigdwmblocks, {.i = 2} },
{ ClkStatusText, 0, Button3, sigdwmblocks, {.i = 3} },
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },

130
config.h Normal file
View File

@@ -0,0 +1,130 @@
/* See LICENSE file for copyright and license details. */
/* for media keys */
#include <X11/XF86keysym.h>
/* appearance */
static const unsigned int borderpx = 1; /* border pixel of windows */
static const unsigned int snap = 32; /* snap pixel */
static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */
static const unsigned int systrayspacing = 2; /* systray spacing */
static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/
static const int showsystray = 1; /* 0 means no systray */
static const int 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 normbgcolor[] = "#0e0f14";
static const char normbordercolor[] = "#363b47";
static const char normfgcolor[] = "#dfdfdf";
static const char selfgcolor[] = "#eeeeee";
static const char selbordercolor[] = "#555a63";
static const char selbgcolor[] = "#282828";
static const char *colors[][3] = {
/* fg bg border */
[SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor },
[SchemeSel] = { selfgcolor, selbgcolor, selbordercolor },
};
/* tagging */
static const char *tags[] = { "", "", "", "", "", "", "", "", "" };
static const char *alttags[] = { "", "", "", "", "", "", "", "", "" };
static const Rule rules[] = {
/* xprop(1):
* WM_CLASS(STRING) = instance, class
* WM_NAME(STRING) = title
*/
/* class instance title tags mask iscentered isfloating monitor */
{ NULL, "origin.exe", NULL, 0, 0, 1, -1 },
};
/* layout(s) */
static const float mfact = 0.5; /* factor of master area size [0.05..0.95] */
static const int nmaster = 1; /* number of clients in master area */
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
static const Layout layouts[] = {
/* symbol arrange function */
{ "M", monocle },
{ "T", tile }, /* first entry is default */
{ "D", deck },
{ "B", bstack },
{ "=", bstackhoriz },
{ "F", NULL }, /* no layout function means floating behavior */
};
/* key definitions */
#define MODKEY Mod4Mask
#define TAGKEYS(KEY,TAG) \
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
{ MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
{ MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
{ MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
/* 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", "-c", "-l", "20", NULL };
static Key keys[] = {
/* modifier key function argument */
{ MODKEY|ShiftMask, XK_Escape, quit, {0} },
{ MODKEY|ShiftMask, XK_b, togglebar, {0} },
{ MODKEY|ShiftMask, XK_c, setlayout, {.v = &layouts[2]} },
{ MODKEY|ShiftMask, XK_d, togglefloating, {0} },
{ MODKEY|ShiftMask, XK_f, togglefullscr, {0} },
{ MODKEY, XK_h, focusstack, {.i = -1 } },
{ MODKEY|ShiftMask, XK_h, zoom, {0} },
{ MODKEY, XK_j, focusstack, {.i = +1 } },
{ MODKEY|ShiftMask, XK_j, zoom, {0} },
{ MODKEY, XK_k, focusstack, {.i = -1 } },
{ MODKEY|ShiftMask, XK_k, zoom, {0} },
{ MODKEY, XK_l, focusstack, {.i = +1 } },
{ MODKEY|ShiftMask, XK_m, setlayout, {.v = &layouts[0]} },
{ MODKEY|ShiftMask, XK_o, setmfact, {.f = +0.05} },
{ MODKEY|ShiftMask, XK_q, killclient, {0} },
{ MODKEY|ShiftMask, XK_t, setlayout, {.v = &layouts[1]} },
{ MODKEY|ShiftMask, XK_u, setlayout, {.v = &layouts[3]} },
{ MODKEY|ShiftMask, XK_v, setlayout, {.v = &layouts[4]} },
{ MODKEY|ShiftMask, XK_z, setmfact, {.f = -0.05} },
{ 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|ShiftMask, XK_o, incnmaster, {.i = +1 } },
//{ MODKEY|ShiftMask, XK_z, incnmaster, {.i = -1 } },
//{ MODKEY, XK_space, setlayout, {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)
};
/* button definitions */
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
static 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, Button1, sigdwmblocks, {.i = 1} },
{ ClkStatusText, 0, Button2, sigdwmblocks, {.i = 2} },
{ ClkStatusText, 0, Button3, sigdwmblocks, {.i = 3} },
{ 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} },
};

4
drw.c
View File

@@ -139,11 +139,11 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
* https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=916349
* and lots more all over the internet.
*/
FcBool iscol;
/*FcBool iscol;
if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) {
XftFontClose(drw->dpy, xfont);
return NULL;
}
}*/
font = ecalloc(1, sizeof(Fnt));
font->xfont = xfont;

View File

@@ -0,0 +1,53 @@
From 3a16816a6f5d38014c2a06ce395873c545c8789a Mon Sep 17 00:00:00 2001
From: Soenke Lambert <s.lambert@mittwald.de>
Date: Tue, 12 Nov 2019 10:44:02 +0100
Subject: [PATCH] Fullscreen current window with [Alt]+[Shift]+[f]
This actually fullscreens a window, instead of just hiding the statusbar
and applying the monocle layout.
---
config.def.h | 1 +
dwm.c | 8 ++++++++
2 files changed, 9 insertions(+)
diff --git a/config.def.h b/config.def.h
index 1c0b587..8cd3204 100644
--- a/config.def.h
+++ b/config.def.h
@@ -78,6 +78,7 @@ static Key keys[] = {
{ 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 } },
diff --git a/dwm.c b/dwm.c
index 4465af1..c1b899a 100644
--- a/dwm.c
+++ b/dwm.c
@@ -211,6 +211,7 @@ static void tagmon(const Arg *arg);
static void tile(Monitor *);
static void togglebar(const Arg *arg);
static void togglefloating(const Arg *arg);
+static void togglefullscr(const Arg *arg);
static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
static void unfocus(Client *c, int setfocus);
@@ -1719,6 +1720,13 @@ togglefloating(const Arg *arg)
arrange(selmon);
}
+void
+togglefullscr(const Arg *arg)
+{
+ if(selmon->sel)
+ setfullscreen(selmon->sel, !selmon->sel->isfullscreen);
+}
+
void
toggletag(const Arg *arg)
{
--
2.17.1

View File

@@ -0,0 +1,67 @@
diff --git a/config.def.h b/config.def.h
index 1c0b587..d4b11fc 100644
--- a/config.def.h
+++ b/config.def.h
@@ -20,6 +20,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):
diff --git a/dwm.c b/dwm.c
index 4465af1..a394159 100644
--- a/dwm.c
+++ b/dwm.c
@@ -416,7 +416,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;
@@ -430,9 +430,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;
@@ -699,6 +703,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;
/* draw status first so it can be overdrawn by tags later */
@@ -715,13 +720,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 = blw = TEXTW(m->ltsymbol);

View File

@@ -0,0 +1,101 @@
diff --git a/config.def.h b/config.def.h
index fd77a07..c3a044b 100644
--- a/config.def.h
+++ b/config.def.h
@@ -41,6 +41,8 @@ static const Layout layouts[] = {
{ "[]=", tile }, /* first entry is default */
{ "><>", NULL }, /* no layout function means floating behavior */
{ "[M]", monocle },
+ { "TTT", bstack },
+ { "===", bstackhoriz },
};
/* key definitions */
@@ -76,6 +78,8 @@ static Key keys[] = {
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
+ { MODKEY, XK_u, setlayout, {.v = &layouts[3]} },
+ { MODKEY, XK_o, setlayout, {.v = &layouts[4]} },
{ MODKEY, XK_space, setlayout, {0} },
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
{ MODKEY, XK_0, view, {.ui = ~0 } },
diff --git a/dwm.c b/dwm.c
index b2bc9bd..8b74165 100644
--- a/dwm.c
+++ b/dwm.c
@@ -234,6 +234,8 @@ static int xerror(Display *dpy, XErrorEvent *ee);
static int xerrordummy(Display *dpy, XErrorEvent *ee);
static int xerrorstart(Display *dpy, XErrorEvent *ee);
static void zoom(const Arg *arg);
+static void bstack(Monitor *m);
+static void bstackhoriz(Monitor *m);
/* variables */
static const char broken[] = "broken";
@@ -2138,3 +2140,65 @@ main(int argc, char *argv[])
XCloseDisplay(dpy);
return EXIT_SUCCESS;
}
+
+static void
+bstack(Monitor *m) {
+ int w, h, mh, mx, tx, ty, tw;
+ unsigned int i, n;
+ Client *c;
+
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
+ if (n == 0)
+ return;
+ if (n > m->nmaster) {
+ mh = m->nmaster ? m->mfact * m->wh : 0;
+ tw = m->ww / (n - m->nmaster);
+ ty = m->wy + mh;
+ } else {
+ mh = m->wh;
+ tw = m->ww;
+ ty = m->wy;
+ }
+ for (i = mx = 0, tx = m->wx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
+ if (i < m->nmaster) {
+ w = (m->ww - mx) / (MIN(n, m->nmaster) - i);
+ resize(c, m->wx + mx, m->wy, w - (2 * c->bw), mh - (2 * c->bw), 0);
+ mx += WIDTH(c);
+ } else {
+ h = m->wh - mh;
+ resize(c, tx, ty, tw - (2 * c->bw), h - (2 * c->bw), 0);
+ if (tw != m->ww)
+ tx += WIDTH(c);
+ }
+ }
+}
+
+static void
+bstackhoriz(Monitor *m) {
+ int w, mh, mx, tx, ty, th;
+ unsigned int i, n;
+ Client *c;
+
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
+ if (n == 0)
+ return;
+ if (n > m->nmaster) {
+ mh = m->nmaster ? m->mfact * m->wh : 0;
+ th = (m->wh - mh) / (n - m->nmaster);
+ ty = m->wy + mh;
+ } else {
+ th = mh = m->wh;
+ ty = m->wy;
+ }
+ for (i = mx = 0, tx = m->wx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
+ if (i < m->nmaster) {
+ w = (m->ww - mx) / (MIN(n, m->nmaster) - i);
+ resize(c, m->wx + mx, m->wy, w - (2 * c->bw), mh - (2 * c->bw), 0);
+ mx += WIDTH(c);
+ } else {
+ resize(c, tx, ty, m->ww - (2 * c->bw), th - (2 * c->bw), 0);
+ if (th != m->wh)
+ ty += HEIGHT(c);
+ }
+ }
+}

58
dwm-center-6.1.diff Normal file
View File

@@ -0,0 +1,58 @@
diff --git a/config.def.h b/config.def.h
index 7054c06..e0cdcf3 100644
--- a/config.def.h
+++ b/config.def.h
@@ -24,9 +24,9 @@ static const Rule rules[] = {
* WM_CLASS(STRING) = instance, class
* WM_NAME(STRING) = title
*/
- /* class instance title tags mask isfloating monitor */
- { "Gimp", NULL, NULL, 0, 1, -1 },
- { "Firefox", NULL, NULL, 1 << 8, 0, -1 },
+ /* class instance title tags mask iscentered isfloating monitor */
+ { "Gimp", NULL, NULL, 0, 0, 1, -1 },
+ { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1 },
};
/* layout(s) */
diff --git a/dwm.c b/dwm.c
index 0362114..4aaaa60 100644
--- a/dwm.c
+++ b/dwm.c
@@ -92,7 +92,7 @@ struct Client {
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
int bw, oldbw;
unsigned int tags;
- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
+ int isfixed, iscentered, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
Client *next;
Client *snext;
Monitor *mon;
@@ -137,6 +137,7 @@ typedef struct {
const char *instance;
const char *title;
unsigned int tags;
+ int iscentered;
int isfloating;
int monitor;
} Rule;
@@ -296,6 +297,7 @@ applyrules(Client *c)
&& (!r->class || strstr(class, r->class))
&& (!r->instance || strstr(instance, r->instance)))
{
+ c->iscentered = r->iscentered;
c->isfloating = r->isfloating;
c->tags |= r->tags;
for (m = mons; m && m->num != r->monitor; m = m->next);
@@ -1063,6 +1065,11 @@ manage(Window w, XWindowAttributes *wa)
&& (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my);
c->bw = borderpx;
+ if(c->iscentered) {
+ c->x = (c->mon->mw - WIDTH(c)) / 2;
+ c->y = (c->mon->mh - HEIGHT(c)) / 2;
+ }
+
wc.border_width = c->bw;
XConfigureWindow(dpy, w, CWBorderWidth, &wc);
XSetWindowBorder(dpy, w, scheme[SchemeNorm].border->pix);

90
dwm-deck-6.0.diff Normal file
View File

@@ -0,0 +1,90 @@
From cb3cac91db32403bb581aecbc2957b00bb49c898 Mon Sep 17 00:00:00 2001
From: aleks <aleks.stier@icloud.com>
Date: Mon, 6 May 2019 16:34:58 +0200
Subject: [PATCH] Add deck-layout
deck is a dwm-layout which is inspired by the TTWM window manager.
It applies the monocle-layout to the clients in the stack.
The master-client is still visible. The stacked clients are like
a deck of cards, hence the name.
The vanilla patch doesn't work properly with patches which add gaps.
This means that when the deck-layout is activated gaps are omitted.
To make it work with the tilegap-patch apply the dwm-deck-tilegap patch
on top of the dwm-deck patch.
The vanilla patch doesn't respect the master-area which is defined by
the rmaster-patch. To make it work with the rmaster-patch apply the
dwm-deck-rmaster patch on top of the dwm-deck patch.
---
config.def.h | 2 ++
dwm.c | 26 ++++++++++++++++++++++++++
2 files changed, 28 insertions(+)
diff --git a/config.def.h b/config.def.h
index 77ff358..55d8a07 100644
--- a/config.def.h
+++ b/config.def.h
@@ -32,6 +32,7 @@ static const Layout layouts[] = {
{ "[]=", tile }, /* first entry is default */
{ "><>", NULL }, /* no layout function means floating behavior */
{ "[M]", monocle },
+ { "[D]", deck },
};
/* key definitions */
@@ -66,6 +67,7 @@ static Key keys[] = {
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
+ { MODKEY, XK_c, setlayout, {.v = &layouts[3]} },
{ MODKEY, XK_space, setlayout, {0} },
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
{ MODKEY, XK_0, view, {.ui = ~0 } },
diff --git a/dwm.c b/dwm.c
index 1d78655..356ab44 100644
--- a/dwm.c
+++ b/dwm.c
@@ -171,6 +171,7 @@ static void configure(Client *c);
static void configurenotify(XEvent *e);
static void configurerequest(XEvent *e);
static Monitor *createmon(void);
+static void deck(Monitor *m);
static void destroynotify(XEvent *e);
static void detach(Client *c);
static void detachstack(Client *c);
@@ -669,6 +670,31 @@ destroynotify(XEvent *e) {
unmanage(c, True);
}
+void
+deck(Monitor *m) {
+ unsigned int i, n, h, mw, my;
+ Client *c;
+
+ for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
+ if(n == 0)
+ return;
+
+ if(n > m->nmaster) {
+ mw = m->nmaster ? m->ww * m->mfact : 0;
+ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n - m->nmaster);
+ }
+ else
+ mw = m->ww;
+ for(i = my = 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), False);
+ my += HEIGHT(c);
+ }
+ else
+ resize(c, m->wx + mw, m->wy, m->ww - mw - (2*c->bw), m->wh - (2*c->bw), False);
+}
+
void
detach(Client *c) {
Client **tc;
--
2.21.0

View File

@@ -0,0 +1,177 @@
diff --git a/dwm.c b/dwm.c
index a5ce993..45f1e27 100644
--- a/dwm.c
+++ b/dwm.c
@@ -112,6 +112,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 {
@@ -272,6 +274,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]; };
@@ -632,6 +643,7 @@ Monitor *
createmon(void)
{
Monitor *m;
+ unsigned int i;
m = ecalloc(1, sizeof(Monitor));
m->tagset[0] = m->tagset[1] = 1;
@@ -642,6 +654,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;
}
@@ -968,7 +994,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);
}
@@ -1503,9 +1529,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);
@@ -1524,7 +1550,7 @@ setmfact(const Arg *arg)
f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
if (f < 0.1 || f > 0.9)
return;
- selmon->mfact = f;
+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f;
arrange(selmon);
}
@@ -1701,7 +1727,7 @@ tile(Monitor *m)
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);
@@ -1740,9 +1766,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);
}
@@ -2036,11 +2086,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);
}

View File

@@ -0,0 +1,25 @@
diff -up a/dwm.c b/dwm.c
--- a/dwm.c 2020-07-09 16:49:10.023585649 +0200
+++ b/dwm.c 2020-07-09 16:49:43.497542191 +0200
@@ -702,7 +702,7 @@ drawbar(Monitor *m)
Client *c;
/* draw status first so it can be overdrawn by tags later */
- if (m == selmon) { /* status is only drawn on selected monitor */
+ if (m == selmon || 1) { /* status is only drawn on selected monitor */
drw_setscheme(drw, scheme[SchemeNorm]);
sw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0);
@@ -1987,9 +1987,11 @@ updatesizehints(Client *c)
void
updatestatus(void)
{
+ Monitor* m;
if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
strcpy(stext, "dwm-"VERSION);
- drawbar(selmon);
+ for(m = mons; m; m = m->next)
+ drawbar(m);
}
void

View File

@@ -0,0 +1,157 @@
diff --git a/config.def.h b/config.def.h
index 1c0b587..b67825e 100644
--- a/config.def.h
+++ b/config.def.h
@@ -103,7 +103,9 @@ static Button buttons[] = {
{ ClkLtSymbol, 0, Button1, setlayout, {0} },
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
{ ClkWinTitle, 0, Button2, zoom, {0} },
- { ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
+ { ClkStatusText, 0, Button1, sigdwmblocks, {.i = 1} },
+ { ClkStatusText, 0, Button2, sigdwmblocks, {.i = 2} },
+ { ClkStatusText, 0, Button3, sigdwmblocks, {.i = 3} },
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
diff --git a/dwm.c b/dwm.c
index 4465af1..c600131 100644
--- a/dwm.c
+++ b/dwm.c
@@ -156,6 +156,7 @@ static void clientmessage(XEvent *e);
static void configure(Client *c);
static void configurenotify(XEvent *e);
static void configurerequest(XEvent *e);
+static void copyvalidchars(char *text, char *rawtext);
static Monitor *createmon(void);
static void destroynotify(XEvent *e);
static void detach(Client *c);
@@ -169,6 +170,7 @@ static void focus(Client *c);
static void focusin(XEvent *e);
static void focusmon(const Arg *arg);
static void focusstack(const Arg *arg);
+static int getdwmblockspid();
static int getrootptr(int *x, int *y);
static long getstate(Window w);
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
@@ -205,6 +207,7 @@ static void setup(void);
static void seturgent(Client *c, int urg);
static void showhide(Client *c);
static void sigchld(int unused);
+static void sigdwmblocks(const Arg *arg);
static void spawn(const Arg *arg);
static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
@@ -237,6 +240,9 @@ static void zoom(const Arg *arg);
/* variables */
static const char broken[] = "broken";
static char stext[256];
+static char rawstext[256];
+static int dwmblockssig;
+pid_t dwmblockspid = 0;
static int screen;
static int sw, sh; /* X display screen geometry width, height */
static int bh, blw = 0; /* bar geometry */
@@ -439,9 +445,26 @@ buttonpress(XEvent *e)
arg.ui = 1 << i;
} else if (ev->x < x + blw)
click = ClkLtSymbol;
- else if (ev->x > selmon->ww - TEXTW(stext))
+ else if (ev->x > (x = selmon->ww - TEXTW(stext) + lrpad)) {
click = ClkStatusText;
- else
+
+ char *text = rawstext;
+ int i = -1;
+ char ch;
+ dwmblockssig = 0;
+ while (text[++i]) {
+ if ((unsigned char)text[i] < ' ') {
+ ch = text[i];
+ text[i] = '\0';
+ x += TEXTW(text) - lrpad;
+ text[i] = ch;
+ text += i+1;
+ i = -1;
+ if (x >= ev->x) break;
+ dwmblockssig = ch;
+ }
+ }
+ } else
click = ClkWinTitle;
} else if ((c = wintoclient(ev->window))) {
focus(c);
@@ -627,6 +650,19 @@ configurerequest(XEvent *e)
XSync(dpy, False);
}
+void
+copyvalidchars(char *text, char *rawtext)
+{
+ int i = -1, j = 0;
+
+ while(rawtext[++i]) {
+ if ((unsigned char)rawtext[i] >= ' ') {
+ text[j++] = rawtext[i];
+ }
+ }
+ text[j] = '\0';
+}
+
Monitor *
createmon(void)
{
@@ -871,6 +907,18 @@ getatomprop(Client *c, Atom prop)
return atom;
}
+int
+getdwmblockspid()
+{
+ char buf[16];
+ FILE *fp = popen("pidof -s dwmblocks", "r");
+ fgets(buf, sizeof(buf), fp);
+ pid_t pid = strtoul(buf, NULL, 10);
+ pclose(fp);
+ dwmblockspid = pid;
+ return pid != 0 ? 0 : -1;
+}
+
int
getrootptr(int *x, int *y)
{
@@ -1636,6 +1684,23 @@ sigchld(int unused)
while (0 < waitpid(-1, NULL, WNOHANG));
}
+void
+sigdwmblocks(const Arg *arg)
+{
+ union sigval sv;
+ sv.sival_int = (dwmblockssig << 8) | arg->i;
+ if (!dwmblockspid)
+ if (getdwmblockspid() == -1)
+ return;
+
+ if (sigqueue(dwmblockspid, SIGUSR1, sv) == -1) {
+ if (errno == ESRCH) {
+ if (!getdwmblockspid())
+ sigqueue(dwmblockspid, SIGUSR1, sv);
+ }
+ }
+}
+
void
spawn(const Arg *arg)
{
@@ -1987,8 +2052,10 @@ updatesizehints(Client *c)
void
updatestatus(void)
{
- if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
+ if (!gettextprop(root, XA_WM_NAME, rawstext, sizeof(rawstext)))
strcpy(stext, "dwm-"VERSION);
+ else
+ copyvalidchars(stext, rawstext);
drawbar(selmon);
}

746
dwm-systray-6.2.diff Normal file
View File

@@ -0,0 +1,746 @@
From 4001ccae7b1a41bdcb247b0cf095a51af7b68c28 Mon Sep 17 00:00:00 2001
From: Igor Gevka <igor.gevka@gmail.com>
Date: Sun, 16 Feb 2020 15:03:10 -0800
Subject: [PATCH] [PATCH] Implements a system tray for dwm.
Original author: Jan Christoph Ebersbach <jceb@e-jc.de>, inspired by http://code.google.com/p/dwm-plus
URL: http://dwm.suckless.org/patches/systray
dwm 6.2 port by Igor Gevka <igor.gevka@gmail.com>
---
config.def.h | 4 +
dwm.c | 404 +++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 382 insertions(+), 26 deletions(-)
diff --git a/config.def.h b/config.def.h
index 1c0b587..2d824d1 100644
--- a/config.def.h
+++ b/config.def.h
@@ -3,6 +3,10 @@
/* appearance */
static const unsigned int borderpx = 1; /* border pixel of windows */
static const unsigned int snap = 32; /* snap pixel */
+static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */
+static const unsigned int systrayspacing = 2; /* systray spacing */
+static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/
+static const int showsystray = 1; /* 0 means no systray */
static const int showbar = 1; /* 0 means no bar */
static const int topbar = 1; /* 0 means bottom bar */
static const char *fonts[] = { "monospace:size=10" };
diff --git a/dwm.c b/dwm.c
index 4465af1..3e361fa 100644
--- a/dwm.c
+++ b/dwm.c
@@ -57,12 +57,30 @@
#define TAGMASK ((1 << LENGTH(tags)) - 1)
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
+#define SYSTEM_TRAY_REQUEST_DOCK 0
+
+/* XEMBED messages */
+#define XEMBED_EMBEDDED_NOTIFY 0
+#define XEMBED_WINDOW_ACTIVATE 1
+#define XEMBED_FOCUS_IN 4
+#define XEMBED_MODALITY_ON 10
+
+#define XEMBED_MAPPED (1 << 0)
+#define XEMBED_WINDOW_ACTIVATE 1
+#define XEMBED_WINDOW_DEACTIVATE 2
+
+#define VERSION_MAJOR 0
+#define VERSION_MINOR 0
+#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR
+
/* enums */
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
enum { SchemeNorm, SchemeSel }; /* color schemes */
enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
+ NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, NetSystemTrayOrientationHorz,
NetWMFullscreen, NetActiveWindow, NetWMWindowType,
NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
+enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */
enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
@@ -141,6 +159,12 @@ typedef struct {
int monitor;
} Rule;
+typedef struct Systray Systray;
+struct Systray {
+ Window win;
+ Client *icons;
+};
+
/* function declarations */
static void applyrules(Client *c);
static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
@@ -169,8 +193,10 @@ static void focus(Client *c);
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 int getrootptr(int *x, int *y);
static long getstate(Window w);
+static unsigned int getsystraywidth();
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
static void grabbuttons(Client *c, int focused);
static void grabkeys(void);
@@ -188,13 +214,16 @@ static void pop(Client *);
static void propertynotify(XEvent *e);
static void quit(const Arg *arg);
static Monitor *recttomon(int x, int y, int w, int h);
+static void removesystrayicon(Client *i);
static void resize(Client *c, int x, int y, int w, int h, int interact);
+static void resizebarwin(Monitor *m);
static void resizeclient(Client *c, int x, int y, int w, int h);
static void resizemouse(const Arg *arg);
+static void resizerequest(XEvent *e);
static void restack(Monitor *m);
static void run(void);
static void scan(void);
-static int sendevent(Client *c, Atom proto);
+static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4);
static void sendmon(Client *c, Monitor *m);
static void setclientstate(Client *c, long state);
static void setfocus(Client *c);
@@ -206,6 +235,7 @@ static void seturgent(Client *c, int urg);
static void showhide(Client *c);
static void sigchld(int unused);
static void spawn(const Arg *arg);
+static Monitor *systraytomon(Monitor *m);
static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
static void tile(Monitor *);
@@ -223,18 +253,23 @@ static int updategeom(void);
static void updatenumlockmask(void);
static void updatesizehints(Client *c);
static void updatestatus(void);
+static void updatesystray(void);
+static void updatesystrayicongeom(Client *i, int w, int h);
+static void updatesystrayiconstate(Client *i, XPropertyEvent *ev);
static void updatetitle(Client *c);
static void updatewindowtype(Client *c);
static void updatewmhints(Client *c);
static void view(const Arg *arg);
static Client *wintoclient(Window w);
static Monitor *wintomon(Window w);
+static Client *wintosystrayicon(Window w);
static int xerror(Display *dpy, XErrorEvent *ee);
static int xerrordummy(Display *dpy, XErrorEvent *ee);
static int xerrorstart(Display *dpy, XErrorEvent *ee);
static void zoom(const Arg *arg);
/* variables */
+static Systray *systray = NULL;
static const char broken[] = "broken";
static char stext[256];
static int screen;
@@ -257,9 +292,10 @@ static void (*handler[LASTEvent]) (XEvent *) = {
[MapRequest] = maprequest,
[MotionNotify] = motionnotify,
[PropertyNotify] = propertynotify,
+ [ResizeRequest] = resizerequest,
[UnmapNotify] = unmapnotify
};
-static Atom wmatom[WMLast], netatom[NetLast];
+static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast];
static int running = 1;
static Cur *cursor[CurLast];
static Clr **scheme;
@@ -439,7 +475,7 @@ buttonpress(XEvent *e)
arg.ui = 1 << i;
} else if (ev->x < x + blw)
click = ClkLtSymbol;
- else if (ev->x > selmon->ww - TEXTW(stext))
+ else if (ev->x > selmon->ww - TEXTW(stext) - getsystraywidth())
click = ClkStatusText;
else
click = ClkWinTitle;
@@ -482,6 +518,11 @@ cleanup(void)
XUngrabKey(dpy, AnyKey, AnyModifier, root);
while (mons)
cleanupmon(mons);
+ if (showsystray) {
+ XUnmapWindow(dpy, systray->win);
+ XDestroyWindow(dpy, systray->win);
+ free(systray);
+ }
for (i = 0; i < CurLast; i++)
drw_cur_free(drw, cursor[i]);
for (i = 0; i < LENGTH(colors); i++)
@@ -512,9 +553,57 @@ cleanupmon(Monitor *mon)
void
clientmessage(XEvent *e)
{
+ XWindowAttributes wa;
+ XSetWindowAttributes swa;
XClientMessageEvent *cme = &e->xclient;
Client *c = wintoclient(cme->window);
+ if (showsystray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) {
+ /* add systray icons */
+ if (cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
+ if (!(c = (Client *)calloc(1, sizeof(Client))))
+ die("fatal: could not malloc() %u bytes\n", sizeof(Client));
+ if (!(c->win = cme->data.l[2])) {
+ free(c);
+ return;
+ }
+ c->mon = selmon;
+ c->next = systray->icons;
+ systray->icons = c;
+ if (!XGetWindowAttributes(dpy, c->win, &wa)) {
+ /* use sane defaults */
+ wa.width = bh;
+ wa.height = bh;
+ wa.border_width = 0;
+ }
+ c->x = c->oldx = c->y = c->oldy = 0;
+ c->w = c->oldw = wa.width;
+ c->h = c->oldh = wa.height;
+ c->oldbw = wa.border_width;
+ c->bw = 0;
+ c->isfloating = True;
+ /* reuse tags field as mapped status */
+ c->tags = 1;
+ updatesizehints(c);
+ updatesystrayicongeom(c, wa.width, wa.height);
+ XAddToSaveSet(dpy, c->win);
+ XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask);
+ XReparentWindow(dpy, c->win, systray->win, 0, 0);
+ /* use parents background color */
+ swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
+ XChangeWindowAttributes(dpy, c->win, CWBackPixel, &swa);
+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
+ /* FIXME not sure if I have to send these events, too */
+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_FOCUS_IN, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
+ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_MODALITY_ON, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
+ XSync(dpy, False);
+ resizebarwin(selmon);
+ updatesystray();
+ setclientstate(c, NormalState);
+ }
+ return;
+ }
if (!c)
return;
if (cme->message_type == netatom[NetWMState]) {
@@ -567,7 +656,7 @@ configurenotify(XEvent *e)
for (c = m->clients; c; c = c->next)
if (c->isfullscreen)
resizeclient(c, m->mx, m->my, m->mw, m->mh);
- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
+ resizebarwin(m);
}
focus(NULL);
arrange(NULL);
@@ -652,6 +741,11 @@ destroynotify(XEvent *e)
if ((c = wintoclient(ev->window)))
unmanage(c, 1);
+ else if ((c = wintosystrayicon(ev->window))) {
+ removesystrayicon(c);
+ resizebarwin(selmon);
+ updatesystray();
+ }
}
void
@@ -695,19 +789,23 @@ dirtomon(int dir)
void
drawbar(Monitor *m)
{
- int x, w, sw = 0;
+ int x, w, sw = 0, stw = 0;
int boxs = drw->fonts->h / 9;
int boxw = drw->fonts->h / 6 + 2;
unsigned int i, occ = 0, urg = 0;
Client *c;
+ if(showsystray && m == systraytomon(m))
+ stw = getsystraywidth();
+
/* draw status first so it can be overdrawn by tags later */
if (m == selmon) { /* status is only drawn on selected monitor */
drw_setscheme(drw, scheme[SchemeNorm]);
- sw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
- drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0);
+ sw = TEXTW(stext) - lrpad / 2 + 2; /* 2px right padding */
+ drw_text(drw, m->ww - sw - stw, 0, sw, bh, lrpad / 2 - 2, stext, 0);
}
+ resizebarwin(m);
for (c = m->clients; c; c = c->next) {
occ |= c->tags;
if (c->isurgent)
@@ -728,7 +826,7 @@ drawbar(Monitor *m)
drw_setscheme(drw, scheme[SchemeNorm]);
x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
- if ((w = m->ww - sw - x) > bh) {
+ if ((w = m->ww - sw - stw - 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);
@@ -739,7 +837,7 @@ drawbar(Monitor *m)
drw_rect(drw, x, 0, w, bh, 1, 1);
}
}
- drw_map(drw, m->barwin, 0, 0, m->ww, bh);
+ drw_map(drw, m->barwin, 0, 0, m->ww - stw, bh);
}
void
@@ -776,8 +874,11 @@ expose(XEvent *e)
Monitor *m;
XExposeEvent *ev = &e->xexpose;
- if (ev->count == 0 && (m = wintomon(ev->window)))
+ if (ev->count == 0 && (m = wintomon(ev->window))) {
drawbar(m);
+ if (m == selmon)
+ updatesystray();
+ }
}
void
@@ -862,10 +963,17 @@ getatomprop(Client *c, Atom prop)
unsigned long dl;
unsigned char *p = NULL;
Atom da, atom = None;
+ /* FIXME getatomprop should return the number of items and a pointer to
+ * the stored data instead of this workaround */
+ Atom req = XA_ATOM;
+ if (prop == xatom[XembedInfo])
+ req = xatom[XembedInfo];
- if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM,
+ if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req,
&da, &di, &dl, &dl, &p) == Success && p) {
atom = *(Atom *)p;
+ if (da == xatom[XembedInfo] && dl == 2)
+ atom = ((Atom *)p)[1];
XFree(p);
}
return atom;
@@ -899,6 +1007,16 @@ getstate(Window w)
return result;
}
+unsigned int
+getsystraywidth()
+{
+ unsigned int w = 0;
+ Client *i;
+ if(showsystray)
+ for(i = systray->icons; i; w += i->w + systrayspacing, i = i->next) ;
+ return w ? w + systrayspacing : 1;
+}
+
int
gettextprop(Window w, Atom atom, char *text, unsigned int size)
{
@@ -1003,7 +1121,7 @@ killclient(const Arg *arg)
{
if (!selmon->sel)
return;
- if (!sendevent(selmon->sel, wmatom[WMDelete])) {
+ if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) {
XGrabServer(dpy);
XSetErrorHandler(xerrordummy);
XSetCloseDownMode(dpy, DestroyAll);
@@ -1091,6 +1209,12 @@ maprequest(XEvent *e)
{
static XWindowAttributes wa;
XMapRequestEvent *ev = &e->xmaprequest;
+ Client *i;
+ if ((i = wintosystrayicon(ev->window))) {
+ sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION);
+ resizebarwin(selmon);
+ updatesystray();
+ }
if (!XGetWindowAttributes(dpy, ev->window, &wa))
return;
@@ -1215,6 +1339,16 @@ propertynotify(XEvent *e)
Window trans;
XPropertyEvent *ev = &e->xproperty;
+ if ((c = wintosystrayicon(ev->window))) {
+ if (ev->atom == XA_WM_NORMAL_HINTS) {
+ updatesizehints(c);
+ updatesystrayicongeom(c, c->w, c->h);
+ }
+ else
+ updatesystrayiconstate(c, ev);
+ resizebarwin(selmon);
+ updatesystray();
+ }
if ((ev->window == root) && (ev->atom == XA_WM_NAME))
updatestatus();
else if (ev->state == PropertyDelete)
@@ -1265,6 +1399,20 @@ recttomon(int x, int y, int w, int h)
return r;
}
+void
+removesystrayicon(Client *i)
+{
+ Client **ii;
+
+ if (!showsystray || !i)
+ return;
+ for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next);
+ if (ii)
+ *ii = i->next;
+ free(i);
+}
+
+
void
resize(Client *c, int x, int y, int w, int h, int interact)
{
@@ -1272,6 +1420,14 @@ resize(Client *c, int x, int y, int w, int h, int interact)
resizeclient(c, x, y, w, h);
}
+void
+resizebarwin(Monitor *m) {
+ unsigned int w = m->ww;
+ if (showsystray && m == systraytomon(m))
+ w -= getsystraywidth();
+ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh);
+}
+
void
resizeclient(Client *c, int x, int y, int w, int h)
{
@@ -1344,6 +1500,19 @@ resizemouse(const Arg *arg)
}
}
+void
+resizerequest(XEvent *e)
+{
+ XResizeRequestEvent *ev = &e->xresizerequest;
+ Client *i;
+
+ if ((i = wintosystrayicon(ev->window))) {
+ updatesystrayicongeom(i, ev->width, ev->height);
+ resizebarwin(selmon);
+ updatesystray();
+ }
+}
+
void
restack(Monitor *m)
{
@@ -1433,26 +1602,36 @@ setclientstate(Client *c, long state)
}
int
-sendevent(Client *c, Atom proto)
+sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4)
{
int n;
- Atom *protocols;
+ Atom *protocols, mt;
int exists = 0;
XEvent ev;
- if (XGetWMProtocols(dpy, c->win, &protocols, &n)) {
- while (!exists && n--)
- exists = protocols[n] == proto;
- XFree(protocols);
+ if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) {
+ mt = wmatom[WMProtocols];
+ if (XGetWMProtocols(dpy, w, &protocols, &n)) {
+ while (!exists && n--)
+ exists = protocols[n] == proto;
+ XFree(protocols);
+ }
+ }
+ else {
+ exists = True;
+ mt = proto;
}
if (exists) {
ev.type = ClientMessage;
- ev.xclient.window = c->win;
- ev.xclient.message_type = wmatom[WMProtocols];
+ ev.xclient.window = w;
+ ev.xclient.message_type = mt;
ev.xclient.format = 32;
- ev.xclient.data.l[0] = proto;
- ev.xclient.data.l[1] = CurrentTime;
- XSendEvent(dpy, c->win, False, NoEventMask, &ev);
+ ev.xclient.data.l[0] = d0;
+ ev.xclient.data.l[1] = d1;
+ ev.xclient.data.l[2] = d2;
+ ev.xclient.data.l[3] = d3;
+ ev.xclient.data.l[4] = d4;
+ XSendEvent(dpy, w, False, mask, &ev);
}
return exists;
}
@@ -1466,7 +1645,7 @@ setfocus(Client *c)
XA_WINDOW, 32, PropModeReplace,
(unsigned char *) &(c->win), 1);
}
- sendevent(c, wmatom[WMTakeFocus]);
+ sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0);
}
void
@@ -1555,6 +1734,10 @@ setup(void)
wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
+ netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False);
+ netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False);
+ netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False);
+ netatom[NetSystemTrayOrientationHorz] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION_HORZ", False);
netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
@@ -1562,6 +1745,9 @@ setup(void)
netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False);
+ xatom[Manager] = XInternAtom(dpy, "MANAGER", False);
+ xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False);
+ xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False);
/* init cursors */
cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr);
cursor[CurResize] = drw_cur_create(drw, XC_sizing);
@@ -1570,6 +1756,8 @@ setup(void)
scheme = ecalloc(LENGTH(colors), sizeof(Clr *));
for (i = 0; i < LENGTH(colors); i++)
scheme[i] = drw_scm_create(drw, colors[i], 3);
+ /* init system tray */
+ updatesystray();
/* init bars */
updatebars();
updatestatus();
@@ -1701,7 +1889,18 @@ togglebar(const Arg *arg)
{
selmon->showbar = !selmon->showbar;
updatebarpos(selmon);
- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
+ resizebarwin(selmon);
+ if (showsystray) {
+ XWindowChanges wc;
+ if (!selmon->showbar)
+ wc.y = -bh;
+ else if (selmon->showbar) {
+ wc.y = 0;
+ if (!selmon->topbar)
+ wc.y = selmon->mh - bh;
+ }
+ XConfigureWindow(dpy, systray->win, CWY, &wc);
+ }
arrange(selmon);
}
@@ -1796,11 +1995,18 @@ unmapnotify(XEvent *e)
else
unmanage(c, 0);
}
+ else if ((c = wintosystrayicon(ev->window))) {
+ /* KLUDGE! sometimes icons occasionally unmap their windows, but do
+ * _not_ destroy them. We map those windows back */
+ XMapRaised(dpy, c->win);
+ updatesystray();
+ }
}
void
updatebars(void)
{
+ unsigned int w;
Monitor *m;
XSetWindowAttributes wa = {
.override_redirect = True,
@@ -1811,10 +2017,15 @@ updatebars(void)
for (m = mons; m; m = m->next) {
if (m->barwin)
continue;
- m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
+ w = m->ww;
+ if (showsystray && m == systraytomon(m))
+ w -= getsystraywidth();
+ m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, bh, 0, DefaultDepth(dpy, screen),
CopyFromParent, DefaultVisual(dpy, screen),
CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor);
+ if (showsystray && m == systraytomon(m))
+ XMapRaised(dpy, systray->win);
XMapRaised(dpy, m->barwin);
XSetClassHint(dpy, m->barwin, &ch);
}
@@ -1990,6 +2201,121 @@ updatestatus(void)
if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
strcpy(stext, "dwm-"VERSION);
drawbar(selmon);
+ updatesystray();
+}
+
+void
+updatesystrayicongeom(Client *i, int w, int h)
+{
+ if (i) {
+ i->h = bh;
+ if (w == h)
+ i->w = bh;
+ else if (h == bh)
+ i->w = w;
+ else
+ i->w = (int) ((float)bh * ((float)w / (float)h));
+ applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False);
+ /* force icons into the systray dimensions if they don't want to */
+ if (i->h > bh) {
+ if (i->w == i->h)
+ i->w = bh;
+ else
+ i->w = (int) ((float)bh * ((float)i->w / (float)i->h));
+ i->h = bh;
+ }
+ }
+}
+
+void
+updatesystrayiconstate(Client *i, XPropertyEvent *ev)
+{
+ long flags;
+ int code = 0;
+
+ if (!showsystray || !i || ev->atom != xatom[XembedInfo] ||
+ !(flags = getatomprop(i, xatom[XembedInfo])))
+ return;
+
+ if (flags & XEMBED_MAPPED && !i->tags) {
+ i->tags = 1;
+ code = XEMBED_WINDOW_ACTIVATE;
+ XMapRaised(dpy, i->win);
+ setclientstate(i, NormalState);
+ }
+ else if (!(flags & XEMBED_MAPPED) && i->tags) {
+ i->tags = 0;
+ code = XEMBED_WINDOW_DEACTIVATE;
+ XUnmapWindow(dpy, i->win);
+ setclientstate(i, WithdrawnState);
+ }
+ else
+ return;
+ sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0,
+ systray->win, XEMBED_EMBEDDED_VERSION);
+}
+
+void
+updatesystray(void)
+{
+ XSetWindowAttributes wa;
+ XWindowChanges wc;
+ Client *i;
+ Monitor *m = systraytomon(NULL);
+ unsigned int x = m->mx + m->mw;
+ unsigned int w = 1;
+
+ if (!showsystray)
+ return;
+ if (!systray) {
+ /* init systray */
+ if (!(systray = (Systray *)calloc(1, sizeof(Systray))))
+ die("fatal: could not malloc() %u bytes\n", sizeof(Systray));
+ systray->win = XCreateSimpleWindow(dpy, root, x, m->by, w, bh, 0, 0, scheme[SchemeSel][ColBg].pixel);
+ wa.event_mask = ButtonPressMask | ExposureMask;
+ wa.override_redirect = True;
+ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
+ XSelectInput(dpy, systray->win, SubstructureNotifyMask);
+ XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char *)&netatom[NetSystemTrayOrientationHorz], 1);
+ XChangeWindowAttributes(dpy, systray->win, CWEventMask|CWOverrideRedirect|CWBackPixel, &wa);
+ XMapRaised(dpy, systray->win);
+ XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime);
+ if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) {
+ sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0);
+ XSync(dpy, False);
+ }
+ else {
+ fprintf(stderr, "dwm: unable to obtain system tray.\n");
+ free(systray);
+ systray = NULL;
+ return;
+ }
+ }
+ for (w = 0, i = systray->icons; i; i = i->next) {
+ /* make sure the background color stays the same */
+ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
+ XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa);
+ XMapRaised(dpy, i->win);
+ w += systrayspacing;
+ i->x = w;
+ XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h);
+ w += i->w;
+ if (i->mon != m)
+ i->mon = m;
+ }
+ w = w ? w + systrayspacing : 1;
+ x -= w;
+ XMoveResizeWindow(dpy, systray->win, x, m->by, w, bh);
+ wc.x = x; wc.y = m->by; wc.width = w; wc.height = bh;
+ wc.stack_mode = Above; wc.sibling = m->barwin;
+ XConfigureWindow(dpy, systray->win, CWX|CWY|CWWidth|CWHeight|CWSibling|CWStackMode, &wc);
+ XMapWindow(dpy, systray->win);
+ XMapSubwindows(dpy, systray->win);
+ /* redraw background */
+ XSetForeground(dpy, drw->gc, scheme[SchemeNorm][ColBg].pixel);
+ XFillRectangle(dpy, systray->win, drw->gc, 0, 0, w, bh);
+ XSync(dpy, False);
}
void
@@ -2057,6 +2383,16 @@ wintoclient(Window w)
return NULL;
}
+Client *
+wintosystrayicon(Window w) {
+ Client *i = NULL;
+
+ if (!showsystray || !w)
+ return i;
+ for (i = systray->icons; i && i->win != w; i = i->next) ;
+ return i;
+}
+
Monitor *
wintomon(Window w)
{
@@ -2110,6 +2446,22 @@ xerrorstart(Display *dpy, XErrorEvent *ee)
return -1;
}
+Monitor *
+systraytomon(Monitor *m) {
+ Monitor *t;
+ int i, n;
+ if(!systraypinning) {
+ if(!m)
+ return selmon;
+ return m == selmon ? m : NULL;
+ }
+ for(n = 1, t = mons; t && t->next; n++, t = t->next) ;
+ for(i = 1, t = mons; t && t->next && i < systraypinning; i++, t = t->next) ;
+ if(systraypinningfailfirst && n < systraypinning)
+ return mons;
+ return t;
+}
+
void
zoom(const Arg *arg)
{
--
2.17.1

692
dwm.c

File diff suppressed because it is too large Load Diff