cycle layouts

This commit is contained in:
2026-06-17 14:36:39 +02:00
parent 506f882d77
commit bed776f6da
9 changed files with 393 additions and 15 deletions

View File

@@ -0,0 +1,95 @@
From d54f931d007a32ddc1fd9d8084258d92378597a5 Mon Sep 17 00:00:00 2001
From: Bakkeby <bakkeby@gmail.com>
Date: Wed, 26 Jun 2024 09:45:28 +0200
Subject: [PATCH] cyclelayout, function to cycle through available layouts.
MOD-CTRL-, and MOD-CTRL-.
cycle backwards and forwards through available layouts.
Probably only useful if you have a lot of additional layouts.
The NULL, NULL layout should always be the last layout in your list,
in order to guarantee consistent behavior.
Refer to https://dwm.suckless.org/patches/cyclelayouts/
---
config.def.h | 3 +++
dwm.1 | 6 ++++++
dwm.c | 18 ++++++++++++++++++
3 files changed, 27 insertions(+)
diff --git a/config.def.h b/config.def.h
index a2ac963..938fd60 100644
--- a/config.def.h
+++ b/config.def.h
@@ -42,6 +42,7 @@ static const Layout layouts[] = {
{ "[]=", tile }, /* first entry is default */
{ "><>", NULL }, /* no layout function means floating behavior */
{ "[M]", monocle },
+ { NULL, NULL },
};
/* key definitions */
@@ -85,6 +86,8 @@ static Key keys[] = {
{ MODKEY, XK_period, focusmon, {.i = +1 } },
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
+ { MODKEY|ControlMask, XK_comma, cyclelayout, {.i = -1 } },
+ { MODKEY|ControlMask, XK_period, cyclelayout, {.i = +1 } },
TAGKEYS( XK_1, 0)
TAGKEYS( XK_2, 1)
TAGKEYS( XK_3, 2)
diff --git a/dwm.1 b/dwm.1
index ddc8321..829047b 100644
--- a/dwm.1
+++ b/dwm.1
@@ -92,6 +92,12 @@ Sets monocle layout.
.B Mod1\-space
Toggles between current and previous layout.
.TP
+.B Mod1\-Control\-,
+Cycles backwards in layout list.
+.TP
+.B Mod1\-Control\-.
+Cycles forwards in layout list.
+.TP
.B Mod1\-j
Focus next window.
.TP
diff --git a/dwm.c b/dwm.c
index a96f33c..2d98c2b 100644
--- a/dwm.c
+++ b/dwm.c
@@ -157,6 +157,7 @@ static void configure(Client *c);
static void configurenotify(XEvent *e);
static void configurerequest(XEvent *e);
static Monitor *createmon(void);
+static void cyclelayout(const Arg *arg);
static void destroynotify(XEvent *e);
static void detach(Client *c);
static void detachstack(Client *c);
@@ -645,6 +646,23 @@ createmon(void)
return m;
}
+void
+cyclelayout(const Arg *arg) {
+ Layout *l;
+ for(l = (Layout *)layouts; l != selmon->lt[selmon->sellt]; l++);
+ if(arg->i > 0) {
+ if(l->symbol && (l + 1)->symbol)
+ setlayout(&((Arg) { .v = (l + 1) }));
+ else
+ setlayout(&((Arg) { .v = layouts }));
+ } else {
+ if(l != layouts && (l - 1)->symbol)
+ setlayout(&((Arg) { .v = (l - 1) }));
+ else
+ setlayout(&((Arg) { .v = &layouts[LENGTH(layouts) - 2] }));
+ }
+}
+
void
destroynotify(XEvent *e)
{
--
2.45.2

View File

@@ -0,0 +1,200 @@
From 6d049ac4a34cb2f3a9e774cf7e13886a9da349a8 Mon Sep 17 00:00:00 2001
From: Bakkeby <bakkeby@gmail.com>
Date: Wed, 26 Jun 2024 10:01:41 +0200
Subject: [PATCH] Adding focusborder patch
---
config.def.h | 1 +
dwm.c | 57 +++++++++++++++++++++++++++++++++++++++++++---------
2 files changed, 48 insertions(+), 10 deletions(-)
diff --git a/config.def.h b/config.def.h
index a2ac963..17d326b 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 unsigned int fh = 5; /* focus window 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 a96f33c..5f93b7e 100644
--- a/dwm.c
+++ b/dwm.c
@@ -267,7 +267,7 @@ static Clr **scheme;
static Display *dpy;
static Drw *drw;
static Monitor *mons, *selmon;
-static Window root, wmcheckwin;
+static Window root, wmcheckwin, focuswin;
/* configuration, allows nested code to access above variables */
#include "config.h"
@@ -487,6 +487,7 @@ cleanup(void)
drw_cur_free(drw, cursor[i]);
for (i = 0; i < LENGTH(colors); i++)
free(scheme[i]);
+ XDestroyWindow(dpy, focuswin);
XDestroyWindow(dpy, wmcheckwin);
drw_free(drw);
XSync(dpy, False);
@@ -787,6 +788,8 @@ expose(XEvent *e)
void
focus(Client *c)
{
+ XWindowChanges wc;
+
if (!c || !ISVISIBLE(c))
for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
if (selmon->sel && selmon->sel != c)
@@ -800,10 +803,16 @@ focus(Client *c)
attachstack(c);
grabbuttons(c, 1);
XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel);
+ XMoveResizeWindow(dpy, focuswin, c->x, c->y, c->w + 2 * c->bw, fh);
+ XMoveResizeWindow(dpy, c->win, c->x, c->y + fh, c->w, c->h - fh);
+ wc.stack_mode = Above;
+ wc.sibling = c->win;
+ XConfigureWindow(dpy, focuswin, CWSibling|CWStackMode, &wc);
setfocus(c);
} else {
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
+ XMoveWindow(dpy, focuswin, 0, -fh);
}
selmon->sel = c;
drawbars();
@@ -1150,8 +1159,8 @@ movemouse(const Arg *arg)
if (c->isfullscreen) /* no support moving fullscreen windows by mouse */
return;
restack(selmon);
- ocx = c->x;
- ocy = c->y;
+ nx = ocx = c->x;
+ ny = ocy = c->y;
if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess)
return;
@@ -1183,16 +1192,23 @@ movemouse(const Arg *arg)
if (!c->isfloating && selmon->lt[selmon->sellt]->arrange
&& (abs(nx - c->x) > snap || abs(ny - c->y) > snap))
togglefloating(NULL);
- if (!selmon->lt[selmon->sellt]->arrange || c->isfloating)
- resize(c, nx, ny, c->w, c->h, 1);
+ if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) {
+ XMoveWindow(dpy, focuswin, nx, ny);
+ XMoveWindow(dpy, c->win, nx, ny + fh);
+ }
break;
}
} while (ev.type != ButtonRelease);
+
XUngrabPointer(dpy, CurrentTime);
+ resize(c, nx, ny, c->w, c->h, 1);
+
if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) {
sendmon(c, m);
selmon = m;
focus(NULL);
+ } else {
+ focus(c);
}
}
@@ -1306,7 +1322,9 @@ resizemouse(const Arg *arg)
return;
restack(selmon);
ocx = c->x;
- ocy = c->y;
+ ocy = c->y + fh;
+ nh = c->h;
+ nw = c->w;
if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess)
return;
@@ -1333,18 +1351,25 @@ resizemouse(const Arg *arg)
&& (abs(nw - c->w) > snap || abs(nh - c->h) > snap))
togglefloating(NULL);
}
- if (!selmon->lt[selmon->sellt]->arrange || c->isfloating)
- resize(c, c->x, c->y, nw, nh, 1);
+ if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) {
+ XMoveResizeWindow(dpy, focuswin, c->x, c->y, nw + 2 * c->bw, fh);
+ XMoveResizeWindow(dpy, c->win, c->x, c->y + fh, nw, nh - fh);
+ }
break;
}
} while (ev.type != ButtonRelease);
+
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
XUngrabPointer(dpy, CurrentTime);
+ resize(c, c->x, c->y, nw, nh, 1);
+
while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) {
sendmon(c, m);
selmon = m;
focus(NULL);
+ } else {
+ focus(c);
}
}
@@ -1358,8 +1383,10 @@ restack(Monitor *m)
drawbar(m);
if (!m->sel)
return;
- if (m->sel->isfloating || !m->lt[m->sellt]->arrange)
+ if (m->sel->isfloating || !m->lt[m->sellt]->arrange) {
XRaiseWindow(dpy, m->sel->win);
+ XRaiseWindow(dpy, focuswin);
+ }
if (m->lt[m->sellt]->arrange) {
wc.stack_mode = Below;
wc.sibling = m->barwin;
@@ -1534,7 +1561,7 @@ void
setup(void)
{
int i;
- XSetWindowAttributes wa;
+ XSetWindowAttributes wa, fwa;
Atom utf8string;
/* clean up any zombies immediately */
@@ -1585,6 +1612,14 @@ setup(void)
PropModeReplace, (unsigned char *) "dwm", 3);
XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32,
PropModeReplace, (unsigned char *) &wmcheckwin, 1);
+ /* focus window */
+ fwa.override_redirect = 1;
+ fwa.background_pixel = scheme[SchemeSel][ColBorder].pixel;
+ focuswin = XCreateWindow(dpy, root, -1, -1, 1, 1, 0, DefaultDepth(dpy, screen),
+ InputOutput, DefaultVisual(dpy, screen),
+ CWOverrideRedirect|CWBackPixel, &fwa
+ );
+ XMapWindow(dpy, focuswin);
/* EWMH support per view */
XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
PropModeReplace, (unsigned char *) netatom, NetLast);
@@ -1723,6 +1758,7 @@ togglefloating(const Arg *arg)
resize(selmon->sel, selmon->sel->x, selmon->sel->y,
selmon->sel->w, selmon->sel->h, 0);
arrange(selmon);
+ focus(NULL);
}
void
@@ -1759,6 +1795,7 @@ unfocus(Client *c, int setfocus)
return;
grabbuttons(c, 0);
XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel);
+ XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
if (setfocus) {
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
--
2.45.2