core: watch for configuration file changes
Automatically reset picom and reload the configuration when a change in the configuration file is detected. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
fe9fec84dc
commit
0e5be97f94
|
@ -154,6 +154,8 @@ typedef struct session {
|
|||
void *backend_blur_context;
|
||||
/// graphic drivers used
|
||||
enum driver drivers;
|
||||
/// file watch handle
|
||||
void *file_watch_handle;
|
||||
/// libev mainloop
|
||||
struct ev_loop *loop;
|
||||
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/inotify.h>
|
||||
|
||||
#include <ev.h>
|
||||
#include <uthash.h>
|
||||
|
||||
#include "file_watch.h"
|
||||
#include "list.h"
|
||||
#include "log.h"
|
||||
#include "utils.h"
|
||||
|
||||
struct watched_file {
|
||||
int wd;
|
||||
void *ud;
|
||||
file_watch_cb_t cb;
|
||||
|
||||
UT_hash_handle hh;
|
||||
};
|
||||
|
||||
struct file_watch_registry {
|
||||
struct ev_io w;
|
||||
|
||||
struct watched_file *reg;
|
||||
};
|
||||
|
||||
static void file_watch_ev_cb(EV_P_ struct ev_io *w, int revent attr_unused) {
|
||||
auto fwr = (struct file_watch_registry *)w;
|
||||
struct inotify_event inotify_event;
|
||||
|
||||
while (true) {
|
||||
auto ret = read(w->fd, &inotify_event, sizeof(struct inotify_event));
|
||||
if (ret < 0) {
|
||||
if (errno != EAGAIN) {
|
||||
log_error("Failed to read from inotify fd: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
struct watched_file *wf = NULL;
|
||||
HASH_FIND_INT(fwr->reg, &inotify_event.wd, wf);
|
||||
if (!wf) {
|
||||
log_warn("Got notification for a file I didn't watch.");
|
||||
continue;
|
||||
}
|
||||
wf->cb(wf->ud);
|
||||
}
|
||||
}
|
||||
|
||||
void *file_watch_init(EV_P) {
|
||||
log_debug("Starting watching for file changes");
|
||||
int fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
log_error("inotify_init1 failed: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
auto fwr = ccalloc(1, struct file_watch_registry);
|
||||
ev_io_init(&fwr->w, file_watch_ev_cb, fd, EV_READ);
|
||||
ev_io_start(EV_A_ & fwr->w);
|
||||
|
||||
return fwr;
|
||||
}
|
||||
|
||||
void file_watch_destroy(EV_P_ void *_fwr) {
|
||||
log_debug("Stopping watching for file changes");
|
||||
auto fwr = (struct file_watch_registry *)_fwr;
|
||||
struct watched_file *i, *tmp;
|
||||
|
||||
HASH_ITER(hh, fwr->reg, i, tmp) {
|
||||
HASH_DEL(fwr->reg, i);
|
||||
free(i);
|
||||
}
|
||||
|
||||
ev_io_stop(EV_A_ & fwr->w);
|
||||
close(fwr->w.fd);
|
||||
free(fwr);
|
||||
}
|
||||
|
||||
bool file_watch_add(void *_fwr, const char *filename, file_watch_cb_t cb, void *ud) {
|
||||
log_debug("Adding \"%s\" to watched files", filename);
|
||||
auto fwr = (struct file_watch_registry *)_fwr;
|
||||
int wd = inotify_add_watch(fwr->w.fd, filename,
|
||||
IN_CLOSE_WRITE | IN_MOVE_SELF | IN_DELETE_SELF);
|
||||
if (wd < 0) {
|
||||
log_error("Failed to watch file \"%s\": %s", filename, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
auto w = ccalloc(1, struct watched_file);
|
||||
w->wd = wd;
|
||||
w->cb = cb;
|
||||
w->ud = ud;
|
||||
|
||||
HASH_ADD_INT(fwr->reg, wd, w);
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#pragma once
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <ev.h>
|
||||
|
||||
typedef void (*file_watch_cb_t)(void *);
|
||||
|
||||
void *file_watch_init(EV_P);
|
||||
bool file_watch_add(void *, const char *, file_watch_cb_t, void *);
|
||||
void file_watch_destroy(EV_P_ void *);
|
|
@ -9,7 +9,7 @@ base_deps = [
|
|||
|
||||
srcs = [ files('picom.c', 'win.c', 'c2.c', 'x.c', 'config.c', 'vsync.c', 'utils.c',
|
||||
'diagnostic.c', 'string_utils.c', 'render.c', 'kernel.c', 'log.c',
|
||||
'options.c', 'event.c', 'cache.c', 'atom.c') ]
|
||||
'options.c', 'event.c', 'cache.c', 'atom.c', 'file_watch.c') ]
|
||||
picom_inc = include_directories('.')
|
||||
|
||||
cflags = []
|
||||
|
|
15
src/picom.c
15
src/picom.c
|
@ -54,6 +54,7 @@
|
|||
#endif
|
||||
#include "atom.h"
|
||||
#include "event.h"
|
||||
#include "file_watch.h"
|
||||
#include "list.h"
|
||||
#include "options.h"
|
||||
#include "uthash_extra.h"
|
||||
|
@ -1538,6 +1539,11 @@ static void exit_enable(EV_P attr_unused, ev_signal *w, int revents attr_unused)
|
|||
quit(ps);
|
||||
}
|
||||
|
||||
static void config_file_change_cb(void *_ps) {
|
||||
auto ps = (struct session *)_ps;
|
||||
reset_enable(ps->loop, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a session.
|
||||
*
|
||||
|
@ -1935,6 +1941,12 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
|
|||
free(config_file_to_free);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
ps->file_watch_handle = file_watch_init(ps->loop);
|
||||
if (ps->file_watch_handle) {
|
||||
file_watch_add(ps->file_watch_handle, config_file, config_file_change_cb, ps);
|
||||
}
|
||||
|
||||
free(config_file_to_free);
|
||||
|
||||
if (bkend_use_glx(ps) && !ps->o.experimental_backends) {
|
||||
|
@ -2100,6 +2112,9 @@ static void session_destroy(session_t *ps) {
|
|||
unredirect(ps);
|
||||
}
|
||||
|
||||
file_watch_destroy(ps->loop, ps->file_watch_handle);
|
||||
ps->file_watch_handle = NULL;
|
||||
|
||||
// Stop listening to events on root window
|
||||
xcb_change_window_attributes(ps->c, ps->root, XCB_CW_EVENT_MASK,
|
||||
(const uint32_t[]){0});
|
||||
|
|
Loading…
Reference in New Issue