aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoe <rbo@gmx.us>2024-12-19 15:06:27 +0100
committerJoe <rbo@gmx.us>2024-12-19 15:06:27 +0100
commit03765f41f101502e9825047419fa9d8667e710ea (patch)
treecef6445d9c3df3081aed9f8cd28555ecfd88e401
parentconflict (diff)
downloaddwm-03765f41f101502e9825047419fa9d8667e710ea.tar.gz
dwm-03765f41f101502e9825047419fa9d8667e710ea.tar.bz2
dwm-03765f41f101502e9825047419fa9d8667e710ea.tar.xz
dwm-03765f41f101502e9825047419fa9d8667e710ea.tar.zst
dwm-03765f41f101502e9825047419fa9d8667e710ea.zip
6.5
-rw-r--r--LICENSE1
-rw-r--r--Makefile14
-rw-r--r--README113
-rw-r--r--README.org72
-rw-r--r--applied/dwm-6.0-winview.diff65
-rw-r--r--applied/dwm-attachasideandbelow-6.4.diff (renamed from applied/dwm-attachasideandbelow-20200702-f04cac6.diff)34
-rw-r--r--applied/dwm-bar-height-6.2.diff25
-rw-r--r--applied/dwm-dash_above_activeWindow-20240604-061e9fe.diff44
-rw-r--r--applied/dwm-foreground-20240220-9f88553.diff180
-rw-r--r--applied/dwm-fullgaps-6.4.diff (renamed from applied/dwm-fullgaps-20200508-7b77734.diff)87
-rw-r--r--applied/dwm-nrowgrid-6.1.diff77
-rw-r--r--applied/dwm-preventfocusshift-20240831-6.5.diff25
-rw-r--r--applied/dwm-sizehints-isfreesize-6.2.diff103
-rw-r--r--applied/dwm-stairs-fullgaps-20220430-8b48e30.diff98
-rw-r--r--applied/dwm-swallow-6.3.diff412
-rw-r--r--applied/dwm-switchtotag-6.2.diff58
-rw-r--r--applied/dwm-systray-20230922-9f88553.diff (renamed from applied/dwm-systray-6.4.diff)79
-rw-r--r--cancelled/dwm-6.2-tagintostack-onemaster.diff34
-rw-r--r--cancelled/dwm-bartabgroups-20210802-138b405.diff187
-rw-r--r--cancelled/dwm-noborder-6.2.diff30
-rw-r--r--cancelled/dwm-showselmon-6.2.diff46
-rw-r--r--compile_commands.json27
-rw-r--r--config.def.h119
-rw-r--r--config.h286
-rw-r--r--config.mk15
-rw-r--r--drw.c191
-rw-r--r--drw.h1
-rw-r--r--dwm.113
-rw-r--r--dwm.c1275
-rw-r--r--movestack.c48
-rw-r--r--util.c36
-rw-r--r--util.h1
32 files changed, 1989 insertions, 1807 deletions
diff --git a/LICENSE b/LICENSE
index d221f09..995172f 100644
--- a/LICENSE
+++ b/LICENSE
@@ -17,6 +17,7 @@ MIT/X Consortium License
© 2015-2016 Quentin Rameau <quinq@fifth.space>
© 2015-2016 Eric Pruitt <eric.pruitt@gmail.com>
© 2016-2017 Markus Teich <markus.teich@stusta.mhn.de>
+© 2020-2022 Chris Down <chris@chrisdown.name>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
diff --git a/Makefile b/Makefile
index 3c89802..3f26804 100644
--- a/Makefile
+++ b/Makefile
@@ -6,27 +6,21 @@ include config.mk
SRC = drw.c dwm.c util.c
OBJ = ${SRC:.c=.o}
-all: options dwm
-
-options:
- @echo dwm build options:
- @echo "CFLAGS = ${CFLAGS}"
- @echo "LDFLAGS = ${LDFLAGS}"
- @echo "CC = ${CC}"
+all: dwm
.c.o:
${CC} -c ${CFLAGS} $<
${OBJ}: config.h config.mk
-config.h: config.def.h
+config.h:
cp config.def.h $@
dwm: ${OBJ}
${CC} -o $@ ${OBJ} ${LDFLAGS}
clean:
- rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz
+ rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz config.h
dist: clean
mkdir -p dwm-${VERSION}
@@ -48,4 +42,4 @@ uninstall:
rm -f ${DESTDIR}${PREFIX}/bin/dwm\
${DESTDIR}${MANPREFIX}/man1/dwm.1
-.PHONY: all options clean dist install uninstall
+.PHONY: all clean dist install uninstall
diff --git a/README b/README
index 7876e76..95d4fd0 100644
--- a/README
+++ b/README
@@ -1,75 +1,48 @@
-Joe's dwm (the dynamic window manager) build
-The original dwm build I used to run. Based on version 6.2.
+dwm - dynamic window manager
+============================
+dwm is an extremely fast, small, and dynamic window manager for X.
-Dependencies
+
+Requirements
------------
- Required:
- ---------
- - A C compiler
- - make
- - xorg
- - libX11
- - libXft
-
- Optional:
- ---------
- - st
- - dmenu
+In order to build dwm you need the Xlib header files.
+
Installation
------------
-To install this open a terminal and run these commands:
-
- $ git clone git://jozanleclerc.xyz/jozan/dwm.git
- $ cd dwm
- $ make
- # make install clean
-
-To use it as a default WM, if you are using xinit, add this to your .xinitrc:
- exec dwm
-
-Bindings
---------
-Some of the main key bindings:
- - switch to workspace 1-12 with super+{F1-F12}
- - move selected stack to workspace 1-12 with super+shift+{F1-F12}
- - fire up st terminal with super+return
- - kill selected stack with super+q
- - cycle through stacks down/up with super+j/k
- - move selected stack down/up with super+shift+j/k
- - resize master stack to left/right with super+h/l
- - invoke dmenu_run application launcher with super+p
- - toggle better tiled mode with super+s
- - toggle alternative tiled mode with super+shift+s
- - toggle normal tiled mode with super+t
- - toggle fullscreen mode on selected stack with super+f
- - toggle floating mode on selected stack with super+space
- - toggle top bar with super+b. Hidden by default
- - restart dwm with super+shift+r
- - exit dwm with super+shift+e
-
-Patches
--------
-List of patches in use:
- - actualfullscreen
- - alwayscenter
- - alwaysfullscreen
- - attachasideandbelow
- - centeredmaster
- - fibonacci
- - focusonclick
- - nmaster
- - moveresize
- - movestack
- - noborder
- - nodmenu
- - pertag
- - restartsig
- - savefloats
- - sizehints
- - switchtotag
- - tagothermon
-
-My own autostart script can be found under my dotfiles-bsd repository:
-https://git.jozanleclerc.xyz/jozan/dotfiles-bsd/files.html
-It should be placed in ~/.config/dwm directory.
+Edit config.mk to match your local setup (dwm is installed into
+the /usr/local namespace by default).
+
+Afterwards enter the following command to build and install dwm (if
+necessary as root):
+
+ make clean install
+
+
+Running dwm
+-----------
+Add the following line to your .xinitrc to start dwm using startx:
+
+ exec dwm
+
+In order to connect dwm to a specific display, make sure that
+the DISPLAY environment variable is set correctly, e.g.:
+
+ DISPLAY=foo.bar:1 exec dwm
+
+(This will start dwm on display :1 of the host foo.bar.)
+
+In order to display status info in the bar, you can do something
+like this in your .xinitrc:
+
+ while xsetroot -name "`date` `uptime | sed 's/.*,//'`"
+ do
+ sleep 1
+ done &
+ exec dwm
+
+
+Configuration
+-------------
+The configuration of dwm is done by creating a custom config.h
+and (re)compiling the source code.
diff --git a/README.org b/README.org
deleted file mode 100644
index 343e089..0000000
--- a/README.org
+++ /dev/null
@@ -1,72 +0,0 @@
-#+TITLE: Joe's dwm (the dynamic window manager) build
-The original [[https://dwm.suckless.org/][dwm]] build I used to run. Based on version 6.2.
-
-* Dependencies
-** Required:
- - A C Compiler
- - ~make~
- - ~xorg~
- - ~libX11~
- - ~libXft~
-
-** Optional:
- - ~st~ find my custom improved build [[https://github.com/JozanLeClerc/st][here]]
- - ~dmenu~
-
-* Installation
-To install this open a terminal and run these commands:
-#+BEGIN_SRC shell
-git clone git://jozanleclerc.xyz/jozan/dwm.git
-cd dwm
-make
-make install clean
-#+END_SRC
-To use it as a default WM, if you are using xinit, add this to your ~.xinitrc~:
-#+BEGIN_SRC shell
-exec dwm
-#+END_SRC
-I am not shure about how to set it up on regular desktop managers like ~gdm~ or ~lightdm~.
-
-* Bindings
-Some of the main key bindings:
-- *switch* to workspace 1-12 with ~super+{F1-F12}~
-- *move* selected stack to workspace 1-12 with ~super+shift+{F1-F12}~
-- *fire up* ~st~ terminal with ~super+return~
-- *kill* selected stack with ~super+q~
-- *cycle through* stacks down/up with ~super+j/k~
-- *move* selected stack down/up with ~super+shift+j/k~
-- *resize* master stack to left/right with ~super+h/l~
-- *invoke* ~dmenu_run~ application launcher with ~super+p~. Get it [[https://tools.suckless.org/dmenu/][here]]
-- toggle *better tiled mode* with ~super+s~
-- toggle *alternative tiled mode* with ~super+shift+s~
-- toggle *normal tiled mode* with ~super+t~
-- toggle *fullscreen mode* on selected stack with ~super+f~
-- toggle *floating mode* on selected stack with ~super+space~
-- toggle *top bar* with ~super+b~. Hidden by default
-- *restart* dwm with ~super+shift+r~
-- *exit* dwm with ~super+shift+e~
-
-* Patches
-List of patches in use:
-- /actualfullscreen/
-- /alwayscenter/
-- /alwaysfullscreen/
-- /attachasideandbelow/
-- /centeredmaster/
-- /fibonacci/
-- /focusonclick/
-- /nmaster/
-- /moveresize/
-- /movestack/
-- /noborder/
-- /nodmenu/
-- /pertag/
-- /restartsig/
-- /savefloats/
-- /sizehints/
-- /switchtotag/
-- /tagothermon/
-
-My own autostart script can be found under my
-[[https://git.jozanleclerc.xyz/jozan/dotfiles-bsd/files.html][dotfiles-bsd]] repository. It should
-be placed in =~/.config/dwm= directory.
diff --git a/applied/dwm-6.0-winview.diff b/applied/dwm-6.0-winview.diff
new file mode 100644
index 0000000..1b796b5
--- /dev/null
+++ b/applied/dwm-6.0-winview.diff
@@ -0,0 +1,65 @@
+diff --git a/config.def.h b/config.def.h
+index 77ff358..3ba0efe 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -84,6 +84,7 @@ static Key keys[] = {
+ TAGKEYS( XK_8, 7)
+ TAGKEYS( XK_9, 8)
+ { MODKEY|ShiftMask, XK_q, quit, {0} },
++ { MODKEY, XK_o, winview, {0} },
+ };
+
+ /* button definitions */
+diff --git a/dwm.1 b/dwm.1
+index 5268a06..1188c82 100644
+--- a/dwm.1
++++ b/dwm.1
+@@ -104,6 +104,9 @@ Increase master area size.
+ .B Mod1\-h
+ Decrease master area size.
+ .TP
++.B Mod1\-o
++Select view of the window in focus. The list of tags to be displayed is matched to the window tag list.
++.TP
+ .B Mod1\-Return
+ Zooms/cycles focused window to/from master area (tiled layouts only).
+ .TP
+diff --git a/dwm.c b/dwm.c
+index 1d78655..abf944c 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -247,6 +247,7 @@ static void updatewmhints(Client *c);
+ static void view(const Arg *arg);
+ static Client *wintoclient(Window w);
+ static Monitor *wintomon(Window w);
++static void winview(const Arg* arg);
+ static int xerror(Display *dpy, XErrorEvent *ee);
+ static int xerrordummy(Display *dpy, XErrorEvent *ee);
+ static int xerrorstart(Display *dpy, XErrorEvent *ee);
+@@ -2080,6 +2081,26 @@ wintomon(Window w) {
+ return selmon;
+ }
+
++/* Selects for the view of the focused window. The list of tags */
++/* to be displayed is matched to the focused window tag list. */
++void
++winview(const Arg* arg){
++ Window win, win_r, win_p, *win_c;
++ unsigned nc;
++ int unused;
++ Client* c;
++ Arg a;
++
++ if (!XGetInputFocus(dpy, &win, &unused)) return;
++ while(XQueryTree(dpy, win, &win_r, &win_p, &win_c, &nc)
++ && win_p != win_r) win = win_p;
++
++ if (!(c = wintoclient(win))) return;
++
++ a.ui = c->tags;
++ view(&a);
++}
++
+ /* There's no way to check accesses to destroyed windows, thus those cases are
+ * ignored (especially on UnmapNotify's). Other types of errors call Xlibs
+ * default error handler, which may call exit. */
diff --git a/applied/dwm-attachasideandbelow-20200702-f04cac6.diff b/applied/dwm-attachasideandbelow-6.4.diff
index 1b9219d..326f757 100644
--- a/applied/dwm-attachasideandbelow-20200702-f04cac6.diff
+++ b/applied/dwm-attachasideandbelow-6.4.diff
@@ -1,6 +1,7 @@
-diff -up b/dwm.c a/dwm.c
---- b/dwm.c 2020-07-05 16:05:02.555947738 -0300
-+++ a/dwm.c 2020-07-05 16:06:19.592609932 -0300
+diff --git a/dwm.c b/dwm.c
+index e5efb6a..7b8d4a0 100644
+--- a/dwm.c
++++ b/dwm.c
@@ -49,7 +49,8 @@
#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
@@ -11,7 +12,7 @@ diff -up b/dwm.c a/dwm.c
#define LENGTH(X) (sizeof X / sizeof X[0])
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
#define WIDTH(X) ((X)->w + 2 * (X)->bw)
-@@ -147,6 +148,7 @@ static int applysizehints(Client *c, int
+@@ -147,6 +148,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);
@@ -25,9 +26,9 @@ diff -up b/dwm.c a/dwm.c
static void movemouse(const Arg *arg);
+static Client *nexttagged(Client *c);
static Client *nexttiled(Client *c);
- static void pop(Client *);
+ static void pop(Client *c);
static void propertynotify(XEvent *e);
-@@ -406,6 +409,27 @@ attach(Client *c)
+@@ -408,6 +411,27 @@ attach(Client *c)
c->next = c->mon->clients;
c->mon->clients = c;
}
@@ -55,7 +56,7 @@ diff -up b/dwm.c a/dwm.c
void
attachstack(Client *c)
-@@ -1063,7 +1087,7 @@ manage(Window w, XWindowAttributes *wa)
+@@ -1065,7 +1089,7 @@ manage(Window w, XWindowAttributes *wa)
c->isfloating = c->oldstate = trans != None || c->isfixed;
if (c->isfloating)
XRaiseWindow(dpy, c->win);
@@ -90,11 +91,14 @@ diff -up b/dwm.c a/dwm.c
attachstack(c);
focus(NULL);
arrange(NULL);
-@@ -1901,6 +1935,7 @@ updategeom(void)
- detachstack(c);
- c->mon = mons;
- attach(c);
-+ attachBelow(c);
- attachstack(c);
- }
- if (m == selmon)
+@@ -1898,6 +1932,7 @@ updategeom(void)
+ detachstack(c);
+ c->mon = mons;
+ attach(c);
++ attachBelow(c);
+ attachstack(c);
+ }
+ if (m == selmon)
+--
+2.41.0
+
diff --git a/applied/dwm-bar-height-6.2.diff b/applied/dwm-bar-height-6.2.diff
deleted file mode 100644
index a576111..0000000
--- a/applied/dwm-bar-height-6.2.diff
+++ /dev/null
@@ -1,25 +0,0 @@
-diff --git a/config.def.h b/config.def.h
-index 1c0b587..9814500 100644
---- a/config.def.h
-+++ b/config.def.h
-@@ -5,6 +5,7 @@ static const unsigned int borderpx = 1; /* 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 int user_bh = 0; /* 0 means that dwm will calculate bar height, >= 1 means dwm will user_bh as bar height */
- static const char *fonts[] = { "monospace:size=10" };
- static const char dmenufont[] = "monospace:size=10";
- static const char col_gray1[] = "#222222";
-diff --git a/dwm.c b/dwm.c
-index 4465af1..2c27cb3 100644
---- a/dwm.c
-+++ b/dwm.c
-@@ -1545,7 +1545,7 @@ setup(void)
- if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
- die("no fonts could be loaded.");
- lrpad = drw->fonts->h;
-- bh = drw->fonts->h + 2;
-+ bh = user_bh ? user_bh : drw->fonts->h + 2;
- updategeom();
- /* init atoms */
- utf8string = XInternAtom(dpy, "UTF8_STRING", False);
diff --git a/applied/dwm-dash_above_activeWindow-20240604-061e9fe.diff b/applied/dwm-dash_above_activeWindow-20240604-061e9fe.diff
new file mode 100644
index 0000000..4d66f6c
--- /dev/null
+++ b/applied/dwm-dash_above_activeWindow-20240604-061e9fe.diff
@@ -0,0 +1,44 @@
+From 89303c44ed3c65e106f7e2e7711c112867226695 Mon Sep 17 00:00:00 2001
+From: DonRehan <30264386+donRehan@users.noreply.github.com>
+Date: Tue, 4 Jun 2024 04:33:48 +0300
+Subject: [PATCH] Add a dash above current active window in dwm bar
+
+Give user ability to modify its position , width and text position.
+---
+ config.def.h | 3 +++
+ dwm.c | 4 +++-
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/config.def.h b/config.def.h
+index 9efa774..2ec5f52 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -2,6 +2,9 @@
+
+ /* appearance */
+ static const unsigned int borderpx = 1; /* border pixel of windows */
++static const unsigned int brdsh_w = 2; /* width of the app bar dash */
++static const unsigned int brdsh_ypos = 18; /* y-position of the dash */
++static const unsigned int text_ypos = 1; /* y-position of text */
+ 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 */
+diff --git a/dwm.c b/dwm.c
+index f1d86b2..3c9b293 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -736,8 +736,10 @@ drawbar(Monitor *m)
+
+ if ((w = m->ww - tw - x) > bh) {
+ if (m->sel) {
++ drw_setscheme(drw, scheme[SchemeNorm]);
++ drw_text(drw, x, text_ypos, w, bh, lrpad / 2, m->sel->name, 0);
+ drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
+- drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0);
++ drw_rect(drw, x , bh - brdsh_ypos , w , brdsh_w , 1, 1);
+ if (m->sel->isfloating)
+ drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0);
+ } else {
+--
+2.34.1
+
diff --git a/applied/dwm-foreground-20240220-9f88553.diff b/applied/dwm-foreground-20240220-9f88553.diff
new file mode 100644
index 0000000..d5e4502
--- /dev/null
+++ b/applied/dwm-foreground-20240220-9f88553.diff
@@ -0,0 +1,180 @@
+From 507895940574e77386d53f81df541e3903bf1ba3 Mon Sep 17 00:00:00 2001
+From: espro1 <ericspero@icloud.com>
+Date: Tue, 20 Feb 2024 16:11:05 -0500
+Subject: [PATCH] Essentially a layout for a special class of floating windows.
+ When a window is foregrounded, it is floated, resized, and moved to a
+ predictable location
+
+---
+ config.def.h | 3 ++
+ dwm.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 84 insertions(+), 1 deletion(-)
+
+diff --git a/config.def.h b/config.def.h
+index 9efa774..718e7c3 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -37,6 +37,8 @@ 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 int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
+
++static const float fgw = .6,fgh = .6;
++
+ static const Layout layouts[] = {
+ /* symbol arrange function */
+ { "[]=", tile }, /* first entry is default */
+@@ -78,6 +80,7 @@ static const Key keys[] = {
+ { MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
+ { MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
+ { MODKEY, XK_space, setlayout, {0} },
++ { MODKEY|Mod4Mask, XK_space, toggleforegrounded, {0} },
+ { MODKEY|ShiftMask, XK_space, togglefloating, {0} },
+ { MODKEY, XK_0, view, {.ui = ~0 } },
+ { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
+diff --git a/dwm.c b/dwm.c
+index f1d86b2..12b037d 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -92,9 +92,10 @@ 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, isforegrounded;
+ Client *next;
+ Client *snext;
++ Client *tnext;
+ Monitor *mon;
+ Window win;
+ };
+@@ -127,6 +128,7 @@ struct Monitor {
+ Client *clients;
+ Client *sel;
+ Client *stack;
++ Client *foregrounded;
+ Monitor *next;
+ Window barwin;
+ const Layout *lt[2];
+@@ -210,6 +212,7 @@ static void tag(const Arg *arg);
+ static void tagmon(const Arg *arg);
+ static void tile(Monitor *m);
+ static void togglebar(const Arg *arg);
++static void toggleforegrounded(const Arg *arg);
+ static void togglefloating(const Arg *arg);
+ static void toggletag(const Arg *arg);
+ static void toggleview(const Arg *arg);
+@@ -415,6 +418,21 @@ attachstack(Client *c)
+ c->mon->stack = c;
+ }
+
++void
++attachforegrounded (Client *c)
++{
++ c->tnext = c->mon->foregrounded;
++ c->mon->foregrounded = c;
++}
++
++void
++detachforegrounded (Client *c)
++{
++ Client **tc;
++ for (tc = &c->mon->foregrounded; *tc && *tc != c; tc = &(*tc)->tnext);
++ *tc = c->tnext;
++}
++
+ void
+ buttonpress(XEvent *e)
+ {
+@@ -1209,6 +1227,39 @@ nexttiled(Client *c)
+ return c;
+ }
+
++Client *
++nextforegrounded(Client *c)
++{
++ for (; c && (!c->isforegrounded || !ISVISIBLE(c)); c = c->tnext);
++ return c;
++}
++
++void
++arrangeforegrounded (Monitor *m)
++{
++ unsigned int n,i,x,y,w,h;
++ Client *c;
++
++ for (n = 0, c = nextforegrounded(m->foregrounded); c; c = nextforegrounded(c->tnext), n++);
++ if (n == 0)
++ return;
++
++ for (i = 0, c = nextforegrounded(m->foregrounded); c; c = nextforegrounded(c->tnext), i++){
++ if (n == 1) {
++ x = m->mx + (m->mw - m->mw * fgw) / 2;
++ y = m->my + (m->mh - m->mh * fgh) / 2;
++ w = (m->mw * fgw) - (2 * (m->foregrounded->bw));
++ h = (m->mh * fgh) - (2 * (m->foregrounded->bw));
++ } else {
++ x = (n - 1 - i) * (m->mw / n);
++ y = m->my + (m->mh - m->mh * fgh) / 2;
++ w = (m->mw * (1 / (float)n)) - (2 * (m->foregrounded->bw));
++ h = (m->mh * fgh) - (2 * (m->foregrounded->bw));
++ }
++ resize(c,x,y,w,h,0);
++ }
++}
++
+ void
+ pop(Client *c)
+ {
+@@ -1721,6 +1772,24 @@ togglebar(const Arg *arg)
+ arrange(selmon);
+ }
+
++void
++toggleforegrounded(const Arg *arg)
++{
++ if (!selmon->sel)
++ return;
++ if (selmon->sel->isfullscreen) /* no support for fullscreen windows */
++ return;
++
++ selmon->sel->isforegrounded || selmon->sel->isfloating ?
++ detachforegrounded(selmon->sel) : attachforegrounded(selmon->sel);
++
++ selmon->sel->isforegrounded = selmon->sel->isfloating =
++ !selmon->sel->isfloating && !selmon->sel->isforegrounded;
++
++ arrangeforegrounded(selmon);
++ arrange(selmon);
++}
++
+ void
+ togglefloating(const Arg *arg)
+ {
+@@ -1732,6 +1801,11 @@ togglefloating(const Arg *arg)
+ if (selmon->sel->isfloating)
+ resize(selmon->sel, selmon->sel->x, selmon->sel->y,
+ selmon->sel->w, selmon->sel->h, 0);
++ if (selmon->sel->isforegrounded) {
++ selmon->sel->isforegrounded = 0;
++ detachforegrounded(selmon->sel);
++ arrangeforegrounded(selmon);
++ }
+ arrange(selmon);
+ }
+
+@@ -1783,6 +1857,12 @@ unmanage(Client *c, int destroyed)
+
+ detach(c);
+ detachstack(c);
++
++ if (c->isforegrounded){
++ detachforegrounded(c);
++ arrangeforegrounded(m);
++ }
++
+ if (!destroyed) {
+ wc.border_width = c->oldbw;
+ XGrabServer(dpy); /* avoid race conditions */
+--
+2.43.0
+
diff --git a/applied/dwm-fullgaps-20200508-7b77734.diff b/applied/dwm-fullgaps-6.4.diff
index 29bd6dc..dc52139 100644
--- a/applied/dwm-fullgaps-20200508-7b77734.diff
+++ b/applied/dwm-fullgaps-6.4.diff
@@ -1,41 +1,27 @@
-From 7b7773458c072e4b24d6ea32d0364a8e402e4a43 Mon Sep 17 00:00:00 2001
-From: swy7ch <swy7ch@protonmail.com>
-Date: Fri, 8 May 2020 19:07:24 +0200
-Subject: [PATCH] [PATCH] update dwm-fullgaps patch to be used with tile layout
- update
-
-the recent tile layout changes in commit HEAD~1 (f09418b) broke the
-patch
-
-this patch adapt the new `if` statements to take gaps into account
-
-this patch also provides manpage entries for the keybindings
----
-diff --git a/dwm.1 b/dwm.1
-index 13b3729..0202d96 100644
---- a/dwm.1
-+++ b/dwm.1
-@@ -140,6 +140,16 @@ View all windows with any tag.
- .B Mod1\-Control\-[1..n]
- Add/remove all windows with nth tag to/from the view.
- .TP
-+.B Mod1\--
-+Decrease the gaps around windows.
-+.TP
-+.B Mod1\-=
-+Increase the gaps around windows.
-+.TP
-+.B Mod1\-Shift-=
-+Reset the gaps around windows to
-+.BR 0 .
-+.TP
- .B Mod1\-Shift\-q
- Quit dwm.
- .SS Mouse commands
-diff --git a/dwm.c b/dwm.c
-index 9fd0286..45a58f3 100644
---- a/dwm.c
-+++ b/dwm.c
+diff -up a/config.def.h b/config.def.h
+--- a/config.def.h
++++ b/config.def.h
+@@ -2,6 +2,7 @@
+
+ /* appearance */
+ static const unsigned int borderpx = 1; /* border pixel of windows */
++static const unsigned int gappx = 5; /* gaps between 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 */
+@@ -85,6 +86,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_minus, setgaps, {.i = -1 } },
++ { MODKEY, XK_equal, setgaps, {.i = +1 } },
++ { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } },
+ TAGKEYS( XK_1, 0)
+ TAGKEYS( XK_2, 1)
+ TAGKEYS( XK_3, 2)
+diff -up a/dwm.c b/dwm.c
+--- a/dwm.c 2023-04-30
++++ b/dwm.c 2023-04-30
@@ -119,6 +119,7 @@ struct Monitor {
int by; /* bar geometry */
int mx, my, mw, mh; /* screen size */
@@ -44,7 +30,7 @@ index 9fd0286..45a58f3 100644
unsigned int seltags;
unsigned int sellt;
unsigned int tagset[2];
-@@ -200,6 +201,7 @@ static void sendmon(Client *c, Monitor *m);
+@@ -200,6 +201,7 @@ static void sendmon(Client *c, Monitor *
static void setclientstate(Client *c, long state);
static void setfocus(Client *c);
static void setfullscreen(Client *c, int fullscreen);
@@ -52,7 +38,7 @@ index 9fd0286..45a58f3 100644
static void setlayout(const Arg *arg);
static void setmfact(const Arg *arg);
static void setup(void);
-@@ -639,6 +641,7 @@ createmon(void)
+@@ -641,6 +643,7 @@ createmon(void)
m->nmaster = nmaster;
m->showbar = showbar;
m->topbar = topbar;
@@ -60,11 +46,10 @@ index 9fd0286..45a58f3 100644
m->lt[0] = &layouts[0];
m->lt[1] = &layouts[1 % LENGTH(layouts)];
strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
-@@ -1498,6 +1501,16 @@ setfullscreen(Client *c, int fullscreen)
- }
+@@ -1508,6 +1511,16 @@ setfullscreen(Client *c, int fullscreen)
}
-+void
+ void
+setgaps(const Arg *arg)
+{
+ if ((arg->i == 0) || (selmon->gappx + arg->i < 0))
@@ -74,22 +59,24 @@ index 9fd0286..45a58f3 100644
+ arrange(selmon);
+}
+
- void
++void
setlayout(const Arg *arg)
{
-@@ -1684,18 +1697,18 @@ tile(Monitor *m)
+ if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
+@@ -1697,18 +1710,18 @@ tile(Monitor *m)
if (n > m->nmaster)
mw = m->nmaster ? m->ww * m->mfact : 0;
else
- mw = m->ww;
- for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
-+ mw = m->ww - m->gappx;
-+ for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
- if (i < m->nmaster) {
+- 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), 0);
- if (my + HEIGHT(c) < m->wh)
- my += HEIGHT(c);
++ mw = m->ww - m->gappx;
++ for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
++ if (i < m->nmaster) {
+ h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx;
+ resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0);
+ if (my + HEIGHT(c) + m->gappx < m->wh)
@@ -105,7 +92,3 @@ index 9fd0286..45a58f3 100644
+ ty += HEIGHT(c) + m->gappx;
}
}
-
---
-2.26.2
-
diff --git a/applied/dwm-nrowgrid-6.1.diff b/applied/dwm-nrowgrid-6.1.diff
new file mode 100644
index 0000000..e2e6505
--- /dev/null
+++ b/applied/dwm-nrowgrid-6.1.diff
@@ -0,0 +1,77 @@
+Author: Chris Noxz <chris@noxz.tech>
+
+diff -upN dwm-6.1/config.def.h dwm-nrowgrid-6.1/config.def.h
+--- dwm-6.1/config.def.h 2015-11-08 23:11:48.000000000 +0100
++++ dwm-nrowgrid-6.1/config.def.h 2018-10-01 10:44:05.631382842 +0200
+@@ -34,11 +34,15 @@ static const float mfact = 0.55; /*
+ static const int nmaster = 1; /* number of clients in master area */
+ static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
+
++#define FORCE_VSPLIT 1
++#include "nrowgrid.c"
++
+ static const Layout layouts[] = {
+ /* symbol arrange function */
+ { "[]=", tile }, /* first entry is default */
+ { "><>", NULL }, /* no layout function means floating behavior */
+ { "[M]", monocle },
++ { "###", nrowgrid },
+ };
+
+ /* key definitions */
+diff -upN dwm-6.1/nrowgrid.c dwm-nrowgrid-6.1/nrowgrid.c
+--- dwm-6.1/nrowgrid.c 1970-01-01 01:00:00.000000000 +0100
++++ dwm-nrowgrid-6.1/nrowgrid.c 2018-10-01 10:44:27.741263063 +0200
+@@ -0,0 +1,52 @@
++void
++nrowgrid(Monitor *m)
++{
++ unsigned int n = 0, i = 0, ri = 0, ci = 0; /* counters */
++ unsigned int cx, cy, cw, ch; /* client geometry */
++ unsigned int uw = 0, uh = 0, uc = 0; /* utilization trackers */
++ unsigned int cols, rows = m->nmaster + 1;
++ Client *c;
++
++ /* count clients */
++ for (c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
++
++ /* nothing to do here */
++ if (n == 0)
++ return;
++
++ /* force 2 clients to always split vertically */
++ if (FORCE_VSPLIT && n == 2)
++ rows = 1;
++
++ /* never allow empty rows */
++ if (n < rows)
++ rows = n;
++
++ /* define first row */
++ cols = n / rows;
++ uc = cols;
++ cy = m->wy;
++ ch = m->wh / rows;
++ uh = ch;
++
++ for (c = nexttiled(m->clients); c; c = nexttiled(c->next), i++, ci++) {
++ if (ci == cols) {
++ uw = 0;
++ ci = 0;
++ ri++;
++
++ /* next row */
++ cols = (n - uc) / (rows - ri);
++ uc += cols;
++ cy = m->wy + uh;
++ ch = (m->wh - uh) / (rows - ri);
++ uh += ch;
++ }
++
++ cx = m->wx + uw;
++ cw = (m->ww - uw) / (cols - ci);
++ uw += cw;
++
++ resize(c, cx, cy, cw - 2 * c->bw, ch - 2 * c->bw, 0);
++ }
++}
diff --git a/applied/dwm-preventfocusshift-20240831-6.5.diff b/applied/dwm-preventfocusshift-20240831-6.5.diff
new file mode 100644
index 0000000..78a24cb
--- /dev/null
+++ b/applied/dwm-preventfocusshift-20240831-6.5.diff
@@ -0,0 +1,25 @@
+From 554f5a8a2205a7c52280babf5685462d8991b038 Mon Sep 17 00:00:00 2001
+From: Suleyman Farajli <suleyman@farajli.net>
+Date: Sat, 31 Aug 2024 13:34:58 +0400
+Subject: [PATCH] prevent focus shifting when a window is spawned in fullscreen
+
+---
+ dwm.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/dwm.c b/dwm.c
+index f1d86b2..31b5d07 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -1080,6 +1080,8 @@ manage(Window w, XWindowAttributes *wa)
+ (unsigned char *) &(c->win), 1);
+ XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */
+ setclientstate(c, NormalState);
++ if(selmon->sel && selmon->sel->isfullscreen && !c->isfloating)
++ setfullscreen(selmon->sel, 0);
+ if (c->mon == selmon)
+ unfocus(selmon->sel, 0);
+ c->mon->sel = c;
+--
+2.44.2
+
diff --git a/applied/dwm-sizehints-isfreesize-6.2.diff b/applied/dwm-sizehints-isfreesize-6.2.diff
deleted file mode 100644
index bd9e5da..0000000
--- a/applied/dwm-sizehints-isfreesize-6.2.diff
+++ /dev/null
@@ -1,103 +0,0 @@
-From 5d4e92801206d47090236498d35f199e46dd07f6 Mon Sep 17 00:00:00 2001
-From: MLquest8 <miskuzius@gmail.com>
-Date: Sat, 20 Jun 2020 15:40:43 +0400
-Subject: [PATCH] sizehints-ruled now with a separate rule "isfreesize" and
- cleaner code.
-
----
- config.def.h | 8 +++++---
- dwm.c | 16 +++++++++++++---
- 2 files changed, 18 insertions(+), 6 deletions(-)
-
-diff --git a/config.def.h b/config.def.h
-index 1c0b587..0e4a5ea 100644
---- a/config.def.h
-+++ b/config.def.h
-@@ -26,9 +26,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 isfreesize monitor */
-+ { "Gimp", NULL, NULL, 0, 1, 1, -1 },
-+ { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1 },
-+ { "st", NULL, NULL, 0, 0, 0, -1 },
-+ { "St", NULL, NULL, 0, 0, 0, -1 }, /* St with Xresources patch */
- };
-
- /* layout(s) */
-diff --git a/dwm.c b/dwm.c
-index 9fd0286..73825d1 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, isfloating, isfreesize, isurgent, neverfocus, oldstate, isfullscreen;
- Client *next;
- Client *snext;
- Monitor *mon;
-@@ -138,6 +138,7 @@ typedef struct {
- const char *title;
- unsigned int tags;
- int isfloating;
-+ int isfreesize;
- int monitor;
- } Rule;
-
-@@ -287,6 +288,7 @@ applyrules(Client *c)
-
- /* rule matching */
- c->isfloating = 0;
-+ c->isfreesize = 1;
- c->tags = 0;
- XGetClassHint(dpy, c->win, &ch);
- class = ch.res_class ? ch.res_class : broken;
-@@ -299,6 +301,7 @@ applyrules(Client *c)
- && (!r->instance || strstr(instance, r->instance)))
- {
- c->isfloating = r->isfloating;
-+ c->isfreesize = r->isfreesize;
- c->tags |= r->tags;
- for (m = mons; m && m->num != r->monitor; m = m->next);
- if (m)
-@@ -1952,7 +1955,7 @@ updatesizehints(Client *c)
-
- if (!XGetWMNormalHints(dpy, c->win, &size, &msize))
- /* size is uninitialized, ensure that size.flags aren't used */
-- size.flags = PSize;
-+ size.flags = 0;
- if (size.flags & PBaseSize) {
- c->basew = size.base_width;
- c->baseh = size.base_height;
-@@ -1984,6 +1987,11 @@ updatesizehints(Client *c)
- c->maxa = (float)size.max_aspect.x / size.max_aspect.y;
- } else
- c->maxa = c->mina = 0.0;
-+ if((size.flags & PSize) && c->isfreesize) {
-+ c->basew = size.base_width;
-+ c->baseh = size.base_height;
-+ c->isfloating = 1;
-+ }
- c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh);
- }
-
-@@ -2012,8 +2020,10 @@ updatewindowtype(Client *c)
-
- if (state == netatom[NetWMFullscreen])
- setfullscreen(c, 1);
-- if (wtype == netatom[NetWMWindowTypeDialog])
-+ if (wtype == netatom[NetWMWindowTypeDialog]) {
- c->isfloating = 1;
-+ c->isfreesize = 1;
-+ }
- }
-
- void
---
-2.26.2
-
diff --git a/applied/dwm-stairs-fullgaps-20220430-8b48e30.diff b/applied/dwm-stairs-fullgaps-20220430-8b48e30.diff
deleted file mode 100644
index 53e7966..0000000
--- a/applied/dwm-stairs-fullgaps-20220430-8b48e30.diff
+++ /dev/null
@@ -1,98 +0,0 @@
-From 2004db267a9478918699961ab2f3579c2c8113fb Mon Sep 17 00:00:00 2001
-From: Ehsan Ghorbannezhad <ehsan@disroot.org>
-Date: Sat, 30 Apr 2022 02:48:58 +0430
-Subject: [PATCH] add the stairs layout with fullgaps support
-
----
- config.def.h | 5 +++++
- dwm.c | 38 ++++++++++++++++++++++++++++++++++++++
- 2 files changed, 43 insertions(+)
-
-diff --git a/config.def.h b/config.def.h
-index 5b0d4de..c0f24f4 100644
---- a/config.def.h
-+++ b/config.def.h
-@@ -6,6 +6,9 @@ static const unsigned int gappx = 5; /* gaps between 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 unsigned int stairpx = 20; /* depth of the stairs layout */
-+static const int stairdirection = 1; /* 0: left-aligned, 1: right-aligned */
-+static const int stairsamesize = 1; /* 1 means shrink all the staired windows to the same size */
- static const char *fonts[] = { "monospace:size=10" };
- static const char dmenufont[] = "monospace:size=10";
- static const char col_gray1[] = "#222222";
-@@ -43,6 +46,7 @@ static const Layout layouts[] = {
- { "[]=", tile }, /* first entry is default */
- { "><>", NULL }, /* no layout function means floating behavior */
- { "[M]", monocle },
-+ { "[S]", stairs },
- };
-
- /* key definitions */
-@@ -78,6 +82,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_s, 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 5b7348c..2c5380f 100644
---- a/dwm.c
-+++ b/dwm.c
-@@ -209,6 +209,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 void stairs(Monitor *m);
- static void tag(const Arg *arg);
- static void tagmon(const Arg *arg);
- static void tile(Monitor *);
-@@ -1672,6 +1673,43 @@ spawn(const Arg *arg)
- }
- }
-
-+void
-+stairs(Monitor *m)
-+{
-+ unsigned int i, n, h, mw, my;
-+ unsigned int ox, oy, ow, oh; /* stair offset values */
-+ 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;
-+ else
-+ mw = m->ww - m->gappx;
-+
-+ for (i = 0, my = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
-+ if (i < m->nmaster) {
-+ h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx;
-+ resize(c, m->wx + m->gappx, m->wy + my, mw - (2 * c->bw) - m->gappx, h - (2 * c->bw), 0);
-+ if (my + HEIGHT(c) + m->gappx < m->wh)
-+ my += HEIGHT(c) + m->gappx;
-+ } else {
-+ oy = i - m->nmaster;
-+ ox = stairdirection ? n - i - 1 : (stairsamesize ? i - m->nmaster : 0);
-+ ow = stairsamesize ? n - m->nmaster - 1 : n - i - 1;
-+ oh = stairsamesize ? ow : i - m->nmaster;
-+ resize(c,
-+ m->wx + mw + (ox * stairpx) + m->gappx,
-+ m->wy + (oy * stairpx) + m->gappx,
-+ m->ww - mw - (2 * c->bw) - (ow * stairpx) - (2 * m->gappx),
-+ m->wh - (2 * c->bw) - (oh * stairpx) - (2 * m->gappx),
-+ 0);
-+ }
-+ }
-+}
-+
- void
- tag(const Arg *arg)
- {
---
-2.36.0
diff --git a/applied/dwm-swallow-6.3.diff b/applied/dwm-swallow-6.3.diff
new file mode 100644
index 0000000..47586a0
--- /dev/null
+++ b/applied/dwm-swallow-6.3.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/applied/dwm-switchtotag-6.2.diff b/applied/dwm-switchtotag-6.2.diff
deleted file mode 100644
index 453f8ef..0000000
--- a/applied/dwm-switchtotag-6.2.diff
+++ /dev/null
@@ -1,58 +0,0 @@
-diff -up dwm-6.2-original/config.def.h dwm-6.2-modified/config.def.h
---- dwm-6.2-original/config.def.h 2019-02-02 14:55:28.000000000 +0200
-+++ dwm-6.2-modified/config.def.h 2019-11-18 19:36:22.515566509 +0200
-@@ -26,9 +26,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 switchtotag isfloating monitor */
-+ { "Gimp", NULL, NULL, 0, 0, 1, -1 },
-+ { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1 },
- };
-
- /* layout(s) */
-diff -up dwm-6.2-original/dwm.c dwm-6.2-modified/dwm.c
---- dwm-6.2-original/dwm.c 2019-02-02 14:55:28.000000000 +0200
-+++ dwm-6.2-modified/dwm.c 2019-11-18 19:37:18.792187705 +0200
-@@ -92,6 +92,7 @@ struct Client {
- int basew, baseh, incw, inch, maxw, maxh, minw, minh;
- int bw, oldbw;
- unsigned int tags;
-+ unsigned int switchtotag;
- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
- Client *next;
- Client *snext;
-@@ -137,6 +138,7 @@ typedef struct {
- const char *instance;
- const char *title;
- unsigned int tags;
-+ unsigned int switchtotag;
- int isfloating;
- int monitor;
- } Rule;
-@@ -302,6 +304,11 @@ applyrules(Client *c)
- for (m = mons; m && m->num != r->monitor; m = m->next);
- if (m)
- c->mon = m;
-+ if (r->switchtotag) {
-+ Arg a = { .ui = r->tags };
-+ c->switchtotag = selmon->tagset[selmon->seltags];
-+ view(&a);
-+ }
- }
- }
- if (ch.res_class)
-@@ -1782,6 +1789,10 @@ unmanage(Client *c, int destroyed)
- focus(NULL);
- updateclientlist();
- arrange(m);
-+ if (c->switchtotag) {
-+ Arg a = { .ui = c->switchtotag };
-+ view(&a);
-+ }
- }
-
- void
diff --git a/applied/dwm-systray-6.4.diff b/applied/dwm-systray-20230922-9f88553.diff
index 58e4a69..9356ec1 100644
--- a/applied/dwm-systray-6.4.diff
+++ b/applied/dwm-systray-20230922-9f88553.diff
@@ -1,5 +1,5 @@
diff --git a/config.def.h b/config.def.h
-index 9efa774..750529d 100644
+index 9efa774..fed4fb9 100644
--- a/config.def.h
+++ b/config.def.h
@@ -3,6 +3,11 @@
@@ -14,19 +14,8 @@ index 9efa774..750529d 100644
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" };
-@@ -101,8 +106,8 @@ static const Key keys[] = {
- /* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
- static const Button buttons[] = {
- /* click event mask button function argument */
-- { ClkLtSymbol, 0, Button1, setlayout, {0} },
-- { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
-+ { ClkTagBar, MODKEY, Button1, tag, {0} },
-+ { ClkTagBar, MODKEY, Button3, toggletag, {0} },
- { ClkWinTitle, 0, Button2, zoom, {0} },
- { ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
- { ClkClientWin, MODKEY, Button1, movemouse, {0} },
diff --git a/dwm.c b/dwm.c
-index 03baf42..4611a03 100644
+index f1d86b2..f9e7e4a 100644
--- a/dwm.c
+++ b/dwm.c
@@ -57,12 +57,27 @@
@@ -96,15 +85,15 @@ index 03baf42..4611a03 100644
static void sendmon(Client *c, Monitor *m);
static void setclientstate(Client *c, long state);
static void setfocus(Client *c);
-@@ -207,6 +232,7 @@ static void seturgent(Client *c, int urg);
+@@ -206,6 +231,7 @@ static void setup(void);
+ 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 *m);
-@@ -224,18 +250,23 @@ static int updategeom(void);
+@@ -223,18 +249,23 @@ static int updategeom(void);
static void updatenumlockmask(void);
static void updatesizehints(Client *c);
static void updatestatus(void);
@@ -128,7 +117,7 @@ index 03baf42..4611a03 100644
static const char broken[] = "broken";
static char stext[256];
static int screen;
-@@ -258,9 +289,10 @@ static void (*handler[LASTEvent]) (XEvent *) = {
+@@ -257,9 +288,10 @@ static void (*handler[LASTEvent]) (XEvent *) = {
[MapRequest] = maprequest,
[MotionNotify] = motionnotify,
[PropertyNotify] = propertynotify,
@@ -140,7 +129,7 @@ index 03baf42..4611a03 100644
static int running = 1;
static Cur *cursor[CurLast];
static Clr **scheme;
-@@ -442,7 +474,7 @@ buttonpress(XEvent *e)
+@@ -441,7 +473,7 @@ buttonpress(XEvent *e)
arg.ui = 1 << i;
} else if (ev->x < x + TEXTW(selmon->ltsymbol))
click = ClkLtSymbol;
@@ -149,7 +138,7 @@ index 03baf42..4611a03 100644
click = ClkStatusText;
else
click = ClkWinTitle;
-@@ -485,6 +517,13 @@ cleanup(void)
+@@ -484,6 +516,13 @@ cleanup(void)
XUngrabKey(dpy, AnyKey, AnyModifier, root);
while (mons)
cleanupmon(mons);
@@ -163,7 +152,7 @@ index 03baf42..4611a03 100644
for (i = 0; i < CurLast; i++)
drw_cur_free(drw, cursor[i]);
for (i = 0; i < LENGTH(colors); i++)
-@@ -516,9 +555,58 @@ cleanupmon(Monitor *mon)
+@@ -515,9 +554,58 @@ cleanupmon(Monitor *mon)
void
clientmessage(XEvent *e)
{
@@ -222,7 +211,7 @@ index 03baf42..4611a03 100644
if (!c)
return;
if (cme->message_type == netatom[NetWMState]) {
-@@ -571,7 +659,7 @@ configurenotify(XEvent *e)
+@@ -570,7 +658,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);
@@ -231,7 +220,7 @@ index 03baf42..4611a03 100644
}
focus(NULL);
arrange(NULL);
-@@ -656,6 +744,11 @@ destroynotify(XEvent *e)
+@@ -655,6 +743,11 @@ destroynotify(XEvent *e)
if ((c = wintoclient(ev->window)))
unmanage(c, 1);
@@ -243,7 +232,7 @@ index 03baf42..4611a03 100644
}
void
-@@ -699,7 +792,7 @@ dirtomon(int dir)
+@@ -698,7 +791,7 @@ dirtomon(int dir)
void
drawbar(Monitor *m)
{
@@ -252,7 +241,7 @@ index 03baf42..4611a03 100644
int boxs = drw->fonts->h / 9;
int boxw = drw->fonts->h / 6 + 2;
unsigned int i, occ = 0, urg = 0;
-@@ -708,13 +801,17 @@ drawbar(Monitor *m)
+@@ -707,13 +800,17 @@ drawbar(Monitor *m)
if (!m->showbar)
return;
@@ -272,7 +261,7 @@ index 03baf42..4611a03 100644
for (c = m->clients; c; c = c->next) {
occ |= c->tags;
if (c->isurgent)
-@@ -735,7 +832,7 @@ drawbar(Monitor *m)
+@@ -734,7 +831,7 @@ drawbar(Monitor *m)
drw_setscheme(drw, scheme[SchemeNorm]);
x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
@@ -281,7 +270,7 @@ index 03baf42..4611a03 100644
if (m->sel) {
drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0);
-@@ -746,7 +843,7 @@ drawbar(Monitor *m)
+@@ -745,7 +842,7 @@ drawbar(Monitor *m)
drw_rect(drw, x, 0, w, bh, 1, 1);
}
}
@@ -290,7 +279,7 @@ index 03baf42..4611a03 100644
}
void
-@@ -783,8 +880,11 @@ expose(XEvent *e)
+@@ -782,8 +879,11 @@ expose(XEvent *e)
Monitor *m;
XExposeEvent *ev = &e->xexpose;
@@ -303,7 +292,7 @@ index 03baf42..4611a03 100644
}
void
-@@ -870,14 +970,32 @@ getatomprop(Client *c, Atom prop)
+@@ -869,14 +969,32 @@ getatomprop(Client *c, Atom prop)
unsigned char *p = NULL;
Atom da, atom = None;
@@ -337,7 +326,7 @@ index 03baf42..4611a03 100644
int
getrootptr(int *x, int *y)
{
-@@ -1018,7 +1136,8 @@ killclient(const Arg *arg)
+@@ -1017,7 +1135,8 @@ killclient(const Arg *arg)
{
if (!selmon->sel)
return;
@@ -347,7 +336,7 @@ index 03baf42..4611a03 100644
XGrabServer(dpy);
XSetErrorHandler(xerrordummy);
XSetCloseDownMode(dpy, DestroyAll);
-@@ -1105,6 +1224,13 @@ maprequest(XEvent *e)
+@@ -1104,6 +1223,13 @@ maprequest(XEvent *e)
static XWindowAttributes wa;
XMapRequestEvent *ev = &e->xmaprequest;
@@ -361,7 +350,7 @@ index 03baf42..4611a03 100644
if (!XGetWindowAttributes(dpy, ev->window, &wa) || wa.override_redirect)
return;
if (!wintoclient(ev->window))
-@@ -1226,6 +1352,17 @@ propertynotify(XEvent *e)
+@@ -1225,6 +1351,17 @@ propertynotify(XEvent *e)
Window trans;
XPropertyEvent *ev = &e->xproperty;
@@ -379,7 +368,7 @@ index 03baf42..4611a03 100644
if ((ev->window == root) && (ev->atom == XA_WM_NAME))
updatestatus();
else if (ev->state == PropertyDelete)
-@@ -1276,6 +1413,19 @@ recttomon(int x, int y, int w, int h)
+@@ -1275,6 +1412,19 @@ recttomon(int x, int y, int w, int h)
return r;
}
@@ -399,7 +388,7 @@ index 03baf42..4611a03 100644
void
resize(Client *c, int x, int y, int w, int h, int interact)
{
-@@ -1283,6 +1433,14 @@ resize(Client *c, int x, int y, int w, int h, int interact)
+@@ -1282,6 +1432,14 @@ resize(Client *c, int x, int y, int w, int h, int interact)
resizeclient(c, x, y, w, h);
}
@@ -414,7 +403,7 @@ index 03baf42..4611a03 100644
void
resizeclient(Client *c, int x, int y, int w, int h)
{
-@@ -1298,6 +1456,19 @@ resizeclient(Client *c, int x, int y, int w, int h)
+@@ -1297,6 +1455,19 @@ resizeclient(Client *c, int x, int y, int w, int h)
XSync(dpy, False);
}
@@ -434,7 +423,7 @@ index 03baf42..4611a03 100644
void
resizemouse(const Arg *arg)
{
-@@ -1444,26 +1615,37 @@ setclientstate(Client *c, long state)
+@@ -1443,26 +1614,37 @@ setclientstate(Client *c, long state)
}
int
@@ -483,7 +472,7 @@ index 03baf42..4611a03 100644
}
return exists;
}
-@@ -1477,7 +1659,7 @@ setfocus(Client *c)
+@@ -1476,7 +1658,7 @@ setfocus(Client *c)
XA_WINDOW, 32, PropModeReplace,
(unsigned char *) &(c->win), 1);
}
@@ -492,7 +481,7 @@ index 03baf42..4611a03 100644
}
void
-@@ -1566,6 +1748,10 @@ setup(void)
+@@ -1572,6 +1754,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);
@@ -503,7 +492,7 @@ index 03baf42..4611a03 100644
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);
-@@ -1573,6 +1759,9 @@ setup(void)
+@@ -1579,6 +1765,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);
@@ -513,7 +502,7 @@ index 03baf42..4611a03 100644
/* init cursors */
cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr);
cursor[CurResize] = drw_cur_create(drw, XC_sizing);
-@@ -1581,6 +1770,8 @@ setup(void)
+@@ -1587,6 +1776,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);
@@ -522,7 +511,7 @@ index 03baf42..4611a03 100644
/* init bars */
updatebars();
updatestatus();
-@@ -1711,7 +1902,18 @@ togglebar(const Arg *arg)
+@@ -1717,7 +1908,18 @@ togglebar(const Arg *arg)
{
selmon->showbar = !selmon->showbar;
updatebarpos(selmon);
@@ -542,7 +531,7 @@ index 03baf42..4611a03 100644
arrange(selmon);
}
-@@ -1807,11 +2009,18 @@ unmapnotify(XEvent *e)
+@@ -1813,11 +2015,18 @@ unmapnotify(XEvent *e)
else
unmanage(c, 0);
}
@@ -561,7 +550,7 @@ index 03baf42..4611a03 100644
Monitor *m;
XSetWindowAttributes wa = {
.override_redirect = True,
-@@ -1822,10 +2031,15 @@ updatebars(void)
+@@ -1828,10 +2037,15 @@ updatebars(void)
for (m = mons; m; m = m->next) {
if (m->barwin)
continue;
@@ -578,7 +567,7 @@ index 03baf42..4611a03 100644
XMapRaised(dpy, m->barwin);
XSetClassHint(dpy, m->barwin, &ch);
}
-@@ -2002,6 +2216,125 @@ updatestatus(void)
+@@ -2008,6 +2222,125 @@ updatestatus(void)
if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
strcpy(stext, "dwm-"VERSION);
drawbar(selmon);
@@ -704,7 +693,7 @@ index 03baf42..4611a03 100644
}
void
-@@ -2069,6 +2402,16 @@ wintoclient(Window w)
+@@ -2075,6 +2408,16 @@ wintoclient(Window w)
return NULL;
}
@@ -721,7 +710,7 @@ index 03baf42..4611a03 100644
Monitor *
wintomon(Window w)
{
-@@ -2122,6 +2465,22 @@ xerrorstart(Display *dpy, XErrorEvent *ee)
+@@ -2128,6 +2471,22 @@ xerrorstart(Display *dpy, XErrorEvent *ee)
return -1;
}
diff --git a/cancelled/dwm-6.2-tagintostack-onemaster.diff b/cancelled/dwm-6.2-tagintostack-onemaster.diff
deleted file mode 100644
index 18fa42b..0000000
--- a/cancelled/dwm-6.2-tagintostack-onemaster.diff
+++ /dev/null
@@ -1,34 +0,0 @@
-From 43fb204a53e3f1bee47f51a2f4e52e5bf242e314 Mon Sep 17 00:00:00 2001
-From: astier <aleksandrs.stier@uni-bielefeld.de>
-Date: Tue, 26 Feb 2019 01:04:55 +0100
-Subject: [PATCH] Attach clients from toggled tag into stack instead of master area
-
-New clients attach into the stack area when you toggle a new tag into
-view. This means your master area will remain unchanged when toggling
-views.
----
- dwm.c | 9 +++++++++
- 1 file changed, 9 insertions(+)
-
-diff --git a/dwm.c b/dwm.c
-index 4465af1..567fa8b 100644
---- a/dwm.c
-+++ b/dwm.c
-@@ -1739,6 +1739,15 @@ toggleview(const Arg *arg)
- {
- unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
-
-+ // the first visible client should be the same after we add a new tag
-+ // we also want to be sure not to mutate the focus
-+ Client *const c = nexttiled(selmon->clients);
-+ if (c) {
-+ Client * const selected = selmon->sel;
-+ pop(c);
-+ focus(selected);
-+ }
-+
- if (newtagset) {
- selmon->tagset[selmon->seltags] = newtagset;
- focus(NULL);
---
-2.20.1
diff --git a/cancelled/dwm-bartabgroups-20210802-138b405.diff b/cancelled/dwm-bartabgroups-20210802-138b405.diff
deleted file mode 100644
index fc275f3..0000000
--- a/cancelled/dwm-bartabgroups-20210802-138b405.diff
+++ /dev/null
@@ -1,187 +0,0 @@
-From 653c99b94cc780a2def9c7e50a87703156535f8b Mon Sep 17 00:00:00 2001
-From: Jack Bird <jack.bird@durham.ac.uk>
-Date: Mon, 2 Aug 2021 18:50:02 +0100
-Subject: [PATCH] bartabgroups updated to work with 138b405
-
----
- config.def.h | 11 +++++
- dwm.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++-----
- 2 files changed, 112 insertions(+), 11 deletions(-)
-
-diff --git a/config.def.h b/config.def.h
-index a2ac963..82accf1 100644
---- a/config.def.h
-+++ b/config.def.h
-@@ -16,6 +16,8 @@ static const char *colors[][3] = {
- /* fg bg border */
- [SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
- [SchemeSel] = { col_gray4, col_cyan, col_cyan },
-+ [SchemeTabActive] = { col_gray2, col_gray3, col_gray2 },
-+ [SchemeTabInactive] = { col_gray1, col_gray3, col_gray1 }
- };
-
- /* tagging */
-@@ -37,6 +39,15 @@ 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 int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
-
-+/* Bartabgroups properties */
-+#define BARTAB_BORDERS 1 // 0 = off, 1 = on
-+#define BARTAB_BOTTOMBORDER 1 // 0 = off, 1 = on
-+#define BARTAB_TAGSINDICATOR 1 // 0 = off, 1 = on if >1 client/view tag, 2 = always on
-+#define BARTAB_TAGSPX 5 // # pixels for tag grid boxes
-+#define BARTAB_TAGSROWS 3 // # rows in tag grid (9 tags, e.g. 3x3)
-+static void (*bartabmonfns[])(Monitor *) = { monocle /* , customlayoutfn */ };
-+static void (*bartabfloatfns[])(Monitor *) = { NULL /* , customlayoutfn */ };
-+
- static const Layout layouts[] = {
- /* symbol arrange function */
- { "[]=", tile }, /* first entry is default */
-diff --git a/dwm.c b/dwm.c
-index 5e4d494..1839a56 100644
---- a/dwm.c
-+++ b/dwm.c
-@@ -59,7 +59,7 @@
-
- /* enums */
- enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
--enum { SchemeNorm, SchemeSel }; /* color schemes */
-+enum { SchemeNorm, SchemeSel, SchemeTabActive, SchemeTabInactive }; /* color schemes */
- enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
- NetWMFullscreen, NetActiveWindow, NetWMWindowType,
- NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
-@@ -378,6 +378,98 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact)
- return *x != c->x || *y != c->y || *w != c->w || *h != c->h;
- }
-
-+void
-+bartabdraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive) {
-+ if (!c) return;
-+ int i, nclienttags = 0, nviewtags = 0;
-+
-+ drw_setscheme(drw, scheme[
-+ m->sel == c ? SchemeSel : (groupactive ? SchemeTabActive: SchemeTabInactive)
-+ ]);
-+ drw_text(drw, x, 0, w, bh, lrpad / 2, c->name, 0);
-+
-+ // Floating win indicator
-+ if (c->isfloating) drw_rect(drw, x + 2, 2, 5, 5, 0, 0);
-+
-+ // Optional borders between tabs
-+ if (BARTAB_BORDERS) {
-+ XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBorder].pixel);
-+ XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, 0, 1, bh);
-+ XFillRectangle(drw->dpy, drw->drawable, drw->gc, x + w, 0, 1, bh);
-+ }
-+
-+ // Optional tags icons
-+ for (i = 0; i < LENGTH(tags); i++) {
-+ if ((m->tagset[m->seltags] >> i) & 1) { nviewtags++; }
-+ if ((c->tags >> i) & 1) { nclienttags++; }
-+ }
-+ if (BARTAB_TAGSINDICATOR == 2 || nclienttags > 1 || nviewtags > 1) {
-+ for (i = 0; i < LENGTH(tags); i++) {
-+ drw_rect(drw,
-+ ( x + w - 2 - ((LENGTH(tags) / BARTAB_TAGSROWS) * BARTAB_TAGSPX)
-+ - (i % (LENGTH(tags)/BARTAB_TAGSROWS)) + ((i % (LENGTH(tags) / BARTAB_TAGSROWS)) * BARTAB_TAGSPX)
-+ ),
-+ ( 2 + ((i / (LENGTH(tags)/BARTAB_TAGSROWS)) * BARTAB_TAGSPX)
-+ - ((i / (LENGTH(tags)/BARTAB_TAGSROWS)))
-+ ),
-+ BARTAB_TAGSPX, BARTAB_TAGSPX, (c->tags >> i) & 1, 0
-+ );
-+ }
-+ }
-+}
-+
-+void
-+battabclick(Monitor *m, Client *c, int passx, int x, int w, int unused) {
-+ if (passx >= x && passx <= x + w) {
-+ focus(c);
-+ restack(selmon);
-+ }
-+}
-+
-+void
-+bartabcalculate(
-+ Monitor *m, int offx, int sw, int passx,
-+ void(*tabfn)(Monitor *, Client *, int, int, int, int)
-+) {
-+ Client *c;
-+ int
-+ i, clientsnmaster = 0, clientsnstack = 0, clientsnfloating = 0,
-+ masteractive = 0, fulllayout = 0, floatlayout = 0,
-+ x, w, tgactive;
-+
-+ for (i = 0, c = m->clients; c; c = c->next) {
-+ if (!ISVISIBLE(c)) continue;
-+ if (c->isfloating) { clientsnfloating++; continue; }
-+ if (m->sel == c) { masteractive = i < m->nmaster; }
-+ if (i < m->nmaster) { clientsnmaster++; } else { clientsnstack++; }
-+ i++;
-+ }
-+ for (i = 0; i < LENGTH(bartabfloatfns); i++) if (m ->lt[m->sellt]->arrange == bartabfloatfns[i]) { floatlayout = 1; break; }
-+ for (i = 0; i < LENGTH(bartabmonfns); i++) if (m ->lt[m->sellt]->arrange == bartabmonfns[i]) { fulllayout = 1; break; }
-+ for (c = m->clients, i = 0; c; c = c->next) {
-+ if (!ISVISIBLE(c)) continue;
-+ if (clientsnmaster + clientsnstack == 0 || floatlayout) {
-+ x = offx + (((m->mw - offx - sw) / (clientsnmaster + clientsnstack + clientsnfloating)) * i);
-+ w = (m->mw - offx - sw) / (clientsnmaster + clientsnstack + clientsnfloating);
-+ tgactive = 1;
-+ } else if (!c->isfloating && (fulllayout || ((clientsnmaster == 0) ^ (clientsnstack == 0)))) {
-+ x = offx + (((m->mw - offx - sw) / (clientsnmaster + clientsnstack)) * i);
-+ w = (m->mw - offx - sw) / (clientsnmaster + clientsnstack);
-+ tgactive = 1;
-+ } else if (i < m->nmaster && !c->isfloating) {
-+ x = offx + ((((m->mw * m->mfact) - offx) /clientsnmaster) * i);
-+ w = ((m->mw * m->mfact) - offx) / clientsnmaster;
-+ tgactive = masteractive;
-+ } else if (!c->isfloating) {
-+ x = (m->mw * m->mfact) + ((((m->mw * (1 - m->mfact)) - sw) / clientsnstack) * (i - m->nmaster));
-+ w = ((m->mw * (1 - m->mfact)) - sw) / clientsnstack;
-+ tgactive = !masteractive;
-+ } else continue;
-+ tabfn(m, c, passx, x, w, tgactive);
-+ i++;
-+ }
-+}
-+
- void
- arrange(Monitor *m)
- {
-@@ -442,8 +534,8 @@ buttonpress(XEvent *e)
- click = ClkLtSymbol;
- else if (ev->x > selmon->ww - (int)TEXTW(stext))
- click = ClkStatusText;
-- else
-- click = ClkWinTitle;
-+ else // Focus clicked tab bar item
-+ bartabcalculate(selmon, x, TEXTW(stext) - lrpad + 2, ev->x, battabclick);
- } else if ((c = wintoclient(ev->window))) {
- focus(c);
- restack(selmon);
-@@ -729,15 +821,13 @@ drawbar(Monitor *m)
- drw_setscheme(drw, scheme[SchemeNorm]);
- x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
-
-+ // Draw bartabgroups
-+ drw_rect(drw, x, 0, m->ww - tw - x, bh, 1, 1);
- if ((w = m->ww - tw - 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);
-- if (m->sel->isfloating)
-- drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0);
-- } else {
-- drw_setscheme(drw, scheme[SchemeNorm]);
-- drw_rect(drw, x, 0, w, bh, 1, 1);
-+ bartabcalculate(m, x, tw, -1, bartabdraw);
-+ if (BARTAB_BOTTOMBORDER) {
-+ drw_setscheme(drw, scheme[SchemeTabActive]);
-+ drw_rect(drw, 0, bh - 1, m->ww, 1, 1, 0);
- }
- }
- drw_map(drw, m->barwin, 0, 0, m->ww, bh);
---
-2.32.0
-
diff --git a/cancelled/dwm-noborder-6.2.diff b/cancelled/dwm-noborder-6.2.diff
deleted file mode 100644
index f381eb8..0000000
--- a/cancelled/dwm-noborder-6.2.diff
+++ /dev/null
@@ -1,30 +0,0 @@
-From 9102fdb9c670218373bbe83c891c8e8138d6a6f4 Mon Sep 17 00:00:00 2001
-From: redacted <redacted@example.com>
-Date: Tue, 23 Apr 2019 00:39:27 +0100
-Subject: [PATCH] added noborder patch
-
----
- dwm.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/dwm.c b/dwm.c
-index 4465af1..685eca1 100644
---- a/dwm.c
-+++ b/dwm.c
-@@ -1282,6 +1282,13 @@ 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) {
-+ 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.21.0
-
diff --git a/cancelled/dwm-showselmon-6.2.diff b/cancelled/dwm-showselmon-6.2.diff
deleted file mode 100644
index bbf837e..0000000
--- a/cancelled/dwm-showselmon-6.2.diff
+++ /dev/null
@@ -1,46 +0,0 @@
-diff -up a/config.def.h b/config.def.h
---- a/config.def.h 2020-07-04 13:56:23.316739958 +0200
-+++ b/config.def.h 2020-07-04 13:57:58.020554340 +0200
-@@ -15,6 +15,7 @@ static const char col_cyan[] = "#
- static const char *colors[][3] = {
- /* fg bg border */
- [SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
-+ [SchemeInv] = { col_gray1, col_gray3, col_gray2 },
- [SchemeSel] = { col_gray4, col_cyan, col_cyan },
- };
-
-diff -up a/dwm.c b/dwm.c
---- a/dwm.c 2020-07-04 13:56:23.316739958 +0200
-+++ b/dwm.c 2020-07-04 14:14:54.124590755 +0200
-@@ -59,7 +59,7 @@
-
- /* enums */
- enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
--enum { SchemeNorm, SchemeSel }; /* color schemes */
-+enum { SchemeNorm, SchemeInv, SchemeSel }; /* color schemes */
- enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
- NetWMFullscreen, NetActiveWindow, NetWMWindowType,
- NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
-@@ -716,7 +716,12 @@ 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]);
-+ if (m == selmon) {
-+ drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]);
-+ }
-+ else {
-+ drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeInv : 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,
-@@ -730,7 +735,7 @@ drawbar(Monitor *m)
-
- if ((w = m->ww - sw - x) > bh) {
- if (m->sel) {
-- drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
-+ drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeInv]);
- drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0);
- if (m->sel->isfloating)
- drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0);
diff --git a/compile_commands.json b/compile_commands.json
new file mode 100644
index 0000000..dcff5ac
--- /dev/null
+++ b/compile_commands.json
@@ -0,0 +1,27 @@
+[
+ {
+ "arguments": [
+ "/usr/bin/cc",
+ "-c",
+ "-std=c99",
+ "-pedantic",
+ "-Wall",
+ "-Wno-deprecated-declarations",
+ "-march=alderlake",
+ "-Os",
+ "-pipe",
+ "-I/usr/X11R6/include",
+ "-I/usr/include/freetype2",
+ "-D_DEFAULT_SOURCE",
+ "-D_BSD_SOURCE",
+ "-D_XOPEN_SOURCE=700L",
+ "-DVERSION=\"6.5\"",
+ "-DXINERAMA",
+ "-DHOME=\"/home/r_bousset/\"",
+ "-DHOMEBIN=\"/home/r_bousset/.local/bin/\"",
+ "dwm.c"
+ ],
+ "directory": "/home/r_bousset/.local/packs/dwm",
+ "file": "/home/r_bousset/.local/packs/dwm/dwm.c"
+ }
+]
diff --git a/config.def.h b/config.def.h
index cfe9aa1..de85588 100644
--- a/config.def.h
+++ b/config.def.h
@@ -2,27 +2,27 @@
/* appearance */
static const unsigned int borderpx = 3; /* border pixel of windows */
-static const unsigned int gappx = 10; /* gaps between windows */
+static const unsigned int brdsh_w = 3; /* width of the app bar dash */
+static const unsigned int brdsh_ypos = 20; /* y-position of the dash */
+static const unsigned int text_ypos = 1; /* y-position of text */
+static const unsigned int gappx = 6; /* gaps between windows */
static const unsigned int snap = 32; /* snap pixel */
+static const int swallowfloating = 1; /* 1 means swallow floating windows by default */
static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */
static const unsigned int systrayonleft = 0; /* 0: systray in the right corner, >0: systray on left of status text */
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 showbar = 0; /* 0 means no bar */
static const int topbar = 1; /* 0 means bottom bar */
-static const int user_bh = 22; /* 0 means that dwm will calculate bar height, >= 1 means dwm will user_bh as bar height */
static const int focusonwheel = 0;
-static const unsigned int stairpx = 25; /* depth of the stairs layout */
-static const int stairdirection = 0; /* 0: left-aligned, 1: right-aligned */
-static const int stairsamesize = 1; /* 1 means shrink all the staired windows to the same size */
static const char *fonts[] = { "UbuntuMono Nerd Font:size=14" };
static const char dmenufont[] = "monospace:size=11";
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[] = "#6e0000";
+static const char col_cyan[] = "#900000";
static const char *colors[][3] = {
/* fg bg border */
[SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
@@ -53,14 +53,17 @@ static const Rule rules[] = {
* WM_CLASS(STRING) = instance, class
* WM_NAME(STRING) = title
*/
- /* class instance title tags mask switchtotag, isfloating isfreesize monitor */
- { "st", NULL, NULL, 0, 0, 0, 0, -1 },
- { "St", NULL, NULL, 0, 0, 0, 0, -1 }, /* St with Xresources patch */
- { "xterm-256color", NULL, NULL, 0, 0, 0, 0, -1 },
- { "mpv", NULL, NULL, 0, 0, 0, 0, -1 },
- { "Alacritty", NULL, NULL, 0, 0, 0, 0, -1 },
- { "KeePass2", NULL, NULL, 0, 0, 1, 0, -1 },
- { NULL, NULL, "Event Tester", 0, 0, 0, 0, -1 }, /* xev */
+ /* class instance title tags mask isfloating isterminal noswallow monitor */
+ { "st", NULL, NULL, 0, 0, 1, 0, -1 },
+ { "St", NULL, NULL, 0, 0, 1, 0, -1 }, /* St with Xresources patch */
+ { "xterm-256color", NULL, NULL, 0, 0, 1, 0, -1 },
+ { "mpv", NULL, NULL, 0, 0, 0, 0, -1 },
+ { "Alacritty", NULL, NULL, 0, 0, 1, 0, -1 },
+ { "rclone-browser", NULL, NULL, 1 << 1, 0, 0, 0, 2 },
+ { "org.remmina.Remmina", NULL, NULL, 1 << 2, 0, 0, 0, 2 },
+ { "Vmware", NULL, NULL, 1 << 3, 0, 0, 0, 2 },
+ { "teams-for-linux", NULL, NULL, 0, 1, 0, 0, 1 },
+ { "thunderbird", NULL, NULL, 1 << 1, 0, 0, 0, 1 },
};
/* layout(s) */
@@ -68,15 +71,18 @@ 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 = 1; /* 1 will force focus on the fullscreen window */
+static const float fgw = .75, fgh = .75;
+
+#define FORCE_VSPLIT 1
static const Layout layouts[] = {
/* symbol arrange function */
- { "[S]", stairs },
{ "[]=", tile }, /* first entry is default */
{ "TTT", bstack },
{ "===", bstackhoriz },
{ "|M|", centeredmaster },
{ ">M>", centeredfloatingmaster },
+ { "###", nrowgrid },
{ "[M]", monocle },
{ "><>", NULL }, /* no layout function means floating behavior */
};
@@ -86,38 +92,39 @@ static const Layout layouts[] = {
#define METAKEY Mod1Mask
#define TAGKEYS(KEY,TAG) \
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
+ { MODKEY|METAKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
{ MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
- { MODKEY|ControlMask, KEY, tagprevmon, {.ui = 1 << TAG} }, \
- { MODKEY|ControlMask|ShiftMask, KEY, tagnextmon, {.ui = 1 << TAG} }, \
{ MODKEY|METAKEY, KEY, toggletag, {.ui = 1 << TAG} }, \
- { MODKEY|METAKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} },
+ { MODKEY|ControlMask, KEY, tagprevmon, {.ui = 1 << TAG} }, \
+ { MODKEY|ControlMask|ShiftMask, KEY, tagnextmon, {.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 *term_cmd[] = { "st", NULL };
-static const char *coolterm_cmd[] = { "cool-retro-term", NULL };
-static const char *dmenu_cmd[] = { "dmenu_run", "-i", "-m", "0", NULL };
-static const char *dmpc_cmd[] = { "/home/jozan/.local/bin/dmpc", NULL };
-static const char *dmkill_cmd[] = { "/home/jozan/.local/bin/dmkill", NULL };
-static const char *dmsearch_cmd[] = { "/home/jozan/.local/bin/dmsearch", NULL };
-static const char *dmscrot_cmd[] = { "/home/jozan/.local/bin/dmscrot", NULL };
-static const char *dmlog_cmd[] = { "/home/jozan/.local/bin/dmlog", NULL };
-static const char *dmpass_full_cmd[] = { "/home/jozan/.local/bin/dmpass", "--full", NULL };
-static const char *dmpass_cmd[] = { "/home/jozan/.local/bin/dmpass", NULL };
-static const char *dmotp_cmd[] = { "/home/jozan/.local/bin/dmotp", NULL };
-static const char *ndate_cmd[] = { "/home/jozan/.local/bin/ndate", NULL };
+static const char *term_cmd[] = { "alacritty", NULL };
+static const char *hardflip_cmd[] = { "alacritty", "-e", "hf", NULL };
+static const char *dmenucmd[] = { "dmenu_run", "-i", "-m", "0", NULL };
+static const char *dmapps_cmd[] = { "/home/r_bousset/.local/bin/dmapps", NULL };
+static const char *dmpc_cmd[] = { "/home/r_bousset/.local/bin/dmpc", NULL };
+static const char *dmkill_cmd[] = { "/home/r_bousset/.local/bin/dmkill", NULL };
+static const char *dmsearch_cmd[] = { "/home/r_bousset/.local/bin/dmsearch", NULL };
+static const char *dmscrot_cmd[] = { "/home/r_bousset/.local/bin/dmscrot", NULL };
+static const char *dmlog_cmd[] = { "/home/r_bousset/.local/bin/dmlog", NULL };
+static const char *dmpass_full_cmd[] = { "/home/r_bousset/.local/bin/dmpass", "--full", NULL };
+static const char *dmpass_cmd[] = { "/home/r_bousset/.local/bin/dmpass", NULL };
+static const char *dmotp_cmd[] = { "/home/r_bousset/.local/bin/dmotp", NULL };
+static const char *ndate_cmd[] = { "/home/r_bousset/.local/bin/ndate", NULL };
static const char *file_cmd[] = { "alacritty", "-e", "zsh", "-ic", "lf", NULL };
static const char *file_alt_cmd[] = { "pcmanfm", NULL };
static const char *edit_cmd[] = { "emacsclient", "-c", NULL };
-static const char *browser_cmd[] = { "iridium", "--force-dark-mode", NULL };
-static const char *torbro_cmd[] = { "torify", "iridium", "--force-dark-mode", NULL };
+static const char *browser_cmd[] = { "firefox", NULL };
+static const char *torbro_cmd[] = { "torify", "librewolf", NULL };
static const char *w3m_cmd[] = { "alacritty", "-e", "w3m", "https://start.duckduckgo.com/", NULL };
static const char *nb_cmd[] = { "alacritty", "-e", "newsboat", NULL };
static const char *ncmpc_cmd[] = { "alacritty", "-e", "ncmpc", NULL };
-static const char *cal_cmd[] = { "alacritty", "-e", "calcurse", "-C", "/home/jozan/.config/calcurse", "-D", "/home/jozan/.local/share/calcurse", NULL };
+static const char *cal_cmd[] = { "alacritty", "-e", "calcurse", "-C", "/home/r_bousset/.config/calcurse", "-D", "/home/r_bousset/.local/share/calcurse", NULL };
static const char *scli_cmd[] = { "alacritty", "-e", "scli", NULL };
static const char *mutt_cmd[] = { "alacritty", "-e", "neomutt", NULL };
static const char *gotop_cmd[] = { "alacritty", "-e", "gotop", NULL };
@@ -125,23 +132,22 @@ static const char *htop_cmd[] = { "alacritty", "-e", "htop", NULL };
static const char *top_cmd[] = { "alacritty", "-e", "top", NULL };
static const char *bl_inc_cmd[] = { "xbacklight", "-inc", "10", NULL };
static const char *bl_dec_cmd[] = { "xbacklight", "-dec", "10", NULL };
-static const char *vol_tog_cmd[] = { "/home/jozan/.local/bin/mixer-set", "toggle", NULL };
-static const char *vol_dec_cmd[] = { "/home/jozan/.local/bin/mixer-set", "lower", NULL };
-static const char *vol_inc_cmd[] = { "/home/jozan/.local/bin/mixer-set", "raise", NULL };
-static const char *mic_cmd[] = { "/home/jozan/.local/bin/mic", NULL };
+static const char *vol_tog_cmd[] = { "/home/r_bousset/.local/bin/mixer-set", "toggle", NULL };
+static const char *vol_dec_cmd[] = { "/home/r_bousset/.local/bin/mixer-set", "lower", NULL };
+static const char *vol_inc_cmd[] = { "/home/r_bousset/.local/bin/mixer-set", "raise", NULL };
+static const char *mic_cmd[] = { "/home/r_bousset/.local/bin/mic", NULL };
static const char *mpc_prev_cmd[] = { "mpc", "prev", NULL };
static const char *mpc_next_cmd[] = { "mpc", "next", NULL };
static const char *mpc_tog_cmd[] = { "mpc", "toggle", NULL };
static const char *mpc_stop_cmd[] = { "mpc", "stop", NULL };
-static const char *killespeak_cmd[] = { "/home/jozan/.local/bin/shutup", NULL };
+static const char *killespeak_cmd[] = { "/home/r_bousset/.local/bin/shutup", NULL };
-#include "movestack.c"
#include <X11/XF86keysym.h>
-static Key keys[] = {
- /* modifier key function argument */
- { MODKEY, XK_p, spawn, {.v = dmenu_cmd } },
+static const Key keys[] = {
+ { MODKEY, XK_p, spawn, {.v = dmenucmd } },
{ MODKEY, XK_Return, spawn, {.v = term_cmd } },
- { MODKEY|ControlMask, XK_Return, spawn, {.v = coolterm_cmd } },
+ { MODKEY|ControlMask|ShiftMask, XK_Return, spawn, {.v = hardflip_cmd } },
+ { MODKEY|ControlMask, XK_Return, spawn, {.v = dmapps_cmd } },
{ MODKEY, XK_F1, spawn, {.v = file_cmd } },
{ MODKEY|ShiftMask, XK_F1, spawn, {.v = file_alt_cmd } },
{ MODKEY, XK_F2, spawn, {.v = edit_cmd } },
@@ -197,18 +203,20 @@ static Key keys[] = {
{ MODKEY|ShiftMask, XK_Return, zoom, {0} },
{ METAKEY, XK_Escape, view, {0} },
{ MODKEY, XK_q, killclient, {0} },
- { MODKEY, XK_s, setlayout, {.v = &layouts[0]} }, /* stairs */
- { MODKEY|ShiftMask, XK_s, setlayout, {.v = &layouts[1]} }, /* tile */
- { MODKEY, XK_z, setlayout, {.v = &layouts[0]} }, /* stairs */
- { MODKEY|ShiftMask, XK_z, setlayout, {.v = &layouts[1]} }, /* tile */
- { MODKEY, XK_x, setlayout, {.v = &layouts[2]} }, /* bottoastack */
- { MODKEY|ShiftMask, XK_x, setlayout, {.v = &layouts[3]} }, /* bottomstackhoriz */
- { MODKEY, XK_c, setlayout, {.v = &layouts[4]} }, /* centeredmaster */
- { MODKEY|ShiftMask, XK_c, setlayout, {.v = &layouts[5]} }, /* centeredfloatingmaster */
+ { MODKEY, XK_s, setlayout, {.v = &layouts[0]} }, /* tile */
+ { MODKEY|ShiftMask, XK_s, setlayout, {.v = &layouts[0]} }, /* tile */
+ { MODKEY, XK_z, setlayout, {.v = &layouts[0]} }, /* tile */
+ { MODKEY|ShiftMask, XK_z, setlayout, {.v = &layouts[0]} }, /* tile */
+ { MODKEY, XK_x, setlayout, {.v = &layouts[1]} }, /* bottoastack */
+ { MODKEY|ShiftMask, XK_x, setlayout, {.v = &layouts[2]} }, /* bottomstackhoriz */
+ { MODKEY, XK_c, setlayout, {.v = &layouts[3]} }, /* centeredmaster */
+ { MODKEY|ShiftMask, XK_c, setlayout, {.v = &layouts[4]} }, /* centeredfloatingmaster */
+ { MODKEY, XK_v, setlayout, {.v = &layouts[5]} }, /* centeredmaster */
{ MODKEY, XK_m, setlayout, {.v = &layouts[6]} }, /* monocle */
{ MODKEY, XK_n, setlayout, {.v = &layouts[7]} }, /* floating */
{ MODKEY|ShiftMask, XK_space, setlayout, {0} },
{ MODKEY, XK_space, togglefloating, {0} },
+ { MODKEY|ControlMask, XK_space, toggleforegrounded, {0} },
{ MODKEY, XK_f, togglefullscr, {0} },
{ MODKEY, XK_bracketleft, focusmon, {.i = +1 } },
{ MODKEY, XK_bracketright, focusmon, {.i = -1 } },
@@ -247,14 +255,15 @@ static Key keys[] = {
{ MODKEY, XK_0, view, {.ui = ~0 } },
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
{ MODKEY|ShiftMask, XK_e, quit, {0} },
+ { MODKEY, XK_o, winview, {0} },
};
/* button definitions */
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
-static Button buttons[] = {
+static const Button buttons[] = {
/* click event mask button function argument */
- { ClkTagBar, MODKEY, Button1, tag, {0} },
- { ClkTagBar, MODKEY, Button3, toggletag, {0} },
+ { ClkLtSymbol, 0, Button1, setlayout, {0} },
+ { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
{ ClkWinTitle, 0, Button2, zoom, {0} },
{ ClkStatusText, 0, Button2, spawn, {.v = term_cmd } },
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
diff --git a/config.h b/config.h
deleted file mode 100644
index 549b8b0..0000000
--- a/config.h
+++ /dev/null
@@ -1,286 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-
-/* appearance */
-static const unsigned int borderpx = 3; /* border pixel of windows */
-static const unsigned int gappx = 10; /* gaps between 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 systrayonleft = 0; /* 0: systray in the right corner, >0: systray on left of status text */
-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 = 0; /* 0 means no bar */
-static const int topbar = 1; /* 0 means bottom bar */
-static const int user_bh = 22; /* 0 means that dwm will calculate bar height, >= 1 means dwm will user_bh as bar height */
-static const int focusonwheel = 0;
-static const unsigned int stairpx = 25; /* depth of the stairs layout */
-static const int stairdirection = 1; /* 0: left-aligned, 1: right-aligned */
-static const int stairsamesize = 1; /* 1 means shrink all the staired windows to the same size */
-static const char *fonts[] = { "UbuntuMono Nerd Font:size=14" };
-static const char dmenufont[] = "monospace:size=11";
-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[] = "#900000";
-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", "6", "7", "8", "9" };
-static const char *tagsel[][2] = {
- { "#ffffff", "#900000" },
- { "#ffffff", "#ff7f00" },
- { "#000000", "#ffff00" },
- { "#000000", "#00ff00" },
- { "#ffffff", "#0000ff" },
- { "#ffffff", "#4b0082" },
- { "#ffffff", "#9400d3" },
- { "#000000", "#ffffff" },
- { "#ffffff", "#000000" },
-};
-
-
-/* grid of tags */
-#define DRAWCLASSICTAGS 1 << 0
-#define DRAWTAGGRID 1 << 1
-
-#define SWITCHTAG_UP 1 << 0
-#define SWITCHTAG_DOWN 1 << 1
-#define SWITCHTAG_LEFT 1 << 2
-#define SWITCHTAG_RIGHT 1 << 3
-#define SWITCHTAG_TOGGLETAG 1 << 4
-#define SWITCHTAG_TAG 1 << 5
-#define SWITCHTAG_VIEW 1 << 6
-#define SWITCHTAG_TOGGLEVIEW 1 << 7
-
-static const unsigned int drawtagmask = DRAWTAGGRID; /* | DRAWCLASSICTAGS to show classic row of tags */
-static const int tagrows = 2;
-
-static const Rule rules[] = {
- /* xprop(1):
- * WM_CLASS(STRING) = instance, class
- * WM_NAME(STRING) = title
- */
- /* class instance title tags mask switchtotag, isfloating isfreesize monitor */
- { "st", NULL, NULL, 0, 0, 0, 0, -1 },
- { "St", NULL, NULL, 0, 0, 0, 0, -1 }, /* St with Xresources patch */
- { "xterm-256color", NULL, NULL, 0, 0, 0, 0, -1 },
- { "mpv", NULL, NULL, 0, 0, 0, 0, -1 },
- { "Alacritty", NULL, NULL, 0, 0, 0, 0, -1 },
- { "rclone-browser", NULL, NULL, 1 << 1, 0, 0, 0, 2 },
- { "org.remmina.Remmina", NULL, NULL, 1 << 2, 0, 0, 0, 2 },
- { "Vmware", NULL, NULL, 1 << 3, 0, 0, 0, 2 },
- { "Microsoft Teams - Preview", NULL, NULL, 0, 0, 0, 0, 1 },
- { "thunderbird", NULL, NULL, 1 << 1, 0, 0, 0, 1 },
- { NULL, NULL, "Event Tester", 0, 0, 0, 0, -1 }, /* xev */
-};
-
-/* 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 = 1; /* 1 will force focus on the fullscreen window */
-
-static const Layout layouts[] = {
- /* symbol arrange function */
- { "[S]", stairs },
- { "[]=", tile }, /* first entry is default */
- { "TTT", bstack },
- { "===", bstackhoriz },
- { "|M|", centeredmaster },
- { ">M>", centeredfloatingmaster },
- { "[M]", monocle },
- { "><>", NULL }, /* no layout function means floating behavior */
-};
-
-/* key definitions */
-#define MODKEY Mod4Mask
-#define METAKEY Mod1Mask
-#define TAGKEYS(KEY,TAG) \
- { MODKEY, KEY, view, {.ui = 1 << TAG} }, \
- { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
- { MODKEY|ControlMask, KEY, tagprevmon, {.ui = 1 << TAG} }, \
- { MODKEY|ControlMask|ShiftMask, KEY, tagnextmon, {.ui = 1 << TAG} }, \
- { MODKEY|METAKEY, KEY, toggletag, {.ui = 1 << TAG} }, \
- { MODKEY|METAKEY|ControlMask, KEY, toggleview, {.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 *term_cmd[] = { "alacritty", NULL };
-static const char *hardflip_cmd[] = { "alacritty", "-e", "hf", NULL };
-static const char *dmenu_cmd[] = { "dmenu_run", "-i", "-m", "0", NULL };
-static const char *dmapps_cmd[] = { "/home/jozan/.local/bin/dmapps", NULL };
-static const char *dmpc_cmd[] = { "/home/jozan/.local/bin/dmpc", NULL };
-static const char *dmkill_cmd[] = { "/home/jozan/.local/bin/dmkill", NULL };
-static const char *dmsearch_cmd[] = { "/home/jozan/.local/bin/dmsearch", NULL };
-static const char *dmscrot_cmd[] = { "/home/jozan/.local/bin/dmscrot", NULL };
-static const char *dmlog_cmd[] = { "/home/jozan/.local/bin/dmlog", NULL };
-static const char *dmpass_full_cmd[] = { "/home/jozan/.local/bin/dmpass", "--full", NULL };
-static const char *dmpass_cmd[] = { "/home/jozan/.local/bin/dmpass", NULL };
-static const char *dmotp_cmd[] = { "/home/jozan/.local/bin/dmotp", NULL };
-static const char *ndate_cmd[] = { "/home/jozan/.local/bin/ndate", NULL };
-static const char *file_cmd[] = { "alacritty", "-e", "zsh", "-ic", "lf", NULL };
-static const char *file_alt_cmd[] = { "pcmanfm", NULL };
-static const char *edit_cmd[] = { "emacsclient", "-c", NULL };
-static const char *browser_cmd[] = { "firefox", NULL };
-static const char *torbro_cmd[] = { "torify", "librewolf", NULL };
-static const char *w3m_cmd[] = { "alacritty", "-e", "w3m", "https://start.duckduckgo.com/", NULL };
-static const char *nb_cmd[] = { "alacritty", "-e", "newsboat", NULL };
-static const char *ncmpc_cmd[] = { "alacritty", "-e", "ncmpc", NULL };
-static const char *cal_cmd[] = { "alacritty", "-e", "calcurse", "-C", "/home/jozan/.config/calcurse", "-D", "/home/jozan/.local/share/calcurse", NULL };
-static const char *scli_cmd[] = { "alacritty", "-e", "scli", NULL };
-static const char *mutt_cmd[] = { "alacritty", "-e", "neomutt", NULL };
-static const char *gotop_cmd[] = { "alacritty", "-e", "gotop", NULL };
-static const char *htop_cmd[] = { "alacritty", "-e", "htop", NULL };
-static const char *top_cmd[] = { "alacritty", "-e", "top", NULL };
-static const char *bl_inc_cmd[] = { "xbacklight", "-inc", "10", NULL };
-static const char *bl_dec_cmd[] = { "xbacklight", "-dec", "10", NULL };
-static const char *vol_tog_cmd[] = { "/home/jozan/.local/bin/mixer-set", "toggle", NULL };
-static const char *vol_dec_cmd[] = { "/home/jozan/.local/bin/mixer-set", "lower", NULL };
-static const char *vol_inc_cmd[] = { "/home/jozan/.local/bin/mixer-set", "raise", NULL };
-static const char *mic_cmd[] = { "/home/jozan/.local/bin/mic", NULL };
-static const char *mpc_prev_cmd[] = { "mpc", "prev", NULL };
-static const char *mpc_next_cmd[] = { "mpc", "next", NULL };
-static const char *mpc_tog_cmd[] = { "mpc", "toggle", NULL };
-static const char *mpc_stop_cmd[] = { "mpc", "stop", NULL };
-static const char *killespeak_cmd[] = { "/home/jozan/.local/bin/shutup", NULL };
-
-#include "movestack.c"
-#include <X11/XF86keysym.h>
-static Key keys[] = {
- /* modifier key function argument */
- { MODKEY, XK_p, spawn, {.v = dmenu_cmd } },
- { MODKEY, XK_Return, spawn, {.v = term_cmd } },
- { MODKEY|ControlMask|ShiftMask, XK_Return, spawn, {.v = hardflip_cmd } },
- { MODKEY|ControlMask, XK_Return, spawn, {.v = dmapps_cmd } },
- { MODKEY, XK_F1, spawn, {.v = file_cmd } },
- { MODKEY|ShiftMask, XK_F1, spawn, {.v = file_alt_cmd } },
- { MODKEY, XK_F2, spawn, {.v = edit_cmd } },
- { MODKEY, XK_F3, spawn, {.v = browser_cmd } },
- { MODKEY|ShiftMask, XK_F3, spawn, {.v = torbro_cmd } },
- { MODKEY, XK_F4, spawn, {.v = w3m_cmd } },
- { MODKEY, XK_F5, spawn, {.v = ncmpc_cmd } },
- { MODKEY, XK_F6, spawn, {.v = nb_cmd} },
- { MODKEY, XK_F7, spawn, {.v = cal_cmd } },
- { MODKEY, XK_F8, spawn, {.v = scli_cmd } },
- { MODKEY, XK_F9, spawn, {.v = mutt_cmd } },
- { MODKEY, XK_F10, spawn, {.v = gotop_cmd } },
- { MODKEY, XK_F11, spawn, {.v = htop_cmd } },
- { MODKEY, XK_F12, spawn, {.v = top_cmd } },
- { MODKEY|ShiftMask, XK_F6, spawn, {.v = mpc_prev_cmd } },
- { MODKEY|ShiftMask, XK_F7, spawn, {.v = mpc_tog_cmd } },
- { MODKEY|ShiftMask, XK_F8, spawn, {.v = mpc_next_cmd } },
- { MODKEY|ShiftMask, XK_F9, spawn, {.v = mpc_stop_cmd } },
- { MODKEY|ShiftMask, XK_F10, spawn, {.v = vol_tog_cmd } },
- { MODKEY|ShiftMask, XK_F11, spawn, {.v = vol_dec_cmd } },
- { MODKEY|ShiftMask, XK_F12, spawn, {.v = vol_inc_cmd } },
- { MODKEY|ShiftMask, XK_Delete, spawn, {.v = mic_cmd } },
- { MODKEY|ControlMask, XK_F9, spawn, {.v = dmkill_cmd } },
- { MODKEY|ControlMask, XK_F10, spawn, {.v = dmscrot_cmd } },
- { MODKEY|ControlMask, XK_F11, spawn, {.v = dmsearch_cmd } },
- { MODKEY|ControlMask, XK_F12, spawn, {.v = dmlog_cmd } },
- { MODKEY|ControlMask, XK_BackSpace, spawn, {.v = dmlog_cmd } },
- { MODKEY, XK_BackSpace, spawn, {.v = dmpc_cmd } },
- { MODKEY|ControlMask, XK_p, spawn, {.v = dmpass_cmd } },
- { MODKEY|ControlMask|ShiftMask, XK_p, spawn, {.v = dmpass_full_cmd } },
- { MODKEY|ControlMask, XK_o, spawn, {.v = dmotp_cmd } },
- { MODKEY, XK_End, spawn, {.v = ndate_cmd } },
- { 0, XF86XK_MonBrightnessUp, spawn, {.v = bl_inc_cmd } },
- { 0, XF86XK_MonBrightnessDown, spawn, {.v = bl_dec_cmd } },
- { 0, XF86XK_AudioRaiseVolume, spawn, {.v = vol_inc_cmd } },
- { 0, XF86XK_AudioLowerVolume, spawn, {.v = vol_dec_cmd } },
- { 0, XF86XK_AudioMute, spawn, {.v = vol_tog_cmd } },
- { 0, XF86XK_AudioPlay, spawn, {.v = mpc_tog_cmd } },
- { 0, XF86XK_AudioPrev, spawn, {.v = mpc_prev_cmd } },
- { 0, XF86XK_AudioNext, spawn, {.v = mpc_next_cmd } },
- { MODKEY, XK_Delete, spawn, {.v = killespeak_cmd } },
- { 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|ControlMask, XK_a, incnmaster, {.i = +1 } },
- { MODKEY|ControlMask, XK_x, incnmaster, {.i = -1 } },
- { MODKEY|ControlMask, XK_minus, setmfact, {.f = -0.025} },
- { MODKEY|ControlMask, XK_equal, setmfact, {.f = +0.025} },
- { MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } },
- { MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } },
- { MODKEY|ShiftMask, XK_Return, zoom, {0} },
- { METAKEY, XK_Escape, view, {0} },
- { MODKEY, XK_q, killclient, {0} },
- { MODKEY, XK_s, setlayout, {.v = &layouts[0]} }, /* stairs */
- { MODKEY|ShiftMask, XK_s, setlayout, {.v = &layouts[1]} }, /* tile */
- { MODKEY, XK_z, setlayout, {.v = &layouts[0]} }, /* stairs */
- { MODKEY|ShiftMask, XK_z, setlayout, {.v = &layouts[1]} }, /* tile */
- { MODKEY, XK_x, setlayout, {.v = &layouts[2]} }, /* bottoastack */
- { MODKEY|ShiftMask, XK_x, setlayout, {.v = &layouts[3]} }, /* bottomstackhoriz */
- { MODKEY, XK_c, setlayout, {.v = &layouts[4]} }, /* centeredmaster */
- { MODKEY|ShiftMask, XK_c, setlayout, {.v = &layouts[5]} }, /* centeredfloatingmaster */
- { MODKEY, XK_m, setlayout, {.v = &layouts[6]} }, /* monocle */
- { MODKEY, XK_n, setlayout, {.v = &layouts[7]} }, /* floating */
- { MODKEY|ShiftMask, XK_space, setlayout, {0} },
- { MODKEY, XK_space, togglefloating, {0} },
- { MODKEY, XK_f, togglefullscr, {0} },
- { MODKEY, XK_bracketleft, focusmon, {.i = +1 } },
- { MODKEY, XK_bracketright, focusmon, {.i = -1 } },
- { MODKEY, XK_h, focusmon, {.i = +1 } },
- { MODKEY, XK_l, focusmon, {.i = -1 } },
- { MODKEY|ShiftMask, XK_bracketleft, tagmon, {.i = +1 } },
- { MODKEY|ShiftMask, XK_bracketright, tagmon, {.i = -1 } },
- { MODKEY|ShiftMask, XK_h, tagmon, {.i = +1 } },
- { MODKEY|ShiftMask, XK_l, tagmon, {.i = -1 } },
- { MODKEY|ShiftMask, XK_bracketleft, focusmon, {.i = +1 } },
- { MODKEY|ShiftMask, XK_bracketright, focusmon, {.i = -1 } },
- { MODKEY|ShiftMask, XK_h, focusmon, {.i = +1 } },
- { MODKEY|ShiftMask, XK_l, focusmon, {.i = -1 } },
- { MODKEY, XK_w, movemouse, {0} },
- { MODKEY|ShiftMask, XK_w, resizemouse, {0} },
- { MODKEY, XK_minus, setgaps, {.i = -1 } },
- { MODKEY, XK_equal, setgaps, {.i = +1 } },
- { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } },
- { MODKEY|ControlMask, XK_k, switchtag, { .ui = SWITCHTAG_UP | SWITCHTAG_VIEW } },
- { MODKEY|ControlMask, XK_j, switchtag, { .ui = SWITCHTAG_DOWN | SWITCHTAG_VIEW } },
- { MODKEY|ControlMask, XK_l, switchtag, { .ui = SWITCHTAG_RIGHT | SWITCHTAG_VIEW } },
- { MODKEY|ControlMask, XK_h, switchtag, { .ui = SWITCHTAG_LEFT | SWITCHTAG_VIEW } },
- { MODKEY|METAKEY, XK_k, switchtag, { .ui = SWITCHTAG_UP | SWITCHTAG_TAG | SWITCHTAG_VIEW } },
- { MODKEY|METAKEY, XK_j, switchtag, { .ui = SWITCHTAG_DOWN | SWITCHTAG_TAG | SWITCHTAG_VIEW } },
- { MODKEY|METAKEY, XK_l, switchtag, { .ui = SWITCHTAG_RIGHT | SWITCHTAG_TAG | SWITCHTAG_VIEW } },
- { MODKEY|METAKEY, XK_h, switchtag, { .ui = SWITCHTAG_LEFT | SWITCHTAG_TAG | SWITCHTAG_VIEW } },
- 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)
- { MODKEY, XK_0, view, {.ui = ~0 } },
- { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
- { MODKEY|ShiftMask, XK_e, quit, {0} },
-};
-
-/* button definitions */
-/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
-static Button buttons[] = {
- /* click event mask button function argument */
- { ClkTagBar, MODKEY, Button1, tag, {0} },
- { ClkTagBar, MODKEY, Button3, toggletag, {0} },
- { ClkWinTitle, 0, Button2, zoom, {0} },
- { ClkStatusText, 0, Button2, spawn, {.v = term_cmd } },
- { 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} },
-};
-
diff --git a/config.mk b/config.mk
index 627ae1a..cfef3dc 100644
--- a/config.mk
+++ b/config.mk
@@ -1,5 +1,5 @@
# dwm version
-VERSION = 6.3
+VERSION = 6.5
# Customize below to fit your system
@@ -7,8 +7,8 @@ VERSION = 6.3
PREFIX = /usr/local
MANPREFIX = ${PREFIX}/share/man
-X11INC = /usr/local/include
-X11LIB = /usr/local/lib
+X11INC = /usr/X11R6/include
+X11LIB = /usr/X11R6/lib
# Xinerama, comment if you don't want it
XINERAMALIBS = -lXinerama
@@ -18,16 +18,17 @@ XINERAMAFLAGS = -DXINERAMA
FREETYPELIBS = -lfontconfig -lXft
FREETYPEINC = /usr/include/freetype2
# OpenBSD (uncomment)
-# FREETYPEINC = ${X11INC}/freetype2
+#FREETYPEINC = ${X11INC}/freetype2
+#MANPREFIX = ${PREFIX}/man
# 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} -DHOME=\"${HOME}/\" -DHOMEBIN=\"${HOME}/.local/bin/\"
+CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -DHOME=\"${HOME}/\" -DHOMEBIN=\"${HOME}/.local/bin/\"
#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS}
-CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -march=haswell -O3 -pipe ${INCS} ${CPPFLAGS}
+CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -march=alderlake -Os -pipe ${INCS} ${CPPFLAGS}
LDFLAGS = ${LIBS}
# Solaris
diff --git a/drw.c b/drw.c
index 8bc82e9..9aa5f24 100644
--- a/drw.c
+++ b/drw.c
@@ -9,54 +9,40 @@
#include "util.h"
#define UTF_INVALID 0xFFFD
-#define UTF_SIZ 4
-static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
-static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
-static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000};
-static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
-
-static long
-utf8decodebyte(const char c, size_t *i)
-{
- for (*i = 0; *i < (UTF_SIZ + 1); ++(*i))
- if (((unsigned char)c & utfmask[*i]) == utfbyte[*i])
- return (unsigned char)c & ~utfmask[*i];
- return 0;
-}
-
-static size_t
-utf8validate(long *u, size_t i)
-{
- if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF))
- *u = UTF_INVALID;
- for (i = 1; *u > utfmax[i]; ++i)
- ;
- return i;
-}
-
-static size_t
-utf8decode(const char *c, long *u, size_t clen)
+static int
+utf8decode(const char *s_in, long *u, int *err)
{
- size_t i, j, len, type;
- long udecoded;
-
+ static const unsigned char lens[] = {
+ /* 0XXXX */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ /* 10XXX */ 0, 0, 0, 0, 0, 0, 0, 0, /* invalid */
+ /* 110XX */ 2, 2, 2, 2,
+ /* 1110X */ 3, 3,
+ /* 11110 */ 4,
+ /* 11111 */ 0, /* invalid */
+ };
+ static const unsigned char leading_mask[] = { 0x7F, 0x1F, 0x0F, 0x07 };
+ static const unsigned int overlong[] = { 0x0, 0x80, 0x0800, 0x10000 };
+
+ const unsigned char *s = (const unsigned char *)s_in;
+ int len = lens[*s >> 3];
*u = UTF_INVALID;
- if (!clen)
- return 0;
- udecoded = utf8decodebyte(c[0], &len);
- if (!BETWEEN(len, 1, UTF_SIZ))
+ *err = 1;
+ if (len == 0)
return 1;
- for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
- udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type);
- if (type)
- return j;
+
+ long cp = s[0] & leading_mask[len - 1];
+ for (int i = 1; i < len; ++i) {
+ if (s[i] == '\0' || (s[i] & 0xC0) != 0x80)
+ return i;
+ cp = (cp << 6) | (s[i] & 0x3F);
}
- if (j < len)
- return 0;
- *u = udecoded;
- utf8validate(u, len);
+ /* out of range, surrogate, overlong encoding */
+ if (cp > 0x10FFFF || (cp >> 11) == 0x1B || cp < overlong[len - 1])
+ return len;
+ *err = 0;
+ *u = cp;
return len;
}
@@ -133,19 +119,6 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
die("no font specified.");
}
- /* Do not allow using color fonts. This is a workaround for a BadLength
- * error from Xft with color glyphs. Modelled on the Xterm workaround. See
- * https://bugzilla.redhat.com/show_bug.cgi?id=1498269
- * https://lists.suckless.org/dev/1701/30932.html
- * https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=916349
- * and lots more all over the internet.
- */
- 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;
font->pattern = pattern;
@@ -203,6 +176,7 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
DefaultColormap(drw->dpy, drw->screen),
clrname, dest))
die("error, cannot allocate color '%s'", clrname);
+
dest->pixel |= 0xff << 24;
}
@@ -252,29 +226,32 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int
int
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert)
{
- char buf[1024];
- int ty;
- unsigned int ew;
+ int ty, ellipsis_x = 0;
+ unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len, hash, h0, h1;
XftDraw *d = NULL;
Fnt *usedfont, *curfont, *nextfont;
- size_t i, len;
- int utf8strlen, utf8charlen, render = x || y || w || h;
+ int utf8strlen, utf8charlen, utf8err, render = x || y || w || h;
long utf8codepoint = 0;
const char *utf8str;
FcCharSet *fccharset;
FcPattern *fcpattern;
FcPattern *match;
XftResult result;
- int charexists = 0;
+ int charexists = 0, overflow = 0;
+ /* keep track of a couple codepoints for which we have no match. */
+ static unsigned int nomatches[128], ellipsis_width, invalid_width;
+ static const char invalid[] = "�";
- if (!drw || (render && !drw->scheme) || !text || !drw->fonts)
+ if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts)
return 0;
if (!render) {
- w = ~w;
+ w = invert ? invert : ~invert;
} else {
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
+ if (w < lpad)
+ return x + w;
d = XftDrawCreate(drw->dpy, drw->drawable,
DefaultVisual(drw->dpy, drw->screen),
DefaultColormap(drw->dpy, drw->screen));
@@ -283,18 +260,40 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
}
usedfont = drw->fonts;
+ if (!ellipsis_width && render)
+ ellipsis_width = drw_fontset_getwidth(drw, "...");
+ if (!invalid_width && render)
+ invalid_width = drw_fontset_getwidth(drw, invalid);
while (1) {
- utf8strlen = 0;
+ ew = ellipsis_len = utf8err = utf8charlen = utf8strlen = 0;
utf8str = text;
nextfont = NULL;
while (*text) {
- utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
+ utf8charlen = utf8decode(text, &utf8codepoint, &utf8err);
for (curfont = drw->fonts; curfont; curfont = curfont->next) {
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
if (charexists) {
- if (curfont == usedfont) {
- utf8strlen += utf8charlen;
+ drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL);
+ if (ew + ellipsis_width <= w) {
+ /* keep track where the ellipsis still fits */
+ ellipsis_x = x + ew;
+ ellipsis_w = w - ew;
+ ellipsis_len = utf8strlen;
+ }
+
+ if (ew + tmpw > w) {
+ overflow = 1;
+ /* called from drw_fontset_getwidth_clamp():
+ * it wants the width AFTER the overflow
+ */
+ if (!render)
+ x += tmpw;
+ else
+ utf8strlen = ellipsis_len;
+ } else if (curfont == usedfont) {
text += utf8charlen;
+ utf8strlen += utf8err ? 0 : utf8charlen;
+ ew += utf8err ? 0 : tmpw;
} else {
nextfont = curfont;
}
@@ -302,36 +301,31 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
}
}
- if (!charexists || nextfont)
+ if (overflow || !charexists || nextfont || utf8err)
break;
else
charexists = 0;
}
if (utf8strlen) {
- drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL);
- /* shorten text if necessary */
- for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--)
- drw_font_getexts(usedfont, utf8str, len, &ew, NULL);
-
- if (len) {
- memcpy(buf, utf8str, len);
- buf[len] = '\0';
- if (len < utf8strlen)
- for (i = len; i && i > len - 3; buf[--i] = '.')
- ; /* NOP */
-
- if (render) {
- ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
- XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
- usedfont->xfont, x, ty, (XftChar8 *)buf, len);
- }
- x += ew;
- w -= ew;
+ if (render) {
+ ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
+ XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
+ usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen);
}
+ x += ew;
+ w -= ew;
}
+ if (utf8err && (!render || invalid_width < w)) {
+ if (render)
+ drw_text(drw, x, y, w, h, 0, invalid, invert);
+ x += invalid_width;
+ w -= invalid_width;
+ }
+ if (render && overflow)
+ drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert);
- if (!*text) {
+ if (!*text || overflow) {
break;
} else if (nextfont) {
charexists = 0;
@@ -341,6 +335,15 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
* character must be drawn. */
charexists = 1;
+ hash = (unsigned int)utf8codepoint;
+ hash = ((hash >> 16) ^ hash) * 0x21F0AAAD;
+ hash = ((hash >> 15) ^ hash) * 0xD35A2D97;
+ h0 = ((hash >> 15) ^ hash) % LENGTH(nomatches);
+ h1 = (hash >> 17) % LENGTH(nomatches);
+ /* avoid expensive XftFontMatch call when we know we won't find a match */
+ if (nomatches[h0] == utf8codepoint || nomatches[h1] == utf8codepoint)
+ goto no_match;
+
fccharset = FcCharSetCreate();
FcCharSetAddChar(fccharset, utf8codepoint);
@@ -352,7 +355,6 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
fcpattern = FcPatternDuplicate(drw->fonts->pattern);
FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
- FcPatternAddBool(fcpattern, FC_COLOR, FcFalse);
FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
FcDefaultSubstitute(fcpattern);
@@ -369,6 +371,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
curfont->next = usedfont;
} else {
xfont_free(usedfont);
+ nomatches[nomatches[h0] ? h1 : h0] = utf8codepoint;
+no_match:
usedfont = drw->fonts;
}
}
@@ -398,6 +402,15 @@ drw_fontset_getwidth(Drw *drw, const char *text)
return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
}
+unsigned int
+drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n)
+{
+ unsigned int tmp = 0;
+ if (drw && drw->fonts && text && n)
+ tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n);
+ return MIN(n, tmp);
+}
+
void
drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
{
diff --git a/drw.h b/drw.h
index 4bcd5ad..6471431 100644
--- a/drw.h
+++ b/drw.h
@@ -35,6 +35,7 @@ void drw_free(Drw *drw);
Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
void drw_fontset_free(Fnt* set);
unsigned int drw_fontset_getwidth(Drw *drw, const char *text);
+unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n);
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
/* Colorscheme abstraction */
diff --git a/dwm.1 b/dwm.1
index d8b2f15..53c9b02 100644
--- a/dwm.1
+++ b/dwm.1
@@ -110,6 +110,9 @@ Increase master area size.
.B Mod1\-h
Decrease master area size.
.TP
+.B Mod1\-o
+Select view of the window in focus. The list of tags to be displayed is matched to the window tag list.
+.TP
.B Mod1\-Return
Zooms/cycles focused window to/from master area (tiled layouts only).
.TP
@@ -143,16 +146,6 @@ View all windows with any tag.
.B Mod1\-Control\-[1..n]
Add/remove all windows with nth tag to/from the view.
.TP
-.B Mod1\--
-Decrease the gaps around windows.
-.TP
-.B Mod1\-=
-Increase the gaps around windows.
-.TP
-.B Mod1\-Shift-=
-Reset the gaps around windows to
-.BR 0 .
-.TP
.B Mod1\-Shift\-q
Quit dwm.
.SS Mouse commands
diff --git a/dwm.c b/dwm.c
index d6788e0..6379295 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"
@@ -51,7 +57,6 @@
* MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
#define ISVISIBLEONTAG(C, T) ((C->tags & T))
#define ISVISIBLE(C) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags])
-#define LENGTH(X) (sizeof X / sizeof X[0])
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
#define WIDTH(X) ((X)->w + 2 * (X)->bw)
#define HEIGHT(X) ((X)->h + 2 * (X)->bw)
@@ -106,13 +111,15 @@ struct Client {
int x, y, w, h;
int sfx, sfy, sfw, sfh; /* stored float geometry, used on mode revert */
int oldx, oldy, oldw, oldh;
- int basew, baseh, incw, inch, maxw, maxh, minw, minh;
+ int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid;
int bw, oldbw;
unsigned int tags;
- unsigned int switchtotag;
- int isfixed, isfloating, isfreesize, isurgent, neverfocus, oldstate, isfullscreen;
+ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow, isforegrounded;
+ pid_t pid;
Client *next;
Client *snext;
+ Client *tnext;
+ Client *swallowing;
Monitor *mon;
Window win;
};
@@ -147,6 +154,7 @@ struct Monitor {
Client *clients;
Client *sel;
Client *stack;
+ Client *foregrounded;
Monitor *next;
Window barwin;
const Layout *lt[2];
@@ -158,9 +166,9 @@ typedef struct {
const char *instance;
const char *title;
unsigned int tags;
- unsigned int switchtotag;
int isfloating;
- int isfreesize;
+ int isterminal;
+ int noswallow;
int monitor;
} Rule;
@@ -179,6 +187,10 @@ static void attach(Client *c);
static void attachBelow(Client *c);
static void attachstack(Client *c);
static void buttonpress(XEvent *e);
+static void bstack(Monitor *m);
+static void bstackhoriz(Monitor *m);
+static void centeredmaster(Monitor *m);
+static void centeredfloatingmaster(Monitor *m);
static void checkotherwm(void);
static void cleanup(void);
static void cleanupmon(Monitor *mon);
@@ -203,7 +215,7 @@ 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 unsigned int getsystraywidth(void);
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
static void grabbuttons(Client *c, int focused);
static void grabkeys(void);
@@ -215,9 +227,10 @@ static void mappingnotify(XEvent *e);
static void maprequest(XEvent *e);
static void monocle(Monitor *m);
static void movemouse(const Arg *arg);
+static void movestack(const Arg *arg);
static Client *nexttagged(Client *c);
static Client *nexttiled(Client *c);
-static void pop(Client *);
+static void nrowgrid(Monitor *m);
static void propertynotify(XEvent *e);
static void quit(const Arg *arg);
static Monitor *recttomon(int x, int y, int w, int h);
@@ -241,7 +254,6 @@ static void setmfact(const Arg *arg);
static void setup(void);
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 switchtag(const Arg *arg);
@@ -250,9 +262,10 @@ static void tagmon(const Arg *arg);
static void tagnextmon(const Arg *arg);
static void tagprevmon(const Arg *arg);
static void tagothermon(const Arg *arg, int dir);
-static void tile(Monitor *);
+static void tile(Monitor *m);
static void togglebar(const Arg *arg);
static void togglefloating(const Arg *arg);
+static void toggleforegrounded(const Arg *arg);
static void togglefullscr(const Arg *arg);
static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
@@ -276,15 +289,17 @@ static void view(const Arg *arg);
static Client *wintoclient(Window w);
static Monitor *wintomon(Window w);
static Client *wintosystrayicon(Window w);
+static void winview(const Arg* arg);
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 centeredmaster(Monitor *m);
-static void centeredfloatingmaster(Monitor *m);
-static void bstack(Monitor *m);
-static void bstackhoriz(Monitor *m);
-static void stairs(Monitor *m);
+
+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 Systray *systray = NULL;
@@ -293,7 +308,7 @@ static const char broken[] = "broken";
static char stext[256];
static int screen;
static int sw, sh; /* X display screen geometry width, height */
-static int bh, blw = 0; /* bar geometry */
+static int bh; /* bar height */
static int lrpad; /* sum of left and right padding for text */
static int (*xerrorxlib)(Display *, XErrorEvent *);
static unsigned int numlockmask = 0;
@@ -316,12 +331,14 @@ static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast];
static int running = 1;
static Cur *cursor[CurLast];
static Clr **scheme;
-static Clr **tagscheme;
static Display *dpy;
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"
@@ -349,7 +366,6 @@ applyrules(Client *c)
/* rule matching */
c->isfloating = 0;
- c->isfreesize = 1;
c->tags = 0;
XGetClassHint(dpy, c->win, &ch);
class = ch.res_class ? ch.res_class : broken;
@@ -361,17 +377,13 @@ 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->isfreesize = r->isfreesize;
c->tags |= r->tags;
for (m = mons; m && m->num != r->monitor; m = m->next);
if (m)
c->mon = m;
- if (r->switchtotag) {
- Arg a = { .ui = r->tags };
- c->switchtotag = selmon->tagset[selmon->seltags];
- view(&a);
- }
}
}
if (ch.res_class)
@@ -414,6 +426,8 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact)
if (*w < bh)
*w = bh;
if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) {
+ if (!c->hintsvalid)
+ updatesizehints(c);
/* see last two sentences in ICCCM 4.1.2.3 */
baseismin = c->basew == c->minw && c->baseh == c->minh;
if (!baseismin) { /* temporarily remove base dimensions */
@@ -475,18 +489,19 @@ attach(Client *c)
c->next = c->mon->clients;
c->mon->clients = c;
}
+
void
attachBelow(Client *c)
{
//If there is nothing on the monitor or the selected client is floating, attach as normal
if(c->mon->sel == NULL || c->mon->sel->isfloating) {
- Client *at = nexttagged(c);
- if(!at) {
- attach(c);
- return;
- }
- c->next = at->next;
- at->next = c;
+ Client *at = nexttagged(c);
+ if(!at) {
+ attach(c);
+ return;
+ }
+ c->next = at->next;
+ at->next = c;
return;
}
@@ -505,6 +520,68 @@ attachstack(Client *c)
}
void
+attachforegrounded (Client *c)
+{
+ c->tnext = c->mon->foregrounded;
+ c->mon->foregrounded = c;
+}
+
+void
+detachforegrounded (Client *c)
+{
+ Client **tc;
+ for (tc = &c->mon->foregrounded; *tc && *tc != c; tc = &(*tc)->tnext);
+ *tc = c->tnext;
+}
+
+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)
{
unsigned int i, x, click;
@@ -532,7 +609,7 @@ buttonpress(XEvent *e)
if(i < LENGTH(tags) && (drawtagmask & DRAWCLASSICTAGS)) {
click = ClkTagBar;
arg.ui = 1 << i;
- } else if((ev->x < x + columns * bh / tagrows) && (drawtagmask & DRAWTAGGRID) != 0) {
+ } else if(ev->x < x + columns * bh / tagrows && (drawtagmask & DRAWTAGGRID)) {
click = ClkTagBar;
i = (ev->x - x) / (bh / tagrows);
i = i + columns * (ev->y / (bh / tagrows));
@@ -541,7 +618,7 @@ buttonpress(XEvent *e)
}
arg.ui = 1 << i;
}
- else if(ev->x < x + blw + columns * bh / tagrows)
+ else if (ev->x < x + TEXTW(selmon->ltsymbol) + columns * bh / tagrows)
click = ClkLtSymbol;
else if (ev->x > selmon->ww - (int)TEXTW(stext) - getsystraywidth())
click = ClkStatusText;
@@ -559,6 +636,171 @@ buttonpress(XEvent *e)
buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);
}
+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);
+ }
+ }
+}
+
+void
+centeredmaster(Monitor *m)
+{
+ unsigned int i, n, h, mw, mx, my, oty, ety, tw;
+ Client *c;
+
+ /* count number of clients in the selected monitor */
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
+ if (n == 0)
+ return;
+
+ /* initialize areas */
+ mw = m->ww;
+ mx = 0;
+ my = 0;
+ tw = mw;
+
+ if (n > m->nmaster) {
+ /* go mfact box in the center if more than nmaster clients */
+ mw = m->nmaster ? m->ww * m->mfact : 0;
+ tw = m->ww - mw;
+
+ if (n - m->nmaster > 1) {
+ /* only one client */
+ mx = (m->ww - mw) / 2;
+ tw = (m->ww - mw) / 2;
+ }
+ }
+
+ oty = 0;
+ ety = 0;
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
+ if (i < m->nmaster) {
+ /* nmaster clients are stacked vertically, in the center
+ * of the screen */
+ h = (m->wh - my) / (MIN(n, m->nmaster) - i);
+ resize(c, m->wx + mx, m->wy + my, mw - (2*c->bw),
+ h - (2*c->bw), 0);
+ my += HEIGHT(c);
+ } else {
+ /* stack clients are stacked vertically */
+ if ((i - m->nmaster) % 2 ) {
+ h = (m->wh - ety) / ( (1 + n - i) / 2);
+ resize(c, m->wx, m->wy + ety, tw - (2*c->bw),
+ h - (2*c->bw), 0);
+ ety += HEIGHT(c);
+ } else {
+ h = (m->wh - oty) / ((1 + n - i) / 2);
+ resize(c, m->wx + mx + mw, m->wy + oty,
+ tw - (2*c->bw), h - (2*c->bw), 0);
+ oty += HEIGHT(c);
+ }
+ }
+}
+
+void
+centeredfloatingmaster(Monitor *m)
+{
+ unsigned int i, n, w, mh, mw, mx, mxo, my, myo, tx;
+ Client *c;
+
+ /* count number of clients in the selected monitor */
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
+ if (n == 0)
+ return;
+
+ /* initialize nmaster area */
+ if (n > m->nmaster) {
+ /* go mfact box in the center if more than nmaster clients */
+ if (m->ww > m->wh) {
+ mw = m->nmaster ? m->ww * m->mfact : 0;
+ mh = m->nmaster ? m->wh * 0.9 : 0;
+ } else {
+ mh = m->nmaster ? m->wh * m->mfact : 0;
+ mw = m->nmaster ? m->ww * 0.9 : 0;
+ }
+ mx = mxo = (m->ww - mw) / 2;
+ my = myo = (m->wh - mh) / 2;
+ } else {
+ /* go fullscreen if all clients are in the master area */
+ mh = m->wh;
+ mw = m->ww;
+ mx = mxo = 0;
+ my = myo = 0;
+ }
+
+ for(i = tx = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
+ if (i < m->nmaster) {
+ /* nmaster clients are stacked horizontally, in the center
+ * of the screen */
+ w = (mw + mxo - mx) / (MIN(n, m->nmaster) - i);
+ resize(c, m->wx + mx, m->wy + my, w - (2*c->bw),
+ mh - (2*c->bw), 0);
+ mx += WIDTH(c);
+ } else {
+ /* stack clients are stacked horizontally */
+ w = (m->ww - tx) / (n - i);
+ resize(c, m->wx + tx, m->wy, w - (2*c->bw),
+ m->wh - (2*c->bw), 0);
+ tx += WIDTH(c);
+ }
+}
+
void
checkotherwm(void)
{
@@ -597,6 +839,7 @@ cleanup(void)
drw_cur_free(drw, cursor[i]);
for (i = 0; i < LENGTH(colors); i++)
free(scheme[i]);
+ free(scheme);
XDestroyWindow(dpy, wmcheckwin);
drw_free(drw);
XSync(dpy, False);
@@ -828,6 +1071,8 @@ destroynotify(XEvent *e)
if ((c = wintoclient(ev->window)))
unmanage(c, 1);
+ else if ((c = swallowingclient(ev->window)))
+ unmanage(c->swallowing, 1);
else if ((c = wintosystrayicon(ev->window))) {
removesystrayicon(c);
resizebarwin(selmon);
@@ -907,7 +1152,7 @@ drawbar(Monitor *m)
if (drawtagmask & DRAWCLASSICTAGS)
for (i = 0; i < LENGTH(tags); i++) {
w = TEXTW(tags[i]);
- drw_setscheme(drw, (m->tagset[m->seltags] & 1 << i ? tagscheme[i] : scheme[SchemeNorm]));
+ 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,
@@ -918,7 +1163,7 @@ drawbar(Monitor *m)
if (drawtagmask & DRAWTAGGRID) {
drawtaggrid(m,&x,occ);
}
- w = blw = TEXTW(m->ltsymbol);
+ w = TEXTW(m->ltsymbol);
drw_setscheme(drw, scheme[SchemeNorm]);
x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
@@ -945,9 +1190,11 @@ drawbar(Monitor *m)
continue;
tw = MIN(m->sel == c ? w : mw, TEXTW(c->name));
- drw_setscheme(drw, scheme[m == selmon && m->sel == c ? SchemeSel : SchemeNorm]);
+ drw_setscheme(drw, scheme[SchemeNorm]);
if (tw > lrpad / 2)
- drw_text(drw, x, 0, tw, bh, lrpad / 2, c->name, 0);
+ drw_text(drw, x, text_ypos, tw, bh, lrpad / 2, c->name, 0);
+ drw_setscheme(drw, scheme[m == selmon && m->sel == c ? SchemeSel : SchemeNorm]);
+ drw_rect(drw, x , bh - brdsh_ypos , tw , brdsh_w , 1, 1);
if (c->isfloating)
drw_rect(drw, x + boxs, boxs, boxw, boxw, c->isfixed, 0);
x += tw;
@@ -969,47 +1216,48 @@ drawbars(void)
drawbar(m);
}
-void drawtaggrid(Monitor *m, int *x_pos, unsigned int occ)
+void
+drawtaggrid(Monitor *m, int *x_pos, unsigned int occ)
{
- unsigned int x, y, h, max_x, columns;
- int invert, i,j, k;
+ unsigned int x, y, h, max_x, columns;
+ int invert, i,j, k;
- h = bh / tagrows;
- x = max_x = *x_pos;
- y = 0;
- columns = LENGTH(tags) / tagrows + ((LENGTH(tags) % tagrows > 0) ? 1 : 0);
+ h = bh / tagrows;
+ x = max_x = *x_pos;
+ y = 0;
+ columns = LENGTH(tags) / tagrows + ((LENGTH(tags) % tagrows > 0) ? 1 : 0);
- /* Firstly we will fill the borders of squares */
+ /* Firstly we will fill the borders of squares */
- XSetForeground(drw->dpy, drw->gc, scheme[SchemeNorm][ColBorder].pixel);
- XFillRectangle(dpy, drw->drawable, drw->gc, x, y, h*columns + 1, bh);
+ XSetForeground(drw->dpy, drw->gc, scheme[SchemeNorm][ColBorder].pixel);
+ XFillRectangle(dpy, drw->drawable, drw->gc, x, y, h*columns + 1, bh);
- /* We will draw LENGTH(tags) squares in tagraws raws. */
+ /* We will draw LENGTH(tags) squares in tagraws raws. */
for(j = 0, i= 0; j < tagrows; j++) {
- x = *x_pos;
- for (k = 0; k < columns && i < LENGTH(tags); k++, i++) {
- invert = m->tagset[m->seltags] & 1 << i ? 0 : 1;
-
- /* Select active color for current square */
- XSetForeground(drw->dpy, drw->gc, !invert ? scheme[SchemeSel][ColBg].pixel :
- scheme[SchemeNorm][ColFg].pixel);
- XFillRectangle(dpy, drw->drawable, drw->gc, x+1, y+1, h-1, h-1);
-
- /* Mark square if tag has client */
- if (occ & 1 << i) {
- XSetForeground(drw->dpy, drw->gc, !invert ? scheme[SchemeSel][ColFg].pixel :
- scheme[SchemeNorm][ColBg].pixel);
- XFillRectangle(dpy, drw->drawable, drw->gc, x + 1, y + 1,
- h / 2, h / 2);
- }
- x += h;
- if (x > max_x) {
- max_x = x;
- }
- }
- y += h;
+ x = *x_pos;
+ for (k = 0; k < columns && i < LENGTH(tags); k++, i++) {
+ invert = m->tagset[m->seltags] & 1 << i ? 0 : 1;
+
+ /* Select active color for current square */
+ XSetForeground(drw->dpy, drw->gc, !invert ? scheme[SchemeSel][ColBg].pixel :
+ scheme[SchemeNorm][ColFg].pixel);
+ XFillRectangle(dpy, drw->drawable, drw->gc, x+1, y+1, h-1, h-1);
+
+ /* Mark square if tag has client */
+ if (occ & 1 << i) {
+ XSetForeground(drw->dpy, drw->gc, !invert ? scheme[SchemeSel][ColFg].pixel :
+ scheme[SchemeNorm][ColBg].pixel);
+ XFillRectangle(dpy, drw->drawable, drw->gc, x + 1, y + 1,
+ h / 2, h / 2);
+ }
+ x += h;
+ if (x > max_x) {
+ max_x = x;
+ }
+ }
+ y += h;
}
- *x_pos = max_x + 1;
+ *x_pos = max_x + 1;
}
void
@@ -1184,13 +1432,11 @@ gettextprop(Window w, Atom atom, char *text, unsigned int size)
text[0] = '\0';
if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems)
return 0;
- if (name.encoding == XA_STRING)
+ if (name.encoding == XA_STRING) {
strncpy(text, (char *)name.value, size - 1);
- else {
- if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) {
- strncpy(text, *list, size - 1);
- XFreeStringList(list);
- }
+ } else if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) {
+ strncpy(text, *list, size - 1);
+ XFreeStringList(list);
}
text[size - 1] = '\0';
XFree(name.value);
@@ -1223,16 +1469,26 @@ grabkeys(void)
{
updatenumlockmask();
{
- unsigned int i, j;
+ unsigned int i, j, k;
unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
- KeyCode code;
+ int start, end, skip;
+ KeySym *syms;
XUngrabKey(dpy, AnyKey, AnyModifier, root);
- for (i = 0; i < LENGTH(keys); i++)
- if ((code = XKeysymToKeycode(dpy, keys[i].keysym)))
- for (j = 0; j < LENGTH(modifiers); j++)
- XGrabKey(dpy, code, keys[i].mod | modifiers[j], root,
- True, GrabModeAsync, GrabModeAsync);
+ XDisplayKeycodes(dpy, &start, &end);
+ syms = XGetKeyboardMapping(dpy, start, end - start + 1, &skip);
+ if (!syms)
+ return;
+ for (k = start; k <= end; k++)
+ for (i = 0; i < LENGTH(keys); i++)
+ /* skip modifier codes, we do that ourselves */
+ if (keys[i].keysym == syms[(k - start) * skip])
+ for (j = 0; j < LENGTH(modifiers); j++)
+ XGrabKey(dpy, k,
+ keys[i].mod | modifiers[j],
+ root, True,
+ GrabModeAsync, GrabModeAsync);
+ XFree(syms);
}
}
@@ -1291,12 +1547,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;
@@ -1311,16 +1568,15 @@ manage(Window w, XWindowAttributes *wa)
} else {
c->mon = selmon;
applyrules(c);
+ term = termforwin(c);
}
- if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw)
- c->x = c->mon->mx + c->mon->mw - WIDTH(c);
- if (c->y + HEIGHT(c) > c->mon->my + c->mon->mh)
- c->y = c->mon->my + c->mon->mh - HEIGHT(c);
- c->x = MAX(c->x, c->mon->mx);
- /* only fix client y-offset, if the client center might cover the bar */
- c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx)
- && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my);
+ if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww)
+ c->x = c->mon->wx + c->mon->ww - WIDTH(c);
+ if (c->y + HEIGHT(c) > c->mon->wy + c->mon->wh)
+ c->y = c->mon->wy + c->mon->wh - HEIGHT(c);
+ c->x = MAX(c->x, c->mon->wx);
+ c->y = MAX(c->y, c->mon->wy);
c->bw = borderpx;
wc.border_width = c->bw;
@@ -1336,7 +1592,6 @@ manage(Window w, XWindowAttributes *wa)
c->sfy = c->y;
c->sfw = c->w;
c->sfh = c->h;
-
XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
grabbuttons(c, 0);
if (!c->isfloating)
@@ -1349,11 +1604,15 @@ manage(Window w, XWindowAttributes *wa)
(unsigned char *) &(c->win), 1);
XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */
setclientstate(c, NormalState);
+ if(selmon->sel && selmon->sel->isfullscreen && !c->isfloating)
+ setfullscreen(selmon->sel, 0);
if (c->mon == selmon)
unfocus(selmon->sel, 0);
c->mon->sel = c;
arrange(c->mon);
XMapWindow(dpy, c->win);
+ if (term)
+ swallow(term, c);
focus(NULL);
}
@@ -1380,9 +1639,7 @@ maprequest(XEvent *e)
updatesystray();
}
- if (!XGetWindowAttributes(dpy, ev->window, &wa))
- return;
- if (wa.override_redirect)
+ if (!XGetWindowAttributes(dpy, ev->window, &wa) || wa.override_redirect)
return;
if (!wintoclient(ev->window))
manage(ev->window, &wa);
@@ -1463,6 +1720,55 @@ movemouse(const Arg *arg)
}
}
+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);
+ }
+}
+
Client *
nexttagged(Client *c) {
Client *walked = c->mon->clients;
@@ -1480,13 +1786,90 @@ nexttiled(Client *c)
return c;
}
+Client*
+nextforegrounded(Client *c)
+{
+ for (; c && (!c->isforegrounded || !ISVISIBLE(c)); c = c->tnext);
+ return c;
+}
+
void
-pop(Client *c)
+arrangeforegrounded (Monitor *m)
{
- detach(c);
- attach(c);
- focus(c);
- arrange(c->mon);
+ unsigned int n,i,x,y,w,h;
+ Client *c;
+
+ for (n = 0, c = nextforegrounded(m->foregrounded); c; c = nextforegrounded(c->tnext), n++);
+ if (n == 0)
+ return;
+
+ for (i = 0, c = nextforegrounded(m->foregrounded); c; c = nextforegrounded(c->tnext), i++){
+ if (n == 1) {
+ x = m->mx + (m->mw - m->mw * fgw) / 2;
+ y = m->my + (m->mh - m->mh * fgh) / 2;
+ w = (m->mw * fgw) - (2 * (m->foregrounded->bw));
+ h = (m->mh * fgh) - (2 * (m->foregrounded->bw));
+ } else {
+ x = m->mx + (n - 1 - i) * (m->mw / n);
+ y = m->my + (m->mh - m->mh * fgh) / 2;
+ w = (m->mw * (1 / (float)n)) - (2 * (m->foregrounded->bw));
+ h = (m->mh * fgh) - (2 * (m->foregrounded->bw));
+ }
+ resize(c,x,y,w,h,0);
+ }
+}
+
+void
+nrowgrid(Monitor *m)
+{
+ unsigned int n = 0, i = 0, ri = 0, ci = 0; /* counters */
+ unsigned int cx, cy, cw, ch; /* client geometry */
+ unsigned int uw = 0, uh = 0, uc = 0; /* utilization trackers */
+ unsigned int cols, rows = m->nmaster + 1;
+ Client *c;
+
+ /* count clients */
+ for (c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
+
+ /* nothing to do here */
+ if (n == 0)
+ return;
+
+ /* force 2 clients to always split vertically */
+ if (FORCE_VSPLIT && n == 2)
+ rows = 1;
+
+ /* never allow empty rows */
+ if (n < rows)
+ rows = n;
+
+ /* define first row */
+ cols = n / rows;
+ uc = cols;
+ cy = m->wy;
+ ch = m->wh / rows;
+ uh = ch;
+
+ for (c = nexttiled(m->clients); c; c = nexttiled(c->next), i++, ci++) {
+ if (ci == cols) {
+ uw = 0;
+ ci = 0;
+ ri++;
+
+ /* next row */
+ cols = (n - uc) / (rows - ri);
+ uc += cols;
+ cy = m->wy + uh;
+ ch = (m->wh - uh) / (rows - ri);
+ uh += ch;
+ }
+
+ cx = m->wx + uw;
+ cw = (m->ww - uw) / (cols - ci);
+ uw += cw;
+
+ resize(c, cx, cy, cw - 2 * c->bw, ch - 2 * c->bw, 0);
+ }
}
void
@@ -1520,7 +1903,7 @@ propertynotify(XEvent *e)
arrange(c->mon);
break;
case XA_WM_NORMAL_HINTS:
- updatesizehints(c);
+ c->hintsvalid = 0;
break;
case XA_WM_HINTS:
updatewmhints(c);
@@ -1879,9 +2262,16 @@ setup(void)
int i;
XSetWindowAttributes wa;
Atom utf8string;
+ struct sigaction sa;
+
+ /* do not transform children into zombies when they terminate */
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT | SA_RESTART;
+ sa.sa_handler = SIG_IGN;
+ sigaction(SIGCHLD, &sa, NULL);
- /* clean up any zombies immediately */
- sigchld(0);
+ /* clean up any zombies (inherited from .xinitrc etc) immediately */
+ while (waitpid(-1, NULL, WNOHANG) > 0);
/* init screen */
screen = DefaultScreen(dpy);
@@ -1892,7 +2282,7 @@ setup(void)
if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
die("no fonts could be loaded.");
lrpad = drw->fonts->h;
- bh = user_bh ? user_bh : drw->fonts->h + 2;
+ bh = drw->fonts->h + 2;
updategeom();
/* init atoms */
utf8string = XInternAtom(dpy, "UTF8_STRING", False);
@@ -1921,14 +2311,9 @@ setup(void)
cursor[CurResize] = drw_cur_create(drw, XC_sizing);
cursor[CurMove] = drw_cur_create(drw, XC_fleur);
/* init appearance */
- if (LENGTH(tags) > LENGTH(tagsel))
- die("too few color schemes for the tags");
scheme = ecalloc(LENGTH(colors), sizeof(Clr *));
for (i = 0; i < LENGTH(colors); i++)
scheme[i] = drw_scm_create(drw, colors[i], 3);
- tagscheme = ecalloc(LENGTH(tagsel), sizeof(Clr *));
- for (i = 0; i < LENGTH(tagsel); i++)
- tagscheme[i] = drw_scm_create(drw, tagsel[i], 2);
/* init system tray */
updatesystray();
/* init bars */
@@ -1957,7 +2342,6 @@ setup(void)
focus(NULL);
}
-
void
seturgent(Client *c, int urg)
{
@@ -1988,140 +2372,103 @@ showhide(Client *c)
XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y);
}
}
-void switchtag(const Arg *arg)
-{
- unsigned int columns;
- unsigned int new_tagset = 0;
- unsigned int pos, i;
- int col, row;
- Arg new_arg;
-
- columns = LENGTH(tags) / tagrows + ((LENGTH(tags) % tagrows > 0) ? 1 : 0);
-
- for (i = 0; i < LENGTH(tags); ++i) {
- if (!(selmon->tagset[selmon->seltags] & 1 << i)) {
- continue;
- }
- pos = i;
- row = pos / columns;
- col = pos % columns;
- if (arg->ui & SWITCHTAG_UP) { /* UP */
- row --;
- if (row < 0) {
- row = tagrows - 1;
- }
- do {
- pos = row * columns + col;
- row --;
- } while (pos >= LENGTH(tags));
- }
- if (arg->ui & SWITCHTAG_DOWN) { /* DOWN */
- row ++;
- if (row >= tagrows) {
- row = 0;
- }
- pos = row * columns + col;
- if (pos >= LENGTH(tags)) {
- row = 0;
- }
- pos = row * columns + col;
- }
- if (arg->ui & SWITCHTAG_LEFT) { /* LEFT */
- col --;
- if (col < 0) {
- col = columns - 1;
- }
- do {
- pos = row * columns + col;
- col --;
- } while (pos >= LENGTH(tags));
- }
- if (arg->ui & SWITCHTAG_RIGHT) { /* RIGHT */
- col ++;
- if (col >= columns) {
- col = 0;
- }
- pos = row * columns + col;
- if (pos >= LENGTH(tags)) {
- col = 0;
- pos = row * columns + col;
- }
- }
- new_tagset |= 1 << pos;
- }
- new_arg.ui = new_tagset;
- if (arg->ui & SWITCHTAG_TOGGLETAG) {
- toggletag(&new_arg);
- }
- if (arg->ui & SWITCHTAG_TAG) {
- tag(&new_arg);
- }
- if (arg->ui & SWITCHTAG_VIEW) {
- view (&new_arg);
- }
- if (arg->ui & SWITCHTAG_TOGGLEVIEW) {
- toggleview (&new_arg);
- }
-}
-
-void
-sigchld(int unused)
-{
- if (signal(SIGCHLD, sigchld) == SIG_ERR)
- die("can't install SIGCHLD handler:");
- while (0 < waitpid(-1, NULL, WNOHANG));
-}
void
spawn(const Arg *arg)
{
- if (arg->v == dmenu_cmd)
+ struct sigaction sa;
+
+ if (arg->v == dmenucmd)
dmenumon[0] = '0' + selmon->num;
if (fork() == 0) {
if (dpy)
close(ConnectionNumber(dpy));
setsid();
+
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = SIG_DFL;
+ sigaction(SIGCHLD, &sa, NULL);
+
execvp(((char **)arg->v)[0], (char **)arg->v);
- fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]);
- perror(" failed");
- exit(EXIT_SUCCESS);
+ die("dwm: execvp '%s' failed:", ((char **)arg->v)[0]);
}
}
void
-stairs(Monitor *m)
+switchtag(const Arg *arg)
{
- unsigned int i, n, h, mw, my;
- unsigned int ox, oy, ow, oh; /* stair offset values */
- Client *c;
-
- for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
- if (n == 0)
- return;
+ unsigned int columns;
+ unsigned int new_tagset = 0;
+ unsigned int pos, i;
+ int col, row;
+ Arg new_arg;
- if (n > m->nmaster)
- mw = m->nmaster ? m->ww * m->mfact : 0;
- else
- mw = m->ww - m->gappx;
+ columns = LENGTH(tags) / tagrows + ((LENGTH(tags) % tagrows > 0) ? 1 : 0);
- for (i = 0, my = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
- if (i < m->nmaster) {
- h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx;
- resize(c, m->wx + m->gappx, m->wy + my, mw - (2 * c->bw) - m->gappx, h - (2 * c->bw), 0);
- if (my + HEIGHT(c) + m->gappx < m->wh)
- my += HEIGHT(c) + m->gappx;
- } else {
- oy = i - m->nmaster;
- ox = stairdirection ? n - i - 1 : (stairsamesize ? i - m->nmaster : 0);
- ow = stairsamesize ? n - m->nmaster - 1 : n - i - 1;
- oh = stairsamesize ? ow : i - m->nmaster;
- resize(c,
- m->wx + mw + (ox * stairpx) + m->gappx,
- m->wy + (oy * stairpx) + m->gappx,
- m->ww - mw - (2 * c->bw) - (ow * stairpx) - (2 * m->gappx),
- m->wh - (2 * c->bw) - (oh * stairpx) - (2 * m->gappx),
- 0);
+ for (i = 0; i < LENGTH(tags); ++i) {
+ if (!(selmon->tagset[selmon->seltags] & 1 << i)) {
+ continue;
+ }
+ pos = i;
+ row = pos / columns;
+ col = pos % columns;
+ if (arg->ui & SWITCHTAG_UP) { /* UP */
+ row --;
+ if (row < 0) {
+ row = tagrows - 1;
+ }
+ do {
+ pos = row * columns + col;
+ row --;
+ } while (pos >= LENGTH(tags));
}
+ if (arg->ui & SWITCHTAG_DOWN) { /* DOWN */
+ row ++;
+ if (row >= tagrows) {
+ row = 0;
+ }
+ pos = row * columns + col;
+ if (pos >= LENGTH(tags)) {
+ row = 0;
+ }
+ pos = row * columns + col;
+ }
+ if (arg->ui & SWITCHTAG_LEFT) { /* LEFT */
+ col --;
+ if (col < 0) {
+ col = columns - 1;
+ }
+ do {
+ pos = row * columns + col;
+ col --;
+ } while (pos >= LENGTH(tags));
+ }
+ if (arg->ui & SWITCHTAG_RIGHT) { /* RIGHT */
+ col ++;
+ if (col >= columns) {
+ col = 0;
+ }
+ pos = row * columns + col;
+ if (pos >= LENGTH(tags)) {
+ col = 0;
+ pos = row * columns + col;
+ }
+ }
+ new_tagset |= 1 << pos;
+ }
+ new_arg.ui = new_tagset;
+ if (arg->ui & SWITCHTAG_TOGGLETAG) {
+ toggletag(&new_arg);
+ }
+ if (arg->ui & SWITCHTAG_TAG) {
+ tag(&new_arg);
+ }
+ if (arg->ui & SWITCHTAG_VIEW) {
+ view (&new_arg);
+ }
+ if (arg->ui & SWITCHTAG_TOGGLEVIEW) {
+ toggleview (&new_arg);
}
}
@@ -2188,7 +2535,7 @@ tile(Monitor *m)
else
mw = m->ww - m->gappx;
for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
- if (i < m->nmaster) {
+ if (i < m->nmaster) {
h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx;
resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0);
if (my + HEIGHT(c) + m->gappx < m->wh)
@@ -2240,14 +2587,37 @@ togglefloating(const Arg *arg)
selmon->sel->sfw = selmon->sel->w;
selmon->sel->sfh = selmon->sel->h;
}
+ if (selmon->sel->isforegrounded) {
+ selmon->sel->isforegrounded = 0;
+ detachforegrounded(selmon->sel);
+ arrangeforegrounded(selmon);
+ }
+ arrange(selmon);
+}
+
+void
+toggleforegrounded(const Arg *arg)
+{
+ if (!selmon->sel)
+ return;
+ if (selmon->sel->isfullscreen) /* no support for fullscreen windows */
+ return;
+
+ selmon->sel->isforegrounded || selmon->sel->isfloating ?
+ detachforegrounded(selmon->sel) : attachforegrounded(selmon->sel);
+
+ selmon->sel->isforegrounded = selmon->sel->isfloating =
+ !selmon->sel->isfloating && !selmon->sel->isforegrounded;
+
+ arrangeforegrounded(selmon);
arrange(selmon);
}
void
togglefullscr(const Arg *arg)
{
- if(selmon->sel)
- setfullscreen(selmon->sel, !selmon->sel->isfullscreen);
+ if(selmon->sel)
+ setfullscreen(selmon->sel, !selmon->sel->isfullscreen);
}
void
@@ -2320,12 +2690,33 @@ 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 (c->isforegrounded){
+ detachforegrounded(c);
+ arrangeforegrounded(m);
+ }
+
if (!destroyed) {
wc.border_width = c->oldbw;
XGrabServer(dpy); /* avoid race conditions */
XSetErrorHandler(xerrordummy);
+ XSelectInput(dpy, c->win, NoEventMask);
XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
setclientstate(c, WithdrawnState);
@@ -2334,12 +2725,11 @@ unmanage(Client *c, int destroyed)
XUngrabServer(dpy);
}
free(c);
- focus(NULL);
- updateclientlist();
- arrange(m);
- if (c->switchtotag) {
- Arg a = { .ui = c->switchtotag };
- view(&a);
+
+ if (!s) {
+ arrange(m);
+ focus(NULL);
+ updateclientlist();
}
}
@@ -2405,7 +2795,7 @@ updatebarpos(Monitor *m)
}
void
-updateclientlist()
+updateclientlist(void)
{
Client *c;
Monitor *m;
@@ -2439,43 +2829,43 @@ updategeom(void)
memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo));
XFree(info);
nn = j;
- if (n <= nn) { /* new monitors available */
- for (i = 0; i < (nn - n); i++) {
- for (m = mons; m && m->next; m = m->next);
- if (m)
- m->next = createmon();
- else
- mons = createmon();
+
+ /* new monitors if nn > n */
+ for (i = n; i < nn; i++) {
+ for (m = mons; m && m->next; m = m->next);
+ if (m)
+ m->next = createmon();
+ else
+ mons = createmon();
+ }
+ for (i = 0, m = mons; i < nn && m; m = m->next, i++)
+ if (i >= n
+ || unique[i].x_org != m->mx || unique[i].y_org != m->my
+ || unique[i].width != m->mw || unique[i].height != m->mh)
+ {
+ dirty = 1;
+ m->num = i;
+ m->mx = m->wx = unique[i].x_org;
+ m->my = m->wy = unique[i].y_org;
+ m->mw = m->ww = unique[i].width;
+ m->mh = m->wh = unique[i].height;
+ updatebarpos(m);
}
- for (i = 0, m = mons; i < nn && m; m = m->next, i++)
- if (i >= n
- || unique[i].x_org != m->mx || unique[i].y_org != m->my
- || unique[i].width != m->mw || unique[i].height != m->mh)
- {
- dirty = 1;
- m->num = i;
- m->mx = m->wx = unique[i].x_org;
- m->my = m->wy = unique[i].y_org;
- m->mw = m->ww = unique[i].width;
- m->mh = m->wh = unique[i].height;
- updatebarpos(m);
- }
- } else { /* less monitors available nn < n */
- for (i = nn; i < n; i++) {
- for (m = mons; m && m->next; m = m->next);
- while ((c = m->clients)) {
- dirty = 1;
- m->clients = c->next;
- detachstack(c);
- c->mon = mons;
- attach(c);
- attachBelow(c);
- attachstack(c);
- }
- if (m == selmon)
- selmon = mons;
- cleanupmon(m);
+ /* removed monitors if n > nn */
+ for (i = nn; i < n; i++) {
+ for (m = mons; m && m->next; m = m->next);
+ while ((c = m->clients)) {
+ dirty = 1;
+ m->clients = c->next;
+ detachstack(c);
+ c->mon = mons;
+ attach(c);
+ attachBelow(c);
+ attachstack(c);
}
+ if (m == selmon)
+ selmon = mons;
+ cleanupmon(m);
}
free(unique);
} else
@@ -2521,7 +2911,7 @@ updatesizehints(Client *c)
if (!XGetWMNormalHints(dpy, c->win, &size, &msize))
/* size is uninitialized, ensure that size.flags aren't used */
- size.flags = 0;
+ size.flags = PSize;
if (size.flags & PBaseSize) {
c->basew = size.base_width;
c->baseh = size.base_height;
@@ -2553,18 +2943,15 @@ updatesizehints(Client *c)
c->maxa = (float)size.max_aspect.x / size.max_aspect.y;
} else
c->maxa = c->mina = 0.0;
- if((size.flags & PSize) && c->isfreesize) {
- c->basew = size.base_width;
- c->baseh = size.base_height;
- c->isfloating = 1;
- }
c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh);
+ c->hintsvalid = 1;
}
void
updatestatus(void)
{
Monitor* m;
+
if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
strcpy(stext, "dwm-"VERSION);
for(m = mons; m; m = m->next)
@@ -2707,10 +3094,8 @@ updatewindowtype(Client *c)
if (state == netatom[NetWMFullscreen])
setfullscreen(c, 1);
- if (wtype == netatom[NetWMWindowTypeDialog]) {
+ if (wtype == netatom[NetWMWindowTypeDialog])
c->isfloating = 1;
- c->isfreesize = 1;
- }
}
void
@@ -2770,6 +3155,137 @@ 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;
+ int s;
+
+#ifdef __linux__
+ FILE *f;
+ char buf[256];
+ snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p);
+
+ if (!(f = fopen(buf, "r")))
+ return 0;
+
+ s = fscanf(f, "%*u %*s %*c %u", &v);
+ (void)s;
+ 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)
{
@@ -2810,6 +3326,29 @@ wintomon(Window w)
return selmon;
}
+/* Selects for the view of the focused window. The list of tags */
+/* to be displayed is matched to the focused window tag list. */
+void
+winview(const Arg* arg){
+ Window win, win_r, win_p, *win_c;
+ unsigned nc;
+ int unused;
+ Client* c;
+ Arg a;
+
+ if (!XGetInputFocus(dpy, &win, &unused))
+ return;
+ while (XQueryTree(dpy, win, &win_r, &win_p, &win_c, &nc)
+ && win_p != win_r)
+ win = win_p;
+
+ if (!(c = wintoclient(win)))
+ return;
+
+ a.ui = c->tags;
+ view(&a);
+}
+
/* There's no way to check accesses to destroyed windows, thus those cases are
* ignored (especially on UnmapNotify's). Other types of errors call Xlibs
* default error handler, which may call exit. */
@@ -2868,8 +3407,7 @@ zoom(const Arg *arg)
Client *c = selmon->sel;
Client *at = NULL, *cold, *cprevious = NULL;
- if (!selmon->lt[selmon->sellt]->arrange
- || (selmon->sel && selmon->sel->isfloating))
+ if (!selmon->lt[selmon->sellt]->arrange || !c || c->isfloating)
return;
if (c == nexttiled(selmon->clients)) {
at = findbefore(prevzoom);
@@ -2911,10 +3449,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();
@@ -2923,168 +3463,3 @@ 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);
- }
- }
-}
-
-void
-centeredmaster(Monitor *m)
-{
- unsigned int i, n, h, mw, mx, my, oty, ety, tw;
- Client *c;
-
- /* count number of clients in the selected monitor */
- for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
- if (n == 0)
- return;
-
- /* initialize areas */
- mw = m->ww;
- mx = 0;
- my = 0;
- tw = mw;
-
- if (n > m->nmaster) {
- /* go mfact box in the center if more than nmaster clients */
- mw = m->nmaster ? m->ww * m->mfact : 0;
- tw = m->ww - mw;
-
- if (n - m->nmaster > 1) {
- /* only one client */
- mx = (m->ww - mw) / 2;
- tw = (m->ww - mw) / 2;
- }
- }
-
- oty = 0;
- ety = 0;
- for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
- if (i < m->nmaster) {
- /* nmaster clients are stacked vertically, in the center
- * of the screen */
- h = (m->wh - my) / (MIN(n, m->nmaster) - i);
- resize(c, m->wx + mx, m->wy + my, mw - (2*c->bw),
- h - (2*c->bw), 0);
- my += HEIGHT(c);
- } else {
- /* stack clients are stacked vertically */
- if ((i - m->nmaster) % 2 ) {
- h = (m->wh - ety) / ( (1 + n - i) / 2);
- resize(c, m->wx, m->wy + ety, tw - (2*c->bw),
- h - (2*c->bw), 0);
- ety += HEIGHT(c);
- } else {
- h = (m->wh - oty) / ((1 + n - i) / 2);
- resize(c, m->wx + mx + mw, m->wy + oty,
- tw - (2*c->bw), h - (2*c->bw), 0);
- oty += HEIGHT(c);
- }
- }
-}
-
-void
-centeredfloatingmaster(Monitor *m)
-{
- unsigned int i, n, w, mh, mw, mx, mxo, my, myo, tx;
- Client *c;
-
- /* count number of clients in the selected monitor */
- for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
- if (n == 0)
- return;
-
- /* initialize nmaster area */
- if (n > m->nmaster) {
- /* go mfact box in the center if more than nmaster clients */
- if (m->ww > m->wh) {
- mw = m->nmaster ? m->ww * m->mfact : 0;
- mh = m->nmaster ? m->wh * 0.9 : 0;
- } else {
- mh = m->nmaster ? m->wh * m->mfact : 0;
- mw = m->nmaster ? m->ww * 0.9 : 0;
- }
- mx = mxo = (m->ww - mw) / 2;
- my = myo = (m->wh - mh) / 2;
- } else {
- /* go fullscreen if all clients are in the master area */
- mh = m->wh;
- mw = m->ww;
- mx = mxo = 0;
- my = myo = 0;
- }
-
- for(i = tx = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
- if (i < m->nmaster) {
- /* nmaster clients are stacked horizontally, in the center
- * of the screen */
- w = (mw + mxo - mx) / (MIN(n, m->nmaster) - i);
- resize(c, m->wx + mx, m->wy + my, w - (2*c->bw),
- mh - (2*c->bw), 0);
- mx += WIDTH(c);
- } else {
- /* stack clients are stacked horizontally */
- w = (m->ww - tx) / (n - i);
- resize(c, m->wx + tx, m->wy, w - (2*c->bw),
- m->wh - (2*c->bw), 0);
- tx += WIDTH(c);
- }
-}
diff --git a/movestack.c b/movestack.c
deleted file mode 100644
index 8d22a6b..0000000
--- a/movestack.c
+++ /dev/null
@@ -1,48 +0,0 @@
-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);
- }
-}
diff --git a/util.c b/util.c
index fe044fc..8e26a51 100644
--- a/util.c
+++ b/util.c
@@ -1,4 +1,5 @@
/* See LICENSE file for copyright and license details. */
+#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -6,30 +7,31 @@
#include "util.h"
-void *
-ecalloc(size_t nmemb, size_t size)
-{
- void *p;
-
- if (!(p = calloc(nmemb, size)))
- die("calloc:");
- return p;
-}
-
void
-die(const char *fmt, ...) {
+die(const char *fmt, ...)
+{
va_list ap;
+ int saved_errno;
+
+ saved_errno = errno;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
- if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
- fputc(' ', stderr);
- perror(NULL);
- } else {
- fputc('\n', stderr);
- }
+ if (fmt[0] && fmt[strlen(fmt)-1] == ':')
+ fprintf(stderr, " %s", strerror(saved_errno));
+ fputc('\n', stderr);
exit(1);
}
+
+void *
+ecalloc(size_t nmemb, size_t size)
+{
+ void *p;
+
+ if (!(p = calloc(nmemb, size)))
+ die("calloc:");
+ return p;
+}
diff --git a/util.h b/util.h
index f633b51..c0a50d4 100644
--- a/util.h
+++ b/util.h
@@ -3,6 +3,7 @@
#define MAX(A, B) ((A) > (B) ? (A) : (B))
#define MIN(A, B) ((A) < (B) ? (A) : (B))
#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B))
+#define LENGTH(X) (sizeof (X) / sizeof (X)[0])
void die(const char *fmt, ...);
void *ecalloc(size_t nmemb, size_t size);