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,

Reply via email to