From 1721b339da73c29fdadbc0022e7ec614defb4ac7 Mon Sep 17 00:00:00 2001 From: Johan Malm Date: Fri, 25 Sep 2020 19:42:40 +0100 Subject: [PATCH] Reload config+theme on SIGHUP --- src/action.c | 14 +++++++++++--- src/common/dir.c | 2 -- src/config/rcxml.c | 45 ++++++++++++++++++++++++++++++--------------- src/keyboard.c | 3 ++- src/main.c | 12 +++++++----- src/server.c | 30 ++++++++++++++++++++++++++++++ 6 files changed, 80 insertions(+), 26 deletions(-) diff --git a/src/action.c b/src/action.c index 4ae7e7d2..4f933f74 100644 --- a/src/action.c +++ b/src/action.c @@ -1,8 +1,14 @@ +#include + #include "labwc.h" #include "common/spawn.h" #include "common/log.h" -#include +static void reconfigure(void) +{ + char *const args[] = { "killall", "-SIGHUP", "labwc", NULL }; + execvp(args[0], args); +} void action(struct server *server, const char *action, const char *command) { @@ -10,11 +16,13 @@ void action(struct server *server, const char *action, const char *command) return; if (!strcasecmp(action, "Exit")) { wl_display_terminate(server->wl_display); + } else if (!strcasecmp(action, "Execute")) { + spawn_async_no_shell(command); } else if (!strcasecmp(action, "NextWindow")) { server->cycle_view = desktop_next_view(server, server->cycle_view); - } else if (!strcasecmp(action, "Execute")) { - spawn_async_no_shell(command); + } else if (!strcasecmp(action, "Reconfigure")) { + reconfigure(); } else if (!strcasecmp(action, "debug-views")) { dbg_show_views(server); } else { diff --git a/src/common/dir.c b/src/common/dir.c index 75adb072..6184ae11 100644 --- a/src/common/dir.c +++ b/src/common/dir.c @@ -122,8 +122,6 @@ char *config_dir(void) char *theme_dir(const char *theme_name) { static char buf[4096] = { 0 }; - if (buf[0] != '\0') - return buf; struct ctx ctx = { .build_path_fn = build_theme_path, .buf = buf, .len = sizeof(buf), diff --git a/src/config/rcxml.c b/src/config/rcxml.c index 1c5f7da5..ecee8edc 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -214,9 +214,22 @@ void rcxml_parse_xml(struct buf *b) xmlCleanupParser(); } +static void pre_processing(void) +{ + rc.xdg_shell_server_side_deco = true; + rc.font_size_activewindow = 8; +} + static void rcxml_init() { + static bool has_run; + + if (has_run) + return; + has_run = true; LIBXML_TEST_VERSION + wl_list_init(&rc.keybinds); + pre_processing(); } static void bind(const char *binding, const char *action, const char *command) @@ -240,12 +253,6 @@ static void set_title_height(void) rc.title_height = font_height(buf); } -static void pre_processing(void) -{ - rc.xdg_shell_server_side_deco = true; - rc.font_size_activewindow = 8; -} - static void post_processing(void) { if (!wl_list_length(&rc.keybinds)) { @@ -271,30 +278,38 @@ static void rcxml_path(char *buf, size_t len) snprintf(buf, len, "%s/rc.xml", config_dir()); } +static void find_config_file(char *buffer, size_t len, const char *filename) +{ + if (filename) { + snprintf(buffer, len, "%s", filename); + return; + } + rcxml_path(buffer, len); +} + void rcxml_read(const char *filename) { FILE *stream; char *line = NULL; size_t len = 0; struct buf b; - char rcxml[4096] = { 0 }; + static char rcxml[4096] = { 0 }; rcxml_init(); - wl_list_init(&rc.keybinds); - pre_processing(); /* - * Reading file into buffer before parsing makes it easier to write - * unit tests. + * rcxml_read() can be called multiple times, but we only set rcxml[] + * the first time. The specified 'filename' is only respected the first + * time. */ - if (filename) - snprintf(rcxml, sizeof(rcxml), "%s", filename); - else - rcxml_path(rcxml, sizeof(rcxml)); + if (rcxml[0] == '\0') + find_config_file(rcxml, sizeof(rcxml), filename); if (rcxml[0] == '\0') { warn("cannot find rc.xml config file"); goto no_config; } + + /* Reading file into buffer before parsing - better for unit tests */ stream = fopen(rcxml, "r"); if (!stream) { warn("cannot read (%s)", rcxml); diff --git a/src/keyboard.c b/src/keyboard.c index ffd270af..e7a05748 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -30,7 +30,8 @@ static bool handle_keybinding(struct server *server, uint32_t modifiers, continue; for (size_t i = 0; i < keybind->keysyms_len; i++) { if (sym == keybind->keysyms[i]) { - action(server, keybind->action, keybind->command); + action(server, keybind->action, + keybind->command); return true; } } diff --git a/src/main.c b/src/main.c index b42f02c2..5a20204b 100644 --- a/src/main.c +++ b/src/main.c @@ -23,17 +23,18 @@ int main(int argc, char *argv[]) { char *startup_cmd = NULL; char *config_file = NULL; - wlr_log_init(WLR_ERROR, NULL); int c; - while ((c = getopt(argc, argv, "s:c:h")) != -1) { + while ((c = getopt(argc, argv, "c:s:h")) != -1) { switch (c) { - case 's': - startup_cmd = optarg; - break; case 'c': config_file = optarg; break; + case 's': + startup_cmd = optarg; + break; + case 'h': + /* fallthrough */ default: usage(); } @@ -41,6 +42,7 @@ int main(int argc, char *argv[]) if (optind < argc) usage(); + wlr_log_init(WLR_ERROR, NULL); rcxml_read(config_file); /* Wayland requires XDG_RUNTIME_DIR to be set */ diff --git a/src/server.c b/src/server.c index 11a7746e..e65e1896 100644 --- a/src/server.c +++ b/src/server.c @@ -1,5 +1,8 @@ #include "labwc.h" +#include "theme/theme.h" +#include "config/rcxml.h" +#include #include #include #include @@ -9,6 +12,7 @@ static struct wlr_backend *backend; static struct wlr_compositor *compositor; +static struct wl_event_source *sighup_source; static void server_new_input(struct wl_listener *listener, void *data) { @@ -72,6 +76,25 @@ static void seat_request_set_selection(struct wl_listener *listener, void *data) wlr_seat_set_selection(server->seat, event->source, event->serial); } +static void reload_config_and_theme(void) +{ + rcxml_finish(); + /* TODO: use rc.config_path */ + rcxml_read(NULL); + theme_read(rc.theme_name); +} + +static int handle_signal(int signal, void *data) +{ + switch (signal) { + case SIGHUP: + reload_config_and_theme(); + return 0; + default: + return 0; + } +} + void server_init(struct server *server) { server->wl_display = wl_display_create(); @@ -80,6 +103,12 @@ void server_init(struct server *server) exit(EXIT_FAILURE); } + /* Catch SIGHUP */ + struct wl_event_loop *event_loop = NULL; + event_loop = wl_display_get_event_loop(server->wl_display); + sighup_source = wl_event_loop_add_signal( + event_loop, SIGHUP, handle_signal, &server->wl_display); + /* * The backend is a wlroots feature which abstracts the underlying * input and output hardware. the autocreate option will choose the @@ -312,6 +341,7 @@ void server_finish(struct server *server) wlr_output_layout_destroy(server->output_layout); wlr_xwayland_destroy(server->xwayland); wlr_xcursor_manager_destroy(server->cursor_mgr); + wl_event_source_remove(sighup_source); wl_display_destroy_clients(server->wl_display); wl_display_destroy(server->wl_display); }