dwm-scratchpads-20200414-728d397b.diff - sites - public wiki contents of suckle… | |
git clone git://git.suckless.org/sites | |
Log | |
Files | |
Refs | |
--- | |
dwm-scratchpads-20200414-728d397b.diff (7977B) | |
--- | |
1 From 728d397b21982af88737277fd9d6939a7b558786 Mon Sep 17 00:00:00 2001 | |
2 From: Christian Tenllado <[email protected]> | |
3 Date: Tue, 14 Apr 2020 23:31:15 +0200 | |
4 Subject: [PATCH] Multiple scratchpads | |
5 | |
6 This patch enables multiple scratchpads, each with one asigned window. | |
7 This enables the same scratchpad workflow that you have in i3. | |
8 | |
9 Scratchpads are implemented as special tags, whose mask does not | |
10 apply to new spawned windows. To assign a window to a scratchpad you | |
11 have to set up a rule, as you do with regular tags. | |
12 | |
13 Windows tagged with scratchpad tags can be set floating or not in the | |
14 rules array. Most users would probably want them floating (i3 style), | |
15 but having them tiled does also perfectly work and might fit better the | |
16 DWM approach. In case they are set floating, the patch moves them to the | |
17 center of the screen whenever they are shown. The patch can easily be | |
18 modified to make this last feature configurable in the rules array (see | |
19 the center patch). | |
20 | |
21 The togglescratch function, borrowed from the previous scratchpad patch | |
22 and slightly modified, can be used to spawn a registered scratchpad | |
23 process or toggle its view. This function looks for a window tagged with | |
24 the selected scratchpad tag. If it is found its view is toggled. If it is | |
25 not found the corresponding registered command is spawned. The | |
26 config.def.h shows three examples of its use to spawn a terminal in the | |
27 first scratchpad tag, a second terminal running ranger on the second | |
28 scratchpad tag and the keepassxc application to manage passwords on a | |
29 third scratchpad tag. | |
30 | |
31 If you prefer to spawn your scratchpad applications from the startup | |
32 script, you might opt for binding keys to toggleview instead, as | |
33 scratchpads are just special tags (you may even extend the TAGKEYS macro | |
34 to generalize the key bindings). | |
35 --- | |
36 config.def.h | 28 ++++++++++++++++++++++++---- | |
37 dwm.c | 43 +++++++++++++++++++++++++++++++++++++++++-- | |
38 2 files changed, 65 insertions(+), 6 deletions(-) | |
39 | |
40 diff --git a/config.def.h b/config.def.h | |
41 index 1c0b587..06265e1 100644 | |
42 --- a/config.def.h | |
43 +++ b/config.def.h | |
44 @@ -18,17 +18,33 @@ static const char *colors[][3] = { | |
45 [SchemeSel] = { col_gray4, col_cyan, col_cyan }, | |
46 }; | |
47 | |
48 +typedef struct { | |
49 + const char *name; | |
50 + const void *cmd; | |
51 +} Sp; | |
52 +const char *spcmd1[] = {"st", "-n", "spterm", "-g", "120x34", NULL }; | |
53 +const char *spcmd2[] = {"st", "-n", "spfm", "-g", "144x41", "-e", "rang… | |
54 +const char *spcmd3[] = {"keepassxc", NULL }; | |
55 +static Sp scratchpads[] = { | |
56 + /* name cmd */ | |
57 + {"spterm", spcmd1}, | |
58 + {"spranger", spcmd2}, | |
59 + {"keepassxc", spcmd3}, | |
60 +}; | |
61 + | |
62 /* tagging */ | |
63 static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "… | |
64 - | |
65 static const Rule rules[] = { | |
66 /* xprop(1): | |
67 * WM_CLASS(STRING) = instance, class | |
68 * WM_NAME(STRING) = title | |
69 */ | |
70 /* class instance title tags mask isfloating … | |
71 - { "Gimp", NULL, NULL, 0, 1, … | |
72 - { "Firefox", NULL, NULL, 1 << 8, 0, … | |
73 + { "Gimp", NULL, NULL, … | |
74 + { "Firefox", NULL, NULL, … | |
75 + { NULL, "spterm", NULL, … | |
76 + { NULL, "spfm", NULL, … | |
77 + { NULL, "keepassxc", NULL, … | |
78 }; | |
79 | |
80 /* layout(s) */ | |
81 @@ -59,6 +75,7 @@ static char dmenumon[2] = "0"; /* component of dmenucm… | |
82 static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", d… | |
83 static const char *termcmd[] = { "st", NULL }; | |
84 | |
85 + | |
86 static Key keys[] = { | |
87 /* modifier key function argu… | |
88 { MODKEY, XK_p, spawn, {.v … | |
89 @@ -84,6 +101,9 @@ static Key keys[] = { | |
90 { MODKEY, XK_period, focusmon, {.i … | |
91 { MODKEY|ShiftMask, XK_comma, tagmon, {.i … | |
92 { MODKEY|ShiftMask, XK_period, tagmon, {.i … | |
93 + { MODKEY, XK_y, … | |
94 + { MODKEY, XK_u, to… | |
95 + { MODKEY, XK_x, to… | |
96 TAGKEYS( XK_1, 0) | |
97 TAGKEYS( XK_2, 1) | |
98 TAGKEYS( XK_3, 2) | |
99 @@ -106,7 +126,7 @@ static Button buttons[] = { | |
100 { ClkStatusText, 0, Button2, spawn, … | |
101 { ClkClientWin, MODKEY, Button1, movemou… | |
102 { ClkClientWin, MODKEY, Button2, togglef… | |
103 - { ClkClientWin, MODKEY, Button3, resizem… | |
104 + { ClkClientWin, MODKEY, Button1, resizem… | |
105 { ClkTagBar, 0, Button1, view, … | |
106 { ClkTagBar, 0, Button3, togglev… | |
107 { ClkTagBar, MODKEY, Button1, tag, … | |
108 diff --git a/dwm.c b/dwm.c | |
109 index 4465af1..646aa1a 100644 | |
110 --- a/dwm.c | |
111 +++ b/dwm.c | |
112 @@ -54,7 +54,10 @@ | |
113 #define MOUSEMASK (BUTTONMASK|PointerMotionMask) | |
114 #define WIDTH(X) ((X)->w + 2 * (X)->bw) | |
115 #define HEIGHT(X) ((X)->h + 2 * (X)->bw) | |
116 -#define TAGMASK ((1 << LENGTH(tags)) - 1) | |
117 +#define NUMTAGS (LENGTH(tags) + … | |
118 +#define TAGMASK ((1 << NUMTAGS) - 1) | |
119 +#define SPTAG(i) ((1 << LENGTH(tags)) <… | |
120 +#define SPTAGMASK (((1 << LENGTH(scratchpads)… | |
121 #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) | |
122 | |
123 /* enums */ | |
124 @@ -211,6 +214,7 @@ static void tagmon(const Arg *arg); | |
125 static void tile(Monitor *); | |
126 static void togglebar(const Arg *arg); | |
127 static void togglefloating(const Arg *arg); | |
128 +static void togglescratch(const Arg *arg); | |
129 static void toggletag(const Arg *arg); | |
130 static void toggleview(const Arg *arg); | |
131 static void unfocus(Client *c, int setfocus); | |
132 @@ -299,6 +303,11 @@ applyrules(Client *c) | |
133 { | |
134 c->isfloating = r->isfloating; | |
135 c->tags |= r->tags; | |
136 + if ((r->tags & SPTAGMASK) && r->isfloating) { | |
137 + c->x = c->mon->wx + (c->mon->ww / 2 - W… | |
138 + c->y = c->mon->wy + (c->mon->wh / 2 - H… | |
139 + } | |
140 + | |
141 for (m = mons; m && m->num != r->monitor; m = m… | |
142 if (m) | |
143 c->mon = m; | |
144 @@ -308,7 +317,7 @@ applyrules(Client *c) | |
145 XFree(ch.res_class); | |
146 if (ch.res_name) | |
147 XFree(ch.res_name); | |
148 - c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagse… | |
149 + c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : (c->mon->tags… | |
150 } | |
151 | |
152 int | |
153 @@ -1616,6 +1625,10 @@ showhide(Client *c) | |
154 if (!c) | |
155 return; | |
156 if (ISVISIBLE(c)) { | |
157 + if ((c->tags & SPTAGMASK) && c->isfloating) { | |
158 + c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) … | |
159 + c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c)… | |
160 + } | |
161 /* show clients top down */ | |
162 XMoveWindow(dpy, c->win, c->x, c->y); | |
163 if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloati… | |
164 @@ -1719,6 +1732,32 @@ togglefloating(const Arg *arg) | |
165 arrange(selmon); | |
166 } | |
167 | |
168 +void | |
169 +togglescratch(const Arg *arg) | |
170 +{ | |
171 + Client *c; | |
172 + unsigned int found = 0; | |
173 + unsigned int scratchtag = SPTAG(arg->ui); | |
174 + Arg sparg = {.v = scratchpads[arg->ui].cmd}; | |
175 + | |
176 + for (c = selmon->clients; c && !(found = c->tags & scratchtag);… | |
177 + if (found) { | |
178 + unsigned int newtagset = selmon->tagset[selmon->seltags… | |
179 + if (newtagset) { | |
180 + selmon->tagset[selmon->seltags] = newtagset; | |
181 + focus(NULL); | |
182 + arrange(selmon); | |
183 + } | |
184 + if (ISVISIBLE(c)) { | |
185 + focus(c); | |
186 + restack(selmon); | |
187 + } | |
188 + } else { | |
189 + selmon->tagset[selmon->seltags] |= scratchtag; | |
190 + spawn(&sparg); | |
191 + } | |
192 +} | |
193 + | |
194 void | |
195 toggletag(const Arg *arg) | |
196 { | |
197 -- | |
198 2.20.1 | |
199 |