From cb7d852b0f41d673577629e43a6b179fd5a4d01d Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Fri, 21 Dec 2018 16:25:28 +0000 Subject: [PATCH 1/2] Clean up options/config file parsing * Pass a options_t, not session_t * Slightly improve error handling when setting vsync method via dbus The goal here is to limit the scope of what a given function can access. And session_t contains basically everything, so don't pass it around. Signed-off-by: Yuxuan Shui --- src/c2.c | 58 ++++--- src/c2.h | 14 +- src/common.h | 322 +------------------------------------ src/compton.c | 52 ++++-- src/config.c | 61 ++++--- src/config.h | 357 +++++++++++++++++++++++++++++++++++++++-- src/config_libconfig.c | 188 +++++++++++----------- src/dbus.c | 28 +++- src/opengl.c | 7 +- src/options.c | 223 +++++++++++++------------ src/options.h | 18 ++- src/render.c | 10 +- 12 files changed, 729 insertions(+), 609 deletions(-) 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 " From c8a9f32b05fc9ad2416541a291ec61f5c9827d58 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Fri, 21 Dec 2018 16:48:21 +0000 Subject: [PATCH 2/2] Add debug logging to get_atom Signed-off-by: Yuxuan Shui --- src/common.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common.h b/src/common.h index baf9aefb..9a7db4ed 100644 --- a/src/common.h +++ b/src/common.h @@ -877,6 +877,7 @@ get_atom(session_t *ps, const char *atom_name) { xcb_atom_t atom = XCB_NONE; if (reply) { + log_debug("Atom %s is %d", atom_name, reply->atom); atom = reply->atom; free(reply); } else