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 "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.
*/

View File

@ -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);

View File

@ -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 <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
/// 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 <code>next</code> 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.
*

View File

@ -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);

View File

@ -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;
}

View File

@ -1,7 +1,11 @@
#pragma once
// SPDX-License-Identifier: MIT
// Copyright (c) 2011-2013, Christopher Jeffrey
// 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>
@ -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 <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.
*/
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 :

View File

@ -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 <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.
*/
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;
}

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))
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;
}

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
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);

View File

@ -6,9 +6,11 @@
#include <stdbool.h>
#include <unistd.h>
#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 :

View File

@ -2,9 +2,15 @@
// Copyright (c) Yuxuan Shui <yshuiv7@gmail.com>
#pragma once
/// Parse command line options
#include <stdbool.h>
#include <xcb/render.h> // 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:

View File

@ -4,6 +4,7 @@
#include <xcb/xcb_image.h>
#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 "