manage: propertynotify: Reduce cost of unused size hints - dwm - dynamic window… | |
git clone git://git.suckless.org/dwm | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 8806b6e2379372900e3d9e0bf6604bc7f727350b | |
parent bece862a0fc4fc18ef9065b18cd28e2032d0d975 | |
Author: Chris Down <[email protected]> | |
Date: Thu, 17 Mar 2022 15:56:13 +0000 | |
manage: propertynotify: Reduce cost of unused size hints | |
This patch defers all size hint calculations until they are actually | |
needed, drastically reducing the number of calls to updatesizehints(), | |
which can be expensive when called repeatedly (as it currently is during | |
resizes). | |
In my unscientific testing this reduces calls to updatesizehints() by | |
over 90% during a typical work session. There are no functional changes | |
for users other than an increase in responsiveness after resizes and | |
a reduction in CPU time. | |
In slower environments or X servers, this patch also offers an | |
improvement in responsiveness that is often tangible after resizing a | |
client that changes hints during resizes. | |
There are two main motivations to defer this work to the time of hint | |
application: | |
1. Some clients, especially terminals using incremental size hints, | |
resend XA_WM_NORMAL_HINTS events on resize to avoid fighting with the | |
WM or mouse resizing. For example, some terminals like urxvt clear | |
PBaseSize and PResizeInc during XResizeWindow and restore them | |
afterwards. | |
For this reason, after the resize is concluded, we typically receive | |
a backlogged XA_WM_NORMAL_HINTS message for each update period with | |
movement, which is useless. In some cases one may get hundreds or | |
thousands of XA_WM_NORMAL_HINTS messages on large resizes, and | |
currently all of these result in a separate updatesizehints() call, | |
of which all but the final one are immediately outdated. | |
(We can't just blindly discard these messages during resizes like we | |
do for EnterNotify, because some of them might actually be for other | |
windows, and may not be XA_WM_NORMAL_HINTS events.) | |
2. For users which use resizehints=0 most of these updates are unused | |
anyway -- in the normal case where the client is not floating these | |
values won't be used, so there's no need to calculate them up front. | |
A synthetic test using the mouse to resize a floating terminal window | |
from roughly 256x256 to 1024x1024 and back again shows that the number | |
of calls to updatesizehints() goes from over 500 before this patch (one | |
for each update interval with movement) to 2 after this patch (one for | |
each hint application), with no change in user visible behaviour. | |
This also reduces the delay before dwm is ready to process new events | |
again after a large resize on such a client, as it avoids the thundering | |
herd of updatesizehints() calls when hundreds of backlogged | |
XA_WM_NORMAL_HINTS messages appear at once after a resize is finished. | |
Diffstat: | |
M dwm.c | 8 +++++--- | |
1 file changed, 5 insertions(+), 3 deletions(-) | |
--- | |
diff --git a/dwm.c b/dwm.c | |
@@ -89,7 +89,7 @@ struct Client { | |
float mina, maxa; | |
int x, y, w, h; | |
int oldx, oldy, oldw, oldh; | |
- int basew, baseh, incw, inch, maxw, maxh, minw, minh; | |
+ int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; | |
int bw, oldbw; | |
unsigned int tags; | |
int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; | |
@@ -345,6 +345,8 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, i… | |
if (*w < bh) | |
*w = bh; | |
if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrang… | |
+ if (!c->hintsvalid) | |
+ updatesizehints(c); | |
/* see last two sentences in ICCCM 4.1.2.3 */ | |
baseismin = c->basew == c->minw && c->baseh == c->minh; | |
if (!baseismin) { /* temporarily remove base dimensions */ | |
@@ -1059,7 +1061,6 @@ manage(Window w, XWindowAttributes *wa) | |
XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); | |
configure(c); /* propagates border_width, if size doesn't change */ | |
updatewindowtype(c); | |
- updatesizehints(c); | |
updatewmhints(c); | |
XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMas… | |
grabbuttons(c, 0); | |
@@ -1233,7 +1234,7 @@ propertynotify(XEvent *e) | |
arrange(c->mon); | |
break; | |
case XA_WM_NORMAL_HINTS: | |
- updatesizehints(c); | |
+ c->hintsvalid = 0; | |
break; | |
case XA_WM_HINTS: | |
updatewmhints(c); | |
@@ -1989,6 +1990,7 @@ updatesizehints(Client *c) | |
} else | |
c->maxa = c->mina = 0.0; | |
c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c… | |
+ c->hintsvalid = 1; | |
} | |
void |