mirror of
https://github.com/mintycube/dwm.git
synced 2024-10-22 14:05:45 +02:00
[dwm][PATCH] Multiple scratchpads
This patch enables multiple scratchpads, each with one assigned window. This enables the same scratchpad workflow that you have in i3. Scratchpads are implemented as special tags, whose mask does not apply to new spawned windows. To assign a window to a scratchpad you have to set up a rule, as you do with regular tags. Windows tagged with scratchpad tags can be set floating or not in the rules array. Most users would probably want them floating (i3 style), but having them tiled does also perfectly work and might fit better the DWM approach. In case they are set floating, the patch moves them to the center of the screen whenever the are shown. The patch can easily be modified to make this last feature configurable in the rules array (see the center patch). The togglescratch function, borrowed from the previous scratchpad patch and slightly modified, can be used to spawn a registered scratchpad process or toggle its view. This function looks for a window tagged on the selected scratchpad. If it is found its view is toggled. If it is not found the corresponding registered command is spawned. The config.def.h shows three examples of its use to spawn a terminal in the first scratchpad tag, a second terminal running ranger on the second scratchpad tag and the keepassxc application to manage passwords on a third scratchpad tag. If you prefer to spawn your scratchpad applications from the startup script, you might opt for binding keys to toggleview instead, as scratchpads are just special tags (you may even extend the TAGKEYS macro to generalize the key bindings).
This commit is contained in:
parent
525dc0d107
commit
f9a001dee7
@ -15,6 +15,8 @@ Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on t
|
||||
|
||||
### Changelog:
|
||||
|
||||
2020-04-16 - Upgraded the scratchpad patch to the multiple scratchpads patch \[[ref](https://lists.suckless.org/hackers/2004/17205.html)\]
|
||||
|
||||
2020-04-13 - Added statuscmd patch
|
||||
|
||||
2020-03-31 - Added the rounded corners patch
|
||||
|
29
config.def.h
29
config.def.h
@ -256,6 +256,18 @@ char *colors[][3] = {
|
||||
};
|
||||
#endif // VTCOLORS_PATCH / FLOAT_BORDER_COLOR_PATCH
|
||||
|
||||
#if SCRATCHPAD_PATCH
|
||||
const char *spcmd1[] = {"st", "-n", "spterm", "-g", "120x34", NULL };
|
||||
const char *spcmd2[] = {"st", "-n", "spfm", "-g", "144x41", "-e", "ranger", NULL };
|
||||
const char *spcmd3[] = {"keepassxc", NULL };
|
||||
static Sp scratchpads[] = {
|
||||
/* name cmd */
|
||||
{"spterm", spcmd1},
|
||||
{"spranger", spcmd2},
|
||||
{"keepassxc", spcmd3},
|
||||
};
|
||||
#endif // SCRATCHPAD_PATCH
|
||||
|
||||
/* tagging */
|
||||
#if EWMHTAGS_PATCH
|
||||
static char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
|
||||
@ -418,6 +430,11 @@ static const Rule rules[] = {
|
||||
/* class instance title tags mask isfloating monitor */
|
||||
{ "Gimp", NULL, NULL, 0, 1, -1 },
|
||||
{ "Firefox", NULL, NULL, 1 << 8, 0, -1 },
|
||||
#if SCRATCHPAD_PATCH
|
||||
{ NULL, "spterm", NULL, SPTAG(0), 1, -1 },
|
||||
{ NULL, "spfm", NULL, SPTAG(1), 1, -1 },
|
||||
{ NULL, "keepassxc",NULL, SPTAG(2), 0, -1 },
|
||||
#endif // SCRATCHPAD_PATCH
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -679,10 +696,6 @@ static const char *statuscmds[] = { "notify-send Mouse$BUTTON" };
|
||||
static char *statuscmd[] = { "/bin/sh", "-c", NULL, NULL };
|
||||
#endif // STATUSCMD_PATCH
|
||||
|
||||
#if SCRATCHPAD_PATCH
|
||||
static const char scratchpadname[] = "scratchpad";
|
||||
static const char *scratchpadcmd[] = { "st", "-t", scratchpadname, "-g", "120x34", NULL };
|
||||
#endif // SCRATCHPAD_PATCH
|
||||
#if SCRATCHPAD_ALT_1_PATCH
|
||||
static const unsigned scratchpad_mask = 1u << sizeof tags / sizeof * tags;
|
||||
#endif // SCRATCHPAD_ALT_1_PATCH
|
||||
@ -691,9 +704,6 @@ static Key keys[] = {
|
||||
/* modifier key function argument */
|
||||
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
|
||||
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
|
||||
#if SCRATCHPAD_PATCH
|
||||
{ MODKEY, XK_grave, togglescratch, {.v = scratchpadcmd } },
|
||||
#endif // SCRATCHPAD_PATCH
|
||||
{ MODKEY, XK_b, togglebar, {0} },
|
||||
#if STACKER_PATCH
|
||||
STACKKEYS(MODKEY, focus)
|
||||
@ -815,6 +825,11 @@ static Key keys[] = {
|
||||
{ MODKEY|ControlMask|ShiftMask, XK_k, toggleverticalmax, {0} },
|
||||
{ MODKEY|ControlMask, XK_m, togglemax, {0} },
|
||||
#endif // MAXIMIZE_PATCH
|
||||
#if SCRATCHPAD_PATCH
|
||||
{ MODKEY, XK_grave, togglescratch, {.ui = 0 } },
|
||||
{ MODKEY|ControlMask, XK_grave, togglescratch, {.ui = 1 } },
|
||||
{ MODKEY|ShiftMask, XK_grave, togglescratch, {.ui = 2 } },
|
||||
#endif // SCRATCHPAD_PATCH
|
||||
#if UNFLOATVISIBLE_PATCH
|
||||
{ MODKEY|Mod4Mask, XK_space, unfloatvisible, {0} },
|
||||
{ MODKEY|ShiftMask, XK_t, unfloatvisible, {.v = &layouts[0]} },
|
||||
|
38
dwm.c
38
dwm.c
@ -75,7 +75,14 @@
|
||||
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
|
||||
#define WIDTH(X) ((X)->w + 2 * (X)->bw)
|
||||
#define HEIGHT(X) ((X)->h + 2 * (X)->bw)
|
||||
#if SCRATCHPAD_PATCH
|
||||
#define NUMTAGS (LENGTH(tags) + LENGTH(scratchpads))
|
||||
#define TAGMASK ((1 << NUMTAGS) - 1)
|
||||
#define SPTAG(i) ((1 << LENGTH(tags)) << (i))
|
||||
#define SPTAGMASK (((1 << LENGTH(scratchpads))-1) << LENGTH(tags))
|
||||
#else
|
||||
#define TAGMASK ((1 << LENGTH(tags)) - 1)
|
||||
#endif // SCRATCHPAD_PATCH
|
||||
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
|
||||
|
||||
/* enums */
|
||||
@ -528,6 +535,12 @@ applyrules(Client *c)
|
||||
#endif // SWALLOW_PATCH
|
||||
c->isfloating = r->isfloating;
|
||||
c->tags |= r->tags;
|
||||
#if SCRATCHPAD_PATCH && !SCRATCHPAD_KEEP_POSITION_AND_SIZE_PATCH
|
||||
if ((r->tags & SPTAGMASK) && r->isfloating) {
|
||||
c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2);
|
||||
c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2);
|
||||
}
|
||||
#endif // SCRATCHPAD_PATCH | SCRATCHPAD_KEEP_POSITION_AND_SIZE_PATCH
|
||||
for (m = mons; m && m->num != r->monitor; m = m->next);
|
||||
if (m)
|
||||
c->mon = m;
|
||||
@ -559,8 +572,14 @@ applyrules(Client *c)
|
||||
XFree(ch.res_name);
|
||||
#if EMPTYVIEW_PATCH
|
||||
if(c->tags & TAGMASK) c->tags = c->tags & TAGMASK;
|
||||
#if SCRATCHPAD_PATCH
|
||||
else if(c->mon->tagset[c->mon->seltags]) c->tags = c->mon->tagset[c->mon->seltags] & ~SPTAGMASK;
|
||||
#else
|
||||
else if(c->mon->tagset[c->mon->seltags]) c->tags = c->mon->tagset[c->mon->seltags];
|
||||
#endif // SCRATCHPAD_PATCH
|
||||
else c->tags = 1;
|
||||
#elif SCRATCHPAD_PATCH
|
||||
c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : (c->mon->tagset[c->mon->seltags] & ~SPTAGMASK);
|
||||
#else
|
||||
c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags];
|
||||
#endif // EMPTYVIEW_PATCH
|
||||
@ -2115,16 +2134,6 @@ manage(Window w, XWindowAttributes *wa)
|
||||
c->bw = borderpx;
|
||||
#endif // SETBORDERPX_PATCH
|
||||
|
||||
#if SCRATCHPAD_PATCH
|
||||
selmon->tagset[selmon->seltags] &= ~scratchtag;
|
||||
if (!strcmp(c->name, scratchpadname)) {
|
||||
c->mon->tagset[c->mon->seltags] |= c->tags = scratchtag;
|
||||
c->isfloating = True;
|
||||
c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2);
|
||||
c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2);
|
||||
}
|
||||
#endif // SCRATCHPAD_PATCH
|
||||
|
||||
wc.border_width = c->bw;
|
||||
XConfigureWindow(dpy, w, CWBorderWidth, &wc);
|
||||
#if FLOAT_BORDER_COLOR_PATCH
|
||||
@ -3081,6 +3090,12 @@ showhide(Client *c)
|
||||
if (!c)
|
||||
return;
|
||||
if (ISVISIBLE(c)) {
|
||||
#if SCRATCHPAD_PATCH && !SCRATCHPAD_KEEP_POSITION_AND_SIZE_PATCH
|
||||
if ((c->tags & SPTAGMASK) && c->isfloating) {
|
||||
c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2);
|
||||
c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2);
|
||||
}
|
||||
#endif // SCRATCHPAD_PATCH | SCRATCHPAD_KEEP_POSITION_AND_SIZE_PATCH
|
||||
/* show clients top down */
|
||||
#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
|
||||
if (!c->mon->lt[c->mon->sellt]->arrange && c->sfx != -9999 && !c->isfullscreen) {
|
||||
@ -3149,9 +3164,6 @@ spawn(const Arg *arg)
|
||||
}
|
||||
#endif // STATUSCMD_PATCH
|
||||
|
||||
#if SCRATCHPAD_PATCH
|
||||
selmon->tagset[selmon->seltags] &= ~scratchtag;
|
||||
#endif // SCRATCHPAD_PATCH
|
||||
if (fork() == 0) {
|
||||
if (dpy)
|
||||
close(ConnectionNumber(dpy));
|
||||
|
@ -1,23 +1,25 @@
|
||||
static unsigned int scratchtag = 1 << LENGTH(tags);
|
||||
|
||||
void
|
||||
togglescratch(const Arg *arg)
|
||||
{
|
||||
Client *c;
|
||||
unsigned int found = 0;
|
||||
Client *c;
|
||||
unsigned int found = 0;
|
||||
unsigned int scratchtag = SPTAG(arg->ui);
|
||||
Arg sparg = {.v = scratchpads[arg->ui].cmd};
|
||||
|
||||
for (c = selmon->clients; c && !(found = c->tags & scratchtag); c = c->next);
|
||||
if (found) {
|
||||
unsigned int newtagset = selmon->tagset[selmon->seltags] ^ scratchtag;
|
||||
if (newtagset) {
|
||||
selmon->tagset[selmon->seltags] = newtagset;
|
||||
focus(NULL);
|
||||
arrange(selmon);
|
||||
}
|
||||
if (ISVISIBLE(c)) {
|
||||
focus(c);
|
||||
restack(selmon);
|
||||
}
|
||||
} else
|
||||
spawn(arg);
|
||||
for (c = selmon->clients; c && !(found = c->tags & scratchtag); c = c->next);
|
||||
if (found) {
|
||||
unsigned int newtagset = selmon->tagset[selmon->seltags] ^ scratchtag;
|
||||
if (newtagset) {
|
||||
selmon->tagset[selmon->seltags] = newtagset;
|
||||
focus(NULL);
|
||||
arrange(selmon);
|
||||
}
|
||||
if (ISVISIBLE(c)) {
|
||||
focus(c);
|
||||
restack(selmon);
|
||||
}
|
||||
} else {
|
||||
selmon->tagset[selmon->seltags] |= scratchtag;
|
||||
spawn(&sparg);
|
||||
}
|
||||
}
|
@ -1 +1,6 @@
|
||||
typedef struct {
|
||||
const char *name;
|
||||
const void *cmd;
|
||||
} Sp;
|
||||
|
||||
static void togglescratch(const Arg *arg);
|
@ -397,12 +397,21 @@
|
||||
*/
|
||||
#define SAVEFLOATS_PATCH 0
|
||||
|
||||
/* The scratchpad patch allows you to spawn or restore a floating terminal window.
|
||||
/* The scratchpad patch allows you to spawn or restore floating terminal windows.
|
||||
* It is typically useful when one need to do some short typing.
|
||||
* Upgraded to Christian Tenllado's multiple scratchpad version.
|
||||
* https://lists.suckless.org/hackers/2004/17205.html
|
||||
* https://dwm.suckless.org/patches/scratchpad/
|
||||
*/
|
||||
#define SCRATCHPAD_PATCH 0
|
||||
|
||||
/* The scratchpad patch above automatically resizes and centers the scratchpad window every
|
||||
* time you spawn it. This alteration of the patch disables that so that the size and position
|
||||
* of the scratchpad window is retained when you respawn it. If you enable this then you may
|
||||
* want to also take the centered patch and enable the iscentered flag for floating scratchpads.
|
||||
*/
|
||||
#define SCRATCHPAD_KEEP_POSITION_AND_SIZE_PATCH 0
|
||||
|
||||
/* This alternative patch enables a scratchpad feature in dwm similar to the scratchpad
|
||||
* feature in i3wm.
|
||||
* https://github.com/GasparVardanyan/dwm-scratchpad
|
||||
|
Loading…
Reference in New Issue
Block a user