mirror of
https://github.com/tiyn/dwl.git
synced 2025-11-13 13:59:45 +01:00
patched swallow
This commit is contained in:
151
dwl.c
151
dwl.c
@@ -74,7 +74,7 @@
|
||||
#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)
|
||||
@@ -101,7 +101,8 @@ typedef struct {
|
||||
} Button;
|
||||
|
||||
typedef struct Monitor Monitor;
|
||||
typedef struct {
|
||||
typedef struct Client Client;
|
||||
struct Client {
|
||||
/* Must keep this field first */
|
||||
unsigned int type; /* XDGShell or X11* */
|
||||
|
||||
@@ -138,8 +139,12 @@ typedef struct {
|
||||
unsigned int bw;
|
||||
uint32_t tags;
|
||||
int isfloating, isurgent, isfullscreen;
|
||||
int isterm, noswallow;
|
||||
uint32_t resize; /* configure serial of a pending resize */
|
||||
} Client;
|
||||
pid_t pid;
|
||||
Client *swallowing; /* client being hidden */
|
||||
Client *swallowedby;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t mod;
|
||||
@@ -227,6 +232,8 @@ typedef struct {
|
||||
const char *title;
|
||||
uint32_t tags;
|
||||
int isfloating;
|
||||
int isterm;
|
||||
int noswallow;
|
||||
int monitor;
|
||||
} Rule;
|
||||
|
||||
@@ -308,6 +315,7 @@ static void moveresize(const Arg *arg);
|
||||
static void outputmgrapply(struct wl_listener *listener, void *data);
|
||||
static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test);
|
||||
static void outputmgrtest(struct wl_listener *listener, void *data);
|
||||
static pid_t parentpid(pid_t pid);
|
||||
static void pointerfocus(Client *c, struct wlr_surface *surface,
|
||||
double sx, double sy, uint32_t time);
|
||||
static void printstatus(void);
|
||||
@@ -331,11 +339,15 @@ static void setsel(struct wl_listener *listener, void *data);
|
||||
static void setup(void);
|
||||
static void spawn(const Arg *arg);
|
||||
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);
|
||||
@@ -487,11 +499,15 @@ applyrules(Client *c)
|
||||
appid = client_get_appid(c);
|
||||
title = client_get_title(c);
|
||||
|
||||
c->pid = client_get_pid(c);
|
||||
|
||||
for (r = rules; r < END(rules); r++) {
|
||||
if ((!r->title || strstr(title, r->title))
|
||||
&& (!r->id || strstr(appid, r->id))) {
|
||||
c->isfloating = r->isfloating;
|
||||
newtags |= r->tags;
|
||||
c->isterm = r->isterm;
|
||||
c->noswallow = r->noswallow;
|
||||
i = 0;
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
if (r->monitor == i++)
|
||||
@@ -499,6 +515,12 @@ applyrules(Client *c)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (enableautoswallow && !c->noswallow && !c->isfloating &&
|
||||
!c->surface.xdg->initial_commit) {
|
||||
Client *p = termforwin(c);
|
||||
if (p)
|
||||
swallow(c, p);
|
||||
}
|
||||
setmon(c, mon, newtags);
|
||||
}
|
||||
|
||||
@@ -2054,6 +2076,20 @@ outputmgrtest(struct wl_listener *listener, void *data)
|
||||
outputmgrapplyortest(config, 1);
|
||||
}
|
||||
|
||||
pid_t
|
||||
parentpid(pid_t pid)
|
||||
{
|
||||
unsigned int v = 0;
|
||||
FILE *f;
|
||||
char buf[256];
|
||||
snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)pid);
|
||||
if (!(f = fopen(buf, "r")))
|
||||
return 0;
|
||||
fscanf(f, "%*u %*s %*c %u", &v);
|
||||
fclose(f);
|
||||
return (pid_t)v;
|
||||
}
|
||||
|
||||
void
|
||||
pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
|
||||
uint32_t time)
|
||||
@@ -2346,7 +2382,7 @@ setfullscreen(Client *c, int fullscreen)
|
||||
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]);
|
||||
@@ -2413,6 +2449,9 @@ setmon(Client *c, Monitor *m, uint32_t newtags)
|
||||
setfloating(c, c->isfloating);
|
||||
}
|
||||
focusclient(focustop(selmon), 1);
|
||||
|
||||
if (c->swallowing)
|
||||
setmon(c->swallowing, m, newtags);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2683,6 +2722,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)
|
||||
{
|
||||
@@ -2704,6 +2781,40 @@ tagmon(const Arg *arg)
|
||||
setmon(sel, dirtomon(arg->i), 0);
|
||||
}
|
||||
|
||||
Client *
|
||||
termforwin(Client *c)
|
||||
{
|
||||
Client *p;
|
||||
pid_t pid;
|
||||
pid_t pids[32];
|
||||
size_t i, pids_len;
|
||||
|
||||
if (!c->pid || c->isterm)
|
||||
return NULL;
|
||||
|
||||
/* Get all parent pids */
|
||||
pids_len = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
void
|
||||
tile(Monitor *m)
|
||||
{
|
||||
@@ -2755,6 +2866,32 @@ togglefullscreen(const Arg *arg)
|
||||
setfullscreen(sel, !sel->isfullscreen);
|
||||
}
|
||||
|
||||
void
|
||||
toggleswallow(const Arg *arg)
|
||||
{
|
||||
Client *c, *sel = focustop(selmon);
|
||||
if (!sel)
|
||||
return;
|
||||
|
||||
if (sel->swallowing) {
|
||||
swallow(sel, NULL);
|
||||
} else {
|
||||
wl_list_for_each(c, &sel->flink, flink) {
|
||||
if (&c->flink == &fstack)
|
||||
continue; /* wrap past the sentinel node */
|
||||
if (VISIBLEON(c, selmon))
|
||||
break; /* found it */
|
||||
}
|
||||
swallow(sel, c);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
toggleautoswallow(const Arg *arg)
|
||||
{
|
||||
enableautoswallow = !enableautoswallow;
|
||||
}
|
||||
|
||||
void
|
||||
toggletag(const Arg *arg)
|
||||
{
|
||||
@@ -2815,6 +2952,12 @@ unmapnotify(struct wl_listener *listener, void *data)
|
||||
grabc = NULL;
|
||||
}
|
||||
|
||||
if (c->swallowing) {
|
||||
swallow(c, NULL);
|
||||
} else if (c->swallowedby) {
|
||||
swallow(c->swallowedby, NULL);
|
||||
}
|
||||
|
||||
if (client_is_unmanaged(c)) {
|
||||
if (c == exclusive_focus) {
|
||||
exclusive_focus = NULL;
|
||||
|
||||
Reference in New Issue
Block a user