Compare commits

...
Sign in to create a new pull request.

8 commits

Author SHA1 Message Date
d19bb915e1
scratchpad - Patch 2025-02-14 22:45:11 -05:00
361054b838
movestack - Patch 2025-02-14 22:32:24 -05:00
1306d2d540
autocenter - Patch 2025-02-14 22:24:05 -05:00
dd8e930f3f
Attach Bottom - Patch 2025-02-14 22:19:22 -05:00
6e9eaf61ac
better stuff 2025-01-27 06:25:23 -05:00
5eb2db4061
Quality of Life 2025-01-27 05:48:41 -05:00
162f3c32f2
My version of DWM 2025-01-26 23:56:56 -05:00
5a38a89afd
Sourced DWM 2025-01-26 14:50:48 -05:00
9 changed files with 2691 additions and 28 deletions

View file

@ -20,7 +20,7 @@ dwm: ${OBJ}
${CC} -o $@ ${OBJ} ${LDFLAGS}
clean:
rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz
rm -f dwm ${OBJ} config.h dwm-${VERSION}.tar.gz
dist: clean
mkdir -p dwm-${VERSION}

View file

@ -1,34 +1,54 @@
/* See LICENSE file for copyright and license details. */
/* appearance */
static const unsigned int borderpx = 1; /* border pixel of windows */
static const unsigned int borderpx = 3; /* 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 */
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_gray3, col_gray1, col_gray2 },
[SchemeSel] = { col_gray4, col_cyan, col_cyan },
/*static const char *fonts[] = { "monospace:size=16" };
*/
static const char *fonts[] = {"Mononoki Nerd Font:size=16:antialias=true:autohint=true",
"Hack:size=14:antialias=true:autohint=true",
"JoyPixels:size=16:antialias=true:autohint=true"};
#include "/home/moo/.config/themes/using/colors-wal-dwm.h"
typedef struct {
const char *name;
const void *cmd;
} Sp;
const char *spcmd1[] = {"st", "-n", "spterm", "-g", "120x34", NULL };
const char *spcmd2[] = {"st", "-n", "spfm", "-g", "144x41", "-e", "ls", NULL };
const char *spcmd3[] = {"keepassxc", NULL };
static Sp scratchpads[] = {
/* name cmd */
{"spterm", spcmd1},
{"spranger", spcmd2},
{"keepassxc", spcmd3},
};
/* tagging */
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
/*static const char *tags[] = { "", "", "", "", "", "", "7", "8", "9" };
*/
static const char *tags[] = { "", "", "", "", "", "", "", "", "" };
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 isfloating monitor */
{ "Gimp", NULL, NULL, 1 << 6, 0, -1 },
{ NULL, NULL, "pulsemixer", 0, 1, -1 },
{ "waterfox", NULL, NULL, 1, 0, -1 },
{ "Element", NULL, NULL, 1 << 8, 0, -1 },
{ NULL, NULL, "LibreWolf", 1 << 0, 0, -1 },
{ NULL, NULL, "Waterfox", 1 << 0, 0, -1 },
{ NULL, NULL, "Discord", 1 << 8, 0, -1 },
{ "mpv", NULL, NULL, 1 << 5, 1, -1 },
{ NULL, "spterm", NULL, SPTAG(0), 1, -1 },
{ NULL, "spfm", NULL, SPTAG(1), 1, -1 },
{ NULL, "keepassxc", NULL, SPTAG(2), 0, -1 },
};
/* layout(s) */
@ -45,7 +65,7 @@ static const Layout layouts[] = {
};
/* 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} }, \
@ -57,21 +77,26 @@ 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 *dmenucmd[] = { "dmenu_run", "-p", "Run: ", NULL };
static const char *termcmd[] = { "st", NULL };
static const char *volume[] = { "st", "-e", "pulsemixer", NULL };
#include "movestack.c"
static const Key keys[] = {
/* modifier key function argument */
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
{ MODKEY, XK_Return, spawn, {.v = termcmd } },
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = dmenucmd } },
{ MODKEY|Mod1Mask, XK_v, spawn, {.v = volume } },
{ 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|ShiftMask, XK_j, movestack, {.i = +1 } },
{ MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } },
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
{ MODKEY, XK_Return, zoom, {0} },
{ MODKEY, XK_p, zoom, {0} },
{ MODKEY, XK_Tab, view, {0} },
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
@ -85,6 +110,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_y, togglescratch, {.ui = 0 } },
{ MODKEY, XK_u, togglescratch, {.ui = 1 } },
{ MODKEY, XK_x, togglescratch, {.ui = 2 } },
TAGKEYS( XK_1, 0)
TAGKEYS( XK_2, 1)
TAGKEYS( XK_3, 2)
@ -107,7 +135,7 @@ static const Button buttons[] = {
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
{ ClkClientWin, MODKEY, Button1, resizemouse, {0} },
{ ClkTagBar, 0, Button1, view, {0} },
{ ClkTagBar, 0, Button3, toggleview, {0} },
{ ClkTagBar, MODKEY, Button1, tag, {0} },

61
dwm.c
View file

@ -53,7 +53,10 @@
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
#define WIDTH(X) ((X)->w + 2 * (X)->bw)
#define HEIGHT(X) ((X)->h + 2 * (X)->bw)
#define TAGMASK ((1 << LENGTH(tags)) - 1)
#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))
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
/* enums */
@ -146,6 +149,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);
@ -210,6 +214,7 @@ static void tagmon(const Arg *arg);
static void tile(Monitor *m);
static void togglebar(const Arg *arg);
static void togglefloating(const Arg *arg);
static void togglescratch(const Arg *arg);
static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
static void unfocus(Client *c, int setfocus);
@ -298,6 +303,11 @@ applyrules(Client *c)
{
c->isfloating = r->isfloating;
c->tags |= r->tags;
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);
}
for (m = mons; m && m->num != r->monitor; m = m->next);
if (m)
c->mon = m;
@ -307,7 +317,7 @@ applyrules(Client *c)
XFree(ch.res_class);
if (ch.res_name)
XFree(ch.res_name);
c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags];
c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : (c->mon->tagset[c->mon->seltags] & ~SPTAGMASK);
}
int
@ -407,6 +417,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)
{
@ -1067,13 +1086,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);
@ -1426,7 +1447,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);
@ -1631,6 +1652,10 @@ showhide(Client *c)
if (!c)
return;
if (ISVISIBLE(c)) {
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);
}
/* show clients top down */
XMoveWindow(dpy, c->win, c->x, c->y);
if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen)
@ -1734,6 +1759,32 @@ togglefloating(const Arg *arg)
arrange(selmon);
}
void
togglescratch(const Arg *arg)
{
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 {
selmon->tagset[selmon->seltags] |= scratchtag;
spawn(&sparg);
}
}
void
toggletag(const Arg *arg)
{
@ -1914,7 +1965,7 @@ updategeom(void)
m->clients = c->next;
detachstack(c);
c->mon = mons;
attach(c);
attachbottom(c);
attachstack(c);
}
if (m == selmon)

2176
dwm.c.orig Normal file

File diff suppressed because it is too large Load diff

48
movestack.c Normal file
View file

@ -0,0 +1,48 @@
void
movestack(const Arg *arg) {
Client *c = NULL, *p = NULL, *pc = NULL, *i;
if(arg->i > 0) {
/* find the client after selmon->sel */
for(c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next);
if(!c)
for(c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next);
}
else {
/* find the client before selmon->sel */
for(i = selmon->clients; i != selmon->sel; i = i->next)
if(ISVISIBLE(i) && !i->isfloating)
c = i;
if(!c)
for(; i; i = i->next)
if(ISVISIBLE(i) && !i->isfloating)
c = i;
}
/* find the client before selmon->sel and c */
for(i = selmon->clients; i && (!p || !pc); i = i->next) {
if(i->next == selmon->sel)
p = i;
if(i->next == c)
pc = i;
}
/* swap c and selmon->sel selmon->clients in the selmon->clients list */
if(c && c != selmon->sel) {
Client *temp = selmon->sel->next==c?selmon->sel:selmon->sel->next;
selmon->sel->next = c->next==selmon->sel?c:c->next;
c->next = temp;
if(p && p != c)
p->next = c;
if(pc && pc != selmon->sel)
pc->next = selmon->sel;
if(selmon->sel == selmon->clients)
selmon->clients = c;
else if(c == selmon->clients)
selmon->clients = selmon->sel;
arrange(selmon);
}
}

View file

@ -0,0 +1,12 @@
diff -up dwm/dwm.c dwmmod/dwm.c
--- dwm/dwm.c 2020-06-25 00:21:30.383692180 -0300
+++ dwmmod/dwm.c 2020-06-25 00:20:35.643692330 -0300
@@ -1057,6 +1057,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)

View file

@ -0,0 +1,54 @@
diff -up dwm-6.3/dwm.c dwm-6.3-attachbottom/dwm.c
--- dwm-6.3/dwm.c 2022-01-07 12:42:18.000000000 +0100
+++ dwm-6.3-attachbottom/dwm.c 2022-08-17 22:14:41.813809073 +0200
@@ -147,6 +147,7 @@ static int applysizehints(Client *c, int
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);
@@ -408,6 +409,15 @@ attach(Client *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)
{
c->snext = c->mon->stack;
@@ -1066,7 +1076,7 @@ manage(Window w, XWindowAttributes *wa)
c->isfloating = c->oldstate = trans != None || c->isfixed;
if (c->isfloating)
XRaiseWindow(dpy, c->win);
- attach(c);
+ attachbottom(c);
attachstack(c);
XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
(unsigned char *) &(c->win), 1);
@@ -1421,7 +1431,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);
@@ -1903,7 +1913,7 @@ updategeom(void)
m->clients = c->next;
detachstack(c);
c->mon = mons;
- attach(c);
+ attachbottom(c);
attachstack(c);
}
if (m == selmon)

View file

@ -0,0 +1,95 @@
From 9a4037dc0ef56f91c009317e78e9e3790dafbb58 Mon Sep 17 00:00:00 2001
From: BrunoCooper17 <BrunoCooper17@outlook.com>
Date: Mon, 15 Nov 2021 14:04:53 -0600
Subject: [PATCH] MoveStack patch
This plugin allows you to move clients around in the stack and swap them
with the master. It emulates the behavior off mod+shift+j and mod+shift+k
in Xmonad. movestack(+1) will swap the client with the current focus with
the next client. movestack(-1) will swap the client with the current focus
with the previous client.
---
config.def.h | 3 +++
movestack.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 51 insertions(+)
create mode 100644 movestack.c
diff --git a/config.def.h b/config.def.h
index a2ac963..33efa5b 100644
--- a/config.def.h
+++ b/config.def.h
@@ -60,6 +60,7 @@ static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn()
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
static const char *termcmd[] = { "st", NULL };
+#include "movestack.c"
static Key keys[] = {
/* modifier key function argument */
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
@@ -71,6 +72,8 @@ static Key keys[] = {
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
+ { MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } },
+ { MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } },
{ MODKEY, XK_Return, zoom, {0} },
{ MODKEY, XK_Tab, view, {0} },
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
diff --git a/movestack.c b/movestack.c
new file mode 100644
index 0000000..520f4ae
--- /dev/null
+++ b/movestack.c
@@ -0,0 +1,48 @@
+void
+movestack(const Arg *arg) {
+ Client *c = NULL, *p = NULL, *pc = NULL, *i;
+
+ if(arg->i > 0) {
+ /* find the client after selmon->sel */
+ for(c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next);
+ if(!c)
+ for(c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next);
+
+ }
+ else {
+ /* find the client before selmon->sel */
+ for(i = selmon->clients; i != selmon->sel; i = i->next)
+ if(ISVISIBLE(i) && !i->isfloating)
+ c = i;
+ if(!c)
+ for(; i; i = i->next)
+ if(ISVISIBLE(i) && !i->isfloating)
+ c = i;
+ }
+ /* find the client before selmon->sel and c */
+ for(i = selmon->clients; i && (!p || !pc); i = i->next) {
+ if(i->next == selmon->sel)
+ p = i;
+ if(i->next == c)
+ pc = i;
+ }
+
+ /* swap c and selmon->sel selmon->clients in the selmon->clients list */
+ if(c && c != selmon->sel) {
+ Client *temp = selmon->sel->next==c?selmon->sel:selmon->sel->next;
+ selmon->sel->next = c->next==selmon->sel?c:c->next;
+ c->next = temp;
+
+ if(p && p != c)
+ p->next = c;
+ if(pc && pc != selmon->sel)
+ pc->next = selmon->sel;
+
+ if(selmon->sel == selmon->clients)
+ selmon->clients = c;
+ else if(c == selmon->clients)
+ selmon->clients = selmon->sel;
+
+ arrange(selmon);
+ }
+}
\ No newline at end of file
--
2.33.1

View file

@ -0,0 +1,199 @@
From 728d397b21982af88737277fd9d6939a7b558786 Mon Sep 17 00:00:00 2001
From: Christian Tenllado <ctenllado@gmail.com>
Date: Tue, 14 Apr 2020 23:31:15 +0200
Subject: [PATCH] Multiple scratchpads
This patch enables multiple scratchpads, each with one asigned 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 they 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 with
the selected scratchpad tag. 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).
---
config.def.h | 28 ++++++++++++++++++++++++----
dwm.c | 43 +++++++++++++++++++++++++++++++++++++++++--
2 files changed, 65 insertions(+), 6 deletions(-)
diff --git a/config.def.h b/config.def.h
index 1c0b587..06265e1 100644
--- a/config.def.h
+++ b/config.def.h
@@ -18,17 +18,33 @@ static const char *colors[][3] = {
[SchemeSel] = { col_gray4, col_cyan, col_cyan },
};
+typedef struct {
+ const char *name;
+ const void *cmd;
+} Sp;
+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},
+};
+
/* tagging */
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
-
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 },
+ { "Gimp", NULL, NULL, 0, 1, -1 },
+ { "Firefox", NULL, NULL, 1 << 8, 0, -1 },
+ { NULL, "spterm", NULL, SPTAG(0), 1, -1 },
+ { NULL, "spfm", NULL, SPTAG(1), 1, -1 },
+ { NULL, "keepassxc", NULL, SPTAG(2), 0, -1 },
};
/* layout(s) */
@@ -59,6 +75,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 };
+
static Key keys[] = {
/* modifier key function argument */
{ MODKEY, XK_p, spawn, {.v = dmenucmd } },
@@ -84,6 +101,9 @@ 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_y, togglescratch, {.ui = 0 } },
+ { MODKEY, XK_u, togglescratch, {.ui = 1 } },
+ { MODKEY, XK_x, togglescratch, {.ui = 2 } },
TAGKEYS( XK_1, 0)
TAGKEYS( XK_2, 1)
TAGKEYS( XK_3, 2)
@@ -106,7 +126,7 @@ static Button buttons[] = {
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
- { ClkClientWin, MODKEY, Button3, resizemouse, {0} },
+ { ClkClientWin, MODKEY, Button1, resizemouse, {0} },
{ ClkTagBar, 0, Button1, view, {0} },
{ ClkTagBar, 0, Button3, toggleview, {0} },
{ ClkTagBar, MODKEY, Button1, tag, {0} },
diff --git a/dwm.c b/dwm.c
index 4465af1..646aa1a 100644
--- a/dwm.c
+++ b/dwm.c
@@ -54,7 +54,10 @@
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
#define WIDTH(X) ((X)->w + 2 * (X)->bw)
#define HEIGHT(X) ((X)->h + 2 * (X)->bw)
-#define TAGMASK ((1 << LENGTH(tags)) - 1)
+#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))
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
/* enums */
@@ -211,6 +214,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 togglescratch(const Arg *arg);
static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
static void unfocus(Client *c, int setfocus);
@@ -299,6 +303,11 @@ applyrules(Client *c)
{
c->isfloating = r->isfloating;
c->tags |= r->tags;
+ 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);
+ }
+
for (m = mons; m && m->num != r->monitor; m = m->next);
if (m)
c->mon = m;
@@ -308,7 +317,7 @@ applyrules(Client *c)
XFree(ch.res_class);
if (ch.res_name)
XFree(ch.res_name);
- c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags];
+ c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : (c->mon->tagset[c->mon->seltags] & ~SPTAGMASK);
}
int
@@ -1616,6 +1625,10 @@ showhide(Client *c)
if (!c)
return;
if (ISVISIBLE(c)) {
+ 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);
+ }
/* show clients top down */
XMoveWindow(dpy, c->win, c->x, c->y);
if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen)
@@ -1719,6 +1732,32 @@ togglefloating(const Arg *arg)
arrange(selmon);
}
+void
+togglescratch(const Arg *arg)
+{
+ 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 {
+ selmon->tagset[selmon->seltags] |= scratchtag;
+ spawn(&sparg);
+ }
+}
+
void
toggletag(const Arg *arg)
{
--
2.20.1