diff --git a/README.md b/README.md index 37ced7e3..ce086666 100644 --- a/README.md +++ b/README.md @@ -79,16 +79,13 @@ Suggested apps to use with labwc: ## 6. Roadmap - [x] Support xwayland -- [x] Parse [rc.xml](docs/rc.xml) -- [x] Parse [themerc](docs/themerc) -- [x] Read xbm icons +- [x] Parse ~/.config/labwc/{rc.xml,autostart,environment} +- [x] Parse /usr/share/themes//openbox-3/themerc and associated xbm icons - [x] Show maximize, iconify, close buttons -- [x] Catch SIGHUP to reconfigure (re-load config and theme) +- [x] Catch SIGHUP to re-load config file and theme - [x] Support layer-shell protocol (partial) - [ ] Support 'maximize' - [ ] Show window title -- [ ] Read ~/.config/labwc/autostart -- [ ] Read ~/.config/labwc/environment (useful for XKB environment variables) - [ ] Support foreign-toplevel protocol (e.g. to integrate with wlroots panels/bars) - [ ] Support damage control to reduce CPU usage - [ ] Implement client-menu diff --git a/include/config/session.h b/include/config/session.h new file mode 100644 index 00000000..89365a50 --- /dev/null +++ b/include/config/session.h @@ -0,0 +1,16 @@ +#ifndef __LABWC_SESSION_H +#define __LABWC_SESSION_H + +/** + * session_environment_init - set enrivonment variables + * Note: Same as `. ~/.config/labwc/environment` (or equivalent XDG config dir) + */ +session_environment_init(void); + +/** + * session_autostart_init - run autostart file as shell script + * Note: Same as `sh ~/.config/labwc/autostart` (or equivalent XDG config dir) + */ +session_autostart_init(void); + +#endif /* __LABWC_SESSION_H */ diff --git a/src/config/meson.build b/src/config/meson.build index ac8e6012..9a42abb9 100644 --- a/src/config/meson.build +++ b/src/config/meson.build @@ -1,4 +1,5 @@ labwc_sources += files( 'rcxml.c', 'keybind.c', + 'session.c', ) diff --git a/src/config/session.c b/src/config/session.c new file mode 100644 index 00000000..eb7cd003 --- /dev/null +++ b/src/config/session.c @@ -0,0 +1,131 @@ +#define _POSIX_C_SOURCE 200809L +#include +#include +#include +#include +#include +#include +#include "common/dir.h" +#include "common/log.h" +#include "common/spawn.h" + +static bool +isfile(const char *path) +{ + struct stat st; + return (!stat(path, &st)); +} + +static bool +string_empty(const char *s) +{ + return !s || !*s; +} + +static void +rtrim(char **s) +{ + size_t len = strlen(*s); + if (!len) { + return; + } + char *end = *s + len - 1; + while (end >= *s && isspace(*end)) { + end--; + } + *(end + 1) = '\0'; +} + +static char * +strstrip(char *s) +{ + rtrim(&s); + while (isspace(*s)) { + s++; + } + return s; +} + +static void +process_line(char *line) +{ + if (string_empty(line) || line[0] == '#') { + return; + } + char *key = NULL, *value = NULL; + char *p = strchr(line, '='); + if (!p) { + return; + } + *p = '\0'; + key = strstrip(line); + value = strstrip(++p); + if (string_empty(key) || string_empty(value)) { + return; + } + info("setenv %s %s", key, value); + setenv(key, value, 1); +} + +void +read_environment_file(const char *filename) +{ + char *line = NULL; + size_t len = 0; + FILE *stream = fopen(filename, "r"); + if (!stream) { + return; + } + while (getline(&line, &len, stream) != -1) { + char *p = strrchr(line, '\n'); + if (p) { + *p = '\0'; + } + process_line(line); + } + free(line); + fclose(stream); +} + +static const char * +config_dir_append(const char *append) +{ + const char *config = config_dir(); + if (string_empty(config) || string_empty(append)) { + return NULL; + } + int len = strlen(config) + strlen(append) + 2; + char *buffer = calloc(len, 1); + strcat(buffer, config); + strcat(buffer, "/"); + strcat(buffer, append); + return buffer; +} + +void +session_environment_init(void) +{ + const char *environment = config_dir_append("environment"); + if (!environment) + return; + read_environment_file(environment); + free((void*)environment); +} + +void +session_autostart_init(void) +{ + const char *autostart = config_dir_append("autostart"); + if (!autostart) + return; + if (!isfile(autostart)) { + warn("no autostart file"); + return; + } + int len = strlen(autostart) + 4; + char *cmd = calloc(len, 1); + strcat(cmd, "sh "); + strcat(cmd, autostart); + spawn_async_no_shell(cmd); + free((void*)autostart); +} diff --git a/src/main.c b/src/main.c index c7c22979..6bc9fcf4 100644 --- a/src/main.c +++ b/src/main.c @@ -1,4 +1,5 @@ #include "common/spawn.h" +#include "config/session.h" #include "labwc.h" #include "theme/theme.h" #include "xbm/xbm.h" @@ -44,6 +45,8 @@ main(int argc, char *argv[]) } wlr_log_init(WLR_ERROR, NULL); + + session_environment_init(); rcxml_read(config_file); if (!getenv("XDG_RUNTIME_DIR")) { @@ -58,6 +61,7 @@ main(int argc, char *argv[]) theme_read(rc.theme_name); xbm_load(server.renderer); + session_autostart_init(); if (startup_cmd) { spawn_async_no_shell(startup_cmd); }