From 0d795bc84a19731b66d5560a41e303efee8a0a32 Mon Sep 17 00:00:00 2001 From: Window Maker Date: Sun, 24 May 2026 14:13:14 +0200 Subject: [PATCH] wl_backend: add inotify config-file watching to event loop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Wayland event loop was missing inotify polling, so theme/style/ background changes from WPrefs (or manual edits to ~/GNUstep/Defaults/) were never detected. The X11 backend had this since day one. Now the Wayland event loop checks inotify on every iteration (non-blocking select with zero timeout). When a config file modification is detected, wDefaultsCheckDomains() is called, which re-reads the defaults database and posts appearance-change notifications — triggering immediate visual refresh of title bars, menus, icons, and backgrounds. --- src/backend/wayland/wl_backend.c | 61 ++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index 391c1c5..db05304 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -110,6 +110,11 @@ #include #include #include +#include +#ifdef HAVE_INOTIFY +#include +#include +#endif #include #include @@ -197,6 +202,7 @@ #include "../../workspace.h" /* WWorkspace */ #include "../../dock.h" /* WDock (for clip->collapsed) */ #include "../../appicon.h" /* WAppIcon */ +#include "../../defaults.h" /* wDefaultsCheckDomains */ #include "../../menu.h" /* WMenu, WMenuEntry */ #include "../../balloon.h" /* WBalloon */ #include "../../dialog.h" /* WMRestart, WMAbort */ @@ -3237,6 +3243,47 @@ wl_signalfd_handler(int fd, uint32_t mask, void *data) return 0; } +#ifdef HAVE_INOTIFY +static void wl_handle_inotify_events(void) +{ + ssize_t eventQLength; + size_t i = 0; + char buff[(sizeof(struct inotify_event) + NAME_MAX + 1) * 5]; + int oneShotFlag = 0; + + eventQLength = read(w_global.inotify.fd_event_queue, buff, sizeof(buff)); + if (eventQLength < 0) { + wwarning(_("read problem when trying to get INotify event: %s"), strerror(errno)); + return; + } + + while (i < (size_t)eventQLength) { + struct inotify_event *pevent = (struct inotify_event *)&buff[i]; + + if (pevent->mask & IN_DELETE_SELF) { + wwarning(_("the defaults database has been deleted!")); + if (w_global.inotify.fd_event_queue >= 0) { + close(w_global.inotify.fd_event_queue); + w_global.inotify.fd_event_queue = -1; + } + } + if (pevent->mask & IN_UNMOUNT) { + wwarning(_("the unit containing the defaults database has been unmounted.")); + if (w_global.inotify.fd_event_queue >= 0) { + close(w_global.inotify.fd_event_queue); + w_global.inotify.fd_event_queue = -1; + } + wPreferences.flags.noupdates = 1; + } + if ((pevent->mask & IN_MODIFY) && oneShotFlag == 0) { + wDefaultsCheckDomains(NULL); + oneShotFlag = 1; + } + i += sizeof(struct inotify_event) + pevent->len; + } +} +#endif + static void wl_event_loop_run(void) { @@ -3375,6 +3422,20 @@ wl_event_loop_run(void) wlr_output_schedule_frame(wl_state.output); wl_event_loop_dispatch(loop, 16); + /* Check inotify for defaults database changes */ +#ifdef HAVE_INOTIFY + if (w_global.inotify.fd_event_queue >= 0) { + fd_set rfds; + struct timeval tv = { 0, 0 }; + FD_ZERO(&rfds); + FD_SET(w_global.inotify.fd_event_queue, &rfds); + if (select(w_global.inotify.fd_event_queue + 1, &rfds, NULL, NULL, &tv) > 0 + && FD_ISSET(w_global.inotify.fd_event_queue, &rfds)) { + wl_handle_inotify_events(); + } + } +#endif + /* Drain WINGs event queue */ WMScreen *wmscr = wl_get_wmscreen(); if (wmscr) {