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 <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2018-12-21 16:25:28 +00:00
parent ee2be09958
commit cb7d852b0f
No known key found for this signature in database
GPG Key ID: 37C999F617EA1A47
12 changed files with 729 additions and 609 deletions

View File

@ -34,6 +34,8 @@
#include "utils.h" #include "utils.h"
#include "log.h" #include "log.h"
#pragma GCC diagnostic error "-Wunused-parameter"
#define C2_MAX_LEVELS 10 #define C2_MAX_LEVELS 10
typedef struct _c2_b c2_b_t; 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 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 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 static int
c2_parse_op(const char *pattern, int offset, c2_ptr_t *presult); c2_parse_op(const char *pattern, int offset, c2_ptr_t *presult);
static int 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 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);
static bool
c2_l_postprocess(session_t *ps, c2_l_t *pleaf);
static void static void
c2_free(c2_ptr_t p); 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. * Parse a condition string.
*/ */
c2_lptr_t * 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) { void *data) {
if (!pattern) if (!pattern)
return NULL; return NULL;
@ -361,9 +360,9 @@ c2_parse(session_t *ps, c2_lptr_t **pcondlst, const char *pattern,
int offset = -1; int offset = -1;
if (strlen(pattern) >= 2 && ':' == pattern[1]) if (strlen(pattern) >= 2 && ':' == pattern[1])
offset = c2_parse_legacy(ps, pattern, 0, &result); offset = c2_parse_legacy(pattern, 0, &result);
else else
offset = c2_parse_grp(ps, pattern, 0, &result, 0); offset = c2_parse_grp(pattern, 0, &result, 0);
if (offset < 0) { if (offset < 0) {
c2_freep(&result); 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 * @return offset of next character in string
*/ */
static int 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 // Check for recursion levels
if (level > C2_MAX_LEVELS) if (level > C2_MAX_LEVELS)
c2_error("Exceeded maximum recursion 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 '(' // It's a subgroup if it starts with '('
if ('(' == pattern[offset]) { 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; goto fail;
} }
// Otherwise it's a leaf // Otherwise it's a leaf
else { else {
if ((offset = c2_parse_target(ps, pattern, offset, pele)) < 0) if ((offset = c2_parse_target(pattern, offset, pele)) < 0)
goto fail; goto fail;
assert(!pele->isbranch && !c2_ptr_isempty(*pele)); 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) if ((offset = c2_parse_op(pattern, offset, pele)) < 0)
goto fail; goto fail;
if ((offset = c2_parse_pattern(ps, pattern, offset, pele)) < 0) if ((offset = c2_parse_pattern(pattern, offset, pele)) < 0)
goto fail;
if (!c2_l_postprocess(ps, pele->l))
goto fail; goto fail;
} }
// Decrement offset -- we will increment it in loop update // Decrement offset -- we will increment it in loop update
@ -579,7 +575,7 @@ fail:
* Parse the target part of a rule. * Parse the target part of a rule.
*/ */
static int 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 // Initialize leaf
presult->isbranch = false; presult->isbranch = false;
presult->l = cmalloc(c2_l_t); presult->l = cmalloc(c2_l_t);
@ -838,7 +834,7 @@ fail:
* Parse the pattern part of a leaf. * Parse the pattern part of a leaf.
*/ */
static int 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; c2_l_t * const pleaf = presult->l;
// Exists operator cannot have pattern // Exists operator cannot have pattern
@ -977,7 +973,7 @@ fail:
* Parse a condition with legacy syntax. * Parse a condition with legacy syntax.
*/ */
static int 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); unsigned plen = strlen(pattern + offset);
if (plen < 4 || ':' != pattern[offset + 1] 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 // Copy the pattern
pleaf->ptnstr = strdup(pattern + offset); pleaf->ptnstr = strdup(pattern + offset);
if (!c2_l_postprocess(ps, pleaf))
return -1;
return offset; return offset;
fail: fail:
@ -1145,6 +1138,25 @@ c2_l_postprocess(session_t *ps, c2_l_t *pleaf) {
return true; 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. * Free a condition tree.
*/ */

View File

@ -17,13 +17,11 @@ typedef struct _c2_lptr c2_lptr_t;
typedef struct session session_t; typedef struct session session_t;
typedef struct win win; typedef struct win win;
c2_lptr_t * c2_lptr_t *c2_parse(c2_lptr_t **pcondlst, const char *pattern, void *data);
c2_parse(session_t *ps, c2_lptr_t **pcondlst, const char *pattern,
void *data);
c2_lptr_t * c2_lptr_t *c2_free_lptr(c2_lptr_t *lp);
c2_free_lptr(c2_lptr_t *lp);
bool bool c2_match(session_t *ps, win *w, const c2_lptr_t *condlst, const c2_lptr_t **cache,
c2_match(session_t *ps, win *w, const c2_lptr_t *condlst, void **pdata);
const c2_lptr_t **cache, void **pdata);
bool c2_list_postprocess(session_t *ps, c2_lptr_t *list);

View File

@ -122,6 +122,7 @@
#include "utils.h" #include "utils.h"
#include "compiler.h" #include "compiler.h"
#include "kernel.h" #include "kernel.h"
#include "options.h"
// === Constants === // === Constants ===
@ -155,9 +156,6 @@
/// @brief Maximum OpenGL buffer age. /// @brief Maximum OpenGL buffer age.
#define CGLX_MAX_BUFFER_AGE 5 #define CGLX_MAX_BUFFER_AGE 5
/// @brief Maximum passes for blur.
#define MAX_BLUR_PASS 5
// Window flags // Window flags
// Window size is changed // Window size is changed
@ -173,9 +171,6 @@
// === Types === // === Types ===
typedef long time_ms_t;
typedef struct _c2_lptr c2_lptr_t;
/// Structure representing needed window updates. /// Structure representing needed window updates.
typedef struct { typedef struct {
bool shadow : 1; bool shadow : 1;
@ -206,25 +201,6 @@ enum wincond_type {
#define CONDF_IGNORECASE 0x0001 #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. /// @brief Possible swap methods.
enum { enum {
SWAPM_BUFFER_AGE = -1, SWAPM_BUFFER_AGE = -1,
@ -371,202 +347,6 @@ typedef struct _latom {
#define REG_DATA_INIT { NULL, 0 } #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 <code>WM_TRANSIENT_FOR</code>.
bool detect_transient;
/// Whether to do window grouping with <code>WM_CLIENT_LEADER</code>.
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 #ifdef CONFIG_OPENGL
/// Structure containing GLX-dependent data for a compton session. /// Structure containing GLX-dependent data for a compton session.
typedef struct { typedef struct {
@ -687,6 +467,9 @@ typedef struct session {
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
/// Pointer to GLX data. /// Pointer to GLX data.
glx_session_t *psglx; 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 #endif
// === Operation related === // === Operation related ===
@ -710,7 +493,7 @@ typedef struct session {
/// Pre-generated alpha pictures. /// Pre-generated alpha pictures.
xcb_render_picture_t *alpha_picts; xcb_render_picture_t *alpha_picts;
/// Time of last fading. In milliseconds. /// Time of last fading. In milliseconds.
time_ms_t fade_time; unsigned long fade_time;
/// Head pointer of the error ignore linked list. /// Head pointer of the error ignore linked list.
ignore_t *ignore_head; ignore_t *ignore_head;
/// Pointer to the <code>next</code> member of tail element of the error /// Pointer to the <code>next</code> member of tail element of the error
@ -894,8 +677,6 @@ typedef enum {
} win_evmode_t; } win_evmode_t;
extern const char * const WINTYPES[NUM_WINTYPES]; 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; extern session_t *ps_g;
// == Debugging code == // == Debugging code ==
@ -924,7 +705,7 @@ timeval_isempty(struct timeval *ptv) {
* @return > 0 if ptv > ms, 0 if ptv == 0, -1 if ptv < ms * @return > 0 if ptv > ms, 0 if ptv == 0, -1 if ptv < ms
*/ */
static inline int static inline int
timeval_ms_cmp(struct timeval *ptv, time_ms_t ms) { timeval_ms_cmp(struct timeval *ptv, unsigned long ms) {
assert(ptv); assert(ptv);
// We use those if statement instead of a - expression because of possible // 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); 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. * Wrapper of XFree() for convenience.
* *

View File

@ -190,7 +190,7 @@ free_win_res(session_t *ps, win *w) {
/** /**
* Get current system clock in milliseconds. * Get current system clock in milliseconds.
*/ */
static inline time_ms_t static inline unsigned long
get_time_ms(void) { get_time_ms(void) {
struct timeval tv; struct timeval tv;
@ -350,7 +350,11 @@ void add_damage(session_t *ps, const region_t *damage) {
*/ */
static double static double
fade_timeout(session_t *ps) { 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); 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; win *t = NULL, *next = NULL;
// Fading step calculation // Fading step calculation
time_ms_t steps = 0L; unsigned long steps = 0L;
if (ps->fade_time) auto now = get_time_ms();
steps = (get_time_ms() - ps->fade_time + auto tolerance = FADE_DELTA_TOLERANCE*ps->o.fade_delta;
FADE_DELTA_TOLERANCE*ps->o.fade_delta) / if (ps->fade_time && now+tolerance >= ps->fade_time) {
ps->o.fade_delta; steps = (now - ps->fade_time + tolerance) / ps->o.fade_delta;
// Reset fade_time if unset, or there appears to be a time disorder } else {
if (!ps->fade_time || steps < 0L) { // Reset fade_time if unset, or there appears to be a time disorder
ps->fade_time = get_time_ms(); ps->fade_time = get_time_ms();
steps = 0L; steps = 0L;
} }
@ -2567,13 +2571,13 @@ session_init(session_t *ps_old, int argc, char **argv) {
.tgt_picture = None, .tgt_picture = None,
.tgt_buffer = PAINT_INIT, .tgt_buffer = PAINT_INIT,
.reg_win = None, .reg_win = None,
#ifdef CONFIG_OPENGL
.glx_prog_win = GLX_PROG_MAIN_INIT,
#endif
.o = { .o = {
.config_file = NULL, .config_file = NULL,
.backend = BKEND_XRENDER, .backend = BKEND_XRENDER,
.glx_no_stencil = false, .glx_no_stencil = false,
#ifdef CONFIG_OPENGL
.glx_prog_win = GLX_PROG_MAIN_INIT,
#endif
.mark_wmwin_focused = false, .mark_wmwin_focused = false,
.mark_ovredir_focused = false, .mark_ovredir_focused = false,
.fork_after_register = 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_discard_reply(ps->c,
xcb_xfixes_query_version(ps->c, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION).sequence); xcb_xfixes_query_version(ps->c, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION).sequence);
// Second pass // Parse configuration file
get_cfg(ps, argc, argv); 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); rebuild_shadow_exclude_reg(ps);

View File

@ -59,8 +59,10 @@ parse_matrix_readnum(const char *src, double *dest) {
* Parse a matrix. * Parse a matrix.
*/ */
xcb_render_fixed_t * 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; int wid = 0, hei = 0;
*hasneg = false;
const char *pc = NULL; const char *pc = NULL;
// Get matrix width and height // Get matrix width and height
@ -95,7 +97,6 @@ parse_matrix(session_t *ps, const char *src, const char **endptr) {
// Read elements // Read elements
{ {
int skip = hei / 2 * wid + wid / 2; int skip = hei / 2 * wid + wid / 2;
bool hasneg = false;
for (int i = 0; i < wid * hei; ++i) { for (int i = 0; i < wid * hei; ++i) {
// Ignore the center element // Ignore the center element
if (i == skip) { 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))) if (src == (pc = parse_matrix_readnum(src, &val)))
goto err2; goto err2;
src = pc; src = pc;
if (val < 0) hasneg = true; if (val < 0) *hasneg = true;
matrix[2 + i] = DOUBLE_TO_XFIXED(val); 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 // Detect trailing characters
@ -151,17 +149,23 @@ err1:
/** /**
* Parse a convolution kernel. * Parse a convolution kernel.
*
* Output:
* hasneg: whether the convolution kernel has negative values
*/ */
xcb_render_fixed_t * xcb_render_fixed_t *
parse_conv_kern(session_t *ps, const char *src, const char **endptr) { parse_conv_kern(const char *src, const char **endptr, bool *hasneg) {
return parse_matrix(ps, src, endptr); return parse_matrix(src, endptr, hasneg);
} }
/** /**
* Parse a list of convolution kernels. * Parse a list of convolution kernels.
*
* Output:
* hasneg: whether any of the convolution kernel has negative values
*/ */
bool 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 { static const struct {
const char *name; const char *name;
const char *kern_str; 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," }, { "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," }, { "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; for (unsigned int i = 0;
i < sizeof(CONV_KERN_PREDEF) / sizeof(CONV_KERN_PREDEF[0]); ++i) i < sizeof(CONV_KERN_PREDEF) / sizeof(CONV_KERN_PREDEF[0]); ++i)
if (!strcmp(CONV_KERN_PREDEF[i].name, src)) 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; int i = 0;
const char *pc = src; 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 // Continue parsing until the end of source string
i = 0; i = 0;
while (pc && *pc && i < max - 1) { 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; return false;
*hasneg |= tmp_hasneg;
} }
if (i > 1) { if (i > 1) {
@ -300,7 +309,7 @@ parse_geometry_end:
/** /**
* Parse a list of opacity rules. * 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 // Find opacity value
char *endptr = NULL; char *endptr = NULL;
long val = strtol(src, &endptr, 0); long val = strtol(src, &endptr, 0);
@ -324,27 +333,30 @@ bool parse_rule_opacity(session_t *ps, const char *src) {
// Parse pattern // Parse pattern
// I hope 1-100 is acceptable for (void *) // 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. * Add a pattern to a condition linked list.
*/ */
bool bool
condlst_add(session_t *ps, c2_lptr_t **pcondlst, const char *pattern) { condlst_add(c2_lptr_t **pcondlst, const char *pattern) {
if (!pattern) if (!pattern)
return false; return false;
if (!c2_parse(ps, pcondlst, pattern, NULL)) if (!c2_parse(pcondlst, pattern, NULL))
exit(1); exit(1);
return true; return true;
} }
void parse_config(session_t *ps, bool *shadow_enable, bool *fading_enable, char *parse_config(options_t *opt, const char *config_file,
win_option_mask_t *winopt_mask) { bool *shadow_enable, bool *fading_enable, bool *hasneg,
win_option_mask_t *winopt_mask) {
char *ret = NULL;
#ifdef CONFIG_LIBCONFIG #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 #endif
// Apply default wintype options that does not depends on global options. // 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. // Except desktop windows are always drawn without shadow.
if (!winopt_mask[WINTYPE_DESKTOP].shadow) { if (!winopt_mask[WINTYPE_DESKTOP].shadow) {
winopt_mask[WINTYPE_DESKTOP].shadow = true; 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 // 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++) { for (unsigned long i = 0; i < ARR_SIZE(nofocus_type); i++) {
if (!winopt_mask[nofocus_type[i]].focus) { if (!winopt_mask[nofocus_type[i]].focus) {
winopt_mask[nofocus_type[i]].focus = true; 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++) { for (unsigned long i = 0; i < NUM_WINTYPES; i++) {
if (!winopt_mask[i].focus) { if (!winopt_mask[i].focus) {
winopt_mask[i].focus = true; winopt_mask[i].focus = true;
ps->o.wintype_option[i].focus = true; opt->wintype_option[i].focus = true;
} }
if (!winopt_mask[i].full_shadow) { if (!winopt_mask[i].full_shadow) {
winopt_mask[i].full_shadow = true; 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) { if (!winopt_mask[i].redir_ignore) {
winopt_mask[i].redir_ignore = true; 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) { if (!winopt_mask[i].opacity) {
winopt_mask[i].opacity = true; winopt_mask[i].opacity = true;
// Opacity is not set to a concrete number here because the opacity logic // Opacity is not set to a concrete number here because the opacity logic
// is complicated, and needs an "unset" state // is complicated, and needs an "unset" state
ps->o.wintype_option[i].opacity = NAN; opt->wintype_option[i].opacity = NAN;
} }
} }
return ret;
} }

View File

@ -1,7 +1,11 @@
#pragma once
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// Copyright (c) 2011-2013, Christopher Jeffrey // Copyright (c) 2011-2013, Christopher Jeffrey
// Copyright (c) 2013 Richard Grenville <pyxlcy@gmail.com> // Copyright (c) 2013 Richard Grenville <pyxlcy@gmail.com>
// Copyright (c) 2018 Yuxuan Shui <yshuiv7@gmail.com>
#pragma once
/// Common functions and definitions for configuration parsing
/// Used for command line arguments and config files
#include <stdbool.h> #include <stdbool.h>
@ -11,25 +15,348 @@
#include "common.h" #include "common.h"
bool parse_long(const char *, long *); /// VSync modes.
const char *parse_matrix_readnum(const char *, double *); typedef enum {
xcb_render_fixed_t *parse_matrix(session_t *, const char *, const char **); VSYNC_NONE,
xcb_render_fixed_t *parse_conv_kern(session_t *, const char *, const char **); VSYNC_DRM,
bool parse_conv_kern_lst(session_t *, const char *, xcb_render_fixed_t **, int); VSYNC_OPENGL,
bool parse_geometry(session_t *, const char *, region_t *); VSYNC_OPENGL_OML,
bool parse_rule_opacity(session_t *, const char *); 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 <code>WM_TRANSIENT_FOR</code>.
bool detect_transient;
/// Whether to do window grouping with <code>WM_CLIENT_LEADER</code>.
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. * 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 #ifdef CONFIG_LIBCONFIG
void /// Parse a configuration file
parse_config_libconfig(session_t *ps, bool *shadow_enable, /// Returns the actually config_file name used, allocated on heap
bool *fading_enable, win_option_mask_t *winopt_mask); /// 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 #endif
void /// Parse a configuration file is that is enabled, also initialize the winopt_mask with
parse_config(session_t *ps, bool *shadow_enable, /// default values
bool *fading_enable, win_option_mask_t *winopt_mask); /// 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 :

View File

@ -12,8 +12,11 @@
#include "common.h" #include "common.h"
#include "config.h" #include "config.h"
#include "string_utils.h" #include "string_utils.h"
#include "options.h"
#include "log.h" #include "log.h"
#pragma GCC diagnostic error "-Wunused-parameter"
/** /**
* Wrapper of libconfig's <code>config_lookup_int</code>. * Wrapper of libconfig's <code>config_lookup_int</code>.
* *
@ -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. * Follows the XDG specification to search for the configuration file.
*/ */
FILE * FILE *
open_config_file(char *cpath, char **ppath) { open_config_file(const char *cpath, char **ppath) {
static const char *config_paths[] = { static const char *config_paths[] = {
"/compton.conf", "/compton.conf",
"/compton/compton.conf" "/compton/compton.conf"
@ -46,7 +49,7 @@ open_config_file(char *cpath, char **ppath) {
if (cpath) { if (cpath) {
FILE *ret = fopen(cpath, "r"); FILE *ret = fopen(cpath, "r");
if (ret && ppath) if (ret && ppath)
*ppath = cpath; *ppath = strdup(cpath);
return ret; return ret;
} }
@ -82,7 +85,7 @@ open_config_file(char *cpath, char **ppath) {
* Parse a condition list in configuration file. * Parse a condition list in configuration file.
*/ */
void 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) { const char *name) {
config_setting_t *setting = config_lookup(pcfg, name); config_setting_t *setting = config_lookup(pcfg, name);
if (setting) { 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)) { if (config_setting_is_array(setting)) {
int i = config_setting_length(setting); int i = config_setting_length(setting);
while (i--) 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 // Treat it as a single pattern if it's a string
else if (CONFIG_TYPE_STRING == config_setting_type(setting)) { 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. * Parse an opacity rule list in configuration file.
*/ */
static inline void 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); config_setting_t *setting = config_lookup(pcfg, name);
if (setting) { if (setting) {
// Parse an array of options // Parse an array of options
if (config_setting_is_array(setting)) { if (config_setting_is_array(setting)) {
int i = config_setting_length(setting); int i = config_setting_length(setting);
while (i--) while (i--)
if (!parse_rule_opacity(ps, config_setting_get_string_elem(setting, if (!parse_rule_opacity(&opt->opacity_rules,
i))) config_setting_get_string_elem(setting, i)))
exit(1); exit(1);
} }
// Treat it as a single pattern if it's a string // Treat it as a single pattern if it's a string
else if (CONFIG_TYPE_STRING == config_setting_type(setting)) { else if (config_setting_type(setting) == CONFIG_TYPE_STRING) {
parse_rule_opacity(ps, config_setting_get_string(setting)); if (!parse_rule_opacity(&opt->opacity_rules, config_setting_get_string(setting)))
exit(1);
} }
} }
} }
/** /**
* Parse a configuration file from default location. * Parse a configuration file from default location.
*
* Returns the actually config_file name
*/ */
void parse_config_libconfig(session_t *ps, bool *shadow_enable, char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shadow_enable,
bool *fading_enable, win_option_mask_t *winopt_mask) bool *fading_enable, bool *conv_kern_hasneg, win_option_mask_t *winopt_mask)
{ {
char *path = NULL; char *path = NULL;
FILE *f; FILE *f;
@ -137,16 +143,14 @@ void parse_config_libconfig(session_t *ps, bool *shadow_enable,
// anything // anything
const char *sval = NULL; const char *sval = NULL;
f = open_config_file(ps->o.config_file, &path); f = open_config_file(config_file, &path);
if (!f) { if (!f) {
if (ps->o.config_file) { if (config_file) {
free(ps->o.config_file); log_fatal("Failed to read configuration file \"%s\".", config_file);
ps->o.config_file = NULL;
log_fatal("Failed to read configuration file \"%s\".", ps->o.config_file);
abort(); abort();
} }
return; free(path);
return NULL;
} }
config_init(&cfg); 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)); path, config_error_line(&cfg), config_error_text(&cfg));
config_destroy(&cfg); config_destroy(&cfg);
free(path); free(path);
return; return NULL;
} }
} }
config_set_auto_convert(&cfg, 1); 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 // Get options from the configuration file. We don't do range checking
// right now. It will be done later // right now. It will be done later
// -D (fade_delta) // -D (fade_delta)
if (config_lookup_int(&cfg, "fade-delta", &ival)) if (config_lookup_int(&cfg, "fade-delta", &ival))
ps->o.fade_delta = ival; opt->fade_delta = ival;
// -I (fade_in_step) // -I (fade_in_step)
if (config_lookup_float(&cfg, "fade-in-step", &dval)) 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) // -O (fade_out_step)
if (config_lookup_float(&cfg, "fade-out-step", &dval)) 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) // -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) // -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) // -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) // -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) // -i (inactive_opacity)
if (config_lookup_float(&cfg, "inactive-opacity", &dval)) 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 // --active_opacity
if (config_lookup_float(&cfg, "active-opacity", &dval)) 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) // -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) // -c (shadow_enable)
if (config_lookup_bool(&cfg, "shadow", &ival)) if (config_lookup_bool(&cfg, "shadow", &ival))
*shadow_enable = 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)) { if (config_lookup_bool(&cfg, "no-dock-shadow", &ival)) {
log_warn("Option `no-dock-shadow` is deprecated, and will be removed." log_warn("Option `no-dock-shadow` is deprecated, and will be removed."
" Please use the wintype option `shadow` of `dock` instead."); " 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; winopt_mask[WINTYPE_DOCK].shadow = true;
} }
// -G (no_dnd_shadow) // -G (no_dnd_shadow)
if (config_lookup_bool(&cfg, "no-dnd-shadow", &ival)) { if (config_lookup_bool(&cfg, "no-dnd-shadow", &ival)) {
log_warn("Option `no-dnd-shadow` is deprecated, and will be removed." log_warn("Option `no-dnd-shadow` is deprecated, and will be removed."
" Please use the wintype option `shadow` of `dnd` instead."); " 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; winopt_mask[WINTYPE_DND].shadow = true;
}; };
// -m (menu_opacity) // -m (menu_opacity)
if (config_lookup_float(&cfg, "menu-opacity", &dval)) { if (config_lookup_float(&cfg, "menu-opacity", &dval)) {
log_warn("Option `menu-opacity` is deprecated, and will be removed.Please use the " log_warn("Option `menu-opacity` is deprecated, and will be removed.Please use the "
"wintype option `opacity` of `popup_menu` and `dropdown_menu` instead."); "wintype option `opacity` of `popup_menu` and `dropdown_menu` instead.");
ps->o.wintype_option[WINTYPE_DROPDOWN_MENU].opacity = dval; opt->wintype_option[WINTYPE_DROPDOWN_MENU].opacity = dval;
ps->o.wintype_option[WINTYPE_POPUP_MENU].opacity = dval; opt->wintype_option[WINTYPE_POPUP_MENU].opacity = dval;
winopt_mask[WINTYPE_DROPDOWN_MENU].opacity = true; winopt_mask[WINTYPE_DROPDOWN_MENU].opacity = true;
winopt_mask[WINTYPE_POPUP_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)) if (config_lookup_bool(&cfg, "fading", &ival))
*fading_enable = ival; *fading_enable = ival;
// --no-fading-open-close // --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 // --no-fading-destroyed-argb
lcfg_lookup_bool(&cfg, "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 // --shadow-red
config_lookup_float(&cfg, "shadow-red", &ps->o.shadow_red); config_lookup_float(&cfg, "shadow-red", &opt->shadow_red);
// --shadow-green // --shadow-green
config_lookup_float(&cfg, "shadow-green", &ps->o.shadow_green); config_lookup_float(&cfg, "shadow-green", &opt->shadow_green);
// --shadow-blue // --shadow-blue
config_lookup_float(&cfg, "shadow-blue", &ps->o.shadow_blue); config_lookup_float(&cfg, "shadow-blue", &opt->shadow_blue);
// --shadow-exclude-reg // --shadow-exclude-reg
if (config_lookup_string(&cfg, "shadow-exclude-reg", &sval)) 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 // --inactive-opacity-override
lcfg_lookup_bool(&cfg, "inactive-opacity-override", lcfg_lookup_bool(&cfg, "inactive-opacity-override",
&ps->o.inactive_opacity_override); &opt->inactive_opacity_override);
// --inactive-dim // --inactive-dim
config_lookup_float(&cfg, "inactive-dim", &ps->o.inactive_dim); config_lookup_float(&cfg, "inactive-dim", &opt->inactive_dim);
// --mark-wmwin-focused // --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 // --mark-ovredir-focused
lcfg_lookup_bool(&cfg, "mark-ovredir-focused", lcfg_lookup_bool(&cfg, "mark-ovredir-focused",
&ps->o.mark_ovredir_focused); &opt->mark_ovredir_focused);
// --shadow-ignore-shaped // --shadow-ignore-shaped
lcfg_lookup_bool(&cfg, "shadow-ignore-shaped", lcfg_lookup_bool(&cfg, "shadow-ignore-shaped",
&ps->o.shadow_ignore_shaped); &opt->shadow_ignore_shaped);
// --detect-rounded-corners // --detect-rounded-corners
lcfg_lookup_bool(&cfg, "detect-rounded-corners", lcfg_lookup_bool(&cfg, "detect-rounded-corners",
&ps->o.detect_rounded_corners); &opt->detect_rounded_corners);
// --xinerama-shadow-crop // --xinerama-shadow-crop
lcfg_lookup_bool(&cfg, "xinerama-shadow-crop", lcfg_lookup_bool(&cfg, "xinerama-shadow-crop",
&ps->o.xinerama_shadow_crop); &opt->xinerama_shadow_crop);
// --detect-client-opacity // --detect-client-opacity
lcfg_lookup_bool(&cfg, "detect-client-opacity", lcfg_lookup_bool(&cfg, "detect-client-opacity",
&ps->o.detect_client_opacity); &opt->detect_client_opacity);
// --refresh-rate // --refresh-rate
config_lookup_int(&cfg, "refresh-rate", &ps->o.refresh_rate); config_lookup_int(&cfg, "refresh-rate", &opt->refresh_rate);
// --vsync // --vsync
if (config_lookup_string(&cfg, "vsync", &sval) && !parse_vsync(ps, sval)) { if (config_lookup_string(&cfg, "vsync", &sval)) {
log_fatal("Cannot parse vsync"); opt->vsync = parse_vsync(sval);
exit(1); if (opt->vsync >= NUM_VSYNC) {
log_fatal("Cannot parse vsync");
exit(1);
}
} }
// --backend // --backend
if (config_lookup_string(&cfg, "backend", &sval) && !parse_backend(ps, sval)) { if (config_lookup_string(&cfg, "backend", &sval)) {
log_fatal("Cannot parse backend"); opt->backend = parse_backend(sval);
exit(1); if (opt->backend >= NUM_BKEND) {
log_fatal("Cannot parse backend");
exit(1);
}
} }
// --log-level // --log-level
if (config_lookup_string(&cfg, "log-level", &sval)) { if (config_lookup_string(&cfg, "log-level", &sval)) {
@ -296,69 +301,71 @@ void parse_config_libconfig(session_t *ps, bool *shadow_enable,
} }
} }
// --sw-opti // --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 // --use-ewmh-active-win
lcfg_lookup_bool(&cfg, "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 // --unredir-if-possible
lcfg_lookup_bool(&cfg, "unredir-if-possible", lcfg_lookup_bool(&cfg, "unredir-if-possible",
&ps->o.unredir_if_possible); &opt->unredir_if_possible);
// --unredir-if-possible-delay // --unredir-if-possible-delay
if (config_lookup_int(&cfg, "unredir-if-possible-delay", &ival)) 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 // --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 // --detect-transient
lcfg_lookup_bool(&cfg, "detect-transient", &ps->o.detect_transient); lcfg_lookup_bool(&cfg, "detect-transient", &opt->detect_transient);
// --detect-client-leader // --detect-client-leader
lcfg_lookup_bool(&cfg, "detect-client-leader", lcfg_lookup_bool(&cfg, "detect-client-leader",
&ps->o.detect_client_leader); &opt->detect_client_leader);
// --shadow-exclude // --shadow-exclude
parse_cfg_condlst(ps, &cfg, &ps->o.shadow_blacklist, "shadow-exclude"); parse_cfg_condlst(&cfg, &opt->shadow_blacklist, "shadow-exclude");
// --fade-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 // --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 // --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 // --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 // --opacity-rule
parse_cfg_condlst_opct(ps, &cfg, "opacity-rule"); parse_cfg_condlst_opct(opt, &cfg, "opacity-rule");
// --unredir-if-possible-exclude // --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 // --blur-background
lcfg_lookup_bool(&cfg, "blur-background", &ps->o.blur_background); lcfg_lookup_bool(&cfg, "blur-background", &opt->blur_background);
// --blur-background-frame // --blur-background-frame
lcfg_lookup_bool(&cfg, "blur-background-frame", lcfg_lookup_bool(&cfg, "blur-background-frame",
&ps->o.blur_background_frame); &opt->blur_background_frame);
// --blur-background-fixed // --blur-background-fixed
lcfg_lookup_bool(&cfg, "blur-background-fixed", lcfg_lookup_bool(&cfg, "blur-background-fixed",
&ps->o.blur_background_fixed); &opt->blur_background_fixed);
// --blur-kern // --blur-kern
if (config_lookup_string(&cfg, "blur-kern", &sval) if (config_lookup_string(&cfg, "blur-kern", &sval) &&
&& !parse_conv_kern_lst(ps, sval, ps->o.blur_kerns, MAX_BLUR_PASS)) { !parse_conv_kern_lst(sval, opt->blur_kerns, MAX_BLUR_PASS, conv_kern_hasneg)) {
log_fatal("Cannot parse \"blur-kern\""); log_fatal("Cannot parse \"blur-kern\"");
exit(1); exit(1);
} }
// --resize-damage // --resize-damage
config_lookup_int(&cfg, "resize-damage", &ps->o.resize_damage); config_lookup_int(&cfg, "resize-damage", &opt->resize_damage);
// --glx-no-stencil // --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 // --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 // --glx-swap-method
if (config_lookup_string(&cfg, "glx-swap-method", &sval) && if (config_lookup_string(&cfg, "glx-swap-method", &sval)) {
!parse_glx_swap_method(ps, sval)) { opt->glx_swap_method = parse_glx_swap_method(sval);
log_fatal("Cannot parse \"glx-swap-method\""); if (opt->glx_swap_method == -2) {
exit(1); log_fatal("Cannot parse \"glx-swap-method\"");
exit(1);
}
} }
// --glx-use-gpushader4 // --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 // --xrender-sync
lcfg_lookup_bool(&cfg, "xrender-sync", &ps->o.xrender_sync); lcfg_lookup_bool(&cfg, "xrender-sync", &opt->xrender_sync);
// --xrender-sync-fence // --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)) if (lcfg_lookup_bool(&cfg, "clear-shadow", &bval))
log_warn("\"clear-shadow\" is removed as an option, and is always" 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); config_setting_t *setting = config_lookup(&cfg, str);
free(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]; win_option_mask_t *mask = &winopt_mask[i];
if (setting) { if (setting) {
if (config_setting_lookup_bool(setting, "shadow", &ival)) { 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); config_destroy(&cfg);
return path;
} }

View File

@ -1183,15 +1183,27 @@ cdbus_process_opts_set(session_t *ps, DBusMessage *msg) {
if (!cdbus_msg_get_arg(msg, 1, DBUS_TYPE_STRING, &val)) if (!cdbus_msg_get_arg(msg, 1, DBUS_TYPE_STRING, &val))
return false; return false;
vsync_deinit(ps); vsync_deinit(ps);
if (!parse_vsync(ps, val)) { auto tmp_vsync = parse_vsync(val);
log_error(CDBUS_ERROR_BADARG_S, 1, "Value invalid."); if (tmp_vsync >= NUM_VSYNC) {
cdbus_reply_err(ps, msg, CDBUS_ERROR_BADARG, CDBUS_ERROR_BADARG_S, 1, "Value invalid."); 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."); auto old_vsync = ps->o.vsync;
cdbus_reply_err(ps, msg, CDBUS_ERROR_CUSTOM, CDBUS_ERROR_CUSTOM_S, "Failed to initialize specified VSync method."); ps->o.vsync = tmp_vsync;
} if (!vsync_init(ps)) {
else // 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; goto cdbus_process_opts_set_success;
return true; return true;
} }

View File

@ -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 // Get XVisualInfo
pvis = get_visualinfo_from_visual(ps, ps->vis); pvis = get_visualinfo_from_visual(ps, ps->vis);
if (!pvis) { if (!pvis) {
@ -436,7 +441,7 @@ glx_destroy(session_t *ps) {
glDeleteProgram(ppass->prog); 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); glx_check_err(ps);

View File

@ -6,9 +6,11 @@
#include <stdbool.h> #include <stdbool.h>
#include <unistd.h> #include <unistd.h>
#include "options.h"
#include "common.h" #include "common.h"
#include "config.h" #include "config.h"
#include "options.h"
#pragma GCC diagnostic error "-Wunused-parameter"
/** /**
* Print usage text and exit. * 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. * 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; int o = 0, longopt_idx = -1;
bool shadow_enable = false, fading_enable = false;
char *lc_numeric_old = strdup(setlocale(LC_NUMERIC, NULL)); 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 // Enforce LC_NUMERIC locale "C" here to make sure dots are recognized
// instead of commas in atof(). // instead of commas in atof().
setlocale(LC_NUMERIC, "C"); setlocale(LC_NUMERIC, "C");
parse_config(ps, &shadow_enable, &fading_enable, winopt_mask);
// Parse commandline arguments. Range checking will be done later. // Parse commandline arguments. Range checking will be done later.
const char *deprecation_message = "has been removed. If you encounter problems " 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) { switch (o) {
#define P_CASEBOOL(idx, option) \ #define P_CASEBOOL(idx, option) \
case idx: \ case idx: \
ps->o.option = true; \ opt->option = true; \
break break
#define P_CASELONG(idx, option) \ #define P_CASELONG(idx, option) \
case idx: \ case idx: \
if (!parse_long(optarg, &val)) \ if (!parse_long(optarg, &val)) \
exit(1); \ exit(1); \
ps->o.option = val; \ opt->option = val; \
break break
// clang-format off
// Short options // Short options
case 'h': usage(0); break; case 'h': usage(0); break;
case 'd': case 'd':
case 'S': case 'S':
case 314: case 314:
case 318: case 318:
case 320: break; P_CASELONG('D', fade_delta); case 320: break;
case 'I': ps->o.fade_in_step = normalize_d(atof(optarg)) * OPAQUE; break; P_CASELONG('D', fade_delta);
case 'O': ps->o.fade_out_step = normalize_d(atof(optarg)) * OPAQUE; break; 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': shadow_enable = true; break;
case 'C': case 'C':
winopt_mask[WINTYPE_DOCK].shadow = true; winopt_mask[WINTYPE_DOCK].shadow = true;
ps->o.wintype_option[WINTYPE_DOCK].shadow = true; opt->wintype_option[WINTYPE_DOCK].shadow = true;
break; break;
case 'G': case 'G':
winopt_mask[WINTYPE_DND].shadow = true; winopt_mask[WINTYPE_DND].shadow = true;
ps->o.wintype_option[WINTYPE_DND].shadow = true; opt->wintype_option[WINTYPE_DND].shadow = true;
break; break;
case 'm':; case 'm':;
double tmp; double tmp;
tmp = normalize_d(atof(optarg)); tmp = normalize_d(atof(optarg));
winopt_mask[WINTYPE_DROPDOWN_MENU].opacity = true; winopt_mask[WINTYPE_DROPDOWN_MENU].opacity = true;
winopt_mask[WINTYPE_POPUP_MENU].opacity = true; winopt_mask[WINTYPE_POPUP_MENU].opacity = true;
ps->o.wintype_option[WINTYPE_POPUP_MENU].opacity = tmp; opt->wintype_option[WINTYPE_POPUP_MENU].opacity = tmp;
ps->o.wintype_option[WINTYPE_DROPDOWN_MENU].opacity = tmp; opt->wintype_option[WINTYPE_DROPDOWN_MENU].opacity = tmp;
break; break;
case 'f': case 'f':
case 'F': case 'F':
fading_enable = true; fading_enable = true;
break; break;
P_CASELONG('r', shadow_radius); P_CASELONG('r', shadow_radius);
case 'o': case 'o':
ps->o.shadow_opacity = atof(optarg); opt->shadow_opacity = atof(optarg);
break; break;
P_CASELONG('l', shadow_offset_x); P_CASELONG('l', shadow_offset_x);
P_CASELONG('t', shadow_offset_y); P_CASELONG('t', shadow_offset_y);
case 'i': case 'i':
ps->o.inactive_opacity = (normalize_d(atof(optarg)) * OPAQUE); opt->inactive_opacity = (normalize_d(atof(optarg)) * OPAQUE);
break; break;
case 'e': ps->o.frame_opacity = atof(optarg); break; case 'e': opt->frame_opacity = atof(optarg); break;
case 'z': case 'z':
log_warn("clear-shadow is removed, shadows are automatically " log_warn("clear-shadow is removed, shadows are automatically "
"cleared now. If you want to prevent shadow from been " "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': case 's':
log_error("-n, -a, and -s have been removed."); log_error("-n, -a, and -s have been removed.");
break; break;
P_CASEBOOL('b', fork_after_register); P_CASEBOOL('b', fork_after_register);
// Long options // Long options
case 256: case 256:
// --config // --config
break; break;
case 257: case 257:
// --shadow-red // --shadow-red
ps->o.shadow_red = atof(optarg); opt->shadow_red = atof(optarg);
break; break;
case 258: case 258:
// --shadow-green // --shadow-green
ps->o.shadow_green = atof(optarg); opt->shadow_green = atof(optarg);
break; break;
case 259: case 259:
// --shadow-blue // --shadow-blue
ps->o.shadow_blue = atof(optarg); opt->shadow_blue = atof(optarg);
break; break;
P_CASEBOOL(260, inactive_opacity_override); P_CASEBOOL(260, inactive_opacity_override);
case 261: case 261:
// --inactive-dim // --inactive-dim
ps->o.inactive_dim = atof(optarg); opt->inactive_dim = atof(optarg);
break; break;
P_CASEBOOL(262, mark_wmwin_focused); P_CASEBOOL(262, mark_wmwin_focused);
case 263: case 263:
// --shadow-exclude // --shadow-exclude
condlst_add(ps, &ps->o.shadow_blacklist, optarg); condlst_add(&opt->shadow_blacklist, optarg);
break; break;
P_CASEBOOL(264, mark_ovredir_focused); P_CASEBOOL(264, mark_ovredir_focused);
P_CASEBOOL(265, no_fading_openclose); P_CASEBOOL(265, no_fading_openclose);
P_CASEBOOL(266, shadow_ignore_shaped); P_CASEBOOL(266, shadow_ignore_shaped);
P_CASEBOOL(267, detect_rounded_corners); P_CASEBOOL(267, detect_rounded_corners);
P_CASEBOOL(268, detect_client_opacity); P_CASEBOOL(268, detect_client_opacity);
P_CASELONG(269, refresh_rate); P_CASELONG(269, refresh_rate);
case 270: case 270:
// --vsync // --vsync
if (!parse_vsync(ps, optarg)) opt->vsync = parse_vsync(optarg);
if (opt->vsync >= NUM_VSYNC)
exit(1); exit(1);
break; break;
case 271: 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 " log_warn("--paint-on-overlay has been removed, and is enabled "
"when possible"); "when possible");
break; break;
P_CASEBOOL(274, sw_opti); P_CASEBOOL(274, sw_opti);
P_CASEBOOL(275, vsync_aggressive); P_CASEBOOL(275, vsync_aggressive);
P_CASEBOOL(276, use_ewmh_active_win); P_CASEBOOL(276, use_ewmh_active_win);
P_CASEBOOL(277, respect_prop_shadow); P_CASEBOOL(277, respect_prop_shadow);
P_CASEBOOL(278, unredir_if_possible); P_CASEBOOL(278, unredir_if_possible);
case 279: case 279:
// --focus-exclude // --focus-exclude
condlst_add(ps, &ps->o.focus_blacklist, optarg); condlst_add(&opt->focus_blacklist, optarg);
break; break;
P_CASEBOOL(280, inactive_dim_fixed); P_CASEBOOL(280, inactive_dim_fixed);
P_CASEBOOL(281, detect_transient); P_CASEBOOL(281, detect_transient);
P_CASEBOOL(282, detect_client_leader); P_CASEBOOL(282, detect_client_leader);
P_CASEBOOL(283, blur_background); P_CASEBOOL(283, blur_background);
P_CASEBOOL(284, blur_background_frame); P_CASEBOOL(284, blur_background_frame);
P_CASEBOOL(285, blur_background_fixed); P_CASEBOOL(285, blur_background_fixed);
P_CASEBOOL(286, dbus); P_CASEBOOL(286, dbus);
case 287: case 287:
// --logpath // --logpath
ps->o.logpath = strdup(optarg); opt->logpath = strdup(optarg);
break; break;
case 288: case 288:
// --invert-color-include // --invert-color-include
condlst_add(ps, &ps->o.invert_color_list, optarg); condlst_add(&opt->invert_color_list, optarg);
break; break;
case 289: case 289:
// --opengl // --opengl
ps->o.backend = BKEND_GLX; opt->backend = BKEND_GLX;
break; break;
case 290: case 290:
// --backend // --backend
if (!parse_backend(ps, optarg)) opt->backend = parse_backend(optarg);
if (opt->backend >= NUM_BKEND)
exit(1); exit(1);
break; break;
P_CASEBOOL(291, glx_no_stencil); P_CASEBOOL(291, glx_no_stencil);
case 292: case 292:
log_warn("--glx-copy-from-front %s", deprecation_message); log_warn("--glx-copy-from-front %s", deprecation_message);
break; break;
P_CASELONG(293, benchmark); P_CASELONG(293, benchmark);
case 294: case 294:
// --benchmark-wid // --benchmark-wid
ps->o.benchmark_wid = strtol(optarg, NULL, 0); opt->benchmark_wid = strtol(optarg, NULL, 0);
break; break;
case 295: case 295:
log_warn("--glx-use-copysubbuffermesa %s", deprecation_message); log_warn("--glx-use-copysubbuffermesa %s", deprecation_message);
break; break;
case 296: case 296:
// --blur-background-exclude // --blur-background-exclude
condlst_add(ps, &ps->o.blur_background_blacklist, optarg); condlst_add(&opt->blur_background_blacklist, optarg);
break; break;
case 297: case 297:
// --active-opacity // --active-opacity
ps->o.active_opacity = (normalize_d(atof(optarg)) * OPAQUE); opt->active_opacity = (normalize_d(atof(optarg)) * OPAQUE);
break; break;
P_CASEBOOL(298, glx_no_rebind_pixmap); P_CASEBOOL(298, glx_no_rebind_pixmap);
case 299: case 299:
// --glx-swap-method // --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); exit(1);
break; break;
case 300: case 300:
// --fade-exclude // --fade-exclude
condlst_add(ps, &ps->o.fade_blacklist, optarg); condlst_add(&opt->fade_blacklist, optarg);
break; break;
case 301: case 301:
// --blur-kern // --blur-kern
if (!parse_conv_kern_lst(ps, optarg, ps->o.blur_kerns, if (!parse_conv_kern_lst(optarg, opt->blur_kerns,
MAX_BLUR_PASS)) MAX_BLUR_PASS, &conv_kern_hasneg))
exit(1); exit(1);
break; break;
P_CASELONG(302, resize_damage); P_CASELONG(302, resize_damage);
P_CASEBOOL(303, glx_use_gpushader4); P_CASEBOOL(303, glx_use_gpushader4);
case 304: case 304:
// --opacity-rule // --opacity-rule
if (!parse_rule_opacity(ps, optarg)) if (!parse_rule_opacity(&opt->opacity_rules, optarg))
exit(1); exit(1);
break; break;
case 305: case 305:
// --shadow-exclude-reg // --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 " log_warn("--shadow-exclude-reg is deprecated. You are likely "
"better off using --shadow-exclude anyway"); "better off using --shadow-exclude anyway");
break; break;
case 306: case 306:
// --paint-exclude // --paint-exclude
condlst_add(ps, &ps->o.paint_blacklist, optarg); condlst_add(&opt->paint_blacklist, optarg);
break; break;
P_CASEBOOL(307, xinerama_shadow_crop); P_CASEBOOL(307, xinerama_shadow_crop);
case 308: case 308:
// --unredir-if-possible-exclude // --unredir-if-possible-exclude
condlst_add(ps, &ps->o.unredir_if_possible_blacklist, optarg); condlst_add(&opt->unredir_if_possible_blacklist, optarg);
break; break;
P_CASELONG(309, unredir_if_possible_delay); P_CASELONG(309, unredir_if_possible_delay);
case 310: case 310:
// --write-pid-path // --write-pid-path
ps->o.write_pid_path = strdup(optarg); opt->write_pid_path = strdup(optarg);
break; break;
P_CASEBOOL(311, vsync_use_glfinish); P_CASEBOOL(311, vsync_use_glfinish);
P_CASEBOOL(312, xrender_sync); P_CASEBOOL(312, xrender_sync);
P_CASEBOOL(313, xrender_sync_fence); P_CASEBOOL(313, xrender_sync_fence);
P_CASEBOOL(315, no_fading_destroyed_argb); P_CASEBOOL(315, no_fading_destroyed_argb);
P_CASEBOOL(316, force_win_blend); P_CASEBOOL(316, force_win_blend);
case 317: 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 " log_warn("--glx-fshader-win is being deprecated, and might be "
"removed in the future. If you really need this " "removed in the future. If you really need this "
"feature, please report an issue to let us know"); "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; break;
} }
P_CASEBOOL(319, no_x_selection); P_CASEBOOL(319, no_x_selection);
P_CASEBOOL(731, reredir_on_root_change); P_CASEBOOL(731, reredir_on_root_change);
P_CASEBOOL(732, glx_reinit_on_root_change); P_CASEBOOL(732, glx_reinit_on_root_change);
P_CASEBOOL(800, monitor_repaint); P_CASEBOOL(800, monitor_repaint);
case 801: ps->o.print_diagnostics = true; break; case 801: opt->print_diagnostics = true; break;
default: usage(1); break; default: usage(1); break;
#undef P_CASEBOOL #undef P_CASEBOOL
} }
// clang-format on
} }
// Restore LC_NUMERIC // Restore LC_NUMERIC
setlocale(LC_NUMERIC, lc_numeric_old); setlocale(LC_NUMERIC, lc_numeric_old);
free(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"); log_warn("--monitor-repaint has no effect when backend is not xrender");
} }
// Range checking and option assignments // Range checking and option assignments
ps->o.fade_delta = max_i(ps->o.fade_delta, 1); opt->fade_delta = max_i(opt->fade_delta, 1);
ps->o.shadow_radius = max_i(ps->o.shadow_radius, 0); opt->shadow_radius = max_i(opt->shadow_radius, 0);
ps->o.shadow_red = normalize_d(ps->o.shadow_red); opt->shadow_red = normalize_d(opt->shadow_red);
ps->o.shadow_green = normalize_d(ps->o.shadow_green); opt->shadow_green = normalize_d(opt->shadow_green);
ps->o.shadow_blue = normalize_d(ps->o.shadow_blue); opt->shadow_blue = normalize_d(opt->shadow_blue);
ps->o.inactive_dim = normalize_d(ps->o.inactive_dim); opt->inactive_dim = normalize_d(opt->inactive_dim);
ps->o.frame_opacity = normalize_d(ps->o.frame_opacity); opt->frame_opacity = normalize_d(opt->frame_opacity);
ps->o.shadow_opacity = normalize_d(ps->o.shadow_opacity); opt->shadow_opacity = normalize_d(opt->shadow_opacity);
ps->o.refresh_rate = normalize_i_range(ps->o.refresh_rate, 0, 300); opt->refresh_rate = normalize_i_range(opt->refresh_rate, 0, 300);
// Apply default wintype options that are dependent on global options // Apply default wintype options that are dependent on global options
for (int i = 0; i < NUM_WINTYPES; i++) { 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]; auto mask = &winopt_mask[i];
if (!mask->shadow) { if (!mask->shadow) {
wo->shadow = shadow_enable; 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 // --blur-background-frame implies --blur-background
if (ps->o.blur_background_frame) if (opt->blur_background_frame)
ps->o.blur_background = true; opt->blur_background = true;
if (ps->o.xrender_sync_fence) if (opt->xrender_sync_fence)
ps->o.xrender_sync = true; opt->xrender_sync = true;
// Other variables determined by options // Other variables determined by options
// Determine whether we need to track focus changes // Determine whether we need to track focus changes
if (ps->o.inactive_opacity != ps->o.active_opacity || ps->o.inactive_dim) { if (opt->inactive_opacity != opt->active_opacity || opt->inactive_dim) {
ps->o.track_focus = true; opt->track_focus = true;
} }
// Determine whether we track window grouping // Determine whether we track window grouping
if (ps->o.detect_transient || ps->o.detect_client_leader) { if (opt->detect_transient || opt->detect_client_leader) {
ps->o.track_leader = true; opt->track_leader = true;
} }
// Fill default blur kernel // 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) // Convolution filter parameter (box blur)
// gaussian or binomial filters are definitely superior, yet looks // gaussian or binomial filters are definitely superior, yet looks
// like they aren't supported as of xorg-server-1.13.0 // 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),
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); 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."); 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 : // vim: set noet sw=8 ts=8 :

View File

@ -2,9 +2,15 @@
// Copyright (c) Yuxuan Shui <yshuiv7@gmail.com> // Copyright (c) Yuxuan Shui <yshuiv7@gmail.com>
#pragma once #pragma once
/// Parse command line options
#include <stdbool.h> #include <stdbool.h>
#include <xcb/render.h> // for xcb_render_fixed_t
#include "compiler.h" #include "compiler.h"
#include "config.h"
#include "types.h"
#include "win.h" // for wintype_t
typedef struct session session_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. * 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:

View File

@ -4,6 +4,7 @@
#include <xcb/xcb_image.h> #include <xcb/xcb_image.h>
#include "common.h" #include "common.h"
#include "options.h"
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
#include "opengl.h" #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, render(ps, x, y, dx, dy, wid, hei, opacity, argb, neg, pict,
(w ? w->paint.ptex : ps->root_tile_paint.ptex), reg_paint, (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) { if (BKEND_GLX == ps->o.backend && ps->o.glx_fshader_win_str) {
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
if (!glx_load_prog_main(ps, NULL, ps->o.glx_fshader_win_str, if (!glx_load_prog_main(ps, NULL, ps->o.glx_fshader_win_str,
&ps->o.glx_prog_win)) &ps->glx_prog_win))
return false; return false;
#else #else
log_error("GLSL supported not compiled in, can't load " log_error("GLSL supported not compiled in, can't load "