Run clang-format
Now we have a consistent style across the codebase. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
7845673734
commit
22da17630f
437
src/c2.c
437
src/c2.c
|
@ -10,10 +10,10 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <fnmatch.h>
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <fnmatch.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
// libpcre
|
// libpcre
|
||||||
#ifdef CONFIG_REGEX_PCRE
|
#ifdef CONFIG_REGEX_PCRE
|
||||||
|
@ -29,17 +29,17 @@
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <xcb/xcb.h>
|
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "win.h"
|
#include "compiler.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "log.h"
|
||||||
#include "string_utils.h"
|
#include "string_utils.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "log.h"
|
#include "win.h"
|
||||||
#include "x.h"
|
#include "x.h"
|
||||||
#include "compiler.h"
|
|
||||||
|
|
||||||
#include "c2.h"
|
#include "c2.h"
|
||||||
|
|
||||||
|
@ -60,10 +60,8 @@ typedef struct {
|
||||||
} c2_ptr_t;
|
} c2_ptr_t;
|
||||||
|
|
||||||
/// Initializer for c2_ptr_t.
|
/// Initializer for c2_ptr_t.
|
||||||
#define C2_PTR_INIT { \
|
#define C2_PTR_INIT \
|
||||||
.isbranch = false, \
|
{ .isbranch = false, .l = NULL, }
|
||||||
.l = NULL, \
|
|
||||||
}
|
|
||||||
|
|
||||||
static const c2_ptr_t C2_PTR_NULL = C2_PTR_INIT;
|
static const c2_ptr_t C2_PTR_NULL = C2_PTR_INIT;
|
||||||
|
|
||||||
|
@ -84,26 +82,20 @@ struct _c2_b {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Initializer for c2_b_t.
|
/// Initializer for c2_b_t.
|
||||||
#define C2_B_INIT { \
|
#define C2_B_INIT \
|
||||||
.neg = false, \
|
{ .neg = false, .op = C2_B_OUNDEFINED, .opr1 = C2_PTR_INIT, .opr2 = C2_PTR_INIT, }
|
||||||
.op = C2_B_OUNDEFINED, \
|
|
||||||
.opr1 = C2_PTR_INIT, \
|
|
||||||
.opr2 = C2_PTR_INIT, \
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Structure for leaf element in a window condition
|
/// Structure for leaf element in a window condition
|
||||||
struct _c2_l {
|
struct _c2_l {
|
||||||
bool neg : 1;
|
bool neg : 1;
|
||||||
enum {
|
enum { C2_L_OEXISTS,
|
||||||
C2_L_OEXISTS,
|
|
||||||
C2_L_OEQ,
|
C2_L_OEQ,
|
||||||
C2_L_OGT,
|
C2_L_OGT,
|
||||||
C2_L_OGTEQ,
|
C2_L_OGTEQ,
|
||||||
C2_L_OLT,
|
C2_L_OLT,
|
||||||
C2_L_OLTEQ,
|
C2_L_OLTEQ,
|
||||||
} op : 3;
|
} op : 3;
|
||||||
enum {
|
enum { C2_L_MEXACT,
|
||||||
C2_L_MEXACT,
|
|
||||||
C2_L_MSTART,
|
C2_L_MSTART,
|
||||||
C2_L_MCONTAINS,
|
C2_L_MCONTAINS,
|
||||||
C2_L_MWILDCARD,
|
C2_L_MWILDCARD,
|
||||||
|
@ -114,8 +106,7 @@ struct _c2_l {
|
||||||
xcb_atom_t tgtatom;
|
xcb_atom_t tgtatom;
|
||||||
bool tgt_onframe;
|
bool tgt_onframe;
|
||||||
int index;
|
int index;
|
||||||
enum {
|
enum { C2_L_PUNDEFINED,
|
||||||
C2_L_PUNDEFINED,
|
|
||||||
C2_L_PID,
|
C2_L_PID,
|
||||||
C2_L_PX,
|
C2_L_PX,
|
||||||
C2_L_PY,
|
C2_L_PY,
|
||||||
|
@ -150,8 +141,7 @@ struct _c2_l {
|
||||||
C2_L_TDRAWABLE,
|
C2_L_TDRAWABLE,
|
||||||
} type;
|
} type;
|
||||||
int format;
|
int format;
|
||||||
enum {
|
enum { C2_L_PTUNDEFINED,
|
||||||
C2_L_PTUNDEFINED,
|
|
||||||
C2_L_PTSTRING,
|
C2_L_PTSTRING,
|
||||||
C2_L_PTINT,
|
C2_L_PTINT,
|
||||||
} ptntype;
|
} ptntype;
|
||||||
|
@ -164,21 +154,12 @@ struct _c2_l {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Initializer for c2_l_t.
|
/// Initializer for c2_l_t.
|
||||||
#define C2_L_INIT { \
|
#define C2_L_INIT \
|
||||||
.neg = false, \
|
{ \
|
||||||
.op = C2_L_OEXISTS, \
|
.neg = false, .op = C2_L_OEXISTS, .match = C2_L_MEXACT, \
|
||||||
.match = C2_L_MEXACT, \
|
.match_ignorecase = false, .tgt = NULL, .tgtatom = 0, .tgt_onframe = false, \
|
||||||
.match_ignorecase = false, \
|
.predef = C2_L_PUNDEFINED, .index = -1, .type = C2_L_TUNDEFINED, \
|
||||||
.tgt = NULL, \
|
.format = 0, .ptntype = C2_L_PTUNDEFINED, .ptnstr = NULL, .ptnint = 0, \
|
||||||
.tgtatom = 0, \
|
|
||||||
.tgt_onframe = false, \
|
|
||||||
.predef = C2_L_PUNDEFINED, \
|
|
||||||
.index = -1, \
|
|
||||||
.type = C2_L_TUNDEFINED, \
|
|
||||||
.format = 0, \
|
|
||||||
.ptntype = C2_L_PTUNDEFINED, \
|
|
||||||
.ptnstr = NULL, \
|
|
||||||
.ptnint = 0, \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const c2_l_t leaf_def = C2_L_INIT;
|
static const c2_l_t leaf_def = C2_L_INIT;
|
||||||
|
@ -191,11 +172,8 @@ struct _c2_lptr {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Initializer for c2_lptr_t.
|
/// Initializer for c2_lptr_t.
|
||||||
#define C2_LPTR_INIT { \
|
#define C2_LPTR_INIT \
|
||||||
.ptr = C2_PTR_INIT, \
|
{ .ptr = C2_PTR_INIT, .data = NULL, .next = NULL, }
|
||||||
.data = NULL, \
|
|
||||||
.next = NULL, \
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Structure representing a predefined target.
|
/// Structure representing a predefined target.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -235,8 +213,7 @@ static const c2_predef_t C2_PREDEFS[] = {
|
||||||
/**
|
/**
|
||||||
* Compare next word in a string with another string.
|
* Compare next word in a string with another string.
|
||||||
*/
|
*/
|
||||||
static inline int
|
static inline int strcmp_wd(const char *needle, const char *src) {
|
||||||
strcmp_wd(const char *needle, const char *src) {
|
|
||||||
int ret = mstrncmp(needle, src);
|
int ret = mstrncmp(needle, src);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -251,16 +228,14 @@ strcmp_wd(const char *needle, const char *src) {
|
||||||
/**
|
/**
|
||||||
* Return whether a c2_ptr_t is empty.
|
* Return whether a c2_ptr_t is empty.
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool c2_ptr_isempty(const c2_ptr_t p) {
|
||||||
c2_ptr_isempty(const c2_ptr_t p) {
|
|
||||||
return !(p.isbranch ? (bool)p.b : (bool)p.l);
|
return !(p.isbranch ? (bool)p.b : (bool)p.l);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset a c2_ptr_t.
|
* Reset a c2_ptr_t.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void c2_ptr_reset(c2_ptr_t *pp) {
|
||||||
c2_ptr_reset(c2_ptr_t *pp) {
|
|
||||||
if (pp)
|
if (pp)
|
||||||
memcpy(pp, &C2_PTR_NULL, sizeof(c2_ptr_t));
|
memcpy(pp, &C2_PTR_NULL, sizeof(c2_ptr_t));
|
||||||
}
|
}
|
||||||
|
@ -268,12 +243,8 @@ c2_ptr_reset(c2_ptr_t *pp) {
|
||||||
/**
|
/**
|
||||||
* Combine two condition trees.
|
* Combine two condition trees.
|
||||||
*/
|
*/
|
||||||
static inline c2_ptr_t
|
static inline c2_ptr_t c2h_comb_tree(c2_b_op_t op, c2_ptr_t p1, c2_ptr_t p2) {
|
||||||
c2h_comb_tree(c2_b_op_t op, c2_ptr_t p1, c2_ptr_t p2) {
|
c2_ptr_t p = {.isbranch = true, .b = cmalloc(c2_b_t)};
|
||||||
c2_ptr_t p = {
|
|
||||||
.isbranch = true,
|
|
||||||
.b = cmalloc(c2_b_t)
|
|
||||||
};
|
|
||||||
|
|
||||||
p.b->opr1 = p1;
|
p.b->opr1 = p1;
|
||||||
p.b->opr2 = p2;
|
p.b->opr2 = p2;
|
||||||
|
@ -285,8 +256,7 @@ c2h_comb_tree(c2_b_op_t op, c2_ptr_t p1, c2_ptr_t p2) {
|
||||||
/**
|
/**
|
||||||
* Get the precedence value of a condition branch operator.
|
* Get the precedence value of a condition branch operator.
|
||||||
*/
|
*/
|
||||||
static inline int
|
static inline int c2h_b_opp(c2_b_op_t op) {
|
||||||
c2h_b_opp(c2_b_op_t op) {
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case C2_B_OAND: return 2;
|
case C2_B_OAND: return 2;
|
||||||
case C2_B_OOR: return 1;
|
case C2_B_OOR: return 1;
|
||||||
|
@ -306,61 +276,46 @@ c2h_b_opp(c2_b_op_t op) {
|
||||||
* @return positive number if op1 > op2, 0 if op1 == op2 in precedence,
|
* @return positive number if op1 > op2, 0 if op1 == op2 in precedence,
|
||||||
* negative number otherwise
|
* negative number otherwise
|
||||||
*/
|
*/
|
||||||
static inline int
|
static inline int c2h_b_opcmp(c2_b_op_t op1, c2_b_op_t op2) {
|
||||||
c2h_b_opcmp(c2_b_op_t op1, c2_b_op_t op2) {
|
|
||||||
return c2h_b_opp(op1) - c2h_b_opp(op2);
|
return c2h_b_opp(op1) - c2h_b_opp(op2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int c2_parse_grp(const char *pattern, int offset, c2_ptr_t *presult, int level);
|
||||||
c2_parse_grp(const char *pattern, int offset, c2_ptr_t *presult, int level);
|
|
||||||
|
|
||||||
static int
|
static int c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult);
|
||||||
c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult);
|
|
||||||
|
|
||||||
static int
|
static int c2_parse_op(const char *pattern, int offset, c2_ptr_t *presult);
|
||||||
c2_parse_op(const char *pattern, int offset, c2_ptr_t *presult);
|
|
||||||
|
|
||||||
static int
|
static int c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult);
|
||||||
c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult);
|
|
||||||
|
|
||||||
static int
|
static int c2_parse_legacy(const char *pattern, int offset, c2_ptr_t *presult);
|
||||||
c2_parse_legacy(const char *pattern, int offset, c2_ptr_t *presult);
|
|
||||||
|
|
||||||
static void
|
static void c2_free(c2_ptr_t p);
|
||||||
c2_free(c2_ptr_t p);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper of c2_free().
|
* Wrapper of c2_free().
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void c2_freep(c2_ptr_t *pp) {
|
||||||
c2_freep(c2_ptr_t *pp) {
|
|
||||||
if (pp) {
|
if (pp) {
|
||||||
c2_free(*pp);
|
c2_free(*pp);
|
||||||
c2_ptr_reset(pp);
|
c2_ptr_reset(pp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *c2h_dump_str_tgt(const c2_l_t *pleaf);
|
||||||
c2h_dump_str_tgt(const c2_l_t *pleaf);
|
|
||||||
|
|
||||||
static const char *
|
static const char *c2h_dump_str_type(const c2_l_t *pleaf);
|
||||||
c2h_dump_str_type(const c2_l_t *pleaf);
|
|
||||||
|
|
||||||
static void attr_unused
|
static void attr_unused c2_dump(c2_ptr_t p);
|
||||||
c2_dump(c2_ptr_t p);
|
|
||||||
|
|
||||||
static xcb_atom_t
|
static xcb_atom_t c2_get_atom_type(const c2_l_t *pleaf);
|
||||||
c2_get_atom_type(const c2_l_t *pleaf);
|
|
||||||
|
|
||||||
static bool
|
static bool c2_match_once(session_t *ps, const win *w, const c2_ptr_t cond);
|
||||||
c2_match_once(session_t *ps, const win *w, const c2_ptr_t cond);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a condition string.
|
* Parse a condition string.
|
||||||
*/
|
*/
|
||||||
c2_lptr_t *
|
c2_lptr_t *c2_parse(c2_lptr_t **pcondlst, const char *pattern, void *data) {
|
||||||
c2_parse(c2_lptr_t **pcondlst, const char *pattern,
|
|
||||||
void *data) {
|
|
||||||
if (!pattern)
|
if (!pattern)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -399,21 +354,25 @@ c2_parse(c2_lptr_t **pcondlst, const char *pattern,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define c2_error(format, ...) do { \
|
#define c2_error(format, ...) \
|
||||||
|
do { \
|
||||||
log_error("Pattern \"%s\" pos %d: " format, pattern, offset, ##__VA_ARGS__); \
|
log_error("Pattern \"%s\" pos %d: " format, pattern, offset, ##__VA_ARGS__); \
|
||||||
goto fail; \
|
goto fail; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
// TODO Not a very good macro
|
// TODO Not a very good macro
|
||||||
#define C2H_SKIP_SPACES() { while (isspace(pattern[offset])) ++offset; }
|
#define C2H_SKIP_SPACES() \
|
||||||
|
{ \
|
||||||
|
while (isspace(pattern[offset])) \
|
||||||
|
++offset; \
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a group in condition string.
|
* Parse a group in condition string.
|
||||||
*
|
*
|
||||||
* @return offset of next character in string
|
* @return offset of next character in string
|
||||||
*/
|
*/
|
||||||
static int
|
static int c2_parse_grp(const char *pattern, int offset, c2_ptr_t *presult, int level) {
|
||||||
c2_parse_grp(const char *pattern, int offset, c2_ptr_t *presult, int level) {
|
|
||||||
// Check for recursion levels
|
// Check for recursion levels
|
||||||
if (level > C2_MAX_LEVELS)
|
if (level > C2_MAX_LEVELS)
|
||||||
c2_error("Exceeded maximum recursion levels.");
|
c2_error("Exceeded maximum recursion levels.");
|
||||||
|
@ -473,12 +432,10 @@ c2_parse_grp(const char *pattern, int offset, c2_ptr_t *presult, int level) {
|
||||||
if (!mstrncmp("&&", pattern + offset)) {
|
if (!mstrncmp("&&", pattern + offset)) {
|
||||||
ops[elei] = C2_B_OAND;
|
ops[elei] = C2_B_OAND;
|
||||||
++offset;
|
++offset;
|
||||||
}
|
} else if (!mstrncmp("||", pattern + offset)) {
|
||||||
else if (!mstrncmp("||", pattern + offset)) {
|
|
||||||
ops[elei] = C2_B_OOR;
|
ops[elei] = C2_B_OOR;
|
||||||
++offset;
|
++offset;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
c2_error("Illegal logical operator.");
|
c2_error("Illegal logical operator.");
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
@ -555,11 +512,9 @@ c2_parse_grp(const char *pattern, int offset, c2_ptr_t *presult, int level) {
|
||||||
// Handle end of group
|
// Handle end of group
|
||||||
if (!elei) {
|
if (!elei) {
|
||||||
c2_error("Empty group.");
|
c2_error("Empty group.");
|
||||||
}
|
} else if (next_expected) {
|
||||||
else if (next_expected) {
|
|
||||||
c2_error("Missing rule before end of group.");
|
c2_error("Missing rule before end of group.");
|
||||||
}
|
} else if (elei > 1) {
|
||||||
else if (elei > 1) {
|
|
||||||
assert(2 == elei);
|
assert(2 == elei);
|
||||||
assert(ops[1]);
|
assert(ops[1]);
|
||||||
eles[0] = c2h_comb_tree(ops[1], eles[0], eles[1]);
|
eles[0] = c2h_comb_tree(ops[1], eles[0], eles[1]);
|
||||||
|
@ -583,8 +538,7 @@ fail:
|
||||||
/**
|
/**
|
||||||
* Parse the target part of a rule.
|
* Parse the target part of a rule.
|
||||||
*/
|
*/
|
||||||
static int
|
static int c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
|
|
||||||
// Initialize leaf
|
// Initialize leaf
|
||||||
presult->isbranch = false;
|
presult->isbranch = false;
|
||||||
presult->l = cmalloc(c2_l_t);
|
presult->l = cmalloc(c2_l_t);
|
||||||
|
@ -601,8 +555,8 @@ c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
|
|
||||||
// Copy target name out
|
// Copy target name out
|
||||||
unsigned tgtlen = 0;
|
unsigned tgtlen = 0;
|
||||||
for (; pattern[offset]
|
for (; pattern[offset] && (isalnum(pattern[offset]) || '_' == pattern[offset]);
|
||||||
&& (isalnum(pattern[offset]) || '_' == pattern[offset]); ++offset) {
|
++offset) {
|
||||||
++tgtlen;
|
++tgtlen;
|
||||||
}
|
}
|
||||||
if (!tgtlen)
|
if (!tgtlen)
|
||||||
|
@ -622,8 +576,7 @@ c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
// Alias for predefined targets
|
// Alias for predefined targets
|
||||||
if (!pleaf->predef) {
|
if (!pleaf->predef) {
|
||||||
#define TGTFILL(pdefid) \
|
#define TGTFILL(pdefid) \
|
||||||
(pleaf->predef = pdefid, \
|
(pleaf->predef = pdefid, pleaf->type = C2_PREDEFS[pdefid].type, \
|
||||||
pleaf->type = C2_PREDEFS[pdefid].type, \
|
|
||||||
pleaf->format = C2_PREDEFS[pdefid].format)
|
pleaf->format = C2_PREDEFS[pdefid].format)
|
||||||
|
|
||||||
// if (!strcmp("WM_NAME", tgt) || !strcmp("_NET_WM_NAME", tgt))
|
// if (!strcmp("WM_NAME", tgt) || !strcmp("_NET_WM_NAME", tgt))
|
||||||
|
@ -632,9 +585,7 @@ c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
|
|
||||||
// Alias for custom properties
|
// Alias for custom properties
|
||||||
#define TGTFILL(target, type, format) \
|
#define TGTFILL(target, type, format) \
|
||||||
(pleaf->target = strdup(target), \
|
(pleaf->target = strdup(target), pleaf->type = type, pleaf->format = format)
|
||||||
pleaf->type = type, \
|
|
||||||
pleaf->format = format)
|
|
||||||
|
|
||||||
// if (!strcmp("SOME_ALIAS"))
|
// if (!strcmp("SOME_ALIAS"))
|
||||||
// TGTFILL("ALIAS_TEXT", C2_L_TSTRING, 32);
|
// TGTFILL("ALIAS_TEXT", C2_L_TSTRING, 32);
|
||||||
|
@ -714,11 +665,12 @@ c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
|
|
||||||
if (type) {
|
if (type) {
|
||||||
if (pleaf->predef) {
|
if (pleaf->predef) {
|
||||||
log_warn("Type specified for a default target will be ignored.");
|
log_warn("Type specified for a default target "
|
||||||
}
|
"will be ignored.");
|
||||||
else {
|
} else {
|
||||||
if (pleaf->type && type != pleaf->type)
|
if (pleaf->type && type != pleaf->type)
|
||||||
log_warn("Default type overridden on target.");
|
log_warn("Default type overridden on "
|
||||||
|
"target.");
|
||||||
pleaf->type = type;
|
pleaf->type = type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -732,24 +684,27 @@ c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
switch (pleaf->type) {
|
switch (pleaf->type) {
|
||||||
case C2_L_TWINDOW:
|
case C2_L_TWINDOW:
|
||||||
case C2_L_TDRAWABLE:
|
case C2_L_TDRAWABLE:
|
||||||
case C2_L_TATOM:
|
case C2_L_TATOM: pleaf->format = 32; break;
|
||||||
pleaf->format = 32; break;
|
case C2_L_TSTRING: pleaf->format = 8; break;
|
||||||
case C2_L_TSTRING:
|
default: break;
|
||||||
pleaf->format = 8; break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write format
|
// Write format
|
||||||
if (hasformat) {
|
if (hasformat) {
|
||||||
if (pleaf->predef)
|
if (pleaf->predef)
|
||||||
log_warn("Format \"%d\" specified on a default target will be ignored.", format);
|
log_warn("Format \"%d\" specified on a default target "
|
||||||
|
"will be ignored.",
|
||||||
|
format);
|
||||||
else if (C2_L_TSTRING == pleaf->type)
|
else if (C2_L_TSTRING == pleaf->type)
|
||||||
log_warn("Format \"%d\" specified on a string target will be ignored.", format);
|
log_warn("Format \"%d\" specified on a string target "
|
||||||
|
"will be ignored.",
|
||||||
|
format);
|
||||||
else {
|
else {
|
||||||
if (pleaf->format && pleaf->format != format)
|
if (pleaf->format && pleaf->format != format)
|
||||||
log_warn("Default format %d overridden on target.", pleaf->format);
|
log_warn("Default format %d overridden on "
|
||||||
|
"target.",
|
||||||
|
pleaf->format);
|
||||||
pleaf->format = format;
|
pleaf->format = format;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -761,8 +716,7 @@ c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
// if (!pleaf->predef && !pleaf->format && C2_L_TSTRING != pleaf->type)
|
// if (!pleaf->predef && !pleaf->format && C2_L_TSTRING != pleaf->type)
|
||||||
// c2_error("Target format cannot be determined.");
|
// c2_error("Target format cannot be determined.");
|
||||||
|
|
||||||
if (pleaf->format && 8 != pleaf->format
|
if (pleaf->format && 8 != pleaf->format && 16 != pleaf->format && 32 != pleaf->format)
|
||||||
&& 16 != pleaf->format && 32 != pleaf->format)
|
|
||||||
c2_error("Invalid format.");
|
c2_error("Invalid format.");
|
||||||
|
|
||||||
return offset;
|
return offset;
|
||||||
|
@ -774,8 +728,7 @@ fail:
|
||||||
/**
|
/**
|
||||||
* Parse the operator part of a leaf.
|
* Parse the operator part of a leaf.
|
||||||
*/
|
*/
|
||||||
static int
|
static int c2_parse_op(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
c2_parse_op(const char *pattern, int offset, c2_ptr_t *presult) {
|
|
||||||
c2_l_t *const pleaf = presult->l;
|
c2_l_t *const pleaf = presult->l;
|
||||||
|
|
||||||
// Parse negation marks
|
// Parse negation marks
|
||||||
|
@ -787,8 +740,8 @@ c2_parse_op(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse qualifiers
|
// Parse qualifiers
|
||||||
if ('*' == pattern[offset] || '^' == pattern[offset]
|
if ('*' == pattern[offset] || '^' == pattern[offset] || '%' == pattern[offset] ||
|
||||||
|| '%' == pattern[offset] || '~' == pattern[offset]) {
|
'~' == pattern[offset]) {
|
||||||
switch (pattern[offset]) {
|
switch (pattern[offset]) {
|
||||||
case '*': pleaf->match = C2_L_MCONTAINS; break;
|
case '*': pleaf->match = C2_L_MCONTAINS; break;
|
||||||
case '^': pleaf->match = C2_L_MSTART; break;
|
case '^': pleaf->match = C2_L_MSTART; break;
|
||||||
|
@ -808,16 +761,14 @@ c2_parse_op(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse operator
|
// Parse operator
|
||||||
while ('=' == pattern[offset] || '>' == pattern[offset]
|
while ('=' == pattern[offset] || '>' == pattern[offset] || '<' == pattern[offset]) {
|
||||||
|| '<' == pattern[offset]) {
|
|
||||||
if ('=' == pattern[offset] && C2_L_OGT == pleaf->op)
|
if ('=' == pattern[offset] && C2_L_OGT == pleaf->op)
|
||||||
pleaf->op = C2_L_OGTEQ;
|
pleaf->op = C2_L_OGTEQ;
|
||||||
else if ('=' == pattern[offset] && C2_L_OLT == pleaf->op)
|
else if ('=' == pattern[offset] && C2_L_OLT == pleaf->op)
|
||||||
pleaf->op = C2_L_OLTEQ;
|
pleaf->op = C2_L_OLTEQ;
|
||||||
else if (pleaf->op) {
|
else if (pleaf->op) {
|
||||||
c2_error("Duplicate operator.");
|
c2_error("Duplicate operator.");
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
switch (pattern[offset]) {
|
switch (pattern[offset]) {
|
||||||
case '=': pleaf->op = C2_L_OEQ; break;
|
case '=': pleaf->op = C2_L_OEQ; break;
|
||||||
case '>': pleaf->op = C2_L_OGT; break;
|
case '>': pleaf->op = C2_L_OGT; break;
|
||||||
|
@ -831,7 +782,8 @@ c2_parse_op(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
|
|
||||||
// Check for problems
|
// Check for problems
|
||||||
if (C2_L_OEQ != pleaf->op && (pleaf->match || pleaf->match_ignorecase))
|
if (C2_L_OEQ != pleaf->op && (pleaf->match || pleaf->match_ignorecase))
|
||||||
c2_error("Exists/greater-than/less-than operators cannot have a qualifier.");
|
c2_error("Exists/greater-than/less-than operators cannot have a "
|
||||||
|
"qualifier.");
|
||||||
|
|
||||||
return offset;
|
return offset;
|
||||||
|
|
||||||
|
@ -842,8 +794,7 @@ fail:
|
||||||
/**
|
/**
|
||||||
* Parse the pattern part of a leaf.
|
* Parse the pattern part of a leaf.
|
||||||
*/
|
*/
|
||||||
static int
|
static int c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult) {
|
|
||||||
c2_l_t *const pleaf = presult->l;
|
c2_l_t *const pleaf = presult->l;
|
||||||
|
|
||||||
// Exists operator cannot have pattern
|
// Exists operator cannot have pattern
|
||||||
|
@ -858,8 +809,7 @@ c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
pleaf->ptntype = C2_L_PTINT;
|
pleaf->ptntype = C2_L_PTINT;
|
||||||
pleaf->ptnint = true;
|
pleaf->ptnint = true;
|
||||||
offset += strlen("true");
|
offset += strlen("true");
|
||||||
}
|
} else if (!strcmp_wd("false", &pattern[offset])) {
|
||||||
else if (!strcmp_wd("false", &pattern[offset])) {
|
|
||||||
pleaf->ptntype = C2_L_PTINT;
|
pleaf->ptntype = C2_L_PTINT;
|
||||||
pleaf->ptnint = false;
|
pleaf->ptnint = false;
|
||||||
offset += strlen("false");
|
offset += strlen("false");
|
||||||
|
@ -917,15 +867,15 @@ c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
case 't': *(ptptnstr++) = '\t'; break;
|
case 't': *(ptptnstr++) = '\t'; break;
|
||||||
case 'v': *(ptptnstr++) = '\v'; break;
|
case 'v': *(ptptnstr++) = '\v'; break;
|
||||||
case 'o':
|
case 'o':
|
||||||
case 'x':
|
case 'x': {
|
||||||
{
|
|
||||||
char *tstr = strndup(pattern + offset + 1, 2);
|
char *tstr = strndup(pattern + offset + 1, 2);
|
||||||
char *pstr = NULL;
|
char *pstr = NULL;
|
||||||
long val = strtol(tstr, &pstr,
|
long val = strtol(
|
||||||
('o' == pattern[offset] ? 8: 16));
|
tstr, &pstr, ('o' == pattern[offset] ? 8 : 16));
|
||||||
free(tstr);
|
free(tstr);
|
||||||
if (pstr != &tstr[2] || val <= 0)
|
if (pstr != &tstr[2] || val <= 0)
|
||||||
c2_error("Invalid octal/hex escape sequence.");
|
c2_error("Invalid octal/hex escape "
|
||||||
|
"sequence.");
|
||||||
assert(val < 256 && val >= 0);
|
assert(val < 256 && val >= 0);
|
||||||
*(ptptnstr++) = val;
|
*(ptptnstr++) = val;
|
||||||
offset += 2;
|
offset += 2;
|
||||||
|
@ -933,8 +883,7 @@ c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
}
|
}
|
||||||
default: c2_error("Invalid escape sequence.");
|
default: c2_error("Invalid escape sequence.");
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
*(ptptnstr++) = pattern[offset];
|
*(ptptnstr++) = pattern[offset];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -952,13 +901,11 @@ c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
c2_error("Invalid pattern type.");
|
c2_error("Invalid pattern type.");
|
||||||
|
|
||||||
// Check if the type is correct
|
// Check if the type is correct
|
||||||
if (!(((C2_L_TSTRING == pleaf->type
|
if (!(((C2_L_TSTRING == pleaf->type || C2_L_TATOM == pleaf->type) &&
|
||||||
|| C2_L_TATOM == pleaf->type)
|
C2_L_PTSTRING == pleaf->ptntype) ||
|
||||||
&& C2_L_PTSTRING == pleaf->ptntype)
|
((C2_L_TCARDINAL == pleaf->type || C2_L_TWINDOW == pleaf->type ||
|
||||||
|| ((C2_L_TCARDINAL == pleaf->type
|
C2_L_TDRAWABLE == pleaf->type) &&
|
||||||
|| C2_L_TWINDOW == pleaf->type
|
C2_L_PTINT == pleaf->ptntype)))
|
||||||
|| C2_L_TDRAWABLE == pleaf->type)
|
|
||||||
&& C2_L_PTINT == pleaf->ptntype)))
|
|
||||||
c2_error("Pattern type incompatible with target type.");
|
c2_error("Pattern type incompatible with target type.");
|
||||||
|
|
||||||
if (C2_L_PTINT == pleaf->ptntype && pleaf->match)
|
if (C2_L_PTINT == pleaf->ptntype && pleaf->match)
|
||||||
|
@ -967,9 +914,9 @@ c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
if (C2_L_PTINT == pleaf->ptntype && pleaf->match_ignorecase)
|
if (C2_L_PTINT == pleaf->ptntype && pleaf->match_ignorecase)
|
||||||
c2_error("Integer/boolean pattern cannot have flags.");
|
c2_error("Integer/boolean pattern cannot have flags.");
|
||||||
|
|
||||||
if (C2_L_PTSTRING == pleaf->ptntype
|
if (C2_L_PTSTRING == pleaf->ptntype &&
|
||||||
&& (C2_L_OGT == pleaf->op || C2_L_OGTEQ == pleaf->op
|
(C2_L_OGT == pleaf->op || C2_L_OGTEQ == pleaf->op || C2_L_OLT == pleaf->op ||
|
||||||
|| C2_L_OLT == pleaf->op || C2_L_OLTEQ == pleaf->op))
|
C2_L_OLTEQ == pleaf->op))
|
||||||
c2_error("String pattern cannot have an arithmetic operator.");
|
c2_error("String pattern cannot have an arithmetic operator.");
|
||||||
|
|
||||||
return offset;
|
return offset;
|
||||||
|
@ -981,12 +928,10 @@ fail:
|
||||||
/**
|
/**
|
||||||
* Parse a condition with legacy syntax.
|
* Parse a condition with legacy syntax.
|
||||||
*/
|
*/
|
||||||
static int
|
static int c2_parse_legacy(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
c2_parse_legacy(const char *pattern, int offset, c2_ptr_t *presult) {
|
|
||||||
unsigned plen = strlen(pattern + offset);
|
unsigned plen = strlen(pattern + offset);
|
||||||
|
|
||||||
if (plen < 4 || ':' != pattern[offset + 1]
|
if (plen < 4 || ':' != pattern[offset + 1] || !strchr(pattern + offset + 2, ':'))
|
||||||
|| !strchr(pattern + offset + 2, ':'))
|
|
||||||
c2_error("Legacy parser: Invalid format.");
|
c2_error("Legacy parser: Invalid format.");
|
||||||
|
|
||||||
// Allocate memory for new leaf
|
// Allocate memory for new leaf
|
||||||
|
@ -1000,8 +945,7 @@ c2_parse_legacy(const char *pattern, int offset, c2_ptr_t *presult) {
|
||||||
|
|
||||||
// Determine the pattern target
|
// Determine the pattern target
|
||||||
#define TGTFILL(pdefid) \
|
#define TGTFILL(pdefid) \
|
||||||
(pleaf->predef = pdefid, \
|
(pleaf->predef = pdefid, pleaf->type = C2_PREDEFS[pdefid].type, \
|
||||||
pleaf->type = C2_PREDEFS[pdefid].type, \
|
|
||||||
pleaf->format = C2_PREDEFS[pdefid].format)
|
pleaf->format = C2_PREDEFS[pdefid].format)
|
||||||
switch (pattern[offset]) {
|
switch (pattern[offset]) {
|
||||||
case 'n': TGTFILL(C2_L_PNAME); break;
|
case 'n': TGTFILL(C2_L_PNAME); break;
|
||||||
|
@ -1049,12 +993,10 @@ fail:
|
||||||
/**
|
/**
|
||||||
* Do postprocessing on a condition leaf.
|
* Do postprocessing on a condition leaf.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool c2_l_postprocess(session_t *ps, c2_l_t *pleaf) {
|
||||||
c2_l_postprocess(session_t *ps, c2_l_t *pleaf) {
|
|
||||||
// Give a pattern type to a leaf with exists operator, if needed
|
// Give a pattern type to a leaf with exists operator, if needed
|
||||||
if (C2_L_OEXISTS == pleaf->op && !pleaf->ptntype) {
|
if (C2_L_OEXISTS == pleaf->op && !pleaf->ptntype) {
|
||||||
pleaf->ptntype =
|
pleaf->ptntype = (C2_L_TSTRING == pleaf->type ? C2_L_PTSTRING : C2_L_PTINT);
|
||||||
(C2_L_TSTRING == pleaf->type ? C2_L_PTSTRING: C2_L_PTINT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get target atom if it's not a predefined one
|
// Get target atom if it's not a predefined one
|
||||||
|
@ -1069,8 +1011,7 @@ c2_l_postprocess(session_t *ps, c2_l_t *pleaf) {
|
||||||
// Insert target Atom into atom track list
|
// Insert target Atom into atom track list
|
||||||
if (pleaf->tgtatom) {
|
if (pleaf->tgtatom) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (latom_t *platom = ps->track_atom_lst; platom;
|
for (latom_t *platom = ps->track_atom_lst; platom; platom = platom->next) {
|
||||||
platom = platom->next) {
|
|
||||||
if (pleaf->tgtatom == platom->atom) {
|
if (pleaf->tgtatom == platom->atom) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
|
@ -1102,7 +1043,8 @@ c2_l_postprocess(session_t *ps, c2_l_t *pleaf) {
|
||||||
if (!pleaf->predef) {
|
if (!pleaf->predef) {
|
||||||
for (const char *pc = pleaf->tgt; *pc; ++pc) {
|
for (const char *pc = pleaf->tgt; *pc; ++pc) {
|
||||||
if (islower(*pc)) {
|
if (islower(*pc)) {
|
||||||
log_warn("Lowercase character in target name \"%s\".", pleaf->tgt);
|
log_warn("Lowercase character in target name \"%s\".",
|
||||||
|
pleaf->tgt);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1120,16 +1062,18 @@ c2_l_postprocess(session_t *ps, c2_l_t *pleaf) {
|
||||||
options |= PCRE_CASELESS;
|
options |= PCRE_CASELESS;
|
||||||
|
|
||||||
// Compile PCRE expression
|
// Compile PCRE expression
|
||||||
pleaf->regex_pcre = pcre_compile(pleaf->ptnstr, options,
|
pleaf->regex_pcre =
|
||||||
&error, &erroffset, NULL);
|
pcre_compile(pleaf->ptnstr, options, &error, &erroffset, NULL);
|
||||||
if (!pleaf->regex_pcre) {
|
if (!pleaf->regex_pcre) {
|
||||||
log_error("Pattern \"%s\": PCRE regular expression parsing failed on "
|
log_error("Pattern \"%s\": PCRE regular expression parsing "
|
||||||
"offset %d: %s", pleaf->ptnstr, erroffset, error);
|
"failed on "
|
||||||
|
"offset %d: %s",
|
||||||
|
pleaf->ptnstr, erroffset, error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_REGEX_PCRE_JIT
|
#ifdef CONFIG_REGEX_PCRE_JIT
|
||||||
pleaf->regex_pcre_extra = pcre_study(pleaf->regex_pcre,
|
pleaf->regex_pcre_extra =
|
||||||
PCRE_STUDY_JIT_COMPILE, &error);
|
pcre_study(pleaf->regex_pcre, PCRE_STUDY_JIT_COMPILE, &error);
|
||||||
if (!pleaf->regex_pcre_extra) {
|
if (!pleaf->regex_pcre_extra) {
|
||||||
printf("Pattern \"%s\": PCRE regular expression study failed: %s",
|
printf("Pattern \"%s\": PCRE regular expression study failed: %s",
|
||||||
pleaf->ptnstr, error);
|
pleaf->ptnstr, error);
|
||||||
|
@ -1169,8 +1113,7 @@ bool c2_list_postprocess(session_t *ps, c2_lptr_t *list) {
|
||||||
/**
|
/**
|
||||||
* Free a condition tree.
|
* Free a condition tree.
|
||||||
*/
|
*/
|
||||||
static void
|
static void c2_free(c2_ptr_t p) {
|
||||||
c2_free(c2_ptr_t p) {
|
|
||||||
// For a branch element
|
// For a branch element
|
||||||
if (p.isbranch) {
|
if (p.isbranch) {
|
||||||
c2_b_t *const pbranch = p.b;
|
c2_b_t *const pbranch = p.b;
|
||||||
|
@ -1202,8 +1145,7 @@ c2_free(c2_ptr_t p) {
|
||||||
/**
|
/**
|
||||||
* Free a condition tree in c2_lptr_t.
|
* Free a condition tree in c2_lptr_t.
|
||||||
*/
|
*/
|
||||||
c2_lptr_t *
|
c2_lptr_t *c2_free_lptr(c2_lptr_t *lp) {
|
||||||
c2_free_lptr(c2_lptr_t *lp) {
|
|
||||||
if (!lp)
|
if (!lp)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -1217,8 +1159,7 @@ c2_free_lptr(c2_lptr_t *lp) {
|
||||||
/**
|
/**
|
||||||
* Get a string representation of a rule target.
|
* Get a string representation of a rule target.
|
||||||
*/
|
*/
|
||||||
static const char *
|
static const char *c2h_dump_str_tgt(const c2_l_t *pleaf) {
|
||||||
c2h_dump_str_tgt(const c2_l_t *pleaf) {
|
|
||||||
if (pleaf->predef)
|
if (pleaf->predef)
|
||||||
return C2_PREDEFS[pleaf->predef].name;
|
return C2_PREDEFS[pleaf->predef].name;
|
||||||
else
|
else
|
||||||
|
@ -1228,8 +1169,7 @@ c2h_dump_str_tgt(const c2_l_t *pleaf) {
|
||||||
/**
|
/**
|
||||||
* Get a string representation of a target.
|
* Get a string representation of a target.
|
||||||
*/
|
*/
|
||||||
static const char *
|
static const char *c2h_dump_str_type(const c2_l_t *pleaf) {
|
||||||
c2h_dump_str_type(const c2_l_t *pleaf) {
|
|
||||||
switch (pleaf->type) {
|
switch (pleaf->type) {
|
||||||
case C2_L_TWINDOW: return "w";
|
case C2_L_TWINDOW: return "w";
|
||||||
case C2_L_TDRAWABLE: return "d";
|
case C2_L_TDRAWABLE: return "d";
|
||||||
|
@ -1245,8 +1185,7 @@ c2h_dump_str_type(const c2_l_t *pleaf) {
|
||||||
/**
|
/**
|
||||||
* Dump a condition tree.
|
* Dump a condition tree.
|
||||||
*/
|
*/
|
||||||
static void
|
static void c2_dump(c2_ptr_t p) {
|
||||||
c2_dump(c2_ptr_t p) {
|
|
||||||
// For a branch
|
// For a branch
|
||||||
if (p.isbranch) {
|
if (p.isbranch) {
|
||||||
const c2_b_t *const pbranch = p.b;
|
const c2_b_t *const pbranch = p.b;
|
||||||
|
@ -1322,16 +1261,12 @@ c2_dump(c2_ptr_t p) {
|
||||||
// Print pattern
|
// Print pattern
|
||||||
putchar(' ');
|
putchar(' ');
|
||||||
switch (pleaf->ptntype) {
|
switch (pleaf->ptntype) {
|
||||||
case C2_L_PTINT:
|
case C2_L_PTINT: printf("%ld", pleaf->ptnint); break;
|
||||||
printf("%ld", pleaf->ptnint);
|
|
||||||
break;
|
|
||||||
case C2_L_PTSTRING:
|
case C2_L_PTSTRING:
|
||||||
// TODO: Escape string before printing out?
|
// TODO: Escape string before printing out?
|
||||||
printf("\"%s\"", pleaf->ptnstr);
|
printf("\"%s\"", pleaf->ptnstr);
|
||||||
break;
|
break;
|
||||||
default:
|
default: assert(0); break;
|
||||||
assert(0);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1339,22 +1274,14 @@ c2_dump(c2_ptr_t p) {
|
||||||
/**
|
/**
|
||||||
* Get the type atom of a condition.
|
* Get the type atom of a condition.
|
||||||
*/
|
*/
|
||||||
static xcb_atom_t
|
static xcb_atom_t c2_get_atom_type(const c2_l_t *pleaf) {
|
||||||
c2_get_atom_type(const c2_l_t *pleaf) {
|
|
||||||
switch (pleaf->type) {
|
switch (pleaf->type) {
|
||||||
case C2_L_TCARDINAL:
|
case C2_L_TCARDINAL: return XCB_ATOM_CARDINAL;
|
||||||
return XCB_ATOM_CARDINAL;
|
case C2_L_TWINDOW: return XCB_ATOM_WINDOW;
|
||||||
case C2_L_TWINDOW:
|
case C2_L_TSTRING: return XCB_ATOM_STRING;
|
||||||
return XCB_ATOM_WINDOW;
|
case C2_L_TATOM: return XCB_ATOM_ATOM;
|
||||||
case C2_L_TSTRING:
|
case C2_L_TDRAWABLE: return XCB_ATOM_DRAWABLE;
|
||||||
return XCB_ATOM_STRING;
|
default: assert(0); break;
|
||||||
case C2_L_TATOM:
|
|
||||||
return XCB_ATOM_ATOM;
|
|
||||||
case C2_L_TDRAWABLE:
|
|
||||||
return XCB_ATOM_DRAWABLE;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
|
@ -1365,8 +1292,7 @@ c2_get_atom_type(const c2_l_t *pleaf) {
|
||||||
* For internal use.
|
* For internal use.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void
|
||||||
c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf,
|
c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres, bool *perr) {
|
||||||
bool *pres, bool *perr) {
|
|
||||||
assert(pleaf);
|
assert(pleaf);
|
||||||
|
|
||||||
const xcb_window_t wid = (pleaf->tgt_onframe ? w->client_win : w->id);
|
const xcb_window_t wid = (pleaf->tgt_onframe ? w->client_win : w->id);
|
||||||
|
@ -1379,8 +1305,7 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf,
|
||||||
|
|
||||||
switch (pleaf->ptntype) {
|
switch (pleaf->ptntype) {
|
||||||
// Deal with integer patterns
|
// Deal with integer patterns
|
||||||
case C2_L_PTINT:
|
case C2_L_PTINT: {
|
||||||
{
|
|
||||||
long tgt = 0;
|
long tgt = 0;
|
||||||
|
|
||||||
// Get the value
|
// Get the value
|
||||||
|
@ -1407,13 +1332,17 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf,
|
||||||
case C2_L_PROUNDED: tgt = w->rounded_corners; break;
|
case C2_L_PROUNDED: tgt = w->rounded_corners; break;
|
||||||
case C2_L_PCLIENT: tgt = w->client_win; break;
|
case C2_L_PCLIENT: tgt = w->client_win; break;
|
||||||
case C2_L_PLEADER: tgt = w->leader; break;
|
case C2_L_PLEADER: tgt = w->leader; break;
|
||||||
default: *perr = true; assert(0); break;
|
default:
|
||||||
|
*perr = true;
|
||||||
|
assert(0);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// A raw window property
|
// A raw window property
|
||||||
else {
|
else {
|
||||||
winprop_t prop = wid_get_prop_adv(ps, wid, pleaf->tgtatom,
|
winprop_t prop =
|
||||||
idx, 1L, c2_get_atom_type(pleaf), pleaf->format);
|
wid_get_prop_adv(ps, wid, pleaf->tgtatom, idx, 1L,
|
||||||
|
c2_get_atom_type(pleaf), pleaf->format);
|
||||||
if (prop.nitems) {
|
if (prop.nitems) {
|
||||||
*perr = false;
|
*perr = false;
|
||||||
tgt = winprop_get_int(prop);
|
tgt = winprop_get_int(prop);
|
||||||
|
@ -1426,29 +1355,27 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf,
|
||||||
|
|
||||||
// Do comparison
|
// Do comparison
|
||||||
switch (pleaf->op) {
|
switch (pleaf->op) {
|
||||||
case C2_L_OEXISTS:
|
case C2_L_OEXISTS: *pres = (pleaf->predef ? tgt : true); break;
|
||||||
*pres = (pleaf->predef ? tgt: true);
|
|
||||||
break;
|
|
||||||
case C2_L_OEQ: *pres = (tgt == pleaf->ptnint); break;
|
case C2_L_OEQ: *pres = (tgt == pleaf->ptnint); break;
|
||||||
case C2_L_OGT: *pres = (tgt > pleaf->ptnint); break;
|
case C2_L_OGT: *pres = (tgt > pleaf->ptnint); break;
|
||||||
case C2_L_OGTEQ: *pres = (tgt >= pleaf->ptnint); break;
|
case C2_L_OGTEQ: *pres = (tgt >= pleaf->ptnint); break;
|
||||||
case C2_L_OLT: *pres = (tgt < pleaf->ptnint); break;
|
case C2_L_OLT: *pres = (tgt < pleaf->ptnint); break;
|
||||||
case C2_L_OLTEQ: *pres = (tgt <= pleaf->ptnint); break;
|
case C2_L_OLTEQ: *pres = (tgt <= pleaf->ptnint); break;
|
||||||
default: *perr = true; assert(0); break;
|
default:
|
||||||
}
|
*perr = true;
|
||||||
}
|
assert(0);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
// String patterns
|
// String patterns
|
||||||
case C2_L_PTSTRING:
|
case C2_L_PTSTRING: {
|
||||||
{
|
|
||||||
const char *tgt = NULL;
|
const char *tgt = NULL;
|
||||||
char *tgt_free = NULL;
|
char *tgt_free = NULL;
|
||||||
|
|
||||||
// A predefined target
|
// A predefined target
|
||||||
if (pleaf->predef) {
|
if (pleaf->predef) {
|
||||||
switch (pleaf->predef) {
|
switch (pleaf->predef) {
|
||||||
case C2_L_PWINDOWTYPE: tgt = WINTYPES[w->window_type];
|
case C2_L_PWINDOWTYPE: tgt = WINTYPES[w->window_type]; break;
|
||||||
break;
|
|
||||||
case C2_L_PNAME: tgt = w->name; break;
|
case C2_L_PNAME: tgt = w->name; break;
|
||||||
case C2_L_PCLASSG: tgt = w->class_general; break;
|
case C2_L_PCLASSG: tgt = w->class_general; break;
|
||||||
case C2_L_PCLASSI: tgt = w->class_instance; break;
|
case C2_L_PCLASSI: tgt = w->class_instance; break;
|
||||||
|
@ -1458,15 +1385,17 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf,
|
||||||
}
|
}
|
||||||
// If it's an atom type property, convert atom to string
|
// If it's an atom type property, convert atom to string
|
||||||
else if (C2_L_TATOM == pleaf->type) {
|
else if (C2_L_TATOM == pleaf->type) {
|
||||||
winprop_t prop = wid_get_prop_adv(ps, wid, pleaf->tgtatom,
|
winprop_t prop =
|
||||||
idx, 1L, c2_get_atom_type(pleaf), pleaf->format);
|
wid_get_prop_adv(ps, wid, pleaf->tgtatom, idx, 1L,
|
||||||
|
c2_get_atom_type(pleaf), pleaf->format);
|
||||||
xcb_atom_t atom = winprop_get_int(prop);
|
xcb_atom_t atom = winprop_get_int(prop);
|
||||||
if (atom) {
|
if (atom) {
|
||||||
xcb_get_atom_name_reply_t *reply =
|
xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(
|
||||||
xcb_get_atom_name_reply(ps->c, xcb_get_atom_name(ps->c, atom), NULL);
|
ps->c, xcb_get_atom_name(ps->c, atom), NULL);
|
||||||
if (reply) {
|
if (reply) {
|
||||||
tgt_free = strndup(
|
tgt_free =
|
||||||
xcb_get_atom_name_name(reply), xcb_get_atom_name_name_length(reply));
|
strndup(xcb_get_atom_name_name(reply),
|
||||||
|
xcb_get_atom_name_name_length(reply));
|
||||||
free(reply);
|
free(reply);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1479,8 +1408,8 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf,
|
||||||
else {
|
else {
|
||||||
char **strlst = NULL;
|
char **strlst = NULL;
|
||||||
int nstr;
|
int nstr;
|
||||||
if (wid_get_text_prop(ps, wid, pleaf->tgtatom, &strlst,
|
if (wid_get_text_prop(ps, wid, pleaf->tgtatom, &strlst, &nstr) &&
|
||||||
&nstr) && nstr > idx) {
|
nstr > idx) {
|
||||||
tgt_free = strdup(strlst[idx]);
|
tgt_free = strdup(strlst[idx]);
|
||||||
tgt = tgt_free;
|
tgt = tgt_free;
|
||||||
}
|
}
|
||||||
|
@ -1490,16 +1419,13 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf,
|
||||||
|
|
||||||
if (tgt) {
|
if (tgt) {
|
||||||
*perr = false;
|
*perr = false;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actual matching
|
// Actual matching
|
||||||
switch (pleaf->op) {
|
switch (pleaf->op) {
|
||||||
case C2_L_OEXISTS:
|
case C2_L_OEXISTS: *pres = true; break;
|
||||||
*pres = true;
|
|
||||||
break;
|
|
||||||
case C2_L_OEQ:
|
case C2_L_OEQ:
|
||||||
switch (pleaf->match) {
|
switch (pleaf->match) {
|
||||||
case C2_L_MEXACT:
|
case C2_L_MEXACT:
|
||||||
|
@ -1522,18 +1448,15 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf,
|
||||||
*pres = !strncmp(tgt, pleaf->ptnstr,
|
*pres = !strncmp(tgt, pleaf->ptnstr,
|
||||||
strlen(pleaf->ptnstr));
|
strlen(pleaf->ptnstr));
|
||||||
break;
|
break;
|
||||||
case C2_L_MWILDCARD:
|
case C2_L_MWILDCARD: {
|
||||||
{
|
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
if (pleaf->match_ignorecase)
|
if (pleaf->match_ignorecase)
|
||||||
flags |= FNM_CASEFOLD;
|
flags |= FNM_CASEFOLD;
|
||||||
*pres = !fnmatch(pleaf->ptnstr, tgt, flags);
|
*pres = !fnmatch(pleaf->ptnstr, tgt, flags);
|
||||||
}
|
} break;
|
||||||
break;
|
|
||||||
case C2_L_MPCRE:
|
case C2_L_MPCRE:
|
||||||
#ifdef CONFIG_REGEX_PCRE
|
#ifdef CONFIG_REGEX_PCRE
|
||||||
*pres = (pcre_exec(pleaf->regex_pcre,
|
*pres = (pcre_exec(pleaf->regex_pcre, pleaf->regex_pcre_extra,
|
||||||
pleaf->regex_pcre_extra,
|
|
||||||
tgt, strlen(tgt), 0, 0, NULL, 0) >= 0);
|
tgt, strlen(tgt), 0, 0, NULL, 0) >= 0);
|
||||||
#else
|
#else
|
||||||
assert(0);
|
assert(0);
|
||||||
|
@ -1541,9 +1464,7 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default: *perr = true; assert(0);
|
||||||
*perr = true;
|
|
||||||
assert(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free the string after usage, if necessary
|
// Free the string after usage, if necessary
|
||||||
|
@ -1553,11 +1474,8 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf,
|
||||||
else
|
else
|
||||||
free(tgt_free);
|
free(tgt_free);
|
||||||
}
|
}
|
||||||
}
|
} break;
|
||||||
break;
|
default: assert(0); break;
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1566,8 +1484,7 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf,
|
||||||
*
|
*
|
||||||
* @return true if matched, false otherwise.
|
* @return true if matched, false otherwise.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool c2_match_once(session_t *ps, const win *w, const c2_ptr_t cond) {
|
||||||
c2_match_once(session_t *ps, const win *w, const c2_ptr_t cond) {
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
bool error = true;
|
bool error = true;
|
||||||
|
|
||||||
|
@ -1582,20 +1499,18 @@ c2_match_once(session_t *ps, const win *w, const c2_ptr_t cond) {
|
||||||
|
|
||||||
switch (pb->op) {
|
switch (pb->op) {
|
||||||
case C2_B_OAND:
|
case C2_B_OAND:
|
||||||
result = (c2_match_once(ps, w, pb->opr1)
|
result = (c2_match_once(ps, w, pb->opr1) &&
|
||||||
&& c2_match_once(ps, w, pb->opr2));
|
c2_match_once(ps, w, pb->opr2));
|
||||||
break;
|
break;
|
||||||
case C2_B_OOR:
|
case C2_B_OOR:
|
||||||
result = (c2_match_once(ps, w, pb->opr1)
|
result = (c2_match_once(ps, w, pb->opr1) ||
|
||||||
|| c2_match_once(ps, w, pb->opr2));
|
c2_match_once(ps, w, pb->opr2));
|
||||||
break;
|
break;
|
||||||
case C2_B_OXOR:
|
case C2_B_OXOR:
|
||||||
result = (c2_match_once(ps, w, pb->opr1)
|
result = (c2_match_once(ps, w, pb->opr1) !=
|
||||||
!= c2_match_once(ps, w, pb->opr2));
|
c2_match_once(ps, w, pb->opr2));
|
||||||
break;
|
break;
|
||||||
default:
|
default: error = true; assert(0);
|
||||||
error = true;
|
|
||||||
assert(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_WINMATCH
|
#ifdef DEBUG_WINMATCH
|
||||||
|
@ -1643,8 +1558,7 @@ c2_match_once(session_t *ps, const win *w, const c2_ptr_t cond) {
|
||||||
* @param pdata a place to return the data
|
* @param pdata a place to return the data
|
||||||
* @return true if matched, false otherwise.
|
* @return true if matched, false otherwise.
|
||||||
*/
|
*/
|
||||||
bool
|
bool c2_match(session_t *ps, const win *w, const c2_lptr_t *condlst, void **pdata) {
|
||||||
c2_match(session_t *ps, const win *w, const c2_lptr_t *condlst, void **pdata) {
|
|
||||||
// Then go through the whole linked list
|
// Then go through the whole linked list
|
||||||
for (; condlst; condlst = condlst->next) {
|
for (; condlst; condlst = condlst->next) {
|
||||||
if (c2_match_once(ps, w, condlst->ptr)) {
|
if (c2_match_once(ps, w, condlst->ptr)) {
|
||||||
|
@ -1656,4 +1570,3 @@ c2_match(session_t *ps, const win *w, const c2_lptr_t *condlst, void **pdata) {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
223
src/common.h
223
src/common.h
|
@ -28,26 +28,26 @@
|
||||||
// === Includes ===
|
// === Includes ===
|
||||||
|
|
||||||
// For some special functions
|
// For some special functions
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <inttypes.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <inttypes.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
#include <ev.h>
|
||||||
|
#include <pixman.h>
|
||||||
#include <xcb/composite.h>
|
#include <xcb/composite.h>
|
||||||
#include <xcb/render.h>
|
|
||||||
#include <xcb/damage.h>
|
#include <xcb/damage.h>
|
||||||
#include <xcb/randr.h>
|
#include <xcb/randr.h>
|
||||||
|
#include <xcb/render.h>
|
||||||
#include <xcb/shape.h>
|
#include <xcb/shape.h>
|
||||||
#include <xcb/sync.h>
|
#include <xcb/sync.h>
|
||||||
#include <xcb/xinerama.h>
|
#include <xcb/xinerama.h>
|
||||||
#include <ev.h>
|
|
||||||
#include <pixman.h>
|
|
||||||
|
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
// libGL
|
// libGL
|
||||||
|
@ -76,17 +76,17 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// FIXME This list of includes should get shorter
|
// FIXME This list of includes should get shorter
|
||||||
#include "types.h"
|
|
||||||
#include "win.h"
|
|
||||||
#include "region.h"
|
|
||||||
#include "kernel.h"
|
|
||||||
#include "render.h"
|
|
||||||
#include "config.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "compiler.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "x.h"
|
|
||||||
#include "backend/backend.h"
|
#include "backend/backend.h"
|
||||||
|
#include "compiler.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "kernel.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "region.h"
|
||||||
|
#include "render.h"
|
||||||
|
#include "types.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "win.h"
|
||||||
|
#include "x.h"
|
||||||
|
|
||||||
// === Constants ===
|
// === Constants ===
|
||||||
|
|
||||||
|
@ -159,8 +159,7 @@ enum wincond_type {
|
||||||
#define CONDF_IGNORECASE 0x0001
|
#define CONDF_IGNORECASE 0x0001
|
||||||
|
|
||||||
/// @brief Possible swap methods.
|
/// @brief Possible swap methods.
|
||||||
enum {
|
enum { SWAPM_BUFFER_AGE = -1,
|
||||||
SWAPM_BUFFER_AGE = -1,
|
|
||||||
SWAPM_UNDEFINED = 0,
|
SWAPM_UNDEFINED = 0,
|
||||||
SWAPM_COPY = 1,
|
SWAPM_COPY = 1,
|
||||||
SWAPM_EXCHANGE = 2,
|
SWAPM_EXCHANGE = 2,
|
||||||
|
@ -170,12 +169,11 @@ typedef struct _glx_texture glx_texture_t;
|
||||||
|
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
#ifdef DEBUG_GLX_DEBUG_CONTEXT
|
#ifdef DEBUG_GLX_DEBUG_CONTEXT
|
||||||
typedef GLXContext (*f_glXCreateContextAttribsARB) (Display *dpy,
|
typedef GLXContext (*f_glXCreateContextAttribsARB)(Display *dpy, GLXFBConfig config,
|
||||||
GLXFBConfig config, GLXContext share_context, Bool direct,
|
GLXContext share_context, Bool direct,
|
||||||
const int *attrib_list);
|
const int *attrib_list);
|
||||||
typedef void (*GLDEBUGPROC) (GLenum source, GLenum type,
|
typedef void (*GLDEBUGPROC)(GLenum source, GLenum type, GLuint id, GLenum severity,
|
||||||
GLuint id, GLenum severity, GLsizei length, const GLchar* message,
|
GLsizei length, const GLchar *message, GLvoid *userParam);
|
||||||
GLvoid* userParam);
|
|
||||||
typedef void (*f_DebugMessageCallback)(GLDEBUGPROC, void *userParam);
|
typedef void (*f_DebugMessageCallback)(GLDEBUGPROC, void *userParam);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -183,12 +181,10 @@ typedef void (*f_DebugMessageCallback) (GLDEBUGPROC, void *userParam);
|
||||||
typedef GLsync (*f_FenceSync)(GLenum condition, GLbitfield flags);
|
typedef GLsync (*f_FenceSync)(GLenum condition, GLbitfield flags);
|
||||||
typedef GLboolean (*f_IsSync)(GLsync sync);
|
typedef GLboolean (*f_IsSync)(GLsync sync);
|
||||||
typedef void (*f_DeleteSync)(GLsync sync);
|
typedef void (*f_DeleteSync)(GLsync sync);
|
||||||
typedef GLenum (*f_ClientWaitSync) (GLsync sync, GLbitfield flags,
|
typedef GLenum (*f_ClientWaitSync)(GLsync sync, GLbitfield flags, GLuint64 timeout);
|
||||||
GLuint64 timeout);
|
typedef void (*f_WaitSync)(GLsync sync, GLbitfield flags, GLuint64 timeout);
|
||||||
typedef void (*f_WaitSync) (GLsync sync, GLbitfield flags,
|
typedef GLsync (*f_ImportSyncEXT)(GLenum external_sync_type, GLintptr external_sync,
|
||||||
GLuint64 timeout);
|
GLbitfield flags);
|
||||||
typedef GLsync (*f_ImportSyncEXT) (GLenum external_sync_type,
|
|
||||||
GLintptr external_sync, GLbitfield flags);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// @brief Wrapper of a binded GLX texture.
|
/// @brief Wrapper of a binded GLX texture.
|
||||||
|
@ -227,19 +223,16 @@ typedef struct glx_prog_main {
|
||||||
GLint unifm_tex;
|
GLint unifm_tex;
|
||||||
} glx_prog_main_t;
|
} glx_prog_main_t;
|
||||||
|
|
||||||
#define GLX_PROG_MAIN_INIT { \
|
#define GLX_PROG_MAIN_INIT \
|
||||||
.prog = 0, \
|
{ .prog = 0, .unifm_opacity = -1, .unifm_invert_color = -1, .unifm_tex = -1, }
|
||||||
.unifm_opacity = -1, \
|
|
||||||
.unifm_invert_color = -1, \
|
|
||||||
.unifm_tex = -1, \
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
struct glx_prog_main {};
|
struct glx_prog_main {};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PAINT_INIT { .pixmap = XCB_NONE, .pict = XCB_NONE }
|
#define PAINT_INIT \
|
||||||
|
{ .pixmap = XCB_NONE, .pict = XCB_NONE }
|
||||||
|
|
||||||
/// Linked list type of atoms.
|
/// Linked list type of atoms.
|
||||||
typedef struct _latom {
|
typedef struct _latom {
|
||||||
|
@ -247,7 +240,8 @@ typedef struct _latom {
|
||||||
struct _latom *next;
|
struct _latom *next;
|
||||||
} latom_t;
|
} latom_t;
|
||||||
|
|
||||||
#define REG_DATA_INIT { NULL, 0 }
|
#define REG_DATA_INIT \
|
||||||
|
{ NULL, 0 }
|
||||||
|
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
/// Structure containing GLX-dependent data for a compton session.
|
/// Structure containing GLX-dependent data for a compton session.
|
||||||
|
@ -276,7 +270,8 @@ typedef struct {
|
||||||
#endif
|
#endif
|
||||||
} glx_session_t;
|
} glx_session_t;
|
||||||
|
|
||||||
#define CGLX_SESSION_INIT { .context = NULL }
|
#define CGLX_SESSION_INIT \
|
||||||
|
{ .context = NULL }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -542,29 +537,22 @@ struct options_tmp {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Enumeration for window event hints.
|
/// Enumeration for window event hints.
|
||||||
typedef enum {
|
typedef enum { WIN_EVMODE_UNKNOWN, WIN_EVMODE_FRAME, WIN_EVMODE_CLIENT } win_evmode_t;
|
||||||
WIN_EVMODE_UNKNOWN,
|
|
||||||
WIN_EVMODE_FRAME,
|
|
||||||
WIN_EVMODE_CLIENT
|
|
||||||
} win_evmode_t;
|
|
||||||
|
|
||||||
extern const char *const WINTYPES[NUM_WINTYPES];
|
extern const char *const WINTYPES[NUM_WINTYPES];
|
||||||
extern session_t *ps_g;
|
extern session_t *ps_g;
|
||||||
|
|
||||||
// == Debugging code ==
|
// == Debugging code ==
|
||||||
static inline void
|
static inline void print_timestamp(session_t *ps);
|
||||||
print_timestamp(session_t *ps);
|
|
||||||
|
|
||||||
void
|
void ev_xcb_error(session_t *ps, xcb_generic_error_t *err);
|
||||||
ev_xcb_error(session_t *ps, xcb_generic_error_t *err);
|
|
||||||
|
|
||||||
// === Functions ===
|
// === Functions ===
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return whether a struct timeval value is empty.
|
* Return whether a struct timeval value is empty.
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool timeval_isempty(struct timeval *ptv) {
|
||||||
timeval_isempty(struct timeval *ptv) {
|
|
||||||
if (!ptv)
|
if (!ptv)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -576,8 +564,7 @@ timeval_isempty(struct timeval *ptv) {
|
||||||
*
|
*
|
||||||
* @return > 0 if ptv > ms, 0 if ptv == 0, -1 if ptv < ms
|
* @return > 0 if ptv > ms, 0 if ptv == 0, -1 if ptv < ms
|
||||||
*/
|
*/
|
||||||
static inline int
|
static inline int timeval_ms_cmp(struct timeval *ptv, unsigned long ms) {
|
||||||
timeval_ms_cmp(struct timeval *ptv, unsigned long ms) {
|
|
||||||
assert(ptv);
|
assert(ptv);
|
||||||
|
|
||||||
// We use those if statement instead of a - expression because of possible
|
// We use those if statement instead of a - expression because of possible
|
||||||
|
@ -611,9 +598,7 @@ timeval_ms_cmp(struct timeval *ptv, unsigned long ms) {
|
||||||
* Return 1 if the difference is negative, otherwise 0.
|
* Return 1 if the difference is negative, otherwise 0.
|
||||||
*/
|
*/
|
||||||
static inline int
|
static inline int
|
||||||
timeval_subtract(struct timeval *result,
|
timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) {
|
||||||
struct timeval *x,
|
|
||||||
struct timeval *y) {
|
|
||||||
/* Perform the carry for the later subtraction by updating y. */
|
/* Perform the carry for the later subtraction by updating y. */
|
||||||
if (x->tv_usec < y->tv_usec) {
|
if (x->tv_usec < y->tv_usec) {
|
||||||
long nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
|
long nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
|
||||||
|
@ -646,9 +631,7 @@ timeval_subtract(struct timeval *result,
|
||||||
* Return 1 if the difference is negative, otherwise 0.
|
* Return 1 if the difference is negative, otherwise 0.
|
||||||
*/
|
*/
|
||||||
static inline int
|
static inline int
|
||||||
timespec_subtract(struct timespec *result,
|
timespec_subtract(struct timespec *result, struct timespec *x, struct timespec *y) {
|
||||||
struct timespec *x,
|
|
||||||
struct timespec *y) {
|
|
||||||
/* Perform the carry for the later subtraction by updating y. */
|
/* Perform the carry for the later subtraction by updating y. */
|
||||||
if (x->tv_nsec < y->tv_nsec) {
|
if (x->tv_nsec < y->tv_nsec) {
|
||||||
long nsec = (y->tv_nsec - x->tv_nsec) / NS_PER_SEC + 1;
|
long nsec = (y->tv_nsec - x->tv_nsec) / NS_PER_SEC + 1;
|
||||||
|
@ -674,8 +657,7 @@ timespec_subtract(struct timespec *result,
|
||||||
/**
|
/**
|
||||||
* Get current time in struct timeval.
|
* Get current time in struct timeval.
|
||||||
*/
|
*/
|
||||||
static inline struct timeval
|
static inline struct timeval get_time_timeval(void) {
|
||||||
get_time_timeval(void) {
|
|
||||||
struct timeval tv = {0, 0};
|
struct timeval tv = {0, 0};
|
||||||
|
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
|
@ -689,8 +671,7 @@ get_time_timeval(void) {
|
||||||
*
|
*
|
||||||
* Note its starting time is unspecified.
|
* Note its starting time is unspecified.
|
||||||
*/
|
*/
|
||||||
static inline struct timespec
|
static inline struct timespec get_time_timespec(void) {
|
||||||
get_time_timespec(void) {
|
|
||||||
struct timespec tm = {0, 0};
|
struct timespec tm = {0, 0};
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &tm);
|
clock_gettime(CLOCK_MONOTONIC, &tm);
|
||||||
|
@ -699,17 +680,16 @@ get_time_timespec(void) {
|
||||||
return tm;
|
return tm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print time passed since program starts execution.
|
* Print time passed since program starts execution.
|
||||||
*
|
*
|
||||||
* Used for debugging.
|
* Used for debugging.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void print_timestamp(session_t *ps) {
|
||||||
print_timestamp(session_t *ps) {
|
|
||||||
struct timeval tm, diff;
|
struct timeval tm, diff;
|
||||||
|
|
||||||
if (gettimeofday(&tm, NULL)) return;
|
if (gettimeofday(&tm, NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
timeval_subtract(&diff, &tm, &ps->time_start);
|
timeval_subtract(&diff, &tm, &ps->time_start);
|
||||||
fprintf(stderr, "[ %5ld.%06ld ] ", diff.tv_sec, diff.tv_usec);
|
fprintf(stderr, "[ %5ld.%06ld ] ", diff.tv_sec, diff.tv_usec);
|
||||||
|
@ -720,14 +700,12 @@ print_timestamp(session_t *ps) {
|
||||||
*
|
*
|
||||||
* Because a NULL pointer cannot be passed to XFree(), its man page says.
|
* Because a NULL pointer cannot be passed to XFree(), its man page says.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void cxfree(void *data) {
|
||||||
cxfree(void *data) {
|
|
||||||
if (data)
|
if (data)
|
||||||
XFree(data);
|
XFree(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
_Noreturn static inline void
|
_Noreturn static inline void die(const char *msg) {
|
||||||
die(const char *msg) {
|
|
||||||
puts(msg);
|
puts(msg);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -735,12 +713,9 @@ die(const char *msg) {
|
||||||
/**
|
/**
|
||||||
* Wrapper of XInternAtom() for convenience.
|
* Wrapper of XInternAtom() for convenience.
|
||||||
*/
|
*/
|
||||||
static inline xcb_atom_t
|
static inline xcb_atom_t get_atom(session_t *ps, const char *atom_name) {
|
||||||
get_atom(session_t *ps, const char *atom_name) {
|
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(
|
||||||
xcb_intern_atom_reply_t *reply =
|
ps->c, xcb_intern_atom(ps->c, 0, strlen(atom_name), atom_name), NULL);
|
||||||
xcb_intern_atom_reply(ps->c,
|
|
||||||
xcb_intern_atom(ps->c, 0, strlen(atom_name), atom_name),
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
xcb_atom_t atom = XCB_NONE;
|
xcb_atom_t atom = XCB_NONE;
|
||||||
if (reply) {
|
if (reply) {
|
||||||
|
@ -755,16 +730,14 @@ get_atom(session_t *ps, const char *atom_name) {
|
||||||
/**
|
/**
|
||||||
* Return the painting target window.
|
* Return the painting target window.
|
||||||
*/
|
*/
|
||||||
static inline xcb_window_t
|
static inline xcb_window_t get_tgt_window(session_t *ps) {
|
||||||
get_tgt_window(session_t *ps) {
|
|
||||||
return ps->overlay != XCB_NONE ? ps->overlay : ps->root;
|
return ps->overlay != XCB_NONE ? ps->overlay : ps->root;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a window from window id in window linked list of the session.
|
* Find a window from window id in window linked list of the session.
|
||||||
*/
|
*/
|
||||||
static inline win *
|
static inline win *find_win(session_t *ps, xcb_window_t id) {
|
||||||
find_win(session_t *ps, xcb_window_t id) {
|
|
||||||
if (!id)
|
if (!id)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -785,8 +758,7 @@ find_win(session_t *ps, xcb_window_t id) {
|
||||||
* @param id window ID
|
* @param id window ID
|
||||||
* @return struct win object of the found window, NULL if not found
|
* @return struct win object of the found window, NULL if not found
|
||||||
*/
|
*/
|
||||||
static inline win *
|
static inline win *find_toplevel(session_t *ps, xcb_window_t id) {
|
||||||
find_toplevel(session_t *ps, xcb_window_t id) {
|
|
||||||
if (!id)
|
if (!id)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -802,17 +774,14 @@ find_toplevel(session_t *ps, xcb_window_t id) {
|
||||||
/**
|
/**
|
||||||
* Check if current backend uses GLX.
|
* Check if current backend uses GLX.
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool bkend_use_glx(session_t *ps) {
|
||||||
bkend_use_glx(session_t *ps) {
|
return BKEND_GLX == ps->o.backend || BKEND_XR_GLX_HYBRID == ps->o.backend;
|
||||||
return BKEND_GLX == ps->o.backend
|
|
||||||
|| BKEND_XR_GLX_HYBRID == ps->o.backend;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a window is really focused.
|
* Check if a window is really focused.
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool win_is_focused_real(session_t *ps, const win *w) {
|
||||||
win_is_focused_real(session_t *ps, const win *w) {
|
|
||||||
return w->a.map_state == XCB_MAP_STATE_VIEWABLE && ps->active_win == w;
|
return w->a.map_state == XCB_MAP_STATE_VIEWABLE && ps->active_win == w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -821,9 +790,9 @@ win_is_focused_real(session_t *ps, const win *w) {
|
||||||
*
|
*
|
||||||
* @return struct win object of the found window, NULL if not found
|
* @return struct win object of the found window, NULL if not found
|
||||||
*/
|
*/
|
||||||
static inline win *
|
static inline win *find_focused(session_t *ps) {
|
||||||
find_focused(session_t *ps) {
|
if (!ps->o.track_focus)
|
||||||
if (!ps->o.track_focus) return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (ps->active_win && win_is_focused_real(ps, ps->active_win))
|
if (ps->active_win && win_is_focused_real(ps, ps->active_win))
|
||||||
return ps->active_win;
|
return ps->active_win;
|
||||||
|
@ -833,20 +802,17 @@ find_focused(session_t *ps) {
|
||||||
/**
|
/**
|
||||||
* Check if a rectangle includes the whole screen.
|
* Check if a rectangle includes the whole screen.
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool rect_is_fullscreen(session_t *ps, int x, int y, int wid, int hei) {
|
||||||
rect_is_fullscreen(session_t *ps, int x, int y, int wid, int hei) {
|
return (x <= 0 && y <= 0 && (x + wid) >= ps->root_width && (y + hei) >= ps->root_height);
|
||||||
return (x <= 0 && y <= 0 &&
|
|
||||||
(x + wid) >= ps->root_width &&
|
|
||||||
(y + hei) >= ps->root_height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void set_ignore(session_t *ps, unsigned long sequence) {
|
||||||
set_ignore(session_t *ps, unsigned long sequence) {
|
|
||||||
if (ps->o.show_all_xerrors)
|
if (ps->o.show_all_xerrors)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto i = cmalloc(ignore_t);
|
auto i = cmalloc(ignore_t);
|
||||||
if (!i) return;
|
if (!i)
|
||||||
|
return;
|
||||||
|
|
||||||
i->sequence = sequence;
|
i->sequence = sequence;
|
||||||
i->next = 0;
|
i->next = 0;
|
||||||
|
@ -857,8 +823,7 @@ set_ignore(session_t *ps, unsigned long sequence) {
|
||||||
/**
|
/**
|
||||||
* Ignore X errors caused by given X request.
|
* Ignore X errors caused by given X request.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void set_ignore_cookie(session_t *ps, xcb_void_cookie_t cookie) {
|
||||||
set_ignore_cookie(session_t *ps, xcb_void_cookie_t cookie) {
|
|
||||||
set_ignore(ps, cookie.sequence);
|
set_ignore(ps, cookie.sequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -867,17 +832,15 @@ set_ignore_cookie(session_t *ps, xcb_void_cookie_t cookie) {
|
||||||
*
|
*
|
||||||
* It's not using w->border_size for performance measures.
|
* It's not using w->border_size for performance measures.
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool win_is_fullscreen(session_t *ps, const win *w) {
|
||||||
win_is_fullscreen(session_t *ps, const win *w) {
|
return rect_is_fullscreen(ps, w->g.x, w->g.y, w->widthb, w->heightb) &&
|
||||||
return rect_is_fullscreen(ps, w->g.x, w->g.y, w->widthb, w->heightb)
|
(!w->bounding_shaped || w->rounded_corners);
|
||||||
&& (!w->bounding_shaped || w->rounded_corners);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a window will be painted solid.
|
* Check if a window will be painted solid.
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool win_is_solid(session_t *ps, const win *w) {
|
||||||
win_is_solid(session_t *ps, const win *w) {
|
|
||||||
return WMODE_SOLID == w->mode && !ps->o.force_win_blend;
|
return WMODE_SOLID == w->mode && !ps->o.force_win_blend;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -889,13 +852,9 @@ win_is_solid(session_t *ps, const win *w) {
|
||||||
* @param atom atom of property to check
|
* @param atom atom of property to check
|
||||||
* @return true if it has the attribute, false otherwise
|
* @return true if it has the attribute, false otherwise
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool wid_has_prop(const session_t *ps, xcb_window_t w, xcb_atom_t atom) {
|
||||||
wid_has_prop(const session_t *ps, xcb_window_t w, xcb_atom_t atom) {
|
auto r = xcb_get_property_reply(
|
||||||
auto r =
|
ps->c, xcb_get_property(ps->c, 0, w, atom, XCB_GET_PROPERTY_TYPE_ANY, 0, 0), NULL);
|
||||||
xcb_get_property_reply(ps->c,
|
|
||||||
xcb_get_property(ps->c, 0, w, atom,
|
|
||||||
XCB_GET_PROPERTY_TYPE_ANY, 0, 0),
|
|
||||||
NULL);
|
|
||||||
if (!r) {
|
if (!r) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -912,8 +871,7 @@ wid_has_prop(const session_t *ps, xcb_window_t w, xcb_atom_t atom) {
|
||||||
/**
|
/**
|
||||||
* Get the numeric property value from a win_prop_t.
|
* Get the numeric property value from a win_prop_t.
|
||||||
*/
|
*/
|
||||||
static inline long
|
static inline long winprop_get_int(winprop_t prop) {
|
||||||
winprop_get_int(winprop_t prop) {
|
|
||||||
long tgt = 0;
|
long tgt = 0;
|
||||||
|
|
||||||
if (!prop.nitems)
|
if (!prop.nitems)
|
||||||
|
@ -923,21 +881,17 @@ winprop_get_int(winprop_t prop) {
|
||||||
case 8: tgt = *(prop.p8); break;
|
case 8: tgt = *(prop.p8); break;
|
||||||
case 16: tgt = *(prop.p16); break;
|
case 16: tgt = *(prop.p16); break;
|
||||||
case 32: tgt = *(prop.p32); break;
|
case 32: tgt = *(prop.p32); break;
|
||||||
default: assert(0);
|
default: assert(0); break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return tgt;
|
return tgt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void force_repaint(session_t *ps);
|
||||||
force_repaint(session_t *ps);
|
|
||||||
|
|
||||||
bool
|
bool vsync_init(session_t *ps);
|
||||||
vsync_init(session_t *ps);
|
|
||||||
|
|
||||||
void
|
void vsync_deinit(session_t *ps);
|
||||||
vsync_deinit(session_t *ps);
|
|
||||||
|
|
||||||
/** @name DBus handling
|
/** @name DBus handling
|
||||||
*/
|
*/
|
||||||
|
@ -946,31 +900,24 @@ vsync_deinit(session_t *ps);
|
||||||
/** @name DBus hooks
|
/** @name DBus hooks
|
||||||
*/
|
*/
|
||||||
///@{
|
///@{
|
||||||
void
|
void win_set_shadow_force(session_t *ps, win *w, switch_t val);
|
||||||
win_set_shadow_force(session_t *ps, win *w, switch_t val);
|
|
||||||
|
|
||||||
void
|
void win_set_fade_force(session_t *ps, win *w, switch_t val);
|
||||||
win_set_fade_force(session_t *ps, win *w, switch_t val);
|
|
||||||
|
|
||||||
void
|
void win_set_focused_force(session_t *ps, win *w, switch_t val);
|
||||||
win_set_focused_force(session_t *ps, win *w, switch_t val);
|
|
||||||
|
|
||||||
void
|
void win_set_invert_color_force(session_t *ps, win *w, switch_t val);
|
||||||
win_set_invert_color_force(session_t *ps, win *w, switch_t val);
|
|
||||||
|
|
||||||
void
|
void opts_init_track_focus(session_t *ps);
|
||||||
opts_init_track_focus(session_t *ps);
|
|
||||||
|
|
||||||
void
|
void opts_set_no_fading_openclose(session_t *ps, bool newval);
|
||||||
opts_set_no_fading_openclose(session_t *ps, bool newval);
|
|
||||||
//!@}
|
//!@}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a <code>bool</code> array of all wintypes to true.
|
* Set a <code>bool</code> array of all wintypes to true.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void wintype_arr_enable(bool arr[]) {
|
||||||
wintype_arr_enable(bool arr[]) {
|
|
||||||
wintype_t i;
|
wintype_t i;
|
||||||
|
|
||||||
for (i = 0; i < NUM_WINTYPES; ++i) {
|
for (i = 0; i < NUM_WINTYPES; ++i) {
|
||||||
|
|
818
src/compton.c
818
src/compton.c
File diff suppressed because it is too large
Load Diff
|
@ -6,24 +6,24 @@
|
||||||
|
|
||||||
// === Includes ===
|
// === Includes ===
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include "common.h"
|
|
||||||
#include "backend/backend.h"
|
#include "backend/backend.h"
|
||||||
#include "win.h"
|
|
||||||
#include "x.h"
|
|
||||||
#include "c2.h"
|
#include "c2.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "compiler.h"
|
||||||
|
#include "config.h"
|
||||||
#include "log.h" // XXX clean up
|
#include "log.h" // XXX clean up
|
||||||
#include "region.h"
|
#include "region.h"
|
||||||
#include "compiler.h"
|
#include "render.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "render.h"
|
#include "win.h"
|
||||||
#include "config.h"
|
#include "x.h"
|
||||||
|
|
||||||
// == Functions ==
|
// == Functions ==
|
||||||
// TODO move static inline functions that are only used in compton.c, into
|
// TODO move static inline functions that are only used in compton.c, into
|
||||||
|
@ -36,16 +36,14 @@ void add_damage(session_t *ps, const region_t *damage);
|
||||||
|
|
||||||
long determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode);
|
long determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode);
|
||||||
|
|
||||||
xcb_window_t
|
xcb_window_t find_client_win(session_t *ps, xcb_window_t w);
|
||||||
find_client_win(session_t *ps, xcb_window_t w);
|
|
||||||
|
|
||||||
win *find_toplevel2(session_t *ps, xcb_window_t wid);
|
win *find_toplevel2(session_t *ps, xcb_window_t wid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a <code>switch_t</code> array of all unset wintypes to true.
|
* Set a <code>switch_t</code> array of all unset wintypes to true.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void wintype_arr_enable_unset(switch_t arr[]) {
|
||||||
wintype_arr_enable_unset(switch_t arr[]) {
|
|
||||||
wintype_t i;
|
wintype_t i;
|
||||||
|
|
||||||
for (i = 0; i < NUM_WINTYPES; ++i)
|
for (i = 0; i < NUM_WINTYPES; ++i)
|
||||||
|
@ -60,8 +58,7 @@ wintype_arr_enable_unset(switch_t arr[]) {
|
||||||
* @param count amount of elements in the array
|
* @param count amount of elements in the array
|
||||||
* @param wid window ID to search for
|
* @param wid window ID to search for
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool array_wid_exists(const xcb_window_t *arr, int count, xcb_window_t wid) {
|
||||||
array_wid_exists(const xcb_window_t *arr, int count, xcb_window_t wid) {
|
|
||||||
while (count--) {
|
while (count--) {
|
||||||
if (arr[count] == wid) {
|
if (arr[count] == wid) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -74,24 +71,22 @@ array_wid_exists(const xcb_window_t *arr, int count, xcb_window_t wid) {
|
||||||
/**
|
/**
|
||||||
* Destroy a condition list.
|
* Destroy a condition list.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void free_wincondlst(c2_lptr_t **pcondlst) {
|
||||||
free_wincondlst(c2_lptr_t **pcondlst) {
|
|
||||||
while ((*pcondlst = c2_free_lptr(*pcondlst)))
|
while ((*pcondlst = c2_free_lptr(*pcondlst)))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_OPENGL
|
#ifndef CONFIG_OPENGL
|
||||||
static inline void
|
static inline void free_paint_glx(session_t *ps, paint_t *p) {
|
||||||
free_paint_glx(session_t *ps, paint_t *p) {}
|
}
|
||||||
static inline void
|
static inline void free_win_res_glx(session_t *ps, win *w) {
|
||||||
free_win_res_glx(session_t *ps, win *w) {}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a XTextProperty of a single string.
|
* Create a XTextProperty of a single string.
|
||||||
*/
|
*/
|
||||||
static inline XTextProperty *
|
static inline XTextProperty *make_text_prop(session_t *ps, char *str) {
|
||||||
make_text_prop(session_t *ps, char *str) {
|
|
||||||
XTextProperty *pprop = ccalloc(1, XTextProperty);
|
XTextProperty *pprop = ccalloc(1, XTextProperty);
|
||||||
|
|
||||||
if (XmbTextListToTextProperty(ps->dpy, &str, 1, XStringStyle, pprop)) {
|
if (XmbTextListToTextProperty(ps->dpy, &str, 1, XStringStyle, pprop)) {
|
||||||
|
@ -103,7 +98,6 @@ make_text_prop(session_t *ps, char *str) {
|
||||||
return pprop;
|
return pprop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a single-string text property on a window.
|
* Set a single-string text property on a window.
|
||||||
*/
|
*/
|
||||||
|
@ -125,8 +119,7 @@ wid_set_text_prop(session_t *ps, xcb_window_t wid, xcb_atom_t prop_atom, char *s
|
||||||
/**
|
/**
|
||||||
* Dump an drawable's info.
|
* Dump an drawable's info.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void dump_drawable(session_t *ps, xcb_drawable_t drawable) {
|
||||||
dump_drawable(session_t *ps, xcb_drawable_t drawable) {
|
|
||||||
auto r = xcb_get_geometry_reply(ps->c, xcb_get_geometry(ps->c, drawable), NULL);
|
auto r = xcb_get_geometry_reply(ps->c, xcb_get_geometry(ps->c, drawable), NULL);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
log_trace("Drawable %#010x: Failed", drawable);
|
log_trace("Drawable %#010x: Failed", drawable);
|
||||||
|
|
111
src/config.c
111
src/config.c
|
@ -2,22 +2,22 @@
|
||||||
// Copyright (c) 2011-2013, Christopher Jeffrey
|
// Copyright (c) 2011-2013, Christopher Jeffrey
|
||||||
// Copyright (c) 2013 Richard Grenville <pyxlcy@gmail.com>
|
// Copyright (c) 2013 Richard Grenville <pyxlcy@gmail.com>
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <xcb/render.h> // for xcb_render_fixed_t, XXX
|
#include <xcb/render.h> // for xcb_render_fixed_t, XXX
|
||||||
|
|
||||||
#include "compiler.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "c2.h"
|
#include "c2.h"
|
||||||
#include "string_utils.h"
|
#include "common.h"
|
||||||
|
#include "compiler.h"
|
||||||
|
#include "kernel.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "region.h"
|
#include "region.h"
|
||||||
|
#include "string_utils.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "kernel.h"
|
#include "utils.h"
|
||||||
#include "win.h"
|
#include "win.h"
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
@ -25,8 +25,7 @@
|
||||||
/**
|
/**
|
||||||
* Parse a long number.
|
* Parse a long number.
|
||||||
*/
|
*/
|
||||||
bool
|
bool parse_long(const char *s, long *dest) {
|
||||||
parse_long(const char *s, long *dest) {
|
|
||||||
const char *endptr = NULL;
|
const char *endptr = NULL;
|
||||||
long val = strtol(s, (char **)&endptr, 0);
|
long val = strtol(s, (char **)&endptr, 0);
|
||||||
if (!endptr || endptr == s) {
|
if (!endptr || endptr == s) {
|
||||||
|
@ -51,8 +50,7 @@ parse_long(const char *s, long *dest) {
|
||||||
* @param[out] dest return the number parsed from the string
|
* @param[out] dest return the number parsed from the string
|
||||||
* @return pointer to the last character parsed
|
* @return pointer to the last character parsed
|
||||||
*/
|
*/
|
||||||
const char *
|
const char *parse_readnum(const char *src, double *dest) {
|
||||||
parse_readnum(const char *src, double *dest) {
|
|
||||||
const char *pc = NULL;
|
const char *pc = NULL;
|
||||||
double val = strtod_simple(src, &pc);
|
double val = strtod_simple(src, &pc);
|
||||||
if (!pc || pc == src) {
|
if (!pc || pc == src) {
|
||||||
|
@ -73,8 +71,7 @@ parse_readnum(const char *src, double *dest) {
|
||||||
* @param[out] endptr return where the end of kernel is in the string
|
* @param[out] endptr return where the end of kernel is in the string
|
||||||
* @param[out] hasneg whether the kernel has negative values
|
* @param[out] hasneg whether the kernel has negative values
|
||||||
*/
|
*/
|
||||||
conv *
|
conv *parse_blur_kern(const char *src, const char **endptr, bool *hasneg) {
|
||||||
parse_blur_kern(const char *src, const char **endptr, bool *hasneg) {
|
|
||||||
int width = 0, height = 0;
|
int width = 0, height = 0;
|
||||||
*hasneg = false;
|
*hasneg = false;
|
||||||
|
|
||||||
|
@ -172,8 +169,7 @@ err1:
|
||||||
* @param[out] hasneg whether any of the kernels have negative values
|
* @param[out] hasneg whether any of the kernels have negative values
|
||||||
* @return if the `src` string is a valid kernel list string
|
* @return if the `src` string is a valid kernel list string
|
||||||
*/
|
*/
|
||||||
bool
|
bool parse_blur_kern_lst(const char *src, conv **dest, int max, bool *hasneg) {
|
||||||
parse_blur_kern_lst(const char *src, conv **dest, int max, bool *hasneg) {
|
|
||||||
// TODO just return a predefined kernels, not parse predefined strings...
|
// TODO just return a predefined kernels, not parse predefined strings...
|
||||||
static const struct {
|
static const struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
@ -181,19 +177,59 @@ parse_blur_kern_lst(const char *src, conv **dest, int max, bool *hasneg) {
|
||||||
} CONV_KERN_PREDEF[] = {
|
} CONV_KERN_PREDEF[] = {
|
||||||
{"3x3box", "3,3,1,1,1,1,1,1,1,1,"},
|
{"3x3box", "3,3,1,1,1,1,1,1,1,1,"},
|
||||||
{"5x5box", "5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,"},
|
{"5x5box", "5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,"},
|
||||||
{ "7x7box", "7,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1," },
|
{"7x7box", "7,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,"
|
||||||
{ "3x3gaussian", "3,3,0.243117,0.493069,0.243117,0.493069,0.493069,0.243117,0.493069,0.243117," },
|
"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,"},
|
||||||
{ "5x5gaussian", "5,5,0.003493,0.029143,0.059106,0.029143,0.003493,0.029143,0.243117,0.493069,0.243117,0.029143,0.059106,0.493069,0.493069,0.059106,0.029143,0.243117,0.493069,0.243117,0.029143,0.003493,0.029143,0.059106,0.029143,0.003493," },
|
{"3x3gaussian", "3,3,0.243117,0.493069,0.243117,0.493069,0.493069,0.243117,0."
|
||||||
{ "7x7gaussian", "7,7,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003,0.000102,0.003493,0.029143,0.059106,0.029143,0.003493,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.003493,0.029143,0.059106,0.029143,0.003493,0.000102,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003," },
|
"493069,0.243117,"},
|
||||||
{ "9x9gaussian", "9,9,0.000000,0.000000,0.000001,0.000006,0.000012,0.000006,0.000001,0.000000,0.000000,0.000000,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003,0.000000,0.000001,0.000102,0.003493,0.029143,0.059106,0.029143,0.003493,0.000102,0.000001,0.000006,0.000849,0.029143,0.243117,0.493069,0.243117,0.029143,0.000849,0.000006,0.000012,0.001723,0.059106,0.493069,0.493069,0.059106,0.001723,0.000012,0.000006,0.000849,0.029143,0.243117,0.493069,0.243117,0.029143,0.000849,0.000006,0.000001,0.000102,0.003493,0.029143,0.059106,0.029143,0.003493,0.000102,0.000001,0.000000,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003,0.000000,0.000000,0.000000,0.000001,0.000006,0.000012,0.000006,0.000001,0.000000,0.000000," },
|
{"5x5gaussian", "5,5,0.003493,0.029143,0.059106,0.029143,0.003493,0.029143,0."
|
||||||
{ "11x11gaussian", "11,11,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000001,0.000006,0.000012,0.000006,0.000001,0.000000,0.000000,0.000000,0.000000,0.000000,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003,0.000000,0.000000,0.000000,0.000001,0.000102,0.003493,0.029143,0.059106,0.029143,0.003493,0.000102,0.000001,0.000000,0.000000,0.000006,0.000849,0.029143,0.243117,0.493069,0.243117,0.029143,0.000849,0.000006,0.000000,0.000000,0.000012,0.001723,0.059106,0.493069,0.493069,0.059106,0.001723,0.000012,0.000000,0.000000,0.000006,0.000849,0.029143,0.243117,0.493069,0.243117,0.029143,0.000849,0.000006,0.000000,0.000000,0.000001,0.000102,0.003493,0.029143,0.059106,0.029143,0.003493,0.000102,0.000001,0.000000,0.000000,0.000000,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003,0.000000,0.000000,0.000000,0.000000,0.000000,0.000001,0.000006,0.000012,0.000006,0.000001,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000," },
|
"243117,0.493069,0.243117,0.029143,0.059106,0.493069,0."
|
||||||
|
"493069,0.059106,0.029143,0.243117,0.493069,0.243117,0."
|
||||||
|
"029143,0.003493,0.029143,0.059106,0.029143,0.003493,"},
|
||||||
|
{"7x7gaussian", "7,7,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0."
|
||||||
|
"000003,0.000102,0.003493,0.029143,0.059106,0.029143,0."
|
||||||
|
"003493,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.003493,0."
|
||||||
|
"029143,0.059106,0.029143,0.003493,0.000102,0.000003,0."
|
||||||
|
"000102,0.000849,0.001723,0.000849,0.000102,0.000003,"},
|
||||||
|
{"9x9gaussian",
|
||||||
|
"9,9,0.000000,0.000000,0.000001,0.000006,0.000012,0.000006,0.000001,0."
|
||||||
|
"000000,0.000000,0.000000,0.000003,0.000102,0.000849,0.001723,0.000849,0."
|
||||||
|
"000102,0.000003,0.000000,0.000001,0.000102,0.003493,0.029143,0.059106,0."
|
||||||
|
"029143,0.003493,0.000102,0.000001,0.000006,0.000849,0.029143,0.243117,0."
|
||||||
|
"493069,0.243117,0.029143,0.000849,0.000006,0.000012,0.001723,0.059106,0."
|
||||||
|
"493069,0.493069,0.059106,0.001723,0.000012,0.000006,0.000849,0.029143,0."
|
||||||
|
"243117,0.493069,0.243117,0.029143,0.000849,0.000006,0.000001,0.000102,0."
|
||||||
|
"003493,0.029143,0.059106,0.029143,0.003493,0.000102,0.000001,0.000000,0."
|
||||||
|
"000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003,0.000000,0."
|
||||||
|
"000000,0.000000,0.000001,0.000006,0.000012,0.000006,0.000001,0.000000,0."
|
||||||
|
"000000,"},
|
||||||
|
{"11x11gaussian",
|
||||||
|
"11,11,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0."
|
||||||
|
"000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000001,0."
|
||||||
|
"000006,0.000012,0.000006,0.000001,0.000000,0.000000,0.000000,0.000000,0."
|
||||||
|
"000000,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003,0."
|
||||||
|
"000000,0.000000,0.000000,0.000001,0.000102,0.003493,0.029143,0.059106,0."
|
||||||
|
"029143,0.003493,0.000102,0.000001,0.000000,0.000000,0.000006,0.000849,0."
|
||||||
|
"029143,0.243117,0.493069,0.243117,0.029143,0.000849,0.000006,0.000000,0."
|
||||||
|
"000000,0.000012,0.001723,0.059106,0.493069,0.493069,0.059106,0.001723,0."
|
||||||
|
"000012,0.000000,0.000000,0.000006,0.000849,0.029143,0.243117,0.493069,0."
|
||||||
|
"243117,0.029143,0.000849,0.000006,0.000000,0.000000,0.000001,0.000102,0."
|
||||||
|
"003493,0.029143,0.059106,0.029143,0.003493,0.000102,0.000001,0.000000,0."
|
||||||
|
"000000,0.000000,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0."
|
||||||
|
"000003,0.000000,0.000000,0.000000,0.000000,0.000000,0.000001,0.000006,0."
|
||||||
|
"000012,0.000006,0.000001,0.000000,0.000000,0.000000,0.000000,0.000000,0."
|
||||||
|
"000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0."
|
||||||
|
"000000,"},
|
||||||
};
|
};
|
||||||
|
|
||||||
*hasneg = false;
|
*hasneg = false;
|
||||||
for (unsigned int i = 0;
|
for (unsigned int i = 0;
|
||||||
i < sizeof(CONV_KERN_PREDEF) / sizeof(CONV_KERN_PREDEF[0]); ++i) {
|
i < sizeof(CONV_KERN_PREDEF) / sizeof(CONV_KERN_PREDEF[0]); ++i) {
|
||||||
if (!strcmp(CONV_KERN_PREDEF[i].name, src))
|
if (!strcmp(CONV_KERN_PREDEF[i].name, src))
|
||||||
return parse_blur_kern_lst(CONV_KERN_PREDEF[i].kern_str, dest, max, hasneg);
|
return parse_blur_kern_lst(CONV_KERN_PREDEF[i].kern_str, dest,
|
||||||
|
max, hasneg);
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -218,8 +254,10 @@ parse_blur_kern_lst(const char *src, conv **dest, int max, bool *hasneg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i > 1) {
|
if (i > 1) {
|
||||||
log_warn("You are seeing this message because your are using multipassblur. Please "
|
log_warn("You are seeing this message because your are using "
|
||||||
"report an issue to us so we know multipass blur is actually been used. "
|
"multipassblur. Please "
|
||||||
|
"report an issue to us so we know multipass blur is actually "
|
||||||
|
"been used. "
|
||||||
"Otherwise it might be removed in future releases");
|
"Otherwise it might be removed in future releases");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,8 +274,7 @@ parse_blur_kern_lst(const char *src, conv **dest, int max, bool *hasneg) {
|
||||||
*
|
*
|
||||||
* ps->root_width and ps->root_height must be valid
|
* ps->root_width and ps->root_height must be valid
|
||||||
*/
|
*/
|
||||||
bool
|
bool parse_geometry(session_t *ps, const char *src, region_t *dest) {
|
||||||
parse_geometry(session_t *ps, const char *src, region_t *dest) {
|
|
||||||
pixman_region32_clear(dest);
|
pixman_region32_clear(dest);
|
||||||
if (!src)
|
if (!src)
|
||||||
return true;
|
return true;
|
||||||
|
@ -351,8 +388,7 @@ bool parse_rule_opacity(c2_lptr_t **res, const char *src) {
|
||||||
/**
|
/**
|
||||||
* Add a pattern to a condition linked list.
|
* Add a pattern to a condition linked list.
|
||||||
*/
|
*/
|
||||||
bool
|
bool condlst_add(c2_lptr_t **pcondlst, const char *pattern) {
|
||||||
condlst_add(c2_lptr_t **pcondlst, const char *pattern) {
|
|
||||||
if (!pattern)
|
if (!pattern)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -362,7 +398,8 @@ condlst_add(c2_lptr_t **pcondlst, const char *pattern) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_default_winopts(options_t *opt, win_option_mask_t *mask, bool shadow_enable, bool fading_enable) {
|
void set_default_winopts(options_t *opt, win_option_mask_t *mask, bool shadow_enable,
|
||||||
|
bool fading_enable) {
|
||||||
// Apply default wintype options.
|
// Apply default wintype options.
|
||||||
if (!mask[WINTYPE_DESKTOP].shadow) {
|
if (!mask[WINTYPE_DESKTOP].shadow) {
|
||||||
// Desktop windows are always drawn without shadow by default.
|
// Desktop windows are always drawn without shadow by default.
|
||||||
|
@ -372,8 +409,7 @@ void set_default_winopts(options_t *opt, win_option_mask_t *mask, bool shadow_en
|
||||||
|
|
||||||
// Focused/unfocused state only apply to a few window types, all other windows
|
// Focused/unfocused state only apply to a few window types, all other windows
|
||||||
// are always considered focused.
|
// are always considered focused.
|
||||||
const wintype_t nofocus_type[] =
|
const wintype_t nofocus_type[] = {WINTYPE_UNKNOWN, WINTYPE_NORMAL, WINTYPE_UTILITY};
|
||||||
{ WINTYPE_UNKNOWN, WINTYPE_NORMAL, WINTYPE_UTILITY };
|
|
||||||
for (unsigned long i = 0; i < ARR_SIZE(nofocus_type); i++) {
|
for (unsigned long i = 0; i < ARR_SIZE(nofocus_type); i++) {
|
||||||
if (!mask[nofocus_type[i]].focus) {
|
if (!mask[nofocus_type[i]].focus) {
|
||||||
mask[nofocus_type[i]].focus = true;
|
mask[nofocus_type[i]].focus = true;
|
||||||
|
@ -403,16 +439,15 @@ void set_default_winopts(options_t *opt, win_option_mask_t *mask, bool shadow_en
|
||||||
}
|
}
|
||||||
if (!mask[i].opacity) {
|
if (!mask[i].opacity) {
|
||||||
mask[i].opacity = true;
|
mask[i].opacity = true;
|
||||||
// Opacity is not set to a concrete number here because the opacity logic
|
// Opacity is not set to a concrete number here because the
|
||||||
// is complicated, and needs an "unset" state
|
// opacity logic is complicated, and needs an "unset" state
|
||||||
opt->wintype_option[i].opacity = NAN;
|
opt->wintype_option[i].opacity = NAN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *parse_config(options_t *opt, const char *config_file,
|
char *parse_config(options_t *opt, const char *config_file, bool *shadow_enable,
|
||||||
bool *shadow_enable, bool *fading_enable, bool *hasneg,
|
bool *fading_enable, bool *hasneg, win_option_mask_t *winopt_mask) {
|
||||||
win_option_mask_t *winopt_mask) {
|
|
||||||
char *ret = NULL;
|
char *ret = NULL;
|
||||||
#ifdef CONFIG_LIBCONFIG
|
#ifdef CONFIG_LIBCONFIG
|
||||||
ret = parse_config_libconfig(opt, config_file, shadow_enable, fading_enable,
|
ret = parse_config_libconfig(opt, config_file, shadow_enable, fading_enable,
|
||||||
|
|
17
src/config.h
17
src/config.h
|
@ -7,24 +7,24 @@
|
||||||
/// Common functions and definitions for configuration parsing
|
/// Common functions and definitions for configuration parsing
|
||||||
/// Used for command line arguments and config files
|
/// Used for command line arguments and config files
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <xcb/xcb.h>
|
|
||||||
#include <xcb/render.h> // for xcb_render_fixed_t, XXX
|
#include <xcb/render.h> // for xcb_render_fixed_t, XXX
|
||||||
|
#include <xcb/xcb.h>
|
||||||
#include <xcb/xfixes.h>
|
#include <xcb/xfixes.h>
|
||||||
|
|
||||||
#ifdef CONFIG_LIBCONFIG
|
#ifdef CONFIG_LIBCONFIG
|
||||||
#include <libconfig.h>
|
#include <libconfig.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "region.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "compiler.h"
|
#include "compiler.h"
|
||||||
#include "win.h"
|
|
||||||
#include "types.h"
|
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "region.h"
|
||||||
|
#include "types.h"
|
||||||
|
#include "win.h"
|
||||||
|
|
||||||
typedef struct session session_t;
|
typedef struct session session_t;
|
||||||
|
|
||||||
|
@ -242,8 +242,7 @@ extern const char *const VSYNC_STRS[NUM_VSYNC + 1];
|
||||||
extern const char *const BACKEND_STRS[NUM_BKEND + 1];
|
extern const char *const BACKEND_STRS[NUM_BKEND + 1];
|
||||||
|
|
||||||
attr_warn_unused_result bool parse_long(const char *, long *);
|
attr_warn_unused_result bool parse_long(const char *, long *);
|
||||||
attr_warn_unused_result bool
|
attr_warn_unused_result bool parse_blur_kern_lst(const char *, conv **, int, bool *hasneg);
|
||||||
parse_blur_kern_lst(const char *, conv **, int, bool *hasneg);
|
|
||||||
attr_warn_unused_result bool parse_geometry(session_t *, const char *, region_t *);
|
attr_warn_unused_result bool parse_geometry(session_t *, const char *, region_t *);
|
||||||
attr_warn_unused_result bool parse_rule_opacity(c2_lptr_t **, const char *);
|
attr_warn_unused_result bool parse_rule_opacity(c2_lptr_t **, const char *);
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
// Copyright (c) 2012-2014 Richard Grenville <pyxlcy@gmail.com>
|
// Copyright (c) 2012-2014 Richard Grenville <pyxlcy@gmail.com>
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <libgen.h>
|
|
||||||
#include <libconfig.h>
|
|
||||||
#include <basedir_fs.h>
|
#include <basedir_fs.h>
|
||||||
|
#include <libconfig.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
|
||||||
#include "err.h"
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "compiler.h"
|
#include "compiler.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "string_utils.h"
|
#include "err.h"
|
||||||
#include "options.h"
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "options.h"
|
||||||
|
#include "string_utils.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "win.h"
|
#include "win.h"
|
||||||
|
|
||||||
|
@ -27,8 +27,7 @@
|
||||||
*
|
*
|
||||||
* So it takes a pointer to bool.
|
* So it takes a pointer to bool.
|
||||||
*/
|
*/
|
||||||
static inline int
|
static inline int lcfg_lookup_bool(const config_t *config, const char *path, bool *value) {
|
||||||
lcfg_lookup_bool(const config_t *config, const char *path, bool *value) {
|
|
||||||
int ival;
|
int ival;
|
||||||
|
|
||||||
int ret = config_lookup_bool(config, path, &ival);
|
int ret = config_lookup_bool(config, path, &ival);
|
||||||
|
@ -39,12 +38,8 @@ lcfg_lookup_bool(const config_t *config, const char *path, bool *value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Search for config file under a base directory
|
/// Search for config file under a base directory
|
||||||
FILE *
|
FILE *open_config_file_at(const char *base, char **out_path) {
|
||||||
open_config_file_at(const char *base, char **out_path) {
|
static const char *config_paths[] = {"/compton.conf", "/compton/compton.conf"};
|
||||||
static const char *config_paths[] = {
|
|
||||||
"/compton.conf",
|
|
||||||
"/compton/compton.conf"
|
|
||||||
};
|
|
||||||
for (size_t i = 0; i < ARR_SIZE(config_paths); i++) {
|
for (size_t i = 0; i < ARR_SIZE(config_paths); i++) {
|
||||||
char *path = mstrjoin(base, config_paths[i]);
|
char *path = mstrjoin(base, config_paths[i]);
|
||||||
FILE *ret = fopen(path, "r");
|
FILE *ret = fopen(path, "r");
|
||||||
|
@ -65,8 +60,7 @@ open_config_file_at(const char *base, char **out_path) {
|
||||||
*
|
*
|
||||||
* Follows the XDG specification to search for the configuration file.
|
* Follows the XDG specification to search for the configuration file.
|
||||||
*/
|
*/
|
||||||
FILE *
|
FILE *open_config_file(const char *cpath, char **ppath) {
|
||||||
open_config_file(const char *cpath, char **ppath) {
|
|
||||||
static const char config_filename_legacy[] = "/.compton.conf";
|
static const char config_filename_legacy[] = "/.compton.conf";
|
||||||
|
|
||||||
if (cpath) {
|
if (cpath) {
|
||||||
|
@ -116,16 +110,15 @@ open_config_file(const char *cpath, char **ppath) {
|
||||||
/**
|
/**
|
||||||
* Parse a condition list in configuration file.
|
* Parse a condition list in configuration file.
|
||||||
*/
|
*/
|
||||||
void
|
void parse_cfg_condlst(const config_t *pcfg, c2_lptr_t **pcondlst, const char *name) {
|
||||||
parse_cfg_condlst(const config_t *pcfg, c2_lptr_t **pcondlst,
|
|
||||||
const char *name) {
|
|
||||||
config_setting_t *setting = config_lookup(pcfg, name);
|
config_setting_t *setting = config_lookup(pcfg, name);
|
||||||
if (setting) {
|
if (setting) {
|
||||||
// Parse an array of options
|
// Parse an array of options
|
||||||
if (config_setting_is_array(setting)) {
|
if (config_setting_is_array(setting)) {
|
||||||
int i = config_setting_length(setting);
|
int i = config_setting_length(setting);
|
||||||
while (i--)
|
while (i--)
|
||||||
condlst_add(pcondlst, config_setting_get_string_elem(setting, i));
|
condlst_add(pcondlst,
|
||||||
|
config_setting_get_string_elem(setting, i));
|
||||||
}
|
}
|
||||||
// Treat it as a single pattern if it's a string
|
// Treat it as a single pattern if it's a string
|
||||||
else if (CONFIG_TYPE_STRING == config_setting_type(setting)) {
|
else if (CONFIG_TYPE_STRING == config_setting_type(setting)) {
|
||||||
|
@ -145,13 +138,15 @@ parse_cfg_condlst_opct(options_t *opt, const config_t *pcfg, const char *name) {
|
||||||
if (config_setting_is_array(setting)) {
|
if (config_setting_is_array(setting)) {
|
||||||
int i = config_setting_length(setting);
|
int i = config_setting_length(setting);
|
||||||
while (i--)
|
while (i--)
|
||||||
if (!parse_rule_opacity(&opt->opacity_rules,
|
if (!parse_rule_opacity(
|
||||||
|
&opt->opacity_rules,
|
||||||
config_setting_get_string_elem(setting, i)))
|
config_setting_get_string_elem(setting, i)))
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
// Treat it as a single pattern if it's a string
|
// Treat it as a single pattern if it's a string
|
||||||
else if (config_setting_type(setting) == CONFIG_TYPE_STRING) {
|
else if (config_setting_type(setting) == CONFIG_TYPE_STRING) {
|
||||||
if (!parse_rule_opacity(&opt->opacity_rules, config_setting_get_string(setting)))
|
if (!parse_rule_opacity(&opt->opacity_rules,
|
||||||
|
config_setting_get_string(setting)))
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,8 +158,8 @@ parse_cfg_condlst_opct(options_t *opt, const config_t *pcfg, const char *name) {
|
||||||
* Returns the actually config_file name
|
* Returns the actually config_file name
|
||||||
*/
|
*/
|
||||||
char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shadow_enable,
|
char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shadow_enable,
|
||||||
bool *fading_enable, bool *conv_kern_hasneg, win_option_mask_t *winopt_mask)
|
bool *fading_enable, bool *conv_kern_hasneg,
|
||||||
{
|
win_option_mask_t *winopt_mask) {
|
||||||
char *path = NULL;
|
char *path = NULL;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
config_t cfg;
|
config_t cfg;
|
||||||
|
@ -203,7 +198,8 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad
|
||||||
fclose(f);
|
fclose(f);
|
||||||
f = NULL;
|
f = NULL;
|
||||||
if (read_result == CONFIG_FALSE) {
|
if (read_result == CONFIG_FALSE) {
|
||||||
log_fatal("Error when reading configuration file \"%s\", line %d: %s",
|
log_fatal("Error when reading configuration file \"%s\", line "
|
||||||
|
"%d: %s",
|
||||||
path, config_error_line(&cfg), config_error_text(&cfg));
|
path, config_error_line(&cfg), config_error_text(&cfg));
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -257,8 +253,10 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad
|
||||||
};
|
};
|
||||||
// -m (menu_opacity)
|
// -m (menu_opacity)
|
||||||
if (config_lookup_float(&cfg, "menu-opacity", &dval)) {
|
if (config_lookup_float(&cfg, "menu-opacity", &dval)) {
|
||||||
log_warn("Option `menu-opacity` is deprecated, and will be removed.Please use the "
|
log_warn("Option `menu-opacity` is deprecated, and will be "
|
||||||
"wintype option `opacity` of `popup_menu` and `dropdown_menu` instead.");
|
"removed.Please use the "
|
||||||
|
"wintype option `opacity` of `popup_menu` and `dropdown_menu` "
|
||||||
|
"instead.");
|
||||||
opt->wintype_option[WINTYPE_DROPDOWN_MENU].opacity = dval;
|
opt->wintype_option[WINTYPE_DROPDOWN_MENU].opacity = dval;
|
||||||
opt->wintype_option[WINTYPE_POPUP_MENU].opacity = dval;
|
opt->wintype_option[WINTYPE_POPUP_MENU].opacity = dval;
|
||||||
winopt_mask[WINTYPE_DROPDOWN_MENU].opacity = true;
|
winopt_mask[WINTYPE_DROPDOWN_MENU].opacity = true;
|
||||||
|
@ -270,8 +268,7 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad
|
||||||
// --no-fading-open-close
|
// --no-fading-open-close
|
||||||
lcfg_lookup_bool(&cfg, "no-fading-openclose", &opt->no_fading_openclose);
|
lcfg_lookup_bool(&cfg, "no-fading-openclose", &opt->no_fading_openclose);
|
||||||
// --no-fading-destroyed-argb
|
// --no-fading-destroyed-argb
|
||||||
lcfg_lookup_bool(&cfg, "no-fading-destroyed-argb",
|
lcfg_lookup_bool(&cfg, "no-fading-destroyed-argb", &opt->no_fading_destroyed_argb);
|
||||||
&opt->no_fading_destroyed_argb);
|
|
||||||
// --shadow-red
|
// --shadow-red
|
||||||
config_lookup_float(&cfg, "shadow-red", &opt->shadow_red);
|
config_lookup_float(&cfg, "shadow-red", &opt->shadow_red);
|
||||||
// --shadow-green
|
// --shadow-green
|
||||||
|
@ -282,27 +279,21 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad
|
||||||
if (config_lookup_string(&cfg, "shadow-exclude-reg", &sval))
|
if (config_lookup_string(&cfg, "shadow-exclude-reg", &sval))
|
||||||
opt->shadow_exclude_reg_str = strdup(sval);
|
opt->shadow_exclude_reg_str = strdup(sval);
|
||||||
// --inactive-opacity-override
|
// --inactive-opacity-override
|
||||||
lcfg_lookup_bool(&cfg, "inactive-opacity-override",
|
lcfg_lookup_bool(&cfg, "inactive-opacity-override", &opt->inactive_opacity_override);
|
||||||
&opt->inactive_opacity_override);
|
|
||||||
// --inactive-dim
|
// --inactive-dim
|
||||||
config_lookup_float(&cfg, "inactive-dim", &opt->inactive_dim);
|
config_lookup_float(&cfg, "inactive-dim", &opt->inactive_dim);
|
||||||
// --mark-wmwin-focused
|
// --mark-wmwin-focused
|
||||||
lcfg_lookup_bool(&cfg, "mark-wmwin-focused", &opt->mark_wmwin_focused);
|
lcfg_lookup_bool(&cfg, "mark-wmwin-focused", &opt->mark_wmwin_focused);
|
||||||
// --mark-ovredir-focused
|
// --mark-ovredir-focused
|
||||||
lcfg_lookup_bool(&cfg, "mark-ovredir-focused",
|
lcfg_lookup_bool(&cfg, "mark-ovredir-focused", &opt->mark_ovredir_focused);
|
||||||
&opt->mark_ovredir_focused);
|
|
||||||
// --shadow-ignore-shaped
|
// --shadow-ignore-shaped
|
||||||
lcfg_lookup_bool(&cfg, "shadow-ignore-shaped",
|
lcfg_lookup_bool(&cfg, "shadow-ignore-shaped", &opt->shadow_ignore_shaped);
|
||||||
&opt->shadow_ignore_shaped);
|
|
||||||
// --detect-rounded-corners
|
// --detect-rounded-corners
|
||||||
lcfg_lookup_bool(&cfg, "detect-rounded-corners",
|
lcfg_lookup_bool(&cfg, "detect-rounded-corners", &opt->detect_rounded_corners);
|
||||||
&opt->detect_rounded_corners);
|
|
||||||
// --xinerama-shadow-crop
|
// --xinerama-shadow-crop
|
||||||
lcfg_lookup_bool(&cfg, "xinerama-shadow-crop",
|
lcfg_lookup_bool(&cfg, "xinerama-shadow-crop", &opt->xinerama_shadow_crop);
|
||||||
&opt->xinerama_shadow_crop);
|
|
||||||
// --detect-client-opacity
|
// --detect-client-opacity
|
||||||
lcfg_lookup_bool(&cfg, "detect-client-opacity",
|
lcfg_lookup_bool(&cfg, "detect-client-opacity", &opt->detect_client_opacity);
|
||||||
&opt->detect_client_opacity);
|
|
||||||
// --refresh-rate
|
// --refresh-rate
|
||||||
config_lookup_int(&cfg, "refresh-rate", &opt->refresh_rate);
|
config_lookup_int(&cfg, "refresh-rate", &opt->refresh_rate);
|
||||||
// --vsync
|
// --vsync
|
||||||
|
@ -333,18 +324,17 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad
|
||||||
// --log-file
|
// --log-file
|
||||||
if (config_lookup_string(&cfg, "log-file", &sval)) {
|
if (config_lookup_string(&cfg, "log-file", &sval)) {
|
||||||
if (*sval != '/') {
|
if (*sval != '/') {
|
||||||
log_warn("The log-file in your configuration file is not an absolute path");
|
log_warn("The log-file in your configuration file is not an "
|
||||||
|
"absolute path");
|
||||||
}
|
}
|
||||||
opt->logpath = strdup(sval);
|
opt->logpath = strdup(sval);
|
||||||
}
|
}
|
||||||
// --sw-opti
|
// --sw-opti
|
||||||
lcfg_lookup_bool(&cfg, "sw-opti", &opt->sw_opti);
|
lcfg_lookup_bool(&cfg, "sw-opti", &opt->sw_opti);
|
||||||
// --use-ewmh-active-win
|
// --use-ewmh-active-win
|
||||||
lcfg_lookup_bool(&cfg, "use-ewmh-active-win",
|
lcfg_lookup_bool(&cfg, "use-ewmh-active-win", &opt->use_ewmh_active_win);
|
||||||
&opt->use_ewmh_active_win);
|
|
||||||
// --unredir-if-possible
|
// --unredir-if-possible
|
||||||
lcfg_lookup_bool(&cfg, "unredir-if-possible",
|
lcfg_lookup_bool(&cfg, "unredir-if-possible", &opt->unredir_if_possible);
|
||||||
&opt->unredir_if_possible);
|
|
||||||
// --unredir-if-possible-delay
|
// --unredir-if-possible-delay
|
||||||
if (config_lookup_int(&cfg, "unredir-if-possible-delay", &ival))
|
if (config_lookup_int(&cfg, "unredir-if-possible-delay", &ival))
|
||||||
opt->unredir_if_possible_delay = ival;
|
opt->unredir_if_possible_delay = ival;
|
||||||
|
@ -353,8 +343,7 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad
|
||||||
// --detect-transient
|
// --detect-transient
|
||||||
lcfg_lookup_bool(&cfg, "detect-transient", &opt->detect_transient);
|
lcfg_lookup_bool(&cfg, "detect-transient", &opt->detect_transient);
|
||||||
// --detect-client-leader
|
// --detect-client-leader
|
||||||
lcfg_lookup_bool(&cfg, "detect-client-leader",
|
lcfg_lookup_bool(&cfg, "detect-client-leader", &opt->detect_client_leader);
|
||||||
&opt->detect_client_leader);
|
|
||||||
// --shadow-exclude
|
// --shadow-exclude
|
||||||
parse_cfg_condlst(&cfg, &opt->shadow_blacklist, "shadow-exclude");
|
parse_cfg_condlst(&cfg, &opt->shadow_blacklist, "shadow-exclude");
|
||||||
// --fade-exclude
|
// --fade-exclude
|
||||||
|
@ -368,15 +357,14 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad
|
||||||
// --opacity-rule
|
// --opacity-rule
|
||||||
parse_cfg_condlst_opct(opt, &cfg, "opacity-rule");
|
parse_cfg_condlst_opct(opt, &cfg, "opacity-rule");
|
||||||
// --unredir-if-possible-exclude
|
// --unredir-if-possible-exclude
|
||||||
parse_cfg_condlst(&cfg, &opt->unredir_if_possible_blacklist, "unredir-if-possible-exclude");
|
parse_cfg_condlst(&cfg, &opt->unredir_if_possible_blacklist,
|
||||||
|
"unredir-if-possible-exclude");
|
||||||
// --blur-background
|
// --blur-background
|
||||||
lcfg_lookup_bool(&cfg, "blur-background", &opt->blur_background);
|
lcfg_lookup_bool(&cfg, "blur-background", &opt->blur_background);
|
||||||
// --blur-background-frame
|
// --blur-background-frame
|
||||||
lcfg_lookup_bool(&cfg, "blur-background-frame",
|
lcfg_lookup_bool(&cfg, "blur-background-frame", &opt->blur_background_frame);
|
||||||
&opt->blur_background_frame);
|
|
||||||
// --blur-background-fixed
|
// --blur-background-fixed
|
||||||
lcfg_lookup_bool(&cfg, "blur-background-fixed",
|
lcfg_lookup_bool(&cfg, "blur-background-fixed", &opt->blur_background_fixed);
|
||||||
&opt->blur_background_fixed);
|
|
||||||
// --blur-kern
|
// --blur-kern
|
||||||
if (config_lookup_string(&cfg, "blur-kern", &sval) &&
|
if (config_lookup_string(&cfg, "blur-kern", &sval) &&
|
||||||
!parse_blur_kern_lst(sval, opt->blur_kerns, MAX_BLUR_PASS, conv_kern_hasneg)) {
|
!parse_blur_kern_lst(sval, opt->blur_kerns, MAX_BLUR_PASS, conv_kern_hasneg)) {
|
||||||
|
@ -399,7 +387,8 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad
|
||||||
}
|
}
|
||||||
// --glx-use-gpushader4
|
// --glx-use-gpushader4
|
||||||
if (config_lookup_bool(&cfg, "glx-use-gpushader4", &ival) && ival) {
|
if (config_lookup_bool(&cfg, "glx-use-gpushader4", &ival) && ival) {
|
||||||
log_warn("glx-use-gpushader4 is deprecated since v6, please remove it from"
|
log_warn("glx-use-gpushader4 is deprecated since v6, please remove it "
|
||||||
|
"from"
|
||||||
"your config file");
|
"your config file");
|
||||||
}
|
}
|
||||||
// --xrender-sync
|
// --xrender-sync
|
||||||
|
@ -421,7 +410,8 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad
|
||||||
log_warn("\"alpha-step\" has been removed, compton now tries to make use"
|
log_warn("\"alpha-step\" has been removed, compton now tries to make use"
|
||||||
" of all alpha values");
|
" of all alpha values");
|
||||||
|
|
||||||
const char *deprecation_message = "has been removed. If you encounter problems "
|
const char *deprecation_message =
|
||||||
|
"has been removed. If you encounter problems "
|
||||||
"without this feature, please feel free to open a bug report";
|
"without this feature, please feel free to open a bug report";
|
||||||
if (lcfg_lookup_bool(&cfg, "glx-use-copysubbuffermesa", &bval) && bval)
|
if (lcfg_lookup_bool(&cfg, "glx-use-copysubbuffermesa", &bval) && bval)
|
||||||
log_warn("\"glx-use-copysubbuffermesa\" %s", deprecation_message);
|
log_warn("\"glx-use-copysubbuffermesa\" %s", deprecation_message);
|
||||||
|
|
309
src/dbus.c
309
src/dbus.c
|
@ -9,23 +9,23 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <xcb/xcb.h>
|
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "config.h"
|
|
||||||
#include "compiler.h"
|
#include "compiler.h"
|
||||||
#include "utils.h"
|
#include "config.h"
|
||||||
#include "types.h"
|
|
||||||
#include "win.h"
|
|
||||||
#include "string_utils.h"
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "string_utils.h"
|
||||||
|
#include "types.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "win.h"
|
||||||
|
|
||||||
#include "dbus.h"
|
#include "dbus.h"
|
||||||
|
|
||||||
|
@ -52,7 +52,8 @@ typedef uint16_t cdbus_enum_t;
|
||||||
#define CDBUS_ERROR_UNKNOWN CDBUS_ERROR_PREFIX ".unknown"
|
#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_UNKNOWN_S "Well, I don't know what happened. Do you?"
|
||||||
#define CDBUS_ERROR_BADMSG CDBUS_ERROR_PREFIX ".bad_message"
|
#define CDBUS_ERROR_BADMSG CDBUS_ERROR_PREFIX ".bad_message"
|
||||||
#define CDBUS_ERROR_BADMSG_S "Unrecognized command. Beware compton " \
|
#define CDBUS_ERROR_BADMSG_S \
|
||||||
|
"Unrecognized command. Beware compton " \
|
||||||
"cannot make you a sandwich."
|
"cannot make you a sandwich."
|
||||||
#define CDBUS_ERROR_BADARG CDBUS_ERROR_PREFIX ".bad_argument"
|
#define CDBUS_ERROR_BADARG CDBUS_ERROR_PREFIX ".bad_argument"
|
||||||
#define CDBUS_ERROR_BADARG_S "Failed to parse argument %d: %s"
|
#define CDBUS_ERROR_BADARG_S "Failed to parse argument %d: %s"
|
||||||
|
@ -66,34 +67,27 @@ typedef uint16_t cdbus_enum_t;
|
||||||
#define CDBUS_ERROR_CUSTOM_S "%s"
|
#define CDBUS_ERROR_CUSTOM_S "%s"
|
||||||
|
|
||||||
#define cdbus_reply_err(ps, srcmsg, err_name, err_format, ...) \
|
#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__))
|
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 *);
|
|
||||||
|
|
||||||
static dbus_bool_t
|
static dbus_bool_t cdbus_callback_add_timeout(DBusTimeout *timeout, void *data);
|
||||||
cdbus_callback_add_timeout(DBusTimeout *timeout, void *data);
|
|
||||||
|
|
||||||
static void
|
static void cdbus_callback_remove_timeout(DBusTimeout *timeout, void *data);
|
||||||
cdbus_callback_remove_timeout(DBusTimeout *timeout, void *data);
|
|
||||||
|
|
||||||
static void
|
static void cdbus_callback_timeout_toggled(DBusTimeout *timeout, void *data);
|
||||||
cdbus_callback_timeout_toggled(DBusTimeout *timeout, void *data);
|
|
||||||
|
|
||||||
static dbus_bool_t
|
static dbus_bool_t cdbus_callback_add_watch(DBusWatch *watch, void *data);
|
||||||
cdbus_callback_add_watch(DBusWatch *watch, void *data);
|
|
||||||
|
|
||||||
static void
|
static void cdbus_callback_remove_watch(DBusWatch *watch, void *data);
|
||||||
cdbus_callback_remove_watch(DBusWatch *watch, void *data);
|
|
||||||
|
|
||||||
static void
|
static void cdbus_callback_watch_toggled(DBusWatch *watch, void *data);
|
||||||
cdbus_callback_watch_toggled(DBusWatch *watch, void *data);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize D-Bus connection.
|
* Initialize D-Bus connection.
|
||||||
*/
|
*/
|
||||||
bool
|
bool cdbus_init(session_t *ps, const char *uniq) {
|
||||||
cdbus_init(session_t *ps, const char *uniq) {
|
|
||||||
auto cd = cmalloc(struct cdbus_data);
|
auto cd = cmalloc(struct cdbus_data);
|
||||||
cd->dbus_service = NULL;
|
cd->dbus_service = NULL;
|
||||||
|
|
||||||
|
@ -129,7 +123,8 @@ cdbus_init(session_t *ps, const char *uniq) {
|
||||||
char *service = ccalloc(service_len, char);
|
char *service = ccalloc(service_len, char);
|
||||||
snprintf(service, service_len, "%s.%s", CDBUS_SERVICE_NAME, uniq);
|
snprintf(service, service_len, "%s.%s", CDBUS_SERVICE_NAME, uniq);
|
||||||
|
|
||||||
// Make a valid dbus name by converting non alphanumeric characters to underscore
|
// Make a valid dbus name by converting non alphanumeric characters to
|
||||||
|
// underscore
|
||||||
char *tmp = service + strlen(CDBUS_SERVICE_NAME) + 1;
|
char *tmp = service + strlen(CDBUS_SERVICE_NAME) + 1;
|
||||||
while (*tmp) {
|
while (*tmp) {
|
||||||
if (!isalnum(*tmp)) {
|
if (!isalnum(*tmp)) {
|
||||||
|
@ -149,25 +144,26 @@ cdbus_init(session_t *ps, const char *uniq) {
|
||||||
goto fail;
|
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;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Add watch handlers
|
// Add watch handlers
|
||||||
if (!dbus_connection_set_watch_functions(cd->dbus_conn,
|
if (!dbus_connection_set_watch_functions(cd->dbus_conn, cdbus_callback_add_watch,
|
||||||
cdbus_callback_add_watch, cdbus_callback_remove_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.");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add timeout handlers
|
// Add timeout handlers
|
||||||
if (!dbus_connection_set_timeout_functions(cd->dbus_conn,
|
if (!dbus_connection_set_timeout_functions(
|
||||||
cdbus_callback_add_timeout, cdbus_callback_remove_timeout,
|
cd->dbus_conn, 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.");
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -193,8 +189,7 @@ fail:
|
||||||
/**
|
/**
|
||||||
* Destroy D-Bus connection.
|
* Destroy D-Bus connection.
|
||||||
*/
|
*/
|
||||||
void
|
void cdbus_destroy(session_t *ps) {
|
||||||
cdbus_destroy(session_t *ps) {
|
|
||||||
struct cdbus_data *cd = ps->dbus_data;
|
struct cdbus_data *cd = ps->dbus_data;
|
||||||
if (cd->dbus_conn) {
|
if (cd->dbus_conn) {
|
||||||
// Release DBus name firstly
|
// Release DBus name firstly
|
||||||
|
@ -229,8 +224,7 @@ typedef struct ev_dbus_timer {
|
||||||
/**
|
/**
|
||||||
* Callback for handling a D-Bus timeout.
|
* Callback for handling a D-Bus timeout.
|
||||||
*/
|
*/
|
||||||
static void
|
static void cdbus_callback_handle_timeout(EV_P_ ev_timer *w, int revents) {
|
||||||
cdbus_callback_handle_timeout(EV_P_ ev_timer *w, int revents) {
|
|
||||||
ev_dbus_timer *t = (void *)w;
|
ev_dbus_timer *t = (void *)w;
|
||||||
dbus_timeout_handle(t->t);
|
dbus_timeout_handle(t->t);
|
||||||
}
|
}
|
||||||
|
@ -238,8 +232,7 @@ cdbus_callback_handle_timeout(EV_P_ ev_timer *w, int revents) {
|
||||||
/**
|
/**
|
||||||
* Callback for adding D-Bus timeout.
|
* Callback for adding D-Bus timeout.
|
||||||
*/
|
*/
|
||||||
static dbus_bool_t
|
static dbus_bool_t cdbus_callback_add_timeout(DBusTimeout *timeout, void *data) {
|
||||||
cdbus_callback_add_timeout(DBusTimeout *timeout, void *data) {
|
|
||||||
session_t *ps = data;
|
session_t *ps = data;
|
||||||
|
|
||||||
auto t = ccalloc(1, ev_dbus_timer);
|
auto t = ccalloc(1, ev_dbus_timer);
|
||||||
|
@ -257,8 +250,7 @@ cdbus_callback_add_timeout(DBusTimeout *timeout, void *data) {
|
||||||
/**
|
/**
|
||||||
* Callback for removing D-Bus timeout.
|
* Callback for removing D-Bus timeout.
|
||||||
*/
|
*/
|
||||||
static void
|
static void cdbus_callback_remove_timeout(DBusTimeout *timeout, void *data) {
|
||||||
cdbus_callback_remove_timeout(DBusTimeout *timeout, void *data) {
|
|
||||||
session_t *ps = data;
|
session_t *ps = data;
|
||||||
|
|
||||||
ev_dbus_timer *t = dbus_timeout_get_data(timeout);
|
ev_dbus_timer *t = dbus_timeout_get_data(timeout);
|
||||||
|
@ -270,8 +262,7 @@ cdbus_callback_remove_timeout(DBusTimeout *timeout, void *data) {
|
||||||
/**
|
/**
|
||||||
* Callback for toggling a D-Bus timeout.
|
* Callback for toggling a D-Bus timeout.
|
||||||
*/
|
*/
|
||||||
static void
|
static void cdbus_callback_timeout_toggled(DBusTimeout *timeout, void *data) {
|
||||||
cdbus_callback_timeout_toggled(DBusTimeout *timeout, void *data) {
|
|
||||||
session_t *ps = data;
|
session_t *ps = data;
|
||||||
ev_dbus_timer *t = dbus_timeout_get_data(timeout);
|
ev_dbus_timer *t = dbus_timeout_get_data(timeout);
|
||||||
|
|
||||||
|
@ -304,14 +295,14 @@ 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->cd->dbus_conn) != DBUS_DISPATCH_COMPLETE);
|
while (dbus_connection_dispatch(dw->cd->dbus_conn) != DBUS_DISPATCH_COMPLETE)
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine the poll condition of a DBusWatch.
|
* Determine the poll condition of a DBusWatch.
|
||||||
*/
|
*/
|
||||||
static inline int
|
static inline int cdbus_get_watch_cond(DBusWatch *watch) {
|
||||||
cdbus_get_watch_cond(DBusWatch *watch) {
|
|
||||||
const unsigned flags = dbus_watch_get_flags(watch);
|
const unsigned flags = dbus_watch_get_flags(watch);
|
||||||
int condition = 0;
|
int condition = 0;
|
||||||
if (flags & DBUS_WATCH_READABLE)
|
if (flags & DBUS_WATCH_READABLE)
|
||||||
|
@ -325,8 +316,7 @@ cdbus_get_watch_cond(DBusWatch *watch) {
|
||||||
/**
|
/**
|
||||||
* Callback for adding D-Bus watch.
|
* Callback for adding D-Bus watch.
|
||||||
*/
|
*/
|
||||||
static dbus_bool_t
|
static dbus_bool_t cdbus_callback_add_watch(DBusWatch *watch, void *data) {
|
||||||
cdbus_callback_add_watch(DBusWatch *watch, void *data) {
|
|
||||||
session_t *ps = data;
|
session_t *ps = data;
|
||||||
|
|
||||||
auto w = ccalloc(1, ev_dbus_io);
|
auto w = ccalloc(1, ev_dbus_io);
|
||||||
|
@ -348,8 +338,7 @@ cdbus_callback_add_watch(DBusWatch *watch, void *data) {
|
||||||
/**
|
/**
|
||||||
* Callback for removing D-Bus watch.
|
* Callback for removing D-Bus watch.
|
||||||
*/
|
*/
|
||||||
static void
|
static void cdbus_callback_remove_watch(DBusWatch *watch, void *data) {
|
||||||
cdbus_callback_remove_watch(DBusWatch *watch, void *data) {
|
|
||||||
session_t *ps = data;
|
session_t *ps = data;
|
||||||
ev_dbus_io *w = dbus_watch_get_data(watch);
|
ev_dbus_io *w = dbus_watch_get_data(watch);
|
||||||
ev_io_stop(ps->loop, &w->w);
|
ev_io_stop(ps->loop, &w->w);
|
||||||
|
@ -359,8 +348,7 @@ cdbus_callback_remove_watch(DBusWatch *watch, void *data) {
|
||||||
/**
|
/**
|
||||||
* Callback for toggling D-Bus watch status.
|
* Callback for toggling D-Bus watch status.
|
||||||
*/
|
*/
|
||||||
static void
|
static void cdbus_callback_watch_toggled(DBusWatch *watch, void *data) {
|
||||||
cdbus_callback_watch_toggled(DBusWatch *watch, void *data) {
|
|
||||||
session_t *ps = data;
|
session_t *ps = data;
|
||||||
ev_io *w = dbus_watch_get_data(watch);
|
ev_io *w = dbus_watch_get_data(watch);
|
||||||
if (dbus_watch_get_enabled(watch))
|
if (dbus_watch_get_enabled(watch))
|
||||||
|
@ -378,14 +366,12 @@ cdbus_callback_watch_toggled(DBusWatch *watch, void *data) {
|
||||||
/**
|
/**
|
||||||
* Callback to append a bool argument to a message.
|
* Callback to append a bool argument to a message.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool cdbus_apdarg_bool(session_t *ps, DBusMessage *msg, const void *data) {
|
||||||
cdbus_apdarg_bool(session_t *ps, DBusMessage *msg, const void *data) {
|
|
||||||
assert(data);
|
assert(data);
|
||||||
|
|
||||||
dbus_bool_t val = *(const bool *)data;
|
dbus_bool_t val = *(const bool *)data;
|
||||||
|
|
||||||
if (!dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &val,
|
if (!dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &val, DBUS_TYPE_INVALID)) {
|
||||||
DBUS_TYPE_INVALID)) {
|
|
||||||
log_error("Failed to append argument.");
|
log_error("Failed to append argument.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -396,10 +382,8 @@ cdbus_apdarg_bool(session_t *ps, DBusMessage *msg, const void *data) {
|
||||||
/**
|
/**
|
||||||
* Callback to append an int32 argument to a message.
|
* Callback to append an int32 argument to a message.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool cdbus_apdarg_int32(session_t *ps, DBusMessage *msg, const void *data) {
|
||||||
cdbus_apdarg_int32(session_t *ps, DBusMessage *msg, const void *data) {
|
if (!dbus_message_append_args(msg, DBUS_TYPE_INT32, data, DBUS_TYPE_INVALID)) {
|
||||||
if (!dbus_message_append_args(msg, DBUS_TYPE_INT32, data,
|
|
||||||
DBUS_TYPE_INVALID)) {
|
|
||||||
log_error("Failed to append argument.");
|
log_error("Failed to append argument.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -410,10 +394,8 @@ cdbus_apdarg_int32(session_t *ps, DBusMessage *msg, const void *data) {
|
||||||
/**
|
/**
|
||||||
* Callback to append an uint32 argument to a message.
|
* Callback to append an uint32 argument to a message.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool cdbus_apdarg_uint32(session_t *ps, DBusMessage *msg, const void *data) {
|
||||||
cdbus_apdarg_uint32(session_t *ps, DBusMessage *msg, const void *data) {
|
if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, data, DBUS_TYPE_INVALID)) {
|
||||||
if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, data,
|
|
||||||
DBUS_TYPE_INVALID)) {
|
|
||||||
log_error("Failed to append argument.");
|
log_error("Failed to append argument.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -424,10 +406,8 @@ cdbus_apdarg_uint32(session_t *ps, DBusMessage *msg, const void *data) {
|
||||||
/**
|
/**
|
||||||
* Callback to append a double argument to a message.
|
* Callback to append a double argument to a message.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool cdbus_apdarg_double(session_t *ps, DBusMessage *msg, const void *data) {
|
||||||
cdbus_apdarg_double(session_t *ps, DBusMessage *msg, const void *data) {
|
if (!dbus_message_append_args(msg, DBUS_TYPE_DOUBLE, data, DBUS_TYPE_INVALID)) {
|
||||||
if (!dbus_message_append_args(msg, DBUS_TYPE_DOUBLE, data,
|
|
||||||
DBUS_TYPE_INVALID)) {
|
|
||||||
log_error("Failed to append argument.");
|
log_error("Failed to append argument.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -438,13 +418,11 @@ cdbus_apdarg_double(session_t *ps, DBusMessage *msg, const void *data) {
|
||||||
/**
|
/**
|
||||||
* Callback to append a Window argument to a message.
|
* Callback to append a Window argument to a message.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool cdbus_apdarg_wid(session_t *ps, DBusMessage *msg, const void *data) {
|
||||||
cdbus_apdarg_wid(session_t *ps, DBusMessage *msg, const void *data) {
|
|
||||||
assert(data);
|
assert(data);
|
||||||
cdbus_window_t val = *(const xcb_window_t *)data;
|
cdbus_window_t val = *(const xcb_window_t *)data;
|
||||||
|
|
||||||
if (!dbus_message_append_args(msg, CDBUS_TYPE_WINDOW, &val,
|
if (!dbus_message_append_args(msg, CDBUS_TYPE_WINDOW, &val, DBUS_TYPE_INVALID)) {
|
||||||
DBUS_TYPE_INVALID)) {
|
|
||||||
log_error("Failed to append argument.");
|
log_error("Failed to append argument.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -455,11 +433,9 @@ cdbus_apdarg_wid(session_t *ps, DBusMessage *msg, const void *data) {
|
||||||
/**
|
/**
|
||||||
* Callback to append an cdbus_enum_t argument to a message.
|
* Callback to append an cdbus_enum_t argument to a message.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool cdbus_apdarg_enum(session_t *ps, DBusMessage *msg, const void *data) {
|
||||||
cdbus_apdarg_enum(session_t *ps, DBusMessage *msg, const void *data) {
|
|
||||||
assert(data);
|
assert(data);
|
||||||
if (!dbus_message_append_args(msg, CDBUS_TYPE_ENUM, data,
|
if (!dbus_message_append_args(msg, CDBUS_TYPE_ENUM, data, DBUS_TYPE_INVALID)) {
|
||||||
DBUS_TYPE_INVALID)) {
|
|
||||||
log_error("Failed to append argument.");
|
log_error("Failed to append argument.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -470,14 +446,12 @@ cdbus_apdarg_enum(session_t *ps, DBusMessage *msg, const void *data) {
|
||||||
/**
|
/**
|
||||||
* Callback to append a string argument to a message.
|
* Callback to append a string argument to a message.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool cdbus_apdarg_string(session_t *ps, DBusMessage *msg, const void *data) {
|
||||||
cdbus_apdarg_string(session_t *ps, DBusMessage *msg, const void *data) {
|
|
||||||
const char *str = data;
|
const char *str = data;
|
||||||
if (!str)
|
if (!str)
|
||||||
str = "";
|
str = "";
|
||||||
|
|
||||||
if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &str,
|
if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID)) {
|
||||||
DBUS_TYPE_INVALID)) {
|
|
||||||
log_error("Failed to append argument.");
|
log_error("Failed to append argument.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -488,8 +462,7 @@ cdbus_apdarg_string(session_t *ps, DBusMessage *msg, const void *data) {
|
||||||
/**
|
/**
|
||||||
* Callback to append all window IDs to a message.
|
* Callback to append all window IDs to a message.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool cdbus_apdarg_wids(session_t *ps, DBusMessage *msg, const void *data) {
|
||||||
cdbus_apdarg_wids(session_t *ps, DBusMessage *msg, const void *data) {
|
|
||||||
// Get the number of wids we are to include
|
// Get the number of wids we are to include
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
for (win *w = ps->list; w; w = w->next) {
|
for (win *w = ps->list; w; w = w->next) {
|
||||||
|
@ -520,8 +493,8 @@ cdbus_apdarg_wids(session_t *ps, DBusMessage *msg, const void *data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append arguments
|
// Append arguments
|
||||||
if (!dbus_message_append_args(msg, DBUS_TYPE_ARRAY, CDBUS_TYPE_WINDOW,
|
if (!dbus_message_append_args(msg, DBUS_TYPE_ARRAY, CDBUS_TYPE_WINDOW, &arr,
|
||||||
&arr, count, DBUS_TYPE_INVALID)) {
|
count, DBUS_TYPE_INVALID)) {
|
||||||
log_error("Failed to append argument.");
|
log_error("Failed to append argument.");
|
||||||
free(arr);
|
free(arr);
|
||||||
return false;
|
return false;
|
||||||
|
@ -541,16 +514,14 @@ cdbus_apdarg_wids(session_t *ps, DBusMessage *msg, const void *data) {
|
||||||
* add an argument
|
* add an argument
|
||||||
* @param data data pointer to pass to the function
|
* @param data data pointer to pass to the function
|
||||||
*/
|
*/
|
||||||
static bool
|
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;
|
struct cdbus_data *cd = ps->dbus_data;
|
||||||
DBusMessage *msg = NULL;
|
DBusMessage *msg = NULL;
|
||||||
|
|
||||||
// Create a signal
|
// Create a signal
|
||||||
msg = dbus_message_new_signal(CDBUS_OBJECT_NAME, CDBUS_INTERFACE_NAME,
|
msg = dbus_message_new_signal(CDBUS_OBJECT_NAME, CDBUS_INTERFACE_NAME, name);
|
||||||
name);
|
|
||||||
if (!msg) {
|
if (!msg) {
|
||||||
log_error("Failed to create D-Bus signal.");
|
log_error("Failed to create D-Bus signal.");
|
||||||
return false;
|
return false;
|
||||||
|
@ -579,8 +550,7 @@ cdbus_signal(session_t *ps, const char *name,
|
||||||
/**
|
/**
|
||||||
* Send a signal with a Window ID as argument.
|
* Send a signal with a Window ID as argument.
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool cdbus_signal_wid(session_t *ps, const char *name, xcb_window_t wid) {
|
||||||
cdbus_signal_wid(session_t *ps, const char *name, xcb_window_t wid) {
|
|
||||||
return cdbus_signal(ps, name, cdbus_apdarg_wid, &wid);
|
return cdbus_signal(ps, name, cdbus_apdarg_wid, &wid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -593,8 +563,7 @@ cdbus_signal_wid(session_t *ps, const char *name, xcb_window_t wid) {
|
||||||
* add an argument
|
* add an argument
|
||||||
* @param data data pointer to pass to the function
|
* @param data data pointer to pass to the function
|
||||||
*/
|
*/
|
||||||
static bool
|
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;
|
struct cdbus_data *cd = ps->dbus_data;
|
||||||
|
@ -630,56 +599,49 @@ cdbus_reply(session_t *ps, DBusMessage *srcmsg,
|
||||||
/**
|
/**
|
||||||
* Send a reply with a bool argument.
|
* Send a reply with a bool argument.
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool cdbus_reply_bool(session_t *ps, DBusMessage *srcmsg, bool bval) {
|
||||||
cdbus_reply_bool(session_t *ps, DBusMessage *srcmsg, bool bval) {
|
|
||||||
return cdbus_reply(ps, srcmsg, cdbus_apdarg_bool, &bval);
|
return cdbus_reply(ps, srcmsg, cdbus_apdarg_bool, &bval);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a reply with an int32 argument.
|
* Send a reply with an int32 argument.
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool cdbus_reply_int32(session_t *ps, DBusMessage *srcmsg, int32_t val) {
|
||||||
cdbus_reply_int32(session_t *ps, DBusMessage *srcmsg, int32_t val) {
|
|
||||||
return cdbus_reply(ps, srcmsg, cdbus_apdarg_int32, &val);
|
return cdbus_reply(ps, srcmsg, cdbus_apdarg_int32, &val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a reply with an uint32 argument.
|
* Send a reply with an uint32 argument.
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool cdbus_reply_uint32(session_t *ps, DBusMessage *srcmsg, uint32_t val) {
|
||||||
cdbus_reply_uint32(session_t *ps, DBusMessage *srcmsg, uint32_t val) {
|
|
||||||
return cdbus_reply(ps, srcmsg, cdbus_apdarg_uint32, &val);
|
return cdbus_reply(ps, srcmsg, cdbus_apdarg_uint32, &val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a reply with a double argument.
|
* Send a reply with a double argument.
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool cdbus_reply_double(session_t *ps, DBusMessage *srcmsg, double val) {
|
||||||
cdbus_reply_double(session_t *ps, DBusMessage *srcmsg, double val) {
|
|
||||||
return cdbus_reply(ps, srcmsg, cdbus_apdarg_double, &val);
|
return cdbus_reply(ps, srcmsg, cdbus_apdarg_double, &val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a reply with a wid argument.
|
* Send a reply with a wid argument.
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool cdbus_reply_wid(session_t *ps, DBusMessage *srcmsg, xcb_window_t wid) {
|
||||||
cdbus_reply_wid(session_t *ps, DBusMessage *srcmsg, xcb_window_t wid) {
|
|
||||||
return cdbus_reply(ps, srcmsg, cdbus_apdarg_wid, &wid);
|
return cdbus_reply(ps, srcmsg, cdbus_apdarg_wid, &wid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a reply with a string argument.
|
* Send a reply with a string argument.
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool cdbus_reply_string(session_t *ps, DBusMessage *srcmsg, const char *str) {
|
||||||
cdbus_reply_string(session_t *ps, DBusMessage *srcmsg, const char *str) {
|
|
||||||
return cdbus_reply(ps, srcmsg, cdbus_apdarg_string, str);
|
return cdbus_reply(ps, srcmsg, cdbus_apdarg_string, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a reply with a enum argument.
|
* Send a reply with a enum argument.
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool cdbus_reply_enum(session_t *ps, DBusMessage *srcmsg, cdbus_enum_t eval) {
|
||||||
cdbus_reply_enum(session_t *ps, DBusMessage *srcmsg, cdbus_enum_t eval) {
|
|
||||||
return cdbus_reply(ps, srcmsg, cdbus_apdarg_enum, &eval);
|
return cdbus_reply(ps, srcmsg, cdbus_apdarg_enum, &eval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -689,8 +651,7 @@ cdbus_reply_enum(session_t *ps, DBusMessage *srcmsg, cdbus_enum_t eval) {
|
||||||
* @param ps current session
|
* @param ps current session
|
||||||
* @param msg the new error DBusMessage
|
* @param msg the new error DBusMessage
|
||||||
*/
|
*/
|
||||||
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;
|
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.");
|
||||||
|
@ -719,8 +680,7 @@ cdbus_reply_errm(session_t *ps, DBusMessage *msg) {
|
||||||
* @param pdest pointer to the target
|
* @param pdest pointer to the target
|
||||||
* @return true if successful, false otherwise.
|
* @return true if successful, false otherwise.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool cdbus_msg_get_arg(DBusMessage *msg, int count, const int type, void *pdest) {
|
||||||
cdbus_msg_get_arg(DBusMessage *msg, int count, const int type, void *pdest) {
|
|
||||||
assert(count >= 0);
|
assert(count >= 0);
|
||||||
|
|
||||||
DBusMessageIter iter = {};
|
DBusMessageIter iter = {};
|
||||||
|
@ -757,8 +717,7 @@ cdbus_msg_get_arg(DBusMessage *msg, int count, const int type, void *pdest) {
|
||||||
/**
|
/**
|
||||||
* Process a list_win D-Bus request.
|
* Process a list_win D-Bus request.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool cdbus_process_list_win(session_t *ps, DBusMessage *msg) {
|
||||||
cdbus_process_list_win(session_t *ps, DBusMessage *msg) {
|
|
||||||
cdbus_reply(ps, msg, cdbus_apdarg_wids, NULL);
|
cdbus_reply(ps, msg, cdbus_apdarg_wids, NULL);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -767,16 +726,13 @@ cdbus_process_list_win(session_t *ps, DBusMessage *msg) {
|
||||||
/**
|
/**
|
||||||
* Process a win_get D-Bus request.
|
* Process a win_get D-Bus request.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool cdbus_process_win_get(session_t *ps, DBusMessage *msg) {
|
||||||
cdbus_process_win_get(session_t *ps, DBusMessage *msg) {
|
|
||||||
cdbus_window_t wid = XCB_NONE;
|
cdbus_window_t wid = XCB_NONE;
|
||||||
const char *target = NULL;
|
const char *target = NULL;
|
||||||
DBusError err = {};
|
DBusError err = {};
|
||||||
|
|
||||||
if (!dbus_message_get_args(msg, &err,
|
if (!dbus_message_get_args(msg, &err, CDBUS_TYPE_WINDOW, &wid, DBUS_TYPE_STRING,
|
||||||
CDBUS_TYPE_WINDOW, &wid,
|
&target, DBUS_TYPE_INVALID)) {
|
||||||
DBUS_TYPE_STRING, &target,
|
|
||||||
DBUS_TYPE_INVALID)) {
|
|
||||||
log_error("Failed to parse argument of \"win_get\" (%s).", err.message);
|
log_error("Failed to parse argument of \"win_get\" (%s).", err.message);
|
||||||
dbus_error_free(&err);
|
dbus_error_free(&err);
|
||||||
return false;
|
return false;
|
||||||
|
@ -869,16 +825,13 @@ cdbus_process_win_get(session_t *ps, DBusMessage *msg) {
|
||||||
/**
|
/**
|
||||||
* Process a win_set D-Bus request.
|
* Process a win_set D-Bus request.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool cdbus_process_win_set(session_t *ps, DBusMessage *msg) {
|
||||||
cdbus_process_win_set(session_t *ps, DBusMessage *msg) {
|
|
||||||
cdbus_window_t wid = XCB_NONE;
|
cdbus_window_t wid = XCB_NONE;
|
||||||
const char *target = NULL;
|
const char *target = NULL;
|
||||||
DBusError err = {};
|
DBusError err = {};
|
||||||
|
|
||||||
if (!dbus_message_get_args(msg, &err,
|
if (!dbus_message_get_args(msg, &err, CDBUS_TYPE_WINDOW, &wid, DBUS_TYPE_STRING,
|
||||||
CDBUS_TYPE_WINDOW, &wid,
|
&target, DBUS_TYPE_INVALID)) {
|
||||||
DBUS_TYPE_STRING, &target,
|
|
||||||
DBUS_TYPE_INVALID)) {
|
|
||||||
log_error("(): Failed to parse argument of \"win_set\" (%s).", err.message);
|
log_error("(): Failed to parse argument of \"win_set\" (%s).", err.message);
|
||||||
dbus_error_free(&err);
|
dbus_error_free(&err);
|
||||||
return false;
|
return false;
|
||||||
|
@ -948,8 +901,7 @@ cdbus_process_win_set_success:
|
||||||
/**
|
/**
|
||||||
* Process a find_win D-Bus request.
|
* Process a find_win D-Bus request.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool cdbus_process_find_win(session_t *ps, DBusMessage *msg) {
|
||||||
cdbus_process_find_win(session_t *ps, DBusMessage *msg) {
|
|
||||||
const char *target = NULL;
|
const char *target = NULL;
|
||||||
|
|
||||||
if (!cdbus_msg_get_arg(msg, 0, DBUS_TYPE_STRING, &target))
|
if (!cdbus_msg_get_arg(msg, 0, DBUS_TYPE_STRING, &target))
|
||||||
|
@ -971,8 +923,7 @@ cdbus_process_find_win(session_t *ps, DBusMessage *msg) {
|
||||||
win *w = find_focused(ps);
|
win *w = find_focused(ps);
|
||||||
if (w)
|
if (w)
|
||||||
wid = w->id;
|
wid = w->id;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
log_error(CDBUS_ERROR_BADTGT_S, target);
|
log_error(CDBUS_ERROR_BADTGT_S, target);
|
||||||
cdbus_reply_err(ps, msg, CDBUS_ERROR_BADTGT, CDBUS_ERROR_BADTGT_S, target);
|
cdbus_reply_err(ps, msg, CDBUS_ERROR_BADTGT, CDBUS_ERROR_BADTGT_S, target);
|
||||||
|
|
||||||
|
@ -987,8 +938,7 @@ cdbus_process_find_win(session_t *ps, DBusMessage *msg) {
|
||||||
/**
|
/**
|
||||||
* Process a opts_get D-Bus request.
|
* Process a opts_get D-Bus request.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool cdbus_process_opts_get(session_t *ps, DBusMessage *msg) {
|
||||||
cdbus_process_opts_get(session_t *ps, DBusMessage *msg) {
|
|
||||||
const char *target = NULL;
|
const char *target = NULL;
|
||||||
|
|
||||||
if (!cdbus_msg_get_arg(msg, 0, DBUS_TYPE_STRING, &target))
|
if (!cdbus_msg_get_arg(msg, 0, DBUS_TYPE_STRING, &target))
|
||||||
|
@ -1109,8 +1059,7 @@ void queue_redraw(session_t *ps);
|
||||||
/**
|
/**
|
||||||
* Process a opts_set D-Bus request.
|
* Process a opts_set D-Bus request.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool cdbus_process_opts_set(session_t *ps, DBusMessage *msg) {
|
||||||
cdbus_process_opts_set(session_t *ps, DBusMessage *msg) {
|
|
||||||
const char *target = NULL;
|
const char *target = NULL;
|
||||||
|
|
||||||
if (!cdbus_msg_get_arg(msg, 0, DBUS_TYPE_STRING, &target))
|
if (!cdbus_msg_get_arg(msg, 0, DBUS_TYPE_STRING, &target))
|
||||||
|
@ -1218,10 +1167,10 @@ cdbus_process_opts_set_success:
|
||||||
/**
|
/**
|
||||||
* Process an Introspect D-Bus request.
|
* Process an Introspect D-Bus request.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool cdbus_process_introspect(session_t *ps, DBusMessage *msg) {
|
||||||
cdbus_process_introspect(session_t *ps, DBusMessage *msg) {
|
|
||||||
static const char *str_introspect =
|
static const char *str_introspect =
|
||||||
"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
|
"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection "
|
||||||
|
"1.0//EN\"\n"
|
||||||
" \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
|
" \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
|
||||||
"<node name='" CDBUS_OBJECT_NAME "'>\n"
|
"<node name='" CDBUS_OBJECT_NAME "'>\n"
|
||||||
" <interface name='org.freedesktop.DBus.Introspectable'>\n"
|
" <interface name='org.freedesktop.DBus.Introspectable'>\n"
|
||||||
|
@ -1268,8 +1217,7 @@ cdbus_process_introspect(session_t *ps, DBusMessage *msg) {
|
||||||
/**
|
/**
|
||||||
* Process a message from D-Bus.
|
* Process a message from D-Bus.
|
||||||
*/
|
*/
|
||||||
static DBusHandlerResult
|
static DBusHandlerResult cdbus_process(DBusConnection *c, DBusMessage *msg, void *ud) {
|
||||||
cdbus_process(DBusConnection *c, DBusMessage *msg, void *ud) {
|
|
||||||
session_t *ps = ud;
|
session_t *ps = ud;
|
||||||
bool handled = false;
|
bool handled = false;
|
||||||
|
|
||||||
|
@ -1281,77 +1229,66 @@ cdbus_process(DBusConnection *c, DBusMessage *msg, void *ud) {
|
||||||
if (!dbus_message_get_no_reply(msg))
|
if (!dbus_message_get_no_reply(msg))
|
||||||
cdbus_reply_bool(ps, msg, true);
|
cdbus_reply_bool(ps, msg, true);
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
} else if (cdbus_m_ismethod("repaint")) {
|
||||||
else if (cdbus_m_ismethod("repaint")) {
|
|
||||||
force_repaint(ps);
|
force_repaint(ps);
|
||||||
if (!dbus_message_get_no_reply(msg))
|
if (!dbus_message_get_no_reply(msg))
|
||||||
cdbus_reply_bool(ps, msg, true);
|
cdbus_reply_bool(ps, msg, true);
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
} else if (cdbus_m_ismethod("list_win")) {
|
||||||
else if (cdbus_m_ismethod("list_win")) {
|
|
||||||
handled = cdbus_process_list_win(ps, msg);
|
handled = cdbus_process_list_win(ps, msg);
|
||||||
}
|
} else if (cdbus_m_ismethod("win_get")) {
|
||||||
else if (cdbus_m_ismethod("win_get")) {
|
|
||||||
handled = cdbus_process_win_get(ps, msg);
|
handled = cdbus_process_win_get(ps, msg);
|
||||||
}
|
} else if (cdbus_m_ismethod("win_set")) {
|
||||||
else if (cdbus_m_ismethod("win_set")) {
|
|
||||||
handled = cdbus_process_win_set(ps, msg);
|
handled = cdbus_process_win_set(ps, msg);
|
||||||
}
|
} else if (cdbus_m_ismethod("find_win")) {
|
||||||
else if (cdbus_m_ismethod("find_win")) {
|
|
||||||
handled = cdbus_process_find_win(ps, msg);
|
handled = cdbus_process_find_win(ps, msg);
|
||||||
}
|
} else if (cdbus_m_ismethod("opts_get")) {
|
||||||
else if (cdbus_m_ismethod("opts_get")) {
|
|
||||||
handled = cdbus_process_opts_get(ps, msg);
|
handled = cdbus_process_opts_get(ps, msg);
|
||||||
}
|
} else if (cdbus_m_ismethod("opts_set")) {
|
||||||
else if (cdbus_m_ismethod("opts_set")) {
|
|
||||||
handled = cdbus_process_opts_set(ps, msg);
|
handled = cdbus_process_opts_set(ps, msg);
|
||||||
}
|
}
|
||||||
#undef cdbus_m_ismethod
|
#undef cdbus_m_ismethod
|
||||||
else if (dbus_message_is_method_call(msg,
|
else if (dbus_message_is_method_call(msg, "org.freedesktop.DBus.Introspectable",
|
||||||
"org.freedesktop.DBus.Introspectable", "Introspect")) {
|
"Introspect")) {
|
||||||
handled = cdbus_process_introspect(ps, msg);
|
handled = cdbus_process_introspect(ps, msg);
|
||||||
}
|
} else if (dbus_message_is_method_call(msg, "org.freedesktop.DBus.Peer", "Ping")) {
|
||||||
else if (dbus_message_is_method_call(msg,
|
|
||||||
"org.freedesktop.DBus.Peer", "Ping")) {
|
|
||||||
cdbus_reply(ps, msg, NULL, NULL);
|
cdbus_reply(ps, msg, NULL, NULL);
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
} else if (dbus_message_is_method_call(msg, "org.freedesktop.DBus.Peer",
|
||||||
else if (dbus_message_is_method_call(msg,
|
"GetMachineId")) {
|
||||||
"org.freedesktop.DBus.Peer", "GetMachineId")) {
|
|
||||||
char *uuid = dbus_get_local_machine_id();
|
char *uuid = dbus_get_local_machine_id();
|
||||||
if (uuid) {
|
if (uuid) {
|
||||||
cdbus_reply_string(ps, msg, uuid);
|
cdbus_reply_string(ps, msg, uuid);
|
||||||
dbus_free(uuid);
|
dbus_free(uuid);
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
}
|
} else if (dbus_message_is_signal(msg, "org.freedesktop.DBus", "NameAcquired") ||
|
||||||
else if (dbus_message_is_signal(msg, "org.freedesktop.DBus", "NameAcquired")
|
dbus_message_is_signal(msg, "org.freedesktop.DBus", "NameLost")) {
|
||||||
|| dbus_message_is_signal(msg, "org.freedesktop.DBus", "NameLost")) {
|
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (DBUS_MESSAGE_TYPE_ERROR == dbus_message_get_type(msg)) {
|
if (DBUS_MESSAGE_TYPE_ERROR == dbus_message_get_type(msg)) {
|
||||||
log_error("Error message of path \"%s\" "
|
log_error(
|
||||||
|
"Error message of path \"%s\" "
|
||||||
"interface \"%s\", member \"%s\", error \"%s\"",
|
"interface \"%s\", member \"%s\", error \"%s\"",
|
||||||
dbus_message_get_path(msg), dbus_message_get_interface(msg),
|
dbus_message_get_path(msg), dbus_message_get_interface(msg),
|
||||||
dbus_message_get_member(msg), dbus_message_get_error_name(msg));
|
dbus_message_get_member(msg), dbus_message_get_error_name(msg));
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
log_error("Illegal message of type \"%s\", path \"%s\" "
|
log_error("Illegal message of type \"%s\", path \"%s\" "
|
||||||
"interface \"%s\", member \"%s\"",
|
"interface \"%s\", member \"%s\"",
|
||||||
cdbus_repr_msgtype(msg), dbus_message_get_path(msg),
|
cdbus_repr_msgtype(msg), dbus_message_get_path(msg),
|
||||||
dbus_message_get_interface(msg), dbus_message_get_member(msg));
|
dbus_message_get_interface(msg),
|
||||||
|
dbus_message_get_member(msg));
|
||||||
}
|
}
|
||||||
if (DBUS_MESSAGE_TYPE_METHOD_CALL == dbus_message_get_type(msg)
|
if (DBUS_MESSAGE_TYPE_METHOD_CALL == dbus_message_get_type(msg) &&
|
||||||
&& !dbus_message_get_no_reply(msg))
|
!dbus_message_get_no_reply(msg))
|
||||||
cdbus_reply_err(ps, msg, CDBUS_ERROR_BADMSG, CDBUS_ERROR_BADMSG_S);
|
cdbus_reply_err(ps, msg, CDBUS_ERROR_BADMSG, CDBUS_ERROR_BADMSG_S);
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the message could not be processed, and an reply is expected, return
|
// If the message could not be processed, and an reply is expected, return
|
||||||
// an empty reply.
|
// an empty reply.
|
||||||
if (!handled && DBUS_MESSAGE_TYPE_METHOD_CALL == dbus_message_get_type(msg)
|
if (!handled && DBUS_MESSAGE_TYPE_METHOD_CALL == dbus_message_get_type(msg) &&
|
||||||
&& !dbus_message_get_no_reply(msg)) {
|
!dbus_message_get_no_reply(msg)) {
|
||||||
cdbus_reply_err(ps, msg, CDBUS_ERROR_UNKNOWN, CDBUS_ERROR_UNKNOWN_S);
|
cdbus_reply_err(ps, msg, CDBUS_ERROR_UNKNOWN, CDBUS_ERROR_UNKNOWN_S);
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
|
@ -1362,43 +1299,37 @@ cdbus_process(DBusConnection *c, DBusMessage *msg, void *ud) {
|
||||||
/** @name Core callbacks
|
/** @name Core callbacks
|
||||||
*/
|
*/
|
||||||
///@{
|
///@{
|
||||||
void
|
void cdbus_ev_win_added(session_t *ps, win *w) {
|
||||||
cdbus_ev_win_added(session_t *ps, win *w) {
|
|
||||||
struct cdbus_data *cd = ps->dbus_data;
|
struct cdbus_data *cd = ps->dbus_data;
|
||||||
if (cd->dbus_conn)
|
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) {
|
|
||||||
struct cdbus_data *cd = ps->dbus_data;
|
struct cdbus_data *cd = ps->dbus_data;
|
||||||
if (cd->dbus_conn)
|
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) {
|
|
||||||
struct cdbus_data *cd = ps->dbus_data;
|
struct cdbus_data *cd = ps->dbus_data;
|
||||||
if (cd->dbus_conn)
|
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) {
|
|
||||||
struct cdbus_data *cd = ps->dbus_data;
|
struct cdbus_data *cd = ps->dbus_data;
|
||||||
if (cd->dbus_conn)
|
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) {
|
|
||||||
struct cdbus_data *cd = ps->dbus_data;
|
struct cdbus_data *cd = ps->dbus_data;
|
||||||
if (cd->dbus_conn)
|
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) {
|
|
||||||
struct cdbus_data *cd = ps->dbus_data;
|
struct cdbus_data *cd = ps->dbus_data;
|
||||||
if (cd->dbus_conn)
|
if (cd->dbus_conn)
|
||||||
cdbus_signal_wid(ps, "win_focusin", w->id);
|
cdbus_signal_wid(ps, "win_focusin", w->id);
|
||||||
|
|
228
src/opengl.c
228
src/opengl.c
|
@ -9,28 +9,27 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <xcb/xcb.h>
|
|
||||||
#include <xcb/render.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <xcb/render.h>
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
|
||||||
#include "compiler.h"
|
|
||||||
#include "string_utils.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "config.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "win.h"
|
|
||||||
#include "region.h"
|
|
||||||
#include "kernel.h"
|
|
||||||
#include "backend/gl/gl_common.h"
|
#include "backend/gl/gl_common.h"
|
||||||
#include "backend/gl/glx.h"
|
#include "backend/gl/glx.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "compiler.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "kernel.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "region.h"
|
||||||
|
#include "string_utils.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "win.h"
|
||||||
|
|
||||||
#include "opengl.h"
|
#include "opengl.h"
|
||||||
|
|
||||||
static inline XVisualInfo *
|
static inline XVisualInfo *get_visualinfo_from_visual(session_t *ps, xcb_visualid_t visual) {
|
||||||
get_visualinfo_from_visual(session_t *ps, xcb_visualid_t visual) {
|
|
||||||
XVisualInfo vreq = {.visualid = visual};
|
XVisualInfo vreq = {.visualid = visual};
|
||||||
int nitems = 0;
|
int nitems = 0;
|
||||||
|
|
||||||
|
@ -40,8 +39,7 @@ get_visualinfo_from_visual(session_t *ps, xcb_visualid_t visual) {
|
||||||
/**
|
/**
|
||||||
* Initialize OpenGL.
|
* Initialize OpenGL.
|
||||||
*/
|
*/
|
||||||
bool
|
bool glx_init(session_t *ps, bool need_render) {
|
||||||
glx_init(session_t *ps, bool need_render) {
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
XVisualInfo *pvis = NULL;
|
XVisualInfo *pvis = NULL;
|
||||||
|
|
||||||
|
@ -75,8 +73,7 @@ glx_init(session_t *ps, bool need_render) {
|
||||||
goto glx_init_end;
|
goto glx_init_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Success != glXGetConfig(ps->dpy, pvis, GLX_DOUBLEBUFFER, &value)
|
if (Success != glXGetConfig(ps->dpy, pvis, GLX_DOUBLEBUFFER, &value) || !value) {
|
||||||
|| !value) {
|
|
||||||
log_error("Root visual is not a double buffered GL visual.");
|
log_error("Root visual is not a double buffered GL visual.");
|
||||||
goto glx_init_end;
|
goto glx_init_end;
|
||||||
}
|
}
|
||||||
|
@ -110,24 +107,24 @@ glx_init(session_t *ps, bool need_render) {
|
||||||
{
|
{
|
||||||
GLXFBConfig fbconfig = get_fbconfig_from_visualinfo(ps, pvis);
|
GLXFBConfig fbconfig = get_fbconfig_from_visualinfo(ps, pvis);
|
||||||
if (!fbconfig) {
|
if (!fbconfig) {
|
||||||
log_error("Failed to get GLXFBConfig for root visual %#lx.", pvis->visualid);
|
log_error("Failed to get GLXFBConfig for root visual "
|
||||||
|
"%#lx.",
|
||||||
|
pvis->visualid);
|
||||||
goto glx_init_end;
|
goto glx_init_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
f_glXCreateContextAttribsARB p_glXCreateContextAttribsARB =
|
f_glXCreateContextAttribsARB p_glXCreateContextAttribsARB =
|
||||||
(f_glXCreateContextAttribsARB)
|
(f_glXCreateContextAttribsARB)glXGetProcAddress(
|
||||||
glXGetProcAddress((const GLubyte *) "glXCreateContextAttribsARB");
|
(const GLubyte *)"glXCreateContextAttribsARB");
|
||||||
if (!p_glXCreateContextAttribsARB) {
|
if (!p_glXCreateContextAttribsARB) {
|
||||||
log_error("Failed to get glXCreateContextAttribsARB().");
|
log_error("Failed to get glXCreateContextAttribsARB().");
|
||||||
goto glx_init_end;
|
goto glx_init_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const int attrib_list[] = {
|
static const int attrib_list[] = {
|
||||||
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB,
|
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB, None};
|
||||||
None
|
psglx->context = p_glXCreateContextAttribsARB(
|
||||||
};
|
ps->dpy, fbconfig, NULL, GL_TRUE, attrib_list);
|
||||||
psglx->context = p_glXCreateContextAttribsARB(ps->dpy, fbconfig, NULL,
|
|
||||||
GL_TRUE, attrib_list);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -145,8 +142,8 @@ glx_init(session_t *ps, bool need_render) {
|
||||||
#ifdef DEBUG_GLX_DEBUG_CONTEXT
|
#ifdef DEBUG_GLX_DEBUG_CONTEXT
|
||||||
{
|
{
|
||||||
f_DebugMessageCallback p_DebugMessageCallback =
|
f_DebugMessageCallback p_DebugMessageCallback =
|
||||||
(f_DebugMessageCallback)
|
(f_DebugMessageCallback)glXGetProcAddress(
|
||||||
glXGetProcAddress((const GLubyte *) "glDebugMessageCallback");
|
(const GLubyte *)"glDebugMessageCallback");
|
||||||
if (!p_DebugMessageCallback) {
|
if (!p_DebugMessageCallback) {
|
||||||
log_error("Failed to get glDebugMessageCallback(0.");
|
log_error("Failed to get glDebugMessageCallback(0.");
|
||||||
goto glx_init_end;
|
goto glx_init_end;
|
||||||
|
@ -154,7 +151,6 @@ glx_init(session_t *ps, bool need_render) {
|
||||||
p_DebugMessageCallback(glx_debug_msg_callback, ps);
|
p_DebugMessageCallback(glx_debug_msg_callback, ps);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure we have a stencil buffer. X Fixes does not guarantee rectangles
|
// Ensure we have a stencil buffer. X Fixes does not guarantee rectangles
|
||||||
|
@ -172,8 +168,8 @@ glx_init(session_t *ps, bool need_render) {
|
||||||
// Check GL_ARB_texture_non_power_of_two, requires a GLX context and
|
// Check GL_ARB_texture_non_power_of_two, requires a GLX context and
|
||||||
// must precede FBConfig fetching
|
// must precede FBConfig fetching
|
||||||
if (need_render)
|
if (need_render)
|
||||||
psglx->has_texture_non_power_of_two = gl_has_extension(
|
psglx->has_texture_non_power_of_two =
|
||||||
"GL_ARB_texture_non_power_of_two");
|
gl_has_extension("GL_ARB_texture_non_power_of_two");
|
||||||
|
|
||||||
// Render preparations
|
// Render preparations
|
||||||
if (need_render) {
|
if (need_render) {
|
||||||
|
@ -209,8 +205,7 @@ glx_init_end:
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void glx_free_prog_main(session_t *ps, glx_prog_main_t *pprogram) {
|
||||||
glx_free_prog_main(session_t *ps, glx_prog_main_t *pprogram) {
|
|
||||||
if (!pprogram)
|
if (!pprogram)
|
||||||
return;
|
return;
|
||||||
if (pprogram->prog) {
|
if (pprogram->prog) {
|
||||||
|
@ -225,8 +220,7 @@ glx_free_prog_main(session_t *ps, glx_prog_main_t *pprogram) {
|
||||||
/**
|
/**
|
||||||
* Destroy GLX related resources.
|
* Destroy GLX related resources.
|
||||||
*/
|
*/
|
||||||
void
|
void glx_destroy(session_t *ps) {
|
||||||
glx_destroy(session_t *ps) {
|
|
||||||
if (!ps->psglx)
|
if (!ps->psglx)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -260,8 +254,7 @@ glx_destroy(session_t *ps) {
|
||||||
/**
|
/**
|
||||||
* Callback to run on root window size change.
|
* Callback to run on root window size change.
|
||||||
*/
|
*/
|
||||||
void
|
void glx_on_root_change(session_t *ps) {
|
||||||
glx_on_root_change(session_t *ps) {
|
|
||||||
glViewport(0, 0, ps->root_width, ps->root_height);
|
glViewport(0, 0, ps->root_width, ps->root_height);
|
||||||
|
|
||||||
// Initialize matrix, copied from dcompmgr
|
// Initialize matrix, copied from dcompmgr
|
||||||
|
@ -275,8 +268,7 @@ glx_on_root_change(session_t *ps) {
|
||||||
/**
|
/**
|
||||||
* Initialize GLX blur filter.
|
* Initialize GLX blur filter.
|
||||||
*/
|
*/
|
||||||
bool
|
bool glx_init_blur(session_t *ps) {
|
||||||
glx_init_blur(session_t *ps) {
|
|
||||||
assert(ps->o.blur_kerns[0]);
|
assert(ps->o.blur_kerns[0]);
|
||||||
|
|
||||||
// Allocate PBO if more than one blur kernel is present
|
// Allocate PBO if more than one blur kernel is present
|
||||||
|
@ -285,7 +277,8 @@ glx_init_blur(session_t *ps) {
|
||||||
GLuint fbo = 0;
|
GLuint fbo = 0;
|
||||||
glGenFramebuffers(1, &fbo);
|
glGenFramebuffers(1, &fbo);
|
||||||
if (!fbo) {
|
if (!fbo) {
|
||||||
log_error("Failed to generate Framebuffer. Cannot do multi-pass blur with GLX"
|
log_error("Failed to generate Framebuffer. Cannot do multi-pass "
|
||||||
|
"blur with GLX"
|
||||||
" backend.");
|
" backend.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -309,21 +302,22 @@ glx_init_blur(session_t *ps) {
|
||||||
"void main() {\n"
|
"void main() {\n"
|
||||||
" vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);\n";
|
" vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);\n";
|
||||||
static const char *FRAG_SHADER_BLUR_ADD =
|
static const char *FRAG_SHADER_BLUR_ADD =
|
||||||
" sum += float(%.7g) * %s(tex_scr, vec2(gl_TexCoord[0].x + offset_x * float(%d), gl_TexCoord[0].y + offset_y * float(%d)));\n";
|
" sum += float(%.7g) * %s(tex_scr, vec2(gl_TexCoord[0].x + offset_x "
|
||||||
|
"* float(%d), gl_TexCoord[0].y + offset_y * float(%d)));\n";
|
||||||
static const char *FRAG_SHADER_BLUR_SUFFIX =
|
static const char *FRAG_SHADER_BLUR_SUFFIX =
|
||||||
" sum += %s(tex_scr, vec2(gl_TexCoord[0].x, gl_TexCoord[0].y)) * factor_center;\n"
|
" sum += %s(tex_scr, vec2(gl_TexCoord[0].x, gl_TexCoord[0].y)) * "
|
||||||
|
"factor_center;\n"
|
||||||
" gl_FragColor = sum / (factor_center + float(%.7g));\n"
|
" gl_FragColor = sum / (factor_center + float(%.7g));\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
const bool use_texture_rect = !ps->psglx->has_texture_non_power_of_two;
|
const bool use_texture_rect = !ps->psglx->has_texture_non_power_of_two;
|
||||||
const char *sampler_type = (use_texture_rect ?
|
const char *sampler_type = (use_texture_rect ? "sampler2DRect" : "sampler2D");
|
||||||
"sampler2DRect": "sampler2D");
|
const char *texture_func = (use_texture_rect ? "texture2DRect" : "texture2D");
|
||||||
const char *texture_func = (use_texture_rect ?
|
|
||||||
"texture2DRect": "texture2D");
|
|
||||||
const char *shader_add = FRAG_SHADER_BLUR_ADD;
|
const char *shader_add = FRAG_SHADER_BLUR_ADD;
|
||||||
char *extension = NULL;
|
char *extension = NULL;
|
||||||
if (use_texture_rect) {
|
if (use_texture_rect) {
|
||||||
mstrextend(&extension, "#extension GL_ARB_texture_rectangle : require\n");
|
mstrextend(&extension, "#extension GL_ARB_texture_rectangle : "
|
||||||
|
"require\n");
|
||||||
}
|
}
|
||||||
if (!extension) {
|
if (!extension) {
|
||||||
extension = strdup("");
|
extension = strdup("");
|
||||||
|
@ -337,9 +331,9 @@ glx_init_blur(session_t *ps) {
|
||||||
{
|
{
|
||||||
int width = kern->w, height = kern->h;
|
int width = kern->w, height = kern->h;
|
||||||
int nele = width * height - 1;
|
int nele = width * height - 1;
|
||||||
unsigned int len = strlen(FRAG_SHADER_BLUR_PREFIX) +
|
unsigned int len =
|
||||||
strlen(sampler_type) +
|
strlen(FRAG_SHADER_BLUR_PREFIX) +
|
||||||
strlen(extension) +
|
strlen(sampler_type) + strlen(extension) +
|
||||||
(strlen(shader_add) + strlen(texture_func) + 42) * nele +
|
(strlen(shader_add) + strlen(texture_func) + 42) * nele +
|
||||||
strlen(FRAG_SHADER_BLUR_SUFFIX) +
|
strlen(FRAG_SHADER_BLUR_SUFFIX) +
|
||||||
strlen(texture_func) + 12 + 1;
|
strlen(texture_func) + 12 + 1;
|
||||||
|
@ -359,7 +353,8 @@ glx_init_blur(session_t *ps) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sum += val;
|
sum += val;
|
||||||
sprintf(pc, shader_add, val, texture_func, k - width / 2, j - height / 2);
|
sprintf(pc, shader_add, val, texture_func,
|
||||||
|
k - width / 2, j - height / 2);
|
||||||
pc += strlen(pc);
|
pc += strlen(pc);
|
||||||
assert(strlen(shader_str) < len);
|
assert(strlen(shader_str) < len);
|
||||||
}
|
}
|
||||||
|
@ -367,7 +362,8 @@ glx_init_blur(session_t *ps) {
|
||||||
|
|
||||||
sprintf(pc, FRAG_SHADER_BLUR_SUFFIX, texture_func, sum);
|
sprintf(pc, FRAG_SHADER_BLUR_SUFFIX, texture_func, sum);
|
||||||
assert(strlen(shader_str) < len);
|
assert(strlen(shader_str) < len);
|
||||||
ppass->frag_shader = gl_create_shader(GL_FRAGMENT_SHADER, shader_str);
|
ppass->frag_shader =
|
||||||
|
gl_create_shader(GL_FRAGMENT_SHADER, shader_str);
|
||||||
free(shader_str);
|
free(shader_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,10 +384,13 @@ glx_init_blur(session_t *ps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get uniform addresses
|
// Get uniform addresses
|
||||||
#define P_GET_UNIFM_LOC(name, target) { \
|
#define P_GET_UNIFM_LOC(name, target) \
|
||||||
|
{ \
|
||||||
ppass->target = glGetUniformLocation(ppass->prog, name); \
|
ppass->target = glGetUniformLocation(ppass->prog, name); \
|
||||||
if (ppass->target < 0) { \
|
if (ppass->target < 0) { \
|
||||||
log_error("Failed to get location of %d-th uniform '" name "'. Might be troublesome.", i); \
|
log_error("Failed to get location of %d-th uniform '" name \
|
||||||
|
"'. Might be troublesome.", \
|
||||||
|
i); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,7 +407,6 @@ glx_init_blur(session_t *ps) {
|
||||||
free(lc_numeric_old);
|
free(lc_numeric_old);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gl_check_err();
|
gl_check_err();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -417,9 +415,7 @@ glx_init_blur(session_t *ps) {
|
||||||
/**
|
/**
|
||||||
* Load a GLSL main program from shader strings.
|
* Load a GLSL main program from shader strings.
|
||||||
*/
|
*/
|
||||||
bool
|
bool glx_load_prog_main(session_t *ps, const char *vshader_str, const char *fshader_str,
|
||||||
glx_load_prog_main(session_t *ps,
|
|
||||||
const char *vshader_str, const char *fshader_str,
|
|
||||||
glx_prog_main_t *pprogram) {
|
glx_prog_main_t *pprogram) {
|
||||||
assert(pprogram);
|
assert(pprogram);
|
||||||
|
|
||||||
|
@ -431,10 +427,12 @@ glx_load_prog_main(session_t *ps,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get uniform addresses
|
// Get uniform addresses
|
||||||
#define P_GET_UNIFM_LOC(name, target) { \
|
#define P_GET_UNIFM_LOC(name, target) \
|
||||||
|
{ \
|
||||||
pprogram->target = glGetUniformLocation(pprogram->prog, name); \
|
pprogram->target = glGetUniformLocation(pprogram->prog, name); \
|
||||||
if (pprogram->target < 0) { \
|
if (pprogram->target < 0) { \
|
||||||
log_error("Failed to get location of uniform '" name "'. Might be troublesome."); \
|
log_error("Failed to get location of uniform '" name \
|
||||||
|
"'. Might be troublesome."); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
P_GET_UNIFM_LOC("opacity", unifm_opacity);
|
P_GET_UNIFM_LOC("opacity", unifm_opacity);
|
||||||
|
@ -450,9 +448,8 @@ glx_load_prog_main(session_t *ps,
|
||||||
/**
|
/**
|
||||||
* Bind a X pixmap to an OpenGL texture.
|
* Bind a X pixmap to an OpenGL texture.
|
||||||
*/
|
*/
|
||||||
bool
|
bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap, unsigned width,
|
||||||
glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap,
|
unsigned height, bool repeat, const struct glx_fbconfig_info *fbcfg) {
|
||||||
unsigned width, unsigned height, bool repeat, const struct glx_fbconfig_info *fbcfg) {
|
|
||||||
if (ps->o.backend != BKEND_GLX && ps->o.backend != BKEND_XR_GLX_HYBRID)
|
if (ps->o.backend != BKEND_GLX && ps->o.backend != BKEND_XR_GLX_HYBRID)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -497,8 +494,8 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap,
|
||||||
Window rroot = None;
|
Window rroot = None;
|
||||||
int rx = 0, ry = 0;
|
int rx = 0, ry = 0;
|
||||||
unsigned rbdwid = 0;
|
unsigned rbdwid = 0;
|
||||||
if (!XGetGeometry(ps->dpy, pixmap, &rroot, &rx, &ry,
|
if (!XGetGeometry(ps->dpy, pixmap, &rroot, &rx, &ry, &width,
|
||||||
&width, &height, &rbdwid, &depth)) {
|
&height, &rbdwid, &depth)) {
|
||||||
log_error("Failed to query info of pixmap %#010x.", pixmap);
|
log_error("Failed to query info of pixmap %#010x.", pixmap);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -513,8 +510,8 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap,
|
||||||
// The assumption we made here is the target never changes based on any
|
// The assumption we made here is the target never changes based on any
|
||||||
// pixmap-specific parameters, and this may change in the future
|
// pixmap-specific parameters, and this may change in the future
|
||||||
GLenum tex_tgt = 0;
|
GLenum tex_tgt = 0;
|
||||||
if (GLX_TEXTURE_2D_BIT_EXT & fbcfg->texture_tgts
|
if (GLX_TEXTURE_2D_BIT_EXT & fbcfg->texture_tgts &&
|
||||||
&& ps->psglx->has_texture_non_power_of_two)
|
ps->psglx->has_texture_non_power_of_two)
|
||||||
tex_tgt = GLX_TEXTURE_2D_EXT;
|
tex_tgt = GLX_TEXTURE_2D_EXT;
|
||||||
else if (GLX_TEXTURE_RECTANGLE_BIT_EXT & fbcfg->texture_tgts)
|
else if (GLX_TEXTURE_RECTANGLE_BIT_EXT & fbcfg->texture_tgts)
|
||||||
tex_tgt = GLX_TEXTURE_RECTANGLE_EXT;
|
tex_tgt = GLX_TEXTURE_RECTANGLE_EXT;
|
||||||
|
@ -536,8 +533,8 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap,
|
||||||
|
|
||||||
ptex->glpixmap = glXCreatePixmap(ps->dpy, fbcfg->cfg, pixmap, attrs);
|
ptex->glpixmap = glXCreatePixmap(ps->dpy, fbcfg->cfg, pixmap, attrs);
|
||||||
ptex->pixmap = pixmap;
|
ptex->pixmap = pixmap;
|
||||||
ptex->target = (GLX_TEXTURE_2D_EXT == tex_tgt ? GL_TEXTURE_2D:
|
ptex->target =
|
||||||
GL_TEXTURE_RECTANGLE);
|
(GLX_TEXTURE_2D_EXT == tex_tgt ? GL_TEXTURE_2D : GL_TEXTURE_RECTANGLE);
|
||||||
ptex->width = width;
|
ptex->width = width;
|
||||||
ptex->height = height;
|
ptex->height = height;
|
||||||
ptex->y_inverted = fbcfg->y_inverted;
|
ptex->y_inverted = fbcfg->y_inverted;
|
||||||
|
@ -597,8 +594,7 @@ glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap,
|
||||||
/**
|
/**
|
||||||
* @brief Release binding of a texture.
|
* @brief Release binding of a texture.
|
||||||
*/
|
*/
|
||||||
void
|
void glx_release_pixmap(session_t *ps, glx_texture_t *ptex) {
|
||||||
glx_release_pixmap(session_t *ps, glx_texture_t *ptex) {
|
|
||||||
// Release binding
|
// Release binding
|
||||||
if (ptex->glpixmap && ptex->texture) {
|
if (ptex->glpixmap && ptex->texture) {
|
||||||
glBindTexture(ptex->target, ptex->texture);
|
glBindTexture(ptex->target, ptex->texture);
|
||||||
|
@ -618,8 +614,7 @@ glx_release_pixmap(session_t *ps, glx_texture_t *ptex) {
|
||||||
/**
|
/**
|
||||||
* Set clipping region on the target window.
|
* Set clipping region on the target window.
|
||||||
*/
|
*/
|
||||||
void
|
void glx_set_clip(session_t *ps, const region_t *reg) {
|
||||||
glx_set_clip(session_t *ps, const region_t *reg) {
|
|
||||||
// Quit if we aren't using stencils
|
// Quit if we aren't using stencils
|
||||||
if (ps->o.glx_no_stencil)
|
if (ps->o.glx_no_stencil)
|
||||||
return;
|
return;
|
||||||
|
@ -660,30 +655,28 @@ glx_set_clip(session_t *ps, const region_t *reg) {
|
||||||
\
|
\
|
||||||
pixman_region32_fini(®_new);
|
pixman_region32_fini(®_new);
|
||||||
|
|
||||||
static inline GLuint
|
static inline GLuint glx_gen_texture(session_t *ps, GLenum tex_tgt, int width, int height) {
|
||||||
glx_gen_texture(session_t *ps, GLenum tex_tgt, int width, int height) {
|
|
||||||
GLuint tex = 0;
|
GLuint tex = 0;
|
||||||
glGenTextures(1, &tex);
|
glGenTextures(1, &tex);
|
||||||
if (!tex) return 0;
|
if (!tex)
|
||||||
|
return 0;
|
||||||
glEnable(tex_tgt);
|
glEnable(tex_tgt);
|
||||||
glBindTexture(tex_tgt, tex);
|
glBindTexture(tex_tgt, tex);
|
||||||
glTexParameteri(tex_tgt, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(tex_tgt, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(tex_tgt, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(tex_tgt, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(tex_tgt, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glTexParameteri(tex_tgt, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(tex_tgt, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameteri(tex_tgt, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
glTexImage2D(tex_tgt, 0, GL_RGB, width, height, 0, GL_RGB,
|
glTexImage2D(tex_tgt, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||||
GL_UNSIGNED_BYTE, NULL);
|
|
||||||
glBindTexture(tex_tgt, 0);
|
glBindTexture(tex_tgt, 0);
|
||||||
|
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void glx_copy_region_to_tex(session_t *ps, GLenum tex_tgt, int basex,
|
||||||
glx_copy_region_to_tex(session_t *ps, GLenum tex_tgt, int basex, int basey,
|
int basey, int dx, int dy, int width, int height) {
|
||||||
int dx, int dy, int width, int height) {
|
|
||||||
if (width > 0 && height > 0)
|
if (width > 0 && height > 0)
|
||||||
glCopyTexSubImage2D(tex_tgt, 0, dx - basex, dy - basey,
|
glCopyTexSubImage2D(tex_tgt, 0, dx - basex, dy - basey, dx,
|
||||||
dx, ps->root_height - dy - height, width, height);
|
ps->root_height - dy - height, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -691,11 +684,8 @@ glx_copy_region_to_tex(session_t *ps, GLenum tex_tgt, int basex, int basey,
|
||||||
*
|
*
|
||||||
* XXX seems to be way to complex for what it does
|
* XXX seems to be way to complex for what it does
|
||||||
*/
|
*/
|
||||||
bool
|
bool glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z,
|
||||||
glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z,
|
GLfloat factor_center, const region_t *reg_tgt, glx_blur_cache_t *pbc) {
|
||||||
GLfloat factor_center,
|
|
||||||
const region_t *reg_tgt,
|
|
||||||
glx_blur_cache_t *pbc) {
|
|
||||||
assert(ps->psglx->blur_passes[0].prog);
|
assert(ps->psglx->blur_passes[0].prog);
|
||||||
const bool more_passes = ps->psglx->blur_passes[1].prog;
|
const bool more_passes = ps->psglx->blur_passes[1].prog;
|
||||||
const bool have_scissors = glIsEnabled(GL_SCISSOR_TEST);
|
const bool have_scissors = glIsEnabled(GL_SCISSOR_TEST);
|
||||||
|
@ -804,13 +794,11 @@ glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z,
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||||
GL_TEXTURE_2D, tex_scr2, 0);
|
GL_TEXTURE_2D, tex_scr2, 0);
|
||||||
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER)
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
!= GL_FRAMEBUFFER_COMPLETE) {
|
|
||||||
log_error("Framebuffer attachment failed.");
|
log_error("Framebuffer attachment failed.");
|
||||||
goto glx_blur_dst_end;
|
goto glx_blur_dst_end;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
glDrawBuffer(GL_BACK);
|
glDrawBuffer(GL_BACK);
|
||||||
if (have_scissors)
|
if (have_scissors)
|
||||||
|
@ -848,7 +836,8 @@ glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z,
|
||||||
GLfloat rdxe = rdx + (crect.x2 - crect.x1);
|
GLfloat rdxe = rdx + (crect.x2 - crect.x1);
|
||||||
GLfloat rdye = rdy - (crect.y2 - crect.y1);
|
GLfloat rdye = rdy - (crect.y2 - crect.y1);
|
||||||
|
|
||||||
//log_trace("%f, %f, %f, %f -> %f, %f, %f, %f", rx, ry, rxe, rye, rdx,
|
// log_trace("%f, %f, %f, %f -> %f, %f, %f, %f", rx, ry,
|
||||||
|
// rxe, rye, rdx,
|
||||||
// rdy, rdxe, rdye);
|
// rdy, rdxe, rdye);
|
||||||
|
|
||||||
glTexCoord2f(rx, ry);
|
glTexCoord2f(rx, ry);
|
||||||
|
@ -862,7 +851,8 @@ glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z,
|
||||||
|
|
||||||
glTexCoord2f(rx, rye);
|
glTexCoord2f(rx, rye);
|
||||||
glVertex3f(rdx, rdye, z);
|
glVertex3f(rdx, rdye, z);
|
||||||
} P_PAINTREG_END();
|
}
|
||||||
|
P_PAINTREG_END();
|
||||||
}
|
}
|
||||||
|
|
||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
|
@ -895,8 +885,7 @@ glx_blur_dst_end:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z,
|
||||||
glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z,
|
|
||||||
GLfloat factor, const region_t *reg_tgt) {
|
GLfloat factor, const region_t *reg_tgt) {
|
||||||
// It's possible to dim in glx_render(), but it would be over-complicated
|
// It's possible to dim in glx_render(), but it would be over-complicated
|
||||||
// considering all those mess in color negation and modulation
|
// considering all those mess in color negation and modulation
|
||||||
|
@ -931,12 +920,9 @@ glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z,
|
||||||
/**
|
/**
|
||||||
* @brief Render a region with texture data.
|
* @brief Render a region with texture data.
|
||||||
*/
|
*/
|
||||||
bool
|
bool glx_render(session_t *ps, const glx_texture_t *ptex, int x, int y, int dx, int dy,
|
||||||
glx_render(session_t *ps, const glx_texture_t *ptex,
|
int width, int height, int z, double opacity, bool argb, bool neg,
|
||||||
int x, int y, int dx, int dy, int width, int height, int z,
|
const region_t *reg_tgt, const glx_prog_main_t *pprogram) {
|
||||||
double opacity, bool argb, bool neg,
|
|
||||||
const region_t *reg_tgt, const glx_prog_main_t *pprogram
|
|
||||||
) {
|
|
||||||
if (!ptex || !ptex->texture) {
|
if (!ptex || !ptex->texture) {
|
||||||
log_error("Missing texture.");
|
log_error("Missing texture.");
|
||||||
return false;
|
return false;
|
||||||
|
@ -963,8 +949,7 @@ glx_render(session_t *ps, const glx_texture_t *ptex,
|
||||||
glColor4f(opacity, opacity, opacity, opacity);
|
glColor4f(opacity, opacity, opacity, opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!has_prog)
|
if (!has_prog) {
|
||||||
{
|
|
||||||
// The default, fixed-function path
|
// The default, fixed-function path
|
||||||
// Color negation
|
// Color negation
|
||||||
if (neg) {
|
if (neg) {
|
||||||
|
@ -977,9 +962,9 @@ glx_render(session_t *ps, const glx_texture_t *ptex,
|
||||||
else if (argb) {
|
else if (argb) {
|
||||||
dual_texture = true;
|
dual_texture = true;
|
||||||
|
|
||||||
// Use two texture stages because the calculation is too complicated,
|
// Use two texture stages because the calculation is too
|
||||||
// thanks to madsy for providing code
|
// complicated, thanks to madsy for providing code Texture
|
||||||
// Texture stage 0
|
// stage 0
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
// Negation for premultiplied color: color = A - C
|
// Negation for premultiplied color: color = A - C
|
||||||
|
@ -1025,7 +1010,8 @@ glx_render(session_t *ps, const glx_texture_t *ptex,
|
||||||
// Modulation with constant factor
|
// Modulation with constant factor
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
|
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_ONE_MINUS_SRC_COLOR);
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB,
|
||||||
|
GL_ONE_MINUS_SRC_COLOR);
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
|
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
|
||||||
|
|
||||||
|
@ -1037,8 +1023,7 @@ glx_render(session_t *ps, const glx_texture_t *ptex,
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
|
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// Programmable path
|
// Programmable path
|
||||||
assert(pprogram->prog);
|
assert(pprogram->prog);
|
||||||
glUseProgram(pprogram->prog);
|
glUseProgram(pprogram->prog);
|
||||||
|
@ -1069,8 +1054,8 @@ glx_render(session_t *ps, const glx_texture_t *ptex,
|
||||||
GLfloat ry = (double)(crect.y1 - dy + y);
|
GLfloat ry = (double)(crect.y1 - dy + y);
|
||||||
GLfloat rxe = rx + (double)(crect.x2 - crect.x1);
|
GLfloat rxe = rx + (double)(crect.x2 - crect.x1);
|
||||||
GLfloat rye = ry + (double)(crect.y2 - crect.y1);
|
GLfloat rye = ry + (double)(crect.y2 - crect.y1);
|
||||||
// Rectangle textures have [0-w] [0-h] while 2D texture has [0-1] [0-1]
|
// Rectangle textures have [0-w] [0-h] while 2D texture has [0-1]
|
||||||
// Thanks to amonakov for pointing out!
|
// [0-1] Thanks to amonakov for pointing out!
|
||||||
if (GL_TEXTURE_2D == ptex->target) {
|
if (GL_TEXTURE_2D == ptex->target) {
|
||||||
rx = rx / ptex->width;
|
rx = rx / ptex->width;
|
||||||
ry = ry / ptex->height;
|
ry = ry / ptex->height;
|
||||||
|
@ -1082,22 +1067,24 @@ glx_render(session_t *ps, const glx_texture_t *ptex,
|
||||||
GLint rdxe = rdx + (crect.x2 - crect.x1);
|
GLint rdxe = rdx + (crect.x2 - crect.x1);
|
||||||
GLint rdye = rdy - (crect.y2 - crect.y1);
|
GLint rdye = rdy - (crect.y2 - crect.y1);
|
||||||
|
|
||||||
// Invert Y if needed, this may not work as expected, though. I don't
|
// Invert Y if needed, this may not work as expected, though. I
|
||||||
// have such a FBConfig to test with.
|
// don't have such a FBConfig to test with.
|
||||||
if (!ptex->y_inverted) {
|
if (!ptex->y_inverted) {
|
||||||
ry = 1.0 - ry;
|
ry = 1.0 - ry;
|
||||||
rye = 1.0 - rye;
|
rye = 1.0 - rye;
|
||||||
}
|
}
|
||||||
|
|
||||||
//log_trace("Rect %d: %f, %f, %f, %f -> %d, %d, %d, %d", ri, rx, ry, rxe, rye,
|
// log_trace("Rect %d: %f, %f, %f, %f -> %d, %d, %d, %d", ri, rx,
|
||||||
|
// ry, rxe, rye,
|
||||||
// rdx, rdy, rdxe, rdye);
|
// rdx, rdy, rdxe, rdye);
|
||||||
|
|
||||||
#define P_TEXCOORD(cx, cy) { \
|
#define P_TEXCOORD(cx, cy) \
|
||||||
|
{ \
|
||||||
if (dual_texture) { \
|
if (dual_texture) { \
|
||||||
glMultiTexCoord2f(GL_TEXTURE0, cx, cy); \
|
glMultiTexCoord2f(GL_TEXTURE0, cx, cy); \
|
||||||
glMultiTexCoord2f(GL_TEXTURE1, cx, cy); \
|
glMultiTexCoord2f(GL_TEXTURE1, cx, cy); \
|
||||||
} \
|
} else \
|
||||||
else glTexCoord2f(cx, cy); \
|
glTexCoord2f(cx, cy); \
|
||||||
}
|
}
|
||||||
P_TEXCOORD(rx, ry);
|
P_TEXCOORD(rx, ry);
|
||||||
glVertex3i(rdx, rdy, z);
|
glVertex3i(rdx, rdy, z);
|
||||||
|
@ -1110,7 +1097,8 @@ glx_render(session_t *ps, const glx_texture_t *ptex,
|
||||||
|
|
||||||
P_TEXCOORD(rx, rye);
|
P_TEXCOORD(rx, rye);
|
||||||
glVertex3i(rdx, rdye, z);
|
glVertex3i(rdx, rdye, z);
|
||||||
} P_PAINTREG_END();
|
}
|
||||||
|
P_PAINTREG_END();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
|
|
109
src/opengl.h
109
src/opengl.h
|
@ -12,104 +12,78 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "compiler.h"
|
||||||
|
#include "log.h"
|
||||||
#include "region.h"
|
#include "region.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "compiler.h"
|
|
||||||
#include "win.h"
|
#include "win.h"
|
||||||
#include "log.h"
|
|
||||||
|
|
||||||
#include <xcb/xcb.h>
|
#include <GL/gl.h>
|
||||||
#include <xcb/render.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <GL/gl.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <xcb/render.h>
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
|
||||||
bool
|
bool glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z,
|
||||||
glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z,
|
|
||||||
GLfloat factor, const region_t *reg_tgt);
|
GLfloat factor, const region_t *reg_tgt);
|
||||||
|
|
||||||
bool
|
bool glx_render(session_t *ps, const glx_texture_t *ptex, int x, int y, int dx, int dy,
|
||||||
glx_render(session_t *ps, const glx_texture_t *ptex,
|
int width, int height, int z, double opacity, bool argb, bool neg,
|
||||||
int x, int y, int dx, int dy, int width, int height, int z,
|
const region_t *reg_tgt, const glx_prog_main_t *pprogram);
|
||||||
double opacity, bool argb, bool neg,
|
|
||||||
const region_t *reg_tgt,
|
|
||||||
const glx_prog_main_t *pprogram);
|
|
||||||
|
|
||||||
bool
|
bool glx_init(session_t *ps, bool need_render);
|
||||||
glx_init(session_t *ps, bool need_render);
|
|
||||||
|
|
||||||
void
|
void glx_destroy(session_t *ps);
|
||||||
glx_destroy(session_t *ps);
|
|
||||||
|
|
||||||
void
|
void glx_on_root_change(session_t *ps);
|
||||||
glx_on_root_change(session_t *ps);
|
|
||||||
|
|
||||||
bool
|
bool glx_init_blur(session_t *ps);
|
||||||
glx_init_blur(session_t *ps);
|
|
||||||
|
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
bool
|
bool glx_load_prog_main(session_t *ps, const char *vshader_str, const char *fshader_str,
|
||||||
glx_load_prog_main(session_t *ps,
|
|
||||||
const char *vshader_str, const char *fshader_str,
|
|
||||||
glx_prog_main_t *pprogram);
|
glx_prog_main_t *pprogram);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool
|
bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap, unsigned width,
|
||||||
glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap,
|
unsigned height, bool repeat, const struct glx_fbconfig_info *);
|
||||||
unsigned width, unsigned height, bool repeat, const struct glx_fbconfig_info *);
|
|
||||||
|
|
||||||
void
|
void glx_release_pixmap(session_t *ps, glx_texture_t *ptex);
|
||||||
glx_release_pixmap(session_t *ps, glx_texture_t *ptex);
|
|
||||||
|
|
||||||
void glx_paint_pre(session_t *ps, region_t *preg)
|
void glx_paint_pre(session_t *ps, region_t *preg) attr_nonnull(1, 2);
|
||||||
attr_nonnull(1, 2);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a texture is binded, or is binded to the given pixmap.
|
* Check if a texture is binded, or is binded to the given pixmap.
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool glx_tex_binded(const glx_texture_t *ptex, xcb_pixmap_t pixmap) {
|
||||||
glx_tex_binded(const glx_texture_t *ptex, xcb_pixmap_t pixmap) {
|
return ptex && ptex->glpixmap && ptex->texture && (!pixmap || pixmap == ptex->pixmap);
|
||||||
return ptex && ptex->glpixmap && ptex->texture
|
|
||||||
&& (!pixmap || pixmap == ptex->pixmap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void glx_set_clip(session_t *ps, const region_t *reg);
|
||||||
glx_set_clip(session_t *ps, const region_t *reg);
|
|
||||||
|
|
||||||
bool
|
bool glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z,
|
||||||
glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z,
|
GLfloat factor_center, const region_t *reg_tgt, glx_blur_cache_t *pbc);
|
||||||
GLfloat factor_center,
|
|
||||||
const region_t *reg_tgt,
|
|
||||||
glx_blur_cache_t *pbc);
|
|
||||||
|
|
||||||
GLuint
|
GLuint glx_create_shader(GLenum shader_type, const char *shader_str);
|
||||||
glx_create_shader(GLenum shader_type, const char *shader_str);
|
|
||||||
|
|
||||||
GLuint
|
GLuint glx_create_program(const GLuint *const shaders, int nshaders);
|
||||||
glx_create_program(const GLuint * const shaders, int nshaders);
|
|
||||||
|
|
||||||
GLuint
|
GLuint glx_create_program_from_str(const char *vert_shader_str, const char *frag_shader_str);
|
||||||
glx_create_program_from_str(const char *vert_shader_str,
|
|
||||||
const char *frag_shader_str);
|
|
||||||
|
|
||||||
unsigned char *
|
unsigned char *glx_take_screenshot(session_t *ps, int *out_length);
|
||||||
glx_take_screenshot(session_t *ps, int *out_length);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if there's a GLX context.
|
* Check if there's a GLX context.
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool glx_has_context(session_t *ps) {
|
||||||
glx_has_context(session_t *ps) {
|
|
||||||
return ps->psglx && ps->psglx->context;
|
return ps->psglx && ps->psglx->context;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure we have a GLX context.
|
* Ensure we have a GLX context.
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool ensure_glx_context(session_t *ps) {
|
||||||
ensure_glx_context(session_t *ps) {
|
|
||||||
// Create GLX context
|
// Create GLX context
|
||||||
if (!glx_has_context(ps))
|
if (!glx_has_context(ps))
|
||||||
glx_init(ps, false);
|
glx_init(ps, false);
|
||||||
|
@ -120,8 +94,7 @@ ensure_glx_context(session_t *ps) {
|
||||||
/**
|
/**
|
||||||
* Free a GLX texture.
|
* Free a GLX texture.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void free_texture_r(session_t *ps, GLuint *ptexture) {
|
||||||
free_texture_r(session_t *ps, GLuint *ptexture) {
|
|
||||||
if (*ptexture) {
|
if (*ptexture) {
|
||||||
assert(glx_has_context(ps));
|
assert(glx_has_context(ps));
|
||||||
glDeleteTextures(1, ptexture);
|
glDeleteTextures(1, ptexture);
|
||||||
|
@ -132,8 +105,7 @@ free_texture_r(session_t *ps, GLuint *ptexture) {
|
||||||
/**
|
/**
|
||||||
* Free a GLX Framebuffer object.
|
* Free a GLX Framebuffer object.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void free_glx_fbo(session_t *ps, GLuint *pfbo) {
|
||||||
free_glx_fbo(session_t *ps, GLuint *pfbo) {
|
|
||||||
if (*pfbo) {
|
if (*pfbo) {
|
||||||
glDeleteFramebuffers(1, pfbo);
|
glDeleteFramebuffers(1, pfbo);
|
||||||
*pfbo = 0;
|
*pfbo = 0;
|
||||||
|
@ -144,8 +116,7 @@ free_glx_fbo(session_t *ps, GLuint *pfbo) {
|
||||||
/**
|
/**
|
||||||
* Free data in glx_blur_cache_t on resize.
|
* Free data in glx_blur_cache_t on resize.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void free_glx_bc_resize(session_t *ps, glx_blur_cache_t *pbc) {
|
||||||
free_glx_bc_resize(session_t *ps, glx_blur_cache_t *pbc) {
|
|
||||||
free_texture_r(ps, &pbc->textures[0]);
|
free_texture_r(ps, &pbc->textures[0]);
|
||||||
free_texture_r(ps, &pbc->textures[1]);
|
free_texture_r(ps, &pbc->textures[1]);
|
||||||
pbc->width = 0;
|
pbc->width = 0;
|
||||||
|
@ -155,8 +126,7 @@ free_glx_bc_resize(session_t *ps, glx_blur_cache_t *pbc) {
|
||||||
/**
|
/**
|
||||||
* Free a glx_blur_cache_t
|
* Free a glx_blur_cache_t
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void free_glx_bc(session_t *ps, glx_blur_cache_t *pbc) {
|
||||||
free_glx_bc(session_t *ps, glx_blur_cache_t *pbc) {
|
|
||||||
free_glx_fbo(ps, &pbc->fbo);
|
free_glx_fbo(ps, &pbc->fbo);
|
||||||
free_glx_bc_resize(ps, pbc);
|
free_glx_bc_resize(ps, pbc);
|
||||||
}
|
}
|
||||||
|
@ -164,8 +134,7 @@ free_glx_bc(session_t *ps, glx_blur_cache_t *pbc) {
|
||||||
/**
|
/**
|
||||||
* Free a glx_texture_t.
|
* Free a glx_texture_t.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void free_texture(session_t *ps, glx_texture_t **pptex) {
|
||||||
free_texture(session_t *ps, glx_texture_t **pptex) {
|
|
||||||
glx_texture_t *ptex = *pptex;
|
glx_texture_t *ptex = *pptex;
|
||||||
|
|
||||||
// Quit if there's nothing
|
// Quit if there's nothing
|
||||||
|
@ -185,16 +154,14 @@ free_texture(session_t *ps, glx_texture_t **pptex) {
|
||||||
/**
|
/**
|
||||||
* Free GLX part of paint_t.
|
* Free GLX part of paint_t.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void free_paint_glx(session_t *ps, paint_t *ppaint) {
|
||||||
free_paint_glx(session_t *ps, paint_t *ppaint) {
|
|
||||||
free_texture(ps, &ppaint->ptex);
|
free_texture(ps, &ppaint->ptex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Free GLX part of win.
|
* Free GLX part of win.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void free_win_res_glx(session_t *ps, win *w) {
|
||||||
free_win_res_glx(session_t *ps, win *w) {
|
|
||||||
free_paint_glx(ps, &w->paint);
|
free_paint_glx(ps, &w->paint);
|
||||||
free_paint_glx(ps, &w->shadow_paint);
|
free_paint_glx(ps, &w->shadow_paint);
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
|
|
|
@ -7,8 +7,7 @@
|
||||||
#define mstrncmp(s1, s2) strncmp((s1), (s2), strlen(s1))
|
#define mstrncmp(s1, s2) strncmp((s1), (s2), strlen(s1))
|
||||||
|
|
||||||
char *mstrjoin(const char *src1, const char *src2);
|
char *mstrjoin(const char *src1, const char *src2);
|
||||||
char *
|
char *mstrjoin3(const char *src1, const char *src2, const char *src3);
|
||||||
mstrjoin3(const char *src1, const char *src2, const char *src3);
|
|
||||||
void mstrextend(char **psrc1, const char *src2);
|
void mstrextend(char **psrc1, const char *src2);
|
||||||
|
|
||||||
/// Parse a floating point number of form (+|-)?[0-9]*(\.[0-9]*)
|
/// Parse a floating point number of form (+|-)?[0-9]*(\.[0-9]*)
|
||||||
|
@ -33,8 +32,7 @@ static inline int uitostr(unsigned int n, char *buf) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline const char *
|
static inline const char *skip_space_const(const char *src) {
|
||||||
skip_space_const(const char *src) {
|
|
||||||
if (!src)
|
if (!src)
|
||||||
return NULL;
|
return NULL;
|
||||||
while (*src && isspace(*src))
|
while (*src && isspace(*src))
|
||||||
|
@ -42,8 +40,7 @@ skip_space_const(const char *src) {
|
||||||
return src;
|
return src;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline char *
|
static inline char *skip_space_mut(char *src) {
|
||||||
skip_space_mut(char *src) {
|
|
||||||
if (!src)
|
if (!src)
|
||||||
return NULL;
|
return NULL;
|
||||||
while (*src && isspace(*src))
|
while (*src && isspace(*src))
|
||||||
|
@ -51,7 +48,5 @@ skip_space_mut(char *src) {
|
||||||
return src;
|
return src;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define skip_space(x) _Generic((x), \
|
#define skip_space(x) \
|
||||||
char *: skip_space_mut, \
|
_Generic((x), char * : skip_space_mut, const char * : skip_space_const)(x)
|
||||||
const char *: skip_space_const \
|
|
||||||
)(x)
|
|
||||||
|
|
|
@ -32,4 +32,5 @@ typedef struct {
|
||||||
|
|
||||||
typedef uint32_t opacity_t;
|
typedef uint32_t opacity_t;
|
||||||
|
|
||||||
#define MARGIN_INIT { 0, 0, 0, 0 }
|
#define MARGIN_INIT \
|
||||||
|
{ 0, 0, 0, 0 }
|
||||||
|
|
56
src/vsync.c
56
src/vsync.c
|
@ -12,12 +12,12 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_VSYNC_DRM
|
#ifdef CONFIG_VSYNC_DRM
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <drm.h>
|
#include <drm.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
@ -27,15 +27,14 @@
|
||||||
/**
|
/**
|
||||||
* Wait for next VSync, DRM method.
|
* Wait for next VSync, DRM method.
|
||||||
*
|
*
|
||||||
* Stolen from: https://github.com/MythTV/mythtv/blob/master/mythtv/libs/libmythtv/vsync.cpp
|
* Stolen from:
|
||||||
|
* https://github.com/MythTV/mythtv/blob/master/mythtv/libs/libmythtv/vsync.cpp
|
||||||
*/
|
*/
|
||||||
static int
|
static int vsync_drm_wait(session_t *ps) {
|
||||||
vsync_drm_wait(session_t *ps) {
|
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
drm_wait_vblank_t vbl;
|
drm_wait_vblank_t vbl;
|
||||||
|
|
||||||
vbl.request.type = _DRM_VBLANK_RELATIVE,
|
vbl.request.type = _DRM_VBLANK_RELATIVE, vbl.request.sequence = 1;
|
||||||
vbl.request.sequence = 1;
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ret = ioctl(ps->drm_fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
|
ret = ioctl(ps->drm_fd, DRM_IOCTL_WAIT_VBLANK, &vbl);
|
||||||
|
@ -46,7 +45,6 @@ vsync_drm_wait(session_t *ps) {
|
||||||
log_error("VBlank ioctl did not work, unimplemented in this drmver?");
|
log_error("VBlank ioctl did not work, unimplemented in this drmver?");
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -55,8 +53,7 @@ vsync_drm_wait(session_t *ps) {
|
||||||
*
|
*
|
||||||
* @return true for success, false otherwise
|
* @return true for success, false otherwise
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool vsync_drm_init(session_t *ps) {
|
||||||
vsync_drm_init(session_t *ps) {
|
|
||||||
#ifdef CONFIG_VSYNC_DRM
|
#ifdef CONFIG_VSYNC_DRM
|
||||||
// Should we always open card0?
|
// Should we always open card0?
|
||||||
if (ps->drm_fd < 0 && (ps->drm_fd = open("/dev/dri/card0", O_RDWR)) < 0) {
|
if (ps->drm_fd < 0 && (ps->drm_fd = open("/dev/dri/card0", O_RDWR)) < 0) {
|
||||||
|
@ -77,13 +74,13 @@ vsync_drm_init(session_t *ps) {
|
||||||
/**
|
/**
|
||||||
* Initialize OpenGL VSync.
|
* Initialize OpenGL VSync.
|
||||||
*
|
*
|
||||||
* Stolen from: http://git.tuxfamily.org/?p=ccm/cairocompmgr.git;a=commitdiff;h=efa4ceb97da501e8630ca7f12c99b1dce853c73e
|
* Stolen from:
|
||||||
|
* http://git.tuxfamily.org/?p=ccm/cairocompmgr.git;a=commitdiff;h=efa4ceb97da501e8630ca7f12c99b1dce853c73e
|
||||||
* Possible original source: http://www.inb.uni-luebeck.de/~boehme/xvideo_sync.html
|
* Possible original source: http://www.inb.uni-luebeck.de/~boehme/xvideo_sync.html
|
||||||
*
|
*
|
||||||
* @return true for success, false otherwise
|
* @return true for success, false otherwise
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool vsync_opengl_init(session_t *ps) {
|
||||||
vsync_opengl_init(session_t *ps) {
|
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
if (!ensure_glx_context(ps))
|
if (!ensure_glx_context(ps))
|
||||||
return false;
|
return false;
|
||||||
|
@ -95,8 +92,7 @@ vsync_opengl_init(session_t *ps) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool vsync_opengl_oml_init(session_t *ps) {
|
||||||
vsync_opengl_oml_init(session_t *ps) {
|
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
if (!ensure_glx_context(ps))
|
if (!ensure_glx_context(ps))
|
||||||
return false;
|
return false;
|
||||||
|
@ -109,8 +105,7 @@ vsync_opengl_oml_init(session_t *ps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
static inline bool
|
static inline bool vsync_opengl_swc_swap_interval(session_t *ps, unsigned int interval) {
|
||||||
vsync_opengl_swc_swap_interval(session_t *ps, unsigned int interval) {
|
|
||||||
if (glxext.has_GLX_MESA_swap_control)
|
if (glxext.has_GLX_MESA_swap_control)
|
||||||
return glXSwapIntervalMESA(interval) == 0;
|
return glXSwapIntervalMESA(interval) == 0;
|
||||||
else if (glxext.has_GLX_SGI_swap_control)
|
else if (glxext.has_GLX_SGI_swap_control)
|
||||||
|
@ -128,8 +123,7 @@ vsync_opengl_swc_swap_interval(session_t *ps, unsigned int interval) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool
|
static bool vsync_opengl_swc_init(session_t *ps) {
|
||||||
vsync_opengl_swc_init(session_t *ps) {
|
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
if (!bkend_use_glx(ps)) {
|
if (!bkend_use_glx(ps)) {
|
||||||
log_warn("OpenGL swap control requires the GLX backend.");
|
log_warn("OpenGL swap control requires the GLX backend.");
|
||||||
|
@ -148,8 +142,7 @@ vsync_opengl_swc_init(session_t *ps) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool vsync_opengl_mswc_init(session_t *ps) {
|
||||||
vsync_opengl_mswc_init(session_t *ps) {
|
|
||||||
log_warn("opengl-mswc is deprecated, please use opengl-swc instead.");
|
log_warn("opengl-mswc is deprecated, please use opengl-swc instead.");
|
||||||
return vsync_opengl_swc_init(ps);
|
return vsync_opengl_swc_init(ps);
|
||||||
}
|
}
|
||||||
|
@ -166,8 +159,7 @@ bool (*const VSYNC_FUNCS_INIT[NUM_VSYNC])(session_t *ps) = {
|
||||||
/**
|
/**
|
||||||
* Wait for next VSync, OpenGL method.
|
* Wait for next VSync, OpenGL method.
|
||||||
*/
|
*/
|
||||||
static int
|
static int vsync_opengl_wait(session_t *ps) {
|
||||||
vsync_opengl_wait(session_t *ps) {
|
|
||||||
unsigned vblank_count = 0;
|
unsigned vblank_count = 0;
|
||||||
|
|
||||||
glXGetVideoSyncSGI(&vblank_count);
|
glXGetVideoSyncSGI(&vblank_count);
|
||||||
|
@ -182,13 +174,11 @@ vsync_opengl_wait(session_t *ps) {
|
||||||
*
|
*
|
||||||
* https://mail.gnome.org/archives/clutter-list/2012-November/msg00031.html
|
* https://mail.gnome.org/archives/clutter-list/2012-November/msg00031.html
|
||||||
*/
|
*/
|
||||||
static int
|
static int vsync_opengl_oml_wait(session_t *ps) {
|
||||||
vsync_opengl_oml_wait(session_t *ps) {
|
|
||||||
int64_t ust = 0, msc = 0, sbc = 0;
|
int64_t ust = 0, msc = 0, sbc = 0;
|
||||||
|
|
||||||
glXGetSyncValuesOML(ps->dpy, ps->reg_win, &ust, &msc, &sbc);
|
glXGetSyncValuesOML(ps->dpy, ps->reg_win, &ust, &msc, &sbc);
|
||||||
glXWaitForMscOML(ps->dpy, ps->reg_win, 0, 2, (msc + 1) % 2,
|
glXWaitForMscOML(ps->dpy, ps->reg_win, 0, 2, (msc + 1) % 2, &ust, &msc, &sbc);
|
||||||
&ust, &msc, &sbc);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -207,13 +197,11 @@ int (*const VSYNC_FUNCS_WAIT[NUM_VSYNC])(session_t *ps) = {
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
static void
|
static void vsync_opengl_swc_deinit(session_t *ps) {
|
||||||
vsync_opengl_swc_deinit(session_t *ps) {
|
|
||||||
vsync_opengl_swc_swap_interval(ps, 0);
|
vsync_opengl_swc_swap_interval(ps, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/// Function pointers to deinitialize VSync.
|
/// Function pointers to deinitialize VSync.
|
||||||
void (*const VSYNC_FUNCS_DEINIT[NUM_VSYNC])(session_t *ps) = {
|
void (*const VSYNC_FUNCS_DEINIT[NUM_VSYNC])(session_t *ps) = {
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
|
@ -232,12 +220,10 @@ bool vsync_init(session_t *ps) {
|
||||||
vsync_opengl_swc_swap_interval(ps, 0);
|
vsync_opengl_swc_swap_interval(ps, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ps->o.vsync && VSYNC_FUNCS_INIT[ps->o.vsync]
|
if (ps->o.vsync && VSYNC_FUNCS_INIT[ps->o.vsync] && !VSYNC_FUNCS_INIT[ps->o.vsync](ps)) {
|
||||||
&& !VSYNC_FUNCS_INIT[ps->o.vsync](ps)) {
|
|
||||||
ps->o.vsync = VSYNC_NONE;
|
ps->o.vsync = VSYNC_NONE;
|
||||||
return false;
|
return false;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
278
src/win.c
278
src/win.c
|
@ -4,29 +4,29 @@
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include <xcb/xcb.h>
|
|
||||||
#include <xcb/render.h>
|
|
||||||
#include <xcb/damage.h>
|
|
||||||
#include <xcb/composite.h>
|
|
||||||
#include <xcb/xcb_renderutil.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <xcb/composite.h>
|
||||||
|
#include <xcb/damage.h>
|
||||||
|
#include <xcb/render.h>
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
#include <xcb/xcb_renderutil.h>
|
||||||
|
|
||||||
#include "compiler.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "config.h"
|
|
||||||
#include "compton.h"
|
|
||||||
#include "c2.h"
|
|
||||||
#include "x.h"
|
|
||||||
#include "string_utils.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "types.h"
|
|
||||||
#include "region.h"
|
|
||||||
#include "backend/backend.h"
|
#include "backend/backend.h"
|
||||||
|
#include "c2.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "compiler.h"
|
||||||
|
#include "compton.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "region.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
#include "string_utils.h"
|
||||||
|
#include "types.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "x.h"
|
||||||
|
|
||||||
#ifdef CONFIG_DBUS
|
#ifdef CONFIG_DBUS
|
||||||
#include "dbus.h"
|
#include "dbus.h"
|
||||||
|
@ -44,7 +44,8 @@
|
||||||
/// Generate a "return by value" function, from a function that returns the
|
/// Generate a "return by value" function, from a function that returns the
|
||||||
/// region via a region_t pointer argument.
|
/// region via a region_t pointer argument.
|
||||||
/// Function signature has to be (win *, region_t *)
|
/// Function signature has to be (win *, region_t *)
|
||||||
#define gen_by_val(fun) region_t fun##_by_val(const win *w) { \
|
#define gen_by_val(fun) \
|
||||||
|
region_t fun##_by_val(const win *w) { \
|
||||||
region_t ret; \
|
region_t ret; \
|
||||||
pixman_region32_init(&ret); \
|
pixman_region32_init(&ret); \
|
||||||
fun(w, &ret); \
|
fun(w, &ret); \
|
||||||
|
@ -54,21 +55,18 @@
|
||||||
/**
|
/**
|
||||||
* Clear leader cache of all windows.
|
* Clear leader cache of all windows.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void clear_cache_win_leaders(session_t *ps) {
|
||||||
clear_cache_win_leaders(session_t *ps) {
|
|
||||||
for (win *w = ps->list; w; w = w->next)
|
for (win *w = ps->list; w; w = w->next)
|
||||||
w->cache_leader = XCB_NONE;
|
w->cache_leader = XCB_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void wid_set_opacity_prop(session_t *ps, xcb_window_t wid, opacity_t val) {
|
||||||
wid_set_opacity_prop(session_t *ps, xcb_window_t wid, opacity_t val) {
|
|
||||||
const uint32_t v = val;
|
const uint32_t v = val;
|
||||||
xcb_change_property(ps->c, XCB_PROP_MODE_REPLACE, wid, ps->atom_opacity,
|
xcb_change_property(ps->c, XCB_PROP_MODE_REPLACE, wid, ps->atom_opacity,
|
||||||
XCB_ATOM_CARDINAL, 32, 1, &v);
|
XCB_ATOM_CARDINAL, 32, 1, &v);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void wid_rm_opacity_prop(session_t *ps, xcb_window_t wid) {
|
||||||
wid_rm_opacity_prop(session_t *ps, xcb_window_t wid) {
|
|
||||||
xcb_delete_property(ps->c, wid, ps->atom_opacity);
|
xcb_delete_property(ps->c, wid, ps->atom_opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,8 +75,7 @@ wid_rm_opacity_prop(session_t *ps, xcb_window_t wid) {
|
||||||
*
|
*
|
||||||
* @param leader leader window ID
|
* @param leader leader window ID
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void group_update_focused(session_t *ps, xcb_window_t leader) {
|
||||||
group_update_focused(session_t *ps, xcb_window_t leader) {
|
|
||||||
if (!leader)
|
if (!leader)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -96,14 +93,13 @@ group_update_focused(session_t *ps, xcb_window_t leader) {
|
||||||
* @param leader leader window ID
|
* @param leader leader window ID
|
||||||
* @return true if the window group is focused, false otherwise
|
* @return true if the window group is focused, false otherwise
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool group_is_focused(session_t *ps, xcb_window_t leader) {
|
||||||
group_is_focused(session_t *ps, xcb_window_t leader) {
|
|
||||||
if (!leader)
|
if (!leader)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (win *w = ps->list; w; w = w->next) {
|
for (win *w = ps->list; w; w = w->next) {
|
||||||
if (win_get_leader(ps, w) == leader && w->state != WSTATE_DESTROYING
|
if (win_get_leader(ps, w) == leader && w->state != WSTATE_DESTROYING &&
|
||||||
&& win_is_focused_real(ps, w))
|
win_is_focused_real(ps, w))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +114,6 @@ static void win_get_region_local(const win *w, region_t *res) {
|
||||||
pixman_region32_init_rect(res, 0, 0, w->widthb, w->heightb);
|
pixman_region32_init_rect(res, 0, 0, w->widthb, w->heightb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a rectangular region a window occupies, excluding frame and shadow.
|
* Get a rectangular region a window occupies, excluding frame and shadow.
|
||||||
*/
|
*/
|
||||||
|
@ -135,12 +130,14 @@ void win_get_region_noframe_local(const win *w, region_t *res) {
|
||||||
pixman_region32_init_rect(res, x, y, width, height);
|
pixman_region32_init_rect(res, x, y, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
gen_by_val(win_get_region_noframe_local)
|
gen_by_val(win_get_region_noframe_local);
|
||||||
|
|
||||||
void win_get_region_frame_local(const win *w, region_t *res) {
|
void win_get_region_frame_local(const win *w, region_t *res) {
|
||||||
const margin_t extents = win_calc_frame_extents(w);
|
const margin_t extents = win_calc_frame_extents(w);
|
||||||
pixman_region32_fini(res);
|
pixman_region32_fini(res);
|
||||||
pixman_region32_init_rects(res, (rect_t[]){
|
pixman_region32_init_rects(
|
||||||
|
res,
|
||||||
|
(rect_t[]){
|
||||||
// top
|
// top
|
||||||
{.x1 = 0, .y1 = 0, .x2 = w->g.width, .y2 = extents.top},
|
{.x1 = 0, .y1 = 0, .x2 = w->g.width, .y2 = extents.top},
|
||||||
// bottom
|
// bottom
|
||||||
|
@ -149,7 +146,8 @@ void win_get_region_frame_local(const win *w, region_t *res) {
|
||||||
{.x1 = 0, .y1 = 0, .x2 = extents.left, .y2 = w->g.height},
|
{.x1 = 0, .y1 = 0, .x2 = extents.left, .y2 = w->g.height},
|
||||||
// right
|
// right
|
||||||
{.x1 = w->g.width - extents.right, .y1 = 0, .x2 = w->g.width, .y2 = w->g.height},
|
{.x1 = w->g.width - extents.right, .y1 = 0, .x2 = w->g.width, .y2 = w->g.height},
|
||||||
}, 4);
|
},
|
||||||
|
4);
|
||||||
|
|
||||||
// limit the frame region to inside the window
|
// limit the frame region to inside the window
|
||||||
region_t reg_win;
|
region_t reg_win;
|
||||||
|
@ -158,7 +156,7 @@ void win_get_region_frame_local(const win *w, region_t *res) {
|
||||||
pixman_region32_fini(®_win);
|
pixman_region32_fini(®_win);
|
||||||
}
|
}
|
||||||
|
|
||||||
gen_by_val(win_get_region_frame_local)
|
gen_by_val(win_get_region_frame_local);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a window to damaged area.
|
* Add a window to damaged area.
|
||||||
|
@ -192,19 +190,21 @@ static bool attr_pure win_has_rounded_corners(const win *w) {
|
||||||
|
|
||||||
// Determine the minimum width/height of a rectangle that could mark
|
// Determine the minimum width/height of a rectangle that could mark
|
||||||
// a window as having rounded corners
|
// a window as having rounded corners
|
||||||
unsigned short minwidth = max_i(w->widthb * (1 - ROUNDED_PERCENT),
|
unsigned short minwidth =
|
||||||
w->widthb - ROUNDED_PIXELS);
|
max_i(w->widthb * (1 - ROUNDED_PERCENT), w->widthb - ROUNDED_PIXELS);
|
||||||
unsigned short minheight = max_i(w->heightb * (1 - ROUNDED_PERCENT),
|
unsigned short minheight =
|
||||||
w->heightb - ROUNDED_PIXELS);
|
max_i(w->heightb * (1 - ROUNDED_PERCENT), w->heightb - ROUNDED_PIXELS);
|
||||||
|
|
||||||
// Get the rectangles in the bounding region
|
// Get the rectangles in the bounding region
|
||||||
int nrects = 0;
|
int nrects = 0;
|
||||||
const rect_t *rects = pixman_region32_rectangles((region_t *)&w->bounding_shape, &nrects);
|
const rect_t *rects =
|
||||||
|
pixman_region32_rectangles((region_t *)&w->bounding_shape, &nrects);
|
||||||
|
|
||||||
// Look for a rectangle large enough for this window be considered
|
// Look for a rectangle large enough for this window be considered
|
||||||
// having rounded corners
|
// having rounded corners
|
||||||
for (int i = 0; i < nrects; ++i) {
|
for (int i = 0; i < nrects; ++i) {
|
||||||
if (rects[i].x2 - rects[i].x1 >= minwidth && rects[i].y2 - rects[i].y1 >= minheight) {
|
if (rects[i].x2 - rects[i].x1 >= minwidth &&
|
||||||
|
rects[i].y2 - rects[i].y1 >= minheight) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -220,14 +220,14 @@ int win_get_name(session_t *ps, win *w) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!(wid_get_text_prop(ps, w->client_win, ps->atom_name_ewmh, &strlst, &nstr))) {
|
if (!(wid_get_text_prop(ps, w->client_win, ps->atom_name_ewmh, &strlst, &nstr))) {
|
||||||
log_trace("(%#010x): _NET_WM_NAME unset, falling back to WM_NAME.", w->client_win);
|
log_trace("(%#010x): _NET_WM_NAME unset, falling back to WM_NAME.",
|
||||||
|
w->client_win);
|
||||||
|
|
||||||
if (!(XGetWMName(ps->dpy, w->client_win, &text_prop) && text_prop.value)) {
|
if (!(XGetWMName(ps->dpy, w->client_win, &text_prop) && text_prop.value)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (Success !=
|
if (Success != XmbTextPropertyToTextList(ps->dpy, &text_prop, &strlst, &nstr) ||
|
||||||
XmbTextPropertyToTextList(ps->dpy, &text_prop, &strlst, &nstr)
|
!nstr || !strlst) {
|
||||||
|| !nstr || !strlst) {
|
|
||||||
if (strlst)
|
if (strlst)
|
||||||
XFreeStringList(strlst);
|
XFreeStringList(strlst);
|
||||||
cxfree(text_prop.value);
|
cxfree(text_prop.value);
|
||||||
|
@ -246,7 +246,8 @@ int win_get_name(session_t *ps, win *w) {
|
||||||
XFreeStringList(strlst);
|
XFreeStringList(strlst);
|
||||||
|
|
||||||
log_trace("(%#010x): client = %#010x, name = \"%s\", "
|
log_trace("(%#010x): client = %#010x, name = \"%s\", "
|
||||||
"ret = %d", w->id, w->client_win, w->name, ret);
|
"ret = %d",
|
||||||
|
w->id, w->client_win, w->name, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +268,8 @@ int win_get_role(session_t *ps, win *w) {
|
||||||
XFreeStringList(strlst);
|
XFreeStringList(strlst);
|
||||||
|
|
||||||
log_trace("(%#010x): client = %#010x, role = \"%s\", "
|
log_trace("(%#010x): client = %#010x, role = \"%s\", "
|
||||||
"ret = %d", w->id, w->client_win, w->role, ret);
|
"ret = %d",
|
||||||
|
w->id, w->client_win, w->role, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,8 +281,8 @@ static inline bool win_bounding_shaped(const session_t *ps, xcb_window_t wid) {
|
||||||
xcb_shape_query_extents_reply_t *reply;
|
xcb_shape_query_extents_reply_t *reply;
|
||||||
Bool bounding_shaped;
|
Bool bounding_shaped;
|
||||||
|
|
||||||
reply = xcb_shape_query_extents_reply(ps->c,
|
reply = xcb_shape_query_extents_reply(
|
||||||
xcb_shape_query_extents(ps->c, wid), NULL);
|
ps->c, xcb_shape_query_extents(ps->c, wid), NULL);
|
||||||
bounding_shaped = reply && reply->bounding_shaped;
|
bounding_shaped = reply && reply->bounding_shaped;
|
||||||
free(reply);
|
free(reply);
|
||||||
|
|
||||||
|
@ -290,8 +292,7 @@ static inline bool win_bounding_shaped(const session_t *ps, xcb_window_t wid) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static wintype_t
|
static wintype_t wid_get_prop_wintype(session_t *ps, xcb_window_t wid) {
|
||||||
wid_get_prop_wintype(session_t *ps, xcb_window_t wid) {
|
|
||||||
winprop_t prop = wid_get_prop(ps, wid, ps->atom_win_type, 32L, XCB_ATOM_ATOM, 32);
|
winprop_t prop = wid_get_prop(ps, wid, ps->atom_win_type, 32L, XCB_ATOM_ATOM, 32);
|
||||||
|
|
||||||
for (unsigned i = 0; i < prop.nitems; ++i) {
|
for (unsigned i = 0; i < prop.nitems; ++i) {
|
||||||
|
@ -309,8 +310,7 @@ wid_get_prop_wintype(session_t *ps, xcb_window_t wid) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
wid_get_opacity_prop(session_t *ps, xcb_window_t wid, opacity_t def,
|
wid_get_opacity_prop(session_t *ps, xcb_window_t wid, opacity_t def, opacity_t *out) {
|
||||||
opacity_t *out) {
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
*out = def;
|
*out = def;
|
||||||
|
|
||||||
|
@ -328,8 +328,7 @@ wid_get_opacity_prop(session_t *ps, xcb_window_t wid, opacity_t def,
|
||||||
|
|
||||||
// XXX should distinguish between frame has alpha and window body has alpha
|
// XXX should distinguish between frame has alpha and window body has alpha
|
||||||
bool win_has_alpha(const win *w) {
|
bool win_has_alpha(const win *w) {
|
||||||
return w->pictfmt &&
|
return w->pictfmt && w->pictfmt->type == XCB_RENDER_PICT_TYPE_DIRECT &&
|
||||||
w->pictfmt->type == XCB_RENDER_PICT_TYPE_DIRECT &&
|
|
||||||
w->pictfmt->direct.alpha_mask;
|
w->pictfmt->direct.alpha_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,8 +529,7 @@ void win_determine_invert_color(session_t *ps, win *w) {
|
||||||
if (UNSET != w->invert_color_force)
|
if (UNSET != w->invert_color_force)
|
||||||
invert_color_new = w->invert_color_force;
|
invert_color_new = w->invert_color_force;
|
||||||
else if (w->a.map_state == XCB_MAP_STATE_VIEWABLE)
|
else if (w->a.map_state == XCB_MAP_STATE_VIEWABLE)
|
||||||
invert_color_new =
|
invert_color_new = c2_match(ps, w, ps->o.invert_color_list, NULL);
|
||||||
c2_match(ps, w, ps->o.invert_color_list, NULL);
|
|
||||||
|
|
||||||
win_set_invert_color(ps, w, invert_color_new);
|
win_set_invert_color(ps, w, invert_color_new);
|
||||||
}
|
}
|
||||||
|
@ -555,8 +553,7 @@ void win_determine_blur_background(session_t *ps, win *w) {
|
||||||
if (w->a.map_state != XCB_MAP_STATE_VIEWABLE)
|
if (w->a.map_state != XCB_MAP_STATE_VIEWABLE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool blur_background_new =
|
bool blur_background_new = ps->o.blur_background &&
|
||||||
ps->o.blur_background &&
|
|
||||||
!c2_match(ps, w, ps->o.blur_background_blacklist, NULL);
|
!c2_match(ps, w, ps->o.blur_background_blacklist, NULL);
|
||||||
|
|
||||||
win_set_blur_background(ps, w, blur_background_new);
|
win_set_blur_background(ps, w, blur_background_new);
|
||||||
|
@ -620,11 +617,10 @@ void win_on_factor_change(session_t *ps, win *w) {
|
||||||
if (ps->o.opacity_rules)
|
if (ps->o.opacity_rules)
|
||||||
win_update_opacity_rule(ps, w);
|
win_update_opacity_rule(ps, w);
|
||||||
if (w->a.map_state == XCB_MAP_STATE_VIEWABLE && ps->o.paint_blacklist)
|
if (w->a.map_state == XCB_MAP_STATE_VIEWABLE && ps->o.paint_blacklist)
|
||||||
w->paint_excluded =
|
w->paint_excluded = c2_match(ps, w, ps->o.paint_blacklist, NULL);
|
||||||
c2_match(ps, w, ps->o.paint_blacklist, NULL);
|
|
||||||
if (w->a.map_state == XCB_MAP_STATE_VIEWABLE && ps->o.unredir_if_possible_blacklist)
|
if (w->a.map_state == XCB_MAP_STATE_VIEWABLE && ps->o.unredir_if_possible_blacklist)
|
||||||
w->unredir_if_possible_excluded = c2_match(
|
w->unredir_if_possible_excluded =
|
||||||
ps, w, ps->o.unredir_if_possible_blacklist, NULL);
|
c2_match(ps, w, ps->o.unredir_if_possible_blacklist, NULL);
|
||||||
w->reg_ignore_valid = false;
|
w->reg_ignore_valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -641,20 +637,22 @@ void win_on_win_size_change(session_t *ps, win *w) {
|
||||||
w->flags |= WFLAG_SIZE_CHANGE;
|
w->flags |= WFLAG_SIZE_CHANGE;
|
||||||
// Invalidate the shadow we built
|
// Invalidate the shadow we built
|
||||||
if (ps->o.experimental_backends && ps->redirected) {
|
if (ps->o.experimental_backends && ps->redirected) {
|
||||||
if (w->state == WSTATE_MAPPED ||
|
if (w->state == WSTATE_MAPPED || w->state == WSTATE_MAPPING ||
|
||||||
w->state == WSTATE_MAPPING ||
|
|
||||||
w->state == WSTATE_FADING) {
|
w->state == WSTATE_FADING) {
|
||||||
ps->backend_data->ops->release_image(ps->backend_data, w->win_image);
|
ps->backend_data->ops->release_image(ps->backend_data, w->win_image);
|
||||||
if (w->shadow_image) {
|
if (w->shadow_image) {
|
||||||
ps->backend_data->ops->release_image(ps->backend_data, w->shadow_image);
|
ps->backend_data->ops->release_image(ps->backend_data,
|
||||||
|
w->shadow_image);
|
||||||
}
|
}
|
||||||
auto pixmap = xcb_generate_id(ps->c);
|
auto pixmap = xcb_generate_id(ps->c);
|
||||||
xcb_composite_name_window_pixmap(ps->c, w->id, pixmap);
|
xcb_composite_name_window_pixmap(ps->c, w->id, pixmap);
|
||||||
w->win_image = ps->backend_data->ops->bind_pixmap(ps->backend_data, pixmap, x_get_visual_info(ps->c, w->a.visual), true);
|
w->win_image = ps->backend_data->ops->bind_pixmap(
|
||||||
|
ps->backend_data, pixmap,
|
||||||
|
x_get_visual_info(ps->c, w->a.visual), true);
|
||||||
if (w->shadow) {
|
if (w->shadow) {
|
||||||
w->shadow_image = ps->backend_data->ops->render_shadow(ps->backend_data, w->widthb,
|
w->shadow_image = ps->backend_data->ops->render_shadow(
|
||||||
w->heightb, ps->gaussian_map,
|
ps->backend_data, w->widthb, w->heightb,
|
||||||
ps->o.shadow_red, ps->o.shadow_green,
|
ps->gaussian_map, ps->o.shadow_red, ps->o.shadow_green,
|
||||||
ps->o.shadow_blue, ps->o.shadow_opacity);
|
ps->o.shadow_blue, ps->o.shadow_opacity);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -749,7 +747,8 @@ void win_unmark_client(session_t *ps, win *w) {
|
||||||
w->client_win = XCB_NONE;
|
w->client_win = XCB_NONE;
|
||||||
|
|
||||||
// Recheck event mask
|
// Recheck event mask
|
||||||
xcb_change_window_attributes(ps->c, client, XCB_CW_EVENT_MASK,
|
xcb_change_window_attributes(
|
||||||
|
ps->c, client, XCB_CW_EVENT_MASK,
|
||||||
(const uint32_t[]){determine_evmask(ps, client, WIN_EVMODE_UNKNOWN)});
|
(const uint32_t[]){determine_evmask(ps, client, WIN_EVMODE_UNKNOWN)});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -803,8 +802,7 @@ void free_win_res(session_t *ps, win *w) {
|
||||||
|
|
||||||
pixman_region32_fini(&w->bounding_shape);
|
pixman_region32_fini(&w->bounding_shape);
|
||||||
// BadDamage may be thrown if the window is destroyed
|
// BadDamage may be thrown if the window is destroyed
|
||||||
set_ignore_cookie(ps,
|
set_ignore_cookie(ps, xcb_damage_destroy(ps->c, w->damage));
|
||||||
xcb_damage_destroy(ps->c, w->damage));
|
|
||||||
rc_region_unref(&w->reg_ignore);
|
rc_region_unref(&w->reg_ignore);
|
||||||
free(w->name);
|
free(w->name);
|
||||||
free(w->class_instance);
|
free(w->class_instance);
|
||||||
|
@ -910,7 +908,8 @@ void add_win(session_t *ps, xcb_window_t id, xcb_window_t prev) {
|
||||||
log_debug("Adding window %#010x, prev %#010x", id, prev);
|
log_debug("Adding window %#010x, prev %#010x", id, prev);
|
||||||
xcb_get_window_attributes_cookie_t acookie = xcb_get_window_attributes(ps->c, id);
|
xcb_get_window_attributes_cookie_t acookie = xcb_get_window_attributes(ps->c, id);
|
||||||
xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(ps->c, id);
|
xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(ps->c, id);
|
||||||
xcb_get_window_attributes_reply_t *a = xcb_get_window_attributes_reply(ps->c, acookie, NULL);
|
xcb_get_window_attributes_reply_t *a =
|
||||||
|
xcb_get_window_attributes_reply(ps->c, acookie, NULL);
|
||||||
xcb_get_geometry_reply_t *g = xcb_get_geometry_reply(ps->c, gcookie, NULL);
|
xcb_get_geometry_reply_t *g = xcb_get_geometry_reply(ps->c, gcookie, NULL);
|
||||||
if (!a || !g || a->map_state == XCB_MAP_STATE_UNVIEWABLE) {
|
if (!a || !g || a->map_state == XCB_MAP_STATE_UNVIEWABLE) {
|
||||||
// Failed to get window attributes or geometry probably means
|
// Failed to get window attributes or geometry probably means
|
||||||
|
@ -941,8 +940,9 @@ void add_win(session_t *ps, xcb_window_t id, xcb_window_t prev) {
|
||||||
// Create Damage for window (if not Input Only)
|
// Create Damage for window (if not Input Only)
|
||||||
if (new->a._class != XCB_WINDOW_CLASS_INPUT_ONLY) {
|
if (new->a._class != XCB_WINDOW_CLASS_INPUT_ONLY) {
|
||||||
new->damage = xcb_generate_id(ps->c);
|
new->damage = xcb_generate_id(ps->c);
|
||||||
xcb_generic_error_t *e = xcb_request_check(ps->c,
|
xcb_generic_error_t *e = xcb_request_check(
|
||||||
xcb_damage_create_checked(ps->c, new->damage, id, XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY));
|
ps->c, xcb_damage_create_checked(ps->c, new->damage, id,
|
||||||
|
XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY));
|
||||||
if (e) {
|
if (e) {
|
||||||
free(e);
|
free(e);
|
||||||
free(new);
|
free(new);
|
||||||
|
@ -987,18 +987,17 @@ void win_update_focused(session_t *ps, win *w) {
|
||||||
|
|
||||||
// Use wintype_focus, and treat WM windows and override-redirected
|
// Use wintype_focus, and treat WM windows and override-redirected
|
||||||
// windows specially
|
// windows specially
|
||||||
if (ps->o.wintype_option[w->window_type].focus
|
if (ps->o.wintype_option[w->window_type].focus ||
|
||||||
|| (ps->o.mark_wmwin_focused && w->wmwin)
|
(ps->o.mark_wmwin_focused && w->wmwin) ||
|
||||||
|| (ps->o.mark_ovredir_focused &&
|
(ps->o.mark_ovredir_focused && w->id == w->client_win && !w->wmwin) ||
|
||||||
w->id == w->client_win && !w->wmwin)
|
(w->a.map_state == XCB_MAP_STATE_VIEWABLE &&
|
||||||
|| (w->a.map_state == XCB_MAP_STATE_VIEWABLE &&
|
|
||||||
c2_match(ps, w, ps->o.focus_blacklist, NULL)))
|
c2_match(ps, w, ps->o.focus_blacklist, NULL)))
|
||||||
w->focused = true;
|
w->focused = true;
|
||||||
|
|
||||||
// If window grouping detection is enabled, mark the window active if
|
// If window grouping detection is enabled, mark the window active if
|
||||||
// its group is
|
// its group is
|
||||||
if (ps->o.track_leader && ps->active_leader
|
if (ps->o.track_leader && ps->active_leader &&
|
||||||
&& win_get_leader(ps, w) == ps->active_leader) {
|
win_get_leader(ps, w) == ps->active_leader) {
|
||||||
w->focused = true;
|
w->focused = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1064,8 +1063,8 @@ void win_update_leader(session_t *ps, win *w) {
|
||||||
|
|
||||||
win_set_leader(ps, w, leader);
|
win_set_leader(ps, w, leader);
|
||||||
|
|
||||||
log_trace("(%#010x): client %#010x, leader %#010x, cache %#010x",
|
log_trace("(%#010x): client %#010x, leader %#010x, cache %#010x", w->id,
|
||||||
w->id, w->client_win, w->leader, win_get_leader(ps, w));
|
w->client_win, w->leader, win_get_leader(ps, w));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1131,13 +1130,10 @@ bool win_get_class(session_t *ps, win *w) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle window focus change.
|
* Handle window focus change.
|
||||||
*/
|
*/
|
||||||
static void
|
static void win_on_focus_change(session_t *ps, win *w) {
|
||||||
win_on_focus_change(session_t *ps, win *w) {
|
|
||||||
// If window grouping detection is enabled
|
// If window grouping detection is enabled
|
||||||
if (ps->o.track_leader) {
|
if (ps->o.track_leader) {
|
||||||
xcb_window_t leader = win_get_leader(ps, w);
|
xcb_window_t leader = win_get_leader(ps, w);
|
||||||
|
@ -1152,8 +1148,8 @@ win_on_focus_change(session_t *ps, win *w) {
|
||||||
group_update_focused(ps, leader);
|
group_update_focused(ps, leader);
|
||||||
}
|
}
|
||||||
// If the group get unfocused, remove it from active_leader
|
// If the group get unfocused, remove it from active_leader
|
||||||
else if (!win_is_focused_real(ps, w) && leader && leader == ps->active_leader
|
else if (!win_is_focused_real(ps, w) && leader &&
|
||||||
&& !group_is_focused(ps, leader)) {
|
leader == ps->active_leader && !group_is_focused(ps, leader)) {
|
||||||
ps->active_leader = XCB_NONE;
|
ps->active_leader = XCB_NONE;
|
||||||
group_update_focused(ps, leader);
|
group_update_focused(ps, leader);
|
||||||
}
|
}
|
||||||
|
@ -1183,20 +1179,19 @@ win_on_focus_change(session_t *ps, win *w) {
|
||||||
/**
|
/**
|
||||||
* Set real focused state of a window.
|
* Set real focused state of a window.
|
||||||
*/
|
*/
|
||||||
void
|
void win_set_focused(session_t *ps, win *w, bool focused) {
|
||||||
win_set_focused(session_t *ps, win *w, bool focused) {
|
|
||||||
// Unmapped windows will have their focused state reset on map
|
// Unmapped windows will have their focused state reset on map
|
||||||
if (w->a.map_state == XCB_MAP_STATE_UNMAPPED)
|
if (w->a.map_state == XCB_MAP_STATE_UNMAPPED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (win_is_focused_real(ps, w) == focused) return;
|
if (win_is_focused_real(ps, w) == focused)
|
||||||
|
return;
|
||||||
|
|
||||||
if (focused) {
|
if (focused) {
|
||||||
if (ps->active_win)
|
if (ps->active_win)
|
||||||
win_set_focused(ps, ps->active_win, false);
|
win_set_focused(ps, ps->active_win, false);
|
||||||
ps->active_win = w;
|
ps->active_win = w;
|
||||||
}
|
} else if (w == ps->active_win)
|
||||||
else if (w == ps->active_win)
|
|
||||||
ps->active_win = NULL;
|
ps->active_win = NULL;
|
||||||
|
|
||||||
assert(win_is_focused_real(ps, w) == focused);
|
assert(win_is_focused_real(ps, w) == focused);
|
||||||
|
@ -1216,10 +1211,11 @@ void win_extents(const win *w, region_t *res) {
|
||||||
|
|
||||||
if (w->shadow)
|
if (w->shadow)
|
||||||
pixman_region32_union_rect(res, res, w->g.x + w->shadow_dx,
|
pixman_region32_union_rect(res, res, w->g.x + w->shadow_dx,
|
||||||
w->g.y + w->shadow_dy, w->shadow_width, w->shadow_height);
|
w->g.y + w->shadow_dy, w->shadow_width,
|
||||||
|
w->shadow_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
gen_by_val(win_extents)
|
gen_by_val(win_extents);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the out-dated bounding shape of a window.
|
* Update the out-dated bounding shape of a window.
|
||||||
|
@ -1242,8 +1238,8 @@ void win_update_bounding_shape(session_t *ps, win *w) {
|
||||||
* as well as not generate a region.
|
* as well as not generate a region.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
xcb_shape_get_rectangles_reply_t *r = xcb_shape_get_rectangles_reply(ps->c,
|
xcb_shape_get_rectangles_reply_t *r = xcb_shape_get_rectangles_reply(
|
||||||
xcb_shape_get_rectangles(ps->c, w->id, XCB_SHAPE_SK_BOUNDING), NULL);
|
ps->c, xcb_shape_get_rectangles(ps->c, w->id, XCB_SHAPE_SK_BOUNDING), NULL);
|
||||||
|
|
||||||
if (!r)
|
if (!r)
|
||||||
break;
|
break;
|
||||||
|
@ -1287,15 +1283,18 @@ void win_update_bounding_shape(session_t *ps, win *w) {
|
||||||
assert(w->state != WSTATE_UNMAPPING && w->state != WSTATE_DESTROYING);
|
assert(w->state != WSTATE_UNMAPPING && w->state != WSTATE_DESTROYING);
|
||||||
ps->backend_data->ops->release_image(ps->backend_data, w->win_image);
|
ps->backend_data->ops->release_image(ps->backend_data, w->win_image);
|
||||||
if (w->shadow_image) {
|
if (w->shadow_image) {
|
||||||
ps->backend_data->ops->release_image(ps->backend_data, w->shadow_image);
|
ps->backend_data->ops->release_image(ps->backend_data,
|
||||||
|
w->shadow_image);
|
||||||
}
|
}
|
||||||
auto pixmap = xcb_generate_id(ps->c);
|
auto pixmap = xcb_generate_id(ps->c);
|
||||||
xcb_composite_name_window_pixmap(ps->c, w->id, pixmap);
|
xcb_composite_name_window_pixmap(ps->c, w->id, pixmap);
|
||||||
w->win_image = ps->backend_data->ops->bind_pixmap(ps->backend_data, pixmap, x_get_visual_info(ps->c, w->a.visual), true);
|
w->win_image = ps->backend_data->ops->bind_pixmap(
|
||||||
|
ps->backend_data, pixmap,
|
||||||
|
x_get_visual_info(ps->c, w->a.visual), true);
|
||||||
if (w->shadow) {
|
if (w->shadow) {
|
||||||
w->shadow_image = ps->backend_data->ops->render_shadow(ps->backend_data, w->widthb,
|
w->shadow_image = ps->backend_data->ops->render_shadow(
|
||||||
w->heightb, ps->gaussian_map,
|
ps->backend_data, w->widthb, w->heightb,
|
||||||
ps->o.shadow_red, ps->o.shadow_green,
|
ps->gaussian_map, ps->o.shadow_red, ps->o.shadow_green,
|
||||||
ps->o.shadow_blue, ps->o.shadow_opacity);
|
ps->o.shadow_blue, ps->o.shadow_opacity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1312,8 +1311,7 @@ void win_update_bounding_shape(session_t *ps, win *w) {
|
||||||
*/
|
*/
|
||||||
void win_update_opacity_prop(session_t *ps, win *w) {
|
void win_update_opacity_prop(session_t *ps, win *w) {
|
||||||
// get frame opacity first
|
// get frame opacity first
|
||||||
w->has_opacity_prop =
|
w->has_opacity_prop = wid_get_opacity_prop(ps, w->id, OPAQUE, &w->opacity_prop);
|
||||||
wid_get_opacity_prop(ps, w->id, OPAQUE, &w->opacity_prop);
|
|
||||||
|
|
||||||
if (w->has_opacity_prop)
|
if (w->has_opacity_prop)
|
||||||
// opacity found
|
// opacity found
|
||||||
|
@ -1331,10 +1329,9 @@ void win_update_opacity_prop(session_t *ps, win *w) {
|
||||||
/**
|
/**
|
||||||
* Retrieve frame extents from a window.
|
* Retrieve frame extents from a window.
|
||||||
*/
|
*/
|
||||||
void
|
void win_update_frame_extents(session_t *ps, win *w, xcb_window_t client) {
|
||||||
win_update_frame_extents(session_t *ps, win *w, xcb_window_t client) {
|
winprop_t prop =
|
||||||
winprop_t prop = wid_get_prop(ps, client, ps->atom_frame_extents,
|
wid_get_prop(ps, client, ps->atom_frame_extents, 4L, XCB_ATOM_CARDINAL, 32);
|
||||||
4L, XCB_ATOM_CARDINAL, 32);
|
|
||||||
|
|
||||||
if (prop.nitems == 4) {
|
if (prop.nitems == 4) {
|
||||||
const uint32_t *const extents = prop.c32;
|
const uint32_t *const extents = prop.c32;
|
||||||
|
@ -1353,9 +1350,8 @@ win_update_frame_extents(session_t *ps, win *w, xcb_window_t client) {
|
||||||
w->reg_ignore_valid = false;
|
w->reg_ignore_valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_trace("(%#010x): %d, %d, %d, %d", w->id,
|
log_trace("(%#010x): %d, %d, %d, %d", w->id, w->frame_extents.left,
|
||||||
w->frame_extents.left, w->frame_extents.right,
|
w->frame_extents.right, w->frame_extents.top, w->frame_extents.bottom);
|
||||||
w->frame_extents.top, w->frame_extents.bottom);
|
|
||||||
|
|
||||||
free_winprop(&prop);
|
free_winprop(&prop);
|
||||||
}
|
}
|
||||||
|
@ -1377,7 +1373,8 @@ void win_ev_stop(session_t *ps, const win *w) {
|
||||||
xcb_change_window_attributes(ps->c, w->id, XCB_CW_EVENT_MASK, (const uint32_t[]){0});
|
xcb_change_window_attributes(ps->c, w->id, XCB_CW_EVENT_MASK, (const uint32_t[]){0});
|
||||||
|
|
||||||
if (w->client_win) {
|
if (w->client_win) {
|
||||||
xcb_change_window_attributes(ps->c, w->client_win, XCB_CW_EVENT_MASK, (const uint32_t[]) { 0 });
|
xcb_change_window_attributes(ps->c, w->client_win, XCB_CW_EVENT_MASK,
|
||||||
|
(const uint32_t[]){0});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ps->shape_exists) {
|
if (ps->shape_exists) {
|
||||||
|
@ -1385,8 +1382,7 @@ void win_ev_stop(session_t *ps, const win *w) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void finish_unmap_win(session_t *ps, win **_w) {
|
||||||
finish_unmap_win(session_t *ps, win **_w) {
|
|
||||||
win *w = *_w;
|
win *w = *_w;
|
||||||
w->ever_damaged = false;
|
w->ever_damaged = false;
|
||||||
w->reg_ignore_valid = false;
|
w->reg_ignore_valid = false;
|
||||||
|
@ -1399,7 +1395,8 @@ finish_unmap_win(session_t *ps, win **_w) {
|
||||||
assert(w->win_image);
|
assert(w->win_image);
|
||||||
ps->backend_data->ops->release_image(ps->backend_data, w->win_image);
|
ps->backend_data->ops->release_image(ps->backend_data, w->win_image);
|
||||||
if (w->shadow_image) {
|
if (w->shadow_image) {
|
||||||
ps->backend_data->ops->release_image(ps->backend_data, w->shadow_image);
|
ps->backend_data->ops->release_image(ps->backend_data,
|
||||||
|
w->shadow_image);
|
||||||
}
|
}
|
||||||
w->win_image = NULL;
|
w->win_image = NULL;
|
||||||
w->shadow_image = NULL;
|
w->shadow_image = NULL;
|
||||||
|
@ -1410,8 +1407,7 @@ finish_unmap_win(session_t *ps, win **_w) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void finish_destroy_win(session_t *ps, win **_w) {
|
||||||
finish_destroy_win(session_t *ps, win **_w) {
|
|
||||||
win *w = *_w;
|
win *w = *_w;
|
||||||
win **prev = NULL;
|
win **prev = NULL;
|
||||||
|
|
||||||
|
@ -1465,15 +1461,13 @@ finish_destroy_win(session_t *ps, win **_w) {
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void finish_map_win(session_t *ps, win **_w) {
|
||||||
finish_map_win(session_t *ps, win **_w) {
|
|
||||||
win *w = *_w;
|
win *w = *_w;
|
||||||
w->in_openclose = false;
|
w->in_openclose = false;
|
||||||
w->state = WSTATE_MAPPED;
|
w->state = WSTATE_MAPPED;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void unmap_win(session_t *ps, win **_w, bool destroy) {
|
||||||
unmap_win(session_t *ps, win **_w, bool destroy) {
|
|
||||||
win *w = *_w;
|
win *w = *_w;
|
||||||
|
|
||||||
winstate_t target_state = destroy ? WSTATE_DESTROYING : WSTATE_UNMAPPING;
|
winstate_t target_state = destroy ? WSTATE_DESTROYING : WSTATE_UNMAPPING;
|
||||||
|
@ -1505,7 +1499,8 @@ unmap_win(session_t *ps, win **_w, bool destroy) {
|
||||||
|
|
||||||
if (unlikely(w->state == WSTATE_UNMAPPED) || w->a._class == XCB_WINDOW_CLASS_INPUT_ONLY) {
|
if (unlikely(w->state == WSTATE_UNMAPPED) || w->a._class == XCB_WINDOW_CLASS_INPUT_ONLY) {
|
||||||
if (unlikely(!destroy)) {
|
if (unlikely(!destroy)) {
|
||||||
log_warn("Unmapping an already unmapped window %#010x %s twice", w->id, w->name);
|
log_warn("Unmapping an already unmapped window %#010x %s twice",
|
||||||
|
w->id, w->name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Window is already unmapped, or is an Input Only window, just destroy it
|
// Window is already unmapped, or is an Input Only window, just destroy it
|
||||||
|
@ -1546,8 +1541,7 @@ unmap_win(session_t *ps, win **_w, bool destroy) {
|
||||||
/**
|
/**
|
||||||
* Execute fade callback of a window if fading finished.
|
* Execute fade callback of a window if fading finished.
|
||||||
*/
|
*/
|
||||||
void
|
void win_check_fade_finished(session_t *ps, win **_w) {
|
||||||
win_check_fade_finished(session_t *ps, win **_w) {
|
|
||||||
win *w = *_w;
|
win *w = *_w;
|
||||||
if (w->state == WSTATE_MAPPED || w->state == WSTATE_UNMAPPED) {
|
if (w->state == WSTATE_MAPPED || w->state == WSTATE_UNMAPPED) {
|
||||||
// No fading in progress
|
// No fading in progress
|
||||||
|
@ -1591,13 +1585,14 @@ void win_update_screen(session_t *ps, win *w) {
|
||||||
if (!ps->xinerama_scrs)
|
if (!ps->xinerama_scrs)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
xcb_xinerama_screen_info_t *scrs = xcb_xinerama_query_screens_screen_info(ps->xinerama_scrs);
|
xcb_xinerama_screen_info_t *scrs =
|
||||||
|
xcb_xinerama_query_screens_screen_info(ps->xinerama_scrs);
|
||||||
int length = xcb_xinerama_query_screens_screen_info_length(ps->xinerama_scrs);
|
int length = xcb_xinerama_query_screens_screen_info_length(ps->xinerama_scrs);
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
xcb_xinerama_screen_info_t *s = &scrs[i];
|
xcb_xinerama_screen_info_t *s = &scrs[i];
|
||||||
if (s->x_org <= w->g.x && s->y_org <= w->g.y
|
if (s->x_org <= w->g.x && s->y_org <= w->g.y &&
|
||||||
&& s->x_org + s->width >= w->g.x + w->widthb
|
s->x_org + s->width >= w->g.x + w->widthb &&
|
||||||
&& s->y_org + s->height >= w->g.y + w->heightb) {
|
s->y_org + s->height >= w->g.y + w->heightb) {
|
||||||
w->xinerama_scr = i;
|
w->xinerama_scr = i;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1634,7 +1629,8 @@ void map_win(session_t *ps, win *w) {
|
||||||
|
|
||||||
// Set window event mask before reading properties so that no property
|
// Set window event mask before reading properties so that no property
|
||||||
// changes are lost
|
// changes are lost
|
||||||
xcb_change_window_attributes(ps->c, w->id, XCB_CW_EVENT_MASK,
|
xcb_change_window_attributes(
|
||||||
|
ps->c, w->id, XCB_CW_EVENT_MASK,
|
||||||
(const uint32_t[]){determine_evmask(ps, w->id, WIN_EVMODE_FRAME)});
|
(const uint32_t[]){determine_evmask(ps, w->id, WIN_EVMODE_FRAME)});
|
||||||
|
|
||||||
// Notify compton when the shape of a window changes
|
// Notify compton when the shape of a window changes
|
||||||
|
@ -1681,16 +1677,17 @@ void map_win(session_t *ps, win *w) {
|
||||||
if (ps->redirected && ps->o.experimental_backends) {
|
if (ps->redirected && ps->o.experimental_backends) {
|
||||||
auto pixmap = xcb_generate_id(ps->c);
|
auto pixmap = xcb_generate_id(ps->c);
|
||||||
xcb_composite_name_window_pixmap(ps->c, w->id, pixmap);
|
xcb_composite_name_window_pixmap(ps->c, w->id, pixmap);
|
||||||
w->win_image = ps->backend_data->ops->bind_pixmap(ps->backend_data, pixmap, x_get_visual_info(ps->c, w->a.visual), true);
|
w->win_image = ps->backend_data->ops->bind_pixmap(
|
||||||
|
ps->backend_data, pixmap, x_get_visual_info(ps->c, w->a.visual), true);
|
||||||
if (w->shadow) {
|
if (w->shadow) {
|
||||||
w->shadow_image =
|
w->shadow_image = ps->backend_data->ops->render_shadow(
|
||||||
ps->backend_data->ops->render_shadow(ps->backend_data, w->widthb,
|
ps->backend_data, w->widthb, w->heightb, ps->gaussian_map,
|
||||||
w->heightb, ps->gaussian_map,
|
ps->o.shadow_red, ps->o.shadow_green, ps->o.shadow_blue,
|
||||||
ps->o.shadow_red, ps->o.shadow_green,
|
ps->o.shadow_opacity);
|
||||||
ps->o.shadow_blue, ps->o.shadow_opacity);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log_debug("Window %#010x has opacity %f, opacity target is %f", w->id, w->opacity, w->opacity_tgt);
|
log_debug("Window %#010x has opacity %f, opacity target is %f", w->id, w->opacity,
|
||||||
|
w->opacity_tgt);
|
||||||
|
|
||||||
win_determine_blur_background(ps, w);
|
win_determine_blur_background(ps, w);
|
||||||
|
|
||||||
|
@ -1744,5 +1741,4 @@ void map_win_by_id(session_t *ps, xcb_window_t id) {
|
||||||
map_win(ps, w);
|
map_win(ps, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// vim: set et sw=2 :
|
// vim: set et sw=2 :
|
||||||
|
|
33
src/win.h
33
src/win.h
|
@ -3,22 +3,22 @@
|
||||||
// Copyright (c) 2013 Richard Grenville <pyxlcy@gmail.com>
|
// Copyright (c) 2013 Richard Grenville <pyxlcy@gmail.com>
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <xcb/xcb.h>
|
|
||||||
#include <xcb/render.h>
|
|
||||||
#include <xcb/damage.h>
|
#include <xcb/damage.h>
|
||||||
|
#include <xcb/render.h>
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
|
||||||
// FIXME shouldn't need this
|
// FIXME shouldn't need this
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "x.h"
|
#include "c2.h"
|
||||||
#include "compiler.h"
|
#include "compiler.h"
|
||||||
#include "region.h"
|
#include "region.h"
|
||||||
#include "types.h"
|
|
||||||
#include "c2.h"
|
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
#include "types.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "x.h"
|
||||||
|
|
||||||
typedef struct session session_t;
|
typedef struct session session_t;
|
||||||
typedef struct _glx_texture glx_texture_t;
|
typedef struct _glx_texture glx_texture_t;
|
||||||
|
@ -363,8 +363,7 @@ region_t win_get_region_frame_local_by_val(const win *w);
|
||||||
/**
|
/**
|
||||||
* Retrieve frame extents from a window.
|
* Retrieve frame extents from a window.
|
||||||
*/
|
*/
|
||||||
void
|
void win_update_frame_extents(session_t *ps, win *w, xcb_window_t client);
|
||||||
win_update_frame_extents(session_t *ps, win *w, xcb_window_t client);
|
|
||||||
void add_win(session_t *ps, xcb_window_t id, xcb_window_t prev);
|
void add_win(session_t *ps, xcb_window_t id, xcb_window_t prev);
|
||||||
/// Unmap or destroy a window
|
/// Unmap or destroy a window
|
||||||
void unmap_win(session_t *ps, win **, bool destroy);
|
void unmap_win(session_t *ps, win **, bool destroy);
|
||||||
|
@ -375,8 +374,7 @@ void map_win_by_id(session_t *ps, xcb_window_t id);
|
||||||
/**
|
/**
|
||||||
* Execute fade callback of a window if fading finished.
|
* Execute fade callback of a window if fading finished.
|
||||||
*/
|
*/
|
||||||
void
|
void win_check_fade_finished(session_t *ps, win **_w);
|
||||||
win_check_fade_finished(session_t *ps, win **_w);
|
|
||||||
|
|
||||||
// Stop receiving events (except ConfigureNotify, XXX why?) from a window
|
// Stop receiving events (except ConfigureNotify, XXX why?) from a window
|
||||||
void win_ev_stop(session_t *ps, const win *w);
|
void win_ev_stop(session_t *ps, const win *w);
|
||||||
|
@ -390,8 +388,7 @@ void win_skip_fading(session_t *ps, win **_w);
|
||||||
*
|
*
|
||||||
* This function updates w->cache_leader if necessary.
|
* This function updates w->cache_leader if necessary.
|
||||||
*/
|
*/
|
||||||
static inline xcb_window_t
|
static inline xcb_window_t win_get_leader(session_t *ps, win *w) {
|
||||||
win_get_leader(session_t *ps, win *w) {
|
|
||||||
return win_get_leader_raw(ps, w, 0);
|
return win_get_leader_raw(ps, w, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,8 +401,7 @@ bool attr_pure win_is_region_ignore_valid(session_t *ps, const win *w);
|
||||||
/// Free all resources in a struct win
|
/// Free all resources in a struct win
|
||||||
void free_win_res(session_t *ps, win *w);
|
void free_win_res(session_t *ps, win *w);
|
||||||
|
|
||||||
static inline region_t
|
static inline region_t win_get_bounding_shape_global_by_val(win *w) {
|
||||||
win_get_bounding_shape_global_by_val(win *w) {
|
|
||||||
region_t ret;
|
region_t ret;
|
||||||
pixman_region32_init(&ret);
|
pixman_region32_init(&ret);
|
||||||
pixman_region32_copy(&ret, &w->bounding_shape);
|
pixman_region32_copy(&ret, &w->bounding_shape);
|
||||||
|
@ -417,8 +413,7 @@ win_get_bounding_shape_global_by_val(win *w) {
|
||||||
* Calculate the extents of the frame of the given window based on EWMH
|
* Calculate the extents of the frame of the given window based on EWMH
|
||||||
* _NET_FRAME_EXTENTS and the X window border width.
|
* _NET_FRAME_EXTENTS and the X window border width.
|
||||||
*/
|
*/
|
||||||
static inline margin_t attr_pure
|
static inline margin_t attr_pure win_calc_frame_extents(const win *w) {
|
||||||
win_calc_frame_extents(const win *w) {
|
|
||||||
margin_t result = w->frame_extents;
|
margin_t result = w->frame_extents;
|
||||||
result.top = max_i(result.top, w->g.border_width);
|
result.top = max_i(result.top, w->g.border_width);
|
||||||
result.left = max_i(result.left, w->g.border_width);
|
result.left = max_i(result.left, w->g.border_width);
|
||||||
|
@ -430,9 +425,7 @@ win_calc_frame_extents(const win *w) {
|
||||||
/**
|
/**
|
||||||
* Check whether a window has WM frames.
|
* Check whether a window has WM frames.
|
||||||
*/
|
*/
|
||||||
static inline bool attr_pure
|
static inline bool attr_pure win_has_frame(const win *w) {
|
||||||
win_has_frame(const win *w) {
|
return w->g.border_width || w->frame_extents.top || w->frame_extents.left ||
|
||||||
return w->g.border_width
|
w->frame_extents.right || w->frame_extents.bottom;
|
||||||
|| w->frame_extents.top || w->frame_extents.left
|
|
||||||
|| w->frame_extents.right || w->frame_extents.bottom;
|
|
||||||
}
|
}
|
||||||
|
|
187
src/x.c
187
src/x.c
|
@ -4,23 +4,23 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include <xcb/xcb.h>
|
#include <pixman.h>
|
||||||
#include <xcb/xcb_renderutil.h>
|
|
||||||
#include <xcb/xfixes.h>
|
|
||||||
#include <xcb/sync.h>
|
|
||||||
#include <xcb/composite.h>
|
#include <xcb/composite.h>
|
||||||
#include <xcb/damage.h>
|
#include <xcb/damage.h>
|
||||||
#include <xcb/render.h>
|
#include <xcb/render.h>
|
||||||
#include <pixman.h>
|
#include <xcb/sync.h>
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
#include <xcb/xcb_renderutil.h>
|
||||||
|
#include <xcb/xfixes.h>
|
||||||
|
|
||||||
#include "utils.h"
|
|
||||||
#include "region.h"
|
|
||||||
#include "compiler.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "kernel.h"
|
|
||||||
#include "x.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "backend/gl/glx.h"
|
#include "backend/gl/glx.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "compiler.h"
|
||||||
|
#include "kernel.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "region.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "x.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a specific attribute of a window.
|
* Get a specific attribute of a window.
|
||||||
|
@ -37,17 +37,15 @@
|
||||||
* @return a <code>winprop_t</code> structure containing the attribute
|
* @return a <code>winprop_t</code> structure containing the attribute
|
||||||
* and number of items. A blank one on failure.
|
* and number of items. A blank one on failure.
|
||||||
*/
|
*/
|
||||||
winprop_t
|
winprop_t wid_get_prop_adv(const session_t *ps, xcb_window_t w, xcb_atom_t atom,
|
||||||
wid_get_prop_adv(const session_t *ps, xcb_window_t w, xcb_atom_t atom, long offset,
|
long offset, long length, xcb_atom_t rtype, int rformat) {
|
||||||
long length, xcb_atom_t rtype, int rformat) {
|
xcb_get_property_reply_t *r = xcb_get_property_reply(
|
||||||
xcb_get_property_reply_t *r = xcb_get_property_reply(ps->c,
|
ps->c, xcb_get_property(ps->c, 0, w, atom, rtype, offset, length), NULL);
|
||||||
xcb_get_property(ps->c, 0, w, atom, rtype, offset, length), NULL);
|
|
||||||
|
|
||||||
if (r && xcb_get_property_value_length(r) &&
|
if (r && xcb_get_property_value_length(r) &&
|
||||||
(rtype == XCB_GET_PROPERTY_TYPE_ANY || r->type == rtype) &&
|
(rtype == XCB_GET_PROPERTY_TYPE_ANY || r->type == rtype) &&
|
||||||
(!rformat || r->format == rformat) &&
|
(!rformat || r->format == rformat) &&
|
||||||
(r->format == 8 || r->format == 16 || r->format == 32))
|
(r->format == 8 || r->format == 16 || r->format == 32)) {
|
||||||
{
|
|
||||||
int len = xcb_get_property_value_length(r);
|
int len = xcb_get_property_value_length(r);
|
||||||
return (winprop_t){
|
return (winprop_t){
|
||||||
.ptr = xcb_get_property_value(r),
|
.ptr = xcb_get_property_value(r),
|
||||||
|
@ -60,11 +58,7 @@ wid_get_prop_adv(const session_t *ps, xcb_window_t w, xcb_atom_t atom, long offs
|
||||||
|
|
||||||
free(r);
|
free(r);
|
||||||
return (winprop_t){
|
return (winprop_t){
|
||||||
.ptr = NULL,
|
.ptr = NULL, .nitems = 0, .type = XCB_GET_PROPERTY_TYPE_ANY, .format = 0};
|
||||||
.nitems = 0,
|
|
||||||
.type = XCB_GET_PROPERTY_TYPE_ANY,
|
|
||||||
.format = 0
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,8 +66,7 @@ wid_get_prop_adv(const session_t *ps, xcb_window_t w, xcb_atom_t atom, long offs
|
||||||
*
|
*
|
||||||
* @return the value if successful, 0 otherwise
|
* @return the value if successful, 0 otherwise
|
||||||
*/
|
*/
|
||||||
xcb_window_t
|
xcb_window_t wid_get_prop_window(session_t *ps, xcb_window_t wid, xcb_atom_t aprop) {
|
||||||
wid_get_prop_window(session_t *ps, xcb_window_t wid, xcb_atom_t aprop) {
|
|
||||||
// Get the attribute
|
// Get the attribute
|
||||||
xcb_window_t p = XCB_NONE;
|
xcb_window_t p = XCB_NONE;
|
||||||
winprop_t prop = wid_get_prop(ps, wid, aprop, 1L, XCB_ATOM_WINDOW, 32);
|
winprop_t prop = wid_get_prop(ps, wid, aprop, 1L, XCB_ATOM_WINDOW, 32);
|
||||||
|
@ -91,16 +84,15 @@ wid_get_prop_window(session_t *ps, xcb_window_t wid, xcb_atom_t aprop) {
|
||||||
/**
|
/**
|
||||||
* Get the value of a text property of a window.
|
* Get the value of a text property of a window.
|
||||||
*/
|
*/
|
||||||
bool wid_get_text_prop(session_t *ps, xcb_window_t wid, xcb_atom_t prop,
|
bool wid_get_text_prop(session_t *ps, xcb_window_t wid, xcb_atom_t prop, char ***pstrlst,
|
||||||
char ***pstrlst, int *pnstr) {
|
int *pnstr) {
|
||||||
XTextProperty text_prop = {NULL, XCB_NONE, 0, 0};
|
XTextProperty text_prop = {NULL, XCB_NONE, 0, 0};
|
||||||
|
|
||||||
if (!(XGetTextProperty(ps->dpy, wid, &text_prop, prop) && text_prop.value))
|
if (!(XGetTextProperty(ps->dpy, wid, &text_prop, prop) && text_prop.value))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (Success !=
|
if (Success != XmbTextPropertyToTextList(ps->dpy, &text_prop, pstrlst, pnstr) ||
|
||||||
XmbTextPropertyToTextList(ps->dpy, &text_prop, pstrlst, pnstr)
|
!*pnstr) {
|
||||||
|| !*pnstr) {
|
|
||||||
*pnstr = 0;
|
*pnstr = 0;
|
||||||
if (*pstrlst)
|
if (*pstrlst)
|
||||||
XFreeStringList(*pstrlst);
|
XFreeStringList(*pstrlst);
|
||||||
|
@ -122,8 +114,7 @@ static inline void x_get_server_pictfmts(xcb_connection_t *c) {
|
||||||
xcb_generic_error_t *e = NULL;
|
xcb_generic_error_t *e = NULL;
|
||||||
// Get window picture format
|
// Get window picture format
|
||||||
g_pictfmts =
|
g_pictfmts =
|
||||||
xcb_render_query_pict_formats_reply(c,
|
xcb_render_query_pict_formats_reply(c, xcb_render_query_pict_formats(c), &e);
|
||||||
xcb_render_query_pict_formats(c), &e);
|
|
||||||
if (e || !g_pictfmts) {
|
if (e || !g_pictfmts) {
|
||||||
log_fatal("failed to get pict formats\n");
|
log_fatal("failed to get pict formats\n");
|
||||||
abort();
|
abort();
|
||||||
|
@ -136,8 +127,8 @@ x_get_pictform_for_visual(xcb_connection_t *c, xcb_visualid_t visual) {
|
||||||
|
|
||||||
xcb_render_pictvisual_t *pv = xcb_render_util_find_visual_format(g_pictfmts, visual);
|
xcb_render_pictvisual_t *pv = xcb_render_util_find_visual_format(g_pictfmts, visual);
|
||||||
for (xcb_render_pictforminfo_iterator_t i =
|
for (xcb_render_pictforminfo_iterator_t i =
|
||||||
xcb_render_query_pict_formats_formats_iterator(g_pictfmts); i.rem;
|
xcb_render_query_pict_formats_formats_iterator(g_pictfmts);
|
||||||
xcb_render_pictforminfo_next(&i)) {
|
i.rem; xcb_render_pictforminfo_next(&i)) {
|
||||||
if (i.data->id == pv->format) {
|
if (i.data->id == pv->format) {
|
||||||
return i.data;
|
return i.data;
|
||||||
}
|
}
|
||||||
|
@ -145,15 +136,14 @@ x_get_pictform_for_visual(xcb_connection_t *c, xcb_visualid_t visual) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static xcb_visualid_t attr_pure
|
static xcb_visualid_t attr_pure x_get_visual_for_pictfmt(xcb_render_query_pict_formats_reply_t *r,
|
||||||
x_get_visual_for_pictfmt(xcb_render_query_pict_formats_reply_t *r,
|
|
||||||
xcb_render_pictformat_t fmt) {
|
xcb_render_pictformat_t fmt) {
|
||||||
for (auto screen = xcb_render_query_pict_formats_screens_iterator(r);
|
for (auto screen = xcb_render_query_pict_formats_screens_iterator(r); screen.rem;
|
||||||
screen.rem; xcb_render_pictscreen_next(&screen)) {
|
xcb_render_pictscreen_next(&screen)) {
|
||||||
for (auto depth = xcb_render_pictscreen_depths_iterator(screen.data);
|
for (auto depth = xcb_render_pictscreen_depths_iterator(screen.data);
|
||||||
depth.rem; xcb_render_pictdepth_next(&depth)) {
|
depth.rem; xcb_render_pictdepth_next(&depth)) {
|
||||||
for (auto pv = xcb_render_pictdepth_visuals_iterator(depth.data); pv.rem;
|
for (auto pv = xcb_render_pictdepth_visuals_iterator(depth.data);
|
||||||
xcb_render_pictvisual_next(&pv)) {
|
pv.rem; xcb_render_pictvisual_next(&pv)) {
|
||||||
if (pv.data->format == fmt) {
|
if (pv.data->format == fmt) {
|
||||||
return pv.data->visual;
|
return pv.data->visual;
|
||||||
}
|
}
|
||||||
|
@ -163,20 +153,20 @@ x_get_visual_for_pictfmt(xcb_render_query_pict_formats_reply_t *r,
|
||||||
return XCB_NONE;
|
return XCB_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_visualid_t
|
xcb_visualid_t x_get_visual_for_standard(xcb_connection_t *c, xcb_pict_standard_t std) {
|
||||||
x_get_visual_for_standard(xcb_connection_t *c, xcb_pict_standard_t std) {
|
|
||||||
x_get_server_pictfmts(c);
|
x_get_server_pictfmts(c);
|
||||||
|
|
||||||
auto pictfmt =
|
auto pictfmt = xcb_render_util_find_standard_format(g_pictfmts, std);
|
||||||
xcb_render_util_find_standard_format(g_pictfmts, std);
|
|
||||||
|
|
||||||
return x_get_visual_for_pictfmt(g_pictfmts, pictfmt->id);
|
return x_get_visual_for_pictfmt(g_pictfmts, pictfmt->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
int x_get_visual_depth(xcb_connection_t *c, xcb_visualid_t visual) {
|
int x_get_visual_depth(xcb_connection_t *c, xcb_visualid_t visual) {
|
||||||
auto setup = xcb_get_setup(c);
|
auto setup = xcb_get_setup(c);
|
||||||
for (auto screen = xcb_setup_roots_iterator(setup); screen.rem; xcb_screen_next(&screen)) {
|
for (auto screen = xcb_setup_roots_iterator(setup); screen.rem;
|
||||||
for (auto depth = xcb_screen_allowed_depths_iterator(screen.data); depth.rem; xcb_depth_next(&depth)) {
|
xcb_screen_next(&screen)) {
|
||||||
|
for (auto depth = xcb_screen_allowed_depths_iterator(screen.data);
|
||||||
|
depth.rem; xcb_depth_next(&depth)) {
|
||||||
const int len = xcb_depth_visuals_length(depth.data);
|
const int len = xcb_depth_visuals_length(depth.data);
|
||||||
const xcb_visualtype_t *visuals = xcb_depth_visuals(depth.data);
|
const xcb_visualtype_t *visuals = xcb_depth_visuals(depth.data);
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
|
@ -190,11 +180,10 @@ int x_get_visual_depth(xcb_connection_t *c, xcb_visualid_t visual) {
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_render_picture_t
|
xcb_render_picture_t
|
||||||
x_create_picture_with_pictfmt_and_pixmap(
|
x_create_picture_with_pictfmt_and_pixmap(xcb_connection_t *c,
|
||||||
xcb_connection_t *c, const xcb_render_pictforminfo_t * pictfmt,
|
const xcb_render_pictforminfo_t *pictfmt,
|
||||||
xcb_pixmap_t pixmap, unsigned long valuemask,
|
xcb_pixmap_t pixmap, unsigned long valuemask,
|
||||||
const xcb_render_create_picture_value_list_t *attr)
|
const xcb_render_create_picture_value_list_t *attr) {
|
||||||
{
|
|
||||||
void *buf = NULL;
|
void *buf = NULL;
|
||||||
if (attr) {
|
if (attr) {
|
||||||
xcb_render_create_picture_value_list_serialize(&buf, valuemask, attr);
|
xcb_render_create_picture_value_list_serialize(&buf, valuemask, attr);
|
||||||
|
@ -206,8 +195,8 @@ x_create_picture_with_pictfmt_and_pixmap(
|
||||||
|
|
||||||
xcb_render_picture_t tmp_picture = xcb_generate_id(c);
|
xcb_render_picture_t tmp_picture = xcb_generate_id(c);
|
||||||
xcb_generic_error_t *e =
|
xcb_generic_error_t *e =
|
||||||
xcb_request_check(c, xcb_render_create_picture_checked(c, tmp_picture,
|
xcb_request_check(c, xcb_render_create_picture_checked(
|
||||||
pixmap, pictfmt->id, valuemask, buf));
|
c, tmp_picture, pixmap, pictfmt->id, valuemask, buf));
|
||||||
free(buf);
|
free(buf);
|
||||||
if (e) {
|
if (e) {
|
||||||
x_print_error(e->full_sequence, e->major_code, e->minor_code, e->error_code);
|
x_print_error(e->full_sequence, e->major_code, e->minor_code, e->error_code);
|
||||||
|
@ -218,25 +207,20 @@ x_create_picture_with_pictfmt_and_pixmap(
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_render_picture_t
|
xcb_render_picture_t
|
||||||
x_create_picture_with_visual_and_pixmap(
|
x_create_picture_with_visual_and_pixmap(xcb_connection_t *c, xcb_visualid_t visual,
|
||||||
xcb_connection_t *c, xcb_visualid_t visual,
|
|
||||||
xcb_pixmap_t pixmap, unsigned long valuemask,
|
xcb_pixmap_t pixmap, unsigned long valuemask,
|
||||||
const xcb_render_create_picture_value_list_t *attr)
|
const xcb_render_create_picture_value_list_t *attr) {
|
||||||
{
|
|
||||||
const xcb_render_pictforminfo_t *pictfmt = x_get_pictform_for_visual(c, visual);
|
const xcb_render_pictforminfo_t *pictfmt = x_get_pictform_for_visual(c, visual);
|
||||||
return x_create_picture_with_pictfmt_and_pixmap(c, pictfmt, pixmap, valuemask, attr);
|
return x_create_picture_with_pictfmt_and_pixmap(c, pictfmt, pixmap, valuemask, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_render_picture_t
|
xcb_render_picture_t
|
||||||
x_create_picture_with_standard_and_pixmap(
|
x_create_picture_with_standard_and_pixmap(xcb_connection_t *c, xcb_pict_standard_t standard,
|
||||||
xcb_connection_t *c, xcb_pict_standard_t standard,
|
|
||||||
xcb_pixmap_t pixmap, unsigned long valuemask,
|
xcb_pixmap_t pixmap, unsigned long valuemask,
|
||||||
const xcb_render_create_picture_value_list_t *attr)
|
const xcb_render_create_picture_value_list_t *attr) {
|
||||||
{
|
|
||||||
x_get_server_pictfmts(c);
|
x_get_server_pictfmts(c);
|
||||||
|
|
||||||
auto pictfmt =
|
auto pictfmt = xcb_render_util_find_standard_format(g_pictfmts, standard);
|
||||||
xcb_render_util_find_standard_format(g_pictfmts, standard);
|
|
||||||
assert(pictfmt);
|
assert(pictfmt);
|
||||||
return x_create_picture_with_pictfmt_and_pixmap(c, pictfmt, pixmap, valuemask, attr);
|
return x_create_picture_with_pictfmt_and_pixmap(c, pictfmt, pixmap, valuemask, attr);
|
||||||
}
|
}
|
||||||
|
@ -247,16 +231,15 @@ x_create_picture_with_standard_and_pixmap(
|
||||||
xcb_render_picture_t
|
xcb_render_picture_t
|
||||||
x_create_picture_with_pictfmt(xcb_connection_t *c, xcb_drawable_t d, int wid, int hei,
|
x_create_picture_with_pictfmt(xcb_connection_t *c, xcb_drawable_t d, int wid, int hei,
|
||||||
const xcb_render_pictforminfo_t *pictfmt, unsigned long valuemask,
|
const xcb_render_pictforminfo_t *pictfmt, unsigned long valuemask,
|
||||||
const xcb_render_create_picture_value_list_t *attr)
|
const xcb_render_create_picture_value_list_t *attr) {
|
||||||
{
|
|
||||||
int depth = pictfmt->depth;
|
int depth = pictfmt->depth;
|
||||||
|
|
||||||
xcb_pixmap_t tmp_pixmap = x_create_pixmap(c, depth, d, wid, hei);
|
xcb_pixmap_t tmp_pixmap = x_create_pixmap(c, depth, d, wid, hei);
|
||||||
if (!tmp_pixmap)
|
if (!tmp_pixmap)
|
||||||
return XCB_NONE;
|
return XCB_NONE;
|
||||||
|
|
||||||
xcb_render_picture_t picture =
|
xcb_render_picture_t picture = x_create_picture_with_pictfmt_and_pixmap(
|
||||||
x_create_picture_with_pictfmt_and_pixmap(c, pictfmt, tmp_pixmap, valuemask, attr);
|
c, pictfmt, tmp_pixmap, valuemask, attr);
|
||||||
|
|
||||||
xcb_free_pixmap(c, tmp_pixmap);
|
xcb_free_pixmap(c, tmp_pixmap);
|
||||||
|
|
||||||
|
@ -266,16 +249,15 @@ x_create_picture_with_pictfmt(xcb_connection_t *c, xcb_drawable_t d, int wid, in
|
||||||
xcb_render_picture_t
|
xcb_render_picture_t
|
||||||
x_create_picture_with_visual(xcb_connection_t *c, xcb_drawable_t d, int w, int h,
|
x_create_picture_with_visual(xcb_connection_t *c, xcb_drawable_t d, int w, int h,
|
||||||
xcb_visualid_t visual, unsigned long valuemask,
|
xcb_visualid_t visual, unsigned long valuemask,
|
||||||
const xcb_render_create_picture_value_list_t *attr)
|
const xcb_render_create_picture_value_list_t *attr) {
|
||||||
{
|
|
||||||
auto pictfmt = x_get_pictform_for_visual(c, visual);
|
auto pictfmt = x_get_pictform_for_visual(c, visual);
|
||||||
return x_create_picture_with_pictfmt(c, d, w, h, pictfmt, valuemask, attr);
|
return x_create_picture_with_pictfmt(c, d, w, h, pictfmt, valuemask, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool x_fetch_region(xcb_connection_t *c, xcb_xfixes_region_t r, pixman_region32_t *res) {
|
bool x_fetch_region(xcb_connection_t *c, xcb_xfixes_region_t r, pixman_region32_t *res) {
|
||||||
xcb_generic_error_t *e = NULL;
|
xcb_generic_error_t *e = NULL;
|
||||||
xcb_xfixes_fetch_region_reply_t *xr = xcb_xfixes_fetch_region_reply(c,
|
xcb_xfixes_fetch_region_reply_t *xr =
|
||||||
xcb_xfixes_fetch_region(c, r), &e);
|
xcb_xfixes_fetch_region_reply(c, xcb_xfixes_fetch_region(c, r), &e);
|
||||||
if (!xr) {
|
if (!xr) {
|
||||||
log_error("Failed to fetch rectangles");
|
log_error("Failed to fetch rectangles");
|
||||||
return false;
|
return false;
|
||||||
|
@ -285,12 +267,10 @@ bool x_fetch_region(xcb_connection_t *c, xcb_xfixes_region_t r, pixman_region32_
|
||||||
auto b = ccalloc(nrect, pixman_box32_t);
|
auto b = ccalloc(nrect, pixman_box32_t);
|
||||||
xcb_rectangle_t *xrect = xcb_xfixes_fetch_region_rectangles(xr);
|
xcb_rectangle_t *xrect = xcb_xfixes_fetch_region_rectangles(xr);
|
||||||
for (int i = 0; i < nrect; i++) {
|
for (int i = 0; i < nrect; i++) {
|
||||||
b[i] = (pixman_box32_t) {
|
b[i] = (pixman_box32_t){.x1 = xrect[i].x,
|
||||||
.x1 = xrect[i].x,
|
|
||||||
.y1 = xrect[i].y,
|
.y1 = xrect[i].y,
|
||||||
.x2 = xrect[i].x + xrect[i].width,
|
.x2 = xrect[i].x + xrect[i].width,
|
||||||
.y2 = xrect[i].y + xrect[i].height
|
.y2 = xrect[i].y + xrect[i].height};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
bool ret = pixman_region32_init_rects(res, b, nrect);
|
bool ret = pixman_region32_init_rects(res, b, nrect);
|
||||||
free(b);
|
free(b);
|
||||||
|
@ -312,8 +292,8 @@ void x_set_picture_clip_region(xcb_connection_t *c, xcb_render_picture_t pict,
|
||||||
};
|
};
|
||||||
|
|
||||||
xcb_generic_error_t *e =
|
xcb_generic_error_t *e =
|
||||||
xcb_request_check(c, xcb_render_set_picture_clip_rectangles_checked(c, pict,
|
xcb_request_check(c, xcb_render_set_picture_clip_rectangles_checked(
|
||||||
clip_x_origin, clip_y_origin, nrects, xrects));
|
c, pict, clip_x_origin, clip_y_origin, nrects, xrects));
|
||||||
if (e)
|
if (e)
|
||||||
log_error("Failed to set clip region");
|
log_error("Failed to set clip region");
|
||||||
free(e);
|
free(e);
|
||||||
|
@ -322,20 +302,16 @@ void x_set_picture_clip_region(xcb_connection_t *c, xcb_render_picture_t pict,
|
||||||
}
|
}
|
||||||
|
|
||||||
void x_clear_picture_clip_region(xcb_connection_t *c, xcb_render_picture_t pict) {
|
void x_clear_picture_clip_region(xcb_connection_t *c, xcb_render_picture_t pict) {
|
||||||
xcb_render_change_picture_value_list_t v = {
|
xcb_render_change_picture_value_list_t v = {.clipmask = XCB_NONE};
|
||||||
.clipmask = XCB_NONE
|
xcb_generic_error_t *e = xcb_request_check(
|
||||||
};
|
c, xcb_render_change_picture(c, pict, XCB_RENDER_CP_CLIP_MASK, &v));
|
||||||
xcb_generic_error_t *e =
|
|
||||||
xcb_request_check(c, xcb_render_change_picture(c, pict,
|
|
||||||
XCB_RENDER_CP_CLIP_MASK, &v));
|
|
||||||
if (e)
|
if (e)
|
||||||
log_error("failed to clear clip region");
|
log_error("failed to clear clip region");
|
||||||
free(e);
|
free(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum {
|
enum { XSyncBadCounter = 0,
|
||||||
XSyncBadCounter = 0,
|
|
||||||
XSyncBadAlarm = 1,
|
XSyncBadAlarm = 1,
|
||||||
XSyncBadFence = 2,
|
XSyncBadFence = 2,
|
||||||
};
|
};
|
||||||
|
@ -345,31 +321,26 @@ enum {
|
||||||
*
|
*
|
||||||
* XXX consider making this error to string
|
* XXX consider making this error to string
|
||||||
*/
|
*/
|
||||||
void
|
void x_print_error(unsigned long serial, uint8_t major, uint8_t minor, uint8_t error_code) {
|
||||||
x_print_error(unsigned long serial, uint8_t major, uint8_t minor, uint8_t error_code) {
|
|
||||||
session_t *const ps = ps_g;
|
session_t *const ps = ps_g;
|
||||||
|
|
||||||
int o = 0;
|
int o = 0;
|
||||||
const char *name = "Unknown";
|
const char *name = "Unknown";
|
||||||
|
|
||||||
if (major == ps->composite_opcode
|
if (major == ps->composite_opcode && minor == XCB_COMPOSITE_REDIRECT_SUBWINDOWS) {
|
||||||
&& minor == XCB_COMPOSITE_REDIRECT_SUBWINDOWS) {
|
|
||||||
log_fatal("Another composite manager is already running "
|
log_fatal("Another composite manager is already running "
|
||||||
"(and does not handle _NET_WM_CM_Sn correctly)");
|
"(and does not handle _NET_WM_CM_Sn correctly)");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CASESTRRET2(s) case s: name = #s; break
|
#define CASESTRRET2(s) \
|
||||||
|
case s: name = #s; break
|
||||||
|
|
||||||
o = error_code - ps->xfixes_error;
|
o = error_code - ps->xfixes_error;
|
||||||
switch (o) {
|
switch (o) { CASESTRRET2(XCB_XFIXES_BAD_REGION); }
|
||||||
CASESTRRET2(XCB_XFIXES_BAD_REGION);
|
|
||||||
}
|
|
||||||
|
|
||||||
o = error_code - ps->damage_error;
|
o = error_code - ps->damage_error;
|
||||||
switch (o) {
|
switch (o) { CASESTRRET2(XCB_DAMAGE_BAD_DAMAGE); }
|
||||||
CASESTRRET2(XCB_DAMAGE_BAD_DAMAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
o = error_code - ps->render_error;
|
o = error_code - ps->render_error;
|
||||||
switch (o) {
|
switch (o) {
|
||||||
|
@ -426,17 +397,18 @@ x_print_error(unsigned long serial, uint8_t major, uint8_t minor, uint8_t error_
|
||||||
|
|
||||||
#undef CASESTRRET2
|
#undef CASESTRRET2
|
||||||
|
|
||||||
log_debug("X error %d %s request %d minor %d serial %lu",
|
log_debug("X error %d %s request %d minor %d serial %lu", error_code, name, major,
|
||||||
error_code, name, major, minor, serial);
|
minor, serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a pixmap and check that creation succeeded.
|
* Create a pixmap and check that creation succeeded.
|
||||||
*/
|
*/
|
||||||
xcb_pixmap_t
|
xcb_pixmap_t x_create_pixmap(xcb_connection_t *c, uint8_t depth, xcb_drawable_t drawable,
|
||||||
x_create_pixmap(xcb_connection_t *c, uint8_t depth, xcb_drawable_t drawable, uint16_t width, uint16_t height) {
|
uint16_t width, uint16_t height) {
|
||||||
xcb_pixmap_t pix = xcb_generate_id(c);
|
xcb_pixmap_t pix = xcb_generate_id(c);
|
||||||
xcb_void_cookie_t cookie = xcb_create_pixmap_checked(c, depth, pix, drawable, width, height);
|
xcb_void_cookie_t cookie =
|
||||||
|
xcb_create_pixmap_checked(c, depth, pix, drawable, width, height);
|
||||||
xcb_generic_error_t *err = xcb_request_check(c, cookie);
|
xcb_generic_error_t *err = xcb_request_check(c, cookie);
|
||||||
if (err == NULL)
|
if (err == NULL)
|
||||||
return pix;
|
return pix;
|
||||||
|
@ -453,8 +425,7 @@ x_create_pixmap(xcb_connection_t *c, uint8_t depth, xcb_drawable_t drawable, uin
|
||||||
* Detect whether the pixmap is valid with XGetGeometry. Well, maybe there
|
* Detect whether the pixmap is valid with XGetGeometry. Well, maybe there
|
||||||
* are better ways.
|
* are better ways.
|
||||||
*/
|
*/
|
||||||
bool
|
bool x_validate_pixmap(xcb_connection_t *c, xcb_pixmap_t pixmap) {
|
||||||
x_validate_pixmap(xcb_connection_t *c, xcb_pixmap_t pixmap) {
|
|
||||||
if (pixmap == XCB_NONE) {
|
if (pixmap == XCB_NONE) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -552,8 +523,8 @@ bool x_fence_sync(xcb_connection_t *c, xcb_sync_fence_t f) {
|
||||||
* @param[inout] size size of the array pointed to by `ret`, in number of elements
|
* @param[inout] size size of the array pointed to by `ret`, in number of elements
|
||||||
* @return number of elements filled into `*ret`
|
* @return number of elements filled into `*ret`
|
||||||
*/
|
*/
|
||||||
size_t x_picture_filter_from_conv(const conv *kernel, double center, xcb_render_fixed_t **ret,
|
size_t x_picture_filter_from_conv(const conv *kernel, double center,
|
||||||
size_t *size) {
|
xcb_render_fixed_t **ret, size_t *size) {
|
||||||
if (*size < (size_t)(kernel->w * kernel->h + 2)) {
|
if (*size < (size_t)(kernel->w * kernel->h + 2)) {
|
||||||
*size = kernel->w * kernel->h + 2;
|
*size = kernel->w * kernel->h + 2;
|
||||||
*ret = crealloc(*ret, *size);
|
*ret = crealloc(*ret, *size);
|
||||||
|
@ -573,14 +544,14 @@ size_t x_picture_filter_from_conv(const conv *kernel, double center, xcb_render_
|
||||||
buf[i + 2] = DOUBLE_TO_XFIXED(kernel->data[i] * factor);
|
buf[i + 2] = DOUBLE_TO_XFIXED(kernel->data[i] * factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
buf[kernel->h / 2 * kernel->w + kernel->w / 2 + 2] = DOUBLE_TO_XFIXED(center * factor);
|
buf[kernel->h / 2 * kernel->w + kernel->w / 2 + 2] =
|
||||||
|
DOUBLE_TO_XFIXED(center * factor);
|
||||||
return kernel->w * kernel->h + 2;
|
return kernel->w * kernel->h + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate a search criteria for fbconfig from a X visual.
|
/// Generate a search criteria for fbconfig from a X visual.
|
||||||
/// Returns {-1, -1, -1, -1, -1, -1} on failure
|
/// Returns {-1, -1, -1, -1, -1, -1} on failure
|
||||||
struct xvisual_info
|
struct xvisual_info x_get_visual_info(xcb_connection_t *c, xcb_visualid_t visual) {
|
||||||
x_get_visual_info(xcb_connection_t *c, xcb_visualid_t visual) {
|
|
||||||
auto pictfmt = x_get_pictform_for_visual(c, visual);
|
auto pictfmt = x_get_pictform_for_visual(c, visual);
|
||||||
auto depth = x_get_visual_depth(c, visual);
|
auto depth = x_get_visual_depth(c, visual);
|
||||||
if (!pictfmt || depth == -1) {
|
if (!pictfmt || depth == -1) {
|
||||||
|
|
19
src/x.h
19
src/x.h
|
@ -137,16 +137,17 @@ x_create_picture_with_standard_and_pixmap(xcb_connection_t *, xcb_pict_standard_
|
||||||
/**
|
/**
|
||||||
* Create an picture.
|
* Create an picture.
|
||||||
*/
|
*/
|
||||||
xcb_render_picture_t attr_nonnull(1, 5)
|
xcb_render_picture_t
|
||||||
x_create_picture_with_pictfmt(xcb_connection_t *, xcb_drawable_t, int wid, int hei,
|
x_create_picture_with_pictfmt(xcb_connection_t *, xcb_drawable_t, int wid, int hei,
|
||||||
const xcb_render_pictforminfo_t *pictfmt,
|
const xcb_render_pictforminfo_t *pictfmt, unsigned long valuemask,
|
||||||
unsigned long valuemask,
|
const xcb_render_create_picture_value_list_t *attr)
|
||||||
const xcb_render_create_picture_value_list_t *attr);
|
attr_nonnull(1, 5);
|
||||||
|
|
||||||
xcb_render_picture_t attr_nonnull(1)
|
xcb_render_picture_t
|
||||||
x_create_picture_with_visual(xcb_connection_t *, xcb_drawable_t, int w, int h,
|
x_create_picture_with_visual(xcb_connection_t *, xcb_drawable_t, int w, int h,
|
||||||
xcb_visualid_t visual, unsigned long valuemask,
|
xcb_visualid_t visual, unsigned long valuemask,
|
||||||
const xcb_render_create_picture_value_list_t *attr);
|
const xcb_render_create_picture_value_list_t *attr)
|
||||||
|
attr_nonnull(1);
|
||||||
|
|
||||||
/// Fetch a X region and store it in a pixman region
|
/// Fetch a X region and store it in a pixman region
|
||||||
bool x_fetch_region(xcb_connection_t *, xcb_xfixes_region_t r, region_t *res);
|
bool x_fetch_region(xcb_connection_t *, xcb_xfixes_region_t r, region_t *res);
|
||||||
|
@ -206,8 +207,6 @@ size_t x_picture_filter_from_conv(const conv *kernel, double center,
|
||||||
|
|
||||||
/// Generate a search criteria for fbconfig from a X visual.
|
/// Generate a search criteria for fbconfig from a X visual.
|
||||||
/// Returns {-1, -1, -1, -1, -1, -1} on failure
|
/// Returns {-1, -1, -1, -1, -1, -1} on failure
|
||||||
struct xvisual_info
|
struct xvisual_info x_get_visual_info(xcb_connection_t *c, xcb_visualid_t visual);
|
||||||
x_get_visual_info(xcb_connection_t *c, xcb_visualid_t visual);
|
|
||||||
|
|
||||||
xcb_visualid_t
|
xcb_visualid_t x_get_visual_for_standard(xcb_connection_t *c, xcb_pict_standard_t std);
|
||||||
x_get_visual_for_standard(xcb_connection_t *c, xcb_pict_standard_t std);
|
|
||||||
|
|
|
@ -8,22 +8,19 @@
|
||||||
|
|
||||||
static xrc_xid_record_t *gs_xid_records = NULL;
|
static xrc_xid_record_t *gs_xid_records = NULL;
|
||||||
|
|
||||||
#define HASH_ADD_XID(head, xidfield, add) \
|
#define HASH_ADD_XID(head, xidfield, add) HASH_ADD(hh, head, xidfield, sizeof(xid), add)
|
||||||
HASH_ADD(hh, head, xidfield, sizeof(xid), add)
|
|
||||||
|
|
||||||
#define HASH_FIND_XID(head, findxid, out) \
|
#define HASH_FIND_XID(head, findxid, out) HASH_FIND(hh, head, findxid, sizeof(xid), out)
|
||||||
HASH_FIND(hh, head, findxid, sizeof(xid), out)
|
|
||||||
|
|
||||||
#define M_CPY_POS_DATA(prec) \
|
#define M_CPY_POS_DATA(prec) \
|
||||||
prec->file = file; \
|
prec->file = file; \
|
||||||
prec->func = func; \
|
prec->func = func; \
|
||||||
prec->line = line; \
|
prec->line = line;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Add a record of given XID to the allocation table.
|
* @brief Add a record of given XID to the allocation table.
|
||||||
*/
|
*/
|
||||||
void
|
void xrc_add_xid_(XID xid, const char *type, M_POS_DATA_PARAMS) {
|
||||||
xrc_add_xid_(XID xid, const char *type, M_POS_DATA_PARAMS) {
|
|
||||||
auto prec = ccalloc(1, xrc_xid_record_t);
|
auto prec = ccalloc(1, xrc_xid_record_t);
|
||||||
prec->xid = xid;
|
prec->xid = xid;
|
||||||
prec->type = type;
|
prec->type = type;
|
||||||
|
@ -35,8 +32,7 @@ xrc_add_xid_(XID xid, const char *type, M_POS_DATA_PARAMS) {
|
||||||
/**
|
/**
|
||||||
* @brief Delete a record of given XID in the allocation table.
|
* @brief Delete a record of given XID in the allocation table.
|
||||||
*/
|
*/
|
||||||
void
|
void xrc_delete_xid_(XID xid, M_POS_DATA_PARAMS) {
|
||||||
xrc_delete_xid_(XID xid, M_POS_DATA_PARAMS) {
|
|
||||||
xrc_xid_record_t *prec = NULL;
|
xrc_xid_record_t *prec = NULL;
|
||||||
HASH_FIND_XID(gs_xid_records, &xid, prec);
|
HASH_FIND_XID(gs_xid_records, &xid, prec);
|
||||||
if (!prec) {
|
if (!prec) {
|
||||||
|
@ -51,18 +47,16 @@ xrc_delete_xid_(XID xid, M_POS_DATA_PARAMS) {
|
||||||
/**
|
/**
|
||||||
* @brief Report about issues found in the XID allocation table.
|
* @brief Report about issues found in the XID allocation table.
|
||||||
*/
|
*/
|
||||||
void
|
void xrc_report_xid(void) {
|
||||||
xrc_report_xid(void) {
|
|
||||||
for (xrc_xid_record_t *prec = gs_xid_records; prec; prec = prec->hh.next)
|
for (xrc_xid_record_t *prec = gs_xid_records; prec; prec = prec->hh.next)
|
||||||
log_trace("XRC: %s:%d %s(): %#010lx (%s) not freed.\n",
|
log_trace("XRC: %s:%d %s(): %#010lx (%s) not freed.\n", prec->file,
|
||||||
prec->file, prec->line, prec->func, prec->xid, prec->type);
|
prec->line, prec->func, prec->xid, prec->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Clear the XID allocation table.
|
* @brief Clear the XID allocation table.
|
||||||
*/
|
*/
|
||||||
void
|
void xrc_clear_xid(void) {
|
||||||
xrc_clear_xid(void) {
|
|
||||||
xrc_xid_record_t *prec = NULL, *ptmp = NULL;
|
xrc_xid_record_t *prec = NULL, *ptmp = NULL;
|
||||||
HASH_ITER(hh, gs_xid_records, prec, ptmp) {
|
HASH_ITER(hh, gs_xid_records, prec, ptmp) {
|
||||||
HASH_DEL(gs_xid_records, prec);
|
HASH_DEL(gs_xid_records, prec);
|
||||||
|
|
|
@ -18,27 +18,23 @@ typedef struct {
|
||||||
#define M_POS_DATA_PASSTHROUGH file, line, func
|
#define M_POS_DATA_PASSTHROUGH file, line, func
|
||||||
#define M_POS_DATA __FILE__, __LINE__, __func__
|
#define M_POS_DATA __FILE__, __LINE__, __func__
|
||||||
|
|
||||||
void
|
void xrc_add_xid_(XID xid, const char *type, M_POS_DATA_PARAMS);
|
||||||
xrc_add_xid_(XID xid, const char *type, M_POS_DATA_PARAMS);
|
|
||||||
|
|
||||||
#define xrc_add_xid(xid, type) xrc_add_xid_(xid, type, M_POS_DATA)
|
#define xrc_add_xid(xid, type) xrc_add_xid_(xid, type, M_POS_DATA)
|
||||||
|
|
||||||
void
|
void xrc_delete_xid_(XID xid, M_POS_DATA_PARAMS);
|
||||||
xrc_delete_xid_(XID xid, M_POS_DATA_PARAMS);
|
|
||||||
|
|
||||||
#define xrc_delete_xid(xid) xrc_delete_xid_(xid, M_POS_DATA)
|
#define xrc_delete_xid(xid) xrc_delete_xid_(xid, M_POS_DATA)
|
||||||
|
|
||||||
void
|
void xrc_report_xid(void);
|
||||||
xrc_report_xid(void);
|
|
||||||
|
|
||||||
void
|
void xrc_clear_xid(void);
|
||||||
xrc_clear_xid(void);
|
|
||||||
|
|
||||||
// Pixmap
|
// Pixmap
|
||||||
|
|
||||||
static inline void
|
static inline void xcb_create_pixmap_(xcb_connection_t *c, uint8_t depth,
|
||||||
xcb_create_pixmap_(xcb_connection_t *c, uint8_t depth, xcb_pixmap_t pixmap,
|
xcb_pixmap_t pixmap, xcb_drawable_t drawable,
|
||||||
xcb_drawable_t drawable, uint16_t width, uint16_t height, M_POS_DATA_PARAMS) {
|
uint16_t width, uint16_t height, M_POS_DATA_PARAMS) {
|
||||||
xcb_create_pixmap(c, depth, pixmap, drawable, width, height);
|
xcb_create_pixmap(c, depth, pixmap, drawable, width, height);
|
||||||
xrc_add_xid_(pixmap, "Pixmap", M_POS_DATA_PASSTHROUGH);
|
xrc_add_xid_(pixmap, "Pixmap", M_POS_DATA_PASSTHROUGH);
|
||||||
}
|
}
|
||||||
|
@ -47,7 +43,8 @@ xcb_create_pixmap_(xcb_connection_t *c, uint8_t depth, xcb_pixmap_t pixmap,
|
||||||
xcb_create_pixmap_(c, depth, pixmap, drawable, width, height, M_POS_DATA)
|
xcb_create_pixmap_(c, depth, pixmap, drawable, width, height, M_POS_DATA)
|
||||||
|
|
||||||
static inline xcb_void_cookie_t
|
static inline xcb_void_cookie_t
|
||||||
xcb_composite_name_window_pixmap_(xcb_connection_t *c, xcb_window_t window, xcb_pixmap_t pixmap, M_POS_DATA_PARAMS) {
|
xcb_composite_name_window_pixmap_(xcb_connection_t *c, xcb_window_t window,
|
||||||
|
xcb_pixmap_t pixmap, M_POS_DATA_PARAMS) {
|
||||||
xcb_void_cookie_t ret = xcb_composite_name_window_pixmap(c, window, pixmap);
|
xcb_void_cookie_t ret = xcb_composite_name_window_pixmap(c, window, pixmap);
|
||||||
xrc_add_xid_(pixmap, "PixmapC", M_POS_DATA_PASSTHROUGH);
|
xrc_add_xid_(pixmap, "PixmapC", M_POS_DATA_PASSTHROUGH);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Reference in New Issue