swallow: rewrite patch, update README.md

This commit is contained in:
Nikita Ivanov 2025-03-03 21:49:52 +01:00
parent 4d0bfa66b4
commit 2e5748edfe
No known key found for this signature in database
GPG Key ID: 6E656AC5B97B5133
3 changed files with 284 additions and 152 deletions

View File

@ -1,29 +1,52 @@
### Description ### Description
Terminals swallow windows that they are the parent of.
This patch adds "window swallowing" to dwl.
foot is the terminal by default, you can change it in client rules in config.h.
If a user runs a graphical program from the terminal (e.g., `mpv`), the terminal
2023-08-16 and up are made to also work with x windows: https://codeberg.org/dwl/dwl/issues/331 will be hidden and only a window of the newly spawned graphical program will
be visible. The terminal stays hidden until the graphical program is closed.
for freebsd users: apply swallow-freebsd.patch **on top of** swallow.patch This patch helps users spawning a lot of graphical programs from their command
line by avoiding cluttering the screen with many unusable terminals.
### Download
- [git branch](https://codeberg.org/notchoc/dwl/src/branch/swallow) `foot` is the terminal by default, you can change it in client rules in config.h.
- [2024-07-13](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/swallow/swallow.patch)
In `2025-03-03 v0.7` version, the patch had been rewritten from scratch to make
it more robust and add a few more features:
- "dynamically swallow" windows by pressing `Alt+a` (a focused window will
swallow/unswallow the previously focused one)
- toggle automatic swallowing by `Alt+Shift+a`
- if a window has swallowed another, it get thicker borders
### Download
#### swallow.patch
- [git branch](https://codeberg.org/nikitaivanov/dwl/src/branch/swallow)
- [2025-03-03 v0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/swallow/swallow.patch) (added "dynamic swallowing support")
- [2024-07-13](https://codeberg.org/dwl/dwl-patches/raw/commit/f1ed83eaeba46108f4ee8164094cb431d64a3e68/patches/swallow/swallow.patch)
- [2024-07-13](https://codeberg.org/dwl/dwl-patches/raw/commit/f64d701bab2f9f52d3637edd091684f920407d87/patches/swallow/swallow.patch) - [2024-07-13](https://codeberg.org/dwl/dwl-patches/raw/commit/f64d701bab2f9f52d3637edd091684f920407d87/patches/swallow/swallow.patch)
- [2024-05-02](https://codeberg.org/dwl/dwl-patches/raw/commit/9c5d5d85f3ac780e7a14d5d0535e3349ce8b8f53/patches/swallow/swallow.patch) - [2024-05-02](https://codeberg.org/dwl/dwl-patches/raw/commit/9c5d5d85f3ac780e7a14d5d0535e3349ce8b8f53/patches/swallow/swallow.patch)
- [2024-04-03](https://codeberg.org/dwl/dwl-patches/raw/commit/3c9a8e3232a8531871924484cef1ef0938730e15/swallow/swallow.patch) - [2024-04-03](https://codeberg.org/dwl/dwl-patches/raw/commit/3c9a8e3232a8531871924484cef1ef0938730e15/swallow/swallow.patch)
- [2024-01-01](https://codeberg.org/dwl/dwl-patches/raw/commit/8a352a1b27a64821ba9fbfda52fe82463ac84c66/swallow/swallow.patch) - [2024-01-01](https://codeberg.org/dwl/dwl-patches/raw/commit/8a352a1b27a64821ba9fbfda52fe82463ac84c66/swallow/swallow.patch)
- [2023-10-26](https://github.com/djpohly/dwl/compare/main...youbitchoc:swallow.patch) - [2023-10-26](https://github.com/djpohly/dwl/compare/main...youbitchoc:swallow.patch)
- [2023-08-16](https://github.com/djpohly/dwl/compare/main...mewkl:swallowx.patch) - [2023-08-16](https://github.com/djpohly/dwl/compare/main...mewkl:swallowx.patch) (added XWayland support)
- [2023-07-15](https://github.com/djpohly/dwl/compare/main...NikitaIvanovV:swallow.patch) - [2023-07-15](https://github.com/djpohly/dwl/compare/main...NikitaIvanovV:swallow.patch)
- [v0.4](https://github.com/djpohly/dwl/compare/main...dm1tz:04-swallow.patch) - [v0.4](https://github.com/djpohly/dwl/compare/main...dm1tz:04-swallow.patch)
- [2021-12-03](https://github.com/djpohly/dwl/compare/main...dm1tz:swallow.patch) - [2021-12-03](https://github.com/djpohly/dwl/compare/main...dm1tz:swallow.patch)
### Authors #### swallow-freebsd.patch
- [Dmitry Zakharchenko](https://github.com/dm1tz)
- [Palanix](https://codeberg.org/Palanix) Apply this patch on top of the swallow.patch if you use FreeBSD.
- [Nikita Ivanov](https://github.com/NikitaIvanovV)
- [Connor Worrell](https://github.com/ConnorWorrell) - [2025-03-03 v0.7](https://codeberg.org/dwl/dwl-patches/raw/branch/main/patches/swallow/swallow-freebsd.patch)
- [Mewkl](https://github.com/mewkl) - [2024-07-13](https://codeberg.org/dwl/dwl-patches/raw/commit/f1ed83eaeba46108f4ee8164094cb431d64a3e68/patches/swallow/swallow-freebsd.patch)
- [Choc](https://codeberg.org/notchoc)
### Authors
- [Nikita Ivanov](https://codeberg.org/nikitaivanov) ([GitHub](https://github.com/NikitaIvanovV))
- [Dmitry Zakharchenko](https://github.com/dm1tz)
- [Palanix](https://codeberg.org/Palanix)
- [Connor Worrell](https://github.com/ConnorWorrell)
- [Mewkl](https://github.com/mewkl)
- [Choc](https://codeberg.org/notchoc)

View File

@ -1,17 +1,17 @@
From 49dc947ba4c33324b969ef7179768c806910fffb Mon Sep 17 00:00:00 2001 From 002e11e197cd254f06b65681ffd5bcf617d830b9 Mon Sep 17 00:00:00 2001
From: choc <notchoc@proton.me> From: Nikita Ivanov <nikita.vyach.ivanov@gmail.com>
Date: Sat, 22 Jun 2024 10:52:33 +0800 Date: Mon, 3 Mar 2025 19:49:07 +0100
Subject: [PATCH] swallow: add freebsd support Subject: [PATCH] swallow: add FreeBSD support
--- ---
dwl.c | 17 +++++++++++++++++ dwl.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+) 1 file changed, 17 insertions(+)
diff --git a/dwl.c b/dwl.c diff --git a/dwl.c b/dwl.c
index 3a3167b..ee9e965 100644 index bbbbe6f..dc55319 100644
--- a/dwl.c --- a/dwl.c
+++ b/dwl.c +++ b/dwl.c
@@ -65,6 +65,14 @@ @@ -67,6 +67,14 @@
#include <xcb/xcb_icccm.h> #include <xcb/xcb_icccm.h>
#endif #endif
@ -26,17 +26,17 @@ index 3a3167b..ee9e965 100644
#include "util.h" #include "util.h"
/* macros */ /* macros */
@@ -1486,6 +1494,7 @@ handlesig(int signo) @@ -2032,6 +2040,7 @@ outputmgrtest(struct wl_listener *listener, void *data)
pid_t pid_t
getparentprocess(pid_t p) parentpid(pid_t pid)
{ {
+#ifdef __linux__ +#ifdef __linux__
unsigned int v = 0; unsigned int v = 0;
FILE *f; FILE *f;
@@ -1499,6 +1508,14 @@ getparentprocess(pid_t p) char buf[256];
@@ -2041,6 +2050,14 @@ parentpid(pid_t pid)
fscanf(f, "%*u %*s %*c %u", &v);
fclose(f); fclose(f);
return (pid_t)v; return (pid_t)v;
+#elif defined(__FreeBSD__) +#elif defined(__FreeBSD__)
+ struct kinfo_proc kip; + struct kinfo_proc kip;
@ -48,8 +48,7 @@ index 3a3167b..ee9e965 100644
+#endif +#endif
} }
int void
-- --
2.43.0 2.48.1

View File

@ -1,13 +1,13 @@
From 4b80c425c9f414bc079a0e61f5a3ef42eea85476 Mon Sep 17 00:00:00 2001 From 7255d7e2e1b87c0583a202ea20c83fa75466c0fc Mon Sep 17 00:00:00 2001
From: choc <notchoc@proton.me> From: Nikita Ivanov <nikita.vyach.ivanov@gmail.com>
Date: Fri, 15 Sep 2023 10:36:21 +0800 Date: Wed, 5 Feb 2025 02:34:39 +0100
Subject: [PATCH] implement swallow Subject: [PATCH] Swallow: hide the terminal when it spawns a client
--- ---
client.h | 12 ++++++ client.h | 12 ++++
config.def.h | 7 ++-- config.def.h | 10 +++-
dwl.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++--- dwl.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 123 insertions(+), 8 deletions(-) 3 files changed, 167 insertions(+), 7 deletions(-)
diff --git a/client.h b/client.h diff --git a/client.h b/client.h
index 42f225f..bc9cad2 100644 index 42f225f..bc9cad2 100644
@ -33,29 +33,61 @@ index 42f225f..bc9cad2 100644
client_get_clip(Client *c, struct wlr_box *clip) client_get_clip(Client *c, struct wlr_box *clip)
{ {
diff --git a/config.def.h b/config.def.h diff --git a/config.def.h b/config.def.h
index 22d2171..7e5fef1 100644 index 22d2171..fb5f8fb 100644
--- a/config.def.h --- a/config.def.h
+++ b/config.def.h +++ b/config.def.h
@@ -22,10 +22,11 @@ static int log_level = WLR_ERROR; @@ -13,6 +13,7 @@ static const float focuscolor[] = COLOR(0x005577ff);
static const float urgentcolor[] = COLOR(0xff0000ff);
/* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */
+static int enableautoswallow = 1; /* enables autoswallowing newly spawned clients */
/* tagging - TAGCOUNT must be no greater than 31 */
#define TAGCOUNT (9)
@@ -22,10 +23,11 @@ static int log_level = WLR_ERROR;
/* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */
static const Rule rules[] = { static const Rule rules[] = {
- /* app_id title tags mask isfloating monitor */ - /* app_id title tags mask isfloating monitor */
+ /* app_id title tags mask isfloating isterm noswallow monitor */ + /* app_id title tags mask isfloating isterm noswallow monitor */
/* examples: */ /* examples: */
- { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */ - { "Gimp_EXAMPLE", NULL, 0, 1, -1 }, /* Start on currently visible tags floating, not tiled */
- { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */ - { "firefox_EXAMPLE", NULL, 1 << 8, 0, -1 }, /* Start on ONLY tag "9" */
+ { "Gimp_EXAMPLE", NULL, 0, 1, 0, 0, -1 }, /* Start on currently visible tags floating, not tiled */ + { "foot", NULL, 0, 0, 1, 1, -1 },
+ { "firefox_EXAMPLE", NULL, 1 << 8, 0, 0, 0, -1 }, /* Start on ONLY tag "9" */ + { "Gimp_EXAMPLE", NULL, 0, 1, 0, 0, -1 }, /* Start on currently visible tags floating, not tiled */
+ { "foot", NULL, 0, 0, 1, 1, -1 }, /* make foot swallow clients that are not foot */ + { "firefox_EXAMPLE", NULL, 1 << 8, 0, 0, 0, -1 }, /* Start on ONLY tag "9" */
}; };
/* layout(s) */ /* layout(s) */
@@ -142,6 +144,8 @@ static const Key keys[] = {
{ MODKEY, XKB_KEY_space, setlayout, {0} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} },
+ { MODKEY, XKB_KEY_a, toggleswallow, {0} },
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_A, toggleautoswallow,{0} },
{ MODKEY, XKB_KEY_0, view, {.ui = ~0} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
{ MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
diff --git a/dwl.c b/dwl.c diff --git a/dwl.c b/dwl.c
index dc0437e..c6a5e9d 100644 index def2562..bbbbe6f 100644
--- a/dwl.c --- a/dwl.c
+++ b/dwl.c +++ b/dwl.c
@@ -103,7 +103,8 @@ typedef struct { @@ -73,12 +73,13 @@
#define MAX(A, B) ((A) > (B) ? (A) : (B))
#define MIN(A, B) ((A) < (B) ? (A) : (B))
#define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS)
-#define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags]))
+#define VISIBLEON(C, M) ((M) && (C)->mon == (M) && ((C)->tags & (M)->tagset[(M)->seltags]) && !(C)->swallowedby)
#define LENGTH(X) (sizeof X / sizeof X[0])
#define END(A) ((A) + LENGTH(A))
#define TAGMASK ((1u << TAGCOUNT) - 1)
#define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L)))
#define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0)
+#define BORDERPX(C) (borderpx + ((C)->swallowing ? (C)->swallowing->bw : 0))
/* enums */
enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
@@ -104,7 +105,8 @@ typedef struct {
} Button; } Button;
typedef struct Monitor Monitor; typedef struct Monitor Monitor;
@ -65,21 +97,21 @@ index dc0437e..c6a5e9d 100644
/* Must keep these three elements in this order */ /* Must keep these three elements in this order */
unsigned int type; /* XDGShell or X11* */ unsigned int type; /* XDGShell or X11* */
struct wlr_box geom; /* layout-relative, includes border */ struct wlr_box geom; /* layout-relative, includes border */
@@ -138,9 +139,11 @@ typedef struct { @@ -140,8 +142,12 @@ typedef struct {
#endif
unsigned int bw; unsigned int bw;
uint32_t tags; uint32_t tags;
- int isfloating, isurgent, isfullscreen; int isfloating, isurgent, isfullscreen;
+ int isfloating, isurgent, isfullscreen, isterm, noswallow; + int isterm, noswallow;
uint32_t resize; /* configure serial of a pending resize */ uint32_t resize; /* configure serial of a pending resize */
-} Client; -} Client;
+ pid_t pid; + pid_t pid;
+ Client *swallowing, *swallowedby; + Client *swallowing; /* client being hidden */
+ Client *swallowedby;
+}; +};
typedef struct { typedef struct {
uint32_t mod; uint32_t mod;
@@ -229,6 +232,8 @@ typedef struct { @@ -230,6 +236,8 @@ typedef struct {
const char *title; const char *title;
uint32_t tags; uint32_t tags;
int isfloating; int isfloating;
@ -88,18 +120,31 @@ index dc0437e..c6a5e9d 100644
int monitor; int monitor;
} Rule; } Rule;
@@ -351,6 +356,10 @@ static Monitor *xytomon(double x, double y); @@ -311,6 +319,7 @@ static void moveresize(const Arg *arg);
static void xytonode(double x, double y, struct wlr_surface **psurface, static void outputmgrapply(struct wl_listener *listener, void *data);
Client **pc, LayerSurface **pl, double *nx, double *ny); static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test);
static void zoom(const Arg *arg); static void outputmgrtest(struct wl_listener *listener, void *data);
+static pid_t getparentprocess(pid_t p); +static pid_t parentpid(pid_t pid);
+static int isdescprocess(pid_t p, pid_t c); static void pointerfocus(Client *c, struct wlr_surface *surface,
+static Client *termforwin(Client *w); double sx, double sy, uint32_t time);
+static void swallow(Client *c, Client *w); static void printstatus(void);
@@ -335,11 +344,15 @@ static void setsel(struct wl_listener *listener, void *data);
/* variables */ static void setup(void);
static const char broken[] = "broken"; static void spawn(const Arg *arg);
@@ -461,10 +470,14 @@ applyrules(Client *c) static void startdrag(struct wl_listener *listener, void *data);
+static void swallow(Client *c, Client *toswallow);
static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
+static Client *termforwin(Client *c);
static void tile(Monitor *m);
static void togglefloating(const Arg *arg);
static void togglefullscreen(const Arg *arg);
+static void toggleswallow(const Arg *arg);
+static void toggleautoswallow(const Arg *arg);
static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
static void unlocksession(struct wl_listener *listener, void *data);
@@ -466,11 +479,15 @@ applyrules(Client *c)
if (!(title = client_get_title(c))) if (!(title = client_get_title(c)))
title = broken; title = broken;
@ -109,132 +154,197 @@ index dc0437e..c6a5e9d 100644
if ((!r->title || strstr(title, r->title)) if ((!r->title || strstr(title, r->title))
&& (!r->id || strstr(appid, r->id))) { && (!r->id || strstr(appid, r->id))) {
c->isfloating = r->isfloating; c->isfloating = r->isfloating;
+ c->isterm = r->isterm;
+ c->noswallow = r->noswallow;
newtags |= r->tags; newtags |= r->tags;
+ c->isterm = r->isterm;
+ c->noswallow = r->noswallow;
i = 0; i = 0;
wl_list_for_each(m, &mons, link) { wl_list_for_each(m, &mons, link) {
@@ -473,6 +486,21 @@ applyrules(Client *c) if (r->monitor == i++)
@@ -478,6 +495,12 @@ applyrules(Client *c)
} }
} }
} }
+ if (!c->noswallow && !client_is_float_type(c) + if (enableautoswallow && !c->noswallow && !c->isfloating &&
+ && !c->surface.xdg->initial_commit) { + !c->surface.xdg->initial_commit) {
+ Client *p = termforwin(c); + Client *p = termforwin(c);
+ if (p) { + if (p)
+ c->swallowedby = p;
+ p->swallowing = c;
+ wl_list_remove(&c->link);
+ wl_list_remove(&c->flink);
+ swallow(c, p); + swallow(c, p);
+ wl_list_remove(&p->link);
+ wl_list_remove(&p->flink);
+ mon = p->mon;
+ newtags = p->tags;
+ }
+ } + }
setmon(c, mon, newtags); setmon(c, mon, newtags);
} }
@@ -1467,6 +1495,63 @@ handlesig(int signo) @@ -2006,6 +2029,20 @@ outputmgrtest(struct wl_listener *listener, void *data)
} outputmgrapplyortest(config, 1);
} }
+pid_t +pid_t
+getparentprocess(pid_t p) +parentpid(pid_t pid)
+{ +{
+ unsigned int v = 0; + unsigned int v = 0;
+
+ FILE *f; + FILE *f;
+ char buf[256]; + char buf[256];
+ snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p); + snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)pid);
+
+ if (!(f = fopen(buf, "r"))) + if (!(f = fopen(buf, "r")))
+ return 0; + return 0;
+
+ fscanf(f, "%*u %*s %*c %u", &v); + fscanf(f, "%*u %*s %*c %u", &v);
+ fclose(f); + fclose(f);
+
+ return (pid_t)v; + return (pid_t)v;
+} +}
+ +
+int void
+isdescprocess(pid_t p, pid_t c) pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
+{ uint32_t time)
+ while (p != c && c != 0) @@ -2326,7 +2363,7 @@ setfullscreen(Client *c, int fullscreen)
+ c = getparentprocess(c); c->isfullscreen = fullscreen;
if (!c->mon || !client_surface(c)->mapped)
return;
- c->bw = fullscreen ? 0 : borderpx;
+ c->bw = fullscreen ? 0 : BORDERPX(c);
client_set_fullscreen(c, fullscreen);
wlr_scene_node_reparent(&c->scene->node, layers[c->isfullscreen
? LyrFS : c->isfloating ? LyrFloat : LyrTile]);
@@ -2404,6 +2441,9 @@ setmon(Client *c, Monitor *m, uint32_t newtags)
setfloating(c, c->isfloating);
}
focusclient(focustop(selmon), 1);
+ +
+ return (int)c; + if (c->swallowing)
+ setmon(c->swallowing, m, newtags);
}
void
@@ -2669,6 +2709,44 @@ startdrag(struct wl_listener *listener, void *data)
LISTEN_STATIC(&drag->icon->events.destroy, destroydragicon);
}
+void
+swallow(Client *c, Client *toswallow)
+{
+ /* Do not allow a client to swallow itself */
+ if (c == toswallow)
+ return;
+
+ /* Swallow */
+ if (toswallow && !c->swallowing) {
+ c->swallowing = toswallow;
+ toswallow->swallowedby = c;
+ toswallow->mon = c->mon;
+ toswallow->mon = c->mon;
+ wl_list_remove(&c->link);
+ wl_list_insert(&c->swallowing->link, &c->link);
+ wl_list_remove(&c->flink);
+ wl_list_insert(&c->swallowing->flink, &c->flink);
+ c->bw = BORDERPX(c);
+ c->tags = toswallow->tags;
+ c->isfloating = toswallow->isfloating;
+ c->geom = toswallow->geom;
+ setfullscreen(toswallow, 0);
+ }
+
+ /* Unswallow */
+ else if (c->swallowing) {
+ wl_list_remove(&c->swallowing->link);
+ wl_list_insert(&c->link, &c->swallowing->link);
+ wl_list_remove(&c->swallowing->flink);
+ wl_list_insert(&c->flink, &c->swallowing->flink);
+ c->swallowing->tags = c->tags;
+ c->swallowing->swallowedby = NULL;
+ c->swallowing = NULL;
+ c->bw = BORDERPX(c);
+ setfullscreen(c, 0);
+ }
+} +}
+ +
void
tag(const Arg *arg)
{
@@ -2690,6 +2768,40 @@ tagmon(const Arg *arg)
setmon(sel, dirtomon(arg->i), 0);
}
+Client * +Client *
+termforwin(Client *w) +termforwin(Client *c)
+{ +{
+ Client *c; + Client *p;
+ pid_t pid;
+ pid_t pids[32];
+ size_t i, pids_len;
+ +
+ if (!w->pid || w->isterm || w->noswallow) + if (!c->pid || c->isterm)
+ return NULL; + return NULL;
+ +
+ wl_list_for_each(c, &fstack, flink) + /* Get all parent pids */
+ if (c->isterm && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid)) + pids_len = 0;
+ return c; + pid = c->pid;
+ while (pids_len < LENGTH(pids)) {
+ pid = parentpid(pid);
+ if (!pid)
+ break;
+ pids[pids_len++] = pid;
+ }
+
+ /* Find closest parent */
+ for (i = 0; i < pids_len; i++) {
+ wl_list_for_each(p, &clients, link) {
+ if (!p->pid || !p->isterm || p->swallowedby)
+ continue;
+ if (pids[i] == p->pid)
+ return p;
+ }
+ }
+ +
+ return NULL; + return NULL;
+} +}
+ +
void
tile(Monitor *m)
{
@@ -2741,6 +2853,32 @@ togglefullscreen(const Arg *arg)
setfullscreen(sel, !sel->isfullscreen);
}
+void +void
+swallow(Client *c, Client *w) +toggleswallow(const Arg *arg)
+{ +{
+ c->bw = w->bw; + Client *c, *sel = focustop(selmon);
+ c->isfloating = w->isfloating; + if (!sel)
+ c->isurgent = w->isurgent; + return;
+ c->isfullscreen = w->isfullscreen; +
+ c->tags = w->tags; + if (sel->swallowing) {
+ c->geom = w->geom; + swallow(sel, NULL);
+ wl_list_insert(&w->link, &c->link); + } else {
+ wl_list_insert(&w->flink, &c->flink); + wl_list_for_each(c, &sel->flink, flink) {
+ wlr_scene_node_set_enabled(&w->scene->node, 0); + if (&c->flink == &fstack)
+ wlr_scene_node_set_enabled(&c->scene->node, 1); + continue; /* wrap past the sentinel node */
+ if (VISIBLEON(c, selmon))
+ break; /* found it */
+ }
+ swallow(sel, c);
+ }
+}
+
+void
+toggleautoswallow(const Arg *arg)
+{
+ enableautoswallow = !enableautoswallow;
+} +}
+ +
void void
incnmaster(const Arg *arg) toggletag(const Arg *arg)
{ {
@@ -2746,15 +2831,32 @@ unmapnotify(struct wl_listener *listener, void *data) @@ -2801,6 +2939,12 @@ unmapnotify(struct wl_listener *listener, void *data)
grabc = NULL; grabc = NULL;
} }
+ if (c->swallowedby) + if (c->swallowing) {
+ swallow(c->swallowedby, c); + swallow(c, NULL);
+ } else if (c->swallowedby) {
+ swallow(c->swallowedby, NULL);
+ }
+ +
if (client_is_unmanaged(c)) { if (client_is_unmanaged(c)) {
if (c == exclusive_focus) { if (c == exclusive_focus) {
exclusive_focus = NULL; exclusive_focus = NULL;
focusclient(focustop(selmon), 1);
}
} else {
- wl_list_remove(&c->link);
+ if (!c->swallowing)
+ wl_list_remove(&c->link);
setmon(c, NULL, 0);
- wl_list_remove(&c->flink);
+ if (!c->swallowing)
+ wl_list_remove(&c->flink);
+ }
+
+ if (c->swallowedby) {
+ c->swallowedby->prev = c->geom;
+ setfullscreen(c->swallowedby, c->isfullscreen);
+ c->swallowedby->swallowing = NULL;
+ c->swallowedby = NULL;
+ }
+
+ if (c->swallowing) {
+ c->swallowing->swallowedby = NULL;
+ c->swallowing = NULL;
}
wlr_scene_node_destroy(&c->scene->node);
-- --
2.43.0 2.48.1