implement version 5 with x11 support
This commit is contained in:
parent
8006e79200
commit
b21a09cb06
66
config.def.h
66
config.def.h
@ -7,10 +7,11 @@
|
|||||||
static const int sloppyfocus = 1; /* focus follows mouse */
|
static const int sloppyfocus = 1; /* focus follows mouse */
|
||||||
static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */
|
static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */
|
||||||
static const unsigned int borderpx = 1; /* border pixel of windows */
|
static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||||
static const float rootcolor[] = COLOR(0x222222ff);
|
static const float rootcolor[] = COLOR(0x330044);
|
||||||
static const float bordercolor[] = COLOR(0x444444ff);
|
static const float bordercolor[] = COLOR(0x32CD32); // Lime green
|
||||||
static const float focuscolor[] = COLOR(0x005577ff);
|
static const float focuscolor[] = COLOR(0x330044); // Darker purple
|
||||||
static const float urgentcolor[] = COLOR(0xff0000ff);
|
static const float urgentcolor[] = COLOR(0x32CD32); // Changed from red to lime green
|
||||||
|
|
||||||
/* To conform the xdg-protocol, set the alpha to zero to restore the old behavior */
|
/* To conform 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 const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */
|
||||||
|
|
||||||
@ -20,12 +21,27 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca
|
|||||||
/* logging */
|
/* logging */
|
||||||
static int log_level = WLR_ERROR;
|
static int log_level = WLR_ERROR;
|
||||||
|
|
||||||
|
|
||||||
|
/* Autostart */
|
||||||
|
static const char *const autostart[] = {
|
||||||
|
"exec", "dbus-update-activation-environment", "--systemd", "DISPLAY", "I3SOCK", "SWAYSOCK", "WAYLAND_DISPLAY", "XDG_CURRENT_DESKTOP=sway", NULL,
|
||||||
|
"/usr/bin/wbg", "/home/s4d/.config/lain.jpg", NULL,
|
||||||
|
"/usr/libexec/kdeconnectd", NULL,
|
||||||
|
"/usr/bin/pipewire", NULL,
|
||||||
|
"/usr/bin/dunst", NULL,
|
||||||
|
"/usr/local/bin/someblocks", NULL,
|
||||||
|
"/usr/bin/swayidle", "-w", "idle", "timeout", "600", "\"/usr/local/bin/swaylock -f\"", NULL,
|
||||||
|
"/usr/bin/spotifyd", "--no-daemon", NULL,
|
||||||
|
"/usr/libexec/xdg-desktop-portal", "-r", NULL,
|
||||||
|
NULL /* terminate */
|
||||||
|
};
|
||||||
|
|
||||||
static const Rule rules[] = {
|
static const Rule rules[] = {
|
||||||
/* app_id title tags mask isfloating monitor */
|
/* app_id title tags mask isfloating isterm noswallow monitor */
|
||||||
/* examples:
|
/* 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) */
|
/* layout(s) */
|
||||||
@ -102,7 +118,7 @@ LIBINPUT_CONFIG_TAP_MAP_LMR -- 1/2/3 finger tap maps to left/middle/right
|
|||||||
static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM;
|
static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM;
|
||||||
|
|
||||||
/* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */
|
/* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */
|
||||||
#define MODKEY WLR_MODIFIER_ALT
|
#define MODKEY WLR_MODIFIER_LOGO
|
||||||
|
|
||||||
#define TAGKEYS(KEY,SKEY,TAG) \
|
#define TAGKEYS(KEY,SKEY,TAG) \
|
||||||
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
|
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
|
||||||
@ -114,20 +130,37 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA
|
|||||||
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
|
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
|
||||||
|
|
||||||
/* commands */
|
/* commands */
|
||||||
static const char *termcmd[] = { "foot", NULL };
|
static const char *termcmd[] = { "kitty", NULL };
|
||||||
static const char *menucmd[] = { "bemenu-run", NULL };
|
/*static const char *menucmd[] = { "dmenu-wl_run", "-fn", "hack_mono:13", "-sb", "#550077", NULL };*/
|
||||||
|
static const char *menucmd[] = { "/bin/sh", "-c",
|
||||||
|
"dmenu-wl_path | wmenu -S \"#550077\" -N \"#000000\" -n \"#32CD32\" -s \"#000000\" -f \"Hack Mono Bold 13\" | xargs -I_-_ /bin/sh -c \"exec _-_\"",
|
||||||
|
NULL };
|
||||||
|
|
||||||
|
/* volume control */
|
||||||
|
static const char *volup[] = {"/usr/bin/pactl", "set-sink-volume", "@DEFAULT_SINK@", "+5%", NULL};
|
||||||
|
static const char *voldown[] = {"/usr/bin/pactl", "set-sink-volume", "@DEFAULT_SINK@", "-5%", NULL};
|
||||||
|
static const char *volmute[] = {"/usr/bin/pactl", "set-sink-mute", "@DEFAULT_SINK@", "toggle", NULL};
|
||||||
|
|
||||||
|
/* volume input */
|
||||||
|
static const char *mutemic[] = { "/usr/bin/pactl", "set-source-mute", "@DEFAULT_SOURCE@", "toggle", NULL };
|
||||||
|
|
||||||
|
/* brightness control */
|
||||||
|
static const char *brightnessup[] = { "/usr/bin/brightnessctl", "s", "3%+", NULL };
|
||||||
|
static const char *brightnessdown[] = { "/usr/bin/brightnessctl", "s", "3%-", NULL };
|
||||||
|
|
||||||
|
|
||||||
static const Key keys[] = {
|
static const Key keys[] = {
|
||||||
/* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */
|
/* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */
|
||||||
/* modifier key function argument */
|
/* modifier key function argument */
|
||||||
{ MODKEY, XKB_KEY_p, spawn, {.v = menucmd} },
|
{ MODKEY, XKB_KEY_p, spawn, {.v = menucmd} },
|
||||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} },
|
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} },
|
||||||
|
/*{ MODKEY, XKB_KEY_b, togglebar, {0}},*/
|
||||||
{ MODKEY, XKB_KEY_j, focusstack, {.i = +1} },
|
{ MODKEY, XKB_KEY_j, focusstack, {.i = +1} },
|
||||||
{ MODKEY, XKB_KEY_k, focusstack, {.i = -1} },
|
{ MODKEY, XKB_KEY_k, focusstack, {.i = -1} },
|
||||||
{ MODKEY, XKB_KEY_i, incnmaster, {.i = +1} },
|
{ MODKEY, XKB_KEY_i, incnmaster, {.i = +1} },
|
||||||
{ MODKEY, XKB_KEY_d, incnmaster, {.i = -1} },
|
{ MODKEY, XKB_KEY_d, incnmaster, {.i = -1} },
|
||||||
{ MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} },
|
{ MODKEY, XKB_KEY_h, setmfact, {.f = -0.05} },
|
||||||
{ MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} },
|
{ MODKEY, XKB_KEY_l, setmfact, {.f = +0.05} },
|
||||||
{ MODKEY, XKB_KEY_Return, zoom, {0} },
|
{ MODKEY, XKB_KEY_Return, zoom, {0} },
|
||||||
{ MODKEY, XKB_KEY_Tab, view, {0} },
|
{ MODKEY, XKB_KEY_Tab, view, {0} },
|
||||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} },
|
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} },
|
||||||
@ -136,6 +169,7 @@ static const Key keys[] = {
|
|||||||
{ MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
|
{ MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
|
||||||
{ MODKEY, XKB_KEY_space, setlayout, {0} },
|
{ MODKEY, XKB_KEY_space, setlayout, {0} },
|
||||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
||||||
|
{ MODKEY, XKB_KEY_s, togglesticky, {0} },
|
||||||
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||||
{ MODKEY, XKB_KEY_0, view, {.ui = ~0} },
|
{ MODKEY, XKB_KEY_0, view, {.ui = ~0} },
|
||||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
|
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
|
||||||
@ -143,6 +177,14 @@ static const Key keys[] = {
|
|||||||
{ MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} },
|
{ MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} },
|
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} },
|
||||||
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} },
|
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||||
|
{ 0, XKB_KEY_XF86AudioRaiseVolume, spawn, {.v = volup} },
|
||||||
|
{ 0, XKB_KEY_XF86AudioLowerVolume, spawn, {.v = voldown} },
|
||||||
|
{ 0, XKB_KEY_XF86AudioMute, spawn, {.v = volmute} },
|
||||||
|
{ 0, XKB_KEY_XF86MonBrightnessUp, spawn, {.v = brightnessup} },
|
||||||
|
{ 0, XKB_KEY_XF86MonBrightnessDown, spawn, {.v = brightnessdown} },
|
||||||
|
{ 0, XKB_KEY_XF86AudioMicMute, spawn, {.v = mutemic} },
|
||||||
|
{ 0, XKB_KEY_Print, spawn, SHCMD("grim -g \"$(slurp)\" ~/media/screenshots/$(date +'%h%d-%H%M-ss.png')") },
|
||||||
|
{ MODKEY, XKB_KEY_q, quit, {0} },
|
||||||
TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0),
|
TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0),
|
||||||
TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1),
|
TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1),
|
||||||
TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2),
|
TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2),
|
||||||
|
@ -8,8 +8,7 @@ PREFIX = /usr/local
|
|||||||
MANDIR = $(PREFIX)/share/man
|
MANDIR = $(PREFIX)/share/man
|
||||||
DATADIR = $(PREFIX)/share
|
DATADIR = $(PREFIX)/share
|
||||||
|
|
||||||
XWAYLAND =
|
|
||||||
XLIBS =
|
|
||||||
# Uncomment to build XWayland support
|
# Uncomment to build XWayland support
|
||||||
#XWAYLAND = -DXWAYLAND
|
XWAYLAND = -DXWAYLAND
|
||||||
#XLIBS = xcb xcb-icccm
|
XLIBS = xcb xcb-icccm
|
||||||
|
171
dwl.c
171
dwl.c
@ -68,7 +68,7 @@
|
|||||||
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
||||||
#define ROUND(X) ((int)((X < 0) ? (X - 0.5) : (X + 0.5)))
|
#define ROUND(X) ((int)((X < 0) ? (X - 0.5) : (X + 0.5)))
|
||||||
#define CLEANMASK(mask) (mask & ~WLR_MODIFIER_CAPS)
|
#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)->issticky))
|
||||||
#define LENGTH(X) (sizeof X / sizeof X[0])
|
#define LENGTH(X) (sizeof X / sizeof X[0])
|
||||||
#define END(A) ((A) + LENGTH(A))
|
#define END(A) ((A) + LENGTH(A))
|
||||||
#define TAGMASK ((1u << TAGCOUNT) - 1)
|
#define TAGMASK ((1u << TAGCOUNT) - 1)
|
||||||
@ -99,7 +99,8 @@ typedef struct {
|
|||||||
} Button;
|
} Button;
|
||||||
|
|
||||||
typedef struct Monitor Monitor;
|
typedef struct Monitor Monitor;
|
||||||
typedef struct {
|
typedef struct Client Client;
|
||||||
|
struct Client {
|
||||||
/* 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 */
|
||||||
@ -134,9 +135,11 @@ typedef struct {
|
|||||||
#endif
|
#endif
|
||||||
unsigned int bw;
|
unsigned int bw;
|
||||||
uint32_t tags;
|
uint32_t tags;
|
||||||
int isfloating, isurgent, isfullscreen;
|
int isfloating, isurgent, isfullscreen, issticky, isterm, noswallow;
|
||||||
uint32_t resize; /* configure serial of a pending resize */
|
uint32_t resize; /* configure serial of a pending resize */
|
||||||
} Client;
|
pid_t pid;
|
||||||
|
Client *swallowing, *swallowedby;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t mod;
|
uint32_t mod;
|
||||||
@ -219,6 +222,8 @@ typedef struct {
|
|||||||
const char *title;
|
const char *title;
|
||||||
uint32_t tags;
|
uint32_t tags;
|
||||||
int isfloating;
|
int isfloating;
|
||||||
|
int isterm;
|
||||||
|
int noswallow;
|
||||||
int monitor;
|
int monitor;
|
||||||
} Rule;
|
} Rule;
|
||||||
|
|
||||||
@ -238,6 +243,7 @@ static void arrange(Monitor *m);
|
|||||||
static void arrangelayer(Monitor *m, struct wl_list *list,
|
static void arrangelayer(Monitor *m, struct wl_list *list,
|
||||||
struct wlr_box *usable_area, int exclusive);
|
struct wlr_box *usable_area, int exclusive);
|
||||||
static void arrangelayers(Monitor *m);
|
static void arrangelayers(Monitor *m);
|
||||||
|
static void autostartexec(void);
|
||||||
static void axisnotify(struct wl_listener *listener, void *data);
|
static void axisnotify(struct wl_listener *listener, void *data);
|
||||||
static void buttonpress(struct wl_listener *listener, void *data);
|
static void buttonpress(struct wl_listener *listener, void *data);
|
||||||
static void chvt(const Arg *arg);
|
static void chvt(const Arg *arg);
|
||||||
@ -318,6 +324,7 @@ static void tag(const Arg *arg);
|
|||||||
static void tagmon(const Arg *arg);
|
static void tagmon(const Arg *arg);
|
||||||
static void tile(Monitor *m);
|
static void tile(Monitor *m);
|
||||||
static void togglefloating(const Arg *arg);
|
static void togglefloating(const Arg *arg);
|
||||||
|
static void togglesticky(const Arg *arg);
|
||||||
static void togglefullscreen(const Arg *arg);
|
static void togglefullscreen(const Arg *arg);
|
||||||
static void toggletag(const Arg *arg);
|
static void toggletag(const Arg *arg);
|
||||||
static void toggleview(const Arg *arg);
|
static void toggleview(const Arg *arg);
|
||||||
@ -334,6 +341,10 @@ static Monitor *xytomon(double x, double y);
|
|||||||
static void xytonode(double x, double y, struct wlr_surface **psurface,
|
static void xytonode(double x, double y, struct wlr_surface **psurface,
|
||||||
Client **pc, LayerSurface **pl, double *nx, double *ny);
|
Client **pc, LayerSurface **pl, double *nx, double *ny);
|
||||||
static void zoom(const Arg *arg);
|
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 */
|
/* variables */
|
||||||
static const char broken[] = "broken";
|
static const char broken[] = "broken";
|
||||||
@ -407,6 +418,9 @@ static xcb_atom_t netatom[NetLast];
|
|||||||
/* attempt to encapsulate suck into one file */
|
/* attempt to encapsulate suck into one file */
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
|
||||||
|
static pid_t *autostart_pids;
|
||||||
|
static size_t autostart_len;
|
||||||
|
|
||||||
/* function implementations */
|
/* function implementations */
|
||||||
void
|
void
|
||||||
applybounds(Client *c, struct wlr_box *bbox)
|
applybounds(Client *c, struct wlr_box *bbox)
|
||||||
@ -445,6 +459,8 @@ applyrules(Client *c)
|
|||||||
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;
|
||||||
i = 0;
|
i = 0;
|
||||||
wl_list_for_each(m, &mons, link) {
|
wl_list_for_each(m, &mons, link) {
|
||||||
@ -541,6 +557,27 @@ arrangelayers(Monitor *m)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
autostartexec(void) {
|
||||||
|
const char *const *p;
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
/* count entries */
|
||||||
|
for (p = autostart; *p; autostart_len++, p++)
|
||||||
|
while (*++p);
|
||||||
|
|
||||||
|
autostart_pids = calloc(autostart_len, sizeof(pid_t));
|
||||||
|
for (p = autostart; *p; i++, p++) {
|
||||||
|
if ((autostart_pids[i] = fork()) == 0) {
|
||||||
|
setsid();
|
||||||
|
execvp(*p, (char *const *)p);
|
||||||
|
die("dwl: execvp %s:", *p);
|
||||||
|
}
|
||||||
|
/* skip arguments */
|
||||||
|
while (*++p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
axisnotify(struct wl_listener *listener, void *data)
|
axisnotify(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
@ -638,11 +675,21 @@ checkidleinhibitor(struct wlr_surface *exclude)
|
|||||||
void
|
void
|
||||||
cleanup(void)
|
cleanup(void)
|
||||||
{
|
{
|
||||||
|
size_t i;
|
||||||
#ifdef XWAYLAND
|
#ifdef XWAYLAND
|
||||||
wlr_xwayland_destroy(xwayland);
|
wlr_xwayland_destroy(xwayland);
|
||||||
xwayland = NULL;
|
xwayland = NULL;
|
||||||
#endif
|
#endif
|
||||||
wl_display_destroy_clients(dpy);
|
wl_display_destroy_clients(dpy);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (child_pid > 0) {
|
if (child_pid > 0) {
|
||||||
kill(child_pid, SIGTERM);
|
kill(child_pid, SIGTERM);
|
||||||
waitpid(child_pid, NULL, 0);
|
waitpid(child_pid, NULL, 0);
|
||||||
@ -957,6 +1004,7 @@ createnotify(struct wl_listener *listener, void *data)
|
|||||||
c->surface.xdg = xdg_surface;
|
c->surface.xdg = xdg_surface;
|
||||||
c->bw = borderpx;
|
c->bw = borderpx;
|
||||||
|
|
||||||
|
wl_client_get_credentials(c->surface.xdg->client->client, &c->pid, NULL, NULL);
|
||||||
wlr_xdg_toplevel_set_wm_capabilities(xdg_surface->toplevel,
|
wlr_xdg_toplevel_set_wm_capabilities(xdg_surface->toplevel,
|
||||||
WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
|
WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
|
||||||
|
|
||||||
@ -1303,23 +1351,91 @@ void
|
|||||||
handlesig(int signo)
|
handlesig(int signo)
|
||||||
{
|
{
|
||||||
if (signo == SIGCHLD) {
|
if (signo == SIGCHLD) {
|
||||||
#ifdef XWAYLAND
|
|
||||||
siginfo_t in;
|
siginfo_t in;
|
||||||
/* wlroots expects to reap the XWayland process itself, so we
|
/* wlroots expects to reap the XWayland process itself, so we
|
||||||
* use WNOWAIT to keep the child waitable until we know it's not
|
* use WNOWAIT to keep the child waitable until we know it's not
|
||||||
* XWayland.
|
* XWayland.
|
||||||
*/
|
*/
|
||||||
while (!waitid(P_ALL, 0, &in, WEXITED|WNOHANG|WNOWAIT) && in.si_pid
|
while (!waitid(P_ALL, 0, &in, WEXITED|WNOHANG|WNOWAIT) && in.si_pid
|
||||||
&& (!xwayland || in.si_pid != xwayland->server->pid))
|
#ifdef XWAYLAND
|
||||||
waitpid(in.si_pid, NULL, 0);
|
&& (!xwayland || in.si_pid != xwayland->server->pid)
|
||||||
#else
|
|
||||||
while (waitpid(-1, NULL, WNOHANG) > 0);
|
|
||||||
#endif
|
#endif
|
||||||
|
) {
|
||||||
|
pid_t *p, *lim;
|
||||||
|
waitpid(in.si_pid, NULL, 0);
|
||||||
|
if (in.si_pid == child_pid)
|
||||||
|
child_pid = -1;
|
||||||
|
if (!(p = autostart_pids))
|
||||||
|
continue;
|
||||||
|
lim = &p[autostart_len];
|
||||||
|
|
||||||
|
for (; p < lim; p++) {
|
||||||
|
if (*p == in.si_pid) {
|
||||||
|
*p = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (signo == SIGINT || signo == SIGTERM) {
|
} else if (signo == SIGINT || signo == SIGTERM) {
|
||||||
quit(NULL);
|
quit(NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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->node, 0);
|
||||||
|
wlr_scene_node_set_enabled(&c->scene->node, 1);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
incnmaster(const Arg *arg)
|
incnmaster(const Arg *arg)
|
||||||
{
|
{
|
||||||
@ -1552,6 +1668,20 @@ mapnotify(struct wl_listener *listener, void *data)
|
|||||||
}
|
}
|
||||||
printstatus();
|
printstatus();
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unset_fullscreen:
|
unset_fullscreen:
|
||||||
m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y);
|
m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y);
|
||||||
wl_list_for_each(w, &clients, link) {
|
wl_list_for_each(w, &clients, link) {
|
||||||
@ -1972,6 +2102,7 @@ run(char *startup_cmd)
|
|||||||
die("startup: backend_start");
|
die("startup: backend_start");
|
||||||
|
|
||||||
/* Now that the socket exists and the backend is started, run the startup command */
|
/* Now that the socket exists and the backend is started, run the startup command */
|
||||||
|
autostartexec();
|
||||||
if (startup_cmd) {
|
if (startup_cmd) {
|
||||||
int piperw[2];
|
int piperw[2];
|
||||||
if (pipe(piperw) < 0)
|
if (pipe(piperw) < 0)
|
||||||
@ -2506,6 +2637,16 @@ togglefloating(const Arg *arg)
|
|||||||
setfloating(sel, !sel->isfloating);
|
setfloating(sel, !sel->isfloating);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
togglesticky(const Arg *arg)
|
||||||
|
{
|
||||||
|
Client *sel = focustop(selmon);
|
||||||
|
if (!sel)
|
||||||
|
return;
|
||||||
|
sel->issticky = !sel->issticky;
|
||||||
|
arrange(selmon);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
togglefullscreen(const Arg *arg)
|
togglefullscreen(const Arg *arg)
|
||||||
{
|
{
|
||||||
@ -2574,6 +2715,18 @@ unmapnotify(struct wl_listener *listener, void *data)
|
|||||||
grabc = NULL;
|
grabc = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (c->swallowing) {
|
||||||
|
c->swallowing->swallowedby = NULL;
|
||||||
|
c->swallowing = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->swallowedby) {
|
||||||
|
setfullscreen(c->swallowedby, 0);
|
||||||
|
swallow(c->swallowedby, c);
|
||||||
|
c->swallowedby->swallowing = NULL;
|
||||||
|
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;
|
||||||
|
154
patches/autostart.patch
Normal file
154
patches/autostart.patch
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
From 51d56a433f23e13ac711b283a03c7903068febf6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?=
|
||||||
|
<leohdz172@proton.me>
|
||||||
|
Date: Sat, 8 Jul 2023 17:11:36 -0600
|
||||||
|
Subject: [PATCH] port autostart patch from dwm
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
https://dwm.suckless.org/patches/cool_autostart/
|
||||||
|
Signed-off-by: Leonardo Hernández Hernández <leohdz172@proton.me>
|
||||||
|
---
|
||||||
|
config.def.h | 7 +++++++
|
||||||
|
dwl.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++-----
|
||||||
|
2 files changed, 61 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/config.def.h b/config.def.h
|
||||||
|
index a8ed61d..3585711 100644
|
||||||
|
--- a/config.def.h
|
||||||
|
+++ b/config.def.h
|
||||||
|
@@ -20,6 +20,13 @@ static const float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0}; /* You can al
|
||||||
|
/* logging */
|
||||||
|
static int log_level = WLR_ERROR;
|
||||||
|
|
||||||
|
+/* Autostart */
|
||||||
|
+static const char *const autostart[] = {
|
||||||
|
+ "wbg", "/path/to/your/image", NULL,
|
||||||
|
+ NULL /* terminate */
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+
|
||||||
|
static const Rule rules[] = {
|
||||||
|
/* app_id title tags mask isfloating monitor */
|
||||||
|
/* examples:
|
||||||
|
diff --git a/dwl.c b/dwl.c
|
||||||
|
index 10d5a5b..bbbef2b 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -236,6 +236,7 @@ static void arrange(Monitor *m);
|
||||||
|
static void arrangelayer(Monitor *m, struct wl_list *list,
|
||||||
|
struct wlr_box *usable_area, int exclusive);
|
||||||
|
static void arrangelayers(Monitor *m);
|
||||||
|
+static void autostartexec(void);
|
||||||
|
static void axisnotify(struct wl_listener *listener, void *data);
|
||||||
|
static void buttonpress(struct wl_listener *listener, void *data);
|
||||||
|
static void chvt(const Arg *arg);
|
||||||
|
@@ -403,6 +404,9 @@ static xcb_atom_t netatom[NetLast];
|
||||||
|
/* attempt to encapsulate suck into one file */
|
||||||
|
#include "client.h"
|
||||||
|
|
||||||
|
+static pid_t *autostart_pids;
|
||||||
|
+static size_t autostart_len;
|
||||||
|
+
|
||||||
|
/* function implementations */
|
||||||
|
void
|
||||||
|
applybounds(Client *c, struct wlr_box *bbox)
|
||||||
|
@@ -533,6 +537,27 @@ arrangelayers(Monitor *m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+void
|
||||||
|
+autostartexec(void) {
|
||||||
|
+ const char *const *p;
|
||||||
|
+ size_t i = 0;
|
||||||
|
+
|
||||||
|
+ /* count entries */
|
||||||
|
+ for (p = autostart; *p; autostart_len++, p++)
|
||||||
|
+ while (*++p);
|
||||||
|
+
|
||||||
|
+ autostart_pids = calloc(autostart_len, sizeof(pid_t));
|
||||||
|
+ for (p = autostart; *p; i++, p++) {
|
||||||
|
+ if ((autostart_pids[i] = fork()) == 0) {
|
||||||
|
+ setsid();
|
||||||
|
+ execvp(*p, (char *const *)p);
|
||||||
|
+ die("dwl: execvp %s:", *p);
|
||||||
|
+ }
|
||||||
|
+ /* skip arguments */
|
||||||
|
+ while (*++p);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void
|
||||||
|
axisnotify(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
@@ -630,11 +655,21 @@ checkidleinhibitor(struct wlr_surface *exclude)
|
||||||
|
void
|
||||||
|
cleanup(void)
|
||||||
|
{
|
||||||
|
+ size_t i;
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
wlr_xwayland_destroy(xwayland);
|
||||||
|
xwayland = NULL;
|
||||||
|
#endif
|
||||||
|
wl_display_destroy_clients(dpy);
|
||||||
|
+
|
||||||
|
+ /* 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);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (child_pid > 0) {
|
||||||
|
kill(child_pid, SIGTERM);
|
||||||
|
waitpid(child_pid, NULL, 0);
|
||||||
|
@@ -1294,18 +1329,31 @@ void
|
||||||
|
handlesig(int signo)
|
||||||
|
{
|
||||||
|
if (signo == SIGCHLD) {
|
||||||
|
-#ifdef XWAYLAND
|
||||||
|
siginfo_t in;
|
||||||
|
/* wlroots expects to reap the XWayland process itself, so we
|
||||||
|
* use WNOWAIT to keep the child waitable until we know it's not
|
||||||
|
* XWayland.
|
||||||
|
*/
|
||||||
|
while (!waitid(P_ALL, 0, &in, WEXITED|WNOHANG|WNOWAIT) && in.si_pid
|
||||||
|
- && (!xwayland || in.si_pid != xwayland->server->pid))
|
||||||
|
- waitpid(in.si_pid, NULL, 0);
|
||||||
|
-#else
|
||||||
|
- while (waitpid(-1, NULL, WNOHANG) > 0);
|
||||||
|
+#ifdef XWAYLAND
|
||||||
|
+ && (!xwayland || in.si_pid != xwayland->server->pid)
|
||||||
|
#endif
|
||||||
|
+ ) {
|
||||||
|
+ pid_t *p, *lim;
|
||||||
|
+ waitpid(in.si_pid, NULL, 0);
|
||||||
|
+ if (in.si_pid == child_pid)
|
||||||
|
+ child_pid = -1;
|
||||||
|
+ if (!(p = autostart_pids))
|
||||||
|
+ continue;
|
||||||
|
+ lim = &p[autostart_len];
|
||||||
|
+
|
||||||
|
+ for (; p < lim; p++) {
|
||||||
|
+ if (*p == in.si_pid) {
|
||||||
|
+ *p = -1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
} else if (signo == SIGINT || signo == SIGTERM) {
|
||||||
|
quit(NULL);
|
||||||
|
}
|
||||||
|
@@ -1965,6 +2013,7 @@ run(char *startup_cmd)
|
||||||
|
die("startup: backend_start");
|
||||||
|
|
||||||
|
/* Now that the socket exists and the backend is started, run the startup command */
|
||||||
|
+ autostartexec();
|
||||||
|
if (startup_cmd) {
|
||||||
|
int piperw[2];
|
||||||
|
if (pipe(piperw) < 0)
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
69
patches/main...dm1tz:04-sticky.patch
Normal file
69
patches/main...dm1tz:04-sticky.patch
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
From 7ba760ab76353e9344a08902a5b12acb431d3843 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Dmitry Zakharchenko <dmitz@disroot.org>
|
||||||
|
Date: Wed, 4 Jan 2023 00:25:55 +0200
|
||||||
|
Subject: [PATCH] sticky: sync with 0.4
|
||||||
|
|
||||||
|
---
|
||||||
|
config.def.h | 1 +
|
||||||
|
dwl.c | 15 +++++++++++++--
|
||||||
|
2 files changed, 14 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/config.def.h b/config.def.h
|
||||||
|
index a4f7c13d0..120c27aa1 100644
|
||||||
|
--- a/config.def.h
|
||||||
|
+++ b/config.def.h
|
||||||
|
@@ -126,6 +126,7 @@ static const Key keys[] = {
|
||||||
|
{ MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
|
||||||
|
{ MODKEY, XKB_KEY_space, setlayout, {0} },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
||||||
|
+ { MODKEY, XKB_KEY_s, togglesticky, {0} },
|
||||||
|
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||||
|
{ MODKEY, XKB_KEY_0, view, {.ui = ~0} },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
|
||||||
|
diff --git a/dwl.c b/dwl.c
|
||||||
|
index 19bb6ce34..ec8c4282d 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -64,7 +64,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)->issticky))
|
||||||
|
#define LENGTH(X) (sizeof X / sizeof X[0])
|
||||||
|
#define END(A) ((A) + LENGTH(A))
|
||||||
|
#define TAGMASK ((1 << LENGTH(tags)) - 1)
|
||||||
|
@@ -124,7 +124,7 @@ typedef struct {
|
||||||
|
#endif
|
||||||
|
unsigned int bw;
|
||||||
|
unsigned int tags;
|
||||||
|
- int isfloating, isurgent, isfullscreen;
|
||||||
|
+ int isfloating, isurgent, isfullscreen, issticky;
|
||||||
|
uint32_t resize; /* configure serial of a pending resize */
|
||||||
|
} Client;
|
||||||
|
|
||||||
|
@@ -295,6 +295,7 @@ static void tag(const Arg *arg);
|
||||||
|
static void tagmon(const Arg *arg);
|
||||||
|
static void tile(Monitor *m);
|
||||||
|
static void togglefloating(const Arg *arg);
|
||||||
|
+static void togglesticky(const Arg *arg);
|
||||||
|
static void togglefullscreen(const Arg *arg);
|
||||||
|
static void toggletag(const Arg *arg);
|
||||||
|
static void toggleview(const Arg *arg);
|
||||||
|
@@ -2337,6 +2338,16 @@ togglefloating(const Arg *arg)
|
||||||
|
setfloating(sel, !sel->isfloating);
|
||||||
|
}
|
||||||
|
|
||||||
|
+void
|
||||||
|
+togglesticky(const Arg *arg)
|
||||||
|
+{
|
||||||
|
+ Client *sel = focustop(selmon);
|
||||||
|
+ if (!sel)
|
||||||
|
+ return;
|
||||||
|
+ sel->issticky = !sel->issticky;
|
||||||
|
+ arrange(selmon);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void
|
||||||
|
togglefullscreen(const Arg *arg)
|
||||||
|
{
|
197
patches/main...dm1tz:04-swallow.patch
Normal file
197
patches/main...dm1tz:04-swallow.patch
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
From bc61a2cc74f65ab5bba51ba65edc1efd1269d510 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Dmitry Zakharchenko <dmitz@disroot.org>
|
||||||
|
Date: Thu, 5 Jan 2023 14:57:48 +0200
|
||||||
|
Subject: [PATCH] swallow: sync with 0.4
|
||||||
|
|
||||||
|
---
|
||||||
|
config.def.h | 6 ++--
|
||||||
|
dwl.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++--
|
||||||
|
2 files changed, 100 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/config.def.h b/config.def.h
|
||||||
|
index a4f7c13d0..9dcedacd4 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 19bb6ce34..262fa62c7 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -95,7 +95,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 */
|
||||||
|
@@ -124,9 +125,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 mod;
|
||||||
|
@@ -201,6 +204,8 @@ typedef struct {
|
||||||
|
const char *title;
|
||||||
|
unsigned int tags;
|
||||||
|
int isfloating;
|
||||||
|
+ int isterm;
|
||||||
|
+ int noswallow;
|
||||||
|
int monitor;
|
||||||
|
} Rule;
|
||||||
|
|
||||||
|
@@ -310,6 +315,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";
|
||||||
|
@@ -453,6 +462,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)
|
||||||
|
@@ -990,6 +1001,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);
|
||||||
|
@@ -1308,6 +1321,61 @@ fullscreennotify(struct wl_listener *listener, void *data)
|
||||||
|
setfullscreen(c, client_wants_fullscreen(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
+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->node, 0);
|
||||||
|
+ wlr_scene_node_set_enabled(&c->scene->node, 1);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void
|
||||||
|
incnmaster(const Arg *arg)
|
||||||
|
{
|
||||||
|
@@ -1528,6 +1596,20 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||||
|
}
|
||||||
|
printstatus();
|
||||||
|
|
||||||
|
+ 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);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
unset_fullscreen:
|
||||||
|
m = c->mon ? c->mon : xytomon(c->geom.x, c->geom.y);
|
||||||
|
wl_list_for_each(w, &clients, link)
|
||||||
|
@@ -2409,6 +2491,18 @@ unmapnotify(struct wl_listener *listener, void *data)
|
||||||
|
grabc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (c->swallowing) {
|
||||||
|
+ c->swallowing->swallowedby = NULL;
|
||||||
|
+ c->swallowing = NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (c->swallowedby) {
|
||||||
|
+ setfullscreen(c->swallowedby, 0);
|
||||||
|
+ swallow(c->swallowedby, c);
|
||||||
|
+ c->swallowedby->swallowing = NULL;
|
||||||
|
+ c->swallowedby = NULL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (client_is_unmanaged(c)) {
|
||||||
|
if (c == exclusive_focus)
|
||||||
|
exclusive_focus = NULL;
|
Loading…
Reference in New Issue
Block a user