diff --git a/src/c2.c b/src/c2.c
index 392f90d8..425dc9fd 100644
--- a/src/c2.c
+++ b/src/c2.c
@@ -34,6 +34,8 @@
#include "utils.h"
#include "log.h"
+#pragma GCC diagnostic error "-Wunused-parameter"
+
#define C2_MAX_LEVELS 10
typedef struct _c2_b c2_b_t;
@@ -301,22 +303,19 @@ c2h_b_opcmp(c2_b_op_t op1, c2_b_op_t op2) {
}
static int
-c2_parse_grp(session_t *ps, const char *pattern, int offset, c2_ptr_t *presult, int level);
+c2_parse_grp(const char *pattern, int offset, c2_ptr_t *presult, int level);
static int
-c2_parse_target(session_t *ps, const char *pattern, int offset, c2_ptr_t *presult);
+c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult);
static int
c2_parse_op(const char *pattern, int offset, c2_ptr_t *presult);
static int
-c2_parse_pattern(session_t *ps, const char *pattern, int offset, c2_ptr_t *presult);
+c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult);
static int
-c2_parse_legacy(session_t *ps, const char *pattern, int offset, c2_ptr_t *presult);
-
-static bool
-c2_l_postprocess(session_t *ps, c2_l_t *pleaf);
+c2_parse_legacy(const char *pattern, int offset, c2_ptr_t *presult);
static void
c2_free(c2_ptr_t p);
@@ -351,7 +350,7 @@ c2_match_once(session_t *ps, win *w, const c2_ptr_t cond);
* Parse a condition string.
*/
c2_lptr_t *
-c2_parse(session_t *ps, c2_lptr_t **pcondlst, const char *pattern,
+c2_parse(c2_lptr_t **pcondlst, const char *pattern,
void *data) {
if (!pattern)
return NULL;
@@ -361,9 +360,9 @@ c2_parse(session_t *ps, c2_lptr_t **pcondlst, const char *pattern,
int offset = -1;
if (strlen(pattern) >= 2 && ':' == pattern[1])
- offset = c2_parse_legacy(ps, pattern, 0, &result);
+ offset = c2_parse_legacy(pattern, 0, &result);
else
- offset = c2_parse_grp(ps, pattern, 0, &result, 0);
+ offset = c2_parse_grp(pattern, 0, &result, 0);
if (offset < 0) {
c2_freep(&result);
@@ -405,7 +404,7 @@ c2_parse(session_t *ps, c2_lptr_t **pcondlst, const char *pattern,
* @return offset of next character in string
*/
static int
-c2_parse_grp(session_t *ps, const char *pattern, int offset, c2_ptr_t *presult, int level) {
+c2_parse_grp(const char *pattern, int offset, c2_ptr_t *presult, int level) {
// Check for recursion levels
if (level > C2_MAX_LEVELS)
c2_error("Exceeded maximum recursion levels.");
@@ -505,12 +504,12 @@ c2_parse_grp(session_t *ps, const char *pattern, int offset, c2_ptr_t *presult,
// It's a subgroup if it starts with '('
if ('(' == pattern[offset]) {
- if ((offset = c2_parse_grp(ps, pattern, offset + 1, pele, level + 1)) < 0)
+ if ((offset = c2_parse_grp(pattern, offset + 1, pele, level + 1)) < 0)
goto fail;
}
// Otherwise it's a leaf
else {
- if ((offset = c2_parse_target(ps, pattern, offset, pele)) < 0)
+ if ((offset = c2_parse_target(pattern, offset, pele)) < 0)
goto fail;
assert(!pele->isbranch && !c2_ptr_isempty(*pele));
@@ -518,10 +517,7 @@ c2_parse_grp(session_t *ps, const char *pattern, int offset, c2_ptr_t *presult,
if ((offset = c2_parse_op(pattern, offset, pele)) < 0)
goto fail;
- if ((offset = c2_parse_pattern(ps, pattern, offset, pele)) < 0)
- goto fail;
-
- if (!c2_l_postprocess(ps, pele->l))
+ if ((offset = c2_parse_pattern(pattern, offset, pele)) < 0)
goto fail;
}
// Decrement offset -- we will increment it in loop update
@@ -579,7 +575,7 @@ fail:
* Parse the target part of a rule.
*/
static int
-c2_parse_target(session_t *ps, const char *pattern, int offset, c2_ptr_t *presult) {
+c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
// Initialize leaf
presult->isbranch = false;
presult->l = cmalloc(c2_l_t);
@@ -838,7 +834,7 @@ fail:
* Parse the pattern part of a leaf.
*/
static int
-c2_parse_pattern(session_t *ps, const char *pattern, int offset, c2_ptr_t *presult) {
+c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult) {
c2_l_t * const pleaf = presult->l;
// Exists operator cannot have pattern
@@ -977,7 +973,7 @@ fail:
* Parse a condition with legacy syntax.
*/
static int
-c2_parse_legacy(session_t *ps, const char *pattern, int offset, c2_ptr_t *presult) {
+c2_parse_legacy(const char *pattern, int offset, c2_ptr_t *presult) {
unsigned plen = strlen(pattern + offset);
if (plen < 4 || ':' != pattern[offset + 1]
@@ -1033,9 +1029,6 @@ c2_parse_legacy(session_t *ps, const char *pattern, int offset, c2_ptr_t *presul
// Copy the pattern
pleaf->ptnstr = strdup(pattern + offset);
- if (!c2_l_postprocess(ps, pleaf))
- return -1;
-
return offset;
fail:
@@ -1145,6 +1138,25 @@ c2_l_postprocess(session_t *ps, c2_l_t *pleaf) {
return true;
}
+
+static bool c2_tree_postprocess(session_t *ps, c2_ptr_t node) {
+ if (!node.isbranch) {
+ return c2_l_postprocess(ps, node.l);
+ }
+ if (!c2_tree_postprocess(ps, node.b->opr1))
+ return false;
+ return c2_tree_postprocess(ps, node.b->opr2);
+}
+
+bool c2_list_postprocess(session_t *ps, c2_lptr_t *list) {
+ c2_lptr_t *head = list;
+ while (head) {
+ if (!c2_tree_postprocess(ps, head->ptr))
+ return false;
+ head = head->next;
+ }
+ return true;
+}
/**
* Free a condition tree.
*/
diff --git a/src/c2.h b/src/c2.h
index 8f50bdf4..370241dd 100644
--- a/src/c2.h
+++ b/src/c2.h
@@ -17,13 +17,11 @@ typedef struct _c2_lptr c2_lptr_t;
typedef struct session session_t;
typedef struct win win;
-c2_lptr_t *
-c2_parse(session_t *ps, c2_lptr_t **pcondlst, const char *pattern,
- void *data);
+c2_lptr_t *c2_parse(c2_lptr_t **pcondlst, const char *pattern, void *data);
-c2_lptr_t *
-c2_free_lptr(c2_lptr_t *lp);
+c2_lptr_t *c2_free_lptr(c2_lptr_t *lp);
-bool
-c2_match(session_t *ps, win *w, const c2_lptr_t *condlst,
- const c2_lptr_t **cache, void **pdata);
+bool c2_match(session_t *ps, win *w, const c2_lptr_t *condlst, const c2_lptr_t **cache,
+ void **pdata);
+
+bool c2_list_postprocess(session_t *ps, c2_lptr_t *list);
diff --git a/src/common.h b/src/common.h
index fb4e4654..baf9aefb 100644
--- a/src/common.h
+++ b/src/common.h
@@ -122,6 +122,7 @@
#include "utils.h"
#include "compiler.h"
#include "kernel.h"
+#include "options.h"
// === Constants ===
@@ -155,9 +156,6 @@
/// @brief Maximum OpenGL buffer age.
#define CGLX_MAX_BUFFER_AGE 5
-/// @brief Maximum passes for blur.
-#define MAX_BLUR_PASS 5
-
// Window flags
// Window size is changed
@@ -173,9 +171,6 @@
// === Types ===
-typedef long time_ms_t;
-typedef struct _c2_lptr c2_lptr_t;
-
/// Structure representing needed window updates.
typedef struct {
bool shadow : 1;
@@ -206,25 +201,6 @@ enum wincond_type {
#define CONDF_IGNORECASE 0x0001
-/// VSync modes.
-typedef enum {
- VSYNC_NONE,
- VSYNC_DRM,
- VSYNC_OPENGL,
- VSYNC_OPENGL_OML,
- VSYNC_OPENGL_SWC,
- VSYNC_OPENGL_MSWC,
- NUM_VSYNC,
-} vsync_t;
-
-/// @brief Possible backends of compton.
-enum backend {
- BKEND_XRENDER,
- BKEND_GLX,
- BKEND_XR_GLX_HYBRID,
- NUM_BKEND,
-};
-
/// @brief Possible swap methods.
enum {
SWAPM_BUFFER_AGE = -1,
@@ -371,202 +347,6 @@ typedef struct _latom {
#define REG_DATA_INIT { NULL, 0 }
-typedef struct win_option_mask {
- bool shadow: 1;
- bool fade: 1;
- bool focus: 1;
- bool full_shadow: 1;
- bool redir_ignore: 1;
- bool opacity: 1;
-} win_option_mask_t;
-
-typedef struct win_option {
- bool shadow;
- bool fade;
- bool focus;
- bool full_shadow;
- bool redir_ignore;
- double opacity;
-} win_option_t;
-
-/// Structure representing all options.
-typedef struct options_t {
- // === Debugging ===
- bool monitor_repaint;
- bool print_diagnostics;
- // === General ===
- /// The configuration file we used.
- char *config_file;
- /// Path to write PID to.
- char *write_pid_path;
- /// The backend in use.
- enum backend backend;
- /// Whether to sync X drawing to avoid certain delay issues with
- /// GLX backend.
- bool xrender_sync;
- /// Whether to sync X drawing with X Sync fence.
- bool xrender_sync_fence;
- /// Whether to avoid using stencil buffer under GLX backend. Might be
- /// unsafe.
- bool glx_no_stencil;
- /// Whether to avoid rebinding pixmap on window damage.
- bool glx_no_rebind_pixmap;
- /// GLX swap method we assume OpenGL uses.
- int glx_swap_method;
- /// Whether to use GL_EXT_gpu_shader4 to (hopefully) accelerates blurring.
- bool glx_use_gpushader4;
- /// Custom fragment shader for painting windows, as a string.
- char *glx_fshader_win_str;
- /// Custom GLX program used for painting window.
- glx_prog_main_t glx_prog_win;
- /// Whether to fork to background.
- bool fork_after_register;
- /// Whether to detect rounded corners.
- bool detect_rounded_corners;
- /// Force painting of window content with blending.
- bool force_win_blend;
- /// Resize damage for a specific number of pixels.
- int resize_damage;
- /// Whether to unredirect all windows if a full-screen opaque window
- /// is detected.
- bool unredir_if_possible;
- /// List of conditions of windows to ignore as a full-screen window
- /// when determining if a window could be unredirected.
- c2_lptr_t *unredir_if_possible_blacklist;
- /// Delay before unredirecting screen.
- time_ms_t unredir_if_possible_delay;
- /// Forced redirection setting through D-Bus.
- switch_t redirected_force;
- /// Whether to stop painting. Controlled through D-Bus.
- switch_t stoppaint_force;
- /// Whether to re-redirect screen on root size change.
- bool reredir_on_root_change;
- /// Whether to reinitialize GLX on root size change.
- bool glx_reinit_on_root_change;
- /// Whether to enable D-Bus support.
- bool dbus;
- /// Path to log file.
- char *logpath;
- /// Number of cycles to paint in benchmark mode. 0 for disabled.
- int benchmark;
- /// Window to constantly repaint in benchmark mode. 0 for full-screen.
- Window benchmark_wid;
- /// A list of conditions of windows not to paint.
- c2_lptr_t *paint_blacklist;
- /// Whether to show all X errors.
- bool show_all_xerrors;
- /// Whether to avoid acquiring X Selection.
- bool no_x_selection;
- /// Window type option override.
- win_option_t wintype_option[NUM_WINTYPES];
-
- // === VSync & software optimization ===
- /// User-specified refresh rate.
- int refresh_rate;
- /// Whether to enable refresh-rate-based software optimization.
- bool sw_opti;
- /// VSync method to use;
- vsync_t vsync;
- /// Whether to do VSync aggressively.
- bool vsync_aggressive;
- /// Whether to use glFinish() instead of glFlush() for (possibly) better
- /// VSync yet probably higher CPU usage.
- bool vsync_use_glfinish;
-
- // === Shadow ===
- /// Red, green and blue tone of the shadow.
- double shadow_red, shadow_green, shadow_blue;
- int shadow_radius;
- int shadow_offset_x, shadow_offset_y;
- double shadow_opacity;
- /// argument string to shadow-exclude-reg option
- char *shadow_exclude_reg_str;
- /// Shadow blacklist. A linked list of conditions.
- c2_lptr_t *shadow_blacklist;
- /// Whether bounding-shaped window should be ignored.
- bool shadow_ignore_shaped;
- /// Whether to respect _COMPTON_SHADOW.
- bool respect_prop_shadow;
- /// Whether to crop shadow to the very Xinerama screen.
- bool xinerama_shadow_crop;
-
- // === Fading ===
- /// How much to fade in in a single fading step.
- opacity_t fade_in_step;
- /// How much to fade out in a single fading step.
- opacity_t fade_out_step;
- /// Fading time delta. In milliseconds.
- time_ms_t fade_delta;
- /// Whether to disable fading on window open/close.
- bool no_fading_openclose;
- /// Whether to disable fading on ARGB managed destroyed windows.
- bool no_fading_destroyed_argb;
- /// Fading blacklist. A linked list of conditions.
- c2_lptr_t *fade_blacklist;
-
- // === Opacity ===
- /// Default opacity for inactive windows.
- /// 32-bit integer with the format of _NET_WM_OPACITY. 0 stands for
- /// not enabled, default.
- opacity_t inactive_opacity;
- /// Default opacity for inactive windows.
- opacity_t active_opacity;
- /// Whether inactive_opacity overrides the opacity set by window
- /// attributes.
- bool inactive_opacity_override;
- /// Frame opacity. Relative to window opacity, also affects shadow
- /// opacity.
- double frame_opacity;
- /// Whether to detect _NET_WM_OPACITY on client windows. Used on window
- /// managers that don't pass _NET_WM_OPACITY to frame windows.
- bool detect_client_opacity;
-
- // === Other window processing ===
- /// Whether to blur background of semi-transparent / ARGB windows.
- bool blur_background;
- /// Whether to blur background when the window frame is not opaque.
- /// Implies blur_background.
- bool blur_background_frame;
- /// Whether to use fixed blur strength instead of adjusting according
- /// to window opacity.
- bool blur_background_fixed;
- /// Background blur blacklist. A linked list of conditions.
- c2_lptr_t *blur_background_blacklist;
- /// Blur convolution kernel.
- xcb_render_fixed_t *blur_kerns[MAX_BLUR_PASS];
- /// How much to dim an inactive window. 0.0 - 1.0, 0 to disable.
- double inactive_dim;
- /// Whether to use fixed inactive dim opacity, instead of deciding
- /// based on window opacity.
- bool inactive_dim_fixed;
- /// Conditions of windows to have inverted colors.
- c2_lptr_t *invert_color_list;
- /// Rules to change window opacity.
- c2_lptr_t *opacity_rules;
-
- // === Focus related ===
- /// Whether to try to detect WM windows and mark them as focused.
- bool mark_wmwin_focused;
- /// Whether to mark override-redirect windows as focused.
- bool mark_ovredir_focused;
- /// Whether to use EWMH _NET_ACTIVE_WINDOW to find active window.
- bool use_ewmh_active_win;
- /// A list of windows always to be considered focused.
- c2_lptr_t *focus_blacklist;
- /// Whether to do window grouping with WM_TRANSIENT_FOR
.
- bool detect_transient;
- /// Whether to do window grouping with WM_CLIENT_LEADER
.
- bool detect_client_leader;
-
- // === Calculated ===
- /// Whether compton needs to track focus changes.
- bool track_focus;
- /// Whether compton needs to track window name and class.
- bool track_wdata;
- /// Whether compton needs to track window leaders.
- bool track_leader;
-} options_t;
-
#ifdef CONFIG_OPENGL
/// Structure containing GLX-dependent data for a compton session.
typedef struct {
@@ -687,6 +467,9 @@ typedef struct session {
#ifdef CONFIG_OPENGL
/// Pointer to GLX data.
glx_session_t *psglx;
+ /// Custom GLX program used for painting window.
+ // XXX should be in glx_session_t
+ glx_prog_main_t glx_prog_win;
#endif
// === Operation related ===
@@ -710,7 +493,7 @@ typedef struct session {
/// Pre-generated alpha pictures.
xcb_render_picture_t *alpha_picts;
/// Time of last fading. In milliseconds.
- time_ms_t fade_time;
+ unsigned long fade_time;
/// Head pointer of the error ignore linked list.
ignore_t *ignore_head;
/// Pointer to the next
member of tail element of the error
@@ -894,8 +677,6 @@ typedef enum {
} win_evmode_t;
extern const char * const WINTYPES[NUM_WINTYPES];
-extern const char * const VSYNC_STRS[NUM_VSYNC + 1];
-extern const char * const BACKEND_STRS[NUM_BKEND + 1];
extern session_t *ps_g;
// == Debugging code ==
@@ -924,7 +705,7 @@ timeval_isempty(struct timeval *ptv) {
* @return > 0 if ptv > ms, 0 if ptv == 0, -1 if ptv < ms
*/
static inline int
-timeval_ms_cmp(struct timeval *ptv, time_ms_t ms) {
+timeval_ms_cmp(struct timeval *ptv, unsigned long ms) {
assert(ptv);
// We use those if statement instead of a - expression because of possible
@@ -1067,97 +848,6 @@ print_timestamp(session_t *ps) {
fprintf(stderr, "[ %5ld.%06ld ] ", diff.tv_sec, diff.tv_usec);
}
-/**
- * Parse a VSync option argument.
- */
-static inline bool
-parse_vsync(session_t *ps, const char *str) {
- for (vsync_t i = 0; VSYNC_STRS[i]; ++i)
- if (!strcasecmp(str, VSYNC_STRS[i])) {
- ps->o.vsync = i;
- return true;
- }
-
- log_error("Invalid vsync argument: %s", str);
- return false;
-}
-
-/**
- * Parse a backend option argument.
- */
-static inline bool
-parse_backend(session_t *ps, const char *str) {
- for (enum backend i = 0; BACKEND_STRS[i]; ++i)
- if (!strcasecmp(str, BACKEND_STRS[i])) {
- ps->o.backend = i;
- return true;
- }
- // Keep compatibility with an old revision containing a spelling mistake...
- if (!strcasecmp(str, "xr_glx_hybird")) {
- ps->o.backend = BKEND_XR_GLX_HYBRID;
- return true;
- }
- // cju wants to use dashes
- if (!strcasecmp(str, "xr-glx-hybrid")) {
- ps->o.backend = BKEND_XR_GLX_HYBRID;
- return true;
- }
- log_error("Invalid backend argument: %s", str);
- return false;
-}
-
-/**
- * Parse a glx_swap_method option argument.
- */
-static inline bool
-parse_glx_swap_method(session_t *ps, const char *str) {
- // Parse alias
- if (!strcmp("undefined", str)) {
- ps->o.glx_swap_method = 0;
- return true;
- }
-
- if (!strcmp("copy", str)) {
- ps->o.glx_swap_method = 1;
- return true;
- }
-
- if (!strcmp("exchange", str)) {
- ps->o.glx_swap_method = 2;
- return true;
- }
-
- if (!strcmp("buffer-age", str)) {
- ps->o.glx_swap_method = -1;
- return true;
- }
-
- // Parse number
- {
- char *pc = NULL;
- int age = strtol(str, &pc, 0);
- if (!pc || str == pc) {
- log_error("glx-swap-method is an invalid number: %s", str);
- return false;
- }
-
- for (; *pc; ++pc)
- if (!isspace(*pc)) {
- log_error("Trailing characters in glx-swap-method option: %s", str);
- return false;
- }
-
- if (age > CGLX_MAX_BUFFER_AGE + 1 || age < -1) {
- log_error("Number for glx-swap-method is too large / too small: %s", str);
- return false;
- }
-
- ps->o.glx_swap_method = age;
- }
-
- return true;
-}
-
/**
* Wrapper of XFree() for convenience.
*
diff --git a/src/compton.c b/src/compton.c
index 1b86536b..a32ca60c 100644
--- a/src/compton.c
+++ b/src/compton.c
@@ -190,7 +190,7 @@ free_win_res(session_t *ps, win *w) {
/**
* Get current system clock in milliseconds.
*/
-static inline time_ms_t
+static inline unsigned long
get_time_ms(void) {
struct timeval tv;
@@ -350,7 +350,11 @@ void add_damage(session_t *ps, const region_t *damage) {
*/
static double
fade_timeout(session_t *ps) {
- int diff = ps->o.fade_delta - get_time_ms() + ps->fade_time;
+ auto now = get_time_ms();
+ if (ps->o.fade_delta + ps->fade_time < now)
+ return 0;
+
+ int diff = ps->o.fade_delta + ps->fade_time - now;
diff = normalize_i_range(diff, 0, ps->o.fade_delta * 2);
@@ -547,13 +551,13 @@ paint_preprocess(session_t *ps, win *list) {
win *t = NULL, *next = NULL;
// Fading step calculation
- time_ms_t steps = 0L;
- if (ps->fade_time)
- steps = (get_time_ms() - ps->fade_time +
- FADE_DELTA_TOLERANCE*ps->o.fade_delta) /
- ps->o.fade_delta;
- // Reset fade_time if unset, or there appears to be a time disorder
- if (!ps->fade_time || steps < 0L) {
+ unsigned long steps = 0L;
+ auto now = get_time_ms();
+ auto tolerance = FADE_DELTA_TOLERANCE*ps->o.fade_delta;
+ if (ps->fade_time && now+tolerance >= ps->fade_time) {
+ steps = (now - ps->fade_time + tolerance) / ps->o.fade_delta;
+ } else {
+ // Reset fade_time if unset, or there appears to be a time disorder
ps->fade_time = get_time_ms();
steps = 0L;
}
@@ -2567,13 +2571,13 @@ session_init(session_t *ps_old, int argc, char **argv) {
.tgt_picture = None,
.tgt_buffer = PAINT_INIT,
.reg_win = None,
+#ifdef CONFIG_OPENGL
+ .glx_prog_win = GLX_PROG_MAIN_INIT,
+#endif
.o = {
.config_file = NULL,
.backend = BKEND_XRENDER,
.glx_no_stencil = false,
-#ifdef CONFIG_OPENGL
- .glx_prog_win = GLX_PROG_MAIN_INIT,
-#endif
.mark_wmwin_focused = false,
.mark_ovredir_focused = false,
.fork_after_register = false,
@@ -2830,8 +2834,28 @@ session_init(session_t *ps_old, int argc, char **argv) {
xcb_discard_reply(ps->c,
xcb_xfixes_query_version(ps->c, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION).sequence);
- // Second pass
- get_cfg(ps, argc, argv);
+ // Parse configuration file
+ win_option_mask_t winopt_mask[NUM_WINTYPES] = {{0}};
+ bool shadow_enabled = false, fading_enable = false, hasneg = false;
+ char *config_file = parse_config(&ps->o, ps->o.config_file, &shadow_enabled,
+ &fading_enable, &hasneg, winopt_mask);
+ free(ps->o.config_file);
+ ps->o.config_file = config_file;
+
+ // Parse all of the rest command line options
+ get_cfg(&ps->o, argc, argv, shadow_enabled, fading_enable, hasneg, winopt_mask);
+
+ // Get needed atoms for c2 condition lists
+ if (!(c2_list_postprocess(ps, ps->o.unredir_if_possible_blacklist) &&
+ c2_list_postprocess(ps, ps->o.paint_blacklist) &&
+ c2_list_postprocess(ps, ps->o.shadow_blacklist) &&
+ c2_list_postprocess(ps, ps->o.fade_blacklist) &&
+ c2_list_postprocess(ps, ps->o.blur_background_blacklist) &&
+ c2_list_postprocess(ps, ps->o.invert_color_list) &&
+ c2_list_postprocess(ps, ps->o.opacity_rules) &&
+ c2_list_postprocess(ps, ps->o.focus_blacklist))) {
+ log_error("Post-processing of conditionals failed, some of your rules might not work");
+ }
rebuild_shadow_exclude_reg(ps);
diff --git a/src/config.c b/src/config.c
index 5bc6b758..ae8a1684 100644
--- a/src/config.c
+++ b/src/config.c
@@ -59,8 +59,10 @@ parse_matrix_readnum(const char *src, double *dest) {
* Parse a matrix.
*/
xcb_render_fixed_t *
-parse_matrix(session_t *ps, const char *src, const char **endptr) {
+parse_matrix(const char *src, const char **endptr, bool *hasneg) {
int wid = 0, hei = 0;
+ *hasneg = false;
+
const char *pc = NULL;
// Get matrix width and height
@@ -95,7 +97,6 @@ parse_matrix(session_t *ps, const char *src, const char **endptr) {
// Read elements
{
int skip = hei / 2 * wid + wid / 2;
- bool hasneg = false;
for (int i = 0; i < wid * hei; ++i) {
// Ignore the center element
if (i == skip) {
@@ -106,12 +107,9 @@ parse_matrix(session_t *ps, const char *src, const char **endptr) {
if (src == (pc = parse_matrix_readnum(src, &val)))
goto err2;
src = pc;
- if (val < 0) hasneg = true;
+ if (val < 0) *hasneg = true;
matrix[2 + i] = DOUBLE_TO_XFIXED(val);
}
- if (BKEND_XRENDER == ps->o.backend && hasneg)
- log_warn("A convolution kernel with negative values may not work properly under X "
- "Render backend.");
}
// Detect trailing characters
@@ -151,17 +149,23 @@ err1:
/**
* Parse a convolution kernel.
+ *
+ * Output:
+ * hasneg: whether the convolution kernel has negative values
*/
xcb_render_fixed_t *
-parse_conv_kern(session_t *ps, const char *src, const char **endptr) {
- return parse_matrix(ps, src, endptr);
+parse_conv_kern(const char *src, const char **endptr, bool *hasneg) {
+ return parse_matrix(src, endptr, hasneg);
}
/**
* Parse a list of convolution kernels.
+ *
+ * Output:
+ * hasneg: whether any of the convolution kernel has negative values
*/
bool
-parse_conv_kern_lst(session_t *ps, const char *src, xcb_render_fixed_t **dest, int max) {
+parse_conv_kern_lst(const char *src, xcb_render_fixed_t **dest, int max, bool *hasneg) {
static const struct {
const char *name;
const char *kern_str;
@@ -175,10 +179,13 @@ parse_conv_kern_lst(session_t *ps, const char *src, xcb_render_fixed_t **dest, i
{ "9x9gaussian", "9,9,0.000000,0.000000,0.000001,0.000006,0.000012,0.000006,0.000001,0.000000,0.000000,0.000000,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003,0.000000,0.000001,0.000102,0.003493,0.029143,0.059106,0.029143,0.003493,0.000102,0.000001,0.000006,0.000849,0.029143,0.243117,0.493069,0.243117,0.029143,0.000849,0.000006,0.000012,0.001723,0.059106,0.493069,0.493069,0.059106,0.001723,0.000012,0.000006,0.000849,0.029143,0.243117,0.493069,0.243117,0.029143,0.000849,0.000006,0.000001,0.000102,0.003493,0.029143,0.059106,0.029143,0.003493,0.000102,0.000001,0.000000,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003,0.000000,0.000000,0.000000,0.000001,0.000006,0.000012,0.000006,0.000001,0.000000,0.000000," },
{ "11x11gaussian", "11,11,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000001,0.000006,0.000012,0.000006,0.000001,0.000000,0.000000,0.000000,0.000000,0.000000,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003,0.000000,0.000000,0.000000,0.000001,0.000102,0.003493,0.029143,0.059106,0.029143,0.003493,0.000102,0.000001,0.000000,0.000000,0.000006,0.000849,0.029143,0.243117,0.493069,0.243117,0.029143,0.000849,0.000006,0.000000,0.000000,0.000012,0.001723,0.059106,0.493069,0.493069,0.059106,0.001723,0.000012,0.000000,0.000000,0.000006,0.000849,0.029143,0.243117,0.493069,0.243117,0.029143,0.000849,0.000006,0.000000,0.000000,0.000001,0.000102,0.003493,0.029143,0.059106,0.029143,0.003493,0.000102,0.000001,0.000000,0.000000,0.000000,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003,0.000000,0.000000,0.000000,0.000000,0.000000,0.000001,0.000006,0.000012,0.000006,0.000001,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000," },
};
+
+ *hasneg = false;
+
for (unsigned int i = 0;
i < sizeof(CONV_KERN_PREDEF) / sizeof(CONV_KERN_PREDEF[0]); ++i)
if (!strcmp(CONV_KERN_PREDEF[i].name, src))
- return parse_conv_kern_lst(ps, CONV_KERN_PREDEF[i].kern_str, dest, max);
+ return parse_conv_kern_lst(CONV_KERN_PREDEF[i].kern_str, dest, max, hasneg);
int i = 0;
const char *pc = src;
@@ -192,8 +199,10 @@ parse_conv_kern_lst(session_t *ps, const char *src, xcb_render_fixed_t **dest, i
// Continue parsing until the end of source string
i = 0;
while (pc && *pc && i < max - 1) {
- if (!(dest[i++] = parse_conv_kern(ps, pc, &pc)))
+ bool tmp_hasneg;
+ if (!(dest[i++] = parse_conv_kern(pc, &pc, &tmp_hasneg)))
return false;
+ *hasneg |= tmp_hasneg;
}
if (i > 1) {
@@ -300,7 +309,7 @@ parse_geometry_end:
/**
* Parse a list of opacity rules.
*/
-bool parse_rule_opacity(session_t *ps, const char *src) {
+bool parse_rule_opacity(c2_lptr_t **res, const char *src) {
// Find opacity value
char *endptr = NULL;
long val = strtol(src, &endptr, 0);
@@ -324,27 +333,30 @@ bool parse_rule_opacity(session_t *ps, const char *src) {
// Parse pattern
// I hope 1-100 is acceptable for (void *)
- return c2_parse(ps, &ps->o.opacity_rules, endptr, (void *) val);
+ return c2_parse(res, endptr, (void *) val);
}
/**
* Add a pattern to a condition linked list.
*/
bool
-condlst_add(session_t *ps, c2_lptr_t **pcondlst, const char *pattern) {
+condlst_add(c2_lptr_t **pcondlst, const char *pattern) {
if (!pattern)
return false;
- if (!c2_parse(ps, pcondlst, pattern, NULL))
+ if (!c2_parse(pcondlst, pattern, NULL))
exit(1);
return true;
}
-void parse_config(session_t *ps, bool *shadow_enable, bool *fading_enable,
- win_option_mask_t *winopt_mask) {
+char *parse_config(options_t *opt, const char *config_file,
+ bool *shadow_enable, bool *fading_enable, bool *hasneg,
+ win_option_mask_t *winopt_mask) {
+ char *ret = NULL;
#ifdef CONFIG_LIBCONFIG
- parse_config_libconfig(ps, shadow_enable, fading_enable, winopt_mask);
+ ret = parse_config_libconfig(opt, config_file, shadow_enable, fading_enable,
+ hasneg, winopt_mask);
#endif
// Apply default wintype options that does not depends on global options.
@@ -354,7 +366,7 @@ void parse_config(session_t *ps, bool *shadow_enable, bool *fading_enable,
// Except desktop windows are always drawn without shadow.
if (!winopt_mask[WINTYPE_DESKTOP].shadow) {
winopt_mask[WINTYPE_DESKTOP].shadow = true;
- ps->o.wintype_option[WINTYPE_DESKTOP].shadow = false;
+ opt->wintype_option[WINTYPE_DESKTOP].shadow = false;
}
// Focused/unfocused state only apply to a few window types, all other windows
@@ -364,27 +376,28 @@ void parse_config(session_t *ps, bool *shadow_enable, bool *fading_enable,
for (unsigned long i = 0; i < ARR_SIZE(nofocus_type); i++) {
if (!winopt_mask[nofocus_type[i]].focus) {
winopt_mask[nofocus_type[i]].focus = true;
- ps->o.wintype_option[nofocus_type[i]].focus = false;
+ opt->wintype_option[nofocus_type[i]].focus = false;
}
}
for (unsigned long i = 0; i < NUM_WINTYPES; i++) {
if (!winopt_mask[i].focus) {
winopt_mask[i].focus = true;
- ps->o.wintype_option[i].focus = true;
+ opt->wintype_option[i].focus = true;
}
if (!winopt_mask[i].full_shadow) {
winopt_mask[i].full_shadow = true;
- ps->o.wintype_option[i].full_shadow = false;
+ opt->wintype_option[i].full_shadow = false;
}
if (!winopt_mask[i].redir_ignore) {
winopt_mask[i].redir_ignore = true;
- ps->o.wintype_option[i].redir_ignore = false;
+ opt->wintype_option[i].redir_ignore = false;
}
if (!winopt_mask[i].opacity) {
winopt_mask[i].opacity = true;
// Opacity is not set to a concrete number here because the opacity logic
// is complicated, and needs an "unset" state
- ps->o.wintype_option[i].opacity = NAN;
+ opt->wintype_option[i].opacity = NAN;
}
}
+ return ret;
}
diff --git a/src/config.h b/src/config.h
index a0e59d9c..04deea24 100644
--- a/src/config.h
+++ b/src/config.h
@@ -1,7 +1,11 @@
-#pragma once
// SPDX-License-Identifier: MIT
// Copyright (c) 2011-2013, Christopher Jeffrey
// Copyright (c) 2013 Richard Grenville
+// Copyright (c) 2018 Yuxuan Shui
+#pragma once
+
+/// Common functions and definitions for configuration parsing
+/// Used for command line arguments and config files
#include
@@ -11,25 +15,348 @@
#include "common.h"
-bool parse_long(const char *, long *);
-const char *parse_matrix_readnum(const char *, double *);
-xcb_render_fixed_t *parse_matrix(session_t *, const char *, const char **);
-xcb_render_fixed_t *parse_conv_kern(session_t *, const char *, const char **);
-bool parse_conv_kern_lst(session_t *, const char *, xcb_render_fixed_t **, int);
-bool parse_geometry(session_t *, const char *, region_t *);
-bool parse_rule_opacity(session_t *, const char *);
+/// VSync modes.
+typedef enum {
+ VSYNC_NONE,
+ VSYNC_DRM,
+ VSYNC_OPENGL,
+ VSYNC_OPENGL_OML,
+ VSYNC_OPENGL_SWC,
+ VSYNC_OPENGL_MSWC,
+ NUM_VSYNC,
+} vsync_t;
+
+/// @brief Possible backends of compton.
+enum backend {
+ BKEND_XRENDER,
+ BKEND_GLX,
+ BKEND_XR_GLX_HYBRID,
+ NUM_BKEND,
+};
+
+typedef struct win_option_mask {
+ bool shadow : 1;
+ bool fade : 1;
+ bool focus : 1;
+ bool full_shadow : 1;
+ bool redir_ignore : 1;
+ bool opacity : 1;
+} win_option_mask_t;
+
+typedef struct win_option {
+ bool shadow;
+ bool fade;
+ bool focus;
+ bool full_shadow;
+ bool redir_ignore;
+ double opacity;
+} win_option_t;
+
+typedef struct _c2_lptr c2_lptr_t;
+
+// This macro is here because this is the maximum number
+// of blur passes options_t can hold, not a limitation of
+// rendering.
+/// @brief Maximum passes for blur.
+#define MAX_BLUR_PASS 5
+
+/// Structure representing all options.
+typedef struct options_t {
+ // === Debugging ===
+ bool monitor_repaint;
+ bool print_diagnostics;
+ // === General ===
+ /// The configuration file we used.
+ char *config_file;
+ /// Path to write PID to.
+ char *write_pid_path;
+ /// The backend in use.
+ enum backend backend;
+ /// Whether to sync X drawing to avoid certain delay issues with
+ /// GLX backend.
+ bool xrender_sync;
+ /// Whether to sync X drawing with X Sync fence.
+ bool xrender_sync_fence;
+ /// Whether to avoid using stencil buffer under GLX backend. Might be
+ /// unsafe.
+ bool glx_no_stencil;
+ /// Whether to avoid rebinding pixmap on window damage.
+ bool glx_no_rebind_pixmap;
+ /// GLX swap method we assume OpenGL uses.
+ int glx_swap_method;
+ /// Whether to use GL_EXT_gpu_shader4 to (hopefully) accelerates blurring.
+ bool glx_use_gpushader4;
+ /// Custom fragment shader for painting windows, as a string.
+ char *glx_fshader_win_str;
+ /// Whether to fork to background.
+ bool fork_after_register;
+ /// Whether to detect rounded corners.
+ bool detect_rounded_corners;
+ /// Force painting of window content with blending.
+ bool force_win_blend;
+ /// Resize damage for a specific number of pixels.
+ int resize_damage;
+ /// Whether to unredirect all windows if a full-screen opaque window
+ /// is detected.
+ bool unredir_if_possible;
+ /// List of conditions of windows to ignore as a full-screen window
+ /// when determining if a window could be unredirected.
+ c2_lptr_t *unredir_if_possible_blacklist;
+ /// Delay before unredirecting screen, in milliseconds.
+ unsigned long unredir_if_possible_delay;
+ /// Forced redirection setting through D-Bus.
+ switch_t redirected_force;
+ /// Whether to stop painting. Controlled through D-Bus.
+ switch_t stoppaint_force;
+ /// Whether to re-redirect screen on root size change.
+ bool reredir_on_root_change;
+ /// Whether to reinitialize GLX on root size change.
+ bool glx_reinit_on_root_change;
+ /// Whether to enable D-Bus support.
+ bool dbus;
+ /// Path to log file.
+ char *logpath;
+ /// Number of cycles to paint in benchmark mode. 0 for disabled.
+ int benchmark;
+ /// Window to constantly repaint in benchmark mode. 0 for full-screen.
+ Window benchmark_wid;
+ /// A list of conditions of windows not to paint.
+ c2_lptr_t *paint_blacklist;
+ /// Whether to show all X errors.
+ bool show_all_xerrors;
+ /// Whether to avoid acquiring X Selection.
+ bool no_x_selection;
+ /// Window type option override.
+ win_option_t wintype_option[NUM_WINTYPES];
+
+ // === VSync & software optimization ===
+ /// User-specified refresh rate.
+ int refresh_rate;
+ /// Whether to enable refresh-rate-based software optimization.
+ bool sw_opti;
+ /// VSync method to use;
+ vsync_t vsync;
+ /// Whether to do VSync aggressively.
+ bool vsync_aggressive;
+ /// Whether to use glFinish() instead of glFlush() for (possibly) better
+ /// VSync yet probably higher CPU usage.
+ bool vsync_use_glfinish;
+
+ // === Shadow ===
+ /// Red, green and blue tone of the shadow.
+ double shadow_red, shadow_green, shadow_blue;
+ int shadow_radius;
+ int shadow_offset_x, shadow_offset_y;
+ double shadow_opacity;
+ /// argument string to shadow-exclude-reg option
+ char *shadow_exclude_reg_str;
+ /// Shadow blacklist. A linked list of conditions.
+ c2_lptr_t *shadow_blacklist;
+ /// Whether bounding-shaped window should be ignored.
+ bool shadow_ignore_shaped;
+ /// Whether to respect _COMPTON_SHADOW.
+ bool respect_prop_shadow;
+ /// Whether to crop shadow to the very Xinerama screen.
+ bool xinerama_shadow_crop;
+
+ // === Fading ===
+ /// How much to fade in in a single fading step.
+ opacity_t fade_in_step;
+ /// How much to fade out in a single fading step.
+ opacity_t fade_out_step;
+ /// Fading time delta. In milliseconds.
+ unsigned long fade_delta;
+ /// Whether to disable fading on window open/close.
+ bool no_fading_openclose;
+ /// Whether to disable fading on ARGB managed destroyed windows.
+ bool no_fading_destroyed_argb;
+ /// Fading blacklist. A linked list of conditions.
+ c2_lptr_t *fade_blacklist;
+
+ // === Opacity ===
+ /// Default opacity for inactive windows.
+ /// 32-bit integer with the format of _NET_WM_OPACITY. 0 stands for
+ /// not enabled, default.
+ opacity_t inactive_opacity;
+ /// Default opacity for inactive windows.
+ opacity_t active_opacity;
+ /// Whether inactive_opacity overrides the opacity set by window
+ /// attributes.
+ bool inactive_opacity_override;
+ /// Frame opacity. Relative to window opacity, also affects shadow
+ /// opacity.
+ double frame_opacity;
+ /// Whether to detect _NET_WM_OPACITY on client windows. Used on window
+ /// managers that don't pass _NET_WM_OPACITY to frame windows.
+ bool detect_client_opacity;
+
+ // === Other window processing ===
+ /// Whether to blur background of semi-transparent / ARGB windows.
+ bool blur_background;
+ /// Whether to blur background when the window frame is not opaque.
+ /// Implies blur_background.
+ bool blur_background_frame;
+ /// Whether to use fixed blur strength instead of adjusting according
+ /// to window opacity.
+ bool blur_background_fixed;
+ /// Background blur blacklist. A linked list of conditions.
+ c2_lptr_t *blur_background_blacklist;
+ /// Blur convolution kernel.
+ xcb_render_fixed_t *blur_kerns[MAX_BLUR_PASS];
+ /// How much to dim an inactive window. 0.0 - 1.0, 0 to disable.
+ double inactive_dim;
+ /// Whether to use fixed inactive dim opacity, instead of deciding
+ /// based on window opacity.
+ bool inactive_dim_fixed;
+ /// Conditions of windows to have inverted colors.
+ c2_lptr_t *invert_color_list;
+ /// Rules to change window opacity.
+ c2_lptr_t *opacity_rules;
+
+ // === Focus related ===
+ /// Whether to try to detect WM windows and mark them as focused.
+ bool mark_wmwin_focused;
+ /// Whether to mark override-redirect windows as focused.
+ bool mark_ovredir_focused;
+ /// Whether to use EWMH _NET_ACTIVE_WINDOW to find active window.
+ bool use_ewmh_active_win;
+ /// A list of windows always to be considered focused.
+ c2_lptr_t *focus_blacklist;
+ /// Whether to do window grouping with WM_TRANSIENT_FOR
.
+ bool detect_transient;
+ /// Whether to do window grouping with WM_CLIENT_LEADER
.
+ bool detect_client_leader;
+
+ // === Calculated ===
+ /// Whether compton needs to track focus changes.
+ bool track_focus;
+ /// Whether compton needs to track window name and class.
+ bool track_wdata;
+ /// Whether compton needs to track window leaders.
+ bool track_leader;
+} options_t;
+
+extern const char *const VSYNC_STRS[NUM_VSYNC + 1];
+extern const char *const BACKEND_STRS[NUM_BKEND + 1];
+
+attr_warn_unused_result bool parse_long(const char *, long *);
+attr_warn_unused_result const char *parse_matrix_readnum(const char *, double *);
+attr_warn_unused_result xcb_render_fixed_t *
+parse_matrix(const char *, const char **, bool *hasneg);
+attr_warn_unused_result xcb_render_fixed_t *
+parse_conv_kern(const char *, const char **, bool *hasneg);
+attr_warn_unused_result bool
+parse_conv_kern_lst(const char *, xcb_render_fixed_t **, int, bool *hasneg);
+attr_warn_unused_result bool parse_geometry(session_t *, const char *, region_t *);
+attr_warn_unused_result bool parse_rule_opacity(c2_lptr_t **, const char *);
/**
* Add a pattern to a condition linked list.
*/
-bool condlst_add(session_t *, c2_lptr_t **, const char *);
+bool condlst_add(c2_lptr_t **, const char *);
#ifdef CONFIG_LIBCONFIG
-void
-parse_config_libconfig(session_t *ps, bool *shadow_enable,
- bool *fading_enable, win_option_mask_t *winopt_mask);
+/// Parse a configuration file
+/// Returns the actually config_file name used, allocated on heap
+/// Outputs:
+/// shadow_enable = whether shaodw is enabled globally
+/// fading_enable = whether fading is enabled globally
+/// win_option_mask = whether option overrides for specific window type is set for given
+/// options
+/// hasneg = whether the convolution kernel has negative values
+char *
+parse_config_libconfig(options_t *, const char *config_file, bool *shadow_enable,
+ bool *fading_enable, bool *hasneg, win_option_mask_t *winopt_mask);
#endif
-void
-parse_config(session_t *ps, bool *shadow_enable,
- bool *fading_enable, win_option_mask_t *winopt_mask);
+/// Parse a configuration file is that is enabled, also initialize the winopt_mask with
+/// default values
+/// Outputs and returns:
+/// same as parse_config_libconfig
+char *parse_config(options_t *, const char *config_file, bool *shadow_enable,
+ bool *fading_enable, bool *hasneg, win_option_mask_t *winopt_mask);
+
+/**
+ * Parse a backend option argument.
+ */
+static inline attr_const enum backend parse_backend(const char *str) {
+ for (enum backend i = 0; BACKEND_STRS[i]; ++i) {
+ if (!strcasecmp(str, BACKEND_STRS[i])) {
+ return i;
+ }
+ }
+ // Keep compatibility with an old revision containing a spelling mistake...
+ if (!strcasecmp(str, "xr_glx_hybird")) {
+ log_warn("backend xr_glx_hybird should be xr_glx_hybrid, the misspelt"
+ "version will be removed soon.");
+ return BKEND_XR_GLX_HYBRID;
+ }
+ // cju wants to use dashes
+ if (!strcasecmp(str, "xr-glx-hybrid")) {
+ log_warn("backend xr-glx-hybrid should be xr_glx_hybrid, the alternative"
+ "version will be removed soon.");
+ return BKEND_XR_GLX_HYBRID;
+ }
+ log_error("Invalid backend argument: %s", str);
+ return NUM_BKEND;
+}
+
+/**
+ * Parse a glx_swap_method option argument.
+ *
+ * Returns -2 on failure
+ */
+static inline attr_const int parse_glx_swap_method(const char *str) {
+ // Parse alias
+ if (!strcmp("undefined", str)) {
+ return 0;
+ }
+
+ if (!strcmp("copy", str)) {
+ return 1;
+ }
+
+ if (!strcmp("exchange", str)) {
+ return 2;
+ }
+
+ if (!strcmp("buffer-age", str)) {
+ return -1;
+ }
+
+ // Parse number
+ char *pc = NULL;
+ int age = strtol(str, &pc, 0);
+ if (!pc || str == pc) {
+ log_error("glx-swap-method is an invalid number: %s", str);
+ return -2;
+ }
+
+ for (; *pc; ++pc)
+ if (!isspace(*pc)) {
+ log_error("Trailing characters in glx-swap-method option: %s", str);
+ return -2;
+ }
+
+ if (age < -1) {
+ log_error("Number for glx-swap-method is too small: %s", str);
+ return -2;
+ }
+
+ return age;
+}
+
+/**
+ * Parse a VSync option argument.
+ */
+static inline vsync_t parse_vsync(const char *str) {
+ for (vsync_t i = 0; VSYNC_STRS[i]; ++i)
+ if (!strcasecmp(str, VSYNC_STRS[i])) {
+ return i;
+ }
+
+ log_error("Invalid vsync argument: %s", str);
+ return NUM_VSYNC;
+}
+
+// vim: set noet sw=8 ts=8 :
diff --git a/src/config_libconfig.c b/src/config_libconfig.c
index 1804a8f6..959182c1 100644
--- a/src/config_libconfig.c
+++ b/src/config_libconfig.c
@@ -12,8 +12,11 @@
#include "common.h"
#include "config.h"
#include "string_utils.h"
+#include "options.h"
#include "log.h"
+#pragma GCC diagnostic error "-Wunused-parameter"
+
/**
* Wrapper of libconfig's config_lookup_int
.
*
@@ -36,7 +39,7 @@ lcfg_lookup_bool(const config_t *config, const char *path, bool *value) {
* Follows the XDG specification to search for the configuration file.
*/
FILE *
-open_config_file(char *cpath, char **ppath) {
+open_config_file(const char *cpath, char **ppath) {
static const char *config_paths[] = {
"/compton.conf",
"/compton/compton.conf"
@@ -46,7 +49,7 @@ open_config_file(char *cpath, char **ppath) {
if (cpath) {
FILE *ret = fopen(cpath, "r");
if (ret && ppath)
- *ppath = cpath;
+ *ppath = strdup(cpath);
return ret;
}
@@ -82,7 +85,7 @@ open_config_file(char *cpath, char **ppath) {
* Parse a condition list in configuration file.
*/
void
-parse_cfg_condlst(session_t *ps, const config_t *pcfg, c2_lptr_t **pcondlst,
+parse_cfg_condlst(const config_t *pcfg, c2_lptr_t **pcondlst,
const char *name) {
config_setting_t *setting = config_lookup(pcfg, name);
if (setting) {
@@ -90,11 +93,11 @@ parse_cfg_condlst(session_t *ps, const config_t *pcfg, c2_lptr_t **pcondlst,
if (config_setting_is_array(setting)) {
int i = config_setting_length(setting);
while (i--)
- condlst_add(ps, pcondlst, config_setting_get_string_elem(setting, i));
+ condlst_add(pcondlst, config_setting_get_string_elem(setting, i));
}
// Treat it as a single pattern if it's a string
else if (CONFIG_TYPE_STRING == config_setting_type(setting)) {
- condlst_add(ps, pcondlst, config_setting_get_string(setting));
+ condlst_add(pcondlst, config_setting_get_string(setting));
}
}
}
@@ -103,29 +106,32 @@ parse_cfg_condlst(session_t *ps, const config_t *pcfg, c2_lptr_t **pcondlst,
* Parse an opacity rule list in configuration file.
*/
static inline void
-parse_cfg_condlst_opct(session_t *ps, const config_t *pcfg, const char *name) {
+parse_cfg_condlst_opct(options_t *opt, const config_t *pcfg, const char *name) {
config_setting_t *setting = config_lookup(pcfg, name);
if (setting) {
// Parse an array of options
if (config_setting_is_array(setting)) {
int i = config_setting_length(setting);
while (i--)
- if (!parse_rule_opacity(ps, config_setting_get_string_elem(setting,
- i)))
+ if (!parse_rule_opacity(&opt->opacity_rules,
+ config_setting_get_string_elem(setting, i)))
exit(1);
}
// Treat it as a single pattern if it's a string
- else if (CONFIG_TYPE_STRING == config_setting_type(setting)) {
- parse_rule_opacity(ps, config_setting_get_string(setting));
+ else if (config_setting_type(setting) == CONFIG_TYPE_STRING) {
+ if (!parse_rule_opacity(&opt->opacity_rules, config_setting_get_string(setting)))
+ exit(1);
}
}
}
/**
* Parse a configuration file from default location.
+ *
+ * Returns the actually config_file name
*/
-void parse_config_libconfig(session_t *ps, bool *shadow_enable,
- bool *fading_enable, win_option_mask_t *winopt_mask)
+char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shadow_enable,
+ bool *fading_enable, bool *conv_kern_hasneg, win_option_mask_t *winopt_mask)
{
char *path = NULL;
FILE *f;
@@ -137,16 +143,14 @@ void parse_config_libconfig(session_t *ps, bool *shadow_enable,
// anything
const char *sval = NULL;
- f = open_config_file(ps->o.config_file, &path);
+ f = open_config_file(config_file, &path);
if (!f) {
- if (ps->o.config_file) {
- free(ps->o.config_file);
- ps->o.config_file = NULL;
-
- log_fatal("Failed to read configuration file \"%s\".", ps->o.config_file);
+ if (config_file) {
+ log_fatal("Failed to read configuration file \"%s\".", config_file);
abort();
}
- return;
+ free(path);
+ return NULL;
}
config_init(&cfg);
@@ -171,44 +175,39 @@ void parse_config_libconfig(session_t *ps, bool *shadow_enable,
path, config_error_line(&cfg), config_error_text(&cfg));
config_destroy(&cfg);
free(path);
- return;
+ return NULL;
}
}
config_set_auto_convert(&cfg, 1);
- if (path != ps->o.config_file) {
- assert(ps->o.config_file == NULL);
- ps->o.config_file = path;
- }
-
// Get options from the configuration file. We don't do range checking
// right now. It will be done later
// -D (fade_delta)
if (config_lookup_int(&cfg, "fade-delta", &ival))
- ps->o.fade_delta = ival;
+ opt->fade_delta = ival;
// -I (fade_in_step)
if (config_lookup_float(&cfg, "fade-in-step", &dval))
- ps->o.fade_in_step = normalize_d(dval) * OPAQUE;
+ opt->fade_in_step = normalize_d(dval) * OPAQUE;
// -O (fade_out_step)
if (config_lookup_float(&cfg, "fade-out-step", &dval))
- ps->o.fade_out_step = normalize_d(dval) * OPAQUE;
+ opt->fade_out_step = normalize_d(dval) * OPAQUE;
// -r (shadow_radius)
- config_lookup_int(&cfg, "shadow-radius", &ps->o.shadow_radius);
+ config_lookup_int(&cfg, "shadow-radius", &opt->shadow_radius);
// -o (shadow_opacity)
- config_lookup_float(&cfg, "shadow-opacity", &ps->o.shadow_opacity);
+ config_lookup_float(&cfg, "shadow-opacity", &opt->shadow_opacity);
// -l (shadow_offset_x)
- config_lookup_int(&cfg, "shadow-offset-x", &ps->o.shadow_offset_x);
+ config_lookup_int(&cfg, "shadow-offset-x", &opt->shadow_offset_x);
// -t (shadow_offset_y)
- config_lookup_int(&cfg, "shadow-offset-y", &ps->o.shadow_offset_y);
+ config_lookup_int(&cfg, "shadow-offset-y", &opt->shadow_offset_y);
// -i (inactive_opacity)
if (config_lookup_float(&cfg, "inactive-opacity", &dval))
- ps->o.inactive_opacity = normalize_d(dval) * OPAQUE;
+ opt->inactive_opacity = normalize_d(dval) * OPAQUE;
// --active_opacity
if (config_lookup_float(&cfg, "active-opacity", &dval))
- ps->o.active_opacity = normalize_d(dval) * OPAQUE;
+ opt->active_opacity = normalize_d(dval) * OPAQUE;
// -e (frame_opacity)
- config_lookup_float(&cfg, "frame-opacity", &ps->o.frame_opacity);
+ config_lookup_float(&cfg, "frame-opacity", &opt->frame_opacity);
// -c (shadow_enable)
if (config_lookup_bool(&cfg, "shadow", &ival))
*shadow_enable = ival;
@@ -216,22 +215,22 @@ void parse_config_libconfig(session_t *ps, bool *shadow_enable,
if (config_lookup_bool(&cfg, "no-dock-shadow", &ival)) {
log_warn("Option `no-dock-shadow` is deprecated, and will be removed."
" Please use the wintype option `shadow` of `dock` instead.");
- ps->o.wintype_option[WINTYPE_DOCK].shadow = false;
+ opt->wintype_option[WINTYPE_DOCK].shadow = false;
winopt_mask[WINTYPE_DOCK].shadow = true;
}
// -G (no_dnd_shadow)
if (config_lookup_bool(&cfg, "no-dnd-shadow", &ival)) {
log_warn("Option `no-dnd-shadow` is deprecated, and will be removed."
" Please use the wintype option `shadow` of `dnd` instead.");
- ps->o.wintype_option[WINTYPE_DND].shadow = false;
+ opt->wintype_option[WINTYPE_DND].shadow = false;
winopt_mask[WINTYPE_DND].shadow = true;
};
// -m (menu_opacity)
if (config_lookup_float(&cfg, "menu-opacity", &dval)) {
log_warn("Option `menu-opacity` is deprecated, and will be removed.Please use the "
"wintype option `opacity` of `popup_menu` and `dropdown_menu` instead.");
- ps->o.wintype_option[WINTYPE_DROPDOWN_MENU].opacity = dval;
- ps->o.wintype_option[WINTYPE_POPUP_MENU].opacity = dval;
+ opt->wintype_option[WINTYPE_DROPDOWN_MENU].opacity = dval;
+ opt->wintype_option[WINTYPE_POPUP_MENU].opacity = dval;
winopt_mask[WINTYPE_DROPDOWN_MENU].opacity = true;
winopt_mask[WINTYPE_POPUP_MENU].opacity = true;
}
@@ -239,52 +238,58 @@ void parse_config_libconfig(session_t *ps, bool *shadow_enable,
if (config_lookup_bool(&cfg, "fading", &ival))
*fading_enable = ival;
// --no-fading-open-close
- lcfg_lookup_bool(&cfg, "no-fading-openclose", &ps->o.no_fading_openclose);
+ lcfg_lookup_bool(&cfg, "no-fading-openclose", &opt->no_fading_openclose);
// --no-fading-destroyed-argb
lcfg_lookup_bool(&cfg, "no-fading-destroyed-argb",
- &ps->o.no_fading_destroyed_argb);
+ &opt->no_fading_destroyed_argb);
// --shadow-red
- config_lookup_float(&cfg, "shadow-red", &ps->o.shadow_red);
+ config_lookup_float(&cfg, "shadow-red", &opt->shadow_red);
// --shadow-green
- config_lookup_float(&cfg, "shadow-green", &ps->o.shadow_green);
+ config_lookup_float(&cfg, "shadow-green", &opt->shadow_green);
// --shadow-blue
- config_lookup_float(&cfg, "shadow-blue", &ps->o.shadow_blue);
+ config_lookup_float(&cfg, "shadow-blue", &opt->shadow_blue);
// --shadow-exclude-reg
if (config_lookup_string(&cfg, "shadow-exclude-reg", &sval))
- ps->o.shadow_exclude_reg_str = strdup(sval);
+ opt->shadow_exclude_reg_str = strdup(sval);
// --inactive-opacity-override
lcfg_lookup_bool(&cfg, "inactive-opacity-override",
- &ps->o.inactive_opacity_override);
+ &opt->inactive_opacity_override);
// --inactive-dim
- config_lookup_float(&cfg, "inactive-dim", &ps->o.inactive_dim);
+ config_lookup_float(&cfg, "inactive-dim", &opt->inactive_dim);
// --mark-wmwin-focused
- lcfg_lookup_bool(&cfg, "mark-wmwin-focused", &ps->o.mark_wmwin_focused);
+ lcfg_lookup_bool(&cfg, "mark-wmwin-focused", &opt->mark_wmwin_focused);
// --mark-ovredir-focused
lcfg_lookup_bool(&cfg, "mark-ovredir-focused",
- &ps->o.mark_ovredir_focused);
+ &opt->mark_ovredir_focused);
// --shadow-ignore-shaped
lcfg_lookup_bool(&cfg, "shadow-ignore-shaped",
- &ps->o.shadow_ignore_shaped);
+ &opt->shadow_ignore_shaped);
// --detect-rounded-corners
lcfg_lookup_bool(&cfg, "detect-rounded-corners",
- &ps->o.detect_rounded_corners);
+ &opt->detect_rounded_corners);
// --xinerama-shadow-crop
lcfg_lookup_bool(&cfg, "xinerama-shadow-crop",
- &ps->o.xinerama_shadow_crop);
+ &opt->xinerama_shadow_crop);
// --detect-client-opacity
lcfg_lookup_bool(&cfg, "detect-client-opacity",
- &ps->o.detect_client_opacity);
+ &opt->detect_client_opacity);
// --refresh-rate
- config_lookup_int(&cfg, "refresh-rate", &ps->o.refresh_rate);
+ config_lookup_int(&cfg, "refresh-rate", &opt->refresh_rate);
// --vsync
- if (config_lookup_string(&cfg, "vsync", &sval) && !parse_vsync(ps, sval)) {
- log_fatal("Cannot parse vsync");
- exit(1);
+ if (config_lookup_string(&cfg, "vsync", &sval)) {
+ opt->vsync = parse_vsync(sval);
+ if (opt->vsync >= NUM_VSYNC) {
+ log_fatal("Cannot parse vsync");
+ exit(1);
+ }
}
// --backend
- if (config_lookup_string(&cfg, "backend", &sval) && !parse_backend(ps, sval)) {
- log_fatal("Cannot parse backend");
- exit(1);
+ if (config_lookup_string(&cfg, "backend", &sval)) {
+ opt->backend = parse_backend(sval);
+ if (opt->backend >= NUM_BKEND) {
+ log_fatal("Cannot parse backend");
+ exit(1);
+ }
}
// --log-level
if (config_lookup_string(&cfg, "log-level", &sval)) {
@@ -296,69 +301,71 @@ void parse_config_libconfig(session_t *ps, bool *shadow_enable,
}
}
// --sw-opti
- lcfg_lookup_bool(&cfg, "sw-opti", &ps->o.sw_opti);
+ lcfg_lookup_bool(&cfg, "sw-opti", &opt->sw_opti);
// --use-ewmh-active-win
lcfg_lookup_bool(&cfg, "use-ewmh-active-win",
- &ps->o.use_ewmh_active_win);
+ &opt->use_ewmh_active_win);
// --unredir-if-possible
lcfg_lookup_bool(&cfg, "unredir-if-possible",
- &ps->o.unredir_if_possible);
+ &opt->unredir_if_possible);
// --unredir-if-possible-delay
if (config_lookup_int(&cfg, "unredir-if-possible-delay", &ival))
- ps->o.unredir_if_possible_delay = ival;
+ opt->unredir_if_possible_delay = ival;
// --inactive-dim-fixed
- lcfg_lookup_bool(&cfg, "inactive-dim-fixed", &ps->o.inactive_dim_fixed);
+ lcfg_lookup_bool(&cfg, "inactive-dim-fixed", &opt->inactive_dim_fixed);
// --detect-transient
- lcfg_lookup_bool(&cfg, "detect-transient", &ps->o.detect_transient);
+ lcfg_lookup_bool(&cfg, "detect-transient", &opt->detect_transient);
// --detect-client-leader
lcfg_lookup_bool(&cfg, "detect-client-leader",
- &ps->o.detect_client_leader);
+ &opt->detect_client_leader);
// --shadow-exclude
- parse_cfg_condlst(ps, &cfg, &ps->o.shadow_blacklist, "shadow-exclude");
+ parse_cfg_condlst(&cfg, &opt->shadow_blacklist, "shadow-exclude");
// --fade-exclude
- parse_cfg_condlst(ps, &cfg, &ps->o.fade_blacklist, "fade-exclude");
+ parse_cfg_condlst(&cfg, &opt->fade_blacklist, "fade-exclude");
// --focus-exclude
- parse_cfg_condlst(ps, &cfg, &ps->o.focus_blacklist, "focus-exclude");
+ parse_cfg_condlst(&cfg, &opt->focus_blacklist, "focus-exclude");
// --invert-color-include
- parse_cfg_condlst(ps, &cfg, &ps->o.invert_color_list, "invert-color-include");
+ parse_cfg_condlst(&cfg, &opt->invert_color_list, "invert-color-include");
// --blur-background-exclude
- parse_cfg_condlst(ps, &cfg, &ps->o.blur_background_blacklist, "blur-background-exclude");
+ parse_cfg_condlst(&cfg, &opt->blur_background_blacklist, "blur-background-exclude");
// --opacity-rule
- parse_cfg_condlst_opct(ps, &cfg, "opacity-rule");
+ parse_cfg_condlst_opct(opt, &cfg, "opacity-rule");
// --unredir-if-possible-exclude
- parse_cfg_condlst(ps, &cfg, &ps->o.unredir_if_possible_blacklist, "unredir-if-possible-exclude");
+ parse_cfg_condlst(&cfg, &opt->unredir_if_possible_blacklist, "unredir-if-possible-exclude");
// --blur-background
- lcfg_lookup_bool(&cfg, "blur-background", &ps->o.blur_background);
+ lcfg_lookup_bool(&cfg, "blur-background", &opt->blur_background);
// --blur-background-frame
lcfg_lookup_bool(&cfg, "blur-background-frame",
- &ps->o.blur_background_frame);
+ &opt->blur_background_frame);
// --blur-background-fixed
lcfg_lookup_bool(&cfg, "blur-background-fixed",
- &ps->o.blur_background_fixed);
+ &opt->blur_background_fixed);
// --blur-kern
- if (config_lookup_string(&cfg, "blur-kern", &sval)
- && !parse_conv_kern_lst(ps, sval, ps->o.blur_kerns, MAX_BLUR_PASS)) {
+ if (config_lookup_string(&cfg, "blur-kern", &sval) &&
+ !parse_conv_kern_lst(sval, opt->blur_kerns, MAX_BLUR_PASS, conv_kern_hasneg)) {
log_fatal("Cannot parse \"blur-kern\"");
exit(1);
}
// --resize-damage
- config_lookup_int(&cfg, "resize-damage", &ps->o.resize_damage);
+ config_lookup_int(&cfg, "resize-damage", &opt->resize_damage);
// --glx-no-stencil
- lcfg_lookup_bool(&cfg, "glx-no-stencil", &ps->o.glx_no_stencil);
+ lcfg_lookup_bool(&cfg, "glx-no-stencil", &opt->glx_no_stencil);
// --glx-no-rebind-pixmap
- lcfg_lookup_bool(&cfg, "glx-no-rebind-pixmap", &ps->o.glx_no_rebind_pixmap);
+ lcfg_lookup_bool(&cfg, "glx-no-rebind-pixmap", &opt->glx_no_rebind_pixmap);
// --glx-swap-method
- if (config_lookup_string(&cfg, "glx-swap-method", &sval) &&
- !parse_glx_swap_method(ps, sval)) {
- log_fatal("Cannot parse \"glx-swap-method\"");
- exit(1);
+ if (config_lookup_string(&cfg, "glx-swap-method", &sval)) {
+ opt->glx_swap_method = parse_glx_swap_method(sval);
+ if (opt->glx_swap_method == -2) {
+ log_fatal("Cannot parse \"glx-swap-method\"");
+ exit(1);
+ }
}
// --glx-use-gpushader4
- lcfg_lookup_bool(&cfg, "glx-use-gpushader4", &ps->o.glx_use_gpushader4);
+ lcfg_lookup_bool(&cfg, "glx-use-gpushader4", &opt->glx_use_gpushader4);
// --xrender-sync
- lcfg_lookup_bool(&cfg, "xrender-sync", &ps->o.xrender_sync);
+ lcfg_lookup_bool(&cfg, "xrender-sync", &opt->xrender_sync);
// --xrender-sync-fence
- lcfg_lookup_bool(&cfg, "xrender-sync-fence", &ps->o.xrender_sync_fence);
+ lcfg_lookup_bool(&cfg, "xrender-sync-fence", &opt->xrender_sync_fence);
if (lcfg_lookup_bool(&cfg, "clear-shadow", &bval))
log_warn("\"clear-shadow\" is removed as an option, and is always"
@@ -386,7 +393,7 @@ void parse_config_libconfig(session_t *ps, bool *shadow_enable,
config_setting_t *setting = config_lookup(&cfg, str);
free(str);
- win_option_t *o = &ps->o.wintype_option[i];
+ win_option_t *o = &opt->wintype_option[i];
win_option_mask_t *mask = &winopt_mask[i];
if (setting) {
if (config_setting_lookup_bool(setting, "shadow", &ival)) {
@@ -419,4 +426,5 @@ void parse_config_libconfig(session_t *ps, bool *shadow_enable,
}
config_destroy(&cfg);
+ return path;
}
diff --git a/src/dbus.c b/src/dbus.c
index 2e3c5ba6..03da24c0 100644
--- a/src/dbus.c
+++ b/src/dbus.c
@@ -1183,15 +1183,27 @@ cdbus_process_opts_set(session_t *ps, DBusMessage *msg) {
if (!cdbus_msg_get_arg(msg, 1, DBUS_TYPE_STRING, &val))
return false;
vsync_deinit(ps);
- if (!parse_vsync(ps, val)) {
- log_error(CDBUS_ERROR_BADARG_S, 1, "Value invalid.");
- cdbus_reply_err(ps, msg, CDBUS_ERROR_BADARG, CDBUS_ERROR_BADARG_S, 1, "Value invalid.");
+ auto tmp_vsync = parse_vsync(val);
+ if (tmp_vsync >= NUM_VSYNC) {
+ log_error("Failed to parse vsync: invalid value %s.", val);
+ cdbus_reply_err(ps, msg, CDBUS_ERROR_BADARG, CDBUS_ERROR_BADARG_S, 1,
+ "Value invalid.");
+ return true;
}
- else if (!vsync_init(ps)) {
- log_error(CDBUS_ERROR_CUSTOM_S, "Failed to initialize specified VSync method.");
- cdbus_reply_err(ps, msg, CDBUS_ERROR_CUSTOM, CDBUS_ERROR_CUSTOM_S, "Failed to initialize specified VSync method.");
- }
- else
+
+ auto old_vsync = ps->o.vsync;
+ ps->o.vsync = tmp_vsync;
+ if (!vsync_init(ps)) {
+ // Trying to revert back to original vsync values
+ log_error("Failed to initialize specified VSync method.");
+ ps->o.vsync = old_vsync;
+ if (!vsync_init(ps)) {
+ log_error("Failed to revert back to original VSync method.");
+ ps->o.vsync = VSYNC_NONE;
+ }
+ cdbus_reply_err(ps, msg, CDBUS_ERROR_CUSTOM, CDBUS_ERROR_CUSTOM_S,
+ "Failed to initialize specified VSync method.");
+ } else
goto cdbus_process_opts_set_success;
return true;
}
diff --git a/src/opengl.c b/src/opengl.c
index 854955e3..e6e7c2fa 100644
--- a/src/opengl.c
+++ b/src/opengl.c
@@ -230,6 +230,11 @@ glx_init(session_t *ps, bool need_render) {
}
}
+ if (ps->o.glx_swap_method > CGLX_MAX_BUFFER_AGE) {
+ log_error("glx-swap-method is too big");
+ goto glx_init_end;
+ }
+
// Get XVisualInfo
pvis = get_visualinfo_from_visual(ps, ps->vis);
if (!pvis) {
@@ -436,7 +441,7 @@ glx_destroy(session_t *ps) {
glDeleteProgram(ppass->prog);
}
- glx_free_prog_main(ps, &ps->o.glx_prog_win);
+ glx_free_prog_main(ps, &ps->glx_prog_win);
glx_check_err(ps);
diff --git a/src/options.c b/src/options.c
index 7cd0afae..ffba3066 100644
--- a/src/options.c
+++ b/src/options.c
@@ -6,9 +6,11 @@
#include
#include
-#include "options.h"
#include "common.h"
#include "config.h"
+#include "options.h"
+
+#pragma GCC diagnostic error "-Wunused-parameter"
/**
* Print usage text and exit.
@@ -502,21 +504,18 @@ bool get_early_config(int argc, char *const *argv, char **config_file, bool *all
/**
* Process arguments and configuration files.
*/
-void get_cfg(session_t *ps, int argc, char *const *argv) {
+void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
+ bool fading_enable, bool conv_kern_hasneg,
+ win_option_mask_t *winopt_mask) {
int o = 0, longopt_idx = -1;
- bool shadow_enable = false, fading_enable = false;
char *lc_numeric_old = strdup(setlocale(LC_NUMERIC, NULL));
- win_option_mask_t winopt_mask[NUM_WINTYPES] = {{0}};
-
// Enforce LC_NUMERIC locale "C" here to make sure dots are recognized
// instead of commas in atof().
setlocale(LC_NUMERIC, "C");
- parse_config(ps, &shadow_enable, &fading_enable, winopt_mask);
-
// Parse commandline arguments. Range checking will be done later.
const char *deprecation_message = "has been removed. If you encounter problems "
@@ -528,55 +527,57 @@ void get_cfg(session_t *ps, int argc, char *const *argv) {
switch (o) {
#define P_CASEBOOL(idx, option) \
case idx: \
- ps->o.option = true; \
+ opt->option = true; \
break
#define P_CASELONG(idx, option) \
case idx: \
if (!parse_long(optarg, &val)) \
exit(1); \
- ps->o.option = val; \
+ opt->option = val; \
break
+ // clang-format off
// Short options
case 'h': usage(0); break;
case 'd':
case 'S':
case 314:
case 318:
- case 320: break; P_CASELONG('D', fade_delta);
- case 'I': ps->o.fade_in_step = normalize_d(atof(optarg)) * OPAQUE; break;
- case 'O': ps->o.fade_out_step = normalize_d(atof(optarg)) * OPAQUE; break;
+ case 320: break;
+ P_CASELONG('D', fade_delta);
+ case 'I': opt->fade_in_step = normalize_d(atof(optarg)) * OPAQUE; break;
+ case 'O': opt->fade_out_step = normalize_d(atof(optarg)) * OPAQUE; break;
case 'c': shadow_enable = true; break;
case 'C':
winopt_mask[WINTYPE_DOCK].shadow = true;
- ps->o.wintype_option[WINTYPE_DOCK].shadow = true;
+ opt->wintype_option[WINTYPE_DOCK].shadow = true;
break;
case 'G':
winopt_mask[WINTYPE_DND].shadow = true;
- ps->o.wintype_option[WINTYPE_DND].shadow = true;
+ opt->wintype_option[WINTYPE_DND].shadow = true;
break;
case 'm':;
double tmp;
tmp = normalize_d(atof(optarg));
winopt_mask[WINTYPE_DROPDOWN_MENU].opacity = true;
winopt_mask[WINTYPE_POPUP_MENU].opacity = true;
- ps->o.wintype_option[WINTYPE_POPUP_MENU].opacity = tmp;
- ps->o.wintype_option[WINTYPE_DROPDOWN_MENU].opacity = tmp;
+ opt->wintype_option[WINTYPE_POPUP_MENU].opacity = tmp;
+ opt->wintype_option[WINTYPE_DROPDOWN_MENU].opacity = tmp;
break;
case 'f':
case 'F':
fading_enable = true;
break;
- P_CASELONG('r', shadow_radius);
+ P_CASELONG('r', shadow_radius);
case 'o':
- ps->o.shadow_opacity = atof(optarg);
+ opt->shadow_opacity = atof(optarg);
break;
- P_CASELONG('l', shadow_offset_x);
- P_CASELONG('t', shadow_offset_y);
+ P_CASELONG('l', shadow_offset_x);
+ P_CASELONG('t', shadow_offset_y);
case 'i':
- ps->o.inactive_opacity = (normalize_d(atof(optarg)) * OPAQUE);
+ opt->inactive_opacity = (normalize_d(atof(optarg)) * OPAQUE);
break;
- case 'e': ps->o.frame_opacity = atof(optarg); break;
+ case 'e': opt->frame_opacity = atof(optarg); break;
case 'z':
log_warn("clear-shadow is removed, shadows are automatically "
"cleared now. If you want to prevent shadow from been "
@@ -588,42 +589,43 @@ void get_cfg(session_t *ps, int argc, char *const *argv) {
case 's':
log_error("-n, -a, and -s have been removed.");
break;
- P_CASEBOOL('b', fork_after_register);
+ P_CASEBOOL('b', fork_after_register);
// Long options
case 256:
// --config
break;
case 257:
// --shadow-red
- ps->o.shadow_red = atof(optarg);
+ opt->shadow_red = atof(optarg);
break;
case 258:
// --shadow-green
- ps->o.shadow_green = atof(optarg);
+ opt->shadow_green = atof(optarg);
break;
case 259:
// --shadow-blue
- ps->o.shadow_blue = atof(optarg);
+ opt->shadow_blue = atof(optarg);
break;
- P_CASEBOOL(260, inactive_opacity_override);
+ P_CASEBOOL(260, inactive_opacity_override);
case 261:
// --inactive-dim
- ps->o.inactive_dim = atof(optarg);
+ opt->inactive_dim = atof(optarg);
break;
- P_CASEBOOL(262, mark_wmwin_focused);
+ P_CASEBOOL(262, mark_wmwin_focused);
case 263:
// --shadow-exclude
- condlst_add(ps, &ps->o.shadow_blacklist, optarg);
+ condlst_add(&opt->shadow_blacklist, optarg);
break;
- P_CASEBOOL(264, mark_ovredir_focused);
- P_CASEBOOL(265, no_fading_openclose);
- P_CASEBOOL(266, shadow_ignore_shaped);
- P_CASEBOOL(267, detect_rounded_corners);
- P_CASEBOOL(268, detect_client_opacity);
- P_CASELONG(269, refresh_rate);
+ P_CASEBOOL(264, mark_ovredir_focused);
+ P_CASEBOOL(265, no_fading_openclose);
+ P_CASEBOOL(266, shadow_ignore_shaped);
+ P_CASEBOOL(267, detect_rounded_corners);
+ P_CASEBOOL(268, detect_client_opacity);
+ P_CASELONG(269, refresh_rate);
case 270:
// --vsync
- if (!parse_vsync(ps, optarg))
+ opt->vsync = parse_vsync(optarg);
+ if (opt->vsync >= NUM_VSYNC)
exit(1);
break;
case 271:
@@ -636,109 +638,111 @@ void get_cfg(session_t *ps, int argc, char *const *argv) {
log_warn("--paint-on-overlay has been removed, and is enabled "
"when possible");
break;
- P_CASEBOOL(274, sw_opti);
- P_CASEBOOL(275, vsync_aggressive);
- P_CASEBOOL(276, use_ewmh_active_win);
- P_CASEBOOL(277, respect_prop_shadow);
- P_CASEBOOL(278, unredir_if_possible);
+ P_CASEBOOL(274, sw_opti);
+ P_CASEBOOL(275, vsync_aggressive);
+ P_CASEBOOL(276, use_ewmh_active_win);
+ P_CASEBOOL(277, respect_prop_shadow);
+ P_CASEBOOL(278, unredir_if_possible);
case 279:
// --focus-exclude
- condlst_add(ps, &ps->o.focus_blacklist, optarg);
+ condlst_add(&opt->focus_blacklist, optarg);
break;
- P_CASEBOOL(280, inactive_dim_fixed);
- P_CASEBOOL(281, detect_transient);
- P_CASEBOOL(282, detect_client_leader);
- P_CASEBOOL(283, blur_background);
- P_CASEBOOL(284, blur_background_frame);
- P_CASEBOOL(285, blur_background_fixed);
- P_CASEBOOL(286, dbus);
+ P_CASEBOOL(280, inactive_dim_fixed);
+ P_CASEBOOL(281, detect_transient);
+ P_CASEBOOL(282, detect_client_leader);
+ P_CASEBOOL(283, blur_background);
+ P_CASEBOOL(284, blur_background_frame);
+ P_CASEBOOL(285, blur_background_fixed);
+ P_CASEBOOL(286, dbus);
case 287:
// --logpath
- ps->o.logpath = strdup(optarg);
+ opt->logpath = strdup(optarg);
break;
case 288:
// --invert-color-include
- condlst_add(ps, &ps->o.invert_color_list, optarg);
+ condlst_add(&opt->invert_color_list, optarg);
break;
case 289:
// --opengl
- ps->o.backend = BKEND_GLX;
+ opt->backend = BKEND_GLX;
break;
case 290:
// --backend
- if (!parse_backend(ps, optarg))
+ opt->backend = parse_backend(optarg);
+ if (opt->backend >= NUM_BKEND)
exit(1);
break;
- P_CASEBOOL(291, glx_no_stencil);
+ P_CASEBOOL(291, glx_no_stencil);
case 292:
log_warn("--glx-copy-from-front %s", deprecation_message);
break;
- P_CASELONG(293, benchmark);
+ P_CASELONG(293, benchmark);
case 294:
// --benchmark-wid
- ps->o.benchmark_wid = strtol(optarg, NULL, 0);
+ opt->benchmark_wid = strtol(optarg, NULL, 0);
break;
case 295:
log_warn("--glx-use-copysubbuffermesa %s", deprecation_message);
break;
case 296:
// --blur-background-exclude
- condlst_add(ps, &ps->o.blur_background_blacklist, optarg);
+ condlst_add(&opt->blur_background_blacklist, optarg);
break;
case 297:
// --active-opacity
- ps->o.active_opacity = (normalize_d(atof(optarg)) * OPAQUE);
+ opt->active_opacity = (normalize_d(atof(optarg)) * OPAQUE);
break;
- P_CASEBOOL(298, glx_no_rebind_pixmap);
+ P_CASEBOOL(298, glx_no_rebind_pixmap);
case 299:
// --glx-swap-method
- if (!parse_glx_swap_method(ps, optarg))
+ opt->glx_swap_method = parse_glx_swap_method(optarg);
+ if (opt->glx_swap_method == -2)
exit(1);
break;
case 300:
// --fade-exclude
- condlst_add(ps, &ps->o.fade_blacklist, optarg);
+ condlst_add(&opt->fade_blacklist, optarg);
break;
case 301:
// --blur-kern
- if (!parse_conv_kern_lst(ps, optarg, ps->o.blur_kerns,
- MAX_BLUR_PASS))
+ if (!parse_conv_kern_lst(optarg, opt->blur_kerns,
+ MAX_BLUR_PASS, &conv_kern_hasneg))
exit(1);
break;
- P_CASELONG(302, resize_damage);
- P_CASEBOOL(303, glx_use_gpushader4);
+ P_CASELONG(302, resize_damage);
+ P_CASEBOOL(303, glx_use_gpushader4);
case 304:
// --opacity-rule
- if (!parse_rule_opacity(ps, optarg))
+ if (!parse_rule_opacity(&opt->opacity_rules, optarg))
exit(1);
break;
case 305:
// --shadow-exclude-reg
- ps->o.shadow_exclude_reg_str = strdup(optarg);
+ opt->shadow_exclude_reg_str = strdup(optarg);
log_warn("--shadow-exclude-reg is deprecated. You are likely "
"better off using --shadow-exclude anyway");
break;
case 306:
// --paint-exclude
- condlst_add(ps, &ps->o.paint_blacklist, optarg);
+ condlst_add(&opt->paint_blacklist, optarg);
break;
- P_CASEBOOL(307, xinerama_shadow_crop);
+ P_CASEBOOL(307, xinerama_shadow_crop);
case 308:
// --unredir-if-possible-exclude
- condlst_add(ps, &ps->o.unredir_if_possible_blacklist, optarg);
+ condlst_add(&opt->unredir_if_possible_blacklist, optarg);
break;
- P_CASELONG(309, unredir_if_possible_delay);
+ P_CASELONG(309, unredir_if_possible_delay);
case 310:
// --write-pid-path
- ps->o.write_pid_path = strdup(optarg);
+ opt->write_pid_path = strdup(optarg);
break;
- P_CASEBOOL(311, vsync_use_glfinish);
- P_CASEBOOL(312, xrender_sync);
- P_CASEBOOL(313, xrender_sync_fence);
- P_CASEBOOL(315, no_fading_destroyed_argb);
- P_CASEBOOL(316, force_win_blend);
+ P_CASEBOOL(311, vsync_use_glfinish);
+ P_CASEBOOL(312, xrender_sync);
+ P_CASEBOOL(313, xrender_sync_fence);
+ P_CASEBOOL(315, no_fading_destroyed_argb);
+ P_CASEBOOL(316, force_win_blend);
case 317:
- ps->o.glx_fshader_win_str = strdup(optarg);
+ opt->glx_fshader_win_str = strdup(optarg);
log_warn("--glx-fshader-win is being deprecated, and might be "
"removed in the future. If you really need this "
"feature, please report an issue to let us know");
@@ -752,38 +756,39 @@ void get_cfg(session_t *ps, int argc, char *const *argv) {
}
break;
}
- P_CASEBOOL(319, no_x_selection);
- P_CASEBOOL(731, reredir_on_root_change);
- P_CASEBOOL(732, glx_reinit_on_root_change);
- P_CASEBOOL(800, monitor_repaint);
- case 801: ps->o.print_diagnostics = true; break;
+ P_CASEBOOL(319, no_x_selection);
+ P_CASEBOOL(731, reredir_on_root_change);
+ P_CASEBOOL(732, glx_reinit_on_root_change);
+ P_CASEBOOL(800, monitor_repaint);
+ case 801: opt->print_diagnostics = true; break;
default: usage(1); break;
#undef P_CASEBOOL
}
+ // clang-format on
}
// Restore LC_NUMERIC
setlocale(LC_NUMERIC, lc_numeric_old);
free(lc_numeric_old);
- if (ps->o.monitor_repaint && ps->o.backend != BKEND_XRENDER) {
+ if (opt->monitor_repaint && opt->backend != BKEND_XRENDER) {
log_warn("--monitor-repaint has no effect when backend is not xrender");
}
// Range checking and option assignments
- ps->o.fade_delta = max_i(ps->o.fade_delta, 1);
- ps->o.shadow_radius = max_i(ps->o.shadow_radius, 0);
- ps->o.shadow_red = normalize_d(ps->o.shadow_red);
- ps->o.shadow_green = normalize_d(ps->o.shadow_green);
- ps->o.shadow_blue = normalize_d(ps->o.shadow_blue);
- ps->o.inactive_dim = normalize_d(ps->o.inactive_dim);
- ps->o.frame_opacity = normalize_d(ps->o.frame_opacity);
- ps->o.shadow_opacity = normalize_d(ps->o.shadow_opacity);
- ps->o.refresh_rate = normalize_i_range(ps->o.refresh_rate, 0, 300);
+ opt->fade_delta = max_i(opt->fade_delta, 1);
+ opt->shadow_radius = max_i(opt->shadow_radius, 0);
+ opt->shadow_red = normalize_d(opt->shadow_red);
+ opt->shadow_green = normalize_d(opt->shadow_green);
+ opt->shadow_blue = normalize_d(opt->shadow_blue);
+ opt->inactive_dim = normalize_d(opt->inactive_dim);
+ opt->frame_opacity = normalize_d(opt->frame_opacity);
+ opt->shadow_opacity = normalize_d(opt->shadow_opacity);
+ opt->refresh_rate = normalize_i_range(opt->refresh_rate, 0, 300);
// Apply default wintype options that are dependent on global options
for (int i = 0; i < NUM_WINTYPES; i++) {
- auto wo = &ps->o.wintype_option[i];
+ auto wo = &opt->wintype_option[i];
auto mask = &winopt_mask[i];
if (!mask->shadow) {
wo->shadow = shadow_enable;
@@ -796,26 +801,26 @@ void get_cfg(session_t *ps, int argc, char *const *argv) {
}
// --blur-background-frame implies --blur-background
- if (ps->o.blur_background_frame)
- ps->o.blur_background = true;
+ if (opt->blur_background_frame)
+ opt->blur_background = true;
- if (ps->o.xrender_sync_fence)
- ps->o.xrender_sync = true;
+ if (opt->xrender_sync_fence)
+ opt->xrender_sync = true;
// Other variables determined by options
// Determine whether we need to track focus changes
- if (ps->o.inactive_opacity != ps->o.active_opacity || ps->o.inactive_dim) {
- ps->o.track_focus = true;
+ if (opt->inactive_opacity != opt->active_opacity || opt->inactive_dim) {
+ opt->track_focus = true;
}
// Determine whether we track window grouping
- if (ps->o.detect_transient || ps->o.detect_client_leader) {
- ps->o.track_leader = true;
+ if (opt->detect_transient || opt->detect_client_leader) {
+ opt->track_leader = true;
}
// Fill default blur kernel
- if (ps->o.blur_background && !ps->o.blur_kerns[0]) {
+ if (opt->blur_background && !opt->blur_kerns[0]) {
// Convolution filter parameter (box blur)
// gaussian or binomial filters are definitely superior, yet looks
// like they aren't supported as of xorg-server-1.13.0
@@ -835,13 +840,17 @@ void get_cfg(session_t *ps, int argc, char *const *argv) {
DOUBLE_TO_XFIXED(1),
DOUBLE_TO_XFIXED(1),
};
- ps->o.blur_kerns[0] =
+ opt->blur_kerns[0] =
ccalloc(ARR_SIZE(convolution_blur), xcb_render_fixed_t);
- memcpy(ps->o.blur_kerns[0], convolution_blur, sizeof(convolution_blur));
+ memcpy(opt->blur_kerns[0], convolution_blur, sizeof(convolution_blur));
}
- if (ps->o.resize_damage < 0)
+ if (opt->resize_damage < 0)
log_warn("Negative --resize-damage will not work correctly.");
+
+ if (opt->backend == BKEND_XRENDER && conv_kern_hasneg)
+ log_warn("A convolution kernel with negative values may not work "
+ "properly under X Render backend.");
}
// vim: set noet sw=8 ts=8 :
diff --git a/src/options.h b/src/options.h
index 09031706..38130859 100644
--- a/src/options.h
+++ b/src/options.h
@@ -2,9 +2,15 @@
// Copyright (c) Yuxuan Shui
#pragma once
+/// Parse command line options
+
#include
+#include // for xcb_render_fixed_t
#include "compiler.h"
+#include "config.h"
+#include "types.h"
+#include "win.h" // for wintype_t
typedef struct session session_t;
@@ -15,5 +21,15 @@ bool get_early_config(int argc, char *const *argv, char **config_file, bool *all
/**
* Process arguments and configuration files.
+ *
+ * Parameters:
+ * shadow_enable = Carry overs from parse_config
+ * fading_enable
+ * conv_kern_hasneg
+ * winopt_mask
*/
-void get_cfg(session_t *ps, int argc, char *const *argv);
+void get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
+ bool fading_enable, bool conv_kern_hasneg,
+ win_option_mask_t *winopt_mask);
+
+// vim: set noet sw=8 ts=8:
diff --git a/src/render.c b/src/render.c
index d61dc5cf..8e316bac 100644
--- a/src/render.c
+++ b/src/render.c
@@ -4,6 +4,7 @@
#include
#include "common.h"
+#include "options.h"
#ifdef CONFIG_OPENGL
#include "opengl.h"
@@ -125,7 +126,12 @@ paint_region(session_t *ps, win *w, int x, int y, int wid, int hei, double opaci
render(ps, x, y, dx, dy, wid, hei, opacity, argb, neg, pict,
(w ? w->paint.ptex : ps->root_tile_paint.ptex), reg_paint,
- (w ? &ps->o.glx_prog_win : NULL));
+#ifdef CONFIG_OPENGL
+ w ? &ps->glx_prog_win : NULL
+#else
+ NULL
+#endif
+ );
}
/**
@@ -1223,7 +1229,7 @@ bool init_render(session_t *ps) {
if (BKEND_GLX == ps->o.backend && ps->o.glx_fshader_win_str) {
#ifdef CONFIG_OPENGL
if (!glx_load_prog_main(ps, NULL, ps->o.glx_fshader_win_str,
- &ps->o.glx_prog_win))
+ &ps->glx_prog_win))
return false;
#else
log_error("GLSL supported not compiled in, can't load "