This commit is contained in:
coast 2025-08-11 16:38:32 +03:30
parent 3e5bc6ba9a
commit c57ac5c106
10 changed files with 373 additions and 6 deletions

View file

@ -146,6 +146,8 @@ static const Key keys[] = {
{ MODKEY, XKB_KEY_b, togglebar, {0} },
{ MODKEY, XKB_KEY_j, focusstack, {.i = +1} },
{ MODKEY, XKB_KEY_k, focusstack, {.i = -1} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_J, movestack, {.i = +1} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_K, movestack, {.i = -1} },
{ MODKEY, XKB_KEY_i, incnmaster, {.i = +1} },
{ MODKEY, XKB_KEY_d, incnmaster, {.i = -1} },
{ MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} },
@ -160,6 +162,14 @@ 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_Down, moveresizekb, {.v = (int []){ 0, 40, 0, 0 }}},
{ MODKEY, XKB_KEY_Up, moveresizekb, {.v = (int []){ 0, -40, 0, 0 }}},
{ MODKEY, XKB_KEY_Right, moveresizekb, {.v = (int []){ 40, 0, 0, 0 }}},
{ MODKEY, XKB_KEY_Left, moveresizekb, {.v = (int []){ -40, 0, 0, 0 }}},
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Down, moveresizekb, {.v = (int []){ 0, 0, 0, 40 }}},
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Up, moveresizekb, {.v = (int []){ 0, 0, 0, -40 }}},
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Right, moveresizekb, {.v = (int []){ 0, 0, 40, 0 }}},
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Left, moveresizekb, {.v = (int []){ 0, 0, -40, 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} },

View file

@ -29,6 +29,13 @@ static char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
/* logging */
static int log_level = WLR_ERROR;
/* Autostart */
static const char *const autostart[] = {
"wbg", "/path/to/your/image", NULL,
NULL /* terminate */
};
/* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */
static const Rule rules[] = {
/* app_id title tags mask isfloating monitor */
@ -153,6 +160,14 @@ 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_Down, moveresizekb, {.v = (int []){ 0, 40, 0, 0 }}},
{ MODKEY, XKB_KEY_Up, moveresizekb, {.v = (int []){ 0, -40, 0, 0 }}},
{ MODKEY, XKB_KEY_Right, moveresizekb, {.v = (int []){ 40, 0, 0, 0 }}},
{ MODKEY, XKB_KEY_Left, moveresizekb, {.v = (int []){ -40, 0, 0, 0 }}},
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Down, moveresizekb, {.v = (int []){ 0, 0, 0, 40 }}},
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Up, moveresizekb, {.v = (int []){ 0, 0, 0, -40 }}},
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Right, moveresizekb, {.v = (int []){ 0, 0, 40, 0 }}},
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Left, moveresizekb, {.v = (int []){ 0, 0, -40, 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} },

View file

@ -313,6 +313,7 @@ static void destroylayersurfacenotify(struct wl_listener *listener, void *data);
static void destroylock(SessionLock *lock, int unlocked);
static void destroylocksurface(struct wl_listener *listener, void *data);
static void destroynotify(struct wl_listener *listener, void *data);
static void moveresizekb(const Arg *arg);
static void destroypointerconstraint(struct wl_listener *listener, void *data);
static void destroysessionlock(struct wl_listener *listener, void *data);
static void destroysessionmgr(struct wl_listener *listener, void *data);
@ -338,6 +339,7 @@ static void locksession(struct wl_listener *listener, void *data);
static void mapnotify(struct wl_listener *listener, void *data);
static void maximizenotify(struct wl_listener *listener, void *data);
static void monocle(Monitor *m);
static void movestack(const Arg *arg);
static void motionabsolute(struct wl_listener *listener, void *data);
static void motionnotify(uint32_t time, struct wlr_input_device *device, double sx,
double sy, double sx_unaccel, double sy_unaccel);
@ -389,6 +391,7 @@ static void urgent(struct wl_listener *listener, void *data);
static void view(const Arg *arg);
static void virtualkeyboard(struct wl_listener *listener, void *data);
static void virtualpointer(struct wl_listener *listener, void *data);
static void warpcursor(const Client *c);
static Monitor *xytomon(double x, double y);
static void xytonode(double x, double y, struct wlr_surface **psurface,
Client **pc, LayerSurface **pl, double *nx, double *ny);
@ -569,6 +572,7 @@ arrange(Monitor *m)
m->lt[m->sellt]->arrange(m);
motionnotify(0, NULL, 0, 0, 0, 0);
checkidleinhibitor(NULL);
warpcursor(focustop(selmon));
}
void
@ -1627,6 +1631,10 @@ focusclient(Client *c, int lift)
if (locked)
return;
/* Warp cursor to center of client if it is outside */
if (lift)
warpcursor(c);
/* Raise client in stacking order if requested */
if (c && lift)
wlr_scene_node_raise_to_top(&c->scene->node);
@ -2080,6 +2088,48 @@ monocle(Monitor *m)
wlr_scene_node_raise_to_top(&c->scene->node);
}
void
movestack(const Arg *arg)
{
Client *c, *sel = focustop(selmon);
if (!sel) {
return;
}
if (wl_list_length(&clients) <= 1) {
return;
}
if (arg->i > 0) {
wl_list_for_each(c, &sel->link, link) {
if (&c->link == &clients) {
c = wl_container_of(&clients, c, link);
break; /* wrap past the sentinel node */
}
if (VISIBLEON(c, selmon) || &c->link == &clients) {
break; /* found it */
}
}
} else {
wl_list_for_each_reverse(c, &sel->link, link) {
if (&c->link == &clients) {
c = wl_container_of(&clients, c, link);
break; /* wrap past the sentinel node */
}
if (VISIBLEON(c, selmon) || &c->link == &clients) {
break; /* found it */
}
}
/* backup one client */
c = wl_container_of(c->link.prev, c, link);
}
wl_list_remove(&sel->link);
wl_list_insert(&c->link, &sel->link);
arrange(selmon);
}
void
motionabsolute(struct wl_listener *listener, void *data)
{
@ -3036,6 +3086,24 @@ togglegaps(const Arg *arg)
arrange(selmon);
}
void
moveresizekb(const Arg *arg)
{
Client *c = focustop(selmon);
Monitor *m = selmon;
if(!(m && arg && arg->v && c && c->isfloating)) {
return;
}
resize(c, (struct wlr_box){
.x = c->geom.x + ((int *)arg->v)[0],
.y = c->geom.y + ((int *)arg->v)[1],
.width = c->geom.width + ((int *)arg->v)[2],
.height = c->geom.height + ((int *)arg->v)[3],
}, 1);
}
void
toggletag(const Arg *arg)
{
@ -3320,6 +3388,27 @@ virtualpointer(struct wl_listener *listener, void *data)
wlr_cursor_map_input_to_output(cursor, device, event->suggested_output);
}
void
warpcursor(const Client *c) {
if (cursor_mode != CurNormal) {
return;
}
if (!c && selmon) {
wlr_cursor_warp_closest(cursor,
NULL,
selmon->w.x + selmon->w.width / 2.0 ,
selmon->w.y + selmon->w.height / 2.0);
}
else if ( c && (cursor->x < c->geom.x ||
cursor->x > c->geom.x + c->geom.width ||
cursor->y < c->geom.y ||
cursor->y > c->geom.y + c->geom.height))
wlr_cursor_warp_closest(cursor,
NULL,
c->geom.x + c->geom.width / 2.0,
c->geom.y + c->geom.height / 2.0);
}
Monitor *
xytomon(double x, double y)
{

View file

@ -274,6 +274,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 bool baracceptsinput(struct wlr_scene_buffer *buffer, double *sx, double *sy);
static void bufdestroy(struct wlr_buffer *buffer);
@ -312,6 +313,7 @@ static void destroylayersurfacenotify(struct wl_listener *listener, void *data);
static void destroylock(SessionLock *lock, int unlocked);
static void destroylocksurface(struct wl_listener *listener, void *data);
static void destroynotify(struct wl_listener *listener, void *data);
static void moveresizekb(const Arg *arg);
static void destroypointerconstraint(struct wl_listener *listener, void *data);
static void destroysessionlock(struct wl_listener *listener, void *data);
static void destroysessionmgr(struct wl_listener *listener, void *data);
@ -337,6 +339,7 @@ static void locksession(struct wl_listener *listener, void *data);
static void mapnotify(struct wl_listener *listener, void *data);
static void maximizenotify(struct wl_listener *listener, void *data);
static void monocle(Monitor *m);
static void movestack(const Arg *arg);
static void motionabsolute(struct wl_listener *listener, void *data);
static void motionnotify(uint32_t time, struct wlr_input_device *device, double sx,
double sy, double sx_unaccel, double sy_unaccel);
@ -478,6 +481,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)
@ -631,6 +637,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)
{
@ -829,11 +856,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);
@ -1742,18 +1779,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);
}
@ -2032,6 +2082,48 @@ monocle(Monitor *m)
wlr_scene_node_raise_to_top(&c->scene->node);
}
void
movestack(const Arg *arg)
{
Client *c, *sel = focustop(selmon);
if (!sel) {
return;
}
if (wl_list_length(&clients) <= 1) {
return;
}
if (arg->i > 0) {
wl_list_for_each(c, &sel->link, link) {
if (&c->link == &clients) {
c = wl_container_of(&clients, c, link);
break; /* wrap past the sentinel node */
}
if (VISIBLEON(c, selmon) || &c->link == &clients) {
break; /* found it */
}
}
} else {
wl_list_for_each_reverse(c, &sel->link, link) {
if (&c->link == &clients) {
c = wl_container_of(&clients, c, link);
break; /* wrap past the sentinel node */
}
if (VISIBLEON(c, selmon) || &c->link == &clients) {
break; /* found it */
}
}
/* backup one client */
c = wl_container_of(c->link.prev, c, link);
}
wl_list_remove(&sel->link);
wl_list_insert(&c->link, &sel->link);
arrange(selmon);
}
void
motionabsolute(struct wl_listener *listener, void *data)
{
@ -2433,6 +2525,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) {
if ((child_pid = fork()) < 0)
die("startup: fork:");
@ -2987,6 +3080,24 @@ togglegaps(const Arg *arg)
arrange(selmon);
}
void
moveresizekb(const Arg *arg)
{
Client *c = focustop(selmon);
Monitor *m = selmon;
if(!(m && arg && arg->v && c && c->isfloating)) {
return;
}
resize(c, (struct wlr_box){
.x = c->geom.x + ((int *)arg->v)[0],
.y = c->geom.y + ((int *)arg->v)[1],
.width = c->geom.width + ((int *)arg->v)[2],
.height = c->geom.height + ((int *)arg->v)[3],
}, 1);
}
void
toggletag(const Arg *arg)
{

BIN
dwl.o Normal file

Binary file not shown.

View file

@ -146,6 +146,8 @@ static const Key keys[] = {
{ MODKEY, XKB_KEY_b, togglebar, {0} },
{ MODKEY, XKB_KEY_j, focusstack, {.i = +1} },
{ MODKEY, XKB_KEY_k, focusstack, {.i = -1} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_J, movestack, {.i = +1} },
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_K, movestack, {.i = -1} },
{ MODKEY, XKB_KEY_i, incnmaster, {.i = +1} },
{ MODKEY, XKB_KEY_d, incnmaster, {.i = -1} },
{ MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} },

View file

@ -160,6 +160,14 @@ 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_Down, moveresizekb, {.v = (int []){ 0, 40, 0, 0 }}},
{ MODKEY, XKB_KEY_Up, moveresizekb, {.v = (int []){ 0, -40, 0, 0 }}},
{ MODKEY, XKB_KEY_Right, moveresizekb, {.v = (int []){ 40, 0, 0, 0 }}},
{ MODKEY, XKB_KEY_Left, moveresizekb, {.v = (int []){ -40, 0, 0, 0 }}},
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Down, moveresizekb, {.v = (int []){ 0, 0, 0, 40 }}},
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Up, moveresizekb, {.v = (int []){ 0, 0, 0, -40 }}},
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Right, moveresizekb, {.v = (int []){ 0, 0, 40, 0 }}},
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Left, moveresizekb, {.v = (int []){ 0, 0, -40, 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} },

View file

@ -14,4 +14,4 @@ XLIBS =
XWAYLAND = -DXWAYLAND
XLIBS = xcb xcb-icccm
CC = gcc
CC = /usr/lib/llvm/20/bin/clang

View file

@ -339,6 +339,7 @@ static void locksession(struct wl_listener *listener, void *data);
static void mapnotify(struct wl_listener *listener, void *data);
static void maximizenotify(struct wl_listener *listener, void *data);
static void monocle(Monitor *m);
static void movestack(const Arg *arg);
static void motionabsolute(struct wl_listener *listener, void *data);
static void motionnotify(uint32_t time, struct wlr_input_device *device, double sx,
double sy, double sx_unaccel, double sy_unaccel);
@ -390,6 +391,7 @@ static void urgent(struct wl_listener *listener, void *data);
static void view(const Arg *arg);
static void virtualkeyboard(struct wl_listener *listener, void *data);
static void virtualpointer(struct wl_listener *listener, void *data);
static void warpcursor(const Client *c);
static Monitor *xytomon(double x, double y);
static void xytonode(double x, double y, struct wlr_surface **psurface,
Client **pc, LayerSurface **pl, double *nx, double *ny);
@ -570,6 +572,7 @@ arrange(Monitor *m)
m->lt[m->sellt]->arrange(m);
motionnotify(0, NULL, 0, 0, 0, 0);
checkidleinhibitor(NULL);
warpcursor(focustop(selmon));
}
void
@ -1628,6 +1631,10 @@ focusclient(Client *c, int lift)
if (locked)
return;
/* Warp cursor to center of client if it is outside */
if (lift)
warpcursor(c);
/* Raise client in stacking order if requested */
if (c && lift)
wlr_scene_node_raise_to_top(&c->scene->node);
@ -2081,6 +2088,48 @@ monocle(Monitor *m)
wlr_scene_node_raise_to_top(&c->scene->node);
}
void
movestack(const Arg *arg)
{
Client *c, *sel = focustop(selmon);
if (!sel) {
return;
}
if (wl_list_length(&clients) <= 1) {
return;
}
if (arg->i > 0) {
wl_list_for_each(c, &sel->link, link) {
if (&c->link == &clients) {
c = wl_container_of(&clients, c, link);
break; /* wrap past the sentinel node */
}
if (VISIBLEON(c, selmon) || &c->link == &clients) {
break; /* found it */
}
}
} else {
wl_list_for_each_reverse(c, &sel->link, link) {
if (&c->link == &clients) {
c = wl_container_of(&clients, c, link);
break; /* wrap past the sentinel node */
}
if (VISIBLEON(c, selmon) || &c->link == &clients) {
break; /* found it */
}
}
/* backup one client */
c = wl_container_of(c->link.prev, c, link);
}
wl_list_remove(&sel->link);
wl_list_insert(&c->link, &sel->link);
arrange(selmon);
}
void
motionabsolute(struct wl_listener *listener, void *data)
{
@ -3339,6 +3388,27 @@ virtualpointer(struct wl_listener *listener, void *data)
wlr_cursor_map_input_to_output(cursor, device, event->suggested_output);
}
void
warpcursor(const Client *c) {
if (cursor_mode != CurNormal) {
return;
}
if (!c && selmon) {
wlr_cursor_warp_closest(cursor,
NULL,
selmon->w.x + selmon->w.width / 2.0 ,
selmon->w.y + selmon->w.height / 2.0);
}
else if ( c && (cursor->x < c->geom.x ||
cursor->x > c->geom.x + c->geom.width ||
cursor->y < c->geom.y ||
cursor->y > c->geom.y + c->geom.height))
wlr_cursor_warp_closest(cursor,
NULL,
c->geom.x + c->geom.width / 2.0,
c->geom.y + c->geom.height / 2.0);
}
Monitor *
xytomon(double x, double y)
{

View file

@ -313,6 +313,7 @@ static void destroylayersurfacenotify(struct wl_listener *listener, void *data);
static void destroylock(SessionLock *lock, int unlocked);
static void destroylocksurface(struct wl_listener *listener, void *data);
static void destroynotify(struct wl_listener *listener, void *data);
static void moveresizekb(const Arg *arg);
static void destroypointerconstraint(struct wl_listener *listener, void *data);
static void destroysessionlock(struct wl_listener *listener, void *data);
static void destroysessionmgr(struct wl_listener *listener, void *data);
@ -338,6 +339,7 @@ static void locksession(struct wl_listener *listener, void *data);
static void mapnotify(struct wl_listener *listener, void *data);
static void maximizenotify(struct wl_listener *listener, void *data);
static void monocle(Monitor *m);
static void movestack(const Arg *arg);
static void motionabsolute(struct wl_listener *listener, void *data);
static void motionnotify(uint32_t time, struct wlr_input_device *device, double sx,
double sy, double sx_unaccel, double sy_unaccel);
@ -2080,6 +2082,48 @@ monocle(Monitor *m)
wlr_scene_node_raise_to_top(&c->scene->node);
}
void
movestack(const Arg *arg)
{
Client *c, *sel = focustop(selmon);
if (!sel) {
return;
}
if (wl_list_length(&clients) <= 1) {
return;
}
if (arg->i > 0) {
wl_list_for_each(c, &sel->link, link) {
if (&c->link == &clients) {
c = wl_container_of(&clients, c, link);
break; /* wrap past the sentinel node */
}
if (VISIBLEON(c, selmon) || &c->link == &clients) {
break; /* found it */
}
}
} else {
wl_list_for_each_reverse(c, &sel->link, link) {
if (&c->link == &clients) {
c = wl_container_of(&clients, c, link);
break; /* wrap past the sentinel node */
}
if (VISIBLEON(c, selmon) || &c->link == &clients) {
break; /* found it */
}
}
/* backup one client */
c = wl_container_of(c->link.prev, c, link);
}
wl_list_remove(&sel->link);
wl_list_insert(&c->link, &sel->link);
arrange(selmon);
}
void
motionabsolute(struct wl_listener *listener, void *data)
{
@ -3036,6 +3080,24 @@ togglegaps(const Arg *arg)
arrange(selmon);
}
void
moveresizekb(const Arg *arg)
{
Client *c = focustop(selmon);
Monitor *m = selmon;
if(!(m && arg && arg->v && c && c->isfloating)) {
return;
}
resize(c, (struct wlr_box){
.x = c->geom.x + ((int *)arg->v)[0],
.y = c->geom.y + ((int *)arg->v)[1],
.width = c->geom.width + ((int *)arg->v)[2],
.height = c->geom.height + ((int *)arg->v)[3],
}, 1);
}
void
toggletag(const Arg *arg)
{