// SPDX-License-Identifier: MPL-2.0 // Copyright (c) Yuxuan Shui #include #include #include #include #include #include #include #include // for xcb_render_fixed_t, XXX #include "backend/backend.h" #include "common.h" #include "config.h" #include "log.h" #include "options.h" #include "utils.h" #include "win.h" #pragma GCC diagnostic error "-Wunused-parameter" /** * Print usage text. */ static void usage(const char *argv0, int ret) { #define WARNING_DISABLED " (DISABLED AT COMPILE TIME)" static const char *usage_text = "picom (" COMPTON_VERSION ")\n" "Please report bugs to https://github.com/yshui/picom\n\n" "usage: %s [options]\n" "Options:\n" "\n" "-r radius\n" " The blur radius for shadows. (default 12)\n" "\n" "-o opacity\n" " The translucency for shadows. (default .75)\n" "\n" "-l left-offset\n" " The left offset for shadows. (default -15)\n" "\n" "-t top-offset\n" " The top offset for shadows. (default -15)\n" "\n" "-I fade-in-step\n" " Opacity change between steps while fading in. (default 0.028)\n" "\n" "-O fade-out-step\n" " Opacity change between steps while fading out. (default 0.03)\n" "\n" "-D fade-delta-time\n" " The time between steps in a fade in milliseconds. (default 10)\n" "\n" "-m opacity\n" " The opacity for menus. (default 1.0)\n" "\n" "-c\n" " Enabled client-side shadows on windows.\n" "\n" "-C\n" " Avoid drawing shadows on dock/panel windows.\n" "\n" "-z\n" " Zero the part of the shadow's mask behind the window.\n" "\n" "-f\n" " Fade windows in/out when opening/closing and when opacity\n" " changes, unless --no-fading-openclose is used.\n" "\n" "-F\n" " Equals to -f. Deprecated.\n" "\n" "-i opacity\n" " Opacity of inactive windows. (0.1 - 1.0)\n" "\n" "-e opacity\n" " Opacity of window titlebars and borders. (0.1 - 1.0)\n" "\n" "-G\n" " Don't draw shadows on DND windows\n" "\n" "-b\n" " Daemonize process.\n" "\n" "--show-all-xerrors\n" " Show all X errors (for debugging).\n" "\n" "--config path\n" " Look for configuration file at the path. Use /dev/null to avoid\n" " loading configuration file." #ifndef CONFIG_LIBCONFIG WARNING_DISABLED #endif "\n\n" "--write-pid-path path\n" " Write process ID to a file.\n" "\n" "--shadow-color color\n" " Color of shadow, as a hex RGB string (defaults to #000000)\n" "\n" "--shadow-red value\n" " Red color value of shadow (0.0 - 1.0, defaults to 0).\n" "\n" "--shadow-green value\n" " Green color value of shadow (0.0 - 1.0, defaults to 0).\n" "\n" "--shadow-blue value\n" " Blue color value of shadow (0.0 - 1.0, defaults to 0).\n" "\n" "--inactive-opacity-override\n" " Inactive opacity set by -i overrides value of _NET_WM_WINDOW_OPACITY.\n" "\n" "--inactive-dim value\n" " Dim inactive windows. (0.0 - 1.0, defaults to 0)\n" "\n" "--active-opacity opacity\n" " Default opacity for active windows. (0.0 - 1.0)\n" "\n" "--corner-radius value\n" " Sets the radius of rounded window corners. When > 0, the compositor\n" " will round the corners of windows. (defaults to 0).\n" "\n" "--rounded-corners-exclude condition\n" " Exclude conditions for rounded corners.\n" "\n" "--mark-wmwin-focused\n" " Try to detect WM windows and mark them as active.\n" "\n" "--shadow-exclude condition\n" " Exclude conditions for shadows.\n" "\n" "--fade-exclude condition\n" " Exclude conditions for fading.\n" "\n" "--mark-ovredir-focused\n" " Mark windows that have no WM frame as active.\n" "\n" "--no-fading-openclose\n" " Do not fade on window open/close.\n" "\n" "--no-fading-destroyed-argb\n" " Do not fade destroyed ARGB windows with WM frame. Workaround of bugs\n" " in Openbox, Fluxbox, etc.\n" "\n" "--shadow-ignore-shaped\n" " Do not paint shadows on shaped windows. (Deprecated, use\n" " --shadow-exclude \'bounding_shaped\' or\n" " --shadow-exclude \'bounding_shaped && !rounded_corners\' instead.)\n" "\n" "--detect-rounded-corners\n" " Try to detect windows with rounded corners and don't consider\n" " them shaped windows. Affects --shadow-ignore-shaped,\n" " --unredir-if-possible, and possibly others. You need to turn this\n" " on manually if you want to match against rounded_corners in\n" " conditions.\n" "\n" "--detect-client-opacity\n" " Detect _NET_WM_WINDOW_OPACITY on client windows, useful for window\n" " managers not passing _NET_WM_WINDOW_OPACITY of client windows to frame\n" " windows.\n" "\n" "--vsync\n" " Enable VSync\n" "\n" "--use-ewmh-active-win\n" " Use _NET_WM_ACTIVE_WINDOW on the root window to determine which\n" " window is focused instead of using FocusIn/Out events.\n" "\n" "--unredir-if-possible\n" " Unredirect all windows if a full-screen opaque window is\n" " detected, to maximize performance for full-screen windows.\n" "\n" "--unredir-if-possible-delay ms\n" " Delay before unredirecting the window, in milliseconds.\n" " Defaults to 0.\n" "\n" "--unredir-if-possible-exclude condition\n" " Conditions of windows that shouldn't be considered full-screen\n" " for unredirecting screen.\n" "\n" "--focus-exclude condition\n" " Specify a list of conditions of windows that should always be\n" " considered focused.\n" "\n" "--inactive-dim-fixed\n" " Use fixed inactive dim value.\n" "\n" "--max-brightness\n" " Dims windows which average brightness is above this threshold.\n" " Requires --no-use-damage.\n" " Default: 1.0 or no dimming.\n" "\n" "--detect-transient\n" " Use WM_TRANSIENT_FOR to group windows, and consider windows in\n" " the same group focused at the same time.\n" "\n" "--detect-client-leader\n" " Use WM_CLIENT_LEADER to group windows, and consider windows in\n" " the same group focused at the same time. This usually means windows\n" " from the same application will be considered focused or unfocused at\n" " the same time. WM_TRANSIENT_FOR has higher priority if\n" " --detect-transient is enabled, too.\n" "\n" "--blur-method\n" " The algorithm used for background bluring. Available choices are:\n" " 'none' to disable, 'gaussian', 'box' or 'kernel' for custom\n" " convolution blur with --blur-kern.\n" " Note: 'gaussian' and 'box' is not supported by --legacy-backends.\n" "\n" "--blur-size\n" " The radius of the blur kernel for 'box' and 'gaussian' blur method.\n" "\n" "--blur-deviation\n" " The standard deviation for the 'gaussian' blur method.\n" "\n" "--blur-strength\n" " The strength level of the 'dual_kawase' blur method.\n" "\n" "--blur-background\n" " Blur background of semi-transparent / ARGB windows. Bad in\n" " performance. The switch name may change without prior\n" " notifications.\n" "\n" "--blur-background-frame\n" " Blur background of windows when the window frame is not opaque.\n" " Implies --blur-background. Bad in performance. The switch name\n" " may change.\n" "\n" "--blur-background-fixed\n" " Use fixed blur strength instead of adjusting according to window\n" " opacity.\n" "\n" "--blur-kern matrix\n" " Specify the blur convolution kernel, with the following format:\n" " WIDTH,HEIGHT,ELE1,ELE2,ELE3,ELE4,ELE5...\n" " The element in the center must not be included, it will be forever\n" " 1.0 or changing based on opacity, depending on whether you have\n" " --blur-background-fixed.\n" " A 7x7 Gaussian blur kernel looks like:\n" " --blur-kern " "'7,7,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003,0." "000102,0.003494,0.029143,0.059106,0.029143,0.003494,0.000102,0.000849,0." "029143,0.243117,0.493069,0.243117,0.029143,0.000849,0.001723,0.059106,0." "493069,0.493069,0.059106,0.001723,0.000849,0.029143,0.243117,0.493069,0." "243117,0.029143,0.000849,0.000102,0.003494,0.029143,0.059106,0.029143,0." "003494,0.000102,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0." "000003'\n" " Up to 4 blur kernels may be specified, separated with semicolon, for\n" " multi-pass blur.\n" " May also be one the predefined kernels: 3x3box (default), 5x5box,\n" " 7x7box, 3x3gaussian, 5x5gaussian, 7x7gaussian, 9x9gaussian,\n" " 11x11gaussian.\n" "\n" "--blur-background-exclude condition\n" " Exclude conditions for background blur.\n" "\n" "--resize-damage integer\n" " Resize damaged region by a specific number of pixels. A positive\n" " value enlarges it while a negative one shrinks it. Useful for\n" " fixing the line corruption issues of blur. May or may not\n" " work with --glx-no-stencil. Shrinking doesn't function correctly.\n" "\n" "--invert-color-include condition\n" " Specify a list of conditions of windows that should be painted with\n" " inverted color. Resource-hogging, and is not well tested.\n" "\n" "--opacity-rule opacity:condition\n" " Specify a list of opacity rules, in the format \"PERCENT:PATTERN\",\n" " like \'50:name *= \"Firefox\"'. picom-trans is recommended over\n" " this. Note we do not distinguish 100%% and unset, and we don't make\n" " any guarantee about possible conflicts with other programs that set\n" " _NET_WM_WINDOW_OPACITY on frame or client windows.\n" "\n" "--shadow-exclude-reg geometry\n" " Specify a X geometry that describes the region in which shadow\n" " should not be painted in, such as a dock window region.\n" " Use --shadow-exclude-reg \'x10+0-0\', for example, if the 10 pixels\n" " on the bottom of the screen should not have shadows painted on.\n" "\n" "--clip-shadow-above condition\n" " Specify a list of conditions of windows to not paint a shadow over,\n" " such as a dock window.\n" "\n" "--xinerama-shadow-crop\n" " Crop shadow of a window fully on a particular Xinerama screen to the\n" " screen.\n" "\n" "--backend backend\n" " Choose backend. Possible choices are xrender, glx, and\n" " xr_glx_hybrid." #ifndef CONFIG_OPENGL " (GLX BACKENDS DISABLED AT COMPILE TIME)" #endif "\n\n" "--glx-no-stencil\n" " GLX backend: Avoid using stencil buffer. Might cause issues\n" " when rendering transparent content. My tests show a 15%% performance\n" " boost.\n" "\n" "--glx-no-rebind-pixmap\n" " GLX backend: Avoid rebinding pixmap on window damage. Probably\n" " could improve performance on rapid window content changes, but is\n" " known to break things on some drivers (LLVMpipe, xf86-video-intel,\n" " etc.).\n" "\n" "--no-use-damage\n" " Disable the use of damage information. This cause the whole screen to\n" " be redrawn everytime, instead of the part of the screen that has\n" " actually changed. Potentially degrades the performance, but might fix\n" " some artifacts.\n" "\n" "--xrender-sync-fence\n" " Additionally use X Sync fence to sync clients' draw calls. Needed\n" " on nvidia-drivers with GLX backend for some users.\n" "\n" "--force-win-blend\n" " Force all windows to be painted with blending. Useful if you have a\n" " --glx-fshader-win that could turn opaque pixels transparent.\n" "\n" "--dbus\n" " Enable remote control via D-Bus. See the D-BUS API section in the\n" " man page for more details." #ifndef CONFIG_DBUS WARNING_DISABLED #endif "\n\n" "--benchmark cycles\n" " Benchmark mode. Repeatedly paint until reaching the specified cycles.\n" "\n" "--benchmark-wid window-id\n" " Specify window ID to repaint in benchmark mode. If omitted or is 0,\n" " the whole screen is repainted.\n" "\n" "--monitor-repaint\n" " Highlight the updated area of the screen. For debugging the xrender\n" " backend only.\n" "\n" "--debug-mode\n" " Render into a separate window, and don't take over the screen. Useful\n" " when you want to attach a debugger to picom\n" "\n" "--no-ewmh-fullscreen\n" " Do not use EWMH to detect fullscreen windows. Reverts to checking\n" " if a window is fullscreen based only on its size and coordinates.\n" "\n" "--transparent-clipping\n" " Make transparent windows clip other windows like non-transparent windows\n" " do, instead of blending on top of them\n" "\n" "--window-shader-fg shader\n" " Specify GLSL fragment shader path for rendering window contents. Does\n" " not work when `--legacy-backends` is enabled.\n" "\n" "--window-shader-fg-rule shader:condition\n" " Specify GLSL fragment shader path for rendering window contents using\n" " patterns. Pattern should be in the format of `SHADER_PATH:PATTERN`,\n" " similar to `--opacity-rule`. `SHADER_PATH` can be \"default\", in which\n" " case the default shader will be used. Does not work when\n" " `--legacy-backends` is enabled.\n"; FILE *f = (ret ? stderr : stdout); fprintf(f, usage_text, argv0); #undef WARNING_DISABLED } static const char *shortopts = "D:I:O:r:o:m:l:t:i:e:hscnfFCazGb"; static const struct option longopts[] = { {"help", no_argument, NULL, 'h'}, {"config", required_argument, NULL, 256}, {"shadow-radius", required_argument, NULL, 'r'}, {"shadow-opacity", required_argument, NULL, 'o'}, {"shadow-offset-x", required_argument, NULL, 'l'}, {"shadow-offset-y", required_argument, NULL, 't'}, {"fade-in-step", required_argument, NULL, 'I'}, {"fade-out-step", required_argument, NULL, 'O'}, {"fade-delta", required_argument, NULL, 'D'}, {"menu-opacity", required_argument, NULL, 'm'}, {"shadow", no_argument, NULL, 'c'}, {"clear-shadow", no_argument, NULL, 'z'}, {"fading", no_argument, NULL, 'f'}, {"inactive-opacity", required_argument, NULL, 'i'}, {"frame-opacity", required_argument, NULL, 'e'}, {"daemon", no_argument, NULL, 'b'}, {"shadow-red", required_argument, NULL, 257}, {"shadow-green", required_argument, NULL, 258}, {"shadow-blue", required_argument, NULL, 259}, {"inactive-opacity-override", no_argument, NULL, 260}, {"inactive-dim", required_argument, NULL, 261}, {"mark-wmwin-focused", no_argument, NULL, 262}, {"shadow-exclude", required_argument, NULL, 263}, {"mark-ovredir-focused", no_argument, NULL, 264}, {"no-fading-openclose", no_argument, NULL, 265}, {"shadow-ignore-shaped", no_argument, NULL, 266}, {"detect-rounded-corners", no_argument, NULL, 267}, {"detect-client-opacity", no_argument, NULL, 268}, {"refresh-rate", required_argument, NULL, 269}, {"vsync", optional_argument, NULL, 270}, {"sw-opti", no_argument, NULL, 274}, {"vsync-aggressive", no_argument, NULL, 275}, {"use-ewmh-active-win", no_argument, NULL, 276}, {"respect-prop-shadow", no_argument, NULL, 277}, {"unredir-if-possible", no_argument, NULL, 278}, {"focus-exclude", required_argument, NULL, 279}, {"inactive-dim-fixed", no_argument, NULL, 280}, {"detect-transient", no_argument, NULL, 281}, {"detect-client-leader", no_argument, NULL, 282}, {"blur-background", no_argument, NULL, 283}, {"blur-background-frame", no_argument, NULL, 284}, {"blur-background-fixed", no_argument, NULL, 285}, {"dbus", no_argument, NULL, 286}, {"logpath", required_argument, NULL, 287}, {"invert-color-include", required_argument, NULL, 288}, {"opengl", no_argument, NULL, 289}, {"backend", required_argument, NULL, 290}, {"glx-no-stencil", no_argument, NULL, 291}, {"benchmark", required_argument, NULL, 293}, {"benchmark-wid", required_argument, NULL, 294}, {"blur-background-exclude", required_argument, NULL, 296}, {"active-opacity", required_argument, NULL, 297}, {"glx-no-rebind-pixmap", no_argument, NULL, 298}, {"glx-swap-method", required_argument, NULL, 299}, {"fade-exclude", required_argument, NULL, 300}, {"blur-kern", required_argument, NULL, 301}, {"resize-damage", required_argument, NULL, 302}, {"glx-use-gpushader4", no_argument, NULL, 303}, {"opacity-rule", required_argument, NULL, 304}, {"shadow-exclude-reg", required_argument, NULL, 305}, {"paint-exclude", required_argument, NULL, 306}, {"xinerama-shadow-crop", no_argument, NULL, 307}, {"unredir-if-possible-exclude", required_argument, NULL, 308}, {"unredir-if-possible-delay", required_argument, NULL, 309}, {"write-pid-path", required_argument, NULL, 310}, {"vsync-use-glfinish", no_argument, NULL, 311}, {"xrender-sync-fence", no_argument, NULL, 313}, {"show-all-xerrors", no_argument, NULL, 314}, {"no-fading-destroyed-argb", no_argument, NULL, 315}, {"force-win-blend", no_argument, NULL, 316}, {"glx-fshader-win", required_argument, NULL, 317}, {"version", no_argument, NULL, 318}, {"no-x-selection", no_argument, NULL, 319}, {"log-level", required_argument, NULL, 321}, {"log-file", required_argument, NULL, 322}, {"use-damage", no_argument, NULL, 323}, {"no-use-damage", no_argument, NULL, 324}, {"no-vsync", no_argument, NULL, 325}, {"max-brightness", required_argument, NULL, 326}, {"transparent-clipping", no_argument, NULL, 327}, {"blur-method", required_argument, NULL, 328}, {"blur-size", required_argument, NULL, 329}, {"blur-deviation", required_argument, NULL, 330}, {"blur-strength", required_argument, NULL, 331}, {"shadow-color", required_argument, NULL, 332}, {"corner-radius", required_argument, NULL, 333}, {"rounded-corners-exclude", required_argument, NULL, 334}, {"clip-shadow-above", required_argument, NULL, 335}, {"window-shader-fg", required_argument, NULL, 336}, {"window-shader-fg-rule", required_argument, NULL, 337}, {"legacy-backends", no_argument, NULL, 733}, {"monitor-repaint", no_argument, NULL, 800}, {"diagnostics", no_argument, NULL, 801}, {"debug-mode", no_argument, NULL, 802}, {"no-ewmh-fullscreen", no_argument, NULL, 803}, // Must terminate with a NULL entry {NULL, 0, NULL, 0}, }; /// Get config options that are needed to parse the rest of the options /// Return true if we should quit bool get_early_config(int argc, char *const *argv, char **config_file, bool *all_xerrors, bool *fork, int *exit_code) { int o = 0, longopt_idx = -1; // Pre-parse the commandline arguments to check for --config and invalid // switches // Must reset optind to 0 here in case we reread the commandline // arguments optind = 1; *config_file = NULL; *exit_code = 0; while (-1 != (o = getopt_long(argc, argv, shortopts, longopts, &longopt_idx))) { if (o == 256) { *config_file = strdup(optarg); } else if (o == 'h') { usage(argv[0], 0); return true; } else if (o == 'b') { *fork = true; } else if (o == 314) { *all_xerrors = true; } else if (o == 318) { printf("%s\n", COMPTON_VERSION); return true; } else if (o == '?' || o == ':') { usage(argv[0], 1); goto err; } } // Check for abundant positional arguments if (optind < argc) { // log is not initialized here yet fprintf(stderr, "picom doesn't accept positional arguments.\n"); goto err; } return false; err: *exit_code = 1; return true; } /** * Process arguments and configuration files. */ bool 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; char *lc_numeric_old = strdup(setlocale(LC_NUMERIC, NULL)); // Enforce LC_NUMERIC locale "C" here to make sure dots are recognized // instead of commas in atof(). setlocale(LC_NUMERIC, "C"); // Parse commandline arguments. Range checking will be done later. bool failed = false; const char *deprecation_message attr_unused = "has been removed. If you encounter problems " "without this feature, please feel free to " "open a bug report."; optind = 1; while (-1 != (o = getopt_long(argc, argv, shortopts, longopts, &longopt_idx))) { switch (o) { #define P_CASEBOOL(idx, option) \ case idx: \ opt->option = true; \ break #define P_CASELONG(idx, option) \ case idx: \ if (!parse_long(optarg, &opt->option)) { \ exit(1); \ } \ break #define P_CASEINT(idx, option) \ case idx: \ if (!parse_int(optarg, &opt->option)) { \ exit(1); \ } \ break // clang-format off // Short options case 318: case 'h': // These options should cause us to exit early, // so assert(false) here assert(false); break; case 'b': case 314: case 320: // These options are handled by get_early_config() break; P_CASEINT('D', fade_delta); case 'I': opt->fade_in_step = normalize_d(atof(optarg)); break; case 'O': opt->fade_out_step = normalize_d(atof(optarg)); break; case 'c': shadow_enable = true; break; case 'm':; log_warn("--menu-opacity is deprecated, and will be removed." "Please use the wintype option `opacity` of `popup_menu`" "and `dropdown_menu` instead."); double tmp; tmp = normalize_d(atof(optarg)); winopt_mask[WINTYPE_DROPDOWN_MENU].opacity = true; winopt_mask[WINTYPE_POPUP_MENU].opacity = true; 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_CASEINT('r', shadow_radius); case 'o': opt->shadow_opacity = atof(optarg); break; P_CASEINT('l', shadow_offset_x); P_CASEINT('t', shadow_offset_y); case 'i': opt->inactive_opacity = normalize_d(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 " "cleared under certain types of windows, you can use " "the \"full-shadow\" per window type option."); break; case 'n': case 'a': case 's': log_error("-n, -a, and -s have been removed."); failed = true; break; // Long options case 256: // --config break; case 332:; // --shadow-color struct color rgb; rgb = hex_to_rgb(optarg); opt->shadow_red = rgb.red; opt->shadow_green = rgb.green; opt->shadow_blue = rgb.blue; break; case 257: // --shadow-red opt->shadow_red = atof(optarg); break; case 258: // --shadow-green opt->shadow_green = atof(optarg); break; case 259: // --shadow-blue opt->shadow_blue = atof(optarg); break; P_CASEBOOL(260, inactive_opacity_override); case 261: // --inactive-dim opt->inactive_dim = atof(optarg); break; P_CASEBOOL(262, mark_wmwin_focused); case 263: // --shadow-exclude 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); case 269: log_warn("--refresh-rate has been deprecated, please remove it from" "your command line options"); break; case 270: if (optarg) { bool parsed_vsync = parse_vsync(optarg); log_error("--vsync doesn't take argument anymore. \"%s\" " "should be changed to \"%s\"", optarg, parsed_vsync ? "true" : "false"); failed = true; } else { opt->vsync = true; } break; case 274: log_warn("--sw-opti has been deprecated, please remove it from the " "command line options"); break; case 275: // --vsync-aggressive log_error("--vsync-aggressive has been removed, please remove it" " from the command line options"); failed = true; break; P_CASEBOOL(276, use_ewmh_active_win); case 277: // --respect-prop-shadow log_warn("--respect-prop-shadow option has been deprecated, its " "functionality will always be enabled. Please remove it " "from the command line options"); break; P_CASEBOOL(278, unredir_if_possible); case 279: // --focus-exclude condlst_add(&opt->focus_blacklist, optarg); break; P_CASEBOOL(280, inactive_dim_fixed); P_CASEBOOL(281, detect_transient); P_CASEBOOL(282, detect_client_leader); case 283: // --blur_background opt->blur_method = BLUR_METHOD_KERNEL; break; P_CASEBOOL(284, blur_background_frame); P_CASEBOOL(285, blur_background_fixed); P_CASEBOOL(286, dbus); case 287: log_warn("Please use --log-file instead of --logpath"); // fallthrough case 322: // --logpath, --log-file free(opt->logpath); opt->logpath = strdup(optarg); break; case 288: // --invert-color-include condlst_add(&opt->invert_color_list, optarg); break; case 289: // --opengl opt->backend = BKEND_GLX; break; case 290: // --backend opt->backend = parse_backend(optarg); if (opt->backend >= NUM_BKEND) exit(1); break; P_CASEBOOL(291, glx_no_stencil); P_CASEINT(293, benchmark); case 294: // --benchmark-wid opt->benchmark_wid = (xcb_window_t)strtol(optarg, NULL, 0); break; case 296: // --blur-background-exclude condlst_add(&opt->blur_background_blacklist, optarg); break; case 297: // --active-opacity opt->active_opacity = normalize_d(atof(optarg)); break; P_CASEBOOL(298, glx_no_rebind_pixmap); case 299: { // --glx-swap-method char *endptr; long tmpval = strtol(optarg, &endptr, 10); bool should_remove = true; if (*endptr || !(*optarg)) { // optarg is not a number, or an empty string tmpval = -1; } if (strcmp(optarg, "undefined") != 0 && tmpval != 0) { // If not undefined, we will use damage and buffer-age to // limit the rendering area. should_remove = false; } log_error("--glx-swap-method has been removed, your setting " "\"%s\" should be %s.", optarg, !should_remove ? "replaced by `--use-damage`" : "removed"); failed = true; break; } case 300: // --fade-exclude condlst_add(&opt->fade_blacklist, optarg); break; case 301: // --blur-kern opt->blur_kerns = parse_blur_kern_lst(optarg, &conv_kern_hasneg, &opt->blur_kernel_count); if (!opt->blur_kerns) { exit(1); } break; P_CASEINT(302, resize_damage); case 303: // --glx-use-gpushader4 log_error("--glx-use-gpushader4 has been removed." " Please remove it from command line options."); failed = true; break; case 304: // --opacity-rule if (!parse_rule_opacity(&opt->opacity_rules, optarg)) exit(1); break; case 305: // --shadow-exclude-reg free(opt->shadow_exclude_reg_str); opt->shadow_exclude_reg_str = strdup(optarg); log_warn("--shadow-exclude-reg is deprecated. You are likely " "better off using --clip-shadow-above anyway"); break; case 306: // --paint-exclude condlst_add(&opt->paint_blacklist, optarg); break; P_CASEBOOL(307, xinerama_shadow_crop); case 308: // --unredir-if-possible-exclude condlst_add(&opt->unredir_if_possible_blacklist, optarg); break; P_CASELONG(309, unredir_if_possible_delay); case 310: // --write-pid-path free(opt->write_pid_path); opt->write_pid_path = strdup(optarg); if (*opt->write_pid_path != '/') { log_warn("--write-pid-path is not an absolute path"); } break; P_CASEBOOL(311, vsync_use_glfinish); P_CASEBOOL(313, xrender_sync_fence); P_CASEBOOL(315, no_fading_destroyed_argb); P_CASEBOOL(316, force_win_blend); case 317: opt->glx_fshader_win_str = strdup(optarg); break; case 336: { // --window-shader-fg scoped_charp cwd = getcwd(NULL, 0); opt->window_shader_fg = locate_auxiliary_file("shaders", optarg, cwd); if (!opt->window_shader_fg) { exit(1); } break; } case 337: { // --window-shader-fg-rule scoped_charp cwd = getcwd(NULL, 0); if (!parse_rule_window_shader(&opt->window_shader_fg_rules, optarg, cwd)) { exit(1); } break; } case 321: { enum log_level tmp_level = string_to_log_level(optarg); if (tmp_level == LOG_LEVEL_INVALID) { log_warn("Invalid log level, defaults to WARN"); } else { log_set_level_tls(tmp_level); } break; } P_CASEBOOL(319, no_x_selection); P_CASEBOOL(323, use_damage); case 324: opt->use_damage = false; break; case 325: opt->vsync = false; break; case 326: opt->max_brightness = atof(optarg); break; P_CASEBOOL(327, transparent_clipping); case 328: { // --blur-method enum blur_method method = parse_blur_method(optarg); if (method >= BLUR_METHOD_INVALID) { log_warn("Invalid blur method %s, ignoring.", optarg); } else { opt->blur_method = method; } break; } case 329: // --blur-size opt->blur_radius = atoi(optarg); break; case 330: // --blur-deviation opt->blur_deviation = atof(optarg); break; case 331: // --blur-strength opt->blur_strength = atoi(optarg); break; case 333: // --cornor-radius opt->corner_radius = atoi(optarg); break; case 334: // --rounded-corners-exclude condlst_add(&opt->rounded_corners_blacklist, optarg); break; case 335: // --clip-shadow-above condlst_add(&opt->shadow_clip_list, optarg); break; P_CASEBOOL(733, legacy_backends); P_CASEBOOL(800, monitor_repaint); case 801: opt->print_diagnostics = true; break; P_CASEBOOL(802, debug_mode); P_CASEBOOL(803, no_ewmh_fullscreen); default: usage(argv[0], 1); break; #undef P_CASEBOOL } // clang-format on if (failed) { // Parsing this option has failed, break the loop break; } } // Restore LC_NUMERIC setlocale(LC_NUMERIC, lc_numeric_old); free(lc_numeric_old); if (failed) { return false; } if (opt->monitor_repaint && opt->backend != BKEND_XRENDER && opt->legacy_backends) { log_warn("--monitor-repaint has no effect when backend is not xrender"); } if (!opt->legacy_backends && !backend_list[opt->backend]) { log_error("Backend \"%s\" is only available as part of the legacy " "backends.", BACKEND_STRS[opt->backend]); return false; } if (opt->debug_mode && opt->legacy_backends) { log_error("Debug mode does not work with the legacy backends."); return false; } if (opt->transparent_clipping && opt->legacy_backends) { log_error("Transparent clipping does not work with the legacy " "backends"); return false; } if (opt->glx_fshader_win_str && !opt->legacy_backends) { log_warn("--glx-fshader-win has been replaced by " "\"--window-shader-fg\" for the new backends."); } if (opt->window_shader_fg || opt->window_shader_fg_rules) { if (opt->legacy_backends || opt->backend != BKEND_GLX) { log_warn("The new window shader interface does not work with the " "legacy glx backend.%s", (opt->backend == BKEND_GLX) ? " You may want to use " "\"--glx-fshader-win\" " "instead on the legacy " "glx backend." : ""); opt->window_shader_fg = NULL; c2_list_free(&opt->window_shader_fg_rules, free); } } // Range checking and option assignments opt->fade_delta = max2(opt->fade_delta, 1); opt->shadow_radius = max2(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->max_brightness = normalize_d(opt->max_brightness); if (opt->max_brightness < 1.0) { if (opt->use_damage) { log_warn("--max-brightness requires --no-use-damage. Falling " "back to 1.0"); opt->max_brightness = 1.0; } if (opt->legacy_backends || opt->backend != BKEND_GLX) { log_warn("--max-brightness requires the new glx " "backend. Falling back to 1.0"); opt->max_brightness = 1.0; } } // --blur-background-frame implies --blur-background if (opt->blur_background_frame && opt->blur_method == BLUR_METHOD_NONE) { opt->blur_method = BLUR_METHOD_KERNEL; } // Apply default wintype options that are dependent on global options set_default_winopts(opt, winopt_mask, shadow_enable, fading_enable, opt->blur_method != BLUR_METHOD_NONE); // Other variables determined by options // Determine whether we track window grouping if (opt->detect_transient || opt->detect_client_leader) { opt->track_leader = true; } // Fill default blur kernel if (opt->blur_method == BLUR_METHOD_KERNEL && (!opt->blur_kerns || !opt->blur_kerns[0])) { opt->blur_kerns = parse_blur_kern_lst("3x3box", &conv_kern_hasneg, &opt->blur_kernel_count); CHECK(opt->blur_kerns); CHECK(opt->blur_kernel_count); } // Sanitize parameters for dual-filter kawase blur if (opt->blur_method == BLUR_METHOD_DUAL_KAWASE) { if (opt->blur_strength <= 0 && opt->blur_radius > 500) { log_warn("Blur radius >500 not supported by dual_kawase method, " "capping to 500."); opt->blur_radius = 500; } if (opt->blur_strength > 20) { log_warn("Blur strength >20 not supported by dual_kawase method, " "capping to 20."); opt->blur_strength = 20; } if (opt->legacy_backends) { log_warn("Dual-kawase blur is not implemented by the legacy " "backends."); } } 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."); } return true; } // vim: set noet sw=8 ts=8 :