On Tue, Aug 12, 2025 at 01:45:31PM +0200, arsen...@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
> @@ -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
> @@ -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
> @@ -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"
> @@ -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);
> @@ -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"
> @@ -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;
>  
> @@ -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)
> {
> @@ -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;
>  
> @@ -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;
>  
> @@ -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

Reply via email to