1 // SPDX-License-Identifier: MPL-2.0
2 // Copyright (c) Yuxuan Shui <yshuiv7@gmail.com>
3
4 #include <getopt.h>
5 #include <locale.h>
6 #include <stdbool.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <xcb/render.h> // for xcb_render_fixed_t, XXX
12
13 #include "backend/backend.h"
14 #include "common.h"
15 #include "config.h"
16 #include "log.h"
17 #include "options.h"
18 #include "utils.h"
19 #include "win.h"
20
21 #pragma GCC diagnostic error "-Wunused-parameter"
22
23 /**
24 * Print usage text.
25 */
usage(const char * argv0,int ret)26 static void usage(const char *argv0, int ret) {
27 #define WARNING_DISABLED " (DISABLED AT COMPILE TIME)"
28 static const char *usage_text =
29 "picom (" COMPTON_VERSION ")\n"
30 "Please report bugs to https://github.com/yshui/picom\n\n"
31 "usage: %s [options]\n"
32 "Options:\n"
33 "\n"
34 "-r radius\n"
35 " The blur radius for shadows. (default 12)\n"
36 "\n"
37 "-o opacity\n"
38 " The translucency for shadows. (default .75)\n"
39 "\n"
40 "-l left-offset\n"
41 " The left offset for shadows. (default -15)\n"
42 "\n"
43 "-t top-offset\n"
44 " The top offset for shadows. (default -15)\n"
45 "\n"
46 "-I fade-in-step\n"
47 " Opacity change between steps while fading in. (default 0.028)\n"
48 "\n"
49 "-O fade-out-step\n"
50 " Opacity change between steps while fading out. (default 0.03)\n"
51 "\n"
52 "-D fade-delta-time\n"
53 " The time between steps in a fade in milliseconds. (default 10)\n"
54 "\n"
55 "-m opacity\n"
56 " The opacity for menus. (default 1.0)\n"
57 "\n"
58 "-c\n"
59 " Enabled client-side shadows on windows.\n"
60 "\n"
61 "-C\n"
62 " Avoid drawing shadows on dock/panel windows.\n"
63 "\n"
64 "-z\n"
65 " Zero the part of the shadow's mask behind the window.\n"
66 "\n"
67 "-f\n"
68 " Fade windows in/out when opening/closing and when opacity\n"
69 " changes, unless --no-fading-openclose is used.\n"
70 "\n"
71 "-F\n"
72 " Equals to -f. Deprecated.\n"
73 "\n"
74 "-i opacity\n"
75 " Opacity of inactive windows. (0.1 - 1.0)\n"
76 "\n"
77 "-e opacity\n"
78 " Opacity of window titlebars and borders. (0.1 - 1.0)\n"
79 "\n"
80 "-G\n"
81 " Don't draw shadows on DND windows\n"
82 "\n"
83 "-b\n"
84 " Daemonize process.\n"
85 "\n"
86 "--show-all-xerrors\n"
87 " Show all X errors (for debugging).\n"
88 "\n"
89 "--config path\n"
90 " Look for configuration file at the path. Use /dev/null to avoid\n"
91 " loading configuration file."
92 #ifndef CONFIG_LIBCONFIG
93 WARNING_DISABLED
94 #endif
95 "\n\n"
96 "--write-pid-path path\n"
97 " Write process ID to a file.\n"
98 "\n"
99 "--shadow-red value\n"
100 " Red color value of shadow (0.0 - 1.0, defaults to 0).\n"
101 "\n"
102 "--shadow-green value\n"
103 " Green color value of shadow (0.0 - 1.0, defaults to 0).\n"
104 "\n"
105 "--shadow-blue value\n"
106 " Blue color value of shadow (0.0 - 1.0, defaults to 0).\n"
107 "\n"
108 "--inactive-opacity-override\n"
109 " Inactive opacity set by -i overrides value of _NET_WM_OPACITY.\n"
110 "\n"
111 "--inactive-dim value\n"
112 " Dim inactive windows. (0.0 - 1.0, defaults to 0)\n"
113 "\n"
114 "--active-opacity opacity\n"
115 " Default opacity for active windows. (0.0 - 1.0)\n"
116 "\n"
117 "--mark-wmwin-focused\n"
118 " Try to detect WM windows and mark them as active.\n"
119 "\n"
120 "--shadow-exclude condition\n"
121 " Exclude conditions for shadows.\n"
122 "\n"
123 "--fade-exclude condition\n"
124 " Exclude conditions for fading.\n"
125 "\n"
126 "--mark-ovredir-focused\n"
127 " Mark windows that have no WM frame as active.\n"
128 "\n"
129 "--no-fading-openclose\n"
130 " Do not fade on window open/close.\n"
131 "\n"
132 "--no-fading-destroyed-argb\n"
133 " Do not fade destroyed ARGB windows with WM frame. Workaround of bugs\n"
134 " in Openbox, Fluxbox, etc.\n"
135 "\n"
136 "--shadow-ignore-shaped\n"
137 " Do not paint shadows on shaped windows. (Deprecated, use\n"
138 " --shadow-exclude \'bounding_shaped\' or\n"
139 " --shadow-exclude \'bounding_shaped && !rounded_corners\' instead.)\n"
140 "\n"
141 "--detect-rounded-corners\n"
142 " Try to detect windows with rounded corners and don't consider\n"
143 " them shaped windows. Affects --shadow-ignore-shaped,\n"
144 " --unredir-if-possible, and possibly others. You need to turn this\n"
145 " on manually if you want to match against rounded_corners in\n"
146 " conditions.\n"
147 "\n"
148 "--detect-client-opacity\n"
149 " Detect _NET_WM_OPACITY on client windows, useful for window\n"
150 " managers not passing _NET_WM_OPACITY of client windows to frame\n"
151 " windows.\n"
152 "\n"
153 "--refresh-rate val\n"
154 " Specify refresh rate of the screen. If not specified or 0, we\n"
155 " will try detecting this with X RandR extension.\n"
156 "\n"
157 "--vsync\n"
158 " Enable VSync\n"
159 "\n"
160 "--paint-on-overlay\n"
161 " Painting on X Composite overlay window.\n"
162 "\n"
163 "--sw-opti\n"
164 " Limit repaint to at most once every 1 / refresh_rate second.\n"
165 "\n"
166 "--use-ewmh-active-win\n"
167 " Use _NET_WM_ACTIVE_WINDOW on the root window to determine which\n"
168 " window is focused instead of using FocusIn/Out events.\n"
169 "\n"
170 "--unredir-if-possible\n"
171 " Unredirect all windows if a full-screen opaque window is\n"
172 " detected, to maximize performance for full-screen windows.\n"
173 "\n"
174 "--unredir-if-possible-delay ms\n"
175 " Delay before unredirecting the window, in milliseconds.\n"
176 " Defaults to 0.\n"
177 "\n"
178 "--unredir-if-possible-exclude condition\n"
179 " Conditions of windows that shouldn't be considered full-screen\n"
180 " for unredirecting screen.\n"
181 "\n"
182 "--focus-exclude condition\n"
183 " Specify a list of conditions of windows that should always be\n"
184 " considered focused.\n"
185 "\n"
186 "--inactive-dim-fixed\n"
187 " Use fixed inactive dim value.\n"
188 "\n"
189 "--max-brightness\n"
190 " Dims windows which average brightness is above this threshold.\n"
191 " Requires --no-use-damage.\n"
192 " Default: 1.0 or no dimming.\n"
193 "\n"
194 "--detect-transient\n"
195 " Use WM_TRANSIENT_FOR to group windows, and consider windows in\n"
196 " the same group focused at the same time.\n"
197 "\n"
198 "--detect-client-leader\n"
199 " Use WM_CLIENT_LEADER to group windows, and consider windows in\n"
200 " the same group focused at the same time. WM_TRANSIENT_FOR has\n"
201 " higher priority if --detect-transient is enabled, too.\n"
202 "\n"
203 "--blur-method\n"
204 " The algorithm used for background bluring. Available choices are:\n"
205 " 'none' to disable, 'gaussian', 'box' or 'kernel' for custom\n"
206 " convolution blur with --blur-kern.\n"
207 " Note: 'gaussian' and 'box' require --experimental-backends.\n"
208 "\n"
209 "--blur-size\n"
210 " The radius of the blur kernel for 'box' and 'gaussian' blur method.\n"
211 "\n"
212 "--blur-deviation\n"
213 " The standard deviation for the 'gaussian' blur method.\n"
214 "\n"
215 "--blur-background\n"
216 " Blur background of semi-transparent / ARGB windows. Bad in\n"
217 " performance. The switch name may change without prior\n"
218 " notifications.\n"
219 "\n"
220 "--blur-background-frame\n"
221 " Blur background of windows when the window frame is not opaque.\n"
222 " Implies --blur-background. Bad in performance. The switch name\n"
223 " may change.\n"
224 "\n"
225 "--blur-background-fixed\n"
226 " Use fixed blur strength instead of adjusting according to window\n"
227 " opacity.\n"
228 "\n"
229 "--blur-kern matrix\n"
230 " Specify the blur convolution kernel, with the following format:\n"
231 " WIDTH,HEIGHT,ELE1,ELE2,ELE3,ELE4,ELE5...\n"
232 " The element in the center must not be included, it will be forever\n"
233 " 1.0 or changing based on opacity, depending on whether you have\n"
234 " --blur-background-fixed.\n"
235 " A 7x7 Gaussian blur kernel looks like:\n"
236 " --blur-kern "
237 "'7,7,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003,0."
238 "000102,0.003494,0.029143,0.059106,0.029143,0.003494,0.000102,0.000849,0."
239 "029143,0.243117,0.493069,0.243117,0.029143,0.000849,0.001723,0.059106,0."
240 "493069,0.493069,0.059106,0.001723,0.000849,0.029143,0.243117,0.493069,0."
241 "243117,0.029143,0.000849,0.000102,0.003494,0.029143,0.059106,0.029143,0."
242 "003494,0.000102,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0."
243 "000003'\n"
244 " Up to 4 blur kernels may be specified, separated with semicolon, for\n"
245 " multi-pass blur.\n"
246 " May also be one the predefined kernels: 3x3box (default), 5x5box,\n"
247 " 7x7box, 3x3gaussian, 5x5gaussian, 7x7gaussian, 9x9gaussian,\n"
248 " 11x11gaussian.\n"
249 "\n"
250 "--blur-background-exclude condition\n"
251 " Exclude conditions for background blur.\n"
252 "\n"
253 "--resize-damage integer\n"
254 " Resize damaged region by a specific number of pixels. A positive\n"
255 " value enlarges it while a negative one shrinks it. Useful for\n"
256 " fixing the line corruption issues of blur. May or may not\n"
257 " work with --glx-no-stencil. Shrinking doesn't function correctly.\n"
258 "\n"
259 "--invert-color-include condition\n"
260 " Specify a list of conditions of windows that should be painted with\n"
261 " inverted color. Resource-hogging, and is not well tested.\n"
262 "\n"
263 "--opacity-rule opacity:condition\n"
264 " Specify a list of opacity rules, in the format \"PERCENT:PATTERN\",\n"
265 " like \'50:name *= \"Firefox\"'. picom-trans is recommended over\n"
266 " this. Note we do not distinguish 100%% and unset, and we don't make\n"
267 " any guarantee about possible conflicts with other programs that set\n"
268 " _NET_WM_WINDOW_OPACITY on frame or client windows.\n"
269 "\n"
270 "--shadow-exclude-reg geometry\n"
271 " Specify a X geometry that describes the region in which shadow\n"
272 " should not be painted in, such as a dock window region.\n"
273 " Use --shadow-exclude-reg \'x10+0-0\', for example, if the 10 pixels\n"
274 " on the bottom of the screen should not have shadows painted on.\n"
275 "\n"
276 "--xinerama-shadow-crop\n"
277 " Crop shadow of a window fully on a particular Xinerama screen to the\n"
278 " screen.\n"
279 "\n"
280 "--backend backend\n"
281 " Choose backend. Possible choices are xrender, glx, and\n"
282 " xr_glx_hybrid."
283 #ifndef CONFIG_OPENGL
284 " (GLX BACKENDS DISABLED AT COMPILE TIME)"
285 #endif
286 "\n\n"
287 "--glx-no-stencil\n"
288 " GLX backend: Avoid using stencil buffer. Might cause issues\n"
289 " when rendering transparent content. My tests show a 15%% performance\n"
290 " boost.\n"
291 "\n"
292 "--glx-no-rebind-pixmap\n"
293 " GLX backend: Avoid rebinding pixmap on window damage. Probably\n"
294 " could improve performance on rapid window content changes, but is\n"
295 " known to break things on some drivers (LLVMpipe, xf86-video-intel,\n"
296 " etc.).\n"
297 "\n"
298 "--no-use-damage\n"
299 " Disable the use of damage information. This cause the whole screen to\n"
300 " be redrawn everytime, instead of the part of the screen that has\n"
301 " actually changed. Potentially degrades the performance, but might fix\n"
302 " some artifacts.\n"
303 "\n"
304 "--xrender-sync-fence\n"
305 " Additionally use X Sync fence to sync clients' draw calls. Needed\n"
306 " on nvidia-drivers with GLX backend for some users.\n"
307 "\n"
308 "--force-win-blend\n"
309 " Force all windows to be painted with blending. Useful if you have a\n"
310 " --glx-fshader-win that could turn opaque pixels transparent.\n"
311 "\n"
312 "--dbus\n"
313 " Enable remote control via D-Bus. See the D-BUS API section in the\n"
314 " man page for more details."
315 #ifndef CONFIG_DBUS
316 WARNING_DISABLED
317 #endif
318 "\n\n"
319 "--benchmark cycles\n"
320 " Benchmark mode. Repeatedly paint until reaching the specified cycles.\n"
321 "\n"
322 "--benchmark-wid window-id\n"
323 " Specify window ID to repaint in benchmark mode. If omitted or is 0,\n"
324 " the whole screen is repainted.\n"
325 "\n"
326 "--monitor-repaint\n"
327 " Highlight the updated area of the screen. For debugging the xrender\n"
328 " backend only.\n"
329 "\n"
330 "--debug-mode\n"
331 " Render into a separate window, and don't take over the screen. Useful\n"
332 " when you want to attach a debugger to picom\n"
333 "\n"
334 "--no-ewmh-fullscreen\n"
335 " Do not use EWMH to detect fullscreen windows. Reverts to checking\n"
336 " if a window is fullscreen based only on its size and coordinates.\n"
337 "\n"
338 "--transparent-clipping\n"
339 " Make transparent windows clip other windows like non-transparent windows\n"
340 " do, instead of blending on top of them\n";
341 FILE *f = (ret ? stderr : stdout);
342 fprintf(f, usage_text, argv0);
343 #undef WARNING_DISABLED
344 }
345
346 static const char *shortopts = "D:I:O:d:r:o:m:l:t:i:e:hscnfFCaSzGb";
347 static const struct option longopts[] = {
348 {"help", no_argument, NULL, 'h'},
349 {"config", required_argument, NULL, 256},
350 {"shadow-radius", required_argument, NULL, 'r'},
351 {"shadow-opacity", required_argument, NULL, 'o'},
352 {"shadow-offset-x", required_argument, NULL, 'l'},
353 {"shadow-offset-y", required_argument, NULL, 't'},
354 {"fade-in-step", required_argument, NULL, 'I'},
355 {"fade-out-step", required_argument, NULL, 'O'},
356 {"fade-delta", required_argument, NULL, 'D'},
357 {"menu-opacity", required_argument, NULL, 'm'},
358 {"shadow", no_argument, NULL, 'c'},
359 {"no-dock-shadow", no_argument, NULL, 'C'},
360 {"clear-shadow", no_argument, NULL, 'z'},
361 {"fading", no_argument, NULL, 'f'},
362 {"inactive-opacity", required_argument, NULL, 'i'},
363 {"frame-opacity", required_argument, NULL, 'e'},
364 {"daemon", no_argument, NULL, 'b'},
365 {"no-dnd-shadow", no_argument, NULL, 'G'},
366 {"shadow-red", required_argument, NULL, 257},
367 {"shadow-green", required_argument, NULL, 258},
368 {"shadow-blue", required_argument, NULL, 259},
369 {"inactive-opacity-override", no_argument, NULL, 260},
370 {"inactive-dim", required_argument, NULL, 261},
371 {"mark-wmwin-focused", no_argument, NULL, 262},
372 {"shadow-exclude", required_argument, NULL, 263},
373 {"mark-ovredir-focused", no_argument, NULL, 264},
374 {"no-fading-openclose", no_argument, NULL, 265},
375 {"shadow-ignore-shaped", no_argument, NULL, 266},
376 {"detect-rounded-corners", no_argument, NULL, 267},
377 {"detect-client-opacity", no_argument, NULL, 268},
378 {"refresh-rate", required_argument, NULL, 269},
379 {"vsync", optional_argument, NULL, 270},
380 {"alpha-step", required_argument, NULL, 271},
381 {"dbe", no_argument, NULL, 272},
382 {"paint-on-overlay", no_argument, NULL, 273},
383 {"sw-opti", no_argument, NULL, 274},
384 {"vsync-aggressive", no_argument, NULL, 275},
385 {"use-ewmh-active-win", no_argument, NULL, 276},
386 {"respect-prop-shadow", no_argument, NULL, 277},
387 {"unredir-if-possible", no_argument, NULL, 278},
388 {"focus-exclude", required_argument, NULL, 279},
389 {"inactive-dim-fixed", no_argument, NULL, 280},
390 {"detect-transient", no_argument, NULL, 281},
391 {"detect-client-leader", no_argument, NULL, 282},
392 {"blur-background", no_argument, NULL, 283},
393 {"blur-background-frame", no_argument, NULL, 284},
394 {"blur-background-fixed", no_argument, NULL, 285},
395 {"dbus", no_argument, NULL, 286},
396 {"logpath", required_argument, NULL, 287},
397 {"invert-color-include", required_argument, NULL, 288},
398 {"opengl", no_argument, NULL, 289},
399 {"backend", required_argument, NULL, 290},
400 {"glx-no-stencil", no_argument, NULL, 291},
401 {"benchmark", required_argument, NULL, 293},
402 {"benchmark-wid", required_argument, NULL, 294},
403 {"blur-background-exclude", required_argument, NULL, 296},
404 {"active-opacity", required_argument, NULL, 297},
405 {"glx-no-rebind-pixmap", no_argument, NULL, 298},
406 {"glx-swap-method", required_argument, NULL, 299},
407 {"fade-exclude", required_argument, NULL, 300},
408 {"blur-kern", required_argument, NULL, 301},
409 {"resize-damage", required_argument, NULL, 302},
410 {"glx-use-gpushader4", no_argument, NULL, 303},
411 {"opacity-rule", required_argument, NULL, 304},
412 {"shadow-exclude-reg", required_argument, NULL, 305},
413 {"paint-exclude", required_argument, NULL, 306},
414 {"xinerama-shadow-crop", no_argument, NULL, 307},
415 {"unredir-if-possible-exclude", required_argument, NULL, 308},
416 {"unredir-if-possible-delay", required_argument, NULL, 309},
417 {"write-pid-path", required_argument, NULL, 310},
418 {"vsync-use-glfinish", no_argument, NULL, 311},
419 {"xrender-sync", no_argument, NULL, 312},
420 {"xrender-sync-fence", no_argument, NULL, 313},
421 {"show-all-xerrors", no_argument, NULL, 314},
422 {"no-fading-destroyed-argb", no_argument, NULL, 315},
423 {"force-win-blend", no_argument, NULL, 316},
424 {"glx-fshader-win", required_argument, NULL, 317},
425 {"version", no_argument, NULL, 318},
426 {"no-x-selection", no_argument, NULL, 319},
427 {"no-name-pixmap", no_argument, NULL, 320},
428 {"log-level", required_argument, NULL, 321},
429 {"log-file", required_argument, NULL, 322},
430 {"use-damage", no_argument, NULL, 323},
431 {"no-use-damage", no_argument, NULL, 324},
432 {"no-vsync", no_argument, NULL, 325},
433 {"max-brightness", required_argument, NULL, 326},
434 {"transparent-clipping", no_argument, NULL, 327},
435 {"blur-method", required_argument, NULL, 328},
436 {"blur-size", required_argument, NULL, 329},
437 {"blur-deviation", required_argument, NULL, 330},
438 {"experimental-backends", no_argument, NULL, 733},
439 {"monitor-repaint", no_argument, NULL, 800},
440 {"diagnostics", no_argument, NULL, 801},
441 {"debug-mode", no_argument, NULL, 802},
442 {"no-ewmh-fullscreen", no_argument, NULL, 803},
443 // Must terminate with a NULL entry
444 {NULL, 0, NULL, 0},
445 };
446
447 /// Get config options that are needed to parse the rest of the options
448 /// Return true if we should quit
get_early_config(int argc,char * const * argv,char ** config_file,bool * all_xerrors,bool * fork,int * exit_code)449 bool get_early_config(int argc, char *const *argv, char **config_file, bool *all_xerrors,
450 bool *fork, int *exit_code) {
451 int o = 0, longopt_idx = -1;
452
453 // Pre-parse the commandline arguments to check for --config and invalid
454 // switches
455 // Must reset optind to 0 here in case we reread the commandline
456 // arguments
457 optind = 1;
458 *config_file = NULL;
459 *exit_code = 0;
460 while (-1 != (o = getopt_long(argc, argv, shortopts, longopts, &longopt_idx))) {
461 if (o == 256) {
462 *config_file = strdup(optarg);
463 } else if (o == 'h') {
464 usage(argv[0], 0);
465 return true;
466
467 } else if (o == 'b') {
468 *fork = true;
469 } else if (o == 'd') {
470 log_error("-d is removed, please use the DISPLAY "
471 "environment variable");
472 goto err;
473 } else if (o == 314) {
474 *all_xerrors = true;
475 } else if (o == 318) {
476 printf("%s\n", COMPTON_VERSION);
477 return true;
478 } else if (o == 'S') {
479 log_error("-S is no longer available");
480 goto err;
481 } else if (o == 320) {
482 log_error("--no-name-pixmap is no longer available");
483 goto err;
484 } else if (o == '?' || o == ':') {
485 usage(argv[0], 1);
486 goto err;
487 }
488 }
489
490 // Check for abundant positional arguments
491 if (optind < argc) {
492 // log is not initialized here yet
493 fprintf(stderr, "picom doesn't accept positional arguments.\n");
494 goto err;
495 }
496
497 return false;
498 err:
499 *exit_code = 1;
500 return true;
501 }
502
503 /**
504 * Process arguments and configuration files.
505 */
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)506 bool get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable,
507 bool fading_enable, bool conv_kern_hasneg, win_option_mask_t *winopt_mask) {
508
509 int o = 0, longopt_idx = -1;
510
511 char *lc_numeric_old = strdup(setlocale(LC_NUMERIC, NULL));
512
513 // Enforce LC_NUMERIC locale "C" here to make sure dots are recognized
514 // instead of commas in atof().
515 setlocale(LC_NUMERIC, "C");
516
517 // Parse commandline arguments. Range checking will be done later.
518
519 const char *deprecation_message attr_unused =
520 "has been removed. If you encounter problems "
521 "without this feature, please feel free to "
522 "open a bug report.";
523 optind = 1;
524 while (-1 != (o = getopt_long(argc, argv, shortopts, longopts, &longopt_idx))) {
525 switch (o) {
526 #define P_CASEBOOL(idx, option) \
527 case idx: \
528 opt->option = true; \
529 break
530 #define P_CASELONG(idx, option) \
531 case idx: \
532 if (!parse_long(optarg, &opt->option)) { \
533 exit(1); \
534 } \
535 break
536 #define P_CASEINT(idx, option) \
537 case idx: \
538 if (!parse_int(optarg, &opt->option)) { \
539 exit(1); \
540 } \
541 break
542
543 // clang-format off
544 // Short options
545 case 318:
546 case 'h':
547 // These options should cause us to exit early,
548 // so assert(false) here
549 assert(false);
550 break;
551 case 'd':
552 case 'b':
553 case 'S':
554 case 314:
555 case 320:
556 // These options are handled by get_early_config()
557 break;
558 P_CASEINT('D', fade_delta);
559 case 'I': opt->fade_in_step = normalize_d(atof(optarg)); break;
560 case 'O': opt->fade_out_step = normalize_d(atof(optarg)); break;
561 case 'c': shadow_enable = true; break;
562 case 'C':
563 winopt_mask[WINTYPE_DOCK].shadow = true;
564 opt->wintype_option[WINTYPE_DOCK].shadow = false;
565 break;
566 case 'G':
567 winopt_mask[WINTYPE_DND].shadow = true;
568 opt->wintype_option[WINTYPE_DND].shadow = false;
569 break;
570 case 'm':;
571 double tmp;
572 tmp = normalize_d(atof(optarg));
573 winopt_mask[WINTYPE_DROPDOWN_MENU].opacity = true;
574 winopt_mask[WINTYPE_POPUP_MENU].opacity = true;
575 opt->wintype_option[WINTYPE_POPUP_MENU].opacity = tmp;
576 opt->wintype_option[WINTYPE_DROPDOWN_MENU].opacity = tmp;
577 break;
578 case 'f':
579 case 'F':
580 fading_enable = true;
581 break;
582 P_CASEINT('r', shadow_radius);
583 case 'o':
584 opt->shadow_opacity = atof(optarg);
585 break;
586 P_CASEINT('l', shadow_offset_x);
587 P_CASEINT('t', shadow_offset_y);
588 case 'i':
589 opt->inactive_opacity = normalize_d(atof(optarg));
590 break;
591 case 'e': opt->frame_opacity = atof(optarg); break;
592 case 'z':
593 log_warn("clear-shadow is removed, shadows are automatically "
594 "cleared now. If you want to prevent shadow from been "
595 "cleared under certain types of windows, you can use "
596 "the \"full-shadow\" per window type option.");
597 break;
598 case 'n':
599 case 'a':
600 case 's':
601 log_error("-n, -a, and -s have been removed.");
602 break;
603 // Long options
604 case 256:
605 // --config
606 break;
607 case 257:
608 // --shadow-red
609 opt->shadow_red = atof(optarg);
610 break;
611 case 258:
612 // --shadow-green
613 opt->shadow_green = atof(optarg);
614 break;
615 case 259:
616 // --shadow-blue
617 opt->shadow_blue = atof(optarg);
618 break;
619 P_CASEBOOL(260, inactive_opacity_override);
620 case 261:
621 // --inactive-dim
622 opt->inactive_dim = atof(optarg);
623 break;
624 P_CASEBOOL(262, mark_wmwin_focused);
625 case 263:
626 // --shadow-exclude
627 condlst_add(&opt->shadow_blacklist, optarg);
628 break;
629 P_CASEBOOL(264, mark_ovredir_focused);
630 P_CASEBOOL(265, no_fading_openclose);
631 P_CASEBOOL(266, shadow_ignore_shaped);
632 P_CASEBOOL(267, detect_rounded_corners);
633 P_CASEBOOL(268, detect_client_opacity);
634 P_CASEINT(269, refresh_rate);
635 case 270:
636 if (optarg) {
637 opt->vsync = parse_vsync(optarg);
638 log_warn("--vsync doesn't take argument anymore. \"%s\" "
639 "is interpreted as \"%s\" for compatibility, but "
640 "this will stop working soon",
641 optarg, opt->vsync ? "true" : "false");
642 } else {
643 opt->vsync = true;
644 }
645 break;
646 case 271:
647 // --alpha-step
648 log_error("--alpha-step has been removed, we now tries to "
649 "make use of all alpha values");
650 return false;
651 case 272: log_error("use of --dbe is deprecated"); return false;
652 case 273:
653 log_error("--paint-on-overlay has been removed, the feature is enabled "
654 "whenever possible");
655 return false;
656 P_CASEBOOL(274, sw_opti);
657 case 275:
658 // --vsync-aggressive
659 log_warn("--vsync-aggressive has been deprecated, please remove it"
660 " from the command line options");
661 break;
662 P_CASEBOOL(276, use_ewmh_active_win);
663 case 277:
664 // --respect-prop-shadow
665 log_warn("--respect-prop-shadow option has been deprecated, its "
666 "functionality will always be enabled. Please remove it "
667 "from the command line options");
668 break;
669 P_CASEBOOL(278, unredir_if_possible);
670 case 279:
671 // --focus-exclude
672 condlst_add(&opt->focus_blacklist, optarg);
673 break;
674 P_CASEBOOL(280, inactive_dim_fixed);
675 P_CASEBOOL(281, detect_transient);
676 P_CASEBOOL(282, detect_client_leader);
677 case 283:
678 // --blur_background
679 opt->blur_method = BLUR_METHOD_KERNEL;
680 break;
681 P_CASEBOOL(284, blur_background_frame);
682 P_CASEBOOL(285, blur_background_fixed);
683 P_CASEBOOL(286, dbus);
684 case 287:
685 log_warn("Please use --log-file instead of --logpath");
686 // fallthrough
687 case 322:
688 // --logpath, --log-file
689 free(opt->logpath);
690 opt->logpath = strdup(optarg);
691 break;
692 case 288:
693 // --invert-color-include
694 condlst_add(&opt->invert_color_list, optarg);
695 break;
696 case 289:
697 // --opengl
698 opt->backend = BKEND_GLX;
699 break;
700 case 290:
701 // --backend
702 opt->backend = parse_backend(optarg);
703 if (opt->backend >= NUM_BKEND)
704 exit(1);
705 break;
706 P_CASEBOOL(291, glx_no_stencil);
707 P_CASEINT(293, benchmark);
708 case 294:
709 // --benchmark-wid
710 opt->benchmark_wid = (xcb_window_t)strtol(optarg, NULL, 0);
711 break;
712 case 296:
713 // --blur-background-exclude
714 condlst_add(&opt->blur_background_blacklist, optarg);
715 break;
716 case 297:
717 // --active-opacity
718 opt->active_opacity = normalize_d(atof(optarg));
719 break;
720 P_CASEBOOL(298, glx_no_rebind_pixmap);
721 case 299: {
722 // --glx-swap-method
723 char *endptr;
724 long tmpval = strtol(optarg, &endptr, 10);
725 bool should_remove = true;
726 if (*endptr || !(*optarg)) {
727 // optarg is not a number, or an empty string
728 tmpval = -1;
729 }
730 if (strcmp(optarg, "undefined") != 0 && tmpval != 0) {
731 // If not undefined, we will use damage and buffer-age to
732 // limit the rendering area.
733 opt->use_damage = true;
734 should_remove = false;
735 }
736 log_warn("--glx-swap-method has been deprecated, your setting "
737 "\"%s\" should be %s.",
738 optarg,
739 !should_remove ? "replaced by `--use-damage`" :
740 "removed");
741 break;
742 }
743 case 300:
744 // --fade-exclude
745 condlst_add(&opt->fade_blacklist, optarg);
746 break;
747 case 301:
748 // --blur-kern
749 opt->blur_kerns = parse_blur_kern_lst(optarg, &conv_kern_hasneg,
750 &opt->blur_kernel_count);
751 if (!opt->blur_kerns) {
752 exit(1);
753 }
754 break;
755 P_CASEINT(302, resize_damage);
756 case 303:
757 // --glx-use-gpushader4
758 log_warn("--glx-use-gpushader4 is deprecated since v6."
759 " Please remove it from command line options.");
760 break;
761 case 304:
762 // --opacity-rule
763 if (!parse_rule_opacity(&opt->opacity_rules, optarg))
764 exit(1);
765 break;
766 case 305:
767 // --shadow-exclude-reg
768 free(opt->shadow_exclude_reg_str);
769 opt->shadow_exclude_reg_str = strdup(optarg);
770 log_warn("--shadow-exclude-reg is deprecated. You are likely "
771 "better off using --shadow-exclude anyway");
772 break;
773 case 306:
774 // --paint-exclude
775 condlst_add(&opt->paint_blacklist, optarg);
776 break;
777 P_CASEBOOL(307, xinerama_shadow_crop);
778 case 308:
779 // --unredir-if-possible-exclude
780 condlst_add(&opt->unredir_if_possible_blacklist, optarg);
781 break;
782 P_CASELONG(309, unredir_if_possible_delay);
783 case 310:
784 // --write-pid-path
785 free(opt->write_pid_path);
786 opt->write_pid_path = strdup(optarg);
787 if (*opt->write_pid_path != '/') {
788 log_warn("--write-pid-path is not an absolute path");
789 }
790 break;
791 P_CASEBOOL(311, vsync_use_glfinish);
792 case 312:
793 // --xrender-sync
794 log_error("Please use --xrender-sync-fence instead of --xrender-sync");
795 return false;
796 P_CASEBOOL(313, xrender_sync_fence);
797 P_CASEBOOL(315, no_fading_destroyed_argb);
798 P_CASEBOOL(316, force_win_blend);
799 case 317:
800 opt->glx_fshader_win_str = strdup(optarg);
801 break;
802 case 321: {
803 enum log_level tmp_level = string_to_log_level(optarg);
804 if (tmp_level == LOG_LEVEL_INVALID) {
805 log_warn("Invalid log level, defaults to WARN");
806 } else {
807 log_set_level_tls(tmp_level);
808 }
809 break;
810 }
811 P_CASEBOOL(319, no_x_selection);
812 P_CASEBOOL(323, use_damage);
813 case 324:
814 opt->use_damage = false;
815 break;
816 case 325:
817 opt->vsync = false;
818 break;
819
820 case 326:
821 opt->max_brightness = atof(optarg);
822 break;
823 P_CASEBOOL(327, transparent_clipping);
824 case 328: {
825 // --blur-method
826 enum blur_method method = parse_blur_method(optarg);
827 if (method >= BLUR_METHOD_INVALID) {
828 log_warn("Invalid blur method %s, ignoring.", optarg);
829 } else {
830 opt->blur_method = method;
831 }
832 break;
833 }
834 case 329:
835 // --blur-size
836 opt->blur_radius = atoi(optarg);
837 break;
838 case 330:
839 // --blur-deviation
840 opt->blur_deviation = atof(optarg);
841 break;
842
843 P_CASEBOOL(733, experimental_backends);
844 P_CASEBOOL(800, monitor_repaint);
845 case 801: opt->print_diagnostics = true; break;
846 P_CASEBOOL(802, debug_mode);
847 P_CASEBOOL(803, no_ewmh_fullscreen);
848 default: usage(argv[0], 1); break;
849 #undef P_CASEBOOL
850 }
851 // clang-format on
852 }
853
854 // Restore LC_NUMERIC
855 setlocale(LC_NUMERIC, lc_numeric_old);
856 free(lc_numeric_old);
857
858 if (opt->monitor_repaint && opt->backend != BKEND_XRENDER &&
859 !opt->experimental_backends) {
860 log_warn("--monitor-repaint has no effect when backend is not xrender");
861 }
862
863 if (opt->experimental_backends && !backend_list[opt->backend]) {
864 log_error("Backend \"%s\" is not available as part of the experimental "
865 "backends.",
866 BACKEND_STRS[opt->backend]);
867 return false;
868 }
869
870 if (opt->debug_mode && !opt->experimental_backends) {
871 log_error("Debug mode only works with the experimental backends.");
872 return false;
873 }
874
875 if (opt->transparent_clipping && !opt->experimental_backends) {
876 log_error("Transparent clipping only works with the experimental "
877 "backends");
878 return false;
879 }
880
881 // Range checking and option assignments
882 opt->fade_delta = max2(opt->fade_delta, 1);
883 opt->shadow_radius = max2(opt->shadow_radius, 0);
884 opt->shadow_red = normalize_d(opt->shadow_red);
885 opt->shadow_green = normalize_d(opt->shadow_green);
886 opt->shadow_blue = normalize_d(opt->shadow_blue);
887 opt->inactive_dim = normalize_d(opt->inactive_dim);
888 opt->frame_opacity = normalize_d(opt->frame_opacity);
889 opt->shadow_opacity = normalize_d(opt->shadow_opacity);
890 opt->refresh_rate = normalize_i_range(opt->refresh_rate, 0, 300);
891
892 opt->max_brightness = normalize_d(opt->max_brightness);
893 if (opt->max_brightness < 1.0) {
894 if (opt->use_damage) {
895 log_warn("--max-brightness requires --no-use-damage. Falling "
896 "back to 1.0");
897 opt->max_brightness = 1.0;
898 }
899
900 if (!opt->experimental_backends || opt->backend != BKEND_GLX) {
901 log_warn("--max-brightness requires the experimental glx "
902 "backend. Falling back to 1.0");
903 opt->max_brightness = 1.0;
904 }
905 }
906
907 // Apply default wintype options that are dependent on global options
908 set_default_winopts(opt, winopt_mask, shadow_enable, fading_enable);
909
910 // --blur-background-frame implies --blur-background
911 if (opt->blur_background_frame && opt->blur_method == BLUR_METHOD_NONE) {
912 opt->blur_method = BLUR_METHOD_KERNEL;
913 }
914
915 // Other variables determined by options
916
917 // Determine whether we track window grouping
918 if (opt->detect_transient || opt->detect_client_leader) {
919 opt->track_leader = true;
920 }
921
922 // Fill default blur kernel
923 if (opt->blur_method == BLUR_METHOD_KERNEL &&
924 (!opt->blur_kerns || !opt->blur_kerns[0])) {
925 opt->blur_kerns = parse_blur_kern_lst("3x3box", &conv_kern_hasneg,
926 &opt->blur_kernel_count);
927 CHECK(opt->blur_kerns);
928 CHECK(opt->blur_kernel_count);
929 }
930
931 if (opt->resize_damage < 0) {
932 log_warn("Negative --resize-damage will not work correctly.");
933 }
934
935 if (opt->backend == BKEND_XRENDER && conv_kern_hasneg) {
936 log_warn("A convolution kernel with negative values may not work "
937 "properly under X Render backend.");
938 }
939
940 return true;
941 }
942
943 // vim: set noet sw=8 ts=8 :
944