diff options
| author | allusive-dev <[email protected]> | 2023-10-30 15:12:21 +1100 |
|---|---|---|
| committer | allusive-dev <[email protected]> | 2023-10-30 15:12:21 +1100 |
| commit | ac33357e7ce7c474aeaffc92e381020289d767a2 (patch) | |
| tree | 7f05fa79b3ccd7834f85cc65a07fbd4f8030eb94 /src/config.c | |
| parent | Create FUNDING.yml (diff) | |
| download | compfy-ac33357e7ce7c474aeaffc92e381020289d767a2.tar.xz compfy-ac33357e7ce7c474aeaffc92e381020289d767a2.zip | |
Version 1.01.0.0
Diffstat (limited to 'src/config.c')
| -rw-r--r-- | src/config.c | 236 |
1 files changed, 224 insertions, 12 deletions
diff --git a/src/config.c b/src/config.c index 1d58f00..cb5e08a 100644 --- a/src/config.c +++ b/src/config.c @@ -3,13 +3,21 @@ // Copyright (c) 2013 Richard Grenville <[email protected]> #include <ctype.h> +#include <errno.h> +#include <fcntl.h> #include <limits.h> #include <math.h> #include <stdbool.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> #include <xcb/render.h> // for xcb_render_fixed_t, XXX +#include <test.h> + #include "c2.h" #include "common.h" #include "compiler.h" @@ -23,6 +31,98 @@ #include "config.h" +const char *xdg_config_home(void) { + char *xdgh = getenv("XDG_CONFIG_HOME"); + char *home = getenv("HOME"); + const char *default_dir = "/.config"; + + if (!xdgh) { + if (!home) { + return NULL; + } + + xdgh = cvalloc(strlen(home) + strlen(default_dir) + 1); + + strcpy(xdgh, home); + strcat(xdgh, default_dir); + } else { + xdgh = strdup(xdgh); + } + + return xdgh; +} + +char **xdg_config_dirs(void) { + char *xdgd = getenv("XDG_CONFIG_DIRS"); + size_t count = 0; + + if (!xdgd) { + xdgd = "/etc/xdg"; + } + + for (int i = 0; xdgd[i]; i++) { + if (xdgd[i] == ':') { + count++; + } + } + + // Store the string and the result pointers together so they can be + // freed together + char **dir_list = cvalloc(sizeof(char *) * (count + 2) + strlen(xdgd) + 1); + auto dirs = strcpy((char *)dir_list + sizeof(char *) * (count + 2), xdgd); + auto path = dirs; + + for (size_t i = 0; i < count; i++) { + dir_list[i] = path; + path = strchr(path, ':'); + *path = '\0'; + path++; + } + dir_list[count] = path; + + size_t fill = 0; + for (size_t i = 0; i <= count; i++) { + if (dir_list[i][0] == '/') { + dir_list[fill] = dir_list[i]; + fill++; + } + } + + dir_list[fill] = NULL; + + return dir_list; +} + +TEST_CASE(xdg_config_dirs) { + auto old_var = getenv("XDG_CONFIG_DIRS"); + if (old_var) { + old_var = strdup(old_var); + } + unsetenv("XDG_CONFIG_DIRS"); + + auto result = xdg_config_dirs(); + TEST_STREQUAL(result[0], "/etc/xdg"); + TEST_EQUAL(result[1], NULL); + free(result); + + setenv("XDG_CONFIG_DIRS", ".:.:/etc/xdg:.:/:", 1); + result = xdg_config_dirs(); + TEST_STREQUAL(result[0], "/etc/xdg"); + TEST_STREQUAL(result[1], "/"); + TEST_EQUAL(result[2], NULL); + free(result); + + setenv("XDG_CONFIG_DIRS", ":", 1); + result = xdg_config_dirs(); + TEST_EQUAL(result[0], NULL); + free(result); + + if (old_var) { + setenv("XDG_CONFIG_DIRS", old_var, 1); + free(old_var); + } +} + /** * Parse a long number. */ @@ -468,6 +568,114 @@ bool parse_rule_corners(c2_lptr_t **res, const char *src) { return c2_parse(res, endptr, (void *)val); } +/// Search for auxiliary file under a base directory +static char *locate_auxiliary_file_at(const char *base, const char *scope, const char *file) { + scoped_charp path = mstrjoin(base, scope); + mstrextend(&path, "/"); + mstrextend(&path, file); + if (access(path, O_RDONLY) == 0) { + // Canonicalize path to avoid duplicates + char *abspath = realpath(path, NULL); + return abspath; + } + return NULL; +} + +/** + * Get a path of an auxiliary file to read, could be a shader file, or any supplimenrary + * file. + * + * Follows the XDG specification to search for the shader file in configuration locations. + * + * The search order is: + * 1) If an absolute path is given, use it directly. + * 2) Search for the file directly under `include_dir`. + * 3) Search for the file in the XDG configuration directories, under path + * /picom/<scope>/ + */ +char *locate_auxiliary_file(const char *scope, const char *path, const char *include_dir) { + if (!path || strlen(path) == 0) { + return NULL; + } + + // Filename is absolute path, so try to load from there + if (path[0] == '/') { + if (access(path, O_RDONLY) == 0) { + return realpath(path, NULL); + } + } + + // First try to load file from the include directory (i.e. relative to the + // config file) + if (include_dir && strlen(include_dir)) { + char *ret = locate_auxiliary_file_at(include_dir, "", path); + if (ret) { + return ret; + } + } + + // Fall back to searching in user config directory + scoped_charp picom_scope = mstrjoin("/picom/", scope); + scoped_charp config_home = (char *)xdg_config_home(); + char *ret = locate_auxiliary_file_at(config_home, picom_scope, path); + if (ret) { + return ret; + } + + // Fall back to searching in system config directory + auto config_dirs = xdg_config_dirs(); + for (int i = 0; config_dirs[i]; i++) { + ret = locate_auxiliary_file_at(config_dirs[i], picom_scope, path); + if (ret) { + free(config_dirs); + return ret; + } + } + free(config_dirs); + + return ret; +} + +/** + * Parse a list of window shader rules. + */ +bool parse_rule_window_shader(c2_lptr_t **res, const char *src, const char *include_dir) { + if (!src) { + return false; + } + + // Find custom shader terminator + const char *endptr = strchr(src, ':'); + if (!endptr) { + log_error("Custom shader terminator not found: %s", src); + return false; + } + + // Parse and create custom shader + scoped_charp untrimed_shader_source = strdup(src); + if (!untrimed_shader_source) { + return false; + } + auto source_end = strchr(untrimed_shader_source, ':'); + *source_end = '\0'; + + size_t length; + char *tmp = (char *)trim_both(untrimed_shader_source, &length); + tmp[length] = '\0'; + char *shader_source = NULL; + + if (strcasecmp(tmp, "default") != 0) { + shader_source = locate_auxiliary_file("shaders", tmp, include_dir); + if (!shader_source) { + log_error("Custom shader file \"%s\" not found for rule: %s", tmp, src); + free(shader_source); + return false; + } + } + + return c2_parse(res, ++endptr, (void *)shader_source); +} + /** * Add a pattern to a condition linked list. */ @@ -578,7 +786,8 @@ char *parse_config(options_t *opt, const char *config_file, bool *shadow_enable, bool *fading_enable, bool *hasneg, win_option_mask_t *winopt_mask) { // clang-format off *opt = (struct options){ - .backend = BKEND_GLX, + .backend = BKEND_XRENDER, + .legacy_backends = false, .glx_no_stencil = false, .mark_wmwin_focused = false, .mark_ovredir_focused = false, @@ -594,14 +803,12 @@ char *parse_config(options_t *opt, const char *config_file, bool *shadow_enable, .benchmark_wid = XCB_NONE, .logpath = NULL, - .refresh_rate = 0, - .sw_opti = false, .use_damage = true, .shadow_red = 0.0, .shadow_green = 0.0, .shadow_blue = 0.0, - .shadow_radius = 12, + .shadow_radius = 18, .shadow_offset_x = -15, .shadow_offset_y = -15, .shadow_opacity = .75, @@ -610,18 +817,20 @@ char *parse_config(options_t *opt, const char *config_file, bool *shadow_enable, .xinerama_shadow_crop = false, .shadow_clip_list = NULL, - .corner_radius = 12, + .corner_radius = 0, - .fade_in_step = 0.03, + .fade_in_step = 0.028, .fade_out_step = 0.03, .fade_delta = 10, .no_fading_openclose = false, .no_fading_destroyed_argb = false, .fade_blacklist = NULL, + // Picom Allusive + .animations = true, .animation_for_open_window = OPEN_WINDOW_ANIMATION_ZOOM, - .animation_for_transient_window = OPEN_WINDOW_ANIMATION_ZOOM, + .animation_for_transient_window = OPEN_WINDOW_ANIMATION_NONE, .animation_for_unmap_window = OPEN_WINDOW_ANIMATION_ZOOM, .animation_for_workspace_switch_in = OPEN_WINDOW_ANIMATION_ZOOM, .animation_for_workspace_switch_out = OPEN_WINDOW_ANIMATION_ZOOM, @@ -631,6 +840,11 @@ char *parse_config(options_t *opt, const char *config_file, bool *shadow_enable, .animation_delta = 10, .animation_force_steps = false, .animation_clamping = true, + .animation_open_blacklist = NULL, + .animation_unmap_blacklist = NULL, + + .corner_rules = NULL, + .blur_rules = NULL, .inactive_opacity = 1.0, .inactive_opacity_override = false, @@ -647,6 +861,8 @@ char *parse_config(options_t *opt, const char *config_file, bool *shadow_enable, .blur_background_blacklist = NULL, .blur_kerns = NULL, .blur_kernel_count = 0, + .window_shader_fg = NULL, + .window_shader_fg_rules = NULL, .inactive_dim = 0.0, .inactive_dim_fixed = false, .invert_color_list = NULL, @@ -661,11 +877,7 @@ char *parse_config(options_t *opt, const char *config_file, bool *shadow_enable, .track_leader = false, - .rounded_corners_blacklist = NULL, - - .animation_open_blacklist = NULL, - .animation_unmap_blacklist = NULL, - .corner_rules = NULL + .rounded_corners_blacklist = NULL }; // clang-format on |