Merge pull request #69 from yshui/arg

Clean ups
This commit is contained in:
yshui 2018-12-21 00:01:48 +00:00 committed by GitHub
commit d2cc4e0243
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 1119 additions and 1155 deletions

View File

@ -22,9 +22,6 @@ OPTIONS
*-h*, *--help*::
Get the usage text embedded in program code, which may be more up-to-date than this man page.
*-d* 'DISPLAY'::
Display to be managed.
*-r*, *--shadow-radius*='RADIUS'::
The blur radius for shadows, in pixels. (defaults to 12)
@ -73,9 +70,6 @@ OPTIONS
*-b*, *--daemon*::
Daemonize process. Fork to background after initialization. Causes issues with certain (badly-written) drivers.
*-S*::
Enable synchronous X operation (for debugging).
*--log-level*::
Set the log level. Possible values are "TRACE", "DEBUG", "INFO", "WARN", "ERROR", in increasing level of importance. Case doesn't matter.

847
src/argparse.c Normal file
View File

@ -0,0 +1,847 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright (c) Yuxuan Shui <yshuiv7@gmail.com>
#include <getopt.h>
#include <locale.h>
#include <stdbool.h>
#include <unistd.h>
#include "argparse.h"
#include "common.h"
#include "config.h"
/**
* Print usage text and exit.
*/
static void usage(int ret) {
#define WARNING_DISABLED " (DISABLED AT COMPILE TIME)"
#define WARNING
static const char *usage_text =
"compton (" COMPTON_VERSION ")\n"
"This is the maintenance fork of compton, please report\n"
"bugs to https://github.com/yshui/compton\n\n"
"usage: compton [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"
#undef WARNING
#ifndef CONFIG_LIBCONFIG
#define WARNING WARNING_DISABLED
#else
#define WARNING
#endif
"--config path\n"
" Look for configuration file at the path. Use /dev/null to avoid\n"
" loading configuration file." WARNING "\n"
"\n"
"--write-pid-path path\n"
" Write process ID to a file.\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_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"
"--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_OPACITY on client windows, useful for window\n"
" managers not passing _NET_WM_OPACITY of client windows to frame\n"
" windows.\n"
"\n"
"--refresh-rate val\n"
" Specify refresh rate of the screen. If not specified or 0, compton\n"
" will try detecting this with X RandR extension.\n"
"\n"
"--vsync vsync-method\n"
" Set VSync method. There are (up to) 5 VSync methods currently\n"
" available:\n"
" none = No VSync\n"
#undef WARNING
#ifndef CONFIG_VSYNC_DRM
#define WARNING WARNING_DISABLED
#else
#define WARNING
#endif
" drm = VSync with DRM_IOCTL_WAIT_VBLANK. May only work on some\n"
" (DRI-based) drivers." WARNING "\n"
#undef WARNING
#ifndef CONFIG_OPENGL
#define WARNING WARNING_DISABLED
#else
#define WARNING
#endif
" opengl = Try to VSync with SGI_video_sync OpenGL extension. Only\n"
" work on some drivers." WARNING "\n"
" opengl-oml = Try to VSync with OML_sync_control OpenGL extension.\n"
" Only work on some drivers." WARNING "\n"
" opengl-swc = Enable driver-level VSync. Works only with GLX "
"backend." WARNING "\n"
" opengl-mswc = Deprecated, use opengl-swc instead." WARNING "\n"
"\n"
"--vsync-aggressive\n"
" Attempt to send painting request before VBlank and do XFlush()\n"
" during VBlank. This switch may be lifted out at any moment.\n"
"\n"
"--paint-on-overlay\n"
" Painting on X Composite overlay window.\n"
"\n"
"--sw-opti\n"
" Limit compton to repaint at most once every 1 / refresh_rate\n"
" second to boost performance.\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"
"--respect-prop-shadow\n"
" Respect _COMPTON_SHADOW. This a prototype-level feature, which\n"
" you must not rely on.\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"
"--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. WM_TRANSIENT_FOR has\n"
" higher priority if --detect-transient is enabled, too.\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\"'. compton-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"
#undef WARNING
#ifndef CONFIG_XINERAMA
#define WARNING WARNING_DISABLED
#else
#define WARNING
#endif
"\n"
"--xinerama-shadow-crop\n"
" Crop shadow of a window fully on a particular Xinerama screen to the\n"
" screen." WARNING "\n"
"\n"
#undef WARNING
#ifndef CONFIG_OPENGL
#define WARNING "(GLX BACKENDS DISABLED AT COMPILE TIME)"
#else
#define WARNING
#endif
"--backend backend\n"
" Choose backend. Possible choices are xrender, glx, and\n"
" xr_glx_hybrid" WARNING ".\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"
"--glx-swap-method undefined/copy/exchange/3/4/5/6/buffer-age\n"
" GLX backend: GLX buffer swap method we assume. Could be\n"
" undefined (0), copy (1), exchange (2), 3-6, or buffer-age (-1).\n"
" \"undefined\" is the slowest and the safest, and the default value.\n"
" 1 is fastest, but may fail on some drivers, 2-6 are gradually slower\n"
" but safer (6 is still faster than 0). -1 means auto-detect using\n"
" GLX_EXT_buffer_age, supported by some drivers. \n"
"\n"
"--glx-use-gpushader4\n"
" GLX backend: Use GL_EXT_gpu_shader4 for some optimization on blur\n"
" GLSL code. My tests on GTX 670 show no noticeable effect.\n"
"\n"
"--xrender-sync\n"
" Attempt to synchronize client applications' draw calls with XSync(),\n"
" used on GLX backend to ensure up-to-date window content is painted.\n"
#undef WARNING
#define WARNING
"\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." WARNING "\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"
#undef WARNING
#ifndef CONFIG_DBUS
#define WARNING WARNING_DISABLED
#else
#define WARNING
#endif
"--dbus\n"
" Enable remote control via D-Bus. See the D-BUS API section in the\n"
" man page for more details." WARNING "\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"
"--monitor-repaint\n"
" Highlight the updated area of the screen. For debugging the xrender\n"
" backend only.\n";
FILE *f = (ret ? stderr : stdout);
fputs(usage_text, f);
#undef WARNING
#undef WARNING_DISABLED
}
static const char *shortopts = "D:I:O:d:r:o:m:l:t:i:e:hscnfFCaSzGb";
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'},
{"no-dock-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'},
{"no-dnd-shadow", no_argument, NULL, 'G'},
{"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", required_argument, NULL, 270},
{"alpha-step", required_argument, NULL, 271},
{"dbe", no_argument, NULL, 272},
{"paint-on-overlay", no_argument, NULL, 273},
{"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},
{"glx-copy-from-front", no_argument, NULL, 292},
{"benchmark", required_argument, NULL, 293},
{"benchmark-wid", required_argument, NULL, 294},
{"glx-use-copysubbuffermesa", no_argument, NULL, 295},
{"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", no_argument, NULL, 312},
{"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},
{"no-name-pixmap", no_argument, NULL, 320},
{"log-level", required_argument, NULL, 321},
{"reredir-on-root-change", no_argument, NULL, 731},
{"glx-reinit-on-root-change", no_argument, NULL, 732},
{"monitor-repaint", no_argument, NULL, 800},
{"diagnostics", no_argument, NULL, 801},
// 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,
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;
while (-1 != (o = getopt_long(argc, argv, shortopts, longopts, &longopt_idx))) {
if (o == 256)
*config_file = strdup(optarg);
else if (o == 'd') {
log_warn("-d will be ignored, please use the DISPLAY "
"environment variable");
} else if (o == 314) {
*all_xerrors = true;
} else if (o == 318) {
printf("%s\n", COMPTON_VERSION);
*exit_code = 0;
return true;
} else if (o == 'S') {
log_warn("-S will be ignored");
} else if (o == 320) {
log_warn("--no-name-pixmap will be ignored");
} else if (o == '?' || o == ':') {
usage(1);
*exit_code = 1;
return true;
}
}
// Check for abundant positional arguments
if (optind < argc)
log_fatal("compton doesn't accept positional arguments.");
return false;
}
/**
* Process arguments and configuration files.
*/
void get_cfg(session_t *ps, int argc, char *const *argv) {
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 "
"without this feature, please feel free to "
"open a bug report.";
optind = 1;
while (-1 != (o = getopt_long(argc, argv, shortopts, longopts, &longopt_idx))) {
long val = 0;
switch (o) {
#define P_CASEBOOL(idx, option) \
case idx: \
ps->o.option = true; \
break
#define P_CASELONG(idx, option) \
case idx: \
if (!parse_long(optarg, &val)) \
exit(1); \
ps->o.option = val; \
break
// 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 'c': shadow_enable = true; break;
case 'C':
winopt_mask[WINTYPE_DOCK].shadow = true;
ps->o.wintype_option[WINTYPE_DOCK].shadow = true;
break;
case 'G':
winopt_mask[WINTYPE_DND].shadow = true;
ps->o.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;
break;
case 'f':
case 'F':
fading_enable = true;
break;
P_CASELONG('r', shadow_radius);
case 'o':
ps->o.shadow_opacity = atof(optarg);
break;
P_CASELONG('l', shadow_offset_x);
P_CASELONG('t', shadow_offset_y);
case 'i':
ps->o.inactive_opacity = (normalize_d(atof(optarg)) * OPAQUE);
break;
case 'e': ps->o.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.");
break;
P_CASEBOOL('b', fork_after_register);
// Long options
case 256:
// --config
break;
case 257:
// --shadow-red
ps->o.shadow_red = atof(optarg);
break;
case 258:
// --shadow-green
ps->o.shadow_green = atof(optarg);
break;
case 259:
// --shadow-blue
ps->o.shadow_blue = atof(optarg);
break;
P_CASEBOOL(260, inactive_opacity_override);
case 261:
// --inactive-dim
ps->o.inactive_dim = atof(optarg);
break;
P_CASEBOOL(262, mark_wmwin_focused);
case 263:
// --shadow-exclude
condlst_add(ps, &ps->o.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);
case 270:
// --vsync
if (!parse_vsync(ps, optarg))
exit(1);
break;
case 271:
// --alpha-step
log_warn("--alpha-step has been removed, compton now tries to "
"make use of all alpha values");
break;
case 272: log_warn("use of --dbe is deprecated"); break;
case 273:
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);
case 279:
// --focus-exclude
condlst_add(ps, &ps->o.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);
case 287:
// --logpath
ps->o.logpath = strdup(optarg);
break;
case 288:
// --invert-color-include
condlst_add(ps, &ps->o.invert_color_list, optarg);
break;
case 289:
// --opengl
ps->o.backend = BKEND_GLX;
break;
case 290:
// --backend
if (!parse_backend(ps, optarg))
exit(1);
break;
P_CASEBOOL(291, glx_no_stencil);
case 292:
log_warn("--glx-copy-from-front %s", deprecation_message);
break;
P_CASELONG(293, benchmark);
case 294:
// --benchmark-wid
ps->o.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);
break;
case 297:
// --active-opacity
ps->o.active_opacity = (normalize_d(atof(optarg)) * OPAQUE);
break;
P_CASEBOOL(298, glx_no_rebind_pixmap);
case 299:
// --glx-swap-method
if (!parse_glx_swap_method(ps, optarg))
exit(1);
break;
case 300:
// --fade-exclude
condlst_add(ps, &ps->o.fade_blacklist, optarg);
break;
case 301:
// --blur-kern
if (!parse_conv_kern_lst(ps, optarg, ps->o.blur_kerns,
MAX_BLUR_PASS))
exit(1);
break;
P_CASELONG(302, resize_damage);
P_CASEBOOL(303, glx_use_gpushader4);
case 304:
// --opacity-rule
if (!parse_rule_opacity(ps, optarg))
exit(1);
break;
case 305:
// --shadow-exclude-reg
ps->o.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);
break;
P_CASEBOOL(307, xinerama_shadow_crop);
case 308:
// --unredir-if-possible-exclude
condlst_add(ps, &ps->o.unredir_if_possible_blacklist, optarg);
break;
P_CASELONG(309, unredir_if_possible_delay);
case 310:
// --write-pid-path
ps->o.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);
case 317:
ps->o.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");
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(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;
default: usage(1); break;
#undef P_CASEBOOL
}
}
// Restore LC_NUMERIC
setlocale(LC_NUMERIC, lc_numeric_old);
free(lc_numeric_old);
if (ps->o.monitor_repaint && ps->o.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);
// 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
if (ps->o.blur_background_frame)
ps->o.blur_background = true;
if (ps->o.xrender_sync_fence)
ps->o.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;
}
// Determine whether we track window grouping
if (ps->o.detect_transient || ps->o.detect_client_leader) {
ps->o.track_leader = true;
}
// Fill default blur kernel
if (ps->o.blur_background && !ps->o.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
static const xcb_render_fixed_t convolution_blur[] = {
// Must convert to XFixed with DOUBLE_TO_XFIXED()
// Matrix size
DOUBLE_TO_XFIXED(3),
DOUBLE_TO_XFIXED(3),
// Matrix
DOUBLE_TO_XFIXED(1),
DOUBLE_TO_XFIXED(1),
DOUBLE_TO_XFIXED(1),
DOUBLE_TO_XFIXED(1),
DOUBLE_TO_XFIXED(1),
DOUBLE_TO_XFIXED(1),
DOUBLE_TO_XFIXED(1),
DOUBLE_TO_XFIXED(1),
DOUBLE_TO_XFIXED(1),
};
ps->o.blur_kerns[0] =
ccalloc(ARR_SIZE(convolution_blur), xcb_render_fixed_t);
memcpy(ps->o.blur_kerns[0], convolution_blur, sizeof(convolution_blur));
}
if (ps->o.resize_damage < 0)
log_warn("Negative --resize-damage will not work correctly.");
}
// vim: set noet sw=8 ts=8 :

19
src/argparse.h Normal file
View File

@ -0,0 +1,19 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright (c) Yuxuan Shui <yshuiv7@gmail.com>
#pragma once
#include <stdbool.h>
#include "compiler.h"
typedef struct session session_t;
/// 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,
int *exit_code);
/**
* Process arguments and configuration files.
*/
void get_cfg(session_t *ps, int argc, char *const *argv);

View File

@ -81,11 +81,6 @@
#include <ev.h>
#include <pixman.h>
// libdbus
#ifdef CONFIG_DBUS
#include <dbus/dbus.h>
#endif
#ifdef CONFIG_OPENGL
// libGL
#define GL_GLEXT_PROTOTYPES
@ -404,11 +399,6 @@ typedef struct options_t {
char *config_file;
/// Path to write PID to.
char *write_pid_path;
/// The display name we used. NULL means we are using the value of the
/// <code>DISPLAY</code> environment variable.
char *display;
/// Safe representation of display name.
char *display_repr;
/// The backend in use.
enum backend backend;
/// Whether to sync X drawing to avoid certain delay issues with
@ -463,10 +453,6 @@ typedef struct options_t {
Window benchmark_wid;
/// A list of conditions of windows not to paint.
c2_lptr_t *paint_blacklist;
/// Whether to avoid using xcb_composite_name_window_pixmap(), for debugging.
bool no_name_pixmap;
/// Whether to work under synchronized mode for debugging.
bool synchronize;
/// Whether to show all X errors.
bool show_all_xerrors;
/// Whether to avoid acquiring X Selection.
@ -888,10 +874,7 @@ typedef struct session {
#ifdef CONFIG_DBUS
// === DBus related ===
// DBus connection.
DBusConnection *dbus_conn;
// DBus service name.
char *dbus_service;
void *dbus_data;
#endif
} session_t;
@ -1507,37 +1490,6 @@ xr_sync(session_t *ps, Drawable d, XSyncFence *pfence) {
*/
///@{
#ifdef CONFIG_DBUS
/** @name DBus handling
*/
///@{
bool
cdbus_init(session_t *ps);
void
cdbus_destroy(session_t *ps);
void
cdbus_loop(session_t *ps);
void
cdbus_ev_win_added(session_t *ps, win *w);
void
cdbus_ev_win_destroyed(session_t *ps, win *w);
void
cdbus_ev_win_mapped(session_t *ps, win *w);
void
cdbus_ev_win_unmapped(session_t *ps, win *w);
void
cdbus_ev_win_focusout(session_t *ps, win *w);
void
cdbus_ev_win_focusin(session_t *ps, win *w);
//!@}
/** @name DBus hooks
*/
///@{

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,11 @@
*
*/
#include <ctype.h>
#include <unistd.h>
#include <sys/types.h>
#include "common.h"
#include "compiler.h"
#include "win.h"
#include "string_utils.h"
@ -16,6 +21,45 @@
#include "dbus.h"
struct cdbus_data {
/// DBus connection.
DBusConnection *dbus_conn;
/// DBus service name.
char *dbus_service;
};
// Window type
typedef uint32_t cdbus_window_t;
#define CDBUS_TYPE_WINDOW DBUS_TYPE_UINT32
#define CDBUS_TYPE_WINDOW_STR DBUS_TYPE_UINT32_AS_STRING
typedef uint16_t cdbus_enum_t;
#define CDBUS_TYPE_ENUM DBUS_TYPE_UINT16
#define CDBUS_TYPE_ENUM_STR DBUS_TYPE_UINT16_AS_STRING
#define CDBUS_SERVICE_NAME "com.github.chjj.compton"
#define CDBUS_INTERFACE_NAME CDBUS_SERVICE_NAME
#define CDBUS_OBJECT_NAME "/com/github/chjj/compton"
#define CDBUS_ERROR_PREFIX CDBUS_INTERFACE_NAME ".error"
#define CDBUS_ERROR_UNKNOWN CDBUS_ERROR_PREFIX ".unknown"
#define CDBUS_ERROR_UNKNOWN_S "Well, I don't know what happened. Do you?"
#define CDBUS_ERROR_BADMSG CDBUS_ERROR_PREFIX ".bad_message"
#define CDBUS_ERROR_BADMSG_S "Unrecognized command. Beware compton " \
"cannot make you a sandwich."
#define CDBUS_ERROR_BADARG CDBUS_ERROR_PREFIX ".bad_argument"
#define CDBUS_ERROR_BADARG_S "Failed to parse argument %d: %s"
#define CDBUS_ERROR_BADWIN CDBUS_ERROR_PREFIX ".bad_window"
#define CDBUS_ERROR_BADWIN_S "Requested window %#010x not found."
#define CDBUS_ERROR_BADTGT CDBUS_ERROR_PREFIX ".bad_target"
#define CDBUS_ERROR_BADTGT_S "Target \"%s\" not found."
#define CDBUS_ERROR_FORBIDDEN CDBUS_ERROR_PREFIX ".forbidden"
#define CDBUS_ERROR_FORBIDDEN_S "Incorrect password, access denied."
#define CDBUS_ERROR_CUSTOM CDBUS_ERROR_PREFIX ".custom"
#define CDBUS_ERROR_CUSTOM_S "%s"
#define cdbus_reply_err(ps, srcmsg, err_name, err_format, ...) \
cdbus_reply_errm((ps), dbus_message_new_error_printf((srcmsg), (err_name), (err_format), ## __VA_ARGS__))
static DBusHandlerResult
cdbus_process(DBusConnection *conn, DBusMessage *m, void *);
@ -41,7 +85,13 @@ cdbus_callback_watch_toggled(DBusWatch *watch, void *data);
* Initialize D-Bus connection.
*/
bool
cdbus_init(session_t *ps) {
cdbus_init(session_t *ps, const char *uniq) {
auto cd = cmalloc(struct cdbus_data);
cd->dbus_service = NULL;
// Set ps->dbus_data here because add_watch functions need it
ps->dbus_data = cd;
DBusError err = { };
// Initialize
@ -49,69 +99,87 @@ cdbus_init(session_t *ps) {
// Connect to D-Bus
// Use dbus_bus_get_private() so we can fully recycle it ourselves
ps->dbus_conn = dbus_bus_get_private(DBUS_BUS_SESSION, &err);
cd->dbus_conn = dbus_bus_get_private(DBUS_BUS_SESSION, &err);
if (dbus_error_is_set(&err)) {
log_error("D-Bus connection failed (%s).", err.message);
dbus_error_free(&err);
return false;
goto fail;
}
if (!ps->dbus_conn) {
if (!cd->dbus_conn) {
log_error("D-Bus connection failed for unknown reason.");
return false;
goto fail;
}
// Avoid exiting on disconnect
dbus_connection_set_exit_on_disconnect(ps->dbus_conn, false);
dbus_connection_set_exit_on_disconnect(cd->dbus_conn, false);
// Request service name
{
// Build service name
char *service = mstrjoin3(CDBUS_SERVICE_NAME, ".", ps->o.display_repr);
ps->dbus_service = service;
size_t service_len = strlen(CDBUS_SERVICE_NAME)+strlen(uniq)+2;
char *service = ccalloc(service_len, char);
snprintf(service, service_len, "%s.%s", CDBUS_SERVICE_NAME, uniq);
// Make a valid dbus name by converting non alphanumeric characters to underscore
char *tmp = service + strlen(CDBUS_SERVICE_NAME)+1;
while (*tmp) {
if (!isalnum(*tmp)) {
*tmp = '_';
}
tmp++;
}
cd->dbus_service = service;
// Request for the name
int ret = dbus_bus_request_name(ps->dbus_conn, service,
int ret = dbus_bus_request_name(cd->dbus_conn, service,
DBUS_NAME_FLAG_DO_NOT_QUEUE, &err);
if (dbus_error_is_set(&err)) {
log_error("Failed to obtain D-Bus name (%s).", err.message);
dbus_error_free(&err);
goto fail;
}
if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret
&& DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER != ret) {
log_error("Failed to become the primary owner of requested D-Bus name (%d).", ret);
goto fail;
}
}
// Add watch handlers
if (!dbus_connection_set_watch_functions(ps->dbus_conn,
if (!dbus_connection_set_watch_functions(cd->dbus_conn,
cdbus_callback_add_watch, cdbus_callback_remove_watch,
cdbus_callback_watch_toggled, ps, NULL)) {
log_error("Failed to add D-Bus watch functions.");
return false;
goto fail;
}
// Add timeout handlers
if (!dbus_connection_set_timeout_functions(ps->dbus_conn,
if (!dbus_connection_set_timeout_functions(cd->dbus_conn,
cdbus_callback_add_timeout, cdbus_callback_remove_timeout,
cdbus_callback_timeout_toggled, ps, NULL)) {
log_error("Failed to add D-Bus timeout functions.");
return false;
goto fail;
}
// Add match
dbus_bus_add_match(ps->dbus_conn,
dbus_bus_add_match(cd->dbus_conn,
"type='method_call',interface='" CDBUS_INTERFACE_NAME "'", &err);
if (dbus_error_is_set(&err)) {
log_error("Failed to add D-Bus match.");
dbus_error_free(&err);
return false;
goto fail;
}
dbus_connection_add_filter(ps->dbus_conn, cdbus_process, ps, NULL);
dbus_connection_add_filter(cd->dbus_conn, cdbus_process, ps, NULL);
return true;
fail:
ps->dbus_data = NULL;
free(cd->dbus_service);
free(cd);
return false;
}
/**
@ -119,13 +187,14 @@ cdbus_init(session_t *ps) {
*/
void
cdbus_destroy(session_t *ps) {
if (ps->dbus_conn) {
struct cdbus_data *cd = ps->dbus_data;
if (cd->dbus_conn) {
// Release DBus name firstly
if (ps->dbus_service) {
if (cd->dbus_service) {
DBusError err = { };
dbus_error_init(&err);
dbus_bus_release_name(ps->dbus_conn, ps->dbus_service, &err);
dbus_bus_release_name(cd->dbus_conn, cd->dbus_service, &err);
if (dbus_error_is_set(&err)) {
log_error("Failed to release DBus name (%s).", err.message);
dbus_error_free(&err);
@ -133,9 +202,10 @@ cdbus_destroy(session_t *ps) {
}
// Close and unref the connection
dbus_connection_close(ps->dbus_conn);
dbus_connection_unref(ps->dbus_conn);
dbus_connection_close(cd->dbus_conn);
dbus_connection_unref(cd->dbus_conn);
}
free(cd);
}
/** @name DBusTimeout handling
@ -213,7 +283,7 @@ cdbus_callback_timeout_toggled(DBusTimeout *timeout, void *data) {
typedef struct ev_dbus_io {
ev_io w;
session_t *ps;
struct cdbus_data *cd;
DBusWatch *dw;
} ev_dbus_io;
@ -225,7 +295,7 @@ void cdbus_io_callback(EV_P_ ev_io *w, int revents) {
if (revents & EV_WRITE)
flags |= DBUS_WATCH_WRITABLE;
dbus_watch_handle(dw->dw, flags);
while (dbus_connection_dispatch(dw->ps->dbus_conn) != DBUS_DISPATCH_COMPLETE);
while (dbus_connection_dispatch(dw->cd->dbus_conn) != DBUS_DISPATCH_COMPLETE);
}
/**
@ -252,7 +322,7 @@ cdbus_callback_add_watch(DBusWatch *watch, void *data) {
auto w = ccalloc(1, ev_dbus_io);
w->dw = watch;
w->ps = ps;
w->cd = ps->dbus_data;
ev_io_init(&w->w, cdbus_io_callback, dbus_watch_get_unix_fd(watch),
cdbus_get_watch_cond(watch));
@ -460,6 +530,7 @@ static bool
cdbus_signal(session_t *ps, const char *name,
bool (*func)(session_t *ps, DBusMessage *msg, const void *data),
const void *data) {
struct cdbus_data *cd = ps->dbus_data;
DBusMessage* msg = NULL;
// Create a signal
@ -477,12 +548,12 @@ cdbus_signal(session_t *ps, const char *name,
}
// Send the message and flush the connection
if (!dbus_connection_send(ps->dbus_conn, msg, NULL)) {
if (!dbus_connection_send(cd->dbus_conn, msg, NULL)) {
log_error("Failed to send D-Bus signal.");
dbus_message_unref(msg);
return false;
}
dbus_connection_flush(ps->dbus_conn);
dbus_connection_flush(cd->dbus_conn);
// Free the message
dbus_message_unref(msg);
@ -490,6 +561,14 @@ cdbus_signal(session_t *ps, const char *name,
return true;
}
/**
* Send a signal with a Window ID as argument.
*/
static inline bool
cdbus_signal_wid(session_t *ps, const char *name, Window wid) {
return cdbus_signal(ps, name, cdbus_apdarg_wid, &wid);
}
/**
* Send a D-Bus reply.
*
@ -503,6 +582,7 @@ static bool
cdbus_reply(session_t *ps, DBusMessage *srcmsg,
bool (*func)(session_t *ps, DBusMessage *msg, const void *data),
const void *data) {
struct cdbus_data *cd = ps->dbus_data;
DBusMessage* msg = NULL;
// Create a reply
@ -519,12 +599,12 @@ cdbus_reply(session_t *ps, DBusMessage *srcmsg,
}
// Send the message and flush the connection
if (!dbus_connection_send(ps->dbus_conn, msg, NULL)) {
if (!dbus_connection_send(cd->dbus_conn, msg, NULL)) {
log_error("Failed to send D-Bus reply.");
dbus_message_unref(msg);
return false;
}
dbus_connection_flush(ps->dbus_conn);
dbus_connection_flush(cd->dbus_conn);
// Free the message
dbus_message_unref(msg);
@ -532,6 +612,62 @@ cdbus_reply(session_t *ps, DBusMessage *srcmsg,
return true;
}
/**
* Send a reply with a bool argument.
*/
static inline bool
cdbus_reply_bool(session_t *ps, DBusMessage *srcmsg, bool bval) {
return cdbus_reply(ps, srcmsg, cdbus_apdarg_bool, &bval);
}
/**
* Send a reply with an int32 argument.
*/
static inline bool
cdbus_reply_int32(session_t *ps, DBusMessage *srcmsg, int32_t val) {
return cdbus_reply(ps, srcmsg, cdbus_apdarg_int32, &val);
}
/**
* Send a reply with an uint32 argument.
*/
static inline bool
cdbus_reply_uint32(session_t *ps, DBusMessage *srcmsg, uint32_t val) {
return cdbus_reply(ps, srcmsg, cdbus_apdarg_uint32, &val);
}
/**
* Send a reply with a double argument.
*/
static inline bool
cdbus_reply_double(session_t *ps, DBusMessage *srcmsg, double val) {
return cdbus_reply(ps, srcmsg, cdbus_apdarg_double, &val);
}
/**
* Send a reply with a wid argument.
*/
static inline bool
cdbus_reply_wid(session_t *ps, DBusMessage *srcmsg, Window wid) {
return cdbus_reply(ps, srcmsg, cdbus_apdarg_wid, &wid);
}
/**
* Send a reply with a string argument.
*/
static inline bool
cdbus_reply_string(session_t *ps, DBusMessage *srcmsg, const char *str) {
return cdbus_reply(ps, srcmsg, cdbus_apdarg_string, str);
}
/**
* Send a reply with a enum argument.
*/
static inline bool
cdbus_reply_enum(session_t *ps, DBusMessage *srcmsg, cdbus_enum_t eval) {
return cdbus_reply(ps, srcmsg, cdbus_apdarg_enum, &eval);
}
/**
* Send a D-Bus error reply.
*
@ -540,18 +676,19 @@ cdbus_reply(session_t *ps, DBusMessage *srcmsg,
*/
static bool
cdbus_reply_errm(session_t *ps, DBusMessage *msg) {
struct cdbus_data *cd = ps->dbus_data;
if (!msg) {
log_error("Failed to create D-Bus reply.");
return false;
}
// Send the message and flush the connection
if (!dbus_connection_send(ps->dbus_conn, msg, NULL)) {
if (!dbus_connection_send(cd->dbus_conn, msg, NULL)) {
log_error("Failed to send D-Bus reply.");
dbus_message_unref(msg);
return false;
}
dbus_connection_flush(ps->dbus_conn);
dbus_connection_flush(cd->dbus_conn);
// Free the message
dbus_message_unref(msg);
@ -875,7 +1012,6 @@ cdbus_process_opts_get(session_t *ps, DBusMessage *msg) {
}
cdbus_m_opts_get_do(config_file, cdbus_reply_string);
cdbus_m_opts_get_do(display_repr, cdbus_reply_string);
cdbus_m_opts_get_do(write_pid_path, cdbus_reply_string);
cdbus_m_opts_get_do(mark_wmwin_focused, cdbus_reply_bool);
cdbus_m_opts_get_do(mark_ovredir_focused, cdbus_reply_bool);
@ -892,7 +1028,7 @@ cdbus_process_opts_get(session_t *ps, DBusMessage *msg) {
cdbus_m_opts_get_do(redirected_force, cdbus_reply_enum);
cdbus_m_opts_get_do(stoppaint_force, cdbus_reply_enum);
cdbus_m_opts_get_do(logpath, cdbus_reply_string);
cdbus_m_opts_get_do(synchronize, cdbus_reply_bool);
cdbus_m_opts_get_stub(synchronize, cdbus_reply_bool, false);
cdbus_m_opts_get_do(refresh_rate, cdbus_reply_int32);
cdbus_m_opts_get_do(sw_opti, cdbus_reply_bool);
@ -1235,37 +1371,43 @@ cdbus_process(DBusConnection *c, DBusMessage *msg, void *ud) {
///@{
void
cdbus_ev_win_added(session_t *ps, win *w) {
if (ps->dbus_conn)
struct cdbus_data *cd = ps->dbus_data;
if (cd->dbus_conn)
cdbus_signal_wid(ps, "win_added", w->id);
}
void
cdbus_ev_win_destroyed(session_t *ps, win *w) {
if (ps->dbus_conn)
struct cdbus_data *cd = ps->dbus_data;
if (cd->dbus_conn)
cdbus_signal_wid(ps, "win_destroyed", w->id);
}
void
cdbus_ev_win_mapped(session_t *ps, win *w) {
if (ps->dbus_conn)
struct cdbus_data *cd = ps->dbus_data;
if (cd->dbus_conn)
cdbus_signal_wid(ps, "win_mapped", w->id);
}
void
cdbus_ev_win_unmapped(session_t *ps, win *w) {
if (ps->dbus_conn)
struct cdbus_data *cd = ps->dbus_data;
if (cd->dbus_conn)
cdbus_signal_wid(ps, "win_unmapped", w->id);
}
void
cdbus_ev_win_focusout(session_t *ps, win *w) {
if (ps->dbus_conn)
struct cdbus_data *cd = ps->dbus_data;
if (cd->dbus_conn)
cdbus_signal_wid(ps, "win_focusout", w->id);
}
void
cdbus_ev_win_focusin(session_t *ps, win *w) {
if (ps->dbus_conn)
struct cdbus_data *cd = ps->dbus_data;
if (cd->dbus_conn)
cdbus_signal_wid(ps, "win_focusin", w->id);
}
//!@}

View File

@ -9,182 +9,46 @@
*
*/
#include "common.h"
#include <stdbool.h>
#include <ctype.h>
#include <sys/types.h>
#include <unistd.h>
#include <dbus/dbus.h>
#define CDBUS_SERVICE_NAME "com.github.chjj.compton"
#define CDBUS_INTERFACE_NAME CDBUS_SERVICE_NAME
#define CDBUS_OBJECT_NAME "/com/github/chjj/compton"
#define CDBUS_ERROR_PREFIX CDBUS_INTERFACE_NAME ".error"
#define CDBUS_ERROR_UNKNOWN CDBUS_ERROR_PREFIX ".unknown"
#define CDBUS_ERROR_UNKNOWN_S "Well, I don't know what happened. Do you?"
#define CDBUS_ERROR_BADMSG CDBUS_ERROR_PREFIX ".bad_message"
#define CDBUS_ERROR_BADMSG_S "Unrecognized command. Beware compton " \
"cannot make you a sandwich."
#define CDBUS_ERROR_BADARG CDBUS_ERROR_PREFIX ".bad_argument"
#define CDBUS_ERROR_BADARG_S "Failed to parse argument %d: %s"
#define CDBUS_ERROR_BADWIN CDBUS_ERROR_PREFIX ".bad_window"
#define CDBUS_ERROR_BADWIN_S "Requested window %#010x not found."
#define CDBUS_ERROR_BADTGT CDBUS_ERROR_PREFIX ".bad_target"
#define CDBUS_ERROR_BADTGT_S "Target \"%s\" not found."
#define CDBUS_ERROR_FORBIDDEN CDBUS_ERROR_PREFIX ".forbidden"
#define CDBUS_ERROR_FORBIDDEN_S "Incorrect password, access denied."
#define CDBUS_ERROR_CUSTOM CDBUS_ERROR_PREFIX ".custom"
#define CDBUS_ERROR_CUSTOM_S "%s"
// Window type
typedef uint32_t cdbus_window_t;
#define CDBUS_TYPE_WINDOW DBUS_TYPE_UINT32
#define CDBUS_TYPE_WINDOW_STR DBUS_TYPE_UINT32_AS_STRING
typedef uint16_t cdbus_enum_t;
#define CDBUS_TYPE_ENUM DBUS_TYPE_UINT16
#define CDBUS_TYPE_ENUM_STR DBUS_TYPE_UINT16_AS_STRING
static bool
cdbus_apdarg_bool(session_t *ps, DBusMessage *msg, const void *data);
static bool
cdbus_apdarg_int32(session_t *ps, DBusMessage *msg, const void *data);
static bool
cdbus_apdarg_uint32(session_t *ps, DBusMessage *msg, const void *data);
static bool
cdbus_apdarg_double(session_t *ps, DBusMessage *msg, const void *data);
static bool
cdbus_apdarg_wid(session_t *ps, DBusMessage *msg, const void *data);
static bool
cdbus_apdarg_enum(session_t *ps, DBusMessage *msg, const void *data);
static bool
cdbus_apdarg_string(session_t *ps, DBusMessage *msg, const void *data);
static bool
cdbus_apdarg_wids(session_t *ps, DBusMessage *msg, const void *data);
/** @name DBus signal sending
*/
///@{
static bool
cdbus_signal(session_t *ps, const char *name,
bool (*func)(session_t *ps, DBusMessage *msg, const void *data),
const void *data);
/**
* Send a signal with no argument.
*/
static inline bool
cdbus_signal_noarg(session_t *ps, const char *name) {
return cdbus_signal(ps, name, NULL, NULL);
}
/**
* Send a signal with a Window ID as argument.
*/
static inline bool
cdbus_signal_wid(session_t *ps, const char *name, Window wid) {
return cdbus_signal(ps, name, cdbus_apdarg_wid, &wid);
}
///@}
/** @name DBus reply sending
*/
///@{
static bool
cdbus_reply(session_t *ps, DBusMessage *srcmsg,
bool (*func)(session_t *ps, DBusMessage *msg, const void *data),
const void *data);
static bool
cdbus_reply_errm(session_t *ps, DBusMessage *msg);
#define cdbus_reply_err(ps, srcmsg, err_name, err_format, ...) \
cdbus_reply_errm((ps), dbus_message_new_error_printf((srcmsg), (err_name), (err_format), ## __VA_ARGS__))
/**
* Send a reply with no argument.
*/
static inline bool
cdbus_reply_noarg(session_t *ps, DBusMessage *srcmsg) {
return cdbus_reply(ps, srcmsg, NULL, NULL);
}
/**
* Send a reply with a bool argument.
*/
static inline bool
cdbus_reply_bool(session_t *ps, DBusMessage *srcmsg, bool bval) {
return cdbus_reply(ps, srcmsg, cdbus_apdarg_bool, &bval);
}
/**
* Send a reply with an int32 argument.
*/
static inline bool
cdbus_reply_int32(session_t *ps, DBusMessage *srcmsg, int32_t val) {
return cdbus_reply(ps, srcmsg, cdbus_apdarg_int32, &val);
}
/**
* Send a reply with an uint32 argument.
*/
static inline bool
cdbus_reply_uint32(session_t *ps, DBusMessage *srcmsg, uint32_t val) {
return cdbus_reply(ps, srcmsg, cdbus_apdarg_uint32, &val);
}
/**
* Send a reply with a double argument.
*/
static inline bool
cdbus_reply_double(session_t *ps, DBusMessage *srcmsg, double val) {
return cdbus_reply(ps, srcmsg, cdbus_apdarg_double, &val);
}
/**
* Send a reply with a wid argument.
*/
static inline bool
cdbus_reply_wid(session_t *ps, DBusMessage *srcmsg, Window wid) {
return cdbus_reply(ps, srcmsg, cdbus_apdarg_wid, &wid);
}
/**
* Send a reply with a string argument.
*/
static inline bool
cdbus_reply_string(session_t *ps, DBusMessage *srcmsg, const char *str) {
return cdbus_reply(ps, srcmsg, cdbus_apdarg_string, str);
}
/**
* Send a reply with a enum argument.
*/
static inline bool
cdbus_reply_enum(session_t *ps, DBusMessage *srcmsg, cdbus_enum_t eval) {
return cdbus_reply(ps, srcmsg, cdbus_apdarg_enum, &eval);
}
///@}
static bool
cdbus_msg_get_arg(DBusMessage *msg, int count, const int type, void *pdest);
typedef struct session session_t;
typedef struct win win;
/**
* Return a string representation of a D-Bus message type.
*/
static inline const char *
cdbus_repr_msgtype(DBusMessage *msg) {
static inline const char *cdbus_repr_msgtype(DBusMessage *msg) {
return dbus_message_type_to_string(dbus_message_get_type(msg));
}
///@}
/**
* Initialize D-Bus connection.
*/
bool cdbus_init(session_t *ps, const char *uniq_name);
/**
* Destroy D-Bus connection.
*/
void cdbus_destroy(session_t *ps);
/// Generate dbus win_added signal
void cdbus_ev_win_added(session_t *ps, win *w);
/// Generate dbus win_destroyed signal
void cdbus_ev_win_destroyed(session_t *ps, win *w);
/// Generate dbus win_mapped signal
void cdbus_ev_win_mapped(session_t *ps, win *w);
/// Generate dbus win_unmapped signal
void cdbus_ev_win_unmapped(session_t *ps, win *w);
/// Generate dbus win_focusout signal
void cdbus_ev_win_focusout(session_t *ps, win *w);
/// Generate dbus win_focusin signal
void cdbus_ev_win_focusin(session_t *ps, win *w);
// vim: set noet sw=8 ts=8 :

View File

@ -5,7 +5,8 @@ deps = [
]
srcs = [ files('compton.c', 'win.c', 'c2.c', 'x.c', 'config.c', 'vsync.c', 'utils.c',
'diagnostic.c', 'string_utils.c', 'render.c', 'kernel.c', 'log.c')]
'diagnostic.c', 'string_utils.c', 'render.c', 'kernel.c', 'log.c',
'argparse.c')]
cflags = []

View File

@ -17,6 +17,10 @@
#include "utils.h"
#include "log.h"
#ifdef CONFIG_DBUS
#include "dbus.h"
#endif
#include "win.h"
/// Generate a "return by value" function, from a function that returns the