diff --git a/compton.sample.conf b/compton.sample.conf index 03b6b21..ceada88 100644 --- a/compton.sample.conf +++ b/compton.sample.conf @@ -1,8 +1,5 @@ # Shadow shadow = true; -no-dnd-shadow = true; -no-dock-shadow = true; -clear-shadow = true; shadow-radius = 7; shadow-offset-x = -7; shadow-offset-y = -7; @@ -22,7 +19,6 @@ shadow-exclude = [ # xinerama-shadow-crop = true; # Opacity -menu-opacity = 0.8; inactive-opacity = 0.8; # active-opacity = 0.8; frame-opacity = 0.7; @@ -59,8 +55,6 @@ detect-rounded-corners = true; detect-client-opacity = true; refresh-rate = 0; vsync = "none"; -dbe = false; -paint-on-overlay = true; # sw-opti = true; # unredir-if-possible = true; # unredir-if-possible-delay = 5000; @@ -83,4 +77,8 @@ glx-swap-method = "undefined"; wintypes: { tooltip = { fade = true; shadow = true; opacity = 0.75; focus = true; full-shadow = false; }; + dock = { shadow = false; } + dnd = { shadow = false; } + popup_menu = { opacity = 0.8; } + dropdown_menu = { opacity = 0.8; } }; diff --git a/src/common.h b/src/common.h index 6bff0df..9da7fde 100644 --- a/src/common.h +++ b/src/common.h @@ -64,6 +64,8 @@ #define MAX_ALPHA (255) +#define ARR_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) + // === Includes === // For some special functions @@ -435,6 +437,24 @@ 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 === @@ -512,6 +532,8 @@ typedef struct options_t { 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. @@ -527,9 +549,6 @@ typedef struct options_t { bool vsync_use_glfinish; // === Shadow === - /// Enable/disable shadow for specific window types. - bool wintype_shadow[NUM_WINTYPES]; - bool wintype_full_shadow[NUM_WINTYPES]; /// Red, green and blue tone of the shadow. double shadow_red, shadow_green, shadow_blue; int shadow_radius; @@ -547,8 +566,6 @@ typedef struct options_t { bool xinerama_shadow_crop; // === Fading === - /// Enable/disable fading for specific window types. - bool wintype_fade[NUM_WINTYPES]; /// 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. @@ -563,8 +580,6 @@ typedef struct options_t { c2_lptr_t *fade_blacklist; // === Opacity === - /// Default opacity for specific window types - double wintype_opacity[NUM_WINTYPES]; /// Default opacity for inactive windows. /// 32-bit integer with the format of _NET_WM_OPACITY. 0 stands for /// not enabled, default. @@ -605,8 +620,6 @@ typedef struct options_t { c2_lptr_t *opacity_rules; // === Focus related === - /// Consider windows of specific types to be always focused. - bool wintype_focus[NUM_WINTYPES]; /// Whether to try to detect WM windows and mark them as focused. bool mark_wmwin_focused; /// Whether to mark override-redirect windows as focused. diff --git a/src/compton.c b/src/compton.c index 58a3209..5bd1b83 100644 --- a/src/compton.c +++ b/src/compton.c @@ -1904,7 +1904,7 @@ paint_all(session_t *ps, region_t *region, const region_t *region_real, win * co // Mask out the body of the window from the shadow if needed // Doing it here instead of in make_shadow() for saving GPU // power and handling shaped windows (XXX unconfirmed) - if (!ps->o.wintype_full_shadow[w->window_type]) + if (!ps->o.wintype_option[w->window_type].full_shadow) pixman_region32_subtract(®_tmp, ®_tmp, &bshape); #ifdef CONFIG_XINERAMA @@ -3920,7 +3920,7 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) { { NULL, 0, NULL, 0 }, }; - int o = 0, longopt_idx = -1, i = 0; + int o = 0, longopt_idx = -1; if (first_pass) { // Pre-parse the commandline arguments to check for --config and invalid @@ -3955,25 +3955,16 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) { return; } - struct options_tmp cfgtmp = { - .no_dock_shadow = false, - .no_dnd_shadow = false, - .menu_opacity = NAN, - }; bool shadow_enable = false, fading_enable = false; char *lc_numeric_old = mstrcpy(setlocale(LC_NUMERIC, NULL)); - for (i = 0; i < NUM_WINTYPES; ++i) { - ps->o.wintype_fade[i] = false; - ps->o.wintype_shadow[i] = false; - ps->o.wintype_opacity[i] = NAN; - } + 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, &cfgtmp); + parse_config(ps, &shadow_enable, &fading_enable, winopt_mask); // Parse commandline arguments. Range checking will be done later. @@ -4012,13 +4003,20 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) { shadow_enable = true; break; case 'C': - cfgtmp.no_dock_shadow = true; + winopt_mask[WINTYPE_DOCK].shadow = true; + ps->o.wintype_option[WINTYPE_DOCK].shadow = true; break; case 'G': - cfgtmp.no_dnd_shadow = true; + winopt_mask[WINTYPE_DND].shadow = true; + ps->o.wintype_option[WINTYPE_DND].shadow = true; break; - case 'm': - cfgtmp.menu_opacity = atof(optarg); + 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; break; case 'f': case 'F': @@ -4232,22 +4230,20 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) { 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); - cfgtmp.menu_opacity = normalize_d(cfgtmp.menu_opacity); ps->o.refresh_rate = normalize_i_range(ps->o.refresh_rate, 0, 300); - if (shadow_enable) - wintype_arr_enable(ps->o.wintype_shadow); - ps->o.wintype_shadow[WINTYPE_DESKTOP] = false; - if (cfgtmp.no_dock_shadow) - ps->o.wintype_shadow[WINTYPE_DOCK] = false; - if (cfgtmp.no_dnd_shadow) - ps->o.wintype_shadow[WINTYPE_DND] = false; - if (fading_enable) - wintype_arr_enable(ps->o.wintype_fade); - - if (!safe_isnan(cfgtmp.menu_opacity)) { - ps->o.wintype_opacity[WINTYPE_DROPDOWN_MENU] = cfgtmp.menu_opacity; - ps->o.wintype_opacity[WINTYPE_POPUP_MENU] = cfgtmp.menu_opacity; + // 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 mask = &winopt_mask[i]; + if (!mask->shadow) { + wo->shadow = shadow_enable; + mask->shadow = true; + } + if (!mask->fade) { + wo->fade = fading_enable; + mask->fade = true; + } } // --blur-background-frame implies --blur-background @@ -5064,8 +5060,6 @@ session_init(session_t *ps_old, int argc, char **argv) { .vsync = VSYNC_NONE, .vsync_aggressive = false, - .wintype_shadow = { false }, - .wintype_full_shadow = { false }, .shadow_red = 0.0, .shadow_green = 0.0, .shadow_blue = 0.0, @@ -5078,7 +5072,6 @@ session_init(session_t *ps_old, int argc, char **argv) { .respect_prop_shadow = false, .xinerama_shadow_crop = false, - .wintype_fade = { false }, .fade_in_step = 0.028 * OPAQUE, .fade_out_step = 0.03 * OPAQUE, .fade_delta = 10, @@ -5086,7 +5079,6 @@ session_init(session_t *ps_old, int argc, char **argv) { .no_fading_destroyed_argb = false, .fade_blacklist = NULL, - .wintype_opacity = { NAN }, .inactive_opacity = OPAQUE, .inactive_opacity_override = false, .active_opacity = OPAQUE, @@ -5103,7 +5095,6 @@ session_init(session_t *ps_old, int argc, char **argv) { .invert_color_list = NULL, .opacity_rules = NULL, - .wintype_focus = { false }, .use_ewmh_active_win = false, .focus_blacklist = NULL, .detect_transient = false, @@ -5203,11 +5194,6 @@ session_init(session_t *ps_old, int argc, char **argv) { ps->ignore_tail = &ps->ignore_head; gettimeofday(&ps->time_start, NULL); - wintype_arr_enable(ps->o.wintype_focus); - ps->o.wintype_focus[WINTYPE_UNKNOWN] = false; - ps->o.wintype_focus[WINTYPE_NORMAL] = false; - ps->o.wintype_focus[WINTYPE_UTILITY] = false; - // First pass get_cfg(ps, argc, argv, true); diff --git a/src/config.h b/src/config.h index 91414ee..da4f4b4 100644 --- a/src/config.h +++ b/src/config.h @@ -33,10 +33,8 @@ parse_cfg_condlst(session_t *ps, const config_t *pcfg, c2_lptr_t **pcondlst, const char *name); void -parse_config(session_t *ps, struct options_tmp *pcfgtmp); +parse_config(session_t *ps, bool *shadow_enable, + bool *fading_enable, win_option_mask_t *winopt_mask); #else -static inline void parse_config(session_t *a, struct options_tmp *b) { - (void)a; - (void)b; -} +static inline void parse_config() {} #endif diff --git a/src/config_libconfig.c b/src/config_libconfig.c index 673b2e0..4a9ec71 100644 --- a/src/config_libconfig.c +++ b/src/config_libconfig.c @@ -156,8 +156,9 @@ parse_cfg_condlst_opct(session_t *ps, const config_t *pcfg, const char *name) { /** * Parse a configuration file from default location. */ -void -parse_config(session_t *ps, struct options_tmp *pcfgtmp) { +void parse_config(session_t *ps, bool *shadow_enable, bool *fading_enable, + win_option_mask_t *winopt_mask) +{ char *path = NULL; FILE *f; config_t cfg; @@ -240,17 +241,35 @@ parse_config(session_t *ps, struct options_tmp *pcfgtmp) { // -e (frame_opacity) config_lookup_float(&cfg, "frame-opacity", &ps->o.frame_opacity); // -c (shadow_enable) - if (config_lookup_bool(&cfg, "shadow", &ival) && ival) - wintype_arr_enable(ps->o.wintype_shadow); + if (config_lookup_bool(&cfg, "shadow", &ival)) + *shadow_enable = ival; // -C (no_dock_shadow) - lcfg_lookup_bool(&cfg, "no-dock-shadow", &pcfgtmp->no_dock_shadow); + if (config_lookup_bool(&cfg, "no-dock-shadow", &ival)) { + printf_errf("(): option `no-dock-shadow` is deprecated, and will be removed.\n" + " Please use the wintype option `shadow` of `dock` instead."); + ps->o.wintype_option[WINTYPE_DOCK].shadow = false; + winopt_mask[WINTYPE_DOCK].shadow = true; + } // -G (no_dnd_shadow) - lcfg_lookup_bool(&cfg, "no-dnd-shadow", &pcfgtmp->no_dnd_shadow); + if (config_lookup_bool(&cfg, "no-dnd-shadow", &ival)) { + printf_errf("(): option `no-dnd-shadow` is deprecated, and will be removed.\n" + " Please use the wintype option `shadow` of `dnd` instead."); + ps->o.wintype_option[WINTYPE_DND].shadow = false; + winopt_mask[WINTYPE_DND].shadow = true; + }; // -m (menu_opacity) - config_lookup_float(&cfg, "menu-opacity", &pcfgtmp->menu_opacity); + if (config_lookup_float(&cfg, "menu-opacity", &dval)) { + printf_errf("(): option `menu-opacity` is deprecated, and will be removed.\n" + "Please use the wintype option `opacity` of `popup_menu` and\n" + "`dropdown_menu` instead."); + ps->o.wintype_option[WINTYPE_DROPDOWN_MENU].opacity = dval; + ps->o.wintype_option[WINTYPE_POPUP_MENU].opacity = dval; + winopt_mask[WINTYPE_DROPDOWN_MENU].opacity = true; + winopt_mask[WINTYPE_POPUP_MENU].opacity = true; + } // -f (fading_enable) - if (config_lookup_bool(&cfg, "fading", &ival) && ival) - wintype_arr_enable(ps->o.wintype_fade); + 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); // --no-fading-destroyed-argb @@ -381,19 +400,69 @@ parse_config(session_t *ps, struct options_tmp *pcfgtmp) { char *str = mstrjoin("wintypes.", WINTYPES[i]); config_setting_t *setting = config_lookup(&cfg, str); free(str); + + win_option_t *o = &ps->o.wintype_option[i]; + win_option_mask_t *mask = &winopt_mask[i]; if (setting) { - if (config_setting_lookup_bool(setting, "shadow", &ival)) - ps->o.wintype_shadow[i] = (bool) ival; - if (config_setting_lookup_bool(setting, "fade", &ival)) - ps->o.wintype_fade[i] = (bool) ival; - if (config_setting_lookup_bool(setting, "focus", &ival)) - ps->o.wintype_focus[i] = (bool) ival; - if (config_setting_lookup_bool(setting, "full-shadow", &ival)) - ps->o.wintype_full_shadow[i] = ival; + if (config_setting_lookup_bool(setting, "shadow", &ival)) { + o->shadow = ival; + mask->shadow = true; + } + if (config_setting_lookup_bool(setting, "fade", &ival)) { + o->fade = ival; + mask->fade = true; + } + if (config_setting_lookup_bool(setting, "focus", &ival)) { + o->focus = ival; + mask->focus = true; + } + if (config_setting_lookup_bool(setting, "full-shadow", &ival)) { + o->full_shadow = ival; + mask->full_shadow = true; + } double fval; - if (config_setting_lookup_float(setting, "opacity", &fval)) - ps->o.wintype_opacity[i] = normalize_d(fval); + if (config_setting_lookup_float(setting, "opacity", &fval)) { + o->opacity = normalize_d(fval); + mask->opacity = true; + } + } + } + + // Apply default wintype options that does not depends on global options. + // For example, wintype shadow option will depend on the global shadow + // option, so it is not set here. + // + // 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; + } + + // Focused/unfocused state only apply to a few window types, all other windows + // are always considered focused. + const wintype_t nofocus_type[] = + { WINTYPE_UNKNOWN, WINTYPE_NORMAL, WINTYPE_UTILITY }; + 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; + } + } + 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; + } + if (!winopt_mask[i].full_shadow) { + winopt_mask[i].full_shadow = true; + ps->o.wintype_option[i].full_shadow = 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; } } diff --git a/src/win.c b/src/win.c index 075ad84..27eaff2 100644 --- a/src/win.c +++ b/src/win.c @@ -323,8 +323,8 @@ void win_calc_opacity(session_t *ps, win *w) { // Try obeying opacity property and window type opacity firstly if (w->has_opacity_prop) opacity = w->opacity_prop; - else if (!safe_isnan(ps->o.wintype_opacity[w->window_type])) - opacity = ps->o.wintype_opacity[w->window_type] * OPAQUE; + else if (!safe_isnan(ps->o.wintype_option[w->window_type].opacity)) + opacity = ps->o.wintype_option[w->window_type].opacity * OPAQUE; else { // Respect active_opacity only when the window is physically focused if (win_is_focused_real(ps, w)) @@ -384,7 +384,7 @@ void win_determine_fade(session_t *ps, win *w) { } else if (c2_match(ps, w, ps->o.fade_blacklist, &w->cache_fblst, NULL)) w->fade = false; else - w->fade = ps->o.wintype_fade[w->window_type]; + w->fade = ps->o.wintype_option[w->window_type].fade; } /** @@ -454,7 +454,7 @@ void win_determine_shadow(session_t *ps, win *w) { if (UNSET != w->shadow_force) shadow_new = w->shadow_force; else if (w->a.map_state == XCB_MAP_STATE_VIEWABLE) - shadow_new = (ps->o.wintype_shadow[w->window_type] && + shadow_new = (ps->o.wintype_option[w->window_type].shadow && !c2_match(ps, w, ps->o.shadow_blacklist, &w->cache_sblst, NULL) && !(ps->o.shadow_ignore_shaped && w->bounding_shaped && !w->rounded_corners) && @@ -914,7 +914,7 @@ void win_update_focused(session_t *ps, win *w) { // Use wintype_focus, and treat WM windows and override-redirected // windows specially - if (ps->o.wintype_focus[w->window_type] + if (ps->o.wintype_option[w->window_type].focus || (ps->o.mark_wmwin_focused && w->wmwin) || (ps->o.mark_ovredir_focused && w->id == w->client_win && !w->wmwin)