summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorProsperousPotato <ProsperousPotato@users.noreply.github.com>2025-06-25 22:04:03 +0100
committerProsperousPotato <ProsperousPotato@users.noreply.github.com>2025-06-25 22:04:03 +0100
commitab32254951825e3543bcb720e3d59baeafb47098 (patch)
tree2701d682718d99691e29758a72b6cc63706cf505
parentfbc7e6ddb8617683dff6e9cba96ae4b8d33d18ef (diff)
change browser to waterfox
-rw-r--r--config.def.h140
-rw-r--r--config.h11
-rw-r--r--config.mk2
-rw-r--r--dwm.c2
-rw-r--r--patches/fullscreen.diff68
-rw-r--r--patches/noborder.diff31
-rw-r--r--patches/restartsig.diff139
-rw-r--r--patches/swallow.diff412
-rw-r--r--patches/warp.diff33
9 files changed, 830 insertions, 8 deletions
diff --git a/config.def.h b/config.def.h
new file mode 100644
index 0000000..f93406a
--- /dev/null
+++ b/config.def.h
@@ -0,0 +1,140 @@
+/* See LICENSE file for copyright and license details. */
+
+/* Constants */
+#define TERMINAL "st"
+#define BROWSER "icecat"
+
+/* appearance */
+static const unsigned int borderpx = 3; /* border pixel of windows */
+static const unsigned int snap = 16; /* snap pixel */
+static const int swallowfloating = 0; /* 1 means swallow floating windows by default */
+static const char *fonts[] = { "Terminess Nerd Font Mono:pixelsize=14, fontawesome:size=16" };
+static const char dmenufont[] = "Terminess Nerd Font Mono:pixelsize=14";
+static const char col_gray1[] = "#000000";
+static const char col_gray2[] = "#000000";
+static const char col_gray3[] = "#bbbbbb";
+static const char col_gray4[] = "#eeeeee";
+static const char col_cyan[] = "#bbbbbb";
+static const char *colors[][3] = {
+ /* fg bg border */
+ [SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
+ [SchemeSel] = { col_gray4, col_cyan, col_cyan },
+};
+
+/* tagging */
+static const char *tags[] = { "1", "2", "3", "4", "5" };
+
+static const Rule rules[] = {
+ /* xprop(1):
+ * WM_CLASS(STRING) = instance, class
+ * WM_NAME(STRING) = title
+ */
+ /* class instance title tags mask isfloating isterminal noswallow monitor */
+ { "steam", "steamwebhelper", NULL, 0, 1, 0, 0, -1 },
+ { "Steam", "Steam", NULL, 0, 1, 0, 0, -1 },
+ { "steam", "steamwebhelper", "Steam", 0, 0, 0, 0, -1 },
+ { "steam", NULL, "Steam Settings", 0, 1, 0, 0, -1 },
+ { "qemu-system-x86_64","qemu-system-x86_64",NULL, 0, 1, 0, 0, -1 },
+ { "Virt-manager",NULL, NULL, 0, 0, 0, 0, -1 },
+ { "qBittorrent", NULL, NULL, 0, 1, 0, 0, -1 },
+ { "qBittorrent", "qbittorrent", NULL, 0, 1, 0, 0, -1 },
+ { "St", "st", NULL, 0, 0, 1, 1, -1 },
+ { "stfloat", "st", NULL, 0, 1, 1, 1, -1 },
+ { "mpv", NULL, NULL, 0, 1, 0, 0, -1 },
+ { "Nsxiv", NULL, NULL, 0, 1, 0, 0, -1 },
+ { "scrcpy", NULL, NULL, 0, 1, 0, 0, -1 },
+ { NULL, NULL, "Event Tester", 0, 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 = 0; /* 1 means respect size hints in tiled resizals */
+static const int lockfullscreen = 0; /* 1 will force focus on the fullscreen window */
+
+static const Layout layouts[] = {
+ /* symbol arrange function */
+ { "[]=", tile }, /* first entry is default */
+ { "><>", NULL }, /* no layout function means floating behavior */
+ { "[M]", monocle },
+};
+
+/* 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", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
+static const char *termcmd[] = { "st", NULL };
+
+#include <X11/XF86keysym.h>
+static const Key keys[] = {
+ /* modifier key function argument */
+ { MODKEY, XK_d, spawn, {.v = dmenucmd } },
+ { MODKEY, XK_space, spawn, {.v = termcmd } },
+ { MODKEY|ShiftMask, XK_space, spawn, SHCMD(TERMINAL" -e su") },
+ { Mod1Mask, XK_space, spawn, SHCMD(TERMINAL" -c stfloat") },
+ { Mod1Mask|ShiftMask, XK_space, spawn, SHCMD(TERMINAL" -c stfloat -e su") },
+ { MODKEY, XK_j, focusstack, {.i = +1 } },
+ { MODKEY, XK_k, focusstack, {.i = -1 } },
+ { MODKEY, XK_i, incnmaster, {.i = +1 } },
+ { MODKEY, XK_u, incnmaster, {.i = -1 } },
+ { MODKEY, XK_h, setmfact, {.f = -0.05} },
+ { MODKEY, XK_l, setmfact, {.f = +0.05} },
+ { Mod1Mask, XK_Tab, zoom, {0} },
+ { MODKEY, XK_Tab, view, {0} },
+ { MODKEY, XK_q, killclient, {0} },
+ { MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
+ // { MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
+ { MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
+ { MODKEY|ShiftMask, XK_f, togglefloating, {0} },
+ { MODKEY, XK_f, togglefullscr, {0} },
+ { MODKEY, XK_grave, view, {.ui = ~0 } },
+ { MODKEY|ShiftMask, XK_grave, 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 } },
+ TAGKEYS( XK_1, 0)
+ TAGKEYS( XK_2, 1)
+ TAGKEYS( XK_3, 2)
+ TAGKEYS( XK_4, 3)
+ TAGKEYS( XK_5, 4)
+ { MODKEY|ShiftMask, XK_End, quit, {0} },
+ { MODKEY|ShiftMask, XK_r, quit, {1} },
+
+ { MODKEY, XK_e, spawn, SHCMD(TERMINAL" -e mc --nosubshell") },
+ { Mod1Mask, XK_e, spawn, SHCMD(TERMINAL" -c stfloat -e mc --nosubshell") },
+ { MODKEY|ShiftMask, XK_m, spawn, SHCMD(TERMINAL" -e neomutt") },
+ { MODKEY, XK_n, spawn, SHCMD(TERMINAL" -e newsboat") },
+ { MODKEY, XK_Escape, spawn, SHCMD(TERMINAL" -e htop") },
+ { Mod1Mask, XK_Escape, spawn, SHCMD(TERMINAL" -c stfloat -e htop") },
+ { MODKEY, XK_x, spawn, SHCMD("xkill") },
+ { MODKEY, XK_s, spawn, SHCMD("steam") },
+ { MODKEY|ShiftMask, XK_s, spawn, SHCMD("pkill -9 steam") },
+ { MODKEY, XK_w, spawn, SHCMD(BROWSER) },
+ { 0, XF86XK_AudioRaiseVolume, spawn, SHCMD("amixer sset Master 5%+") },
+ { 0, XF86XK_AudioLowerVolume, spawn, SHCMD("amixer sset Master 5%-") },
+ { 0, XF86XK_AudioMute, spawn, SHCMD("amixer sset Master toggle") },
+ { 0, XF86XK_MonBrightnessUp, spawn, SHCMD("xbacklight -inc 10") },
+ { 0, XF86XK_MonBrightnessDown, spawn, SHCMD("xbacklight -dec 10") },
+ { MODKEY, XK_Print, spawn, SHCMD("maimpick") },
+};
+
+/* button definitions */
+/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
+static const Button buttons[] = {
+ /* click event mask button function argument */
+ { ClkClientWin, MODKEY, Button1, movemouse, {0} },
+ { ClkClientWin, MODKEY, Button2, togglefloating, {0} },
+ { ClkClientWin, MODKEY, Button3, resizemouse, {0} },
+};
+
diff --git a/config.h b/config.h
index f0ea0ef..02f7495 100644
--- a/config.h
+++ b/config.h
@@ -2,7 +2,7 @@
/* Constants */
#define TERMINAL "st"
-#define BROWSER "icecat"
+#define BROWSER "waterfox"
/* appearance */
static const unsigned int borderpx = 3; /* border pixel of windows */
@@ -55,7 +55,6 @@ static const Layout layouts[] = {
/* symbol arrange function */
{ "[]=", tile }, /* first entry is default */
{ "[M]", monocle },
- { "><>", NULL }, /* no layout function means floating behavior */
};
/* key definitions */
@@ -92,8 +91,7 @@ static const Key keys[] = {
{ MODKEY, XK_Tab, view, {0} },
{ MODKEY, XK_q, 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_m, setlayout, {.v = &layouts[1]} },
{ MODKEY|ShiftMask, XK_f, togglefloating, {0} },
{ MODKEY, XK_f, togglefullscr, {0} },
{ MODKEY, XK_grave, view, {.ui = ~0 } },
@@ -112,8 +110,9 @@ static const Key keys[] = {
{ MODKEY, XK_e, spawn, SHCMD(TERMINAL" -e mc --nosubshell") },
{ Mod1Mask, XK_e, spawn, SHCMD(TERMINAL" -c stfloat -e mc --nosubshell") },
- { MODKEY|ShiftMask, XK_m, spawn, SHCMD(TERMINAL" -e neomutt") },
- { MODKEY, XK_n, spawn, SHCMD(TERMINAL" -e newsboat") },
+ { MODKEY|ShiftMask, XK_m, spawn, SHCMD(TERMINAL" -c stfloat -e neomutt") },
+ { MODKEY, XK_n, spawn, SHCMD(TERMINAL" -c stfloat -e newsboat") },
+ { MODKEY, XK_p, spawn, SHCMD(TERMINAL" -c stfloat -e pulsemixer") },
{ MODKEY, XK_Escape, spawn, SHCMD(TERMINAL" -e htop") },
{ Mod1Mask, XK_Escape, spawn, SHCMD(TERMINAL" -c stfloat -e htop") },
{ Mod1Mask, XK_n, spawn, SHCMD(TERMINAL" -c stfloat -e nvtop") },
diff --git a/config.mk b/config.mk
index a933c0b..43176ad 100644
--- a/config.mk
+++ b/config.mk
@@ -29,7 +29,7 @@ LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-r
# flags
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS}
-CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS}
+CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -O3 -march=native ${INCS} ${CPPFLAGS}
LDFLAGS = ${LIBS}
# Solaris
diff --git a/dwm.c b/dwm.c
index 7696552..fd3a37e 100644
--- a/dwm.c
+++ b/dwm.c
@@ -1313,7 +1313,7 @@ resizemouse(const Arg *arg)
break;
}
} while (ev.type != ButtonRelease);
- XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
+ // XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
XUngrabPointer(dpy, CurrentTime);
while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) {
diff --git a/patches/fullscreen.diff b/patches/fullscreen.diff
new file mode 100644
index 0000000..d3be230
--- /dev/null
+++ b/patches/fullscreen.diff
@@ -0,0 +1,68 @@
+From eea13010ffc3983392857ee1e3804e3aa1064d7a Mon Sep 17 00:00:00 2001
+From: Soenke Lambert <s.lambert@mittwald.de>
+Date: Wed, 13 Oct 2021 18:21:09 +0200
+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.1 | 3 +++
+ dwm.c | 8 ++++++++
+ 3 files changed, 12 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.1 b/dwm.1
+index 13b3729..a368d05 100644
+--- a/dwm.1
++++ b/dwm.1
+@@ -116,6 +116,9 @@ Zooms/cycles focused window to/from master area (tiled layouts only).
+ .B Mod1\-Shift\-c
+ Close focused window.
+ .TP
++.B Mod1\-Shift\-f
++Toggle fullscreen for focused window.
++.TP
+ .B Mod1\-Shift\-space
+ Toggle focused window between tiled and floating state.
+ .TP
+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.30.2
+
diff --git a/patches/noborder.diff b/patches/noborder.diff
new file mode 100644
index 0000000..4db7a4f
--- /dev/null
+++ b/patches/noborder.diff
@@ -0,0 +1,31 @@
+From 700b0bdea872f4c00182b2bd925b41fe03f8d222 Mon Sep 17 00:00:00 2001
+From: Aidan Hall <aidan.hall@outlook.com>
+Date: Tue, 2 Jun 2020 14:41:53 +0000
+Subject: [PATCH] Prevents hiding the border if layout is floating.
+
+---
+ dwm.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/dwm.c b/dwm.c
+index 4465af1..2dd959d 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -1282,6 +1282,14 @@ resizeclient(Client *c, int x, int y, int w, int h)
+ c->oldw = c->w; c->w = wc.width = w;
+ c->oldh = c->h; c->h = wc.height = h;
+ wc.border_width = c->bw;
++ if (((nexttiled(c->mon->clients) == c && !nexttiled(c->next))
++ || &monocle == c->mon->lt[c->mon->sellt]->arrange)
++ && !c->isfullscreen && !c->isfloating
++ && NULL != c->mon->lt[c->mon->sellt]->arrange) {
++ c->w = wc.width += c->bw * 2;
++ c->h = wc.height += c->bw * 2;
++ wc.border_width = 0;
++ }
+ XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
+ configure(c);
+ XSync(dpy, False);
+--
+2.26.2
+
diff --git a/patches/restartsig.diff b/patches/restartsig.diff
new file mode 100644
index 0000000..f1f8680
--- /dev/null
+++ b/patches/restartsig.diff
@@ -0,0 +1,139 @@
+From 2991f37f0aaf44b9f9b11e7893ff0af8eb88f649 Mon Sep 17 00:00:00 2001
+From: Christopher Drelich <cd@cdrakka.com>
+Date: Wed, 23 May 2018 22:50:38 -0400
+Subject: [PATCH] Modifies quit to handle restarts and adds SIGHUP and SIGTERM
+ handlers.
+
+Modified quit() to restart if it receives arg .i = 1
+MOD+CTRL+SHIFT+Q was added to confid.def.h to do just that.
+
+Signal handlers were handled for SIGHUP and SIGTERM.
+If dwm receives these signals it calls quit() with
+arg .i = to 1 or 0, respectively.
+
+To restart dwm:
+MOD+CTRL+SHIFT+Q
+or
+kill -HUP dwmpid
+
+To quit dwm cleanly:
+MOD+SHIFT+Q
+or
+kill -TERM dwmpid
+---
+ config.def.h | 1 +
+ dwm.1 | 10 ++++++++++
+ dwm.c | 22 ++++++++++++++++++++++
+ 3 files changed, 33 insertions(+)
+
+diff --git a/config.def.h b/config.def.h
+index a9ac303..e559429 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -94,6 +94,7 @@ static Key keys[] = {
+ TAGKEYS( XK_8, 7)
+ TAGKEYS( XK_9, 8)
+ { MODKEY|ShiftMask, XK_q, quit, {0} },
++ { MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} },
+ };
+
+ /* button definitions */
+diff --git a/dwm.1 b/dwm.1
+index 13b3729..36a331c 100644
+--- a/dwm.1
++++ b/dwm.1
+@@ -142,6 +142,9 @@ Add/remove all windows with nth tag to/from the view.
+ .TP
+ .B Mod1\-Shift\-q
+ Quit dwm.
++.TP
++.B Mod1\-Control\-Shift\-q
++Restart dwm.
+ .SS Mouse commands
+ .TP
+ .B Mod1\-Button1
+@@ -155,6 +158,13 @@ Resize focused window while dragging. Tiled windows will be toggled to the float
+ .SH CUSTOMIZATION
+ dwm is customized by creating a custom config.h and (re)compiling the source
+ code. This keeps it fast, secure and simple.
++.SH SIGNALS
++.TP
++.B SIGHUP - 1
++Restart the dwm process.
++.TP
++.B SIGTERM - 15
++Cleanly terminate the dwm process.
+ .SH SEE ALSO
+ .BR dmenu (1),
+ .BR st (1)
+diff --git a/dwm.c b/dwm.c
+index bb95e26..286eecd 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -205,6 +205,8 @@ static void setup(void);
+ static void seturgent(Client *c, int urg);
+ static void showhide(Client *c);
+ static void sigchld(int unused);
++static void sighup(int unused);
++static void sigterm(int unused);
+ static void spawn(const Arg *arg);
+ static void tag(const Arg *arg);
+ static void tagmon(const Arg *arg);
+@@ -260,6 +262,7 @@ static void (*handler[LASTEvent]) (XEvent *) = {
+ [UnmapNotify] = unmapnotify
+ };
+ static Atom wmatom[WMLast], netatom[NetLast];
++static int restart = 0;
+ static int running = 1;
+ static Cur *cursor[CurLast];
+ static Clr **scheme;
+@@ -1248,6 +1251,7 @@ propertynotify(XEvent *e)
+ void
+ quit(const Arg *arg)
+ {
++ if(arg->i) restart = 1;
+ running = 0;
+ }
+
+@@ -1536,6 +1540,9 @@ setup(void)
+ /* clean up any zombies immediately */
+ sigchld(0);
+
++ signal(SIGHUP, sighup);
++ signal(SIGTERM, sigterm);
++
+ /* init screen */
+ screen = DefaultScreen(dpy);
+ sw = DisplayWidth(dpy, screen);
+@@ -1637,6 +1644,20 @@ sigchld(int unused)
+ }
+
+ void
++sighup(int unused)
++{
++ Arg a = {.i = 1};
++ quit(&a);
++}
++
++void
++sigterm(int unused)
++{
++ Arg a = {.i = 0};
++ quit(&a);
++}
++
++void
+ spawn(const Arg *arg)
+ {
+ if (arg->v == dmenucmd)
+@@ -2139,6 +2160,7 @@ main(int argc, char *argv[])
+ setup();
+ scan();
+ run();
++ if(restart) execvp(argv[0], argv);
+ cleanup();
+ XCloseDisplay(dpy);
+ return EXIT_SUCCESS;
+--
+2.7.4
+
diff --git a/patches/swallow.diff b/patches/swallow.diff
new file mode 100644
index 0000000..47586a0
--- /dev/null
+++ b/patches/swallow.diff
@@ -0,0 +1,412 @@
+From 0cf9a007511f7dfd7dd94171b172562ebac9b6d5 Mon Sep 17 00:00:00 2001
+From: Tom Schwindl <schwindl@posteo.de>
+Date: Sat, 10 Sep 2022 12:51:09 +0200
+Subject: [PATCH] 6.3 swallow patch
+
+---
+ config.def.h | 9 +-
+ config.mk | 3 +-
+ dwm.c | 235 +++++++++++++++++++++++++++++++++++++++++++++++++--
+ 3 files changed, 237 insertions(+), 10 deletions(-)
+
+diff --git a/config.def.h b/config.def.h
+index 061ad662f82a..0b2b8ffd30d5 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -3,6 +3,7 @@
+ /* appearance */
+ static const unsigned int borderpx = 1; /* border pixel of windows */
+ static const unsigned int snap = 32; /* snap pixel */
++static const int swallowfloating = 0; /* 1 means swallow floating windows by default */
+ 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" };
+@@ -26,9 +27,11 @@ 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 isfloating isterminal noswallow monitor */
++ { "Gimp", NULL, NULL, 0, 1, 0, 0, -1 },
++ { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1, -1 },
++ { "St", NULL, NULL, 0, 0, 1, 0, -1 },
++ { NULL, NULL, "Event Tester", 0, 0, 0, 1, -1 }, /* xev */
+ };
+
+ /* layout(s) */
+diff --git a/config.mk b/config.mk
+index 81c493ef4aff..52d1ebf30bec 100644
+--- a/config.mk
++++ b/config.mk
+@@ -20,10 +20,11 @@ FREETYPEINC = /usr/include/freetype2
+ # OpenBSD (uncomment)
+ #FREETYPEINC = ${X11INC}/freetype2
+ #MANPREFIX = ${PREFIX}/man
++#KVMLIB = -lkvm
+
+ # includes and libs
+ INCS = -I${X11INC} -I${FREETYPEINC}
+-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res ${KVMLIB}
+
+ # flags
+ CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
+diff --git a/dwm.c b/dwm.c
+index e5efb6a22806..e68294b6b679 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -40,6 +40,12 @@
+ #include <X11/extensions/Xinerama.h>
+ #endif /* XINERAMA */
+ #include <X11/Xft/Xft.h>
++#include <X11/Xlib-xcb.h>
++#include <xcb/res.h>
++#ifdef __OpenBSD__
++#include <sys/sysctl.h>
++#include <kvm.h>
++#endif /* __OpenBSD */
+
+ #include "drw.h"
+ #include "util.h"
+@@ -92,9 +98,11 @@ struct Client {
+ int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid;
+ int bw, oldbw;
+ unsigned int tags;
+- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
++ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow;
++ pid_t pid;
+ Client *next;
+ Client *snext;
++ Client *swallowing;
+ Monitor *mon;
+ Window win;
+ };
+@@ -138,6 +146,8 @@ typedef struct {
+ const char *title;
+ unsigned int tags;
+ int isfloating;
++ int isterminal;
++ int noswallow;
+ int monitor;
+ } Rule;
+
+@@ -235,6 +245,12 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee);
+ static int xerrorstart(Display *dpy, XErrorEvent *ee);
+ static void zoom(const Arg *arg);
+
++static pid_t getparentprocess(pid_t p);
++static int isdescprocess(pid_t p, pid_t c);
++static Client *swallowingclient(Window w);
++static Client *termforwin(const Client *c);
++static pid_t winpid(Window w);
++
+ /* variables */
+ static const char broken[] = "broken";
+ static char stext[256];
+@@ -269,6 +285,8 @@ static Drw *drw;
+ static Monitor *mons, *selmon;
+ static Window root, wmcheckwin;
+
++static xcb_connection_t *xcon;
++
+ /* configuration, allows nested code to access above variables */
+ #include "config.h"
+
+@@ -298,6 +316,8 @@ applyrules(Client *c)
+ && (!r->class || strstr(class, r->class))
+ && (!r->instance || strstr(instance, r->instance)))
+ {
++ c->isterminal = r->isterminal;
++ c->noswallow = r->noswallow;
+ c->isfloating = r->isfloating;
+ c->tags |= r->tags;
+ for (m = mons; m && m->num != r->monitor; m = m->next);
+@@ -416,6 +436,53 @@ attachstack(Client *c)
+ c->mon->stack = c;
+ }
+
++void
++swallow(Client *p, Client *c)
++{
++
++ if (c->noswallow || c->isterminal)
++ return;
++ if (c->noswallow && !swallowfloating && c->isfloating)
++ return;
++
++ detach(c);
++ detachstack(c);
++
++ setclientstate(c, WithdrawnState);
++ XUnmapWindow(dpy, p->win);
++
++ p->swallowing = c;
++ c->mon = p->mon;
++
++ Window w = p->win;
++ p->win = c->win;
++ c->win = w;
++ updatetitle(p);
++ XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h);
++ arrange(p->mon);
++ configure(p);
++ updateclientlist();
++}
++
++void
++unswallow(Client *c)
++{
++ c->win = c->swallowing->win;
++
++ free(c->swallowing);
++ c->swallowing = NULL;
++
++ /* unfullscreen the client */
++ setfullscreen(c, 0);
++ updatetitle(c);
++ arrange(c->mon);
++ XMapWindow(dpy, c->win);
++ XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
++ setclientstate(c, NormalState);
++ focus(NULL);
++ arrange(c->mon);
++}
++
+ void
+ buttonpress(XEvent *e)
+ {
+@@ -656,6 +723,9 @@ destroynotify(XEvent *e)
+
+ if ((c = wintoclient(ev->window)))
+ unmanage(c, 1);
++
++ else if ((c = swallowingclient(ev->window)))
++ unmanage(c->swallowing, 1);
+ }
+
+ void
+@@ -1022,12 +1092,13 @@ killclient(const Arg *arg)
+ void
+ manage(Window w, XWindowAttributes *wa)
+ {
+- Client *c, *t = NULL;
++ Client *c, *t = NULL, *term = NULL;
+ Window trans = None;
+ XWindowChanges wc;
+
+ c = ecalloc(1, sizeof(Client));
+ c->win = w;
++ c->pid = winpid(w);
+ /* geometry */
+ c->x = c->oldx = wa->x;
+ c->y = c->oldy = wa->y;
+@@ -1042,6 +1113,7 @@ manage(Window w, XWindowAttributes *wa)
+ } else {
+ c->mon = selmon;
+ applyrules(c);
++ term = termforwin(c);
+ }
+
+ if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww)
+@@ -1076,6 +1148,8 @@ manage(Window w, XWindowAttributes *wa)
+ c->mon->sel = c;
+ arrange(c->mon);
+ XMapWindow(dpy, c->win);
++ if (term)
++ swallow(term, c);
+ focus(NULL);
+ }
+
+@@ -1763,6 +1837,20 @@ unmanage(Client *c, int destroyed)
+ Monitor *m = c->mon;
+ XWindowChanges wc;
+
++ if (c->swallowing) {
++ unswallow(c);
++ return;
++ }
++
++ Client *s = swallowingclient(c->win);
++ if (s) {
++ free(s->swallowing);
++ s->swallowing = NULL;
++ arrange(m);
++ focus(NULL);
++ return;
++ }
++
+ detach(c);
+ detachstack(c);
+ if (!destroyed) {
+@@ -1778,9 +1866,12 @@ unmanage(Client *c, int destroyed)
+ XUngrabServer(dpy);
+ }
+ free(c);
+- focus(NULL);
+- updateclientlist();
+- arrange(m);
++
++ if (!s) {
++ arrange(m);
++ focus(NULL);
++ updateclientlist();
++ }
+ }
+
+ void
+@@ -2044,6 +2135,136 @@ view(const Arg *arg)
+ arrange(selmon);
+ }
+
++pid_t
++winpid(Window w)
++{
++
++ pid_t result = 0;
++
++#ifdef __linux__
++ xcb_res_client_id_spec_t spec = {0};
++ spec.client = w;
++ spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID;
++
++ xcb_generic_error_t *e = NULL;
++ xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec);
++ xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e);
++
++ if (!r)
++ return (pid_t)0;
++
++ xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r);
++ for (; i.rem; xcb_res_client_id_value_next(&i)) {
++ spec = i.data->spec;
++ if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) {
++ uint32_t *t = xcb_res_client_id_value_value(i.data);
++ result = *t;
++ break;
++ }
++ }
++
++ free(r);
++
++ if (result == (pid_t)-1)
++ result = 0;
++
++#endif /* __linux__ */
++
++#ifdef __OpenBSD__
++ Atom type;
++ int format;
++ unsigned long len, bytes;
++ unsigned char *prop;
++ pid_t ret;
++
++ if (XGetWindowProperty(dpy, w, XInternAtom(dpy, "_NET_WM_PID", 0), 0, 1, False, AnyPropertyType, &type, &format, &len, &bytes, &prop) != Success || !prop)
++ return 0;
++
++ ret = *(pid_t*)prop;
++ XFree(prop);
++ result = ret;
++
++#endif /* __OpenBSD__ */
++ return result;
++}
++
++pid_t
++getparentprocess(pid_t p)
++{
++ unsigned int v = 0;
++
++#ifdef __linux__
++ FILE *f;
++ char buf[256];
++ snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p);
++
++ if (!(f = fopen(buf, "r")))
++ return 0;
++
++ fscanf(f, "%*u %*s %*c %u", &v);
++ fclose(f);
++#endif /* __linux__*/
++
++#ifdef __OpenBSD__
++ int n;
++ kvm_t *kd;
++ struct kinfo_proc *kp;
++
++ kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, NULL);
++ if (!kd)
++ return 0;
++
++ kp = kvm_getprocs(kd, KERN_PROC_PID, p, sizeof(*kp), &n);
++ v = kp->p_ppid;
++#endif /* __OpenBSD__ */
++
++ return (pid_t)v;
++}
++
++int
++isdescprocess(pid_t p, pid_t c)
++{
++ while (p != c && c != 0)
++ c = getparentprocess(c);
++
++ return (int)c;
++}
++
++Client *
++termforwin(const Client *w)
++{
++ Client *c;
++ Monitor *m;
++
++ if (!w->pid || w->isterminal)
++ return NULL;
++
++ for (m = mons; m; m = m->next) {
++ for (c = m->clients; c; c = c->next) {
++ if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid))
++ return c;
++ }
++ }
++
++ return NULL;
++}
++
++Client *
++swallowingclient(Window w)
++{
++ Client *c;
++ Monitor *m;
++
++ for (m = mons; m; m = m->next) {
++ for (c = m->clients; c; c = c->next) {
++ if (c->swallowing && c->swallowing->win == w)
++ return c;
++ }
++ }
++
++ return NULL;
++}
++
+ Client *
+ wintoclient(Window w)
+ {
+@@ -2133,10 +2354,12 @@ main(int argc, char *argv[])
+ fputs("warning: no locale support\n", stderr);
+ if (!(dpy = XOpenDisplay(NULL)))
+ die("dwm: cannot open display");
++ if (!(xcon = XGetXCBConnection(dpy)))
++ die("dwm: cannot get xcb connection\n");
+ checkotherwm();
+ setup();
+ #ifdef __OpenBSD__
+- if (pledge("stdio rpath proc exec", NULL) == -1)
++ if (pledge("stdio rpath proc exec ps", NULL) == -1)
+ die("pledge");
+ #endif /* __OpenBSD__ */
+ scan();
+--
+2.37.2
+
diff --git a/patches/warp.diff b/patches/warp.diff
new file mode 100644
index 0000000..6aa04a5
--- /dev/null
+++ b/patches/warp.diff
@@ -0,0 +1,33 @@
+From 1e4936416fa5517fe447e3388e1d44c913e29f56 Mon Sep 17 00:00:00 2001
+From: Markus Dam <markus.dam123@gmail.com>
+Date: Mon, 22 Feb 2021 13:40:13 +0100
+Subject: [PATCH] Add cursor warping
+
+---
+ dwm.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/dwm.c b/dwm.c
+index 331a309..c80ef8a 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -882,6 +882,8 @@ focusmon(const Arg *arg)
+ unfocus(selmon->sel, 0);
+ selmon = m;
+ focus(NULL);
++ if (selmon->sel)
++ XWarpPointer(dpy, None, selmon->sel->win, 0, 0, 0, 0, selmon->sel->w/2, selmon->sel->h/2);
+ }
+
+ void
+@@ -906,6 +908,7 @@ focusstack(const Arg *arg)
+ if (c) {
+ focus(c);
+ restack(selmon);
++ XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w/2, c->h/2);
+ }
+ }
+
+--
+2.30.1
+