Index | Thread | Search

From:
Volker Schlecht <openbsd-ports@schlecht.dev>
Subject:
Testing: wayland monitor hotplug
To:
ports@openbsd.org
Date:
Tue, 5 Aug 2025 19:31:55 +0200

Download raw body.

Thread
During l2k25 I tried to get output hotplug to work with wlroots based wayland
compositors. The attached diff seems to work rather well for matthieu@ and myself
but could probably use some wider testing from whoever is interested :-)

For those who haven't used wayland on OpenBSD before:

$ doas pkg_add sway

* apply the attached diff to wayland/wlroots, rebuild and install
* kill all running X sessions, make sure to stop xenodm if it's running

$ startsway.sh

* Plug, unplug and replug any external monitors you have around, and see if
   sway detects and uses them.
Index: Makefile
===================================================================
RCS file: /cvs/ports/wayland/wlroots/Makefile,v
diff -u -p -r1.11 Makefile
--- Makefile	16 Dec 2024 18:25:23 -0000	1.11
+++ Makefile	5 Aug 2025 17:21:53 -0000
@@ -2,6 +2,7 @@ COMMENT =	modular Wayland compositor lib
 
 V =		0.18.2
 EPOCH =		0
+REVISION =	0
 DISTNAME =	wlroots-${V}
 CATEGORIES =	wayland
 
Index: patches/patch-backend_drm_backend_c
===================================================================
RCS file: patches/patch-backend_drm_backend_c
diff -N patches/patch-backend_drm_backend_c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ patches/patch-backend_drm_backend_c	5 Aug 2025 17:21:53 -0000
@@ -0,0 +1,45 @@
+Index: backend/drm/backend.c
+--- backend/drm/backend.c.orig
++++ backend/drm/backend.c
+@@ -10,6 +10,7 @@
+ #include <wlr/backend/session.h>
+ #include <wlr/interfaces/wlr_output.h>
+ #include <wlr/util/log.h>
++#include <sys/event.h>
+ #include <xf86drm.h>
+ #include "backend/drm/drm.h"
+ #include "backend/drm/fb.h"
+@@ -167,6 +168,8 @@ static void handle_parent_destroy(struct wl_listener *
+ 
+ struct wlr_backend *wlr_drm_backend_create(struct wlr_session *session,
+ 		struct wlr_device *dev, struct wlr_backend *parent) {
++	int kq;
++	struct kevent kev;
+ 	assert(session && dev);
+ 	assert(!parent || wlr_backend_is_drm(parent));
+ 
+@@ -267,6 +270,24 @@ struct wlr_backend *wlr_drm_backend_create(struct wlr_
+ 	drm->session_destroy.notify = handle_session_destroy;
+ 	wl_signal_add(&session->events.destroy, &drm->session_destroy);
+ 
++	if ((kq = kqueue()) <= 0)
++		goto error_kqueue;
++
++	EV_SET(&kev, dev->fd, EVFILT_DEVICE, EV_ADD | EV_ENABLE | EV_CLEAR,
++	       NOTE_CHANGE, 0, NULL);
++
++	if (kevent(kq, &kev, 1, NULL, 0, NULL) < 0)
++		goto error_kqueue;
++
++	drm->drm_kevent = wl_event_loop_add_fd(session->event_loop, kq,
++		WL_EVENT_READABLE, handle_drm_kevent, drm);
++	if (!drm->drm_kevent) {
++		wlr_log(WLR_ERROR, "Failed to create DRM kevent source");
++		goto error_kqueue;
++	}
++	wlr_log(WLR_INFO, "DRM kevent source added");
++
++error_kqueue:
+ 	return &drm->backend;
+ 
+ error_mgpu_renderer:
Index: patches/patch-backend_drm_drm_c
===================================================================
RCS file: patches/patch-backend_drm_drm_c
diff -N patches/patch-backend_drm_drm_c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ patches/patch-backend_drm_drm_c	5 Aug 2025 17:21:53 -0000
@@ -0,0 +1,30 @@
+Index: backend/drm/drm.c
+--- backend/drm/drm.c.orig
++++ backend/drm/drm.c
+@@ -9,6 +9,7 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <strings.h>
++#include <sys/event.h>
+ #include <time.h>
+ #include <wayland-server-core.h>
+ #include <wayland-util.h>
+@@ -2113,6 +2114,18 @@ int handle_drm_event(int fd, uint32_t mask, void *data
+ 		wlr_log(WLR_ERROR, "drmHandleEvent failed");
+ 		wlr_backend_destroy(&drm->backend);
+ 	}
++	return 1;
++}
++
++int handle_drm_kevent(int fd, uint32_t mask, void *data) {
++	struct kevent kev;
++	struct wlr_drm_backend *drm = data;
++
++	if ((kevent(fd, NULL, 0, &kev, 1, NULL)) && kev.fflags & NOTE_CHANGE) {
++		wlr_log(WLR_INFO, "drm hotplug detected");
++		scan_drm_connectors(drm, NULL);
++	}
++
+ 	return 1;
+ }
+ 
Index: patches/patch-include_backend_drm_drm_h
===================================================================
RCS file: patches/patch-include_backend_drm_drm_h
diff -N patches/patch-include_backend_drm_drm_h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ patches/patch-include_backend_drm_drm_h	5 Aug 2025 17:21:53 -0000
@@ -0,0 +1,19 @@
+Index: include/backend/drm/drm.h
+--- include/backend/drm/drm.h.orig
++++ include/backend/drm/drm.h
+@@ -96,6 +96,7 @@ struct wlr_drm_backend {
+ 	struct wlr_drm_plane *planes;
+ 
+ 	struct wl_event_source *drm_event;
++	struct wl_event_source *drm_kevent;
+ 
+ 	struct wl_listener session_destroy;
+ 	struct wl_listener session_active;
+@@ -215,6 +216,7 @@ bool commit_drm_device(struct wlr_drm_backend *drm,
+ 	const struct wlr_backend_output_state *states, size_t states_len, bool test_only);
+ void restore_drm_device(struct wlr_drm_backend *drm);
+ int handle_drm_event(int fd, uint32_t mask, void *data);
++int handle_drm_kevent(int fd, uint32_t mask, void *data);
+ void destroy_drm_connector(struct wlr_drm_connector *conn);
+ bool drm_connector_is_cursor_visible(struct wlr_drm_connector *conn);
+ size_t drm_crtc_get_gamma_lut_size(struct wlr_drm_backend *drm,