[hackers] [dwm][PATCH] MotionNotify update interval

From: <arsentii_AT_tuta.io>
Date: Tue, 12 Aug 2025 13:45:31 +0200 (CEST)

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
Received on Tue Aug 12 2025 - 13:45:31 CEST

This archive was generated by hypermail 2.3.0 : Tue Aug 12 2025 - 13:48:37 CEST