aboutsummaryrefslogtreecommitdiff
path: root/src/config.c
diff options
context:
space:
mode:
authorallusive-dev <[email protected]>2023-10-30 15:12:21 +1100
committerallusive-dev <[email protected]>2023-10-30 15:12:21 +1100
commitac33357e7ce7c474aeaffc92e381020289d767a2 (patch)
tree7f05fa79b3ccd7834f85cc65a07fbd4f8030eb94 /src/config.c
parentCreate FUNDING.yml (diff)
downloadcompfy-ac33357e7ce7c474aeaffc92e381020289d767a2.tar.xz
compfy-ac33357e7ce7c474aeaffc92e381020289d767a2.zip
Version 1.01.0.0
Diffstat (limited to 'src/config.c')
-rw-r--r--src/config.c236
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