This commit is contained in:
2026-03-16 01:59:49 -04:00
parent a09a4096b0
commit bba5f6794a
468 changed files with 60004 additions and 0 deletions

View File

@@ -0,0 +1,68 @@
From eea13010ffc3983392857ee1e3804e3aa1064d7a Mon Sep 17 00:00:00 2001
From: Soenke Lambert <s.lambert@mittwald.de>
Date: Wed, 13 Oct 2021 18:21:09 +0200
Subject: [PATCH] Fullscreen current window with [Alt]+[Shift]+[f]
This actually fullscreens a window, instead of just hiding the statusbar
and applying the monocle layout.
---
config.def.h | 1 +
dwm.1 | 3 +++
dwm.c | 8 ++++++++
3 files changed, 12 insertions(+)
diff --git a/config.def.h b/config.def.h
index 1c0b587..8cd3204 100644
--- a/config.def.h
+++ b/config.def.h
@@ -78,6 +78,7 @@ static Key keys[] = {
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
{ MODKEY, XK_space, setlayout, {0} },
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
+ { MODKEY|ShiftMask, XK_f, togglefullscr, {0} },
{ MODKEY, XK_0, view, {.ui = ~0 } },
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
{ MODKEY, XK_comma, focusmon, {.i = -1 } },
diff --git a/dwm.1 b/dwm.1
index 13b3729..a368d05 100644
--- a/dwm.1
+++ b/dwm.1
@@ -116,6 +116,9 @@ Zooms/cycles focused window to/from master area (tiled layouts only).
.B Mod1\-Shift\-c
Close focused window.
.TP
+.B Mod1\-Shift\-f
+Toggle fullscreen for focused window.
+.TP
.B Mod1\-Shift\-space
Toggle focused window between tiled and floating state.
.TP
diff --git a/dwm.c b/dwm.c
index 4465af1..c1b899a 100644
--- a/dwm.c
+++ b/dwm.c
@@ -211,6 +211,7 @@ static void tagmon(const Arg *arg);
static void tile(Monitor *);
static void togglebar(const Arg *arg);
static void togglefloating(const Arg *arg);
+static void togglefullscr(const Arg *arg);
static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
static void unfocus(Client *c, int setfocus);
@@ -1719,6 +1720,13 @@ togglefloating(const Arg *arg)
arrange(selmon);
}
+void
+togglefullscr(const Arg *arg)
+{
+ if(selmon->sel)
+ setfullscreen(selmon->sel, !selmon->sel->isfullscreen);
+}
+
void
toggletag(const Arg *arg)
{
--
2.30.2

View File

@@ -0,0 +1,67 @@
diff --git a/config.def.h b/config.def.h
index 1c0b587..d4b11fc 100644
--- a/config.def.h
+++ b/config.def.h
@@ -20,6 +20,7 @@ static const char *colors[][3] = {
/* tagging */
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
+static const char *alttags[] = { "<01>", "<02>", "<03>", "<04>", "<05>" };
static const Rule rules[] = {
/* xprop(1):
diff --git a/dwm.c b/dwm.c
index 4465af1..a394159 100644
--- a/dwm.c
+++ b/dwm.c
@@ -416,7 +416,7 @@ attachstack(Client *c)
void
buttonpress(XEvent *e)
{
- unsigned int i, x, click;
+ unsigned int i, x, click, occ;
Arg arg = {0};
Client *c;
Monitor *m;
@@ -430,9 +430,13 @@ buttonpress(XEvent *e)
focus(NULL);
}
if (ev->window == selmon->barwin) {
- i = x = 0;
+ i = x = occ = 0;
+ /* Bitmask of occupied tags */
+ for (c = m->clients; c; c = c->next)
+ occ |= c->tags;
+
do
- x += TEXTW(tags[i]);
+ x += TEXTW(occ & 1 << i ? alttags[i] : tags[i]);
while (ev->x >= x && ++i < LENGTH(tags));
if (i < LENGTH(tags)) {
click = ClkTagBar;
@@ -699,6 +703,7 @@ drawbar(Monitor *m)
int boxs = drw->fonts->h / 9;
int boxw = drw->fonts->h / 6 + 2;
unsigned int i, occ = 0, urg = 0;
+ const char *tagtext;
Client *c;
/* draw status first so it can be overdrawn by tags later */
@@ -715,13 +720,10 @@ 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]);
- 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,
- m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
- urg & 1 << i);
+ tagtext = occ & 1 << i ? alttags[i] : tags[i];
+ w = TEXTW(tagtext);
+ drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]);
+ drw_text(drw, x, 0, w, bh, lrpad / 2, tagtext, urg & 1 << i);
x += w;
}
w = blw = TEXTW(m->ltsymbol);

View File

@@ -0,0 +1,67 @@
From e7f651b1321747fb92521522f0aa07a01160d4af Mon Sep 17 00:00:00 2001
From: Jasper Shovelton <Beanie.github@proton.me>
Date: Tue, 26 Dec 2023 12:57:35 +0000
Subject: [PATCH] Add a `borderpx` value to `rules` in `config.def.h`.
---
config.def.h | 6 +++---
dwm.c | 5 ++++-
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/config.def.h b/config.def.h
index 9efa774..bdddfa5 100644
--- a/config.def.h
+++ b/config.def.h
@@ -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 isfloating monitor border width */
+ { "Gimp", NULL, NULL, 0, 1, -1, -1 },
+ { "Firefox", NULL, NULL, 1 << 8, 0, -1, 0 },
};
/* layout(s) */
diff --git a/dwm.c b/dwm.c
index f1d86b2..48403c2 100644
--- a/dwm.c
+++ b/dwm.c
@@ -139,6 +139,7 @@ typedef struct {
unsigned int tags;
int isfloating;
int monitor;
+ int bw;
} Rule;
/* function declarations */
@@ -287,6 +288,7 @@ applyrules(Client *c)
/* rule matching */
c->isfloating = 0;
c->tags = 0;
+ c->bw = borderpx;
XGetClassHint(dpy, c->win, &ch);
class = ch.res_class ? ch.res_class : broken;
instance = ch.res_name ? ch.res_name : broken;
@@ -299,6 +301,8 @@ applyrules(Client *c)
{
c->isfloating = r->isfloating;
c->tags |= r->tags;
+ if (r->bw != -1)
+ c->bw = r->bw;
for (m = mons; m && m->num != r->monitor; m = m->next);
if (m)
c->mon = m;
@@ -1059,7 +1063,6 @@ manage(Window w, XWindowAttributes *wa)
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;
XConfigureWindow(dpy, w, CWBorderWidth, &wc);
--
2.43.0

View File

@@ -0,0 +1,121 @@
diff --git a/config.def.h b/config.def.h
index 9efa774..aba210d 100644
--- a/config.def.h
+++ b/config.def.h
@@ -18,6 +18,11 @@ static const char *colors[][3] = {
[SchemeSel] = { col_gray4, col_cyan, col_cyan },
};
+static const char *const autostart[] = {
+ "st", NULL,
+ NULL /* terminate */
+};
+
/* tagging */
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
diff --git a/dwm.c b/dwm.c
index f1d86b2..3ce99fc 100644
--- a/dwm.c
+++ b/dwm.c
@@ -233,6 +233,7 @@ 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 autostart_exec(void);
/* variables */
static const char broken[] = "broken";
@@ -274,6 +275,36 @@ static Window root, wmcheckwin;
/* compile-time check if all tags fit into an unsigned int bit array. */
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
+/* dwm will keep pid's of processes from autostart array and kill them at quit */
+static pid_t *autostart_pids;
+static size_t autostart_len;
+
+/* execute command from autostart array */
+static void
+autostart_exec() {
+ const char *const *p;
+ size_t i = 0;
+
+ /* count entries */
+ for (p = autostart; *p; autostart_len++, p++)
+ while (*++p);
+
+ autostart_pids = malloc(autostart_len * sizeof(pid_t));
+ for (p = autostart; *p; i++, p++) {
+ if ((autostart_pids[i] = fork()) == 0) {
+ setsid();
+ execvp(*p, (char *const *)p);
+ fprintf(stderr, "dwm: execvp %s\n", *p);
+ perror(" failed");
+ _exit(EXIT_FAILURE);
+ }
+ /* skip arguments */
+ while (*++p);
+ }
+}
+
+
+
/* function implementations */
void
applyrules(Client *c)
@@ -1258,6 +1289,16 @@ propertynotify(XEvent *e)
void
quit(const Arg *arg)
{
+ size_t i;
+
+ /* kill child processes */
+ for (i = 0; i < autostart_len; i++) {
+ if (0 < autostart_pids[i]) {
+ kill(autostart_pids[i], SIGTERM);
+ waitpid(autostart_pids[i], NULL, 0);
+ }
+ }
+
running = 0;
}
@@ -1543,6 +1584,7 @@ setup(void)
XSetWindowAttributes wa;
Atom utf8string;
struct sigaction sa;
+ pid_t pid;
/* do not transform children into zombies when they terminate */
sigemptyset(&sa.sa_mask);
@@ -1551,7 +1593,21 @@ setup(void)
sigaction(SIGCHLD, &sa, NULL);
/* clean up any zombies (inherited from .xinitrc etc) immediately */
- while (waitpid(-1, NULL, WNOHANG) > 0);
+ while (0 < (pid = waitpid(-1, NULL, WNOHANG))) {
+ pid_t *p, *lim;
+
+ if (!(p = autostart_pids))
+ continue;
+ lim = &p[autostart_len];
+
+ for (; p < lim; p++) {
+ if (*p == pid) {
+ *p = -1;
+ break;
+ }
+ }
+
+ }
/* init screen */
screen = DefaultScreen(dpy);
@@ -2152,6 +2208,7 @@ main(int argc, char *argv[])
if (!(dpy = XOpenDisplay(NULL)))
die("dwm: cannot open display");
checkotherwm();
+ autostart_exec();
setup();
#ifdef __OpenBSD__
if (pledge("stdio rpath proc exec", NULL) == -1)

View File

@@ -0,0 +1,27 @@
From 1529909466206016f2101457bbf37c67195714c8 Mon Sep 17 00:00:00 2001
From: Jakub Leszczak <szatan@gecc.xyz>
Date: Fri, 22 Nov 2019 10:46:53 +0800
Subject: [PATCH] Fix transparent borders
When terminal has transparency then its borders also become transparent.
Fix it by removing transparency from any pixels drawn.
---
drw.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drw.c b/drw.c
index 8fd1ca4..490a592 100644
--- a/drw.c
+++ b/drw.c
@@ -202,6 +202,8 @@ 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;
}
/* Wrapper to create color schemes. The caller has to call free(3) on the
--
2.26.2

View File

@@ -0,0 +1,148 @@
diff --git a/config.def.h b/config.def.h
index 1c0b587..b172f63 100644
--- 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 Gap default_gap = {.isgap = 1, .realgap = 10, .gappx = 10};
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 */
@@ -84,6 +85,10 @@ static Key keys[] = {
{ MODKEY, XK_period, focusmon, {.i = +1 } },
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
+ { MODKEY, XK_minus, setgaps, {.i = -5 } },
+ { MODKEY, XK_equal, setgaps, {.i = +5 } },
+ { MODKEY|ShiftMask, XK_minus, setgaps, {.i = GAP_RESET } },
+ { MODKEY|ShiftMask, XK_equal, setgaps, {.i = GAP_TOGGLE} },
TAGKEYS( XK_1, 0)
TAGKEYS( XK_2, 1)
TAGKEYS( XK_3, 2)
diff --git a/dwm.c b/dwm.c
index 664c527..25bc9b7 100644
--- a/dwm.c
+++ b/dwm.c
@@ -57,6 +57,9 @@
#define TAGMASK ((1 << LENGTH(tags)) - 1)
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
+#define GAP_TOGGLE 100
+#define GAP_RESET 0
+
/* enums */
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
enum { SchemeNorm, SchemeSel }; /* color schemes */
@@ -111,6 +114,12 @@ typedef struct {
void (*arrange)(Monitor *);
} Layout;
+typedef struct {
+ int isgap;
+ int realgap;
+ int gappx;
+} Gap;
+
struct Monitor {
char ltsymbol[16];
float mfact;
@@ -119,6 +128,7 @@ struct Monitor {
int by; /* bar geometry */
int mx, my, mw, mh; /* screen size */
int wx, wy, ww, wh; /* window area */
+ Gap *gap;
unsigned int seltags;
unsigned int sellt;
unsigned int tagset[2];
@@ -169,6 +179,7 @@ static void focus(Client *c);
static void focusin(XEvent *e);
static void focusmon(const Arg *arg);
static void focusstack(const Arg *arg);
+static void gap_copy(Gap *to, const Gap *from);
static Atom getatomprop(Client *c, Atom prop);
static int getrootptr(int *x, int *y);
static long getstate(Window w);
@@ -200,6 +211,7 @@ static void sendmon(Client *c, Monitor *m);
static void setclientstate(Client *c, long state);
static void setfocus(Client *c);
static void setfullscreen(Client *c, int fullscreen);
+static void setgaps(const Arg *arg);
static void setlayout(const Arg *arg);
static void setmfact(const Arg *arg);
static void setup(void);
@@ -639,6 +651,8 @@ createmon(void)
m->nmaster = nmaster;
m->showbar = showbar;
m->topbar = topbar;
+ m->gap = malloc(sizeof(Gap));
+ gap_copy(m->gap, &default_gap);
m->lt[0] = &layouts[0];
m->lt[1] = &layouts[1 % LENGTH(layouts)];
strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
@@ -1498,6 +1512,35 @@ setfullscreen(Client *c, int fullscreen)
}
}
+void
+gap_copy(Gap *to, const Gap *from)
+{
+ to->isgap = from->isgap;
+ to->realgap = from->realgap;
+ to->gappx = from->gappx;
+}
+
+void
+setgaps(const Arg *arg)
+{
+ Gap *p = selmon->gap;
+ switch(arg->i)
+ {
+ case GAP_TOGGLE:
+ p->isgap = 1 - p->isgap;
+ break;
+ case GAP_RESET:
+ gap_copy(p, &default_gap);
+ break;
+ default:
+ p->realgap += arg->i;
+ p->isgap = 1;
+ }
+ p->realgap = MAX(p->realgap, 0);
+ p->gappx = p->realgap * p->isgap;
+ arrange(selmon);
+}
+
void
setlayout(const Arg *arg)
{
@@ -1684,18 +1727,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->gap->gappx;
+ for (i = 0, my = ty = m->gap->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
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);
+ h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gap->gappx;
+ resize(c, m->wx + m->gap->gappx, m->wy + my, mw - (2*c->bw) - m->gap->gappx, h - (2*c->bw), 0);
+ if (my + HEIGHT(c) + m->gap->gappx < m->wh)
+ my += HEIGHT(c) + m->gap->gappx;
} else {
- h = (m->wh - ty) / (n - i);
- resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0);
- if (ty + HEIGHT(c) < m->wh)
- ty += HEIGHT(c);
+ h = (m->wh - ty) / (n - i) - m->gap->gappx;
+ resize(c, m->wx + mw + m->gap->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gap->gappx, h - (2*c->bw), 0);
+ if (ty + HEIGHT(c) + m->gap->gappx < m->wh)
+ ty += HEIGHT(c) + m->gap->gappx;
}
}

View File

@@ -0,0 +1,70 @@
From 064e1d48631cd9b03f32b42d7be79677197ee42f Mon Sep 17 00:00:00 2001
From: Marshall Mason <marshallmason3@gmail.com>
Date: Mon, 9 Nov 2015 12:38:28 -0800
Subject: [PATCH] Added horizgrid function
---
config.def.h | 2 ++
horizgrid.c | 32 ++++++++++++++++++++++++++++++++
2 files changed, 34 insertions(+)
create mode 100644 horizgrid.c
diff --git a/config.def.h b/config.def.h
index eaae8f3..c2ad519 100644
--- a/config.def.h
+++ b/config.def.h
@@ -36,11 +36,13 @@ static const float mfact = 0.55; /* factor of master area size [0.05..0.95]
static const int nmaster = 1; /* number of clients in master area */
static const Bool resizehints = True; /* True means respect size hints in tiled resizals */
+#include "horizgrid.c"
static const Layout layouts[] = {
/* symbol arrange function */
{ "[]=", tile }, /* first entry is default */
{ "><>", NULL }, /* no layout function means floating behavior */
{ "[M]", monocle },
+ { "###", horizgrid },
};
/* key definitions */
diff --git a/horizgrid.c b/horizgrid.c
new file mode 100644
index 0000000..51ce0f8
--- /dev/null
+++ b/horizgrid.c
@@ -0,0 +1,32 @@
+void
+horizgrid(Monitor *m) {
+ Client *c;
+ unsigned int n, i;
+ int w = 0;
+ int ntop, nbottom = 0;
+
+ /* Count windows */
+ for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
+
+ if(n == 0)
+ return;
+ else if(n == 1) { /* Just fill the whole screen */
+ c = nexttiled(m->clients);
+ resize(c, m->wx, m->wy, m->ww - (2*c->bw), m->wh - (2*c->bw), False);
+ } else if(n == 2) { /* Split vertically */
+ w = m->ww / 2;
+ c = nexttiled(m->clients);
+ resize(c, m->wx, m->wy, w - (2*c->bw), m->wh - (2*c->bw), False);
+ c = nexttiled(c->next);
+ resize(c, m->wx + w, m->wy, w - (2*c->bw), m->wh - (2*c->bw), False);
+ } else {
+ ntop = n / 2;
+ nbottom = n - ntop;
+ for(i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
+ if(i < ntop)
+ resize(c, m->wx + i * m->ww / ntop, m->wy, m->ww / ntop - (2*c->bw), m->wh / 2 - (2*c->bw), False);
+ else
+ resize(c, m->wx + (i - ntop) * m->ww / nbottom, m->wy + m->wh / 2, m->ww / nbottom - (2*c->bw), m->wh / 2 - (2*c->bw), False);
+ }
+ }
+}
--
2.1.4

View File

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

View File

@@ -0,0 +1,371 @@
diff --git a/config.def.h b/config.def.h
index a2ac963..322d181 100644
--- a/config.def.h
+++ b/config.def.h
@@ -5,6 +5,8 @@ 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 */
+#define ICONSIZE 16 /* icon size */
+#define ICONSPACING 5 /* space between icon and title */
static const char *fonts[] = { "monospace:size=10" };
static const char dmenufont[] = "monospace:size=10";
static const char col_gray1[] = "#222222";
diff --git a/config.mk b/config.mk
index b6eb7e0..f3c01b0 100644
--- a/config.mk
+++ b/config.mk
@@ -22,7 +22,7 @@ FREETYPEINC = /usr/include/freetype2
# includes and libs
INCS = -I${X11INC} -I${FREETYPEINC}
-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
+LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lXrender -lImlib2
# flags
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
diff --git a/drw.c b/drw.c
index 4cdbcbe..9b474c5 100644
--- a/drw.c
+++ b/drw.c
@@ -4,6 +4,7 @@
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xft/Xft.h>
+#include <Imlib2.h>
#include "drw.h"
#include "util.h"
@@ -71,6 +72,7 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h
drw->w = w;
drw->h = h;
drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen));
+ drw->picture = XRenderCreatePicture(dpy, drw->drawable, XRenderFindVisualFormat(dpy, DefaultVisual(dpy, screen)), 0, NULL);
drw->gc = XCreateGC(dpy, root, 0, NULL);
XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
@@ -85,14 +87,18 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h)
drw->w = w;
drw->h = h;
+ if (drw->picture)
+ XRenderFreePicture(drw->dpy, drw->picture);
if (drw->drawable)
XFreePixmap(drw->dpy, drw->drawable);
drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen));
+ drw->picture = XRenderCreatePicture(drw->dpy, drw->drawable, XRenderFindVisualFormat(drw->dpy, DefaultVisual(drw->dpy, drw->screen)), 0, NULL);
}
void
drw_free(Drw *drw)
{
+ XRenderFreePicture(drw->dpy, drw->picture);
XFreePixmap(drw->dpy, drw->drawable);
XFreeGC(drw->dpy, drw->gc);
drw_fontset_free(drw->fonts);
@@ -236,6 +242,67 @@ drw_setscheme(Drw *drw, Clr *scm)
drw->scheme = scm;
}
+Picture
+drw_picture_create_resized(Drw *drw, char *src, unsigned int srcw, unsigned int srch, unsigned int dstw, unsigned int dsth) {
+ Pixmap pm;
+ Picture pic;
+ GC gc;
+
+ if (srcw <= (dstw << 1u) && srch <= (dsth << 1u)) {
+ XImage img = {
+ srcw, srch, 0, ZPixmap, src,
+ ImageByteOrder(drw->dpy), BitmapUnit(drw->dpy), BitmapBitOrder(drw->dpy), 32,
+ 32, 0, 32,
+ 0, 0, 0
+ };
+ XInitImage(&img);
+
+ pm = XCreatePixmap(drw->dpy, drw->root, srcw, srch, 32);
+ gc = XCreateGC(drw->dpy, pm, 0, NULL);
+ XPutImage(drw->dpy, pm, gc, &img, 0, 0, 0, 0, srcw, srch);
+ XFreeGC(drw->dpy, gc);
+
+ pic = XRenderCreatePicture(drw->dpy, pm, XRenderFindStandardFormat(drw->dpy, PictStandardARGB32), 0, NULL);
+ XFreePixmap(drw->dpy, pm);
+
+ XRenderSetPictureFilter(drw->dpy, pic, FilterBilinear, NULL, 0);
+ XTransform xf;
+ xf.matrix[0][0] = (srcw << 16u) / dstw; xf.matrix[0][1] = 0; xf.matrix[0][2] = 0;
+ xf.matrix[1][0] = 0; xf.matrix[1][1] = (srch << 16u) / dsth; xf.matrix[1][2] = 0;
+ xf.matrix[2][0] = 0; xf.matrix[2][1] = 0; xf.matrix[2][2] = 65536;
+ XRenderSetPictureTransform(drw->dpy, pic, &xf);
+ } else {
+ Imlib_Image origin = imlib_create_image_using_data(srcw, srch, (DATA32 *)src);
+ if (!origin) return None;
+ imlib_context_set_image(origin);
+ imlib_image_set_has_alpha(1);
+ Imlib_Image scaled = imlib_create_cropped_scaled_image(0, 0, srcw, srch, dstw, dsth);
+ imlib_free_image_and_decache();
+ if (!scaled) return None;
+ imlib_context_set_image(scaled);
+ imlib_image_set_has_alpha(1);
+
+ XImage img = {
+ dstw, dsth, 0, ZPixmap, (char *)imlib_image_get_data_for_reading_only(),
+ ImageByteOrder(drw->dpy), BitmapUnit(drw->dpy), BitmapBitOrder(drw->dpy), 32,
+ 32, 0, 32,
+ 0, 0, 0
+ };
+ XInitImage(&img);
+
+ pm = XCreatePixmap(drw->dpy, drw->root, dstw, dsth, 32);
+ gc = XCreateGC(drw->dpy, pm, 0, NULL);
+ XPutImage(drw->dpy, pm, gc, &img, 0, 0, 0, 0, dstw, dsth);
+ imlib_free_image_and_decache();
+ XFreeGC(drw->dpy, gc);
+
+ pic = XRenderCreatePicture(drw->dpy, pm, XRenderFindStandardFormat(drw->dpy, PictStandardARGB32), 0, NULL);
+ XFreePixmap(drw->dpy, pm);
+ }
+
+ return pic;
+}
+
void
drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert)
{
@@ -379,6 +446,14 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
return x + (render ? w : 0);
}
+void
+drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic)
+{
+ if (!drw)
+ return;
+ XRenderComposite(drw->dpy, PictOpOver, pic, None, drw->picture, 0, 0, 0, 0, x, y, w, h);
+}
+
void
drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
{
diff --git a/drw.h b/drw.h
index 4bcd5ad..71aefa2 100644
--- a/drw.h
+++ b/drw.h
@@ -21,6 +21,7 @@ typedef struct {
int screen;
Window root;
Drawable drawable;
+ Picture picture;
GC gc;
Clr *scheme;
Fnt *fonts;
@@ -49,9 +50,12 @@ void drw_cur_free(Drw *drw, Cur *cursor);
void drw_setfontset(Drw *drw, Fnt *set);
void drw_setscheme(Drw *drw, Clr *scm);
+Picture drw_picture_create_resized(Drw *drw, char *src, unsigned int src_w, unsigned int src_h, unsigned int dst_w, unsigned int dst_h);
+
/* Drawing functions */
void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert);
int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert);
+void drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic);
/* Map functions */
void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);
diff --git a/dwm.c b/dwm.c
index a96f33c..033ccec 100644
--- a/dwm.c
+++ b/dwm.c
@@ -28,6 +28,8 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <limits.h>
+#include <stdint.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <X11/cursorfont.h>
@@ -60,7 +62,7 @@
/* enums */
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
enum { SchemeNorm, SchemeSel }; /* color schemes */
-enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
+enum { NetSupported, NetWMName, NetWMIcon, NetWMState, NetWMCheck,
NetWMFullscreen, NetActiveWindow, NetWMWindowType,
NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
@@ -93,6 +95,7 @@ struct Client {
int bw, oldbw;
unsigned int tags;
int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
+ unsigned int icw, ich; Picture icon;
Client *next;
Client *snext;
Monitor *mon;
@@ -170,6 +173,7 @@ static void focusin(XEvent *e);
static void focusmon(const Arg *arg);
static void focusstack(const Arg *arg);
static Atom getatomprop(Client *c, Atom prop);
+static Picture geticonprop(Window w, unsigned int *icw, unsigned int *ich);
static int getrootptr(int *x, int *y);
static long getstate(Window w);
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
@@ -214,6 +218,7 @@ static void togglebar(const Arg *arg);
static void togglefloating(const Arg *arg);
static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
+static void freeicon(Client *c);
static void unfocus(Client *c, int setfocus);
static void unmanage(Client *c, int destroyed);
static void unmapnotify(XEvent *e);
@@ -225,6 +230,7 @@ static void updatenumlockmask(void);
static void updatesizehints(Client *c);
static void updatestatus(void);
static void updatetitle(Client *c);
+static void updateicon(Client *c);
static void updatewindowtype(Client *c);
static void updatewmhints(Client *c);
static void view(const Arg *arg);
@@ -735,7 +741,8 @@ drawbar(Monitor *m)
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);
+ drw_text(drw, x, 0, w, bh, lrpad / 2 + (m->sel->icon ? m->sel->icw + ICONSPACING : 0), m->sel->name, 0);
+ if (m->sel->icon) drw_pic(drw, x + lrpad / 2, (bh - m->sel->ich) / 2, m->sel->icw, m->sel->ich, m->sel->icon);
if (m->sel->isfloating)
drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0);
} else {
@@ -875,6 +882,67 @@ getatomprop(Client *c, Atom prop)
return atom;
}
+static uint32_t prealpha(uint32_t p) {
+ uint8_t a = p >> 24u;
+ uint32_t rb = (a * (p & 0xFF00FFu)) >> 8u;
+ uint32_t g = (a * (p & 0x00FF00u)) >> 8u;
+ return (rb & 0xFF00FFu) | (g & 0x00FF00u) | (a << 24u);
+}
+
+Picture
+geticonprop(Window win, unsigned int *picw, unsigned int *pich)
+{
+ int format;
+ unsigned long n, extra, *p = NULL;
+ Atom real;
+
+ if (XGetWindowProperty(dpy, win, netatom[NetWMIcon], 0L, LONG_MAX, False, AnyPropertyType,
+ &real, &format, &n, &extra, (unsigned char **)&p) != Success)
+ return None;
+ if (n == 0 || format != 32) { XFree(p); return None; }
+
+ unsigned long *bstp = NULL;
+ uint32_t w, h, sz;
+ {
+ unsigned long *i; const unsigned long *end = p + n;
+ uint32_t bstd = UINT32_MAX, d, m;
+ for (i = p; i < end - 1; i += sz) {
+ if ((w = *i++) >= 16384 || (h = *i++) >= 16384) { XFree(p); return None; }
+ if ((sz = w * h) > end - i) break;
+ if ((m = w > h ? w : h) >= ICONSIZE && (d = m - ICONSIZE) < bstd) { bstd = d; bstp = i; }
+ }
+ if (!bstp) {
+ for (i = p; i < end - 1; i += sz) {
+ if ((w = *i++) >= 16384 || (h = *i++) >= 16384) { XFree(p); return None; }
+ if ((sz = w * h) > end - i) break;
+ if ((d = ICONSIZE - (w > h ? w : h)) < bstd) { bstd = d; bstp = i; }
+ }
+ }
+ if (!bstp) { XFree(p); return None; }
+ }
+
+ if ((w = *(bstp - 2)) == 0 || (h = *(bstp - 1)) == 0) { XFree(p); return None; }
+
+ uint32_t icw, ich;
+ if (w <= h) {
+ ich = ICONSIZE; icw = w * ICONSIZE / h;
+ if (icw == 0) icw = 1;
+ }
+ else {
+ icw = ICONSIZE; ich = h * ICONSIZE / w;
+ if (ich == 0) ich = 1;
+ }
+ *picw = icw; *pich = ich;
+
+ uint32_t i, *bstp32 = (uint32_t *)bstp;
+ for (sz = w * h, i = 0; i < sz; ++i) bstp32[i] = prealpha(bstp[i]);
+
+ Picture ret = drw_picture_create_resized(drw, (char *)bstp, w, h, icw, ich);
+ XFree(p);
+
+ return ret;
+}
+
int
getrootptr(int *x, int *y)
{
@@ -1034,6 +1102,7 @@ manage(Window w, XWindowAttributes *wa)
c->h = c->oldh = wa->height;
c->oldbw = wa->border_width;
+ updateicon(c);
updatetitle(c);
if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
c->mon = t->mon;
@@ -1244,6 +1313,11 @@ propertynotify(XEvent *e)
if (c == c->mon->sel)
drawbar(c->mon);
}
+ else if (ev->atom == netatom[NetWMIcon]) {
+ updateicon(c);
+ if (c == c->mon->sel)
+ drawbar(c->mon);
+ }
if (ev->atom == netatom[NetWMWindowType])
updatewindowtype(c);
}
@@ -1560,6 +1634,7 @@ setup(void)
netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
+ netatom[NetWMIcon] = XInternAtom(dpy, "_NET_WM_ICON", False);
netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
@@ -1752,6 +1827,15 @@ toggleview(const Arg *arg)
}
}
+void
+freeicon(Client *c)
+{
+ if (c->icon) {
+ XRenderFreePicture(dpy, c->icon);
+ c->icon = None;
+ }
+}
+
void
unfocus(Client *c, int setfocus)
{
@@ -1773,6 +1857,7 @@ unmanage(Client *c, int destroyed)
detach(c);
detachstack(c);
+ freeicon(c);
if (!destroyed) {
wc.border_width = c->oldbw;
XGrabServer(dpy); /* avoid race conditions */
@@ -2007,6 +2092,13 @@ updatetitle(Client *c)
strcpy(c->name, broken);
}
+void
+updateicon(Client *c)
+{
+ freeicon(c);
+ c->icon = geticonprop(c->win, &c->icw, &c->ich);
+}
+
void
updatewindowtype(Client *c)
{