From d6a18d69c0c104a3f3ce3bb67d984b4479f6717e Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Thu, 30 Jul 2020 13:03:40 +1000 Subject: [PATCH] do not render frames when any surface has uncommitted resizes --- dwl.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/dwl.c b/dwl.c index 4cef058..2fb3399 100644 --- a/dwl.c +++ b/dwl.c @@ -75,6 +75,7 @@ typedef struct { struct wlr_xwayland_surface *xwayland_surface; }; struct wl_listener activate; + struct wl_listener commit; struct wl_listener map; struct wl_listener unmap; struct wl_listener destroy; @@ -84,6 +85,7 @@ typedef struct { int bw; unsigned int tags; int isfloating; + uint32_t resize; /* configure serial of a pending resize */ } Client; typedef struct { @@ -442,6 +444,16 @@ cleanupmon(struct wl_listener *listener, void *data) free(m); } +void +commitnotify(struct wl_listener *listener, void *data) +{ + Client *c = wl_container_of(listener, c, commit); + + /* mark a pending resize as completed */ + if (c->resize && c->resize <= c->xdg_surface->configure_serial) + c->resize = 0; +} + void createkeyboard(struct wlr_input_device *device) { @@ -553,6 +565,8 @@ createnotify(struct wl_listener *listener, void *data) WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); /* Listen to the various events it can emit */ + c->commit.notify = commitnotify; + wl_signal_add(&xdg_surface->surface->events.commit, &c->commit); c->map.notify = maprequest; wl_signal_add(&xdg_surface->events.map, &c->map); c->unmap.notify = unmapnotify; @@ -628,6 +642,8 @@ destroynotify(struct wl_listener *listener, void *data) wl_list_remove(&c->map.link); wl_list_remove(&c->unmap.link); wl_list_remove(&c->destroy.link); + if (c->type == XDGShell) + wl_list_remove(&c->commit.link); if (c->type == X11Managed) wl_list_remove(&c->activate.link); free(c); @@ -1220,6 +1236,8 @@ void rendermon(struct wl_listener *listener, void *data) { struct wlr_output *output = data; + Client *c; + int render = 1; /* This function is called every time an output is ready to display a frame, * generally at the output's refresh rate (e.g. 60Hz). */ @@ -1228,16 +1246,30 @@ rendermon(struct wl_listener *listener, void *data) struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); + /* Do not render if any XDG clients have an outstanding resize. */ + wl_list_for_each(c, &stack, slink) + { + if (c->resize) + { + wlr_surface_send_frame_done(WLR_SURFACE(c), &now); + render = 0; + } + } + /* wlr_output_attach_render makes the OpenGL context current. */ if (!wlr_output_attach_render(m->wlr_output, NULL)) return; /* Begin the renderer (calls glViewport and some other GL sanity checks) */ wlr_renderer_begin(drw, m->wlr_output->width, m->wlr_output->height); - wlr_renderer_clear(drw, rootcolor); - renderclients(m, &now); - renderindependents(output, &now); + if (render) + { + wlr_renderer_clear(drw, rootcolor); + + renderclients(m, &now); + renderindependents(output, &now); + } /* Hardware cursors are rendered by the GPU on a separate plane, and can be * moved around without re-rendering what's beneath them - which is more @@ -1273,7 +1305,7 @@ resize(Client *c, int x, int y, int w, int h, int interact) c->geom.x, c->geom.y, c->geom.width - 2 * c->bw, c->geom.height - 2 * c->bw); else - wlr_xdg_toplevel_set_size(c->xdg_surface, + c->resize = wlr_xdg_toplevel_set_size(c->xdg_surface, c->geom.width - 2 * c->bw, c->geom.height - 2 * c->bw); }