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().
This commit is contained in:
parent
58c0ecec40
commit
00424b1082
11
Makefile
11
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.<DISPLAY>`. `<DISPLAY>` 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
|
||||
--------
|
||||
|
|
132
src/common.h
132
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
|
||||
/// <code>DISPLAY</code> environment variable.
|
||||
char *display;
|
||||
/// Whether to try to detect WM windows and mark them as focused.
|
||||
bool mark_wmwin_focused;
|
||||
|
@ -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 <code>winprop_t</code>.
|
||||
*
|
||||
* @param pprop pointer to the <code>winprop_t</code> 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
|
||||
|
|
123
src/compton.c
123
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 <code>winprop_t</code> 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);
|
||||
|
|
128
src/compton.h
128
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 <code>winprop_t</code> 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 <code>winprop_t</code>.
|
||||
*
|
||||
* @param pprop pointer to the <code>winprop_t</code> 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);
|
||||
|
||||
|
|
140
src/dbus.c
140
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) {
|
|||
"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
|
||||
" \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
|
||||
"<node name='" CDBUS_OBJECT_NAME "'>\n"
|
||||
" <interface name='org.freedesktop.DBus.Introspectable'>\n"
|
||||
" <method name='Introspect'>\n"
|
||||
" <arg name='data' direction='out' type='s' />\n"
|
||||
" </method>\n"
|
||||
" </interface>\n"
|
||||
" <interface name='" CDBUS_INTERFACE_NAME "'>\n"
|
||||
" <signal name='win_added'>\n"
|
||||
" <arg name='wid' type='" CDBUS_TYPE_WINDOW_STR "'/>\n"
|
||||
|
|
35
src/dbus.h
35
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.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue