From 00424b10822378642b238e647d9ae711a1c27f92 Mon Sep 17 00:00:00 2001 From: Richard Grenville Date: Thu, 24 Jan 2013 13:38:03 +0800 Subject: [PATCH] Bug fix #84: Root window not repainted sometimes on wallpaper change - Fix a bug that root window is not repainted on wallpaper change unless an Expose X event is received. Seemingly, if there's no mapped window on a screen, X will not send an Expose event when the wallpaper changes. Thanks to baskerville for reporting. - Fix a X Pixmap leak when there's no existing wallpaper pixmap found. - Fix a bug in mstrncpy() that null character is not added to the end of the copied string. - Make VSYNC_STRS public, for use in src/dbus.c. Adjust the type of WINTYPES array. Add NUM_VSYNC. - Add more targets for various D-Bus methods. Add "bad_target" D-Bus error. Improve error handling. Add more helper functions to append arguments to a D-Bus message. Add Introspect method to D-Bus introspection reply. - Add public declarations of things in the new condition format code to common.h. Move definitions of some inline functions from compton.h to common.h. Make some functions public. Move wid_get_prop_adv() to compton.c. The primary code files of the new format src/c2.{c,h} will be published when ready. - Add support for dumping version string in Makefile (make version), to make snapshot generation easier. - Add repeated inclusion protection to common.h. - Update documentation. - Use gsed instead of sed in dbus-examples/cdbus-driver.sh if possible, as some BSD systems does not come with GNU sed by default. Thanks to DaChiChang for reporting. - Code clean-up. Small type changes in register_cm() to silence warnings. Quit on failure in parse_vsync(). Apply stricter checks in force_repaint(). --- Makefile | 11 ++- dbus-examples/cdbus-driver.sh | 7 +- man/compton.1.asciidoc | 17 +++- src/common.h | 144 +++++++++++++++++++++++++++++++--- src/compton.c | 123 +++++++++++++++++++++-------- src/compton.h | 128 ------------------------------ src/dbus.c | 140 +++++++++++++++++++++++++++++---- src/dbus.h | 35 +++++++++ 8 files changed, 415 insertions(+), 190 deletions(-) diff --git a/Makefile b/Makefile index 1d4c8e7..8143a6a 100644 --- a/Makefile +++ b/Makefile @@ -54,6 +54,12 @@ ifeq "$(NO_DBUS)" "" OBJS += dbus.o endif +# ==== C2 ==== +# ifeq "$(NO_C2)" "" +# CFG += -DCONFIG_C2 +# OBJS += c2.o +# endif + # === Version string === COMPTON_VERSION ?= git-$(shell git describe --always --dirty)-$(shell git log -1 --date=short --pretty=format:%cd) CFG += -DCOMPTON_VERSION="\"$(COMPTON_VERSION)\"" @@ -101,4 +107,7 @@ uninstall: clean: @rm -f $(OBJS) compton $(MANPAGES) $(MANPAGES_HTML) -.PHONY: uninstall clean docs +version: + @echo "$(COMPTON_VERSION)" + +.PHONY: uninstall clean docs version diff --git a/dbus-examples/cdbus-driver.sh b/dbus-examples/cdbus-driver.sh index 61b6135..9582fc7 100755 --- a/dbus-examples/cdbus-driver.sh +++ b/dbus-examples/cdbus-driver.sh @@ -1,5 +1,10 @@ #!/bin/sh +if [ -z "$SED" ]; then + SED="sed" + command -v gsed > /dev/null && SED="gsed" +fi + # === Get connection parameters === dpy=$(echo -n "$DISPLAY" | tr -c '[:alnum:]' _) @@ -21,7 +26,7 @@ type_enum='uint16' dbus-send --print-reply --dest="$service" "$object" "${interface}.list_win" # Get window ID of currently focused window -focused=$(dbus-send --print-reply --dest="$service" "$object" "${interface}.find_win" string:focused | sed -n 's/^[[:space:]]*'${type_win}'\s*\([[:digit:]]*\).*/\1/p') +focused=$(dbus-send --print-reply --dest="$service" "$object" "${interface}.find_win" string:focused | $SED -n 's/^[[:space:]]*'${type_win}'\s*\([[:digit:]]*\).*/\1/p') if [ -n "$focused" ]; then # Get invert_color_force property of the window diff --git a/man/compton.1.asciidoc b/man/compton.1.asciidoc index b06632f..10d3901 100644 --- a/man/compton.1.asciidoc +++ b/man/compton.1.asciidoc @@ -15,7 +15,7 @@ SYNOPSIS WARNING ------- -This man page may be less up-to-date than the usage text in compton. +This man page may be less up-to-date than the usage text in compton (`compton -h`). DESCRIPTION ----------- @@ -23,6 +23,9 @@ compton is a compositor based on Dana Jansens' version of xcompmgr (which itself 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. @@ -169,6 +172,12 @@ OPTIONS *--blur-background-fixed*:: Use fixed blur strength rather than adjusting according to window opacity. +*--invert-color-include* condition:: + Specify a list of conditions of windows that should be painted with inverted color. Resource-hogging, and is not well tested. + +*--dbus*:: + Enable remote control via D-Bus. See the *D-BUS API* section below for more details. + FORMAT OF CONDITIONS -------------------- @@ -193,6 +202,12 @@ SIGNALS * compton reinitializes itself upon receiving `SIGUSR1`. +D-BUS API +--------- + +It's possible to control compton via D-Bus messages, by running compton with *--dbus* and send messages to `com.github.chjj.compton.`. `` is the display used by compton, with all non-alphanumeric characters transformed to underscores. For `DISPLAY=:0.0` you should use `com.github.chjj.compton._0_0`, for example. + +The D-Bus methods and signals are not yet stable, thus undocumented right now. EXAMPLES -------- diff --git a/src/common.h b/src/common.h index 31c9c20..004d955 100644 --- a/src/common.h +++ b/src/common.h @@ -8,6 +8,9 @@ * */ +#ifndef COMPTON_COMMON_H +#define COMPTON_COMMON_H + // === Options === // Debug options, enable them using -D in CFLAGS @@ -22,6 +25,7 @@ // #define DEBUG_ALLOC_REG 1 // #define DEBUG_FRAME 1 // #define DEBUG_LEADER 1 +// #define DEBUG_C2 1 // #define MONITOR_REPAINT 1 // Whether to enable PCRE regular expression support in blacklists, enabled @@ -40,6 +44,12 @@ // #define CONFIG_VSYNC_OPENGL 1 // Whether to enable DBus support with libdbus. // #define CONFIG_DBUS 1 +// Whether to enable condition support. +// #define CONFIG_C2 1 + +#if !defined(CONFIG_C2) && defined(DEBUG_C2) +#error Cannot enable c2 debugging without c2 support. +#endif // === Includes === @@ -264,6 +274,7 @@ typedef enum { VSYNC_NONE, VSYNC_DRM, VSYNC_OPENGL, + NUM_VSYNC, } vsync_t; #ifdef CONFIG_VSYNC_OPENGL @@ -286,9 +297,15 @@ struct _timeout_t; struct _win; +#ifdef CONFIG_C2 +typedef struct _c2_lptr c2_lptr_t; +#endif + /// Structure representing all options. typedef struct { // === General === + /// The display name we used. NULL means we are using the value of the + /// DISPLAY environment variable. char *display; /// Whether to try to detect WM windows and mark them as focused. bool mark_wmwin_focused; @@ -534,13 +551,13 @@ typedef struct { /// Nanosecond offset of the first painting. long paint_tm_offset; - #ifdef CONFIG_VSYNC_DRM +#ifdef CONFIG_VSYNC_DRM // === DRM VSync related === /// File descriptor of DRI device file. Used for DRM VSync. int drm_fd; - #endif +#endif - #ifdef CONFIG_VSYNC_OPENGL +#ifdef CONFIG_VSYNC_OPENGL // === OpenGL VSync related === /// GLX context. GLXContext glx_context; @@ -548,7 +565,7 @@ typedef struct { f_GetVideoSync glx_get_video_sync; /// Pointer to glXWaitVideoSyncSGI function. f_WaitVideoSync glx_wait_video_sync; - #endif +#endif // === X extension related === /// Event base number for X Fixes extension. @@ -584,14 +601,14 @@ typedef struct { int randr_event; /// Error base number for X RandR extension. int randr_error; - #ifdef CONFIG_VSYNC_OPENGL +#ifdef CONFIG_VSYNC_OPENGL /// Whether X GLX extension exists. bool glx_exists; /// Event base number for X GLX extension. int glx_event; /// Error base number for X GLX extension. int glx_error; - #endif +#endif /// Whether X DBE extension exists. bool dbe_exists; /// Whether X Render convolution filter exists. @@ -816,7 +833,8 @@ typedef enum { WIN_EVMODE_CLIENT } win_evmode_t; -extern const char *WINTYPES[NUM_WINTYPES]; +extern const char * const WINTYPES[NUM_WINTYPES]; +extern const char * const VSYNC_STRS[NUM_VSYNC]; extern session_t *ps_g; // == Debugging code == @@ -1055,6 +1073,7 @@ mstrncpy(const char *src, unsigned len) { char *str = malloc(sizeof(char) * (len + 1)); strncpy(str, src, len); + str[len] = '\0'; return str; } @@ -1259,6 +1278,14 @@ fds_poll(session_t *ps, struct timeval *ptv) { } #undef CPY_FDS +/** + * Wrapper of XInternAtom() for convenience. + */ +static inline Atom +get_atom(session_t *ps, const char *atom_name) { + return XInternAtom(ps->dpy, atom_name, False); +} + /** * Find a window from window id in window linked list of the session. */ @@ -1326,6 +1353,86 @@ copy_region(const session_t *ps, XserverRegion oldregion) { return region; } +/** + * Determine if a window has a specific property. + * + * @param ps current session + * @param w window to check + * @param atom atom of property to check + * @return 1 if it has the attribute, 0 otherwise + */ +static inline bool +wid_has_prop(const session_t *ps, Window w, Atom atom) { + Atom type = None; + int format; + unsigned long nitems, after; + unsigned char *data; + + if (Success == XGetWindowProperty(ps->dpy, w, atom, 0, 0, False, + AnyPropertyType, &type, &format, &nitems, &after, &data)) { + XFree(data); + if (type) return true; + } + + return false; +} + +winprop_t +wid_get_prop_adv(const session_t *ps, Window w, Atom atom, long offset, + long length, Atom rtype, int rformat); + +/** + * Wrapper of wid_get_prop_adv(). + */ +static inline winprop_t +wid_get_prop(const session_t *ps, Window wid, Atom atom, long length, + Atom rtype, int rformat) { + return wid_get_prop_adv(ps, wid, atom, 0L, length, rtype, rformat); +} + +/** + * Get the numeric property value from a win_prop_t. + */ +static inline long +winprop_get_int(winprop_t prop) { + long tgt = 0; + + if (!prop.nitems) + return 0; + + switch (prop.format) { + case 8: tgt = *(prop.data.p8); break; + case 16: tgt = *(prop.data.p16); break; + case 32: tgt = *(prop.data.p32); break; + default: assert(0); + break; + } + + return tgt; +} + +bool +wid_get_text_prop(session_t *ps, Window wid, Atom prop, + char ***pstrlst, int *pnstr); + +/** + * Free a winprop_t. + * + * @param pprop pointer to the winprop_t to free. + */ +static inline void +free_winprop(winprop_t *pprop) { + // Empty the whole structure to avoid possible issues + if (pprop->data.p8) { + XFree(pprop->data.p8); + pprop->data.p8 = NULL; + } + pprop->nitems = 0; +} + +void +force_repaint(session_t *ps); + #ifdef CONFIG_DBUS /** @name DBus handling */ @@ -1363,8 +1470,25 @@ win_set_focused_force(session_t *ps, win *w, switch_t val); void win_set_invert_color_force(session_t *ps, win *w, switch_t val); - -void -force_repaint(session_t *ps); //!@} #endif + +#ifdef CONFIG_C2 +/** @name c2 + */ +///@{ + +c2_lptr_t * +c2_parse(session_t *ps, c2_lptr_t **pcondlst, char *pattern); + +c2_lptr_t * +c2_free_lptr(c2_lptr_t *lp); + +bool +c2_match(session_t *ps, win *w, const c2_lptr_t *condlst, + const c2_lptr_t **cache); +#endif + +///@} + +#endif diff --git a/src/compton.c b/src/compton.c index 90133d1..814bf4a 100644 --- a/src/compton.c +++ b/src/compton.c @@ -13,7 +13,7 @@ // === Global constants === /// Name strings for window types. -const char *WINTYPES[NUM_WINTYPES] = { +const char * const WINTYPES[NUM_WINTYPES] = { "unknown", "desktop", "dock", @@ -31,9 +31,16 @@ const char *WINTYPES[NUM_WINTYPES] = { "dnd", }; +/// Names of VSync modes +const char * const VSYNC_STRS[NUM_VSYNC] = { + "none", // VSYNC_NONE + "drm", // VSYNC_DRM + "opengl", // VSYNC_OPENGL +}; + /// Names of root window properties that could point to a pixmap of /// background. -const char *background_props_str[] = { +const static char *background_props_str[] = { "_XROOTPMAP_ID", "_XSETROOT_ID", 0, @@ -534,6 +541,52 @@ should_ignore(session_t *ps, unsigned long sequence) { // === Windows === +/** + * Get a specific attribute of a window. + * + * Returns a blank structure if the returned type and format does not + * match the requested type and format. + * + * @param ps current session + * @param w window + * @param atom atom of attribute to fetch + * @param length length to read + * @param rtype atom of the requested type + * @param rformat requested format + * @return a winprop_t structure containing the attribute + * and number of items. A blank one on failure. + */ +winprop_t +wid_get_prop_adv(const session_t *ps, Window w, Atom atom, long offset, + long length, Atom rtype, int rformat) { + Atom type = None; + int format = 0; + unsigned long nitems = 0, after = 0; + unsigned char *data = NULL; + + if (Success == XGetWindowProperty(ps->dpy, w, atom, offset, length, + False, rtype, &type, &format, &nitems, &after, &data) + && nitems && (AnyPropertyType == type || type == rtype) + && (!format || format == rformat) + && (8 == format || 16 == format || 32 == format)) { + return (winprop_t) { + .data.p8 = data, + .nitems = nitems, + .type = type, + .format = format, + }; + } + + XFree(data); + + return (winprop_t) { + .data.p8 = NULL, + .nitems = 0, + .type = AnyPropertyType, + .format = 0 + }; +} + /** * Check if a window has rounded corners. */ @@ -966,6 +1019,8 @@ root_tile_f(session_t *ps) { c.alpha = 0xffff; XRenderFillRectangle( ps->dpy, PictOpSrc, picture, &c, 0, 0, 1, 1); + + free_pixmap(ps, &pixmap); } return picture; @@ -2120,10 +2175,8 @@ win_determine_mode(session_t *ps, win *w) { * > window type default opacity (if not opaque) * > inactive_opacity * - * @param dpy X display to use + * @param ps current session * @param w struct _win object representing the window - * @param refetch_prop whether _NET_WM_OPACITY of the window needs to be - * refetched */ static void calc_opacity(session_t *ps, win *w) { @@ -2858,9 +2911,9 @@ root_damaged(session_t *ps) { add_damage(ps, parts); } */ } - // Mark screen damaged if we are painting on overlay - if (ps->o.paint_on_overlay) - add_damage(ps, get_screen_region(ps)); + + // Mark screen damaged + force_repaint(ps); } static void @@ -3133,7 +3186,7 @@ win_get_leader_raw(session_t *ps, win *w, int recursions) { /** * Get the value of a text property of a window. */ -static bool +bool wid_get_text_prop(session_t *ps, Window wid, Atom prop, char ***pstrlst, int *pnstr) { XTextProperty text_prop = { NULL, None, 0, 0 }; @@ -3282,6 +3335,19 @@ win_get_class(session_t *ps, win *w) { return true; } +/** + * Force a full-screen repaint. + */ +void +force_repaint(session_t *ps) { + assert(ps->screen_reg); + XserverRegion reg = None; + if (ps->screen_reg && (reg = copy_region(ps, ps->screen_reg))) { + ps->ev_received = true; + add_damage(ps, reg); + } +} + #ifdef CONFIG_DBUS /** @name DBus hooks */ @@ -3319,18 +3385,6 @@ win_set_invert_color_force(session_t *ps, win *w, switch_t val) { win_determine_invert_color(ps, w); } } - -/** - * Force a full-screen repaint. - */ -void -force_repaint(session_t *ps) { - XserverRegion reg = None; - if (ps->screen_reg && (reg = copy_region(ps, ps->screen_reg))) { - ps->ev_received = true; - add_damage(ps, reg); - } -} //!@} #endif @@ -4039,6 +4093,9 @@ usage(void) { "--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" + "--dbus\n" + " Enable remote control via D-Bus. See the D-BUS API section in the\n" + " man page for more details.\n" "\n" "Format of a condition:\n" "\n" @@ -4068,7 +4125,6 @@ static void register_cm(session_t *ps, bool want_glxct) { Atom a; char *buf; - int len, s; #ifdef CONFIG_VSYNC_OPENGL // Create a window with the wanted GLX visual @@ -4128,8 +4184,8 @@ register_cm(session_t *ps, bool want_glxct) { Xutf8SetWMProperties(ps->dpy, ps->reg_win, "xcompmgr", "xcompmgr", NULL, 0, NULL, NULL, NULL); - len = strlen(REGISTER_PROP) + 2; - s = ps->scr; + unsigned len = strlen(REGISTER_PROP) + 2; + int s = ps->scr; while (s >= 10) { ++len; @@ -4284,21 +4340,15 @@ open_config_file(char *cpath, char **ppath) { */ static inline void parse_vsync(session_t *ps, const char *optarg) { - const static char * const vsync_str[] = { - "none", // VSYNC_NONE - "drm", // VSYNC_DRM - "opengl", // VSYNC_OPENGL - }; - vsync_t i; - for (i = 0; i < (sizeof(vsync_str) / sizeof(vsync_str[0])); ++i) - if (!strcasecmp(optarg, vsync_str[i])) { + for (i = 0; i < (sizeof(VSYNC_STRS) / sizeof(VSYNC_STRS[0])); ++i) + if (!strcasecmp(optarg, VSYNC_STRS[i])) { ps->o.vsync = i; break; } - if ((sizeof(vsync_str) / sizeof(vsync_str[0])) == i) { - fputs("Invalid --vsync argument. Ignored.\n", stderr); + if ((sizeof(VSYNC_STRS) / sizeof(VSYNC_STRS[0])) == i) { + printf_errfq(1, "(\"%s\"): Invalid --vsync argument.", optarg); } } @@ -6114,6 +6164,11 @@ main(int argc, char **argv) { printf_errf("Failed to create new session."); return 1; } +#ifdef DEBUG_C2 + // c2_parse(ps_g, NULL, "name ~= \"master\""); + // c2_parse(ps_g, NULL, "n:e:Notification"); + c2_parse(ps_g, NULL, "(WM_NAME:16s = 'Notification' || class_g = 'fox') && class_g = 'fox'"); +#endif session_run(ps_g); ps_old = ps_g; session_destroy(ps_g); diff --git a/src/compton.h b/src/compton.h index c309910..7670424 100644 --- a/src/compton.h +++ b/src/compton.h @@ -52,14 +52,6 @@ set_ignore_next(session_t *ps) { static int should_ignore(session_t *ps, unsigned long sequence); -/** - * Wrapper of XInternAtom() for convenience. - */ -static inline Atom -get_atom(session_t *ps, const char *atom_name) { - return XInternAtom(ps->dpy, atom_name, False); -} - /** * Return the painting target window. */ @@ -291,122 +283,6 @@ static Picture solid_picture(session_t *ps, bool argb, double a, double r, double g, double b); -/** - * Determine if a window has a specific property. - * - * @param session_t current session - * @param w window to check - * @param atom atom of property to check - * @return 1 if it has the attribute, 0 otherwise - */ -static inline bool -wid_has_prop(const session_t *ps, Window w, Atom atom) { - Atom type = None; - int format; - unsigned long nitems, after; - unsigned char *data; - - if (Success == XGetWindowProperty(ps->dpy, w, atom, 0, 0, False, - AnyPropertyType, &type, &format, &nitems, &after, &data)) { - XFree(data); - if (type) return true; - } - - return false; -} - -/** - * Get a specific attribute of a window. - * - * Returns a blank structure if the returned type and format does not - * match the requested type and format. - * - * @param session_t current session - * @param w window - * @param atom atom of attribute to fetch - * @param length length to read - * @param rtype atom of the requested type - * @param rformat requested format - * @return a winprop_t structure containing the attribute - * and number of items. A blank one on failure. - */ -// TODO: Move to compton.c -static winprop_t -wid_get_prop_adv(const session_t *ps, Window w, Atom atom, long offset, - long length, Atom rtype, int rformat) { - Atom type = None; - int format = 0; - unsigned long nitems = 0, after = 0; - unsigned char *data = NULL; - - if (Success == XGetWindowProperty(ps->dpy, w, atom, offset, length, - False, rtype, &type, &format, &nitems, &after, &data) - && nitems && (AnyPropertyType == type || type == rtype) - && (!format || format == rformat) - && (8 == format || 16 == format || 32 == format)) { - return (winprop_t) { - .data.p8 = data, - .nitems = nitems, - .type = type, - .format = format, - }; - } - - XFree(data); - - return (winprop_t) { - .data.p8 = NULL, - .nitems = 0, - .type = AnyPropertyType, - .format = 0 - }; -} - -/** - * Wrapper of wid_get_prop_adv(). - */ -static inline winprop_t -wid_get_prop(const session_t *ps, Window wid, Atom atom, long length, - Atom rtype, int rformat) { - return wid_get_prop_adv(ps, wid, atom, 0L, length, rtype, rformat); -} - -/** - * Get the numeric property value from a win_prop_t. - */ -static inline long -winprop_get_int(winprop_t prop) { - long tgt = 0; - - if (!prop.nitems) - return 0; - - switch (prop.format) { - case 8: tgt = *(prop.data.p8); break; - case 16: tgt = *(prop.data.p16); break; - case 32: tgt = *(prop.data.p32); break; - default: assert(0); - break; - } - - return tgt; -} - -/** - * Free a winprop_t. - * - * @param pprop pointer to the winprop_t to free. - */ -static inline void -free_winprop(winprop_t *pprop) { - // Empty the whole structure to avoid possible issues - if (pprop->data.p8) { - XFree(pprop->data.p8); - pprop->data.p8 = NULL; - } - pprop->nitems = 0; -} - /** * Stop listening for events on a particular window. */ @@ -768,10 +644,6 @@ error(Display *dpy, XErrorEvent *ev); static void expose_root(session_t *ps, XRectangle *rects, int nrects); -static bool -wid_get_text_prop(session_t *ps, Window wid, Atom prop, - char ***pstrlst, int *pnstr); - static Window wid_get_prop_window(session_t *ps, Window wid, Atom aprop); diff --git a/src/dbus.c b/src/dbus.c index 16be7cc..a86ed17 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -266,6 +266,48 @@ cdbus_apdarg_bool(session_t *ps, DBusMessage *msg, const void *data) { return true; } +/** + * Callback to append an int32 argument to a message. + */ +static bool +cdbus_apdarg_int32(session_t *ps, DBusMessage *msg, const void *data) { + if (!dbus_message_append_args(msg, DBUS_TYPE_INT32, data, + DBUS_TYPE_INVALID)) { + printf_errf("(): Failed to append argument."); + return false; + } + + return true; +} + +/** + * Callback to append an uint32 argument to a message. + */ +static bool +cdbus_apdarg_uint32(session_t *ps, DBusMessage *msg, const void *data) { + if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, data, + DBUS_TYPE_INVALID)) { + printf_errf("(): Failed to append argument."); + return false; + } + + return true; +} + +/** + * Callback to append a double argument to a message. + */ +static bool +cdbus_apdarg_double(session_t *ps, DBusMessage *msg, const void *data) { + if (!dbus_message_append_args(msg, DBUS_TYPE_DOUBLE, data, + DBUS_TYPE_INVALID)) { + printf_errf("(): Failed to append argument."); + return false; + } + + return true; +} + /** * Callback to append a Window argument to a message. */ @@ -639,6 +681,21 @@ cdbus_process_win_get(session_t *ps, DBusMessage *msg) { return true; \ } + cdbus_m_win_get_do(id, cdbus_reply_wid); + + // next + if (!strcmp("next", target)) { + cdbus_reply_wid(ps, msg, (w->next ? w->next->id: 0)); + return true; + } + + // map_state + if (!strcmp("map_state", target)) { + cdbus_reply_bool(ps, msg, w->a.map_state); + return true; + } + + cdbus_m_win_get_do(mode, cdbus_reply_enum); cdbus_m_win_get_do(client_win, cdbus_reply_wid); cdbus_m_win_get_do(damaged, cdbus_reply_bool); cdbus_m_win_get_do(destroyed, cdbus_reply_bool); @@ -649,15 +706,22 @@ cdbus_process_win_get(session_t *ps, DBusMessage *msg) { cdbus_m_win_get_do(shadow_force, cdbus_reply_enum); cdbus_m_win_get_do(focused_force, cdbus_reply_enum); cdbus_m_win_get_do(invert_color_force, cdbus_reply_enum); - if (!strcmp("map_state", target)) { - cdbus_reply_bool(ps, msg, w->a.map_state); - return true; - } + cdbus_m_win_get_do(name, cdbus_reply_string); + cdbus_m_win_get_do(class_instance, cdbus_reply_string); + cdbus_m_win_get_do(class_general, cdbus_reply_string); + cdbus_m_win_get_do(role, cdbus_reply_string); + cdbus_m_win_get_do(opacity, cdbus_reply_uint32); + cdbus_m_win_get_do(frame_opacity, cdbus_reply_double); + cdbus_m_win_get_do(left_width, cdbus_reply_uint32); + cdbus_m_win_get_do(right_width, cdbus_reply_uint32); + cdbus_m_win_get_do(top_width, cdbus_reply_uint32); + cdbus_m_win_get_do(bottom_width, cdbus_reply_uint32); #undef cdbus_m_win_get_do - printf_errf("(): No matching target found."); + printf_errf("(): " CDBUS_ERROR_BADTGT_S, target); + cdbus_reply_err(ps, msg, CDBUS_ERROR_BADTGT, CDBUS_ERROR_BADTGT_S, target); - return false; + return true; } /** @@ -723,9 +787,10 @@ cdbus_process_win_set(session_t *ps, DBusMessage *msg) { } #undef cdbus_m_win_set_do - printf_errf("(): No matching target found."); + printf_errf("(): " CDBUS_ERROR_BADTGT_S, target); + cdbus_reply_err(ps, msg, CDBUS_ERROR_BADTGT, CDBUS_ERROR_BADTGT_S, target); - return false; + return true; cdbus_process_win_set_success: if (!dbus_message_get_no_reply(msg)) @@ -761,9 +826,10 @@ cdbus_process_find_win(session_t *ps, DBusMessage *msg) { wid = w->id; } else { - printf_errf("(): No matching target found."); + printf_errf("(): " CDBUS_ERROR_BADTGT_S, target); + cdbus_reply_err(ps, msg, CDBUS_ERROR_BADTGT, CDBUS_ERROR_BADTGT_S, target); - return false; + return true; } cdbus_reply_wid(ps, msg, wid); @@ -787,7 +853,12 @@ cdbus_process_opts_get(session_t *ps, DBusMessage *msg) { return true; \ } - cdbus_m_opts_get_do(display, cdbus_reply_string); + // display + if (!strcmp("display", target)) { + cdbus_reply_string(ps, msg, DisplayString(ps->dpy)); + return true; + } + 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(fork_after_register, cdbus_reply_bool); @@ -797,12 +868,45 @@ cdbus_process_opts_get(session_t *ps, DBusMessage *msg) { cdbus_m_opts_get_do(logpath, cdbus_reply_string); cdbus_m_opts_get_do(synchronize, cdbus_reply_bool); + cdbus_m_opts_get_do(refresh_rate, cdbus_reply_int32); + cdbus_m_opts_get_do(sw_opti, cdbus_reply_bool); + if (!strcmp("vsync", target)) { + assert(ps->o.vsync < sizeof(VSYNC_STRS) / sizeof(VSYNC_STRS[0])); + cdbus_reply_string(ps, msg, VSYNC_STRS[ps->o.vsync]); + return true; + } + cdbus_m_opts_get_do(dbe, cdbus_reply_bool); + cdbus_m_opts_get_do(vsync_aggressive, cdbus_reply_bool); + + cdbus_m_opts_get_do(shadow_red, cdbus_reply_double); + cdbus_m_opts_get_do(shadow_green, cdbus_reply_double); + cdbus_m_opts_get_do(shadow_blue, cdbus_reply_double); + cdbus_m_opts_get_do(shadow_radius, cdbus_reply_int32); + cdbus_m_opts_get_do(shadow_offset_x, cdbus_reply_int32); + cdbus_m_opts_get_do(shadow_offset_y, cdbus_reply_int32); + cdbus_m_opts_get_do(shadow_opacity, cdbus_reply_double); cdbus_m_opts_get_do(clear_shadow, cdbus_reply_bool); + + cdbus_m_opts_get_do(blur_background, cdbus_reply_bool); + cdbus_m_opts_get_do(blur_background_frame, cdbus_reply_bool); + cdbus_m_opts_get_do(blur_background_fixed, cdbus_reply_bool); + + cdbus_m_opts_get_do(inactive_dim, cdbus_reply_double); + cdbus_m_opts_get_do(inactive_dim_fixed, cdbus_reply_bool); + + cdbus_m_opts_get_do(use_ewmh_active_win, cdbus_reply_bool); + cdbus_m_opts_get_do(detect_transient, cdbus_reply_bool); + cdbus_m_opts_get_do(detect_client_leader, cdbus_reply_bool); + + cdbus_m_opts_get_do(track_focus, cdbus_reply_bool); + cdbus_m_opts_get_do(track_wdata, cdbus_reply_bool); + cdbus_m_opts_get_do(track_leader, cdbus_reply_bool); #undef cdbus_m_opts_get_do - printf_errf("(): No matching target found."); + printf_errf("(): " CDBUS_ERROR_BADTGT_S, target); + cdbus_reply_err(ps, msg, CDBUS_ERROR_BADTGT, CDBUS_ERROR_BADTGT_S, target); - return false; + return true; } /** @@ -849,9 +953,10 @@ cdbus_process_opts_set(session_t *ps, DBusMessage *msg) { } #undef cdbus_m_opts_set_do - printf_errf("(): No matching target found."); + printf_errf("(): " CDBUS_ERROR_BADTGT_S, target); + cdbus_reply_err(ps, msg, CDBUS_ERROR_BADTGT, CDBUS_ERROR_BADTGT_S, target); - return false; + return true; cdbus_process_opts_set_success: if (!dbus_message_get_no_reply(msg)) @@ -868,6 +973,11 @@ cdbus_process_introspect(session_t *ps, DBusMessage *msg) { "\n" "\n" + " \n" + " \n" + " \n" + " \n" + " \n" " \n" " \n" " \n" diff --git a/src/dbus.h b/src/dbus.h index fb51c8c..e69a6ae 100644 --- a/src/dbus.h +++ b/src/dbus.h @@ -24,6 +24,8 @@ #define CDBUS_ERROR_BADARG_S "Something wrong in arguments?" #define CDBUS_ERROR_BADWIN CDBUS_ERROR_PREFIX ".bad_window" #define CDBUS_ERROR_BADWIN_S "Requested window %#010lx 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." @@ -75,6 +77,15 @@ cdbus_callback_watch_toggled(DBusWatch *watch, void *data); 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); @@ -145,6 +156,30 @@ 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. */