wl_backend: add inotify config-file watching to event loop

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.
This commit is contained in:
Window Maker 2026-05-24 14:13:14 +02:00
parent 8119bfe098
commit 0d795bc84a
1 changed files with 61 additions and 0 deletions

View File

@ -110,6 +110,11 @@
#include <errno.h>
#include <signal.h>
#include <sys/signalfd.h>
#include <sys/select.h>
#ifdef HAVE_INOTIFY
#include <sys/inotify.h>
#include <limits.h>
#endif
#include <time.h>
#include <pthread.h>
@ -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) {