1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
|
From 17585c99f57856d39fd0d4c489d8bafd103d53f4 Mon Sep 17 00:00:00 2001
From: Dmitry Zakharchenko <dmitz@disroot.org>
Date: Sun, 28 Aug 2022 11:38:08 +0300
Subject: [PATCH] update swallow patch
---
config.def.h | 6 ++--
dwl.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 97 insertions(+), 6 deletions(-)
diff --git a/config.def.h b/config.def.h
index 29c6dbf8..4aa6903b 100644
--- a/config.def.h
+++ b/config.def.h
@@ -12,11 +12,11 @@ static const float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0};
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
static const Rule rules[] = {
- /* app_id title tags mask isfloating monitor */
+ /* app_id title tags mask isfloating isterm noswallow monitor */
/* examples:
- { "Gimp", NULL, 0, 1, -1 },
++ { "Gimp", NULL, 0, 1, 0, 1, -1 },
*/
- { "firefox", NULL, 1 << 8, 0, -1 },
+ { "firefox", NULL, 1 << 8, 0, 0, 1, -1 },
};
/* layout(s) */
diff --git a/dwl.c b/dwl.c
index 66aea65c..e897a9ff 100644
--- a/dwl.c
+++ b/dwl.c
@@ -90,7 +90,8 @@ typedef struct {
} Button;
typedef struct Monitor Monitor;
-typedef struct {
+typedef struct Client Client;
+struct Client{
/* Must keep these three elements in this order */
unsigned int type; /* XDGShell or X11* */
struct wlr_box geom; /* layout-relative, includes border */
@@ -119,9 +120,11 @@ typedef struct {
#endif
unsigned int bw;
unsigned int tags;
- int isfloating, isurgent, isfullscreen;
+ int isfloating, isurgent, isfullscreen, isterm, noswallow;
uint32_t resize; /* configure serial of a pending resize */
-} Client;
+ pid_t pid;
+ Client *swallowing, *swallowedby;
+};
typedef struct {
uint32_t singular_anchor;
@@ -200,6 +203,8 @@ typedef struct {
const char *title;
unsigned int tags;
int isfloating;
+ int isterm;
+ int noswallow;
int monitor;
} Rule;
@@ -295,6 +300,10 @@ static Monitor *xytomon(double x, double y);
static struct wlr_scene_node *xytonode(double x, double y, struct wlr_surface **psurface,
Client **pc, LayerSurface **pl, double *nx, double *ny);
static void zoom(const Arg *arg);
+static pid_t getparentprocess(pid_t p);
+static int isdescprocess(pid_t p, pid_t c);
+static Client *termforwin(Client *w);
+static void swallow(Client *c, Client *w);
/* variables */
static const char broken[] = "broken";
@@ -479,6 +488,8 @@ applyrules(Client *c)
if ((!r->title || strstr(title, r->title))
&& (!r->id || strstr(appid, r->id))) {
c->isfloating = r->isfloating;
+ c->isterm = r->isterm;
+ c->noswallow = r->noswallow;
newtags |= r->tags;
i = 0;
wl_list_for_each(m, &mons, link)
@@ -975,6 +986,8 @@ createnotify(struct wl_listener *listener, void *data)
c->surface.xdg = xdg_surface;
c->bw = borderpx;
+ wl_client_get_credentials(c->surface.xdg->client->client, &c->pid, NULL, NULL);
+
LISTEN(&xdg_surface->events.map, &c->map, mapnotify);
LISTEN(&xdg_surface->events.unmap, &c->unmap, unmapnotify);
LISTEN(&xdg_surface->events.destroy, &c->destroy, destroynotify);
@@ -1239,6 +1252,61 @@ fullscreennotify(struct wl_listener *listener, void *data)
setfullscreen(c, fullscreen);
}
+pid_t
+getparentprocess(pid_t p)
+{
+ unsigned int v = 0;
+
+ 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);
+
+ 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(Client *w)
+{
+ Client *c;
+
+ if (!w->pid || w->isterm || w->noswallow)
+ return NULL;
+
+ wl_list_for_each(c, &clients, link)
+ if (c->isterm && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid))
+ return c;
+
+ return NULL;
+}
+
+void
+swallow(Client *c, Client *w) {
+ c->bw = w->bw;
+ c->isfloating = w->isfloating;
+ c->isurgent = w->isurgent;
+ c->isfullscreen = w->isfullscreen;
+ resize(c, w->geom, 0);
+ wl_list_insert(&w->link, &c->link);
+ wl_list_insert(&w->flink, &c->flink);
+ wlr_scene_node_set_enabled(w->scene, 0);
+ wlr_scene_node_set_enabled(c->scene, 1);
+}
+
void
incnmaster(const Arg *arg)
{
@@ -1430,6 +1498,19 @@ mapnotify(struct wl_listener *listener, void *data)
setfullscreen(c, 1);
c->mon->un_map = 1;
+ if (!c->noswallow) {
+ Client *p = termforwin(c);
+ if (p) {
+ c->swallowedby = p;
+ p->swallowing = c;
+ wl_list_remove(&c->link);
+ wl_list_remove(&c->flink);
+ swallow(c,p);
+ wl_list_remove(&p->link);
+ wl_list_remove(&p->flink);
+ }
+ arrange(c->mon);
+ }
}
void
@@ -2322,6 +2403,16 @@ unmapnotify(struct wl_listener *listener, void *data)
cursor_mode = CurNormal;
grabc = NULL;
}
+ if (c->swallowing) {
+ c->swallowing->swallowedby = NULL;
+ c->swallowing = NULL;
+ }
+
+ if (c->swallowedby) {
+ swallow(c->swallowedby, c);
+ c->swallowedby->swallowing = NULL;
+ c->swallowedby = NULL;
+ }
if (c->mon)
c->mon->un_map = 1;
|