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*:: *-h*, *--help*::
Get the usage text embedded in program code, which may be more up-to-date than this man page. 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':: *-r*, *--shadow-radius*='RADIUS'::
The blur radius for shadows, in pixels. (defaults to 12) The blur radius for shadows, in pixels. (defaults to 12)
@ -73,9 +70,6 @@ OPTIONS
*-b*, *--daemon*:: *-b*, *--daemon*::
Daemonize process. Fork to background after initialization. Causes issues with certain (badly-written) drivers. Daemonize process. Fork to background after initialization. Causes issues with certain (badly-written) drivers.
*-S*::
Enable synchronous X operation (for debugging).
*--log-level*:: *--log-level*::
Set the log level. Possible values are "TRACE", "DEBUG", "INFO", "WARN", "ERROR", in increasing level of importance. Case doesn't matter. 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 <ev.h>
#include <pixman.h> #include <pixman.h>
// libdbus
#ifdef CONFIG_DBUS
#include <dbus/dbus.h>
#endif
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
// libGL // libGL
#define GL_GLEXT_PROTOTYPES #define GL_GLEXT_PROTOTYPES
@ -404,11 +399,6 @@ typedef struct options_t {
char *config_file; char *config_file;
/// Path to write PID to. /// Path to write PID to.
char *write_pid_path; 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. /// The backend in use.
enum backend backend; enum backend backend;
/// Whether to sync X drawing to avoid certain delay issues with /// Whether to sync X drawing to avoid certain delay issues with
@ -463,10 +453,6 @@ typedef struct options_t {
Window benchmark_wid; Window benchmark_wid;
/// A list of conditions of windows not to paint. /// A list of conditions of windows not to paint.
c2_lptr_t *paint_blacklist; 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. /// Whether to show all X errors.
bool show_all_xerrors; bool show_all_xerrors;
/// Whether to avoid acquiring X Selection. /// Whether to avoid acquiring X Selection.
@ -888,10 +874,7 @@ typedef struct session {
#ifdef CONFIG_DBUS #ifdef CONFIG_DBUS
// === DBus related === // === DBus related ===
// DBus connection. void *dbus_data;
DBusConnection *dbus_conn;
// DBus service name.
char *dbus_service;
#endif #endif
} session_t; } session_t;
@ -1507,37 +1490,6 @@ xr_sync(session_t *ps, Drawable d, XSyncFence *pfence) {
*/ */
///@{ ///@{
#ifdef CONFIG_DBUS #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 /** @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 "compiler.h"
#include "win.h" #include "win.h"
#include "string_utils.h" #include "string_utils.h"
@ -16,6 +21,45 @@
#include "dbus.h" #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 static DBusHandlerResult
cdbus_process(DBusConnection *conn, DBusMessage *m, void *); cdbus_process(DBusConnection *conn, DBusMessage *m, void *);
@ -41,7 +85,13 @@ cdbus_callback_watch_toggled(DBusWatch *watch, void *data);
* Initialize D-Bus connection. * Initialize D-Bus connection.
*/ */
bool 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 = { }; DBusError err = { };
// Initialize // Initialize
@ -49,69 +99,87 @@ cdbus_init(session_t *ps) {
// Connect to D-Bus // Connect to D-Bus
// Use dbus_bus_get_private() so we can fully recycle it ourselves // 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)) { if (dbus_error_is_set(&err)) {
log_error("D-Bus connection failed (%s).", err.message); log_error("D-Bus connection failed (%s).", err.message);
dbus_error_free(&err); 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."); log_error("D-Bus connection failed for unknown reason.");
return false; goto fail;
} }
// Avoid exiting on disconnect // 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 // Request service name
{ {
// Build service name // Build service name
char *service = mstrjoin3(CDBUS_SERVICE_NAME, ".", ps->o.display_repr); size_t service_len = strlen(CDBUS_SERVICE_NAME)+strlen(uniq)+2;
ps->dbus_service = service; 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 // 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); DBUS_NAME_FLAG_DO_NOT_QUEUE, &err);
if (dbus_error_is_set(&err)) { if (dbus_error_is_set(&err)) {
log_error("Failed to obtain D-Bus name (%s).", err.message); log_error("Failed to obtain D-Bus name (%s).", err.message);
dbus_error_free(&err); dbus_error_free(&err);
goto fail;
} }
if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret
&& DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER != ret) { && DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER != ret) {
log_error("Failed to become the primary owner of requested D-Bus name (%d).", ret); log_error("Failed to become the primary owner of requested D-Bus name (%d).", ret);
goto fail;
} }
} }
// Add watch handlers // 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_add_watch, cdbus_callback_remove_watch,
cdbus_callback_watch_toggled, ps, NULL)) { cdbus_callback_watch_toggled, ps, NULL)) {
log_error("Failed to add D-Bus watch functions."); log_error("Failed to add D-Bus watch functions.");
return false; goto fail;
} }
// Add timeout handlers // 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_add_timeout, cdbus_callback_remove_timeout,
cdbus_callback_timeout_toggled, ps, NULL)) { cdbus_callback_timeout_toggled, ps, NULL)) {
log_error("Failed to add D-Bus timeout functions."); log_error("Failed to add D-Bus timeout functions.");
return false; goto fail;
} }
// Add match // Add match
dbus_bus_add_match(ps->dbus_conn, dbus_bus_add_match(cd->dbus_conn,
"type='method_call',interface='" CDBUS_INTERFACE_NAME "'", &err); "type='method_call',interface='" CDBUS_INTERFACE_NAME "'", &err);
if (dbus_error_is_set(&err)) { if (dbus_error_is_set(&err)) {
log_error("Failed to add D-Bus match."); log_error("Failed to add D-Bus match.");
dbus_error_free(&err); 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; 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 void
cdbus_destroy(session_t *ps) { cdbus_destroy(session_t *ps) {
if (ps->dbus_conn) { struct cdbus_data *cd = ps->dbus_data;
if (cd->dbus_conn) {
// Release DBus name firstly // Release DBus name firstly
if (ps->dbus_service) { if (cd->dbus_service) {
DBusError err = { }; DBusError err = { };
dbus_error_init(&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)) { if (dbus_error_is_set(&err)) {
log_error("Failed to release DBus name (%s).", err.message); log_error("Failed to release DBus name (%s).", err.message);
dbus_error_free(&err); dbus_error_free(&err);
@ -133,9 +202,10 @@ cdbus_destroy(session_t *ps) {
} }
// Close and unref the connection // Close and unref the connection
dbus_connection_close(ps->dbus_conn); dbus_connection_close(cd->dbus_conn);
dbus_connection_unref(ps->dbus_conn); dbus_connection_unref(cd->dbus_conn);
} }
free(cd);
} }
/** @name DBusTimeout handling /** @name DBusTimeout handling
@ -213,7 +283,7 @@ cdbus_callback_timeout_toggled(DBusTimeout *timeout, void *data) {
typedef struct ev_dbus_io { typedef struct ev_dbus_io {
ev_io w; ev_io w;
session_t *ps; struct cdbus_data *cd;
DBusWatch *dw; DBusWatch *dw;
} ev_dbus_io; } ev_dbus_io;
@ -225,7 +295,7 @@ void cdbus_io_callback(EV_P_ ev_io *w, int revents) {
if (revents & EV_WRITE) if (revents & EV_WRITE)
flags |= DBUS_WATCH_WRITABLE; flags |= DBUS_WATCH_WRITABLE;
dbus_watch_handle(dw->dw, flags); 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); auto w = ccalloc(1, ev_dbus_io);
w->dw = watch; 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), ev_io_init(&w->w, cdbus_io_callback, dbus_watch_get_unix_fd(watch),
cdbus_get_watch_cond(watch)); cdbus_get_watch_cond(watch));
@ -460,6 +530,7 @@ static bool
cdbus_signal(session_t *ps, const char *name, cdbus_signal(session_t *ps, const char *name,
bool (*func)(session_t *ps, DBusMessage *msg, const void *data), bool (*func)(session_t *ps, DBusMessage *msg, const void *data),
const void *data) { const void *data) {
struct cdbus_data *cd = ps->dbus_data;
DBusMessage* msg = NULL; DBusMessage* msg = NULL;
// Create a signal // Create a signal
@ -477,12 +548,12 @@ cdbus_signal(session_t *ps, const char *name,
} }
// Send the message and flush the connection // 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."); log_error("Failed to send D-Bus signal.");
dbus_message_unref(msg); dbus_message_unref(msg);
return false; return false;
} }
dbus_connection_flush(ps->dbus_conn); dbus_connection_flush(cd->dbus_conn);
// Free the message // Free the message
dbus_message_unref(msg); dbus_message_unref(msg);
@ -490,6 +561,14 @@ cdbus_signal(session_t *ps, const char *name,
return true; 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. * Send a D-Bus reply.
* *
@ -503,6 +582,7 @@ static bool
cdbus_reply(session_t *ps, DBusMessage *srcmsg, cdbus_reply(session_t *ps, DBusMessage *srcmsg,
bool (*func)(session_t *ps, DBusMessage *msg, const void *data), bool (*func)(session_t *ps, DBusMessage *msg, const void *data),
const void *data) { const void *data) {
struct cdbus_data *cd = ps->dbus_data;
DBusMessage* msg = NULL; DBusMessage* msg = NULL;
// Create a reply // Create a reply
@ -519,12 +599,12 @@ cdbus_reply(session_t *ps, DBusMessage *srcmsg,
} }
// Send the message and flush the connection // 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."); log_error("Failed to send D-Bus reply.");
dbus_message_unref(msg); dbus_message_unref(msg);
return false; return false;
} }
dbus_connection_flush(ps->dbus_conn); dbus_connection_flush(cd->dbus_conn);
// Free the message // Free the message
dbus_message_unref(msg); dbus_message_unref(msg);
@ -532,6 +612,62 @@ cdbus_reply(session_t *ps, DBusMessage *srcmsg,
return true; 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. * Send a D-Bus error reply.
* *
@ -540,18 +676,19 @@ cdbus_reply(session_t *ps, DBusMessage *srcmsg,
*/ */
static bool static bool
cdbus_reply_errm(session_t *ps, DBusMessage *msg) { cdbus_reply_errm(session_t *ps, DBusMessage *msg) {
struct cdbus_data *cd = ps->dbus_data;
if (!msg) { if (!msg) {
log_error("Failed to create D-Bus reply."); log_error("Failed to create D-Bus reply.");
return false; return false;
} }
// Send the message and flush the connection // 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."); log_error("Failed to send D-Bus reply.");
dbus_message_unref(msg); dbus_message_unref(msg);
return false; return false;
} }
dbus_connection_flush(ps->dbus_conn); dbus_connection_flush(cd->dbus_conn);
// Free the message // Free the message
dbus_message_unref(msg); 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(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(write_pid_path, cdbus_reply_string);
cdbus_m_opts_get_do(mark_wmwin_focused, cdbus_reply_bool); cdbus_m_opts_get_do(mark_wmwin_focused, cdbus_reply_bool);
cdbus_m_opts_get_do(mark_ovredir_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(redirected_force, cdbus_reply_enum);
cdbus_m_opts_get_do(stoppaint_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(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(refresh_rate, cdbus_reply_int32);
cdbus_m_opts_get_do(sw_opti, cdbus_reply_bool); cdbus_m_opts_get_do(sw_opti, cdbus_reply_bool);
@ -1235,37 +1371,43 @@ cdbus_process(DBusConnection *c, DBusMessage *msg, void *ud) {
///@{ ///@{
void void
cdbus_ev_win_added(session_t *ps, win *w) { 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); cdbus_signal_wid(ps, "win_added", w->id);
} }
void void
cdbus_ev_win_destroyed(session_t *ps, win *w) { 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); cdbus_signal_wid(ps, "win_destroyed", w->id);
} }
void void
cdbus_ev_win_mapped(session_t *ps, win *w) { 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); cdbus_signal_wid(ps, "win_mapped", w->id);
} }
void void
cdbus_ev_win_unmapped(session_t *ps, win *w) { 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); cdbus_signal_wid(ps, "win_unmapped", w->id);
} }
void void
cdbus_ev_win_focusout(session_t *ps, win *w) { 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); cdbus_signal_wid(ps, "win_focusout", w->id);
} }
void void
cdbus_ev_win_focusin(session_t *ps, win *w) { 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); cdbus_signal_wid(ps, "win_focusin", w->id);
} }
//!@} //!@}

View File

@ -9,182 +9,46 @@
* *
*/ */
#include "common.h" #include <stdbool.h>
#include <ctype.h> #include <dbus/dbus.h>
#include <sys/types.h>
#include <unistd.h>
#define CDBUS_SERVICE_NAME "com.github.chjj.compton" typedef struct session session_t;
#define CDBUS_INTERFACE_NAME CDBUS_SERVICE_NAME typedef struct win win;
#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);
/** /**
* Return a string representation of a D-Bus message type. * Return a string representation of a D-Bus message type.
*/ */
static inline const char * static inline const char *cdbus_repr_msgtype(DBusMessage *msg) {
cdbus_repr_msgtype(DBusMessage *msg) { return dbus_message_type_to_string(dbus_message_get_type(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', 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 = [] cflags = []

View File

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