Merge branch 'main' into wlroots-next

This commit is contained in:
Leonardo Hernández Hernández 2022-12-24 18:04:41 -06:00
commit b39d270b9f
No known key found for this signature in database
GPG key ID: E538897EE11B9624
3 changed files with 84 additions and 58 deletions

View file

@ -141,7 +141,7 @@ client_set_bounds(Client *c, int32_t width, int32_t height)
return 0; return 0;
#endif #endif
if (c->surface.xdg->client->shell->version >= if (c->surface.xdg->client->shell->version >=
XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION) XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION && width >= 0 && height >= 0)
return wlr_xdg_toplevel_set_bounds(c->surface.xdg->toplevel, width, height); return wlr_xdg_toplevel_set_bounds(c->surface.xdg->toplevel, width, height);
return 0; return 0;
} }
@ -240,6 +240,47 @@ client_is_mapped(Client *c)
return c->surface.xdg->mapped; return c->surface.xdg->mapped;
} }
static inline int
client_is_rendered_on_mon(Client *c, Monitor *m)
{
/* This is needed for when you don't want to check formal assignment,
* but rather actual displaying of the pixels.
* Usually VISIBLEON suffices and is also faster. */
struct wlr_surface_output *s;
if (!c->scene->node.enabled)
return 0;
wl_list_for_each(s, &client_surface(c)->current_outputs, link)
if (s->output == m->wlr_output)
return 1;
return 0;
}
static inline int
client_is_stopped(Client *c)
{
int pid;
siginfo_t in = {0};
#ifdef XWAYLAND
if (client_is_x11(c))
return 0;
#endif
wl_client_get_credentials(c->surface.xdg->client->client, &pid, NULL, NULL);
if (waitid(P_PID, pid, &in, WNOHANG|WCONTINUED|WSTOPPED|WNOWAIT) < 0) {
/* This process is not our child process, while is very unluckely that
* it is stopped, in order to do not skip frames assume that it is. */
if (errno == ECHILD)
return 1;
} else if (in.si_pid) {
if (in.si_code == CLD_STOPPED || in.si_code == CLD_TRAPPED)
return 1;
if (in.si_code == CLD_CONTINUED)
return 0;
}
return 0;
}
static inline int static inline int
client_is_unmanaged(Client *c) client_is_unmanaged(Client *c)
{ {
@ -304,6 +345,9 @@ client_set_size(Client *c, uint32_t width, uint32_t height)
return 0; return 0;
} }
#endif #endif
if (width == c->surface.xdg->toplevel->current.width
&& height ==c->surface.xdg->toplevel->current.height)
return 0;
return wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, width, height); return wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, width, height);
} }

View file

@ -1,4 +1,4 @@
_VERSION = 0.4-rc2 _VERSION = 0.4-rc3
VERSION = `git describe --long --tags --dirty 2>/dev/null || echo $(_VERSION)` VERSION = `git describe --long --tags --dirty 2>/dev/null || echo $(_VERSION)`
PKG_CONFIG = pkg-config PKG_CONFIG = pkg-config

94
dwl.c
View file

@ -186,7 +186,6 @@ struct Monitor {
unsigned int tagset[2]; unsigned int tagset[2];
double mfact; double mfact;
int nmaster; int nmaster;
int un_map; /* If a map/unmap happened on this monitor, then this should be true */
}; };
typedef struct { typedef struct {
@ -232,6 +231,7 @@ static void cleanupmon(struct wl_listener *listener, void *data);
static void closemon(Monitor *m); static void closemon(Monitor *m);
static void commitlayersurfacenotify(struct wl_listener *listener, void *data); static void commitlayersurfacenotify(struct wl_listener *listener, void *data);
static void commitnotify(struct wl_listener *listener, void *data); static void commitnotify(struct wl_listener *listener, void *data);
static void createdecoration(struct wl_listener *listener, void *data);
static void createidleinhibitor(struct wl_listener *listener, void *data); static void createidleinhibitor(struct wl_listener *listener, void *data);
static void createkeyboard(struct wlr_keyboard *keyboard); static void createkeyboard(struct wlr_keyboard *keyboard);
static void createlayersurface(struct wl_listener *listener, void *data); static void createlayersurface(struct wl_listener *listener, void *data);
@ -282,7 +282,6 @@ static void requeststartdrag(struct wl_listener *listener, void *data);
static void requestmonstate(struct wl_listener *listener, void *data); static void requestmonstate(struct wl_listener *listener, void *data);
static void resize(Client *c, struct wlr_box geo, int interact); static void resize(Client *c, struct wlr_box geo, int interact);
static void run(char *startup_cmd); static void run(char *startup_cmd);
static Client *selclient(void);
static void setcursor(struct wl_listener *listener, void *data); static void setcursor(struct wl_listener *listener, void *data);
static void setfloating(Client *c, int floating); static void setfloating(Client *c, int floating);
static void setfullscreen(Client *c, int fullscreen); static void setfullscreen(Client *c, int fullscreen);
@ -331,6 +330,7 @@ static struct wlr_session *session;
static struct wlr_xdg_shell *xdg_shell; static struct wlr_xdg_shell *xdg_shell;
static struct wlr_xdg_activation_v1 *activation; static struct wlr_xdg_activation_v1 *activation;
static struct wlr_xdg_decoration_manager_v1 *xdg_decoration_mgr;
static struct wl_list clients; /* tiling order */ static struct wl_list clients; /* tiling order */
static struct wl_list fstack; /* focus order */ static struct wl_list fstack; /* focus order */
static struct wlr_idle *idle; static struct wlr_idle *idle;
@ -373,6 +373,7 @@ static struct wl_listener new_input = {.notify = inputdevice};
static struct wl_listener new_virtual_keyboard = {.notify = virtualkeyboard}; static struct wl_listener new_virtual_keyboard = {.notify = virtualkeyboard};
static struct wl_listener new_output = {.notify = createmon}; static struct wl_listener new_output = {.notify = createmon};
static struct wl_listener new_xdg_surface = {.notify = createnotify}; static struct wl_listener new_xdg_surface = {.notify = createnotify};
static struct wl_listener new_xdg_decoration = {.notify = createdecoration};
static struct wl_listener new_layer_shell_surface = {.notify = createlayersurface}; static struct wl_listener new_layer_shell_surface = {.notify = createlayersurface};
static struct wl_listener output_mgr_apply = {.notify = outputmgrapply}; static struct wl_listener output_mgr_apply = {.notify = outputmgrapply};
static struct wl_listener output_mgr_test = {.notify = outputmgrtest}; static struct wl_listener output_mgr_test = {.notify = outputmgrtest};
@ -480,6 +481,7 @@ arrange(Monitor *m)
if (m && m->lt[m->sellt]->arrange) if (m && m->lt[m->sellt]->arrange)
m->lt[m->sellt]->arrange(m); m->lt[m->sellt]->arrange(m);
motionnotify(0); motionnotify(0);
checkidleinhibitor(NULL);
} }
void void
@ -631,8 +633,8 @@ checkidleinhibitor(struct wlr_surface *exclude)
wl_list_for_each(inhibitor, &idle_inhibit_mgr->inhibitors, link) { wl_list_for_each(inhibitor, &idle_inhibit_mgr->inhibitors, link) {
struct wlr_surface *surface = wlr_surface_get_root_surface(inhibitor->surface); struct wlr_surface *surface = wlr_surface_get_root_surface(inhibitor->surface);
struct wlr_scene_tree *tree = surface->data; struct wlr_scene_tree *tree = surface->data;
if (bypass_surface_visibility || (exclude != surface if (exclude != surface && (bypass_surface_visibility || (!tree
&& tree->node.enabled)) { || tree->node.enabled))) {
inhibited = 1; inhibited = 1;
break; break;
} }
@ -765,7 +767,7 @@ commitnotify(struct wl_listener *listener, void *data)
if (c->mon && !wlr_box_empty(&box) && (box.width != c->geom.width - 2 * c->bw if (c->mon && !wlr_box_empty(&box) && (box.width != c->geom.width - 2 * c->bw
|| box.height != c->geom.height - 2 * c->bw)) || box.height != c->geom.height - 2 * c->bw))
arrange(c->mon); c->isfloating ? resize(c, c->geom, 1) : arrange(c->mon);
/* mark a pending resize as completed */ /* mark a pending resize as completed */
if (c->resize && (c->resize <= c->surface.xdg->current.configure_serial if (c->resize && (c->resize <= c->surface.xdg->current.configure_serial
@ -774,6 +776,13 @@ commitnotify(struct wl_listener *listener, void *data)
c->resize = 0; c->resize = 0;
} }
void
createdecoration(struct wl_listener *listener, void *data)
{
struct wlr_xdg_toplevel_decoration_v1 *dec = data;
wlr_xdg_toplevel_decoration_v1_set_mode(dec, WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
}
void void
createidleinhibitor(struct wl_listener *listener, void *data) createidleinhibitor(struct wl_listener *listener, void *data)
{ {
@ -1057,7 +1066,7 @@ void
destroydragicon(struct wl_listener *listener, void *data) destroydragicon(struct wl_listener *listener, void *data)
{ {
/* Focus enter isn't sent during drag, so refocus the focused node. */ /* Focus enter isn't sent during drag, so refocus the focused node. */
focusclient(selclient(), 1); focusclient(focustop(selmon), 1);
motionnotify(0); motionnotify(0);
} }
@ -1229,9 +1238,7 @@ focusclient(Client *c, int lift)
client_activate_surface(old, 0); client_activate_surface(old, 0);
} }
} }
printstatus(); printstatus();
checkidleinhibitor(NULL);
if (!c) { if (!c) {
/* With no client, all we have left is to clear focus */ /* With no client, all we have left is to clear focus */
@ -1264,7 +1271,7 @@ void
focusstack(const Arg *arg) focusstack(const Arg *arg)
{ {
/* Focus the next or previous client (in tiling order) on selmon */ /* Focus the next or previous client (in tiling order) on selmon */
Client *c, *sel = selclient(); Client *c, *sel = focustop(selmon);
if (!sel || sel->isfullscreen) if (!sel || sel->isfullscreen)
return; return;
if (arg->i > 0) { if (arg->i > 0) {
@ -1421,7 +1428,7 @@ keypressmod(struct wl_listener *listener, void *data)
void void
killclient(const Arg *arg) killclient(const Arg *arg)
{ {
Client *sel = selclient(); Client *sel = focustop(selmon);
if (sel) if (sel)
client_send_close(sel); client_send_close(sel);
} }
@ -1469,6 +1476,7 @@ mapnotify(struct wl_listener *listener, void *data)
/* Create scene tree for this client and its border */ /* Create scene tree for this client and its border */
c->scene = wlr_scene_tree_create(layers[LyrTile]); c->scene = wlr_scene_tree_create(layers[LyrTile]);
wlr_scene_node_set_enabled(&c->scene->node, c->type != XDGShell);
c->scene_surface = c->type == XDGShell c->scene_surface = c->type == XDGShell
? wlr_scene_xdg_surface_create(c->scene, c->surface.xdg) ? wlr_scene_xdg_surface_create(c->scene, c->surface.xdg)
: wlr_scene_subsurface_tree_create(c->scene, client_surface(c)); : wlr_scene_subsurface_tree_create(c->scene, client_surface(c));
@ -1525,12 +1533,10 @@ mapnotify(struct wl_listener *listener, void *data)
} }
printstatus(); printstatus();
c->mon->un_map = 1;
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)
if (w != c && w->isfullscreen && VISIBLEON(w, m)) if (w != c && w->isfullscreen && m == w->mon && (w->tags & c->tags))
setfullscreen(w, 0); setfullscreen(w, 0);
} }
@ -1806,6 +1812,7 @@ printstatus(void)
sel, urg); sel, urg);
printf("%s layout %s\n", m->wlr_output->name, m->lt[m->sellt]->symbol); printf("%s layout %s\n", m->wlr_output->name, m->lt[m->sellt]->symbol);
} }
fflush(stdout);
} }
void void
@ -1827,30 +1834,19 @@ rendermon(struct wl_listener *listener, void *data)
* generally at the output's refresh rate (e.g. 60Hz). */ * generally at the output's refresh rate (e.g. 60Hz). */
Monitor *m = wl_container_of(listener, m, frame); Monitor *m = wl_container_of(listener, m, frame);
Client *c; Client *c;
int skip = 0;
struct timespec now; struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
/* Render if no XDG clients have an outstanding resize and are visible on /* Render if no XDG clients have an outstanding resize and are visible on
* this monitor. */ * this monitor. */
/* Checking m->un_map for every client is not optimal but works */ wl_list_for_each(c, &clients, link)
wl_list_for_each(c, &clients, link) { if (client_is_rendered_on_mon(c, m) && (!c->isfloating && c->resize) && !client_is_stopped(c))
if ((c->resize && m->un_map) || (c->type == XDGShell goto skip;
&& (c->surface.xdg->pending.geometry.width != if (!wlr_scene_output_commit(m->scene_output))
c->surface.xdg->current.geometry.width
|| c->surface.xdg->pending.geometry.height !=
c->surface.xdg->current.geometry.height))) {
/* Lie */
wlr_surface_send_frame_done(client_surface(c), &now);
skip = 1;
}
}
if (!skip && !wlr_scene_output_commit(m->scene_output))
return; return;
skip:
/* Let clients know a frame has been rendered */ /* Let clients know a frame has been rendered */
clock_gettime(CLOCK_MONOTONIC, &now);
wlr_scene_output_send_frame_done(m->scene_output, &now); wlr_scene_output_send_frame_done(m->scene_output, &now);
m->un_map = 0;
} }
void void
@ -1951,15 +1947,6 @@ run(char *startup_cmd)
wl_display_run(dpy); wl_display_run(dpy);
} }
Client *
selclient(void)
{
Client *c = wl_container_of(fstack.next, c, flink);
if (wl_list_empty(&fstack) || !VISIBLEON(c, selmon))
return NULL;
return c;
}
void void
setcursor(struct wl_listener *listener, void *data) setcursor(struct wl_listener *listener, void *data)
{ {
@ -2092,9 +2079,6 @@ setsel(struct wl_listener *listener, void *data)
void void
setup(void) setup(void)
{ {
/* Force line-buffered stdout */
setvbuf(stdout, NULL, _IOLBF, 0);
/* The Wayland display is managed by libwayland. It handles accepting /* The Wayland display is managed by libwayland. It handles accepting
* clients from the Unix socket, manging Wayland globals, and so on. */ * clients from the Unix socket, manging Wayland globals, and so on. */
dpy = wl_display_create(); dpy = wl_display_create();
@ -2205,7 +2189,8 @@ setup(void)
wlr_server_decoration_manager_set_default_mode( wlr_server_decoration_manager_set_default_mode(
wlr_server_decoration_manager_create(dpy), wlr_server_decoration_manager_create(dpy),
WLR_SERVER_DECORATION_MANAGER_MODE_SERVER); WLR_SERVER_DECORATION_MANAGER_MODE_SERVER);
wlr_xdg_decoration_manager_v1_create(dpy); xdg_decoration_mgr = wlr_xdg_decoration_manager_v1_create(dpy);
wl_signal_add(&xdg_decoration_mgr->events.new_toplevel_decoration, &new_xdg_decoration);
/* /*
* Creates a cursor, which is a wlroots utility for tracking the cursor * Creates a cursor, which is a wlroots utility for tracking the cursor
@ -2306,7 +2291,7 @@ startdrag(struct wl_listener *listener, void *data)
void void
tag(const Arg *arg) tag(const Arg *arg)
{ {
Client *sel = selclient(); Client *sel = focustop(selmon);
if (sel && arg->ui & TAGMASK) { if (sel && arg->ui & TAGMASK) {
sel->tags = arg->ui & TAGMASK; sel->tags = arg->ui & TAGMASK;
focusclient(focustop(selmon), 1); focusclient(focustop(selmon), 1);
@ -2318,7 +2303,7 @@ tag(const Arg *arg)
void void
tagmon(const Arg *arg) tagmon(const Arg *arg)
{ {
Client *sel = selclient(); Client *sel = focustop(selmon);
if (sel) if (sel)
setmon(sel, dirtomon(arg->i), 0); setmon(sel, dirtomon(arg->i), 0);
} }
@ -2359,7 +2344,7 @@ tile(Monitor *m)
void void
togglefloating(const Arg *arg) togglefloating(const Arg *arg)
{ {
Client *sel = selclient(); Client *sel = focustop(selmon);
/* return if fullscreen */ /* return if fullscreen */
if (sel && !sel->isfullscreen) if (sel && !sel->isfullscreen)
setfloating(sel, !sel->isfloating); setfloating(sel, !sel->isfloating);
@ -2368,7 +2353,7 @@ togglefloating(const Arg *arg)
void void
togglefullscreen(const Arg *arg) togglefullscreen(const Arg *arg)
{ {
Client *sel = selclient(); Client *sel = focustop(selmon);
if (sel) if (sel)
setfullscreen(sel, !sel->isfullscreen); setfullscreen(sel, !sel->isfullscreen);
} }
@ -2377,7 +2362,7 @@ void
toggletag(const Arg *arg) toggletag(const Arg *arg)
{ {
unsigned int newtags; unsigned int newtags;
Client *sel = selclient(); Client *sel = focustop(selmon);
if (!sel) if (!sel)
return; return;
newtags = sel->tags ^ (arg->ui & TAGMASK); newtags = sel->tags ^ (arg->ui & TAGMASK);
@ -2423,7 +2408,7 @@ unmaplayersurfacenotify(struct wl_listener *listener, void *data)
arrangelayers(layersurface->mon); arrangelayers(layersurface->mon);
if (layersurface->layer_surface->surface == if (layersurface->layer_surface->surface ==
seat->keyboard_state.focused_surface) seat->keyboard_state.focused_surface)
focusclient(selclient(), 1); focusclient(focustop(selmon), 1);
motionnotify(0); motionnotify(0);
} }
@ -2437,14 +2422,11 @@ unmapnotify(struct wl_listener *listener, void *data)
grabc = NULL; grabc = NULL;
} }
if (c->mon)
c->mon->un_map = 1;
if (client_is_unmanaged(c)) { if (client_is_unmanaged(c)) {
if (c == exclusive_focus) if (c == exclusive_focus)
exclusive_focus = NULL; exclusive_focus = NULL;
if (client_surface(c) == seat->keyboard_state.focused_surface) if (client_surface(c) == seat->keyboard_state.focused_surface)
focusclient(selclient(), 1); focusclient(focustop(selmon), 1);
} else { } else {
wl_list_remove(&c->link); wl_list_remove(&c->link);
setmon(c, NULL, 0); setmon(c, NULL, 0);
@ -2549,7 +2531,7 @@ urgent(struct wl_listener *listener, void *data)
struct wlr_xdg_activation_v1_request_activate_event *event = data; struct wlr_xdg_activation_v1_request_activate_event *event = data;
Client *c = NULL; Client *c = NULL;
int type = toplevel_from_wlr_surface(event->surface, &c, NULL); int type = toplevel_from_wlr_surface(event->surface, &c, NULL);
if (type >= 0 && type != LayerShell && c != selclient()) { if (type >= 0 && type != LayerShell && c != focustop(selmon)) {
c->isurgent = 1; c->isurgent = 1;
printstatus(); printstatus();
} }
@ -2619,7 +2601,7 @@ xytonode(double x, double y, struct wlr_surface **psurface,
void void
zoom(const Arg *arg) zoom(const Arg *arg)
{ {
Client *c, *sel = selclient(); Client *c, *sel = focustop(selmon);
if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange || sel->isfloating) if (!sel || !selmon || !selmon->lt[selmon->sellt]->arrange || sel->isfloating)
return; return;
@ -2713,7 +2695,7 @@ void
sethints(struct wl_listener *listener, void *data) sethints(struct wl_listener *listener, void *data)
{ {
Client *c = wl_container_of(listener, c, set_hints); Client *c = wl_container_of(listener, c, set_hints);
if (c != selclient()) { if (c != focustop(selmon)) {
c->isurgent = xcb_icccm_wm_hints_get_urgency(c->surface.xwayland->hints); c->isurgent = xcb_icccm_wm_hints_get_urgency(c->surface.xwayland->hints);
printstatus(); printstatus();
} }