On Tue, Aug 12, 2025 at 01:45:31PM +0200, arsentii_AT_tuta.io wrote:
> Set update interval for MotionNotify based on the highest
> refresh rate among active outputs. Before, the interval was
> constant - (1000 / 60) ms.
> This change allows for a smoother image if output's refresh rate
> is higher than 60 Hz.
>
> What do you think?
> ---
> config.mk | 3 ++-
> dwm.c | 46 +++++++++++++++++++++++++++++++++++++++++++---
> 2 files changed, 45 insertions(+), 4 deletions(-)
>
> diff --git a/config.mk b/config.mk
> index 8efca9a..8c3c202 100644
> --- a/config.mk
> +++ b/config.mk
> _AT_@ -13,6 +13,7 @@ X11LIB = /usr/X11R6/lib
> # Xinerama, comment if you don't want it
> XINERAMALIBS = -lXinerama
> XINERAMAFLAGS = -DXINERAMA
> +XRANDRLIBS = -lXrandr
>
> # freetype
> FREETYPELIBS = -lfontconfig -lXft
> _AT_@ -23,7 +24,7 @@ FREETYPEINC = /usr/include/freetype2
>
> # includes and libs
> INCS = -I${X11INC} -I${FREETYPEINC}
> -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
> +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${XRANDRLIBS} ${FREETYPELIBS}
>
> # flags
> CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
> diff --git a/dwm.c b/dwm.c
> index 1443802..d2c2882 100644
> --- a/dwm.c
> +++ b/dwm.c
> _AT_@ -39,6 +39,7 @@
> #ifdef XINERAMA
> #include <X11/extensions/Xinerama.h>
> #endif /* XINERAMA */
> +#include <X11/extensions/Xrandr.h>
> #include <X11/Xft/Xft.h>
>
> #include "drw.h"
> _AT_@ -188,6 +189,7 @@ static void pop(Client *c);
> static void propertynotify(XEvent *e);
> static void quit(const Arg *arg);
> static Monitor *recttomon(int x, int y, int w, int h);
> +static double refresh_rate(XRRModeInfo *mode_info);
> static void resize(Client *c, int x, int y, int w, int h, int interact);
> static void resizeclient(Client *c, int x, int y, int w, int h);
> static void resizemouse(const Arg *arg);
> _AT_@ -266,6 +268,7 @@ static Display *dpy;
> static Drw *drw;
> static Monitor *mons, *selmon;
> static Window root, wmcheckwin;
> +static unsigned int rate = 60;
>
> /* configuration, allows nested code to access above variables */
> #include "config.h"
> _AT_@ -1171,7 +1174,7 @@ movemouse(const Arg *arg)
> handler[ev.type](&ev);
> break;
> case MotionNotify:
> - if ((ev.xmotion.time - lasttime) <= (1000 / 60))
> + if ((ev.xmotion.time - lasttime) <= (1000 / rate))
> continue;
> lasttime = ev.xmotion.time;
>
> _AT_@ -1274,6 +1277,17 @@ recttomon(int x, int y, int w, int h)
> return r;
> }
>
> +static double
> +refresh_rate(XRRModeInfo *m)
> +{
> + /* from xrandr(1) source code */
> + double r = 0.0;
> + if (m->hTotal && m->vTotal)
> + r = ((double) m->dotClock /
> + ((double) m->hTotal * (double) m->vTotal));
> + return r;
> +}
> +
> void
> resize(Client *c, int x, int y, int w, int h, int interact)
> {
> _AT_@ -1325,7 +1339,7 @@ resizemouse(const Arg *arg)
> handler[ev.type](&ev);
> break;
> case MotionNotify:
> - if ((ev.xmotion.time - lasttime) <= (1000 / 60))
> + if ((ev.xmotion.time - lasttime) <= (1000 / rate))
> continue;
> lasttime = ev.xmotion.time;
>
> _AT_@ -1538,8 +1552,10 @@ setmfact(const Arg *arg)
> void
> setup(void)
> {
> - int i;
> + int i, j, k, n;
> XSetWindowAttributes wa;
> + XRRScreenResources *res;
> + XRRMonitorInfo *monitors;
> Atom utf8string;
> struct sigaction sa;
>
> _AT_@ -1557,6 +1573,30 @@ setup(void)
> sw = DisplayWidth(dpy, screen);
> sh = DisplayHeight(dpy, screen);
> root = RootWindow(dpy, screen);
> +
> + /* refresh rate */
> + monitors = XRRGetMonitors(dpy, root, 1, &n);
> + res = XRRGetScreenResources(dpy, root);
> + XRROutputInfo *o;
> + XRRCrtcInfo *crtc;
> + XRRModeInfo *mode;
> + double r = 0.0;
> + for (i = 0; i < n; i++) {
> + for (j = 0; j < monitors[i].noutput; j++) {
> + o = XRRGetOutputInfo(dpy, res, monitors[i].outputs[j]);
> + crtc = XRRGetCrtcInfo(dpy, res, o->crtc);
> + for (k = 0; k < res->nmode; k++) {
> + mode = &res->modes[k];
> + if (crtc->mode == mode->id) {
> + r = MAX(refresh_rate(mode), r);
> + break;
> + }
> + }
> + }
> + }
> + if (r)
> + rate = (unsigned int)r + 1;
> +
> drw = drw_create(dpy, screen, root, sw, sh);
> if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
> die("no fonts could be loaded.");
> --
> 2.50.1
>
>
>
Hi,
I like the idea and I think it has also been reported a few times over the years.
For simplicity a config.h variable is OK I think.
I have committed the below diff which makes it a bit more clear what to modify
and bumped the default from 60 to 120:
https://git.suckless.org/dwm/commit/74edc27caa65aba9ea8d1fe03d26e3b449f79590.html
iirc there can be some lag on old machines or ones with software rendering etc.
Then they can change the default to 60 again or lower.
--
Kind regards,
Hiltjo
Received on Tue Aug 12 2025 - 19:22:29 CEST