diff --git a/src/c2.c b/src/c2.c index fb0f98e..fae0d26 100644 --- a/src/c2.c +++ b/src/c2.c @@ -10,10 +10,10 @@ * */ -#include -#include -#include #include +#include +#include +#include // libpcre #ifdef CONFIG_REGEX_PCRE @@ -21,25 +21,25 @@ // For compatibility with #include +#include #include "common.h" -#include "win.h" +#include "compiler.h" #include "config.h" +#include "log.h" #include "string_utils.h" #include "utils.h" -#include "log.h" +#include "win.h" #include "x.h" -#include "compiler.h" #include "c2.h" @@ -52,250 +52,220 @@ typedef struct _c2_l c2_l_t; /// Pointer to a condition tree. typedef struct { - bool isbranch : 1; - union { - c2_b_t *b; - c2_l_t *l; - }; + bool isbranch : 1; + union { + c2_b_t *b; + c2_l_t *l; + }; } c2_ptr_t; /// Initializer for c2_ptr_t. -#define C2_PTR_INIT { \ - .isbranch = false, \ - .l = NULL, \ -} +#define C2_PTR_INIT \ + { .isbranch = false, .l = NULL, } static const c2_ptr_t C2_PTR_NULL = C2_PTR_INIT; /// Operator of a branch element. typedef enum { - C2_B_OUNDEFINED, - C2_B_OAND, - C2_B_OOR, - C2_B_OXOR, + C2_B_OUNDEFINED, + C2_B_OAND, + C2_B_OOR, + C2_B_OXOR, } c2_b_op_t; /// Structure for branch element in a window condition struct _c2_b { - bool neg : 1; - c2_b_op_t op; - c2_ptr_t opr1; - c2_ptr_t opr2; + bool neg : 1; + c2_b_op_t op; + c2_ptr_t opr1; + c2_ptr_t opr2; }; /// Initializer for c2_b_t. -#define C2_B_INIT { \ - .neg = false, \ - .op = C2_B_OUNDEFINED, \ - .opr1 = C2_PTR_INIT, \ - .opr2 = C2_PTR_INIT, \ -} +#define C2_B_INIT \ + { .neg = false, .op = C2_B_OUNDEFINED, .opr1 = C2_PTR_INIT, .opr2 = C2_PTR_INIT, } /// Structure for leaf element in a window condition struct _c2_l { - bool neg : 1; - enum { - C2_L_OEXISTS, - C2_L_OEQ, - C2_L_OGT, - C2_L_OGTEQ, - C2_L_OLT, - C2_L_OLTEQ, - } op : 3; - enum { - C2_L_MEXACT, - C2_L_MSTART, - C2_L_MCONTAINS, - C2_L_MWILDCARD, - C2_L_MPCRE, - } match : 3; - bool match_ignorecase : 1; - char *tgt; - xcb_atom_t tgtatom; - bool tgt_onframe; - int index; - enum { - C2_L_PUNDEFINED, - C2_L_PID, - C2_L_PX, - C2_L_PY, - C2_L_PX2, - C2_L_PY2, - C2_L_PWIDTH, - C2_L_PHEIGHT, - C2_L_PWIDTHB, - C2_L_PHEIGHTB, - C2_L_PBDW, - C2_L_PFULLSCREEN, - C2_L_POVREDIR, - C2_L_PARGB, - C2_L_PFOCUSED, - C2_L_PWMWIN, - C2_L_PBSHAPED, - C2_L_PROUNDED, - C2_L_PCLIENT, - C2_L_PWINDOWTYPE, - C2_L_PLEADER, - C2_L_PNAME, - C2_L_PCLASSG, - C2_L_PCLASSI, - C2_L_PROLE, - } predef; - enum c2_l_type { - C2_L_TUNDEFINED, - C2_L_TSTRING, - C2_L_TCARDINAL, - C2_L_TWINDOW, - C2_L_TATOM, - C2_L_TDRAWABLE, - } type; - int format; - enum { - C2_L_PTUNDEFINED, - C2_L_PTSTRING, - C2_L_PTINT, - } ptntype; - char *ptnstr; - long ptnint; + bool neg : 1; + enum { C2_L_OEXISTS, + C2_L_OEQ, + C2_L_OGT, + C2_L_OGTEQ, + C2_L_OLT, + C2_L_OLTEQ, + } op : 3; + enum { C2_L_MEXACT, + C2_L_MSTART, + C2_L_MCONTAINS, + C2_L_MWILDCARD, + C2_L_MPCRE, + } match : 3; + bool match_ignorecase : 1; + char *tgt; + xcb_atom_t tgtatom; + bool tgt_onframe; + int index; + enum { C2_L_PUNDEFINED, + C2_L_PID, + C2_L_PX, + C2_L_PY, + C2_L_PX2, + C2_L_PY2, + C2_L_PWIDTH, + C2_L_PHEIGHT, + C2_L_PWIDTHB, + C2_L_PHEIGHTB, + C2_L_PBDW, + C2_L_PFULLSCREEN, + C2_L_POVREDIR, + C2_L_PARGB, + C2_L_PFOCUSED, + C2_L_PWMWIN, + C2_L_PBSHAPED, + C2_L_PROUNDED, + C2_L_PCLIENT, + C2_L_PWINDOWTYPE, + C2_L_PLEADER, + C2_L_PNAME, + C2_L_PCLASSG, + C2_L_PCLASSI, + C2_L_PROLE, + } predef; + enum c2_l_type { + C2_L_TUNDEFINED, + C2_L_TSTRING, + C2_L_TCARDINAL, + C2_L_TWINDOW, + C2_L_TATOM, + C2_L_TDRAWABLE, + } type; + int format; + enum { C2_L_PTUNDEFINED, + C2_L_PTSTRING, + C2_L_PTINT, + } ptntype; + char *ptnstr; + long ptnint; #ifdef CONFIG_REGEX_PCRE - pcre *regex_pcre; - pcre_extra *regex_pcre_extra; + pcre *regex_pcre; + pcre_extra *regex_pcre_extra; #endif }; /// Initializer for c2_l_t. -#define C2_L_INIT { \ - .neg = false, \ - .op = C2_L_OEXISTS, \ - .match = C2_L_MEXACT, \ - .match_ignorecase = false, \ - .tgt = NULL, \ - .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, \ -} +#define C2_L_INIT \ + { \ + .neg = false, .op = C2_L_OEXISTS, .match = C2_L_MEXACT, \ + .match_ignorecase = false, .tgt = NULL, .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; /// Linked list type of conditions. struct _c2_lptr { - c2_ptr_t ptr; - void *data; - struct _c2_lptr *next; + c2_ptr_t ptr; + void *data; + struct _c2_lptr *next; }; /// Initializer for c2_lptr_t. -#define C2_LPTR_INIT { \ - .ptr = C2_PTR_INIT, \ - .data = NULL, \ - .next = NULL, \ -} +#define C2_LPTR_INIT \ + { .ptr = C2_PTR_INIT, .data = NULL, .next = NULL, } /// Structure representing a predefined target. typedef struct { - const char *name; - enum c2_l_type type; - int format; + const char *name; + enum c2_l_type type; + int format; } c2_predef_t; // Predefined targets. static const c2_predef_t C2_PREDEFS[] = { - [C2_L_PID ] = { "id" , C2_L_TCARDINAL , 0 }, - [C2_L_PX ] = { "x" , C2_L_TCARDINAL , 0 }, - [C2_L_PY ] = { "y" , C2_L_TCARDINAL , 0 }, - [C2_L_PX2 ] = { "x2" , C2_L_TCARDINAL , 0 }, - [C2_L_PY2 ] = { "y2" , C2_L_TCARDINAL , 0 }, - [C2_L_PWIDTH ] = { "width" , C2_L_TCARDINAL , 0 }, - [C2_L_PHEIGHT ] = { "height" , C2_L_TCARDINAL , 0 }, - [C2_L_PWIDTHB ] = { "widthb" , C2_L_TCARDINAL , 0 }, - [C2_L_PHEIGHTB ] = { "heightb" , C2_L_TCARDINAL , 0 }, - [C2_L_PBDW ] = { "border_width" , C2_L_TCARDINAL , 0 }, - [C2_L_PFULLSCREEN ] = { "fullscreen" , C2_L_TCARDINAL , 0 }, - [C2_L_POVREDIR ] = { "override_redirect" , C2_L_TCARDINAL , 0 }, - [C2_L_PARGB ] = { "argb" , C2_L_TCARDINAL , 0 }, - [C2_L_PFOCUSED ] = { "focused" , C2_L_TCARDINAL , 0 }, - [C2_L_PWMWIN ] = { "wmwin" , C2_L_TCARDINAL , 0 }, - [C2_L_PBSHAPED ] = { "bounding_shaped" , C2_L_TCARDINAL , 0 }, - [C2_L_PROUNDED ] = { "rounded_corners" , C2_L_TCARDINAL , 0 }, - [C2_L_PCLIENT ] = { "client" , C2_L_TWINDOW , 0 }, - [C2_L_PWINDOWTYPE ] = { "window_type" , C2_L_TSTRING , 0 }, - [C2_L_PLEADER ] = { "leader" , C2_L_TWINDOW , 0 }, - [C2_L_PNAME ] = { "name" , C2_L_TSTRING , 0 }, - [C2_L_PCLASSG ] = { "class_g" , C2_L_TSTRING , 0 }, - [C2_L_PCLASSI ] = { "class_i" , C2_L_TSTRING , 0 }, - [C2_L_PROLE ] = { "role" , C2_L_TSTRING , 0 }, + [C2_L_PID] = {"id", C2_L_TCARDINAL, 0}, + [C2_L_PX] = {"x", C2_L_TCARDINAL, 0}, + [C2_L_PY] = {"y", C2_L_TCARDINAL, 0}, + [C2_L_PX2] = {"x2", C2_L_TCARDINAL, 0}, + [C2_L_PY2] = {"y2", C2_L_TCARDINAL, 0}, + [C2_L_PWIDTH] = {"width", C2_L_TCARDINAL, 0}, + [C2_L_PHEIGHT] = {"height", C2_L_TCARDINAL, 0}, + [C2_L_PWIDTHB] = {"widthb", C2_L_TCARDINAL, 0}, + [C2_L_PHEIGHTB] = {"heightb", C2_L_TCARDINAL, 0}, + [C2_L_PBDW] = {"border_width", C2_L_TCARDINAL, 0}, + [C2_L_PFULLSCREEN] = {"fullscreen", C2_L_TCARDINAL, 0}, + [C2_L_POVREDIR] = {"override_redirect", C2_L_TCARDINAL, 0}, + [C2_L_PARGB] = {"argb", C2_L_TCARDINAL, 0}, + [C2_L_PFOCUSED] = {"focused", C2_L_TCARDINAL, 0}, + [C2_L_PWMWIN] = {"wmwin", C2_L_TCARDINAL, 0}, + [C2_L_PBSHAPED] = {"bounding_shaped", C2_L_TCARDINAL, 0}, + [C2_L_PROUNDED] = {"rounded_corners", C2_L_TCARDINAL, 0}, + [C2_L_PCLIENT] = {"client", C2_L_TWINDOW, 0}, + [C2_L_PWINDOWTYPE] = {"window_type", C2_L_TSTRING, 0}, + [C2_L_PLEADER] = {"leader", C2_L_TWINDOW, 0}, + [C2_L_PNAME] = {"name", C2_L_TSTRING, 0}, + [C2_L_PCLASSG] = {"class_g", C2_L_TSTRING, 0}, + [C2_L_PCLASSI] = {"class_i", C2_L_TSTRING, 0}, + [C2_L_PROLE] = {"role", C2_L_TSTRING, 0}, }; /** * Compare next word in a string with another string. */ -static inline int -strcmp_wd(const char *needle, const char *src) { - int ret = mstrncmp(needle, src); - if (ret) - return ret; +static inline int strcmp_wd(const char *needle, const char *src) { + int ret = mstrncmp(needle, src); + if (ret) + return ret; - char c = src[strlen(needle)]; - if (isalnum(c) || '_' == c) - return 1; - else - return 0; + char c = src[strlen(needle)]; + if (isalnum(c) || '_' == c) + return 1; + else + return 0; } /** * Return whether a c2_ptr_t is empty. */ -static inline bool -c2_ptr_isempty(const c2_ptr_t p) { - return !(p.isbranch ? (bool) p.b: (bool) p.l); +static inline bool c2_ptr_isempty(const c2_ptr_t p) { + return !(p.isbranch ? (bool)p.b : (bool)p.l); } /** * Reset a c2_ptr_t. */ -static inline void -c2_ptr_reset(c2_ptr_t *pp) { - if (pp) - memcpy(pp, &C2_PTR_NULL, sizeof(c2_ptr_t)); +static inline void c2_ptr_reset(c2_ptr_t *pp) { + if (pp) + memcpy(pp, &C2_PTR_NULL, sizeof(c2_ptr_t)); } /** * Combine two condition trees. */ -static inline c2_ptr_t -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) - }; +static inline c2_ptr_t 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)}; - p.b->opr1 = p1; - p.b->opr2 = p2; - p.b->op = op; + p.b->opr1 = p1; + p.b->opr2 = p2; + p.b->op = op; - return p; + return p; } /** * Get the precedence value of a condition branch operator. */ -static inline int -c2h_b_opp(c2_b_op_t op) { - switch (op) { - case C2_B_OAND: return 2; - case C2_B_OOR: return 1; - case C2_B_OXOR: return 1; - default: break; - } +static inline int c2h_b_opp(c2_b_op_t op) { + switch (op) { + case C2_B_OAND: return 2; + case C2_B_OOR: return 1; + case C2_B_OXOR: return 1; + default: break; + } - assert(0); - return 0; + assert(0); + return 0; } /** @@ -306,742 +276,716 @@ c2h_b_opp(c2_b_op_t op) { * @return positive number if op1 > op2, 0 if op1 == op2 in precedence, * negative number otherwise */ -static inline int -c2h_b_opcmp(c2_b_op_t op1, c2_b_op_t op2) { - return c2h_b_opp(op1) - c2h_b_opp(op2); +static inline int c2h_b_opcmp(c2_b_op_t op1, c2_b_op_t op2) { + return c2h_b_opp(op1) - c2h_b_opp(op2); } -static int -c2_parse_grp(const char *pattern, int offset, c2_ptr_t *presult, int level); +static int c2_parse_grp(const char *pattern, int offset, c2_ptr_t *presult, int level); -static int -c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult); +static int c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult); -static int -c2_parse_op(const char *pattern, int offset, c2_ptr_t *presult); +static int c2_parse_op(const char *pattern, int offset, c2_ptr_t *presult); -static int -c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult); +static int c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult); -static int -c2_parse_legacy(const char *pattern, int offset, c2_ptr_t *presult); +static int c2_parse_legacy(const char *pattern, int offset, c2_ptr_t *presult); -static void -c2_free(c2_ptr_t p); +static void c2_free(c2_ptr_t p); /** * Wrapper of c2_free(). */ -static inline void -c2_freep(c2_ptr_t *pp) { - if (pp) { - c2_free(*pp); - c2_ptr_reset(pp); - } +static inline void c2_freep(c2_ptr_t *pp) { + if (pp) { + c2_free(*pp); + c2_ptr_reset(pp); + } } -static const char * -c2h_dump_str_tgt(const c2_l_t *pleaf); +static const char *c2h_dump_str_tgt(const c2_l_t *pleaf); -static const char * -c2h_dump_str_type(const c2_l_t *pleaf); +static const char *c2h_dump_str_type(const c2_l_t *pleaf); -static void attr_unused -c2_dump(c2_ptr_t p); +static void attr_unused c2_dump(c2_ptr_t p); -static xcb_atom_t -c2_get_atom_type(const c2_l_t *pleaf); +static xcb_atom_t c2_get_atom_type(const c2_l_t *pleaf); -static bool -c2_match_once(session_t *ps, const win *w, const c2_ptr_t cond); +static bool c2_match_once(session_t *ps, const win *w, const c2_ptr_t cond); /** * Parse a condition string. */ -c2_lptr_t * -c2_parse(c2_lptr_t **pcondlst, const char *pattern, - void *data) { - if (!pattern) - return NULL; +c2_lptr_t *c2_parse(c2_lptr_t **pcondlst, const char *pattern, void *data) { + if (!pattern) + return NULL; - // Parse the pattern - c2_ptr_t result = C2_PTR_INIT; - int offset = -1; + // Parse the pattern + c2_ptr_t result = C2_PTR_INIT; + int offset = -1; - if (strlen(pattern) >= 2 && ':' == pattern[1]) - offset = c2_parse_legacy(pattern, 0, &result); - else - offset = c2_parse_grp(pattern, 0, &result, 0); + if (strlen(pattern) >= 2 && ':' == pattern[1]) + offset = c2_parse_legacy(pattern, 0, &result); + else + offset = c2_parse_grp(pattern, 0, &result, 0); - if (offset < 0) { - c2_freep(&result); - return NULL; - } + if (offset < 0) { + c2_freep(&result); + return NULL; + } - // Insert to pcondlst - { - static const c2_lptr_t lptr_def = C2_LPTR_INIT; - auto plptr = cmalloc(c2_lptr_t); - memcpy(plptr, &lptr_def, sizeof(c2_lptr_t)); - plptr->ptr = result; - plptr->data = data; - if (pcondlst) { - plptr->next = *pcondlst; - *pcondlst = plptr; - } + // Insert to pcondlst + { + static const c2_lptr_t lptr_def = C2_LPTR_INIT; + auto plptr = cmalloc(c2_lptr_t); + memcpy(plptr, &lptr_def, sizeof(c2_lptr_t)); + plptr->ptr = result; + plptr->data = data; + if (pcondlst) { + plptr->next = *pcondlst; + *pcondlst = plptr; + } #ifdef DEBUG_C2 - log_trace("(\"%s\"): ", pattern); - c2_dump(plptr->ptr); + log_trace("(\"%s\"): ", pattern); + c2_dump(plptr->ptr); #endif - return plptr; - } + return plptr; + } } -#define c2_error(format, ...) do { \ - log_error("Pattern \"%s\" pos %d: " format, pattern, offset, ##__VA_ARGS__); \ - goto fail; \ -} while(0) +#define c2_error(format, ...) \ + do { \ + log_error("Pattern \"%s\" pos %d: " format, pattern, offset, ##__VA_ARGS__); \ + goto fail; \ + } while (0) // 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. * * @return offset of next character in string */ -static int -c2_parse_grp(const char *pattern, int offset, c2_ptr_t *presult, int level) { - // Check for recursion levels - if (level > C2_MAX_LEVELS) - c2_error("Exceeded maximum recursion levels."); +static int c2_parse_grp(const char *pattern, int offset, c2_ptr_t *presult, int level) { + // Check for recursion levels + if (level > C2_MAX_LEVELS) + c2_error("Exceeded maximum recursion levels."); - if (!pattern) - return -1; + if (!pattern) + return -1; - // Expected end character - const char endchar = (offset ? ')': '\0'); + // Expected end character + const char endchar = (offset ? ')' : '\0'); - // We use a system that a maximum of 2 elements are kept. When we find - // the third element, we combine the elements according to operator - // precedence. This design limits operators to have at most two-levels - // of precedence and fixed left-to-right associativity. + // We use a system that a maximum of 2 elements are kept. When we find + // the third element, we combine the elements according to operator + // precedence. This design limits operators to have at most two-levels + // of precedence and fixed left-to-right associativity. - // For storing branch operators. ops[0] is actually unused - c2_b_op_t ops[3] = { }; - // For storing elements - c2_ptr_t eles[2] = { C2_PTR_INIT, C2_PTR_INIT }; - // Index of next free element slot in eles - int elei = 0; - // Pointer to the position of next element - c2_ptr_t *pele = eles; - // Negation flag of next operator - bool neg = false; - // Whether we are expecting an element immediately, is true at first, or - // after encountering a logical operator - bool next_expected = true; + // For storing branch operators. ops[0] is actually unused + c2_b_op_t ops[3] = {}; + // For storing elements + c2_ptr_t eles[2] = {C2_PTR_INIT, C2_PTR_INIT}; + // Index of next free element slot in eles + int elei = 0; + // Pointer to the position of next element + c2_ptr_t *pele = eles; + // Negation flag of next operator + bool neg = false; + // Whether we are expecting an element immediately, is true at first, or + // after encountering a logical operator + bool next_expected = true; - // Parse the pattern character-by-character - for (; pattern[offset]; ++offset) { - assert(elei <= 2); + // Parse the pattern character-by-character + for (; pattern[offset]; ++offset) { + assert(elei <= 2); - // Jump over spaces - if (isspace(pattern[offset])) - continue; + // Jump over spaces + if (isspace(pattern[offset])) + continue; - // Handle end of group - if (')' == pattern[offset]) - break; + // Handle end of group + if (')' == pattern[offset]) + break; - // Handle "!" - if ('!' == pattern[offset]) { - if (!next_expected) - c2_error("Unexpected \"!\"."); + // Handle "!" + if ('!' == pattern[offset]) { + if (!next_expected) + c2_error("Unexpected \"!\"."); - neg = !neg; - continue; - } + neg = !neg; + continue; + } - // Handle AND and OR - if ('&' == pattern[offset] || '|' == pattern[offset]) { - if (next_expected) - c2_error("Unexpected logical operator."); + // Handle AND and OR + if ('&' == pattern[offset] || '|' == pattern[offset]) { + if (next_expected) + c2_error("Unexpected logical operator."); - next_expected = true; - if (!mstrncmp("&&", pattern + offset)) { - ops[elei] = C2_B_OAND; - ++offset; - } - else if (!mstrncmp("||", pattern + offset)) { - ops[elei] = C2_B_OOR; - ++offset; - } - else - c2_error("Illegal logical operator."); + next_expected = true; + if (!mstrncmp("&&", pattern + offset)) { + ops[elei] = C2_B_OAND; + ++offset; + } else if (!mstrncmp("||", pattern + offset)) { + ops[elei] = C2_B_OOR; + ++offset; + } else + c2_error("Illegal logical operator."); - continue; - } + continue; + } - // Parsing an element - if (!next_expected) - c2_error("Unexpected expression."); + // Parsing an element + if (!next_expected) + c2_error("Unexpected expression."); - assert(!elei || ops[elei]); + assert(!elei || ops[elei]); - // If we are out of space - if (2 == elei) { - --elei; - // If the first operator has higher or equal precedence, combine - // the first two elements - if (c2h_b_opcmp(ops[1], ops[2]) >= 0) { - eles[0] = c2h_comb_tree(ops[1], eles[0], eles[1]); - c2_ptr_reset(&eles[1]); - pele = &eles[elei]; - ops[1] = ops[2]; - } - // Otherwise, combine the second and the incoming one - else { - eles[1] = c2h_comb_tree(ops[2], eles[1], C2_PTR_NULL); - assert(eles[1].isbranch); - pele = &eles[1].b->opr2; - } - // The last operator always needs to be reset - ops[2] = C2_B_OUNDEFINED; - } + // If we are out of space + if (2 == elei) { + --elei; + // If the first operator has higher or equal precedence, combine + // the first two elements + if (c2h_b_opcmp(ops[1], ops[2]) >= 0) { + eles[0] = c2h_comb_tree(ops[1], eles[0], eles[1]); + c2_ptr_reset(&eles[1]); + pele = &eles[elei]; + ops[1] = ops[2]; + } + // Otherwise, combine the second and the incoming one + else { + eles[1] = c2h_comb_tree(ops[2], eles[1], C2_PTR_NULL); + assert(eles[1].isbranch); + pele = &eles[1].b->opr2; + } + // The last operator always needs to be reset + ops[2] = C2_B_OUNDEFINED; + } - // It's a subgroup if it starts with '(' - if ('(' == pattern[offset]) { - if ((offset = c2_parse_grp(pattern, offset + 1, pele, level + 1)) < 0) - goto fail; - } - // Otherwise it's a leaf - else { - if ((offset = c2_parse_target(pattern, offset, pele)) < 0) - goto fail; + // It's a subgroup if it starts with '(' + if ('(' == pattern[offset]) { + if ((offset = c2_parse_grp(pattern, offset + 1, pele, level + 1)) < 0) + goto fail; + } + // Otherwise it's a leaf + else { + if ((offset = c2_parse_target(pattern, offset, pele)) < 0) + goto fail; - assert(!pele->isbranch && !c2_ptr_isempty(*pele)); + assert(!pele->isbranch && !c2_ptr_isempty(*pele)); - if ((offset = c2_parse_op(pattern, offset, pele)) < 0) - goto fail; + if ((offset = c2_parse_op(pattern, offset, pele)) < 0) + goto fail; - if ((offset = c2_parse_pattern(pattern, offset, pele)) < 0) - goto fail; - } - // Decrement offset -- we will increment it in loop update - --offset; + if ((offset = c2_parse_pattern(pattern, offset, pele)) < 0) + goto fail; + } + // Decrement offset -- we will increment it in loop update + --offset; - // Apply negation - if (neg) { - neg = false; - if (pele->isbranch) - pele->b->neg = !pele->b->neg; - else - pele->l->neg = !pele->l->neg; - } + // Apply negation + if (neg) { + neg = false; + if (pele->isbranch) + pele->b->neg = !pele->b->neg; + else + pele->l->neg = !pele->l->neg; + } - next_expected = false; - ++elei; - pele = &eles[elei]; - } + next_expected = false; + ++elei; + pele = &eles[elei]; + } - // Wrong end character? - if (pattern[offset] && !endchar) - c2_error("Expected end of string but found '%c'.", pattern[offset]); - if (!pattern[offset] && endchar) - c2_error("Expected '%c' but found end of string.", endchar); + // Wrong end character? + if (pattern[offset] && !endchar) + c2_error("Expected end of string but found '%c'.", pattern[offset]); + if (!pattern[offset] && endchar) + c2_error("Expected '%c' but found end of string.", endchar); - // Handle end of group - if (!elei) { - c2_error("Empty group."); - } - else if (next_expected) { - c2_error("Missing rule before end of group."); - } - else if (elei > 1) { - assert(2 == elei); - assert(ops[1]); - eles[0] = c2h_comb_tree(ops[1], eles[0], eles[1]); - c2_ptr_reset(&eles[1]); - } + // Handle end of group + if (!elei) { + c2_error("Empty group."); + } else if (next_expected) { + c2_error("Missing rule before end of group."); + } else if (elei > 1) { + assert(2 == elei); + assert(ops[1]); + eles[0] = c2h_comb_tree(ops[1], eles[0], eles[1]); + c2_ptr_reset(&eles[1]); + } - *presult = eles[0]; + *presult = eles[0]; - if (')' == pattern[offset]) - ++offset; + if (')' == pattern[offset]) + ++offset; - return offset; + return offset; fail: - c2_freep(&eles[0]); - c2_freep(&eles[1]); + c2_freep(&eles[0]); + c2_freep(&eles[1]); - return -1; + return -1; } /** * Parse the target part of a rule. */ -static int -c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) { - // Initialize leaf - presult->isbranch = false; - presult->l = cmalloc(c2_l_t); +static int c2_parse_target(const char *pattern, int offset, c2_ptr_t *presult) { + // Initialize leaf + presult->isbranch = false; + presult->l = cmalloc(c2_l_t); - c2_l_t * const pleaf = presult->l; - memcpy(pleaf, &leaf_def, sizeof(c2_l_t)); + c2_l_t *const pleaf = presult->l; + memcpy(pleaf, &leaf_def, sizeof(c2_l_t)); - // Parse negation marks - while ('!' == pattern[offset]) { - pleaf->neg = !pleaf->neg; - ++offset; - C2H_SKIP_SPACES(); - } + // Parse negation marks + while ('!' == pattern[offset]) { + pleaf->neg = !pleaf->neg; + ++offset; + C2H_SKIP_SPACES(); + } - // Copy target name out - unsigned tgtlen = 0; - for (; pattern[offset] - && (isalnum(pattern[offset]) || '_' == pattern[offset]); ++offset) { - ++tgtlen; - } - if (!tgtlen) - c2_error("Empty target."); - pleaf->tgt = strndup(&pattern[offset - tgtlen], tgtlen); + // Copy target name out + unsigned tgtlen = 0; + for (; pattern[offset] && (isalnum(pattern[offset]) || '_' == pattern[offset]); + ++offset) { + ++tgtlen; + } + if (!tgtlen) + c2_error("Empty target."); + pleaf->tgt = strndup(&pattern[offset - tgtlen], tgtlen); - // Check for predefined targets - for (unsigned i = 1; i < sizeof(C2_PREDEFS) / sizeof(C2_PREDEFS[0]); ++i) { - if (!strcmp(C2_PREDEFS[i].name, pleaf->tgt)) { - pleaf->predef = i; - pleaf->type = C2_PREDEFS[i].type; - pleaf->format = C2_PREDEFS[i].format; - break; - } - } + // Check for predefined targets + for (unsigned i = 1; i < sizeof(C2_PREDEFS) / sizeof(C2_PREDEFS[0]); ++i) { + if (!strcmp(C2_PREDEFS[i].name, pleaf->tgt)) { + pleaf->predef = i; + pleaf->type = C2_PREDEFS[i].type; + pleaf->format = C2_PREDEFS[i].format; + break; + } + } - // Alias for predefined targets - if (!pleaf->predef) { -#define TGTFILL(pdefid) \ - (pleaf->predef = pdefid, \ - pleaf->type = C2_PREDEFS[pdefid].type, \ - pleaf->format = C2_PREDEFS[pdefid].format) + // Alias for predefined targets + if (!pleaf->predef) { +#define TGTFILL(pdefid) \ + (pleaf->predef = pdefid, pleaf->type = C2_PREDEFS[pdefid].type, \ + pleaf->format = C2_PREDEFS[pdefid].format) - // if (!strcmp("WM_NAME", tgt) || !strcmp("_NET_WM_NAME", tgt)) - // TGTFILL(C2_L_PNAME); + // if (!strcmp("WM_NAME", tgt) || !strcmp("_NET_WM_NAME", tgt)) + // TGTFILL(C2_L_PNAME); #undef TGTFILL - // Alias for custom properties -#define TGTFILL(target, type, format) \ - (pleaf->target = strdup(target), \ - pleaf->type = type, \ - pleaf->format = format) + // Alias for custom properties +#define TGTFILL(target, type, format) \ + (pleaf->target = strdup(target), pleaf->type = type, pleaf->format = format) - // if (!strcmp("SOME_ALIAS")) - // TGTFILL("ALIAS_TEXT", C2_L_TSTRING, 32); + // if (!strcmp("SOME_ALIAS")) + // TGTFILL("ALIAS_TEXT", C2_L_TSTRING, 32); #undef TGTFILL - } + } - C2H_SKIP_SPACES(); + C2H_SKIP_SPACES(); - // Parse target-on-frame flag - if ('@' == pattern[offset]) { - pleaf->tgt_onframe = true; - ++offset; - C2H_SKIP_SPACES(); - } + // Parse target-on-frame flag + if ('@' == pattern[offset]) { + pleaf->tgt_onframe = true; + ++offset; + C2H_SKIP_SPACES(); + } - // Parse index - if ('[' == pattern[offset]) { - offset++; + // Parse index + if ('[' == pattern[offset]) { + offset++; - C2H_SKIP_SPACES(); + C2H_SKIP_SPACES(); - int index = -1; - char *endptr = NULL; + int index = -1; + char *endptr = NULL; - index = strtol(pattern + offset, &endptr, 0); + index = strtol(pattern + offset, &endptr, 0); - if (!endptr || pattern + offset == endptr) - c2_error("No index number found after bracket."); + if (!endptr || pattern + offset == endptr) + c2_error("No index number found after bracket."); - if (index < 0) - c2_error("Index number invalid."); + if (index < 0) + c2_error("Index number invalid."); - if (pleaf->predef) - c2_error("Predefined targets can't have index."); + if (pleaf->predef) + c2_error("Predefined targets can't have index."); - pleaf->index = index; - offset = endptr - pattern; + pleaf->index = index; + offset = endptr - pattern; - C2H_SKIP_SPACES(); + C2H_SKIP_SPACES(); - if (']' != pattern[offset]) - c2_error("Index end marker not found."); + if (']' != pattern[offset]) + c2_error("Index end marker not found."); - ++offset; + ++offset; - C2H_SKIP_SPACES(); - } + C2H_SKIP_SPACES(); + } - // Parse target type and format - if (':' == pattern[offset]) { - ++offset; - C2H_SKIP_SPACES(); + // Parse target type and format + if (':' == pattern[offset]) { + ++offset; + C2H_SKIP_SPACES(); - // Look for format - bool hasformat = false; - int format = 0; - { - char *endptr = NULL; - format = strtol(pattern + offset, &endptr, 0); - assert(endptr); - if ((hasformat = (endptr && endptr != pattern + offset))) - offset = endptr - pattern; - C2H_SKIP_SPACES(); - } + // Look for format + bool hasformat = false; + int format = 0; + { + char *endptr = NULL; + format = strtol(pattern + offset, &endptr, 0); + assert(endptr); + if ((hasformat = (endptr && endptr != pattern + offset))) + offset = endptr - pattern; + C2H_SKIP_SPACES(); + } - // Look for type - enum c2_l_type type = C2_L_TUNDEFINED; - { - switch (pattern[offset]) { - case 'w': type = C2_L_TWINDOW; break; - case 'd': type = C2_L_TDRAWABLE; break; - case 'c': type = C2_L_TCARDINAL; break; - case 's': type = C2_L_TSTRING; break; - case 'a': type = C2_L_TATOM; break; - default: c2_error("Invalid type character."); - } + // Look for type + enum c2_l_type type = C2_L_TUNDEFINED; + { + switch (pattern[offset]) { + case 'w': type = C2_L_TWINDOW; break; + case 'd': type = C2_L_TDRAWABLE; break; + case 'c': type = C2_L_TCARDINAL; break; + case 's': type = C2_L_TSTRING; break; + case 'a': type = C2_L_TATOM; break; + default: c2_error("Invalid type character."); + } - if (type) { - if (pleaf->predef) { - log_warn("Type specified for a default target will be ignored."); - } - else { - if (pleaf->type && type != pleaf->type) - log_warn("Default type overridden on target."); - pleaf->type = type; - } - } + if (type) { + if (pleaf->predef) { + log_warn("Type specified for a default target " + "will be ignored."); + } else { + if (pleaf->type && type != pleaf->type) + log_warn("Default type overridden on " + "target."); + pleaf->type = type; + } + } - offset++; - C2H_SKIP_SPACES(); - } + offset++; + C2H_SKIP_SPACES(); + } - // Default format - if (!pleaf->format) { - switch (pleaf->type) { - case C2_L_TWINDOW: - case C2_L_TDRAWABLE: - case C2_L_TATOM: - pleaf->format = 32; break; - case C2_L_TSTRING: - pleaf->format = 8; break; - default: - break; - } - } + // Default format + if (!pleaf->format) { + switch (pleaf->type) { + case C2_L_TWINDOW: + case C2_L_TDRAWABLE: + case C2_L_TATOM: pleaf->format = 32; break; + case C2_L_TSTRING: pleaf->format = 8; break; + default: break; + } + } - // Write format - if (hasformat) { - if (pleaf->predef) - log_warn("Format \"%d\" specified on a default target will be ignored.", format); - else if (C2_L_TSTRING == pleaf->type) - log_warn("Format \"%d\" specified on a string target will be ignored.", format); - else { - if (pleaf->format && pleaf->format != format) - log_warn("Default format %d overridden on target.", pleaf->format); - pleaf->format = format; - } - } - } + // Write format + if (hasformat) { + if (pleaf->predef) + log_warn("Format \"%d\" specified on a default target " + "will be ignored.", + format); + else if (C2_L_TSTRING == pleaf->type) + log_warn("Format \"%d\" specified on a string target " + "will be ignored.", + format); + else { + if (pleaf->format && pleaf->format != format) + log_warn("Default format %d overridden on " + "target.", + pleaf->format); + pleaf->format = format; + } + } + } - if (!pleaf->type) - c2_error("Target type cannot be determined."); + if (!pleaf->type) + c2_error("Target type cannot be determined."); - // if (!pleaf->predef && !pleaf->format && C2_L_TSTRING != pleaf->type) - // c2_error("Target format cannot be determined."); + // if (!pleaf->predef && !pleaf->format && C2_L_TSTRING != pleaf->type) + // c2_error("Target format cannot be determined."); - if (pleaf->format && 8 != pleaf->format - && 16 != pleaf->format && 32 != pleaf->format) - c2_error("Invalid format."); + if (pleaf->format && 8 != pleaf->format && 16 != pleaf->format && 32 != pleaf->format) + c2_error("Invalid format."); - return offset; + return offset; fail: - return -1; + return -1; } /** * Parse the operator part of a leaf. */ -static int -c2_parse_op(const char *pattern, int offset, c2_ptr_t *presult) { - c2_l_t * const pleaf = presult->l; +static int c2_parse_op(const char *pattern, int offset, c2_ptr_t *presult) { + c2_l_t *const pleaf = presult->l; - // Parse negation marks - C2H_SKIP_SPACES(); - while ('!' == pattern[offset]) { - pleaf->neg = !pleaf->neg; - ++offset; - C2H_SKIP_SPACES(); - } + // Parse negation marks + C2H_SKIP_SPACES(); + while ('!' == pattern[offset]) { + pleaf->neg = !pleaf->neg; + ++offset; + C2H_SKIP_SPACES(); + } - // Parse qualifiers - if ('*' == pattern[offset] || '^' == pattern[offset] - || '%' == pattern[offset] || '~' == pattern[offset]) { - switch (pattern[offset]) { - case '*': pleaf->match = C2_L_MCONTAINS; break; - case '^': pleaf->match = C2_L_MSTART; break; - case '%': pleaf->match = C2_L_MWILDCARD; break; - case '~': pleaf->match = C2_L_MPCRE; break; - default: assert(0); - } - ++offset; - C2H_SKIP_SPACES(); - } + // Parse qualifiers + if ('*' == pattern[offset] || '^' == pattern[offset] || '%' == pattern[offset] || + '~' == pattern[offset]) { + switch (pattern[offset]) { + case '*': pleaf->match = C2_L_MCONTAINS; break; + case '^': pleaf->match = C2_L_MSTART; break; + case '%': pleaf->match = C2_L_MWILDCARD; break; + case '~': pleaf->match = C2_L_MPCRE; break; + default: assert(0); + } + ++offset; + C2H_SKIP_SPACES(); + } - // Parse flags - while ('?' == pattern[offset]) { - pleaf->match_ignorecase = true; - ++offset; - C2H_SKIP_SPACES(); - } + // Parse flags + while ('?' == pattern[offset]) { + pleaf->match_ignorecase = true; + ++offset; + C2H_SKIP_SPACES(); + } - // Parse operator - while ('=' == pattern[offset] || '>' == pattern[offset] - || '<' == pattern[offset]) { - if ('=' == pattern[offset] && C2_L_OGT == pleaf->op) - pleaf->op = C2_L_OGTEQ; - else if ('=' == pattern[offset] && C2_L_OLT == pleaf->op) - pleaf->op = C2_L_OLTEQ; - else if (pleaf->op) { - c2_error("Duplicate operator."); - } - else { - switch (pattern[offset]) { - case '=': pleaf->op = C2_L_OEQ; break; - case '>': pleaf->op = C2_L_OGT; break; - case '<': pleaf->op = C2_L_OLT; break; - default: assert(0); - } - } - ++offset; - C2H_SKIP_SPACES(); - } + // Parse operator + while ('=' == pattern[offset] || '>' == pattern[offset] || '<' == pattern[offset]) { + if ('=' == pattern[offset] && C2_L_OGT == pleaf->op) + pleaf->op = C2_L_OGTEQ; + else if ('=' == pattern[offset] && C2_L_OLT == pleaf->op) + pleaf->op = C2_L_OLTEQ; + else if (pleaf->op) { + c2_error("Duplicate operator."); + } else { + switch (pattern[offset]) { + case '=': pleaf->op = C2_L_OEQ; break; + case '>': pleaf->op = C2_L_OGT; break; + case '<': pleaf->op = C2_L_OLT; break; + default: assert(0); + } + } + ++offset; + C2H_SKIP_SPACES(); + } - // Check for problems - if (C2_L_OEQ != pleaf->op && (pleaf->match || pleaf->match_ignorecase)) - c2_error("Exists/greater-than/less-than operators cannot have a qualifier."); + // Check for problems + if (C2_L_OEQ != pleaf->op && (pleaf->match || pleaf->match_ignorecase)) + c2_error("Exists/greater-than/less-than operators cannot have a " + "qualifier."); - return offset; + return offset; fail: - return -1; + return -1; } /** * Parse the pattern part of a leaf. */ -static int -c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult) { - c2_l_t * const pleaf = presult->l; +static int c2_parse_pattern(const char *pattern, int offset, c2_ptr_t *presult) { + c2_l_t *const pleaf = presult->l; - // Exists operator cannot have pattern - if (!pleaf->op) - return offset; + // Exists operator cannot have pattern + if (!pleaf->op) + return offset; - C2H_SKIP_SPACES(); + C2H_SKIP_SPACES(); - char *endptr = NULL; - // Check for boolean patterns - if (!strcmp_wd("true", &pattern[offset])) { - pleaf->ptntype = C2_L_PTINT; - pleaf->ptnint = true; - offset += strlen("true"); - } - else if (!strcmp_wd("false", &pattern[offset])) { - pleaf->ptntype = C2_L_PTINT; - pleaf->ptnint = false; - offset += strlen("false"); - } - // Check for integer patterns - else if (pleaf->ptnint = strtol(pattern + offset, &endptr, 0), - pattern + offset != endptr) { - pleaf->ptntype = C2_L_PTINT; - offset = endptr - pattern; - // Make sure we are stopping at the end of a word - if (isalnum(pattern[offset])) - c2_error("Trailing characters after a numeric pattern."); - } - // Check for string patterns - else { - bool raw = false; - char delim = '\0'; + char *endptr = NULL; + // Check for boolean patterns + if (!strcmp_wd("true", &pattern[offset])) { + pleaf->ptntype = C2_L_PTINT; + pleaf->ptnint = true; + offset += strlen("true"); + } else if (!strcmp_wd("false", &pattern[offset])) { + pleaf->ptntype = C2_L_PTINT; + pleaf->ptnint = false; + offset += strlen("false"); + } + // Check for integer patterns + else if (pleaf->ptnint = strtol(pattern + offset, &endptr, 0), + pattern + offset != endptr) { + pleaf->ptntype = C2_L_PTINT; + offset = endptr - pattern; + // Make sure we are stopping at the end of a word + if (isalnum(pattern[offset])) + c2_error("Trailing characters after a numeric pattern."); + } + // Check for string patterns + else { + bool raw = false; + char delim = '\0'; - // String flags - if ('r' == tolower(pattern[offset])) { - raw = true; - ++offset; - C2H_SKIP_SPACES(); - } + // String flags + if ('r' == tolower(pattern[offset])) { + raw = true; + ++offset; + C2H_SKIP_SPACES(); + } - // Check for delimiters - if ('\"' == pattern[offset] || '\'' == pattern[offset]) { - pleaf->ptntype = C2_L_PTSTRING; - delim = pattern[offset]; - ++offset; - } + // Check for delimiters + if ('\"' == pattern[offset] || '\'' == pattern[offset]) { + pleaf->ptntype = C2_L_PTSTRING; + delim = pattern[offset]; + ++offset; + } - if (C2_L_PTSTRING != pleaf->ptntype) - c2_error("Invalid pattern type."); + if (C2_L_PTSTRING != pleaf->ptntype) + c2_error("Invalid pattern type."); - // Parse the string now - // We can't determine the length of the pattern, so we use the length - // to the end of the pattern string -- currently escape sequences - // cannot be converted to a string longer than itself. - auto tptnstr = ccalloc((strlen(pattern + offset) + 1), char); - char *ptptnstr = tptnstr; - pleaf->ptnstr = tptnstr; - for (; pattern[offset] && delim != pattern[offset]; ++offset) { - // Handle escape sequences if it's not a raw string - if ('\\' == pattern[offset] && !raw) { - switch(pattern[++offset]) { - case '\\': *(ptptnstr++) = '\\'; break; - case '\'': *(ptptnstr++) = '\''; break; - case '\"': *(ptptnstr++) = '\"'; break; - case 'a': *(ptptnstr++) = '\a'; break; - case 'b': *(ptptnstr++) = '\b'; break; - case 'f': *(ptptnstr++) = '\f'; break; - case 'n': *(ptptnstr++) = '\n'; break; - case 'r': *(ptptnstr++) = '\r'; break; - case 't': *(ptptnstr++) = '\t'; break; - case 'v': *(ptptnstr++) = '\v'; break; - case 'o': - case 'x': - { - char *tstr = strndup(pattern + offset + 1, 2); - char *pstr = NULL; - long val = strtol(tstr, &pstr, - ('o' == pattern[offset] ? 8: 16)); - free(tstr); - if (pstr != &tstr[2] || val <= 0) - c2_error("Invalid octal/hex escape sequence."); - assert(val < 256 && val >= 0); - *(ptptnstr++) = val; - offset += 2; - break; - } - default: c2_error("Invalid escape sequence."); - } - } - else { - *(ptptnstr++) = pattern[offset]; - } - } - if (!pattern[offset]) - c2_error("Premature end of pattern string."); - ++offset; - *ptptnstr = '\0'; - pleaf->ptnstr = strdup(tptnstr); - free(tptnstr); - } + // Parse the string now + // We can't determine the length of the pattern, so we use the length + // to the end of the pattern string -- currently escape sequences + // cannot be converted to a string longer than itself. + auto tptnstr = ccalloc((strlen(pattern + offset) + 1), char); + char *ptptnstr = tptnstr; + pleaf->ptnstr = tptnstr; + for (; pattern[offset] && delim != pattern[offset]; ++offset) { + // Handle escape sequences if it's not a raw string + if ('\\' == pattern[offset] && !raw) { + switch (pattern[++offset]) { + case '\\': *(ptptnstr++) = '\\'; break; + case '\'': *(ptptnstr++) = '\''; break; + case '\"': *(ptptnstr++) = '\"'; break; + case 'a': *(ptptnstr++) = '\a'; break; + case 'b': *(ptptnstr++) = '\b'; break; + case 'f': *(ptptnstr++) = '\f'; break; + case 'n': *(ptptnstr++) = '\n'; break; + case 'r': *(ptptnstr++) = '\r'; break; + case 't': *(ptptnstr++) = '\t'; break; + case 'v': *(ptptnstr++) = '\v'; break; + case 'o': + case 'x': { + char *tstr = strndup(pattern + offset + 1, 2); + char *pstr = NULL; + long val = strtol( + tstr, &pstr, ('o' == pattern[offset] ? 8 : 16)); + free(tstr); + if (pstr != &tstr[2] || val <= 0) + c2_error("Invalid octal/hex escape " + "sequence."); + assert(val < 256 && val >= 0); + *(ptptnstr++) = val; + offset += 2; + break; + } + default: c2_error("Invalid escape sequence."); + } + } else { + *(ptptnstr++) = pattern[offset]; + } + } + if (!pattern[offset]) + c2_error("Premature end of pattern string."); + ++offset; + *ptptnstr = '\0'; + pleaf->ptnstr = strdup(tptnstr); + free(tptnstr); + } - C2H_SKIP_SPACES(); + C2H_SKIP_SPACES(); - if (!pleaf->ptntype) - c2_error("Invalid pattern type."); + if (!pleaf->ptntype) + c2_error("Invalid pattern type."); - // Check if the type is correct - if (!(((C2_L_TSTRING == pleaf->type - || C2_L_TATOM == pleaf->type) - && C2_L_PTSTRING == pleaf->ptntype) - || ((C2_L_TCARDINAL == pleaf->type - || C2_L_TWINDOW == pleaf->type - || C2_L_TDRAWABLE == pleaf->type) - && C2_L_PTINT == pleaf->ptntype))) - c2_error("Pattern type incompatible with target type."); + // Check if the type is correct + if (!(((C2_L_TSTRING == pleaf->type || C2_L_TATOM == pleaf->type) && + C2_L_PTSTRING == pleaf->ptntype) || + ((C2_L_TCARDINAL == pleaf->type || C2_L_TWINDOW == pleaf->type || + C2_L_TDRAWABLE == pleaf->type) && + C2_L_PTINT == pleaf->ptntype))) + c2_error("Pattern type incompatible with target type."); - if (C2_L_PTINT == pleaf->ptntype && pleaf->match) - c2_error("Integer/boolean pattern cannot have operator qualifiers."); + if (C2_L_PTINT == pleaf->ptntype && pleaf->match) + c2_error("Integer/boolean pattern cannot have operator qualifiers."); - if (C2_L_PTINT == pleaf->ptntype && pleaf->match_ignorecase) - c2_error("Integer/boolean pattern cannot have flags."); + if (C2_L_PTINT == pleaf->ptntype && pleaf->match_ignorecase) + c2_error("Integer/boolean pattern cannot have flags."); - if (C2_L_PTSTRING == pleaf->ptntype - && (C2_L_OGT == pleaf->op || C2_L_OGTEQ == pleaf->op - || C2_L_OLT == pleaf->op || C2_L_OLTEQ == pleaf->op)) - c2_error("String pattern cannot have an arithmetic operator."); + if (C2_L_PTSTRING == pleaf->ptntype && + (C2_L_OGT == pleaf->op || C2_L_OGTEQ == pleaf->op || C2_L_OLT == pleaf->op || + C2_L_OLTEQ == pleaf->op)) + c2_error("String pattern cannot have an arithmetic operator."); - return offset; + return offset; fail: - return -1; + return -1; } /** * Parse a condition with legacy syntax. */ -static int -c2_parse_legacy(const char *pattern, int offset, c2_ptr_t *presult) { - unsigned plen = strlen(pattern + offset); +static int c2_parse_legacy(const char *pattern, int offset, c2_ptr_t *presult) { + unsigned plen = strlen(pattern + offset); - if (plen < 4 || ':' != pattern[offset + 1] - || !strchr(pattern + offset + 2, ':')) - c2_error("Legacy parser: Invalid format."); + if (plen < 4 || ':' != pattern[offset + 1] || !strchr(pattern + offset + 2, ':')) + c2_error("Legacy parser: Invalid format."); - // Allocate memory for new leaf - auto pleaf = cmalloc(c2_l_t); - presult->isbranch = false; - presult->l = pleaf; - memcpy(pleaf, &leaf_def, sizeof(c2_l_t)); - pleaf->type = C2_L_TSTRING; - pleaf->op = C2_L_OEQ; - pleaf->ptntype = C2_L_PTSTRING; + // Allocate memory for new leaf + auto pleaf = cmalloc(c2_l_t); + presult->isbranch = false; + presult->l = pleaf; + memcpy(pleaf, &leaf_def, sizeof(c2_l_t)); + pleaf->type = C2_L_TSTRING; + pleaf->op = C2_L_OEQ; + pleaf->ptntype = C2_L_PTSTRING; - // Determine the pattern target -#define TGTFILL(pdefid) \ - (pleaf->predef = pdefid, \ - pleaf->type = C2_PREDEFS[pdefid].type, \ - pleaf->format = C2_PREDEFS[pdefid].format) - switch (pattern[offset]) { - case 'n': TGTFILL(C2_L_PNAME); break; - case 'i': TGTFILL(C2_L_PCLASSI); break; - case 'g': TGTFILL(C2_L_PCLASSG); break; - case 'r': TGTFILL(C2_L_PROLE); break; - default: c2_error("Target \"%c\" invalid.\n", pattern[offset]); - } + // Determine the pattern target +#define TGTFILL(pdefid) \ + (pleaf->predef = pdefid, pleaf->type = C2_PREDEFS[pdefid].type, \ + pleaf->format = C2_PREDEFS[pdefid].format) + switch (pattern[offset]) { + case 'n': TGTFILL(C2_L_PNAME); break; + case 'i': TGTFILL(C2_L_PCLASSI); break; + case 'g': TGTFILL(C2_L_PCLASSG); break; + case 'r': TGTFILL(C2_L_PROLE); break; + default: c2_error("Target \"%c\" invalid.\n", pattern[offset]); + } #undef TGTFILL - offset += 2; + offset += 2; - // Determine the match type - switch (pattern[offset]) { - case 'e': pleaf->match = C2_L_MEXACT; break; - case 'a': pleaf->match = C2_L_MCONTAINS; break; - case 's': pleaf->match = C2_L_MSTART; break; - case 'w': pleaf->match = C2_L_MWILDCARD; break; - case 'p': pleaf->match = C2_L_MPCRE; break; - default: c2_error("Type \"%c\" invalid.\n", pattern[offset]); - } - ++offset; + // Determine the match type + switch (pattern[offset]) { + case 'e': pleaf->match = C2_L_MEXACT; break; + case 'a': pleaf->match = C2_L_MCONTAINS; break; + case 's': pleaf->match = C2_L_MSTART; break; + case 'w': pleaf->match = C2_L_MWILDCARD; break; + case 'p': pleaf->match = C2_L_MPCRE; break; + default: c2_error("Type \"%c\" invalid.\n", pattern[offset]); + } + ++offset; - // Determine the pattern flags - while (':' != pattern[offset]) { - switch (pattern[offset]) { - case 'i': pleaf->match_ignorecase = true; break; - default: c2_error("Flag \"%c\" invalid.", pattern[offset]); - } - ++offset; - } - ++offset; + // Determine the pattern flags + while (':' != pattern[offset]) { + switch (pattern[offset]) { + case 'i': pleaf->match_ignorecase = true; break; + default: c2_error("Flag \"%c\" invalid.", pattern[offset]); + } + ++offset; + } + ++offset; - // Copy the pattern - pleaf->ptnstr = strdup(pattern + offset); + // Copy the pattern + pleaf->ptnstr = strdup(pattern + offset); - return offset; + return offset; fail: - return -1; + return -1; } #undef c2_error @@ -1049,314 +993,297 @@ fail: /** * Do postprocessing on a condition leaf. */ -static bool -c2_l_postprocess(session_t *ps, c2_l_t *pleaf) { - // Give a pattern type to a leaf with exists operator, if needed - if (C2_L_OEXISTS == pleaf->op && !pleaf->ptntype) { - pleaf->ptntype = - (C2_L_TSTRING == pleaf->type ? C2_L_PTSTRING: C2_L_PTINT); - } +static bool c2_l_postprocess(session_t *ps, c2_l_t *pleaf) { + // Give a pattern type to a leaf with exists operator, if needed + if (C2_L_OEXISTS == pleaf->op && !pleaf->ptntype) { + pleaf->ptntype = (C2_L_TSTRING == pleaf->type ? C2_L_PTSTRING : C2_L_PTINT); + } - // Get target atom if it's not a predefined one - if (!pleaf->predef) { - pleaf->tgtatom = get_atom(ps, pleaf->tgt); - if (!pleaf->tgtatom) { - log_error("Failed to get atom for target \"%s\".", pleaf->tgt); - return false; - } - } + // Get target atom if it's not a predefined one + if (!pleaf->predef) { + pleaf->tgtatom = get_atom(ps, pleaf->tgt); + if (!pleaf->tgtatom) { + log_error("Failed to get atom for target \"%s\".", pleaf->tgt); + return false; + } + } - // Insert target Atom into atom track list - if (pleaf->tgtatom) { - bool found = false; - for (latom_t *platom = ps->track_atom_lst; platom; - platom = platom->next) { - if (pleaf->tgtatom == platom->atom) { - found = true; - break; - } - } - if (!found) { - auto pnew = cmalloc(latom_t); - pnew->next = ps->track_atom_lst; - pnew->atom = pleaf->tgtatom; - ps->track_atom_lst = pnew; - } - } + // Insert target Atom into atom track list + if (pleaf->tgtatom) { + bool found = false; + for (latom_t *platom = ps->track_atom_lst; platom; platom = platom->next) { + if (pleaf->tgtatom == platom->atom) { + found = true; + break; + } + } + if (!found) { + auto pnew = cmalloc(latom_t); + pnew->next = ps->track_atom_lst; + pnew->atom = pleaf->tgtatom; + ps->track_atom_lst = pnew; + } + } - // Enable specific tracking options in compton if needed by the condition - // TODO: Add track_leader - if (pleaf->predef) { - switch (pleaf->predef) { - case C2_L_PFOCUSED: ps->o.track_focus = true; break; - // case C2_L_PROUNDED: ps->o.detect_rounded_corners = true; break; - case C2_L_PNAME: - case C2_L_PCLASSG: - case C2_L_PCLASSI: - case C2_L_PROLE: ps->o.track_wdata = true; break; - default: break; - } - } + // Enable specific tracking options in compton if needed by the condition + // TODO: Add track_leader + if (pleaf->predef) { + switch (pleaf->predef) { + case C2_L_PFOCUSED: ps->o.track_focus = true; break; + // case C2_L_PROUNDED: ps->o.detect_rounded_corners = true; break; + case C2_L_PNAME: + case C2_L_PCLASSG: + case C2_L_PCLASSI: + case C2_L_PROLE: ps->o.track_wdata = true; break; + default: break; + } + } - // Warn about lower case characters in target name - if (!pleaf->predef) { - for (const char *pc = pleaf->tgt; *pc; ++pc) { - if (islower(*pc)) { - log_warn("Lowercase character in target name \"%s\".", pleaf->tgt); - break; - } - } - } + // Warn about lower case characters in target name + if (!pleaf->predef) { + for (const char *pc = pleaf->tgt; *pc; ++pc) { + if (islower(*pc)) { + log_warn("Lowercase character in target name \"%s\".", + pleaf->tgt); + break; + } + } + } - // PCRE patterns - if (C2_L_PTSTRING == pleaf->ptntype && C2_L_MPCRE == pleaf->match) { + // PCRE patterns + if (C2_L_PTSTRING == pleaf->ptntype && C2_L_MPCRE == pleaf->match) { #ifdef CONFIG_REGEX_PCRE - const char *error = NULL; - int erroffset = 0; - int options = 0; + const char *error = NULL; + int erroffset = 0; + int options = 0; - // Ignore case flag - if (pleaf->match_ignorecase) - options |= PCRE_CASELESS; + // Ignore case flag + if (pleaf->match_ignorecase) + options |= PCRE_CASELESS; - // Compile PCRE expression - pleaf->regex_pcre = pcre_compile(pleaf->ptnstr, options, - &error, &erroffset, NULL); - if (!pleaf->regex_pcre) { - log_error("Pattern \"%s\": PCRE regular expression parsing failed on " - "offset %d: %s", pleaf->ptnstr, erroffset, error); - return false; - } + // Compile PCRE expression + pleaf->regex_pcre = + pcre_compile(pleaf->ptnstr, options, &error, &erroffset, NULL); + if (!pleaf->regex_pcre) { + log_error("Pattern \"%s\": PCRE regular expression parsing " + "failed on " + "offset %d: %s", + pleaf->ptnstr, erroffset, error); + return false; + } #ifdef CONFIG_REGEX_PCRE_JIT - pleaf->regex_pcre_extra = pcre_study(pleaf->regex_pcre, - PCRE_STUDY_JIT_COMPILE, &error); - if (!pleaf->regex_pcre_extra) { - printf("Pattern \"%s\": PCRE regular expression study failed: %s", - pleaf->ptnstr, error); - } + pleaf->regex_pcre_extra = + pcre_study(pleaf->regex_pcre, PCRE_STUDY_JIT_COMPILE, &error); + if (!pleaf->regex_pcre_extra) { + printf("Pattern \"%s\": PCRE regular expression study failed: %s", + pleaf->ptnstr, error); + } #endif - // Free the target string - // free(pleaf->tgt); - // pleaf->tgt = NULL; + // Free the target string + // free(pleaf->tgt); + // pleaf->tgt = NULL; #else - log_error("PCRE regular expression support not compiled in."); - return false; + log_error("PCRE regular expression support not compiled in."); + return false; #endif - } + } - return true; + return true; } static bool c2_tree_postprocess(session_t *ps, c2_ptr_t node) { - if (!node.isbranch) { - return c2_l_postprocess(ps, node.l); - } - if (!c2_tree_postprocess(ps, node.b->opr1)) - return false; - return c2_tree_postprocess(ps, node.b->opr2); + if (!node.isbranch) { + return c2_l_postprocess(ps, node.l); + } + if (!c2_tree_postprocess(ps, node.b->opr1)) + return false; + return c2_tree_postprocess(ps, node.b->opr2); } bool c2_list_postprocess(session_t *ps, c2_lptr_t *list) { - c2_lptr_t *head = list; - while (head) { - if (!c2_tree_postprocess(ps, head->ptr)) - return false; - head = head->next; - } - return true; + c2_lptr_t *head = list; + while (head) { + if (!c2_tree_postprocess(ps, head->ptr)) + return false; + head = head->next; + } + return true; } /** * Free a condition tree. */ -static void -c2_free(c2_ptr_t p) { - // For a branch element - if (p.isbranch) { - c2_b_t * const pbranch = p.b; +static void c2_free(c2_ptr_t p) { + // For a branch element + if (p.isbranch) { + c2_b_t *const pbranch = p.b; - if (!pbranch) - return; + if (!pbranch) + return; - c2_free(pbranch->opr1); - c2_free(pbranch->opr2); - free(pbranch); - } - // For a leaf element - else { - c2_l_t * const pleaf = p.l; + c2_free(pbranch->opr1); + c2_free(pbranch->opr2); + free(pbranch); + } + // For a leaf element + else { + c2_l_t *const pleaf = p.l; - if (!pleaf) - return; + if (!pleaf) + return; - free(pleaf->tgt); - free(pleaf->ptnstr); + free(pleaf->tgt); + free(pleaf->ptnstr); #ifdef CONFIG_REGEX_PCRE - pcre_free(pleaf->regex_pcre); - LPCRE_FREE_STUDY(pleaf->regex_pcre_extra); + pcre_free(pleaf->regex_pcre); + LPCRE_FREE_STUDY(pleaf->regex_pcre_extra); #endif - free(pleaf); - } + free(pleaf); + } } /** * Free a condition tree in c2_lptr_t. */ -c2_lptr_t * -c2_free_lptr(c2_lptr_t *lp) { - if (!lp) - return NULL; +c2_lptr_t *c2_free_lptr(c2_lptr_t *lp) { + if (!lp) + return NULL; - c2_lptr_t *pnext = lp->next; - c2_free(lp->ptr); - free(lp); + c2_lptr_t *pnext = lp->next; + c2_free(lp->ptr); + free(lp); - return pnext; + return pnext; } /** * Get a string representation of a rule target. */ -static const char * -c2h_dump_str_tgt(const c2_l_t *pleaf) { - if (pleaf->predef) - return C2_PREDEFS[pleaf->predef].name; - else - return pleaf->tgt; +static const char *c2h_dump_str_tgt(const c2_l_t *pleaf) { + if (pleaf->predef) + return C2_PREDEFS[pleaf->predef].name; + else + return pleaf->tgt; } /** * Get a string representation of a target. */ -static const char * -c2h_dump_str_type(const c2_l_t *pleaf) { - switch (pleaf->type) { - case C2_L_TWINDOW: return "w"; - case C2_L_TDRAWABLE: return "d"; - case C2_L_TCARDINAL: return "c"; - case C2_L_TSTRING: return "s"; - case C2_L_TATOM: return "a"; - case C2_L_TUNDEFINED: break; - } +static const char *c2h_dump_str_type(const c2_l_t *pleaf) { + switch (pleaf->type) { + case C2_L_TWINDOW: return "w"; + case C2_L_TDRAWABLE: return "d"; + case C2_L_TCARDINAL: return "c"; + case C2_L_TSTRING: return "s"; + case C2_L_TATOM: return "a"; + case C2_L_TUNDEFINED: break; + } - return NULL; + return NULL; } /** * Dump a condition tree. */ -static void -c2_dump(c2_ptr_t p) { - // For a branch - if (p.isbranch) { - const c2_b_t * const pbranch = p.b; +static void c2_dump(c2_ptr_t p) { + // For a branch + if (p.isbranch) { + const c2_b_t *const pbranch = p.b; - if (!pbranch) - return; + if (!pbranch) + return; - if (pbranch->neg) - putchar('!'); + if (pbranch->neg) + putchar('!'); - printf("("); - c2_dump(pbranch->opr1); + printf("("); + c2_dump(pbranch->opr1); - switch (pbranch->op) { - case C2_B_OAND: printf(" && "); break; - case C2_B_OOR: printf(" || "); break; - case C2_B_OXOR: printf(" XOR "); break; - default: assert(0); break; - } + switch (pbranch->op) { + case C2_B_OAND: printf(" && "); break; + case C2_B_OOR: printf(" || "); break; + case C2_B_OXOR: printf(" XOR "); break; + default: assert(0); break; + } - c2_dump(pbranch->opr2); - printf(")"); - } - // For a leaf - else { - const c2_l_t * const pleaf = p.l; + c2_dump(pbranch->opr2); + printf(")"); + } + // For a leaf + else { + const c2_l_t *const pleaf = p.l; - if (!pleaf) - return; + if (!pleaf) + return; - if (C2_L_OEXISTS == pleaf->op && pleaf->neg) - putchar('!'); + if (C2_L_OEXISTS == pleaf->op && pleaf->neg) + putchar('!'); - // Print target name, type, and format - { - printf("%s", c2h_dump_str_tgt(pleaf)); - if (pleaf->tgt_onframe) - putchar('@'); - if (pleaf->index >= 0) - printf("[%d]", pleaf->index); - printf(":%d%s", pleaf->format, c2h_dump_str_type(pleaf)); - } + // Print target name, type, and format + { + printf("%s", c2h_dump_str_tgt(pleaf)); + if (pleaf->tgt_onframe) + putchar('@'); + if (pleaf->index >= 0) + printf("[%d]", pleaf->index); + printf(":%d%s", pleaf->format, c2h_dump_str_type(pleaf)); + } - // Print operator - putchar(' '); + // Print operator + putchar(' '); - if (C2_L_OEXISTS != pleaf->op && pleaf->neg) - putchar('!'); + if (C2_L_OEXISTS != pleaf->op && pleaf->neg) + putchar('!'); - switch (pleaf->match) { - case C2_L_MEXACT: break; - case C2_L_MCONTAINS: putchar('*'); break; - case C2_L_MSTART: putchar('^'); break; - case C2_L_MPCRE: putchar('~'); break; - case C2_L_MWILDCARD: putchar('%'); break; - } + switch (pleaf->match) { + case C2_L_MEXACT: break; + case C2_L_MCONTAINS: putchar('*'); break; + case C2_L_MSTART: putchar('^'); break; + case C2_L_MPCRE: putchar('~'); break; + case C2_L_MWILDCARD: putchar('%'); break; + } - if (pleaf->match_ignorecase) - putchar('?'); + if (pleaf->match_ignorecase) + putchar('?'); - switch (pleaf->op) { - case C2_L_OEXISTS: break; - case C2_L_OEQ: fputs("=", stdout); break; - case C2_L_OGT: fputs(">", stdout); break; - case C2_L_OGTEQ: fputs(">=", stdout); break; - case C2_L_OLT: fputs("<", stdout); break; - case C2_L_OLTEQ: fputs("<=", stdout); break; - } + switch (pleaf->op) { + case C2_L_OEXISTS: break; + case C2_L_OEQ: fputs("=", stdout); break; + case C2_L_OGT: fputs(">", stdout); break; + case C2_L_OGTEQ: fputs(">=", stdout); break; + case C2_L_OLT: fputs("<", stdout); break; + case C2_L_OLTEQ: fputs("<=", stdout); break; + } - if (C2_L_OEXISTS == pleaf->op) - return; + if (C2_L_OEXISTS == pleaf->op) + return; - // Print pattern - putchar(' '); - switch (pleaf->ptntype) { - case C2_L_PTINT: - printf("%ld", pleaf->ptnint); - break; - case C2_L_PTSTRING: - // TODO: Escape string before printing out? - printf("\"%s\"", pleaf->ptnstr); - break; - default: - assert(0); - break; - } - } + // Print pattern + putchar(' '); + switch (pleaf->ptntype) { + case C2_L_PTINT: printf("%ld", pleaf->ptnint); break; + case C2_L_PTSTRING: + // TODO: Escape string before printing out? + printf("\"%s\"", pleaf->ptnstr); + break; + default: assert(0); break; + } + } } /** * Get the type atom of a condition. */ -static xcb_atom_t -c2_get_atom_type(const c2_l_t *pleaf) { - switch (pleaf->type) { - case C2_L_TCARDINAL: - return XCB_ATOM_CARDINAL; - case C2_L_TWINDOW: - return XCB_ATOM_WINDOW; - case C2_L_TSTRING: - return XCB_ATOM_STRING; - case C2_L_TATOM: - return XCB_ATOM_ATOM; - case C2_L_TDRAWABLE: - return XCB_ATOM_DRAWABLE; - default: - assert(0); - break; - } - unreachable; +static xcb_atom_t c2_get_atom_type(const c2_l_t *pleaf) { + switch (pleaf->type) { + case C2_L_TCARDINAL: return XCB_ATOM_CARDINAL; + case C2_L_TWINDOW: return XCB_ATOM_WINDOW; + case C2_L_TSTRING: return XCB_ATOM_STRING; + case C2_L_TATOM: return XCB_ATOM_ATOM; + case C2_L_TDRAWABLE: return XCB_ATOM_DRAWABLE; + default: assert(0); break; + } + unreachable; } /** @@ -1365,200 +1292,191 @@ c2_get_atom_type(const c2_l_t *pleaf) { * For internal use. */ static inline void -c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, - bool *pres, bool *perr) { - assert(pleaf); +c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, bool *pres, bool *perr) { + 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); - // Return if wid is missing - if (!pleaf->predef && !wid) - return; + // Return if wid is missing + if (!pleaf->predef && !wid) + return; - const int idx = (pleaf->index < 0 ? 0: pleaf->index); + const int idx = (pleaf->index < 0 ? 0 : pleaf->index); - switch (pleaf->ptntype) { - // Deal with integer patterns - case C2_L_PTINT: - { - long tgt = 0; + switch (pleaf->ptntype) { + // Deal with integer patterns + case C2_L_PTINT: { + long tgt = 0; - // Get the value - // A predefined target - if (pleaf->predef) { - *perr = false; - switch (pleaf->predef) { - case C2_L_PID: tgt = wid; break; - case C2_L_PX: tgt = w->g.x; break; - case C2_L_PY: tgt = w->g.y; break; - case C2_L_PX2: tgt = w->g.x + w->widthb; break; - case C2_L_PY2: tgt = w->g.y + w->heightb; break; - case C2_L_PWIDTH: tgt = w->g.width; break; - case C2_L_PHEIGHT: tgt = w->g.height; break; - case C2_L_PWIDTHB: tgt = w->widthb; break; - case C2_L_PHEIGHTB: tgt = w->heightb; break; - case C2_L_PBDW: tgt = w->g.border_width; break; - case C2_L_PFULLSCREEN: tgt = win_is_fullscreen(ps, w); break; - case C2_L_POVREDIR: tgt = w->a.override_redirect; break; - case C2_L_PARGB: tgt = win_has_alpha(w); break; - case C2_L_PFOCUSED: tgt = win_is_focused_real(ps, w); break; - case C2_L_PWMWIN: tgt = w->wmwin; break; - case C2_L_PBSHAPED: tgt = w->bounding_shaped; break; - case C2_L_PROUNDED: tgt = w->rounded_corners; break; - case C2_L_PCLIENT: tgt = w->client_win; break; - case C2_L_PLEADER: tgt = w->leader; break; - default: *perr = true; assert(0); break; - } - } - // A raw window property - else { - winprop_t prop = wid_get_prop_adv(ps, wid, pleaf->tgtatom, - idx, 1L, c2_get_atom_type(pleaf), pleaf->format); - if (prop.nitems) { - *perr = false; - tgt = winprop_get_int(prop); - } - free_winprop(&prop); - } + // Get the value + // A predefined target + if (pleaf->predef) { + *perr = false; + switch (pleaf->predef) { + case C2_L_PID: tgt = wid; break; + case C2_L_PX: tgt = w->g.x; break; + case C2_L_PY: tgt = w->g.y; break; + case C2_L_PX2: tgt = w->g.x + w->widthb; break; + case C2_L_PY2: tgt = w->g.y + w->heightb; break; + case C2_L_PWIDTH: tgt = w->g.width; break; + case C2_L_PHEIGHT: tgt = w->g.height; break; + case C2_L_PWIDTHB: tgt = w->widthb; break; + case C2_L_PHEIGHTB: tgt = w->heightb; break; + case C2_L_PBDW: tgt = w->g.border_width; break; + case C2_L_PFULLSCREEN: tgt = win_is_fullscreen(ps, w); break; + case C2_L_POVREDIR: tgt = w->a.override_redirect; break; + case C2_L_PARGB: tgt = win_has_alpha(w); break; + case C2_L_PFOCUSED: tgt = win_is_focused_real(ps, w); break; + case C2_L_PWMWIN: tgt = w->wmwin; break; + case C2_L_PBSHAPED: tgt = w->bounding_shaped; break; + case C2_L_PROUNDED: tgt = w->rounded_corners; break; + case C2_L_PCLIENT: tgt = w->client_win; break; + case C2_L_PLEADER: tgt = w->leader; break; + default: + *perr = true; + assert(0); + break; + } + } + // A raw window property + else { + winprop_t prop = + wid_get_prop_adv(ps, wid, pleaf->tgtatom, idx, 1L, + c2_get_atom_type(pleaf), pleaf->format); + if (prop.nitems) { + *perr = false; + tgt = winprop_get_int(prop); + } + free_winprop(&prop); + } - if (*perr) - return; + if (*perr) + return; - // Do comparison - switch (pleaf->op) { - case C2_L_OEXISTS: - *pres = (pleaf->predef ? tgt: true); - break; - case C2_L_OEQ: *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_OLT: *pres = (tgt < pleaf->ptnint); break; - case C2_L_OLTEQ: *pres = (tgt <= pleaf->ptnint); break; - default: *perr = true; assert(0); break; - } - } - break; - // String patterns - case C2_L_PTSTRING: - { - const char *tgt = NULL; - char *tgt_free = NULL; + // Do comparison + switch (pleaf->op) { + case C2_L_OEXISTS: *pres = (pleaf->predef ? tgt : true); break; + case C2_L_OEQ: *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_OLT: *pres = (tgt < pleaf->ptnint); break; + case C2_L_OLTEQ: *pres = (tgt <= pleaf->ptnint); break; + default: + *perr = true; + assert(0); + break; + } + } break; + // String patterns + case C2_L_PTSTRING: { + const char *tgt = NULL; + char *tgt_free = NULL; - // A predefined target - if (pleaf->predef) { - switch (pleaf->predef) { - case C2_L_PWINDOWTYPE: tgt = WINTYPES[w->window_type]; - break; - case C2_L_PNAME: tgt = w->name; break; - case C2_L_PCLASSG: tgt = w->class_general; break; - case C2_L_PCLASSI: tgt = w->class_instance; break; - case C2_L_PROLE: tgt = w->role; break; - default: assert(0); break; - } - } - // If it's an atom type property, convert atom to string - else if (C2_L_TATOM == pleaf->type) { - winprop_t prop = 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); - if (atom) { - xcb_get_atom_name_reply_t *reply = - xcb_get_atom_name_reply(ps->c, xcb_get_atom_name(ps->c, atom), NULL); - if (reply) { - tgt_free = strndup( - xcb_get_atom_name_name(reply), xcb_get_atom_name_name_length(reply)); - free(reply); - } - } - if (tgt_free) { - tgt = tgt_free; - } - free_winprop(&prop); - } - // Otherwise, just fetch the string list - else { - char **strlst = NULL; - int nstr; - if (wid_get_text_prop(ps, wid, pleaf->tgtatom, &strlst, - &nstr) && nstr > idx) { - tgt_free = strdup(strlst[idx]); - tgt = tgt_free; - } - if (strlst) - XFreeStringList(strlst); - } + // A predefined target + if (pleaf->predef) { + switch (pleaf->predef) { + case C2_L_PWINDOWTYPE: tgt = WINTYPES[w->window_type]; break; + case C2_L_PNAME: tgt = w->name; break; + case C2_L_PCLASSG: tgt = w->class_general; break; + case C2_L_PCLASSI: tgt = w->class_instance; break; + case C2_L_PROLE: tgt = w->role; break; + default: assert(0); break; + } + } + // If it's an atom type property, convert atom to string + else if (C2_L_TATOM == pleaf->type) { + winprop_t prop = + 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); + if (atom) { + xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply( + ps->c, xcb_get_atom_name(ps->c, atom), NULL); + if (reply) { + tgt_free = + strndup(xcb_get_atom_name_name(reply), + xcb_get_atom_name_name_length(reply)); + free(reply); + } + } + if (tgt_free) { + tgt = tgt_free; + } + free_winprop(&prop); + } + // Otherwise, just fetch the string list + else { + char **strlst = NULL; + int nstr; + if (wid_get_text_prop(ps, wid, pleaf->tgtatom, &strlst, &nstr) && + nstr > idx) { + tgt_free = strdup(strlst[idx]); + tgt = tgt_free; + } + if (strlst) + XFreeStringList(strlst); + } - if (tgt) { - *perr = false; - } - else { - return; - } + if (tgt) { + *perr = false; + } else { + return; + } - // Actual matching - switch (pleaf->op) { - case C2_L_OEXISTS: - *pres = true; - break; - case C2_L_OEQ: - switch (pleaf->match) { - case C2_L_MEXACT: - if (pleaf->match_ignorecase) - *pres = !strcasecmp(tgt, pleaf->ptnstr); - else - *pres = !strcmp(tgt, pleaf->ptnstr); - break; - case C2_L_MCONTAINS: - if (pleaf->match_ignorecase) - *pres = strcasestr(tgt, pleaf->ptnstr); - else - *pres = strstr(tgt, pleaf->ptnstr); - break; - case C2_L_MSTART: - if (pleaf->match_ignorecase) - *pres = !strncasecmp(tgt, pleaf->ptnstr, - strlen(pleaf->ptnstr)); - else - *pres = !strncmp(tgt, pleaf->ptnstr, - strlen(pleaf->ptnstr)); - break; - case C2_L_MWILDCARD: - { - int flags = 0; - if (pleaf->match_ignorecase) - flags |= FNM_CASEFOLD; - *pres = !fnmatch(pleaf->ptnstr, tgt, flags); - } - break; - case C2_L_MPCRE: + // Actual matching + switch (pleaf->op) { + case C2_L_OEXISTS: *pres = true; break; + case C2_L_OEQ: + switch (pleaf->match) { + case C2_L_MEXACT: + if (pleaf->match_ignorecase) + *pres = !strcasecmp(tgt, pleaf->ptnstr); + else + *pres = !strcmp(tgt, pleaf->ptnstr); + break; + case C2_L_MCONTAINS: + if (pleaf->match_ignorecase) + *pres = strcasestr(tgt, pleaf->ptnstr); + else + *pres = strstr(tgt, pleaf->ptnstr); + break; + case C2_L_MSTART: + if (pleaf->match_ignorecase) + *pres = !strncasecmp(tgt, pleaf->ptnstr, + strlen(pleaf->ptnstr)); + else + *pres = !strncmp(tgt, pleaf->ptnstr, + strlen(pleaf->ptnstr)); + break; + case C2_L_MWILDCARD: { + int flags = 0; + if (pleaf->match_ignorecase) + flags |= FNM_CASEFOLD; + *pres = !fnmatch(pleaf->ptnstr, tgt, flags); + } break; + case C2_L_MPCRE: #ifdef CONFIG_REGEX_PCRE - *pres = (pcre_exec(pleaf->regex_pcre, - pleaf->regex_pcre_extra, - tgt, strlen(tgt), 0, 0, NULL, 0) >= 0); + *pres = (pcre_exec(pleaf->regex_pcre, pleaf->regex_pcre_extra, + tgt, strlen(tgt), 0, 0, NULL, 0) >= 0); #else - assert(0); + assert(0); #endif - break; - } - break; - default: - *perr = true; - assert(0); - } + break; + } + break; + default: *perr = true; assert(0); + } - // Free the string after usage, if necessary - if (tgt_free) { - if (C2_L_TATOM == pleaf->type) - cxfree(tgt_free); - else - free(tgt_free); - } - } - break; - default: - assert(0); - break; - } + // Free the string after usage, if necessary + if (tgt_free) { + if (C2_L_TATOM == pleaf->type) + cxfree(tgt_free); + else + free(tgt_free); + } + } break; + default: assert(0); break; + } } /** @@ -1566,74 +1484,71 @@ c2_match_once_leaf(session_t *ps, const win *w, const c2_l_t *pleaf, * * @return true if matched, false otherwise. */ -static bool -c2_match_once(session_t *ps, const win *w, const c2_ptr_t cond) { - bool result = false; - bool error = true; +static bool c2_match_once(session_t *ps, const win *w, const c2_ptr_t cond) { + bool result = false; + bool error = true; - // Handle a branch - if (cond.isbranch) { - const c2_b_t *pb = cond.b; + // Handle a branch + if (cond.isbranch) { + const c2_b_t *pb = cond.b; - if (!pb) - return false; + if (!pb) + return false; - error = false; + error = false; - switch (pb->op) { - case C2_B_OAND: - result = (c2_match_once(ps, w, pb->opr1) - && c2_match_once(ps, w, pb->opr2)); - break; - case C2_B_OOR: - result = (c2_match_once(ps, w, pb->opr1) - || c2_match_once(ps, w, pb->opr2)); - break; - case C2_B_OXOR: - result = (c2_match_once(ps, w, pb->opr1) - != c2_match_once(ps, w, pb->opr2)); - break; - default: - error = true; - assert(0); - } + switch (pb->op) { + case C2_B_OAND: + result = (c2_match_once(ps, w, pb->opr1) && + c2_match_once(ps, w, pb->opr2)); + break; + case C2_B_OOR: + result = (c2_match_once(ps, w, pb->opr1) || + c2_match_once(ps, w, pb->opr2)); + break; + case C2_B_OXOR: + result = (c2_match_once(ps, w, pb->opr1) != + c2_match_once(ps, w, pb->opr2)); + break; + default: error = true; assert(0); + } #ifdef DEBUG_WINMATCH - log_trace("(%#010lx): branch: result = %d, pattern = ", w->id, result); - c2_dump(cond); + log_trace("(%#010lx): branch: result = %d, pattern = ", w->id, result); + c2_dump(cond); #endif - } - // Handle a leaf - else { - const c2_l_t *pleaf = cond.l; + } + // Handle a leaf + else { + const c2_l_t *pleaf = cond.l; - if (!pleaf) - return false; + if (!pleaf) + return false; - c2_match_once_leaf(ps, w, pleaf, &result, &error); + c2_match_once_leaf(ps, w, pleaf, &result, &error); - // For EXISTS operator, no errors are fatal - if (C2_L_OEXISTS == pleaf->op && error) { - result = false; - error = false; - } + // For EXISTS operator, no errors are fatal + if (C2_L_OEXISTS == pleaf->op && error) { + result = false; + error = false; + } #ifdef DEBUG_WINMATCH - log_trace("(%#010lx): leaf: result = %d, error = %d, " - "client = %#010lx, pattern = ", - w->id, result, error, w->client_win); - c2_dump(cond); + log_trace("(%#010lx): leaf: result = %d, error = %d, " + "client = %#010lx, pattern = ", + w->id, result, error, w->client_win); + c2_dump(cond); #endif - } + } - // Postprocess the result - if (error) - result = false; + // Postprocess the result + if (error) + result = false; - if (cond.isbranch ? cond.b->neg: cond.l->neg) - result = !result; + if (cond.isbranch ? cond.b->neg : cond.l->neg) + result = !result; - return result; + return result; } /** @@ -1643,17 +1558,15 @@ c2_match_once(session_t *ps, const win *w, const c2_ptr_t cond) { * @param pdata a place to return the data * @return true if matched, false otherwise. */ -bool -c2_match(session_t *ps, const win *w, const c2_lptr_t *condlst, void **pdata) { - // Then go through the whole linked list - for (; condlst; condlst = condlst->next) { - if (c2_match_once(ps, w, condlst->ptr)) { - if (pdata) - *pdata = condlst->data; - return true; - } - } +bool c2_match(session_t *ps, const win *w, const c2_lptr_t *condlst, void **pdata) { + // Then go through the whole linked list + for (; condlst; condlst = condlst->next) { + if (c2_match_once(ps, w, condlst->ptr)) { + if (pdata) + *pdata = condlst->data; + return true; + } + } - return false; + return false; } - diff --git a/src/common.h b/src/common.h index a0edf25..4690ee7 100644 --- a/src/common.h +++ b/src/common.h @@ -28,26 +28,26 @@ // === Includes === // For some special functions +#include +#include +#include #include #include #include #include -#include -#include -#include -#include #include +#include #include +#include +#include #include -#include #include #include +#include #include #include #include -#include -#include #ifdef CONFIG_OPENGL // libGL @@ -67,8 +67,8 @@ // === Macros === -#define MSTR_(s) #s -#define MSTR(s) MSTR_(s) +#define MSTR_(s) #s +#define MSTR(s) MSTR_(s) // X resource checker #ifdef DEBUG_XRC @@ -76,17 +76,17 @@ #endif // 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 "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 === @@ -94,7 +94,7 @@ #define BUF_LEN 80 #define ROUNDED_PERCENT 0.05 -#define ROUNDED_PIXELS 10 +#define ROUNDED_PIXELS 10 #define REGISTER_PROP "_NET_WM_CM_S" @@ -106,9 +106,9 @@ #define US_PER_SEC 1000000L #define MS_PER_SEC 1000 -#define XRFILTER_CONVOLUTION "convolution" -#define XRFILTER_GAUSSIAN "gaussian" -#define XRFILTER_BINOMIAL "binomial" +#define XRFILTER_CONVOLUTION "convolution" +#define XRFILTER_GAUSSIAN "gaussian" +#define XRFILTER_BINOMIAL "binomial" /// @brief Maximum OpenGL FBConfig depth. #define OPENGL_MAX_DEPTH 32 @@ -119,456 +119,444 @@ // Window flags // Window size is changed -#define WFLAG_SIZE_CHANGE 0x0001 +#define WFLAG_SIZE_CHANGE 0x0001 // Window size/position is changed -#define WFLAG_POS_CHANGE 0x0002 +#define WFLAG_POS_CHANGE 0x0002 // Window opacity / dim state changed -#define WFLAG_OPCT_CHANGE 0x0004 +#define WFLAG_OPCT_CHANGE 0x0004 // === Types === typedef struct glx_fbconfig glx_fbconfig_t; /// Structure representing needed window updates. typedef struct { - bool shadow : 1; - bool fade : 1; - bool focus : 1; - bool invert_color : 1; + bool shadow : 1; + bool fade : 1; + bool focus : 1; + bool invert_color : 1; } win_upd_t; typedef struct _ignore { - struct _ignore *next; - unsigned long sequence; + struct _ignore *next; + unsigned long sequence; } ignore_t; enum wincond_target { - CONDTGT_NAME, - CONDTGT_CLASSI, - CONDTGT_CLASSG, - CONDTGT_ROLE, + CONDTGT_NAME, + CONDTGT_CLASSI, + CONDTGT_CLASSG, + CONDTGT_ROLE, }; enum wincond_type { - CONDTP_EXACT, - CONDTP_ANYWHERE, - CONDTP_FROMSTART, - CONDTP_WILDCARD, - CONDTP_REGEX_PCRE, + CONDTP_EXACT, + CONDTP_ANYWHERE, + CONDTP_FROMSTART, + CONDTP_WILDCARD, + CONDTP_REGEX_PCRE, }; #define CONDF_IGNORECASE 0x0001 /// @brief Possible swap methods. -enum { - SWAPM_BUFFER_AGE = -1, - SWAPM_UNDEFINED = 0, - SWAPM_COPY = 1, - SWAPM_EXCHANGE = 2, +enum { SWAPM_BUFFER_AGE = -1, + SWAPM_UNDEFINED = 0, + SWAPM_COPY = 1, + SWAPM_EXCHANGE = 2, }; typedef struct _glx_texture glx_texture_t; #ifdef CONFIG_OPENGL #ifdef DEBUG_GLX_DEBUG_CONTEXT -typedef GLXContext (*f_glXCreateContextAttribsARB) (Display *dpy, - GLXFBConfig config, GLXContext share_context, Bool direct, - const int *attrib_list); -typedef void (*GLDEBUGPROC) (GLenum source, GLenum type, - GLuint id, GLenum severity, GLsizei length, const GLchar* message, - GLvoid* userParam); -typedef void (*f_DebugMessageCallback) (GLDEBUGPROC, void *userParam); +typedef GLXContext (*f_glXCreateContextAttribsARB)(Display *dpy, GLXFBConfig config, + GLXContext share_context, Bool direct, + const int *attrib_list); +typedef void (*GLDEBUGPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, + GLsizei length, const GLchar *message, GLvoid *userParam); +typedef void (*f_DebugMessageCallback)(GLDEBUGPROC, void *userParam); #endif #ifdef CONFIG_OPENGL -typedef GLsync (*f_FenceSync) (GLenum condition, GLbitfield flags); -typedef GLboolean (*f_IsSync) (GLsync sync); -typedef void (*f_DeleteSync) (GLsync sync); -typedef GLenum (*f_ClientWaitSync) (GLsync sync, GLbitfield flags, - GLuint64 timeout); -typedef void (*f_WaitSync) (GLsync sync, GLbitfield flags, - GLuint64 timeout); -typedef GLsync (*f_ImportSyncEXT) (GLenum external_sync_type, - GLintptr external_sync, GLbitfield flags); +typedef GLsync (*f_FenceSync)(GLenum condition, GLbitfield flags); +typedef GLboolean (*f_IsSync)(GLsync sync); +typedef void (*f_DeleteSync)(GLsync sync); +typedef GLenum (*f_ClientWaitSync)(GLsync sync, GLbitfield flags, GLuint64 timeout); +typedef void (*f_WaitSync)(GLsync sync, GLbitfield flags, GLuint64 timeout); +typedef GLsync (*f_ImportSyncEXT)(GLenum external_sync_type, GLintptr external_sync, + GLbitfield flags); #endif /// @brief Wrapper of a binded GLX texture. struct _glx_texture { - GLuint texture; - GLXPixmap glpixmap; - xcb_pixmap_t pixmap; - GLenum target; - unsigned width; - unsigned height; - bool y_inverted; + GLuint texture; + GLXPixmap glpixmap; + xcb_pixmap_t pixmap; + GLenum target; + unsigned width; + unsigned height; + bool y_inverted; }; #ifdef CONFIG_OPENGL typedef struct { - /// Fragment shader for blur. - GLuint frag_shader; - /// GLSL program for blur. - GLuint prog; - /// Location of uniform "offset_x" in blur GLSL program. - GLint unifm_offset_x; - /// Location of uniform "offset_y" in blur GLSL program. - GLint unifm_offset_y; - /// Location of uniform "factor_center" in blur GLSL program. - GLint unifm_factor_center; + /// Fragment shader for blur. + GLuint frag_shader; + /// GLSL program for blur. + GLuint prog; + /// Location of uniform "offset_x" in blur GLSL program. + GLint unifm_offset_x; + /// Location of uniform "offset_y" in blur GLSL program. + GLint unifm_offset_y; + /// Location of uniform "factor_center" in blur GLSL program. + GLint unifm_factor_center; } glx_blur_pass_t; typedef struct glx_prog_main { - /// GLSL program. - GLuint prog; - /// Location of uniform "opacity" in window GLSL program. - GLint unifm_opacity; - /// Location of uniform "invert_color" in blur GLSL program. - GLint unifm_invert_color; - /// Location of uniform "tex" in window GLSL program. - GLint unifm_tex; + /// GLSL program. + GLuint prog; + /// Location of uniform "opacity" in window GLSL program. + GLint unifm_opacity; + /// Location of uniform "invert_color" in blur GLSL program. + GLint unifm_invert_color; + /// Location of uniform "tex" in window GLSL program. + GLint unifm_tex; } glx_prog_main_t; -#define GLX_PROG_MAIN_INIT { \ - .prog = 0, \ - .unifm_opacity = -1, \ - .unifm_invert_color = -1, \ - .unifm_tex = -1, \ -} +#define GLX_PROG_MAIN_INIT \ + { .prog = 0, .unifm_opacity = -1, .unifm_invert_color = -1, .unifm_tex = -1, } #endif #else -struct glx_prog_main { }; +struct glx_prog_main {}; #endif -#define PAINT_INIT { .pixmap = XCB_NONE, .pict = XCB_NONE } +#define PAINT_INIT \ + { .pixmap = XCB_NONE, .pict = XCB_NONE } /// Linked list type of atoms. typedef struct _latom { - xcb_atom_t atom; - struct _latom *next; + xcb_atom_t atom; + struct _latom *next; } latom_t; -#define REG_DATA_INIT { NULL, 0 } +#define REG_DATA_INIT \ + { NULL, 0 } #ifdef CONFIG_OPENGL /// Structure containing GLX-dependent data for a compton session. typedef struct { - // === OpenGL related === - /// GLX context. - GLXContext context; - /// Whether we have GL_ARB_texture_non_power_of_two. - bool has_texture_non_power_of_two; - /// Pointer to the glFenceSync() function. - f_FenceSync glFenceSyncProc; - /// Pointer to the glIsSync() function. - f_IsSync glIsSyncProc; - /// Pointer to the glDeleteSync() function. - f_DeleteSync glDeleteSyncProc; - /// Pointer to the glClientWaitSync() function. - f_ClientWaitSync glClientWaitSyncProc; - /// Pointer to the glWaitSync() function. - f_WaitSync glWaitSyncProc; - /// Pointer to the glImportSyncEXT() function. - f_ImportSyncEXT glImportSyncEXT; - /// Current GLX Z value. - int z; + // === OpenGL related === + /// GLX context. + GLXContext context; + /// Whether we have GL_ARB_texture_non_power_of_two. + bool has_texture_non_power_of_two; + /// Pointer to the glFenceSync() function. + f_FenceSync glFenceSyncProc; + /// Pointer to the glIsSync() function. + f_IsSync glIsSyncProc; + /// Pointer to the glDeleteSync() function. + f_DeleteSync glDeleteSyncProc; + /// Pointer to the glClientWaitSync() function. + f_ClientWaitSync glClientWaitSyncProc; + /// Pointer to the glWaitSync() function. + f_WaitSync glWaitSyncProc; + /// Pointer to the glImportSyncEXT() function. + f_ImportSyncEXT glImportSyncEXT; + /// Current GLX Z value. + int z; #ifdef CONFIG_OPENGL - glx_blur_pass_t blur_passes[MAX_BLUR_PASS]; + glx_blur_pass_t blur_passes[MAX_BLUR_PASS]; #endif } glx_session_t; -#define CGLX_SESSION_INIT { .context = NULL } +#define CGLX_SESSION_INIT \ + { .context = NULL } #endif /// Structure containing all necessary data for a compton session. typedef struct session { - // === Event handlers === - /// ev_io for X connection - ev_io xiow; - /// Timeout for delayed unredirection. - ev_timer unredir_timer; - /// Timer for fading - ev_timer fade_timer; - /// Timer for delayed drawing, right now only used by - /// swopti - ev_timer delayed_draw_timer; - /// Use an ev_idle callback for drawing - /// So we only start drawing when events are processed - ev_idle draw_idle; - /// Called everytime we have timeouts or new data on socket, - /// so we can be sure if xcb read from X socket at anytime during event - /// handling, we will not left any event unhandled in the queue - ev_prepare event_check; - /// Signal handler for SIGUSR1 - ev_signal usr1_signal; - /// Signal handler for SIGINT - ev_signal int_signal; - /// backend data - backend_t *backend_data; - /// libev mainloop - struct ev_loop *loop; + // === Event handlers === + /// ev_io for X connection + ev_io xiow; + /// Timeout for delayed unredirection. + ev_timer unredir_timer; + /// Timer for fading + ev_timer fade_timer; + /// Timer for delayed drawing, right now only used by + /// swopti + ev_timer delayed_draw_timer; + /// Use an ev_idle callback for drawing + /// So we only start drawing when events are processed + ev_idle draw_idle; + /// Called everytime we have timeouts or new data on socket, + /// so we can be sure if xcb read from X socket at anytime during event + /// handling, we will not left any event unhandled in the queue + ev_prepare event_check; + /// Signal handler for SIGUSR1 + ev_signal usr1_signal; + /// Signal handler for SIGINT + ev_signal int_signal; + /// backend data + backend_t *backend_data; + /// libev mainloop + struct ev_loop *loop; - // === Display related === - /// Display in use. - Display *dpy; - /// Default screen. - int scr; - /// XCB connection. - xcb_connection_t *c; - /// Default visual. - xcb_visualid_t vis; - /// Default depth. - int depth; - /// Root window. - xcb_window_t root; - /// Height of root window. - int root_height; - /// Width of root window. - int root_width; - // Damage of root window. - // Damage root_damage; - /// X Composite overlay window. Used if --paint-on-overlay. - xcb_window_t overlay; - /// Whether the root tile is filled by compton. - bool root_tile_fill; - /// Picture of the root window background. - paint_t root_tile_paint; - /// The backend data the root pixmap bound to - void *root_image; - /// A region of the size of the screen. - region_t screen_reg; - /// Picture of root window. Destination of painting in no-DBE painting - /// mode. - xcb_render_picture_t root_picture; - /// A Picture acting as the painting target. - xcb_render_picture_t tgt_picture; - /// Temporary buffer to paint to before sending to display. - paint_t tgt_buffer; - /// Window ID of the window we register as a symbol. - xcb_window_t reg_win; + // === Display related === + /// Display in use. + Display *dpy; + /// Default screen. + int scr; + /// XCB connection. + xcb_connection_t *c; + /// Default visual. + xcb_visualid_t vis; + /// Default depth. + int depth; + /// Root window. + xcb_window_t root; + /// Height of root window. + int root_height; + /// Width of root window. + int root_width; + // Damage of root window. + // Damage root_damage; + /// X Composite overlay window. Used if --paint-on-overlay. + xcb_window_t overlay; + /// Whether the root tile is filled by compton. + bool root_tile_fill; + /// Picture of the root window background. + paint_t root_tile_paint; + /// The backend data the root pixmap bound to + void *root_image; + /// A region of the size of the screen. + region_t screen_reg; + /// Picture of root window. Destination of painting in no-DBE painting + /// mode. + xcb_render_picture_t root_picture; + /// A Picture acting as the painting target. + xcb_render_picture_t tgt_picture; + /// Temporary buffer to paint to before sending to display. + paint_t tgt_buffer; + /// Window ID of the window we register as a symbol. + xcb_window_t reg_win; #ifdef CONFIG_OPENGL - /// Pointer to GLX data. - glx_session_t *psglx; - /// Custom GLX program used for painting window. - // XXX should be in glx_session_t - glx_prog_main_t glx_prog_win; + /// Pointer to GLX data. + glx_session_t *psglx; + /// Custom GLX program used for painting window. + // XXX should be in glx_session_t + glx_prog_main_t glx_prog_win; #endif - /// Sync fence to sync draw operations - xcb_sync_fence_t sync_fence; + /// Sync fence to sync draw operations + xcb_sync_fence_t sync_fence; - // === Operation related === - /// Program options. - options_t o; - /// Whether we have hit unredirection timeout. - bool tmout_unredir_hit; - /// Whether we need to redraw the screen - bool redraw_needed; - /// Program start time. - struct timeval time_start; - /// The region needs to painted on next paint. - region_t *damage; - /// The region damaged on the last paint. - region_t *damage_ring; - /// Number of damage regions we track - int ndamage; - /// Whether all windows are currently redirected. - bool redirected; - /// Pre-generated alpha pictures. - xcb_render_picture_t *alpha_picts; - /// Time of last fading. In milliseconds. - unsigned long fade_time; - /// Head pointer of the error ignore linked list. - ignore_t *ignore_head; - /// Pointer to the next member of tail element of the error - /// ignore linked list. - ignore_t **ignore_tail; - // Cached blur convolution kernels. - xcb_render_fixed_t *blur_kerns_cache[MAX_BLUR_PASS]; - /// Reset program after next paint. - bool reset; - /// If compton should quit - bool quit; + // === Operation related === + /// Program options. + options_t o; + /// Whether we have hit unredirection timeout. + bool tmout_unredir_hit; + /// Whether we need to redraw the screen + bool redraw_needed; + /// Program start time. + struct timeval time_start; + /// The region needs to painted on next paint. + region_t *damage; + /// The region damaged on the last paint. + region_t *damage_ring; + /// Number of damage regions we track + int ndamage; + /// Whether all windows are currently redirected. + bool redirected; + /// Pre-generated alpha pictures. + xcb_render_picture_t *alpha_picts; + /// Time of last fading. In milliseconds. + unsigned long fade_time; + /// Head pointer of the error ignore linked list. + ignore_t *ignore_head; + /// Pointer to the next member of tail element of the error + /// ignore linked list. + ignore_t **ignore_tail; + // Cached blur convolution kernels. + xcb_render_fixed_t *blur_kerns_cache[MAX_BLUR_PASS]; + /// Reset program after next paint. + bool reset; + /// If compton should quit + bool quit; - // === Expose event related === - /// Pointer to an array of XRectangle-s of exposed region. - /// XXX why do we need this array? - rect_t *expose_rects; - /// Number of XRectangle-s in expose_rects. - int size_expose; - /// Index of the next free slot in expose_rects. - int n_expose; + // === Expose event related === + /// Pointer to an array of XRectangle-s of exposed region. + /// XXX why do we need this array? + rect_t *expose_rects; + /// Number of XRectangle-s in expose_rects. + int size_expose; + /// Index of the next free slot in expose_rects. + int n_expose; - // === Window related === - /// Linked list of all windows. - win *list; - /// Pointer to win of current active window. Used by - /// EWMH _NET_ACTIVE_WINDOW focus detection. In theory, - /// it's more reliable to store the window ID directly here, just in - /// case the WM does something extraordinary, but caching the pointer - /// means another layer of complexity. - win *active_win; - /// Window ID of leader window of currently active window. Used for - /// subsidiary window detection. - xcb_window_t active_leader; + // === Window related === + /// Linked list of all windows. + win *list; + /// Pointer to win of current active window. Used by + /// EWMH _NET_ACTIVE_WINDOW focus detection. In theory, + /// it's more reliable to store the window ID directly here, just in + /// case the WM does something extraordinary, but caching the pointer + /// means another layer of complexity. + win *active_win; + /// Window ID of leader window of currently active window. Used for + /// subsidiary window detection. + xcb_window_t active_leader; - // === Shadow/dimming related === - /// 1x1 black Picture. - xcb_render_picture_t black_picture; - /// 1x1 Picture of the shadow color. - xcb_render_picture_t cshadow_picture; - /// 1x1 white Picture. - xcb_render_picture_t white_picture; - /// Gaussian map of shadow. - conv *gaussian_map; - // for shadow precomputation - /// A region in which shadow is not painted on. - region_t shadow_exclude_reg; + // === Shadow/dimming related === + /// 1x1 black Picture. + xcb_render_picture_t black_picture; + /// 1x1 Picture of the shadow color. + xcb_render_picture_t cshadow_picture; + /// 1x1 white Picture. + xcb_render_picture_t white_picture; + /// Gaussian map of shadow. + conv *gaussian_map; + // for shadow precomputation + /// A region in which shadow is not painted on. + region_t shadow_exclude_reg; - // === Software-optimization-related === - /// Currently used refresh rate. - short refresh_rate; - /// Interval between refresh in nanoseconds. - long refresh_intv; - /// Nanosecond offset of the first painting. - long paint_tm_offset; + // === Software-optimization-related === + /// Currently used refresh rate. + short refresh_rate; + /// Interval between refresh in nanoseconds. + long refresh_intv; + /// Nanosecond offset of the first painting. + long paint_tm_offset; #ifdef CONFIG_VSYNC_DRM - // === DRM VSync related === - /// File descriptor of DRI device file. Used for DRM VSync. - int drm_fd; + // === DRM VSync related === + /// File descriptor of DRI device file. Used for DRM VSync. + int drm_fd; #endif - // === X extension related === - /// Event base number for X Fixes extension. - int xfixes_event; - /// Error base number for X Fixes extension. - int xfixes_error; - /// Event base number for X Damage extension. - int damage_event; - /// Error base number for X Damage extension. - int damage_error; - /// Event base number for X Render extension. - int render_event; - /// Error base number for X Render extension. - int render_error; - /// Event base number for X Composite extension. - int composite_event; - /// Error base number for X Composite extension. - int composite_error; - /// Major opcode for X Composite extension. - int composite_opcode; - /// Whether X Shape extension exists. - bool shape_exists; - /// Event base number for X Shape extension. - int shape_event; - /// Error base number for X Shape extension. - int shape_error; - /// Whether X RandR extension exists. - bool randr_exists; - /// Event base number for X RandR extension. - int randr_event; - /// Error base number for X RandR extension. - int randr_error; - /// Whether X Present extension exists. - bool present_exists; + // === X extension related === + /// Event base number for X Fixes extension. + int xfixes_event; + /// Error base number for X Fixes extension. + int xfixes_error; + /// Event base number for X Damage extension. + int damage_event; + /// Error base number for X Damage extension. + int damage_error; + /// Event base number for X Render extension. + int render_event; + /// Error base number for X Render extension. + int render_error; + /// Event base number for X Composite extension. + int composite_event; + /// Error base number for X Composite extension. + int composite_error; + /// Major opcode for X Composite extension. + int composite_opcode; + /// Whether X Shape extension exists. + bool shape_exists; + /// Event base number for X Shape extension. + int shape_event; + /// Error base number for X Shape extension. + int shape_error; + /// Whether X RandR extension exists. + bool randr_exists; + /// Event base number for X RandR extension. + int randr_event; + /// Error base number for X RandR extension. + int randr_error; + /// Whether X Present extension exists. + bool present_exists; #ifdef CONFIG_OPENGL - /// Whether X GLX extension exists. - bool glx_exists; - /// Event base number for X GLX extension. - int glx_event; - /// Error base number for X GLX extension. - int glx_error; + /// Whether X GLX extension exists. + bool glx_exists; + /// Event base number for X GLX extension. + int glx_event; + /// Error base number for X GLX extension. + int glx_error; #endif - /// Whether X Xinerama extension exists. - bool xinerama_exists; - /// Xinerama screen info. - xcb_xinerama_query_screens_reply_t *xinerama_scrs; - /// Xinerama screen regions. - region_t *xinerama_scr_regs; - /// Number of Xinerama screens. - int xinerama_nscrs; - /// Whether X Sync extension exists. - bool xsync_exists; - /// Event base number for X Sync extension. - int xsync_event; - /// Error base number for X Sync extension. - int xsync_error; - /// Whether X Render convolution filter exists. - bool xrfilter_convolution_exists; + /// Whether X Xinerama extension exists. + bool xinerama_exists; + /// Xinerama screen info. + xcb_xinerama_query_screens_reply_t *xinerama_scrs; + /// Xinerama screen regions. + region_t *xinerama_scr_regs; + /// Number of Xinerama screens. + int xinerama_nscrs; + /// Whether X Sync extension exists. + bool xsync_exists; + /// Event base number for X Sync extension. + int xsync_event; + /// Error base number for X Sync extension. + int xsync_error; + /// Whether X Render convolution filter exists. + bool xrfilter_convolution_exists; - // === Atoms === - /// Atom of property _NET_WM_OPACITY. - xcb_atom_t atom_opacity; - /// Atom of _NET_FRAME_EXTENTS. - xcb_atom_t atom_frame_extents; - /// Property atom to identify top-level frame window. Currently - /// WM_STATE. - xcb_atom_t atom_client; - /// Atom of property WM_NAME. - xcb_atom_t atom_name; - /// Atom of property _NET_WM_NAME. - xcb_atom_t atom_name_ewmh; - /// Atom of property WM_CLASS. - xcb_atom_t atom_class; - /// Atom of property WM_WINDOW_ROLE. - xcb_atom_t atom_role; - /// Atom of property WM_TRANSIENT_FOR. - xcb_atom_t atom_transient; - /// Atom of property WM_CLIENT_LEADER. - xcb_atom_t atom_client_leader; - /// Atom of property _NET_ACTIVE_WINDOW. - xcb_atom_t atom_ewmh_active_win; - /// Atom of property _COMPTON_SHADOW. - xcb_atom_t atom_compton_shadow; - /// Atom of property _NET_WM_WINDOW_TYPE. - xcb_atom_t atom_win_type; - /// Array of atoms of all possible window types. - xcb_atom_t atoms_wintypes[NUM_WINTYPES]; - /// Linked list of additional atoms to track. - latom_t *track_atom_lst; + // === Atoms === + /// Atom of property _NET_WM_OPACITY. + xcb_atom_t atom_opacity; + /// Atom of _NET_FRAME_EXTENTS. + xcb_atom_t atom_frame_extents; + /// Property atom to identify top-level frame window. Currently + /// WM_STATE. + xcb_atom_t atom_client; + /// Atom of property WM_NAME. + xcb_atom_t atom_name; + /// Atom of property _NET_WM_NAME. + xcb_atom_t atom_name_ewmh; + /// Atom of property WM_CLASS. + xcb_atom_t atom_class; + /// Atom of property WM_WINDOW_ROLE. + xcb_atom_t atom_role; + /// Atom of property WM_TRANSIENT_FOR. + xcb_atom_t atom_transient; + /// Atom of property WM_CLIENT_LEADER. + xcb_atom_t atom_client_leader; + /// Atom of property _NET_ACTIVE_WINDOW. + xcb_atom_t atom_ewmh_active_win; + /// Atom of property _COMPTON_SHADOW. + xcb_atom_t atom_compton_shadow; + /// Atom of property _NET_WM_WINDOW_TYPE. + xcb_atom_t atom_win_type; + /// Array of atoms of all possible window types. + xcb_atom_t atoms_wintypes[NUM_WINTYPES]; + /// Linked list of additional atoms to track. + latom_t *track_atom_lst; #ifdef CONFIG_DBUS - // === DBus related === - void *dbus_data; + // === DBus related === + void *dbus_data; #endif } session_t; /// Temporary structure used for communication between /// get_cfg() and parse_config(). struct options_tmp { - bool no_dock_shadow; - bool no_dnd_shadow; - double menu_opacity; + bool no_dock_shadow; + bool no_dnd_shadow; + double menu_opacity; }; /// Enumeration for window event hints. -typedef enum { - WIN_EVMODE_UNKNOWN, - WIN_EVMODE_FRAME, - WIN_EVMODE_CLIENT -} win_evmode_t; +typedef enum { 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; // == Debugging code == -static inline void -print_timestamp(session_t *ps); +static inline void print_timestamp(session_t *ps); -void -ev_xcb_error(session_t *ps, xcb_generic_error_t *err); +void ev_xcb_error(session_t *ps, xcb_generic_error_t *err); // === Functions === /** * Return whether a struct timeval value is empty. */ -static inline bool -timeval_isempty(struct timeval *ptv) { - if (!ptv) - return false; +static inline bool timeval_isempty(struct timeval *ptv) { + if (!ptv) + return false; - return ptv->tv_sec <= 0 && ptv->tv_usec <= 0; + return ptv->tv_sec <= 0 && ptv->tv_usec <= 0; } /** @@ -576,29 +564,28 @@ timeval_isempty(struct timeval *ptv) { * * @return > 0 if ptv > ms, 0 if ptv == 0, -1 if ptv < ms */ -static inline int -timeval_ms_cmp(struct timeval *ptv, unsigned long ms) { - assert(ptv); +static inline int timeval_ms_cmp(struct timeval *ptv, unsigned long ms) { + assert(ptv); - // We use those if statement instead of a - expression because of possible - // truncation problem from long to int. - { - long sec = ms / MS_PER_SEC; - if (ptv->tv_sec > sec) - return 1; - if (ptv->tv_sec < sec) - return -1; - } + // We use those if statement instead of a - expression because of possible + // truncation problem from long to int. + { + long sec = ms / MS_PER_SEC; + if (ptv->tv_sec > sec) + return 1; + if (ptv->tv_sec < sec) + return -1; + } - { - long usec = ms % MS_PER_SEC * (US_PER_SEC / MS_PER_SEC); - if (ptv->tv_usec > usec) - return 1; - if (ptv->tv_usec < usec) - return -1; - } + { + long usec = ms % MS_PER_SEC * (US_PER_SEC / MS_PER_SEC); + if (ptv->tv_usec > usec) + return 1; + if (ptv->tv_usec < usec) + return -1; + } - return 0; + return 0; } /** @@ -611,29 +598,27 @@ timeval_ms_cmp(struct timeval *ptv, unsigned long ms) { * Return 1 if the difference is negative, otherwise 0. */ static inline int -timeval_subtract(struct timeval *result, - struct timeval *x, - struct timeval *y) { - /* Perform the carry for the later subtraction by updating y. */ - if (x->tv_usec < y->tv_usec) { - long nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; - y->tv_usec -= 1000000 * nsec; - y->tv_sec += nsec; - } +timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) { + /* Perform the carry for the later subtraction by updating y. */ + if (x->tv_usec < y->tv_usec) { + long nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; + y->tv_usec -= 1000000 * nsec; + y->tv_sec += nsec; + } - if (x->tv_usec - y->tv_usec > 1000000) { - long nsec = (x->tv_usec - y->tv_usec) / 1000000; - y->tv_usec += 1000000 * nsec; - y->tv_sec -= nsec; - } + if (x->tv_usec - y->tv_usec > 1000000) { + long nsec = (x->tv_usec - y->tv_usec) / 1000000; + y->tv_usec += 1000000 * nsec; + y->tv_sec -= nsec; + } - /* Compute the time remaining to wait. - tv_usec is certainly positive. */ - result->tv_sec = x->tv_sec - y->tv_sec; - result->tv_usec = x->tv_usec - y->tv_usec; + /* Compute the time remaining to wait. + tv_usec is certainly positive. */ + result->tv_sec = x->tv_sec - y->tv_sec; + result->tv_usec = x->tv_usec - y->tv_usec; - /* Return 1 if result is negative. */ - return x->tv_sec < y->tv_sec; + /* Return 1 if result is negative. */ + return x->tv_sec < y->tv_sec; } /** @@ -646,42 +631,39 @@ timeval_subtract(struct timeval *result, * Return 1 if the difference is negative, otherwise 0. */ static inline int -timespec_subtract(struct timespec *result, - struct timespec *x, - struct timespec *y) { - /* Perform the carry for the later subtraction by updating y. */ - if (x->tv_nsec < y->tv_nsec) { - long nsec = (y->tv_nsec - x->tv_nsec) / NS_PER_SEC + 1; - y->tv_nsec -= NS_PER_SEC * nsec; - y->tv_sec += nsec; - } +timespec_subtract(struct timespec *result, struct timespec *x, struct timespec *y) { + /* Perform the carry for the later subtraction by updating y. */ + if (x->tv_nsec < y->tv_nsec) { + long nsec = (y->tv_nsec - x->tv_nsec) / NS_PER_SEC + 1; + y->tv_nsec -= NS_PER_SEC * nsec; + y->tv_sec += nsec; + } - if (x->tv_nsec - y->tv_nsec > NS_PER_SEC) { - long nsec = (x->tv_nsec - y->tv_nsec) / NS_PER_SEC; - y->tv_nsec += NS_PER_SEC * nsec; - y->tv_sec -= nsec; - } + if (x->tv_nsec - y->tv_nsec > NS_PER_SEC) { + long nsec = (x->tv_nsec - y->tv_nsec) / NS_PER_SEC; + y->tv_nsec += NS_PER_SEC * nsec; + y->tv_sec -= nsec; + } - /* Compute the time remaining to wait. - tv_nsec is certainly positive. */ - result->tv_sec = x->tv_sec - y->tv_sec; - result->tv_nsec = x->tv_nsec - y->tv_nsec; + /* Compute the time remaining to wait. + tv_nsec is certainly positive. */ + result->tv_sec = x->tv_sec - y->tv_sec; + result->tv_nsec = x->tv_nsec - y->tv_nsec; - /* Return 1 if result is negative. */ - return x->tv_sec < y->tv_sec; + /* Return 1 if result is negative. */ + return x->tv_sec < y->tv_sec; } /** * Get current time in struct timeval. */ -static inline struct timeval -get_time_timeval(void) { - struct timeval tv = { 0, 0 }; +static inline struct timeval get_time_timeval(void) { + struct timeval tv = {0, 0}; - gettimeofday(&tv, NULL); + gettimeofday(&tv, NULL); - // Return a time of all 0 if the call fails - return tv; + // Return a time of all 0 if the call fails + return tv; } /** @@ -689,30 +671,28 @@ get_time_timeval(void) { * * Note its starting time is unspecified. */ -static inline struct timespec -get_time_timespec(void) { - struct timespec tm = { 0, 0 }; +static inline struct timespec get_time_timespec(void) { + struct timespec tm = {0, 0}; - clock_gettime(CLOCK_MONOTONIC, &tm); + clock_gettime(CLOCK_MONOTONIC, &tm); - // Return a time of all 0 if the call fails - return tm; + // Return a time of all 0 if the call fails + return tm; } - /** * Print time passed since program starts execution. * * Used for debugging. */ -static inline void -print_timestamp(session_t *ps) { - struct timeval tm, diff; +static inline void print_timestamp(session_t *ps) { + struct timeval tm, diff; - if (gettimeofday(&tm, NULL)) return; + if (gettimeofday(&tm, NULL)) + return; - timeval_subtract(&diff, &tm, &ps->time_start); - fprintf(stderr, "[ %5ld.%06ld ] ", diff.tv_sec, diff.tv_usec); + timeval_subtract(&diff, &tm, &ps->time_start); + fprintf(stderr, "[ %5ld.%06ld ] ", diff.tv_sec, diff.tv_usec); } /** @@ -720,63 +700,56 @@ print_timestamp(session_t *ps) { * * Because a NULL pointer cannot be passed to XFree(), its man page says. */ -static inline void -cxfree(void *data) { - if (data) - XFree(data); +static inline void cxfree(void *data) { + if (data) + XFree(data); } -_Noreturn static inline void -die(const char *msg) { - puts(msg); - exit(1); +_Noreturn static inline void die(const char *msg) { + puts(msg); + exit(1); } /** * Wrapper of XInternAtom() for convenience. */ -static inline xcb_atom_t -get_atom(session_t *ps, const char *atom_name) { - xcb_intern_atom_reply_t *reply = - xcb_intern_atom_reply(ps->c, - xcb_intern_atom(ps->c, 0, strlen(atom_name), atom_name), - NULL); +static inline xcb_atom_t get_atom(session_t *ps, const char *atom_name) { + xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply( + ps->c, xcb_intern_atom(ps->c, 0, strlen(atom_name), atom_name), NULL); - xcb_atom_t atom = XCB_NONE; - if (reply) { - log_debug("Atom %s is %d", atom_name, reply->atom); - atom = reply->atom; - free(reply); - } else - die("Failed to intern atoms, bail out"); - return atom; + xcb_atom_t atom = XCB_NONE; + if (reply) { + log_debug("Atom %s is %d", atom_name, reply->atom); + atom = reply->atom; + free(reply); + } else + die("Failed to intern atoms, bail out"); + return atom; } /** * Return the painting target window. */ -static inline xcb_window_t -get_tgt_window(session_t *ps) { - return ps->overlay != XCB_NONE ? ps->overlay: ps->root; +static inline xcb_window_t get_tgt_window(session_t *ps) { + return ps->overlay != XCB_NONE ? ps->overlay : ps->root; } /** * Find a window from window id in window linked list of the session. */ -static inline win * -find_win(session_t *ps, xcb_window_t id) { - if (!id) - return NULL; +static inline win *find_win(session_t *ps, xcb_window_t id) { + if (!id) + return NULL; - win *w; + win *w; - for (w = ps->list; w; w = w->next) { - if (w->id == id && w->state != WSTATE_DESTROYING) { - return w; - } - } + for (w = ps->list; w; w = w->next) { + if (w->id == id && w->state != WSTATE_DESTROYING) { + return w; + } + } - return 0; + return 0; } /** @@ -785,35 +758,31 @@ find_win(session_t *ps, xcb_window_t id) { * @param id window ID * @return struct win object of the found window, NULL if not found */ -static inline win * -find_toplevel(session_t *ps, xcb_window_t id) { - if (!id) - return NULL; +static inline win *find_toplevel(session_t *ps, xcb_window_t id) { + if (!id) + return NULL; - for (win *w = ps->list; w; w = w->next) { - if (w->client_win == id && w->state != WSTATE_DESTROYING) { - return w; - } - } + for (win *w = ps->list; w; w = w->next) { + if (w->client_win == id && w->state != WSTATE_DESTROYING) { + return w; + } + } - return NULL; + return NULL; } /** * Check if current backend uses GLX. */ -static inline bool -bkend_use_glx(session_t *ps) { - return BKEND_GLX == ps->o.backend - || BKEND_XR_GLX_HYBRID == ps->o.backend; +static inline bool bkend_use_glx(session_t *ps) { + return BKEND_GLX == ps->o.backend || BKEND_XR_GLX_HYBRID == ps->o.backend; } /** * Check if a window is really focused. */ -static inline bool -win_is_focused_real(session_t *ps, const win *w) { - return w->a.map_state == XCB_MAP_STATE_VIEWABLE && ps->active_win == w; +static inline bool win_is_focused_real(session_t *ps, const win *w) { + return w->a.map_state == XCB_MAP_STATE_VIEWABLE && ps->active_win == w; } /** @@ -821,45 +790,41 @@ win_is_focused_real(session_t *ps, const win *w) { * * @return struct win object of the found window, NULL if not found */ -static inline win * -find_focused(session_t *ps) { - if (!ps->o.track_focus) return NULL; +static inline win *find_focused(session_t *ps) { + if (!ps->o.track_focus) + return NULL; - if (ps->active_win && win_is_focused_real(ps, ps->active_win)) - return ps->active_win; - return NULL; + if (ps->active_win && win_is_focused_real(ps, ps->active_win)) + return ps->active_win; + return NULL; } /** * Check if a rectangle includes the whole screen. */ -static inline bool -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); +static inline bool 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); } -static void -set_ignore(session_t *ps, unsigned long sequence) { - if (ps->o.show_all_xerrors) - return; +static void set_ignore(session_t *ps, unsigned long sequence) { + if (ps->o.show_all_xerrors) + return; - auto i = cmalloc(ignore_t); - if (!i) return; + auto i = cmalloc(ignore_t); + if (!i) + return; - i->sequence = sequence; - i->next = 0; - *ps->ignore_tail = i; - ps->ignore_tail = &i->next; + i->sequence = sequence; + i->next = 0; + *ps->ignore_tail = i; + ps->ignore_tail = &i->next; } /** * Ignore X errors caused by given X request. */ -static inline void -set_ignore_cookie(session_t *ps, xcb_void_cookie_t cookie) { - set_ignore(ps, cookie.sequence); +static inline void set_ignore_cookie(session_t *ps, xcb_void_cookie_t cookie) { + set_ignore(ps, cookie.sequence); } /** @@ -867,18 +832,16 @@ set_ignore_cookie(session_t *ps, xcb_void_cookie_t cookie) { * * It's not using w->border_size for performance measures. */ -static inline bool -win_is_fullscreen(session_t *ps, const win *w) { - return rect_is_fullscreen(ps, w->g.x, w->g.y, w->widthb, w->heightb) - && (!w->bounding_shaped || w->rounded_corners); +static inline bool win_is_fullscreen(session_t *ps, const win *w) { + return rect_is_fullscreen(ps, w->g.x, w->g.y, w->widthb, w->heightb) && + (!w->bounding_shaped || w->rounded_corners); } /** * Check if a window will be painted solid. */ -static inline bool -win_is_solid(session_t *ps, const win *w) { - return WMODE_SOLID == w->mode && !ps->o.force_win_blend; +static inline bool win_is_solid(session_t *ps, const win *w) { + return WMODE_SOLID == w->mode && !ps->o.force_win_blend; } /** @@ -889,55 +852,46 @@ win_is_solid(session_t *ps, const win *w) { * @param atom atom of property to check * @return true if it has the attribute, false otherwise */ -static inline bool -wid_has_prop(const session_t *ps, xcb_window_t w, xcb_atom_t atom) { - auto r = - xcb_get_property_reply(ps->c, - xcb_get_property(ps->c, 0, w, atom, - XCB_GET_PROPERTY_TYPE_ANY, 0, 0), - NULL); - if (!r) { - return false; - } +static inline bool wid_has_prop(const session_t *ps, xcb_window_t w, xcb_atom_t atom) { + auto r = xcb_get_property_reply( + ps->c, xcb_get_property(ps->c, 0, w, atom, XCB_GET_PROPERTY_TYPE_ANY, 0, 0), NULL); + if (!r) { + return false; + } - auto rtype = r->type; - free(r); + auto rtype = r->type; + free(r); - if (rtype != XCB_NONE) { - return true; - } - return false; + if (rtype != XCB_NONE) { + return true; + } + return false; } /** * Get the numeric property value from a win_prop_t. */ -static inline long -winprop_get_int(winprop_t prop) { - long tgt = 0; +static inline long winprop_get_int(winprop_t prop) { + long tgt = 0; - if (!prop.nitems) - return 0; + if (!prop.nitems) + return 0; - switch (prop.format) { - case 8: tgt = *(prop.p8); break; - case 16: tgt = *(prop.p16); break; - case 32: tgt = *(prop.p32); break; - default: assert(0); - break; - } + switch (prop.format) { + case 8: tgt = *(prop.p8); break; + case 16: tgt = *(prop.p16); break; + case 32: tgt = *(prop.p32); break; + default: assert(0); break; + } - return tgt; + return tgt; } -void -force_repaint(session_t *ps); +void force_repaint(session_t *ps); -bool -vsync_init(session_t *ps); +bool vsync_init(session_t *ps); -void -vsync_deinit(session_t *ps); +void vsync_deinit(session_t *ps); /** @name DBus handling */ @@ -946,34 +900,27 @@ vsync_deinit(session_t *ps); /** @name DBus hooks */ ///@{ -void -win_set_shadow_force(session_t *ps, win *w, switch_t val); +void win_set_shadow_force(session_t *ps, win *w, switch_t val); -void -win_set_fade_force(session_t *ps, win *w, switch_t val); +void win_set_fade_force(session_t *ps, win *w, switch_t val); -void -win_set_focused_force(session_t *ps, win *w, switch_t val); +void win_set_focused_force(session_t *ps, win *w, switch_t val); -void -win_set_invert_color_force(session_t *ps, win *w, switch_t val); +void win_set_invert_color_force(session_t *ps, win *w, switch_t val); -void -opts_init_track_focus(session_t *ps); +void opts_init_track_focus(session_t *ps); -void -opts_set_no_fading_openclose(session_t *ps, bool newval); +void opts_set_no_fading_openclose(session_t *ps, bool newval); //!@} #endif /** * Set a bool array of all wintypes to true. */ -static inline void -wintype_arr_enable(bool arr[]) { - wintype_t i; +static inline void wintype_arr_enable(bool arr[]) { + wintype_t i; - for (i = 0; i < NUM_WINTYPES; ++i) { - arr[i] = true; - } + for (i = 0; i < NUM_WINTYPES; ++i) { + arr[i] = true; + } } diff --git a/src/compton.c b/src/compton.c index 90f1e19..6cd1217 100644 --- a/src/compton.c +++ b/src/compton.c @@ -9,129 +9,104 @@ * */ +#include +#include +#include +#include +#include #include +#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include #include -#include "err.h" -#include "kernel.h" #include "common.h" #include "compiler.h" #include "compton.h" +#include "err.h" +#include "kernel.h" #ifdef CONFIG_OPENGL #include "opengl.h" #endif -#include "win.h" -#include "x.h" +#include "backend/backend.h" +#include "c2.h" #include "config.h" #include "diagnostic.h" -#include "render.h" -#include "utils.h" -#include "region.h" -#include "types.h" -#include "c2.h" #include "log.h" -#include "backend/backend.h" +#include "region.h" +#include "render.h" +#include "types.h" +#include "utils.h" +#include "win.h" +#include "x.h" #ifdef CONFIG_DBUS #include "dbus.h" #endif #include "options.h" -#define CASESTRRET(s) case s: return #s +#define CASESTRRET(s) \ + case s: return #s /// Get session_t pointer from a pointer to a member of session_t -#define session_ptr(ptr, member) ({ \ - const __typeof__( ((session_t *)0)->member ) *__mptr = (ptr); \ - (session_t *)((char *)__mptr - offsetof(session_t, member)); \ -}) +#define session_ptr(ptr, member) \ + ({ \ + const __typeof__(((session_t *)0)->member) *__mptr = (ptr); \ + (session_t *)((char *)__mptr - offsetof(session_t, member)); \ + }) -static void -update_refresh_rate(session_t *ps); +static void update_refresh_rate(session_t *ps); -static bool -swopti_init(session_t *ps); +static bool swopti_init(session_t *ps); -static void -cxinerama_upd_scrs(session_t *ps); +static void cxinerama_upd_scrs(session_t *ps); -static void -session_destroy(session_t *ps); +static void session_destroy(session_t *ps); -static void -cxinerama_upd_scrs(session_t *ps); +static void cxinerama_upd_scrs(session_t *ps); -static bool must_use -redir_start(session_t *ps); +static bool must_use redir_start(session_t *ps); -static void -redir_stop(session_t *ps); +static void redir_stop(session_t *ps); -static win * -recheck_focus(session_t *ps); +static win *recheck_focus(session_t *ps); -static void -restack_win(session_t *ps, win *w, xcb_window_t new_above); +static void restack_win(session_t *ps, win *w, xcb_window_t new_above); -static void -update_ewmh_active_win(session_t *ps); +static void update_ewmh_active_win(session_t *ps); -static void -draw_callback(EV_P_ ev_idle *w, int revents); +static void draw_callback(EV_P_ ev_idle *w, int revents); // === Global constants === /// Name strings for window types. -const char * const WINTYPES[NUM_WINTYPES] = { - "unknown", - "desktop", - "dock", - "toolbar", - "menu", - "utility", - "splash", - "dialog", - "normal", - "dropdown_menu", - "popup_menu", - "tooltip", - "notify", - "combo", - "dnd", +const char *const WINTYPES[NUM_WINTYPES] = { + "unknown", "desktop", "dock", "toolbar", "menu", + "utility", "splash", "dialog", "normal", "dropdown_menu", + "popup_menu", "tooltip", "notify", "combo", "dnd", }; /// Names of VSync modes. -const char * const VSYNC_STRS[NUM_VSYNC + 1] = { - "none", // VSYNC_NONE - "drm", // VSYNC_DRM - "opengl", // VSYNC_OPENGL - "opengl-oml", // VSYNC_OPENGL_OML - "opengl-swc", // VSYNC_OPENGL_SWC - "opengl-mswc", // VSYNC_OPENGL_MSWC - NULL -}; +const char *const VSYNC_STRS[NUM_VSYNC + 1] = {"none", // VSYNC_NONE + "drm", // VSYNC_DRM + "opengl", // VSYNC_OPENGL + "opengl-oml", // VSYNC_OPENGL_OML + "opengl-swc", // VSYNC_OPENGL_SWC + "opengl-mswc", // VSYNC_OPENGL_MSWC + NULL}; /// Names of backends. -const char * const BACKEND_STRS[NUM_BKEND + 1] = { - "xrender", // BKEND_XRENDER - "glx", // BKEND_GLX - "xr_glx_hybrid",// BKEND_XR_GLX_HYBRID - NULL -}; +const char *const BACKEND_STRS[NUM_BKEND + 1] = {"xrender", // BKEND_XRENDER + "glx", // BKEND_GLX + "xr_glx_hybrid", // BKEND_XR_GLX_HYBRID + NULL}; // === Global variables === @@ -145,58 +120,57 @@ session_t *ps_g = NULL; * * XXX consider moving to x.c */ -static inline void -free_xinerama_info(session_t *ps) { - if (ps->xinerama_scr_regs) { - for (int i = 0; i < ps->xinerama_nscrs; ++i) - pixman_region32_fini(&ps->xinerama_scr_regs[i]); - free(ps->xinerama_scr_regs); - } - cxfree(ps->xinerama_scrs); - ps->xinerama_scrs = NULL; - ps->xinerama_nscrs = 0; +static inline void free_xinerama_info(session_t *ps) { + if (ps->xinerama_scr_regs) { + for (int i = 0; i < ps->xinerama_nscrs; ++i) + pixman_region32_fini(&ps->xinerama_scr_regs[i]); + free(ps->xinerama_scr_regs); + } + cxfree(ps->xinerama_scrs); + ps->xinerama_scrs = NULL; + ps->xinerama_nscrs = 0; } /** * Get current system clock in milliseconds. */ -static inline uint64_t -get_time_ms(void) { - struct timespec tp; - clock_gettime(CLOCK_MONOTONIC, &tp); - return tp.tv_sec * ((uint64_t)1000ul) + tp.tv_nsec / 1000000; +static inline uint64_t get_time_ms(void) { + struct timespec tp; + clock_gettime(CLOCK_MONOTONIC, &tp); + return tp.tv_sec * ((uint64_t)1000ul) + tp.tv_nsec / 1000000; } // XXX Move to x.c -static void -cxinerama_upd_scrs(session_t *ps) { - // XXX Consider deprecating Xinerama, switch to RandR when necessary - free_xinerama_info(ps); +static void cxinerama_upd_scrs(session_t *ps) { + // XXX Consider deprecating Xinerama, switch to RandR when necessary + free_xinerama_info(ps); - if (!ps->o.xinerama_shadow_crop || !ps->xinerama_exists) return; + if (!ps->o.xinerama_shadow_crop || !ps->xinerama_exists) + return; - xcb_xinerama_is_active_reply_t *active = - xcb_xinerama_is_active_reply(ps->c, - xcb_xinerama_is_active(ps->c), NULL); - if (!active || !active->state) { - free(active); - return; - } - free(active); + xcb_xinerama_is_active_reply_t *active = + xcb_xinerama_is_active_reply(ps->c, xcb_xinerama_is_active(ps->c), NULL); + if (!active || !active->state) { + free(active); + return; + } + free(active); - ps->xinerama_scrs = xcb_xinerama_query_screens_reply(ps->c, - xcb_xinerama_query_screens(ps->c), NULL); - if (!ps->xinerama_scrs) - return; + ps->xinerama_scrs = + xcb_xinerama_query_screens_reply(ps->c, xcb_xinerama_query_screens(ps->c), NULL); + if (!ps->xinerama_scrs) + return; - xcb_xinerama_screen_info_t *scrs = xcb_xinerama_query_screens_screen_info(ps->xinerama_scrs); - ps->xinerama_nscrs = xcb_xinerama_query_screens_screen_info_length(ps->xinerama_scrs); + xcb_xinerama_screen_info_t *scrs = + xcb_xinerama_query_screens_screen_info(ps->xinerama_scrs); + ps->xinerama_nscrs = xcb_xinerama_query_screens_screen_info_length(ps->xinerama_scrs); - ps->xinerama_scr_regs = ccalloc(ps->xinerama_nscrs, region_t); - for (int i = 0; i < ps->xinerama_nscrs; ++i) { - const xcb_xinerama_screen_info_t * const s = &scrs[i]; - pixman_region32_init_rect(&ps->xinerama_scr_regs[i], s->x_org, s->y_org, s->width, s->height); - } + ps->xinerama_scr_regs = ccalloc(ps->xinerama_nscrs, region_t); + for (int i = 0; i < ps->xinerama_nscrs; ++i) { + const xcb_xinerama_screen_info_t *const s = &scrs[i]; + pixman_region32_init_rect(&ps->xinerama_scr_regs[i], s->x_org, s->y_org, + s->width, s->height); + } } /** @@ -204,46 +178,42 @@ cxinerama_upd_scrs(session_t *ps) { * * XXX move to win.c */ -static inline win * -find_win_all(session_t *ps, const xcb_window_t wid) { - if (!wid || PointerRoot == wid || wid == ps->root || wid == ps->overlay) - return NULL; +static inline win *find_win_all(session_t *ps, const xcb_window_t wid) { + if (!wid || PointerRoot == wid || wid == ps->root || wid == ps->overlay) + return NULL; - win *w = find_win(ps, wid); - if (!w) w = find_toplevel(ps, wid); - if (!w) w = find_toplevel2(ps, wid); - return w; + win *w = find_win(ps, wid); + if (!w) + w = find_toplevel(ps, wid); + if (!w) + w = find_toplevel2(ps, wid); + return w; } void queue_redraw(session_t *ps) { - // If --benchmark is used, redraw is always queued - if (!ps->redraw_needed && !ps->o.benchmark) - ev_idle_start(ps->loop, &ps->draw_idle); - ps->redraw_needed = true; + // If --benchmark is used, redraw is always queued + if (!ps->redraw_needed && !ps->o.benchmark) + ev_idle_start(ps->loop, &ps->draw_idle); + ps->redraw_needed = true; } /** * Get a region of the screen size. */ -static inline void -get_screen_region(session_t *ps, region_t *res) { - pixman_box32_t b = { - .x1 = 0, .y1 = 0, - .x2 = ps->root_width, - .y2 = ps->root_height - }; - pixman_region32_fini(res); - pixman_region32_init_rects(res, &b, 1); +static inline void get_screen_region(session_t *ps, region_t *res) { + pixman_box32_t b = {.x1 = 0, .y1 = 0, .x2 = ps->root_width, .y2 = ps->root_height}; + pixman_region32_fini(res); + pixman_region32_init_rects(res, &b, 1); } void add_damage(session_t *ps, const region_t *damage) { - // Ignore damage when screen isn't redirected - if (!ps->redirected) - return; + // Ignore damage when screen isn't redirected + if (!ps->redirected) + return; - if (!damage) - return; - pixman_region32_union(ps->damage, ps->damage, (region_t *)damage); + if (!damage) + return; + pixman_region32_union(ps->damage, ps->damage, (region_t *)damage); } // === Fading === @@ -253,17 +223,16 @@ void add_damage(session_t *ps, const region_t *damage) { * * In milliseconds. */ -static double -fade_timeout(session_t *ps) { - auto now = get_time_ms(); - if (ps->o.fade_delta + ps->fade_time < now) - return 0; +static double fade_timeout(session_t *ps) { + auto now = get_time_ms(); + if (ps->o.fade_delta + ps->fade_time < now) + return 0; - int diff = ps->o.fade_delta + ps->fade_time - now; + int diff = ps->o.fade_delta + ps->fade_time - now; - diff = normalize_i_range(diff, 0, ps->o.fade_delta * 2); + diff = normalize_i_range(diff, 0, ps->o.fade_delta * 2); - return diff / 1000.0; + return diff / 1000.0; } /** @@ -272,68 +241,63 @@ fade_timeout(session_t *ps) { * @param steps steps of fading * @return whether we are still in fading mode */ -static bool -run_fade(session_t *ps, win **_w, unsigned steps) { - win *w = *_w; - if (w->state == WSTATE_MAPPED || w->state == WSTATE_UNMAPPED) { - // We are not fading - assert(w->opacity_tgt == w->opacity); - return false; - } +static bool run_fade(session_t *ps, win **_w, unsigned steps) { + win *w = *_w; + if (w->state == WSTATE_MAPPED || w->state == WSTATE_UNMAPPED) { + // We are not fading + assert(w->opacity_tgt == w->opacity); + return false; + } - if (!win_should_fade(ps, w)) { - log_debug("Window %#010x %s doesn't need fading", w->id, w->name); - w->opacity = w->opacity_tgt; - } - if (w->opacity == w->opacity_tgt) { - // We have reached target opacity, wrapping up. - // Note, we reach here after we have rendered the window with the target - // opacity at least once. If the window is destroyed because it is faded out, - // there is no need to add damage here. - log_debug("Fading finished for window %#010x %s", w->id, w->name); - win_check_fade_finished(ps, _w); - return false; - } + if (!win_should_fade(ps, w)) { + log_debug("Window %#010x %s doesn't need fading", w->id, w->name); + w->opacity = w->opacity_tgt; + } + if (w->opacity == w->opacity_tgt) { + // We have reached target opacity, wrapping up. + // Note, we reach here after we have rendered the window with the target + // opacity at least once. If the window is destroyed because it is faded + // out, there is no need to add damage here. + log_debug("Fading finished for window %#010x %s", w->id, w->name); + win_check_fade_finished(ps, _w); + return false; + } - if (steps) { - if (w->opacity < w->opacity_tgt) { - w->opacity = normalize_d_range( - w->opacity + ps->o.fade_in_step * steps, - 0.0, w->opacity_tgt); - } else { - w->opacity = normalize_d_range( - w->opacity - ps->o.fade_out_step * steps, - w->opacity_tgt, 1); - } - } + if (steps) { + if (w->opacity < w->opacity_tgt) { + w->opacity = normalize_d_range( + w->opacity + ps->o.fade_in_step * steps, 0.0, w->opacity_tgt); + } else { + w->opacity = normalize_d_range( + w->opacity - ps->o.fade_out_step * steps, w->opacity_tgt, 1); + } + } - // Note even if opacity == opacity_tgt, we still want to run preprocess one last - // time to finish state transition. So return true in that case too. - return true; + // Note even if opacity == opacity_tgt, we still want to run preprocess one last + // time to finish state transition. So return true in that case too. + return true; } // === Error handling === -static void -discard_ignore(session_t *ps, unsigned long sequence) { - while (ps->ignore_head) { - if (sequence > ps->ignore_head->sequence) { - ignore_t *next = ps->ignore_head->next; - free(ps->ignore_head); - ps->ignore_head = next; - if (!ps->ignore_head) { - ps->ignore_tail = &ps->ignore_head; - } - } else { - break; - } - } +static void discard_ignore(session_t *ps, unsigned long sequence) { + while (ps->ignore_head) { + if (sequence > ps->ignore_head->sequence) { + ignore_t *next = ps->ignore_head->next; + free(ps->ignore_head); + ps->ignore_head = next; + if (!ps->ignore_head) { + ps->ignore_tail = &ps->ignore_head; + } + } else { + break; + } + } } -static int -should_ignore(session_t *ps, unsigned long sequence) { - discard_ignore(ps, sequence); - return ps->ignore_head && ps->ignore_head->sequence == sequence; +static int should_ignore(session_t *ps, unsigned long sequence) { + discard_ignore(ps, sequence); + return ps->ignore_head && ps->ignore_head->sequence == sequence; } // === Windows === @@ -342,26 +306,26 @@ should_ignore(session_t *ps, unsigned long sequence) { * Determine the event mask for a window. */ long determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode) { - long evmask = 0; - win *w = NULL; + long evmask = 0; + win *w = NULL; - // Check if it's a mapped frame window - if (WIN_EVMODE_FRAME == mode - || ((w = find_win(ps, wid)) && w->a.map_state == XCB_MAP_STATE_VIEWABLE)) { - evmask |= XCB_EVENT_MASK_PROPERTY_CHANGE; - if (ps->o.track_focus && !ps->o.use_ewmh_active_win) - evmask |= XCB_EVENT_MASK_FOCUS_CHANGE; - } + // Check if it's a mapped frame window + if (WIN_EVMODE_FRAME == mode || + ((w = find_win(ps, wid)) && w->a.map_state == XCB_MAP_STATE_VIEWABLE)) { + evmask |= XCB_EVENT_MASK_PROPERTY_CHANGE; + if (ps->o.track_focus && !ps->o.use_ewmh_active_win) + evmask |= XCB_EVENT_MASK_FOCUS_CHANGE; + } - // Check if it's a mapped client window - if (WIN_EVMODE_CLIENT == mode - || ((w = find_toplevel(ps, wid)) && w->a.map_state == XCB_MAP_STATE_VIEWABLE)) { - if (ps->o.frame_opacity || ps->o.track_wdata || ps->track_atom_lst - || ps->o.detect_client_opacity) - evmask |= XCB_EVENT_MASK_PROPERTY_CHANGE; - } + // Check if it's a mapped client window + if (WIN_EVMODE_CLIENT == mode || + ((w = find_toplevel(ps, wid)) && w->a.map_state == XCB_MAP_STATE_VIEWABLE)) { + if (ps->o.frame_opacity || ps->o.track_wdata || ps->track_atom_lst || + ps->o.detect_client_opacity) + evmask |= XCB_EVENT_MASK_PROPERTY_CHANGE; + } - return evmask; + return evmask; } /** @@ -372,28 +336,28 @@ long determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode) { * @return struct _win object of the found window, NULL if not found */ win *find_toplevel2(session_t *ps, xcb_window_t wid) { - // TODO this should probably be an "update tree", then find_toplevel. - // current approach is a bit more "racy" - win *w = NULL; + // TODO this should probably be an "update tree", then find_toplevel. + // current approach is a bit more "racy" + win *w = NULL; - // We traverse through its ancestors to find out the frame - while (wid && wid != ps->root && !(w = find_win(ps, wid))) { - xcb_query_tree_reply_t *reply; + // We traverse through its ancestors to find out the frame + while (wid && wid != ps->root && !(w = find_win(ps, wid))) { + xcb_query_tree_reply_t *reply; - // xcb_query_tree probably fails if you run compton when X is somehow - // initializing (like add it in .xinitrc). In this case - // just leave it alone. - reply = xcb_query_tree_reply(ps->c, xcb_query_tree(ps->c, wid), NULL); - if (reply == NULL) { - break; - } + // xcb_query_tree probably fails if you run compton when X is somehow + // initializing (like add it in .xinitrc). In this case + // just leave it alone. + reply = xcb_query_tree_reply(ps->c, xcb_query_tree(ps->c, wid), NULL); + if (reply == NULL) { + break; + } - wid = reply->parent; + wid = reply->parent; - free(reply); - } + free(reply); + } - return w; + return w; } /** @@ -403,266 +367,262 @@ win *find_toplevel2(session_t *ps, xcb_window_t wid) { * @param ps current session * @return struct _win of currently focused window, NULL if not found */ -static win * -recheck_focus(session_t *ps) { - // Use EWMH _NET_ACTIVE_WINDOW if enabled - if (ps->o.use_ewmh_active_win) { - update_ewmh_active_win(ps); - return ps->active_win; - } +static win *recheck_focus(session_t *ps) { + // Use EWMH _NET_ACTIVE_WINDOW if enabled + if (ps->o.use_ewmh_active_win) { + update_ewmh_active_win(ps); + return ps->active_win; + } - // Determine the currently focused window so we can apply appropriate - // opacity on it - xcb_window_t wid = XCB_NONE; - xcb_get_input_focus_reply_t *reply = - xcb_get_input_focus_reply(ps->c, xcb_get_input_focus(ps->c), NULL); + // Determine the currently focused window so we can apply appropriate + // opacity on it + xcb_window_t wid = XCB_NONE; + xcb_get_input_focus_reply_t *reply = + xcb_get_input_focus_reply(ps->c, xcb_get_input_focus(ps->c), NULL); - if (reply) { - wid = reply->focus; - free(reply); - } + if (reply) { + wid = reply->focus; + free(reply); + } - win *w = find_win_all(ps, wid); + win *w = find_win_all(ps, wid); - log_trace("%#010" PRIx32 " (%#010lx \"%s\") focused.", wid, - (w ? w->id: XCB_NONE), (w ? w->name: NULL)); + log_trace("%#010" PRIx32 " (%#010lx \"%s\") focused.", wid, + (w ? w->id : XCB_NONE), (w ? w->name : NULL)); - // And we set the focus state here - if (w) { - win_set_focused(ps, w, true); - return w; - } + // And we set the focus state here + if (w) { + win_set_focused(ps, w, true); + return w; + } - return NULL; + return NULL; } /** * Look for the client window of a particular window. */ -xcb_window_t -find_client_win(session_t *ps, xcb_window_t w) { - if (wid_has_prop(ps, w, ps->atom_client)) { - return w; - } +xcb_window_t find_client_win(session_t *ps, xcb_window_t w) { + if (wid_has_prop(ps, w, ps->atom_client)) { + return w; + } - xcb_query_tree_reply_t *reply = xcb_query_tree_reply(ps->c, - xcb_query_tree(ps->c, w), NULL); - if (!reply) - return 0; + xcb_query_tree_reply_t *reply = + xcb_query_tree_reply(ps->c, xcb_query_tree(ps->c, w), NULL); + if (!reply) + return 0; - xcb_window_t *children = xcb_query_tree_children(reply); - int nchildren = xcb_query_tree_children_length(reply); - int i; - xcb_window_t ret = 0; + xcb_window_t *children = xcb_query_tree_children(reply); + int nchildren = xcb_query_tree_children_length(reply); + int i; + xcb_window_t ret = 0; - for (i = 0; i < nchildren; ++i) { - if ((ret = find_client_win(ps, children[i]))) - break; - } + for (i = 0; i < nchildren; ++i) { + if ((ret = find_client_win(ps, children[i]))) + break; + } - free(reply); + free(reply); - return ret; + return ret; } -static win * -paint_preprocess(session_t *ps, bool *fade_running) { - // XXX need better, more general name for `fade_running`. It really - // means if fade is still ongoing after the current frame is rendered - win *t = NULL, *next = NULL; - *fade_running = false; +static win *paint_preprocess(session_t *ps, bool *fade_running) { + // XXX need better, more general name for `fade_running`. It really + // means if fade is still ongoing after the current frame is rendered + win *t = NULL, *next = NULL; + *fade_running = false; - // Fading step calculation - unsigned long steps = 0L; - auto now = get_time_ms(); - if (ps->fade_time) { - assert(now >= ps->fade_time); - steps = (now - ps->fade_time) / ps->o.fade_delta; - } else { - // Reset fade_time if unset - ps->fade_time = get_time_ms(); - steps = 0L; - } - ps->fade_time += steps * ps->o.fade_delta; + // Fading step calculation + unsigned long steps = 0L; + auto now = get_time_ms(); + if (ps->fade_time) { + assert(now >= ps->fade_time); + steps = (now - ps->fade_time) / ps->o.fade_delta; + } else { + // Reset fade_time if unset + ps->fade_time = get_time_ms(); + steps = 0L; + } + ps->fade_time += steps * ps->o.fade_delta; - // First, let's process fading - for (win *w = ps->list; w; w = next) { - next = w->next; - const winmode_t mode_old = w->mode; - const bool was_painted = w->to_paint; - const opacity_t opacity_old = w->opacity; + // First, let's process fading + for (win *w = ps->list; w; w = next) { + next = w->next; + const winmode_t mode_old = w->mode; + const bool was_painted = w->to_paint; + const opacity_t opacity_old = w->opacity; - if (win_should_dim(ps, w) != w->dim) { - w->dim = win_should_dim(ps, w); - add_damage_from_win(ps, w); - } + if (win_should_dim(ps, w) != w->dim) { + w->dim = win_should_dim(ps, w); + add_damage_from_win(ps, w); + } - // Run fading - if (run_fade(ps, &w, steps)) { - *fade_running = true; - } + // Run fading + if (run_fade(ps, &w, steps)) { + *fade_running = true; + } - if (!w) { - // the window might have been destroyed because fading finished - continue; - } + if (!w) { + // the window might have been destroyed because fading finished + continue; + } - if (win_has_frame(w)) { - w->frame_opacity = ps->o.frame_opacity; - } else { - w->frame_opacity = 1.0; - } + if (win_has_frame(w)) { + w->frame_opacity = ps->o.frame_opacity; + } else { + w->frame_opacity = 1.0; + } - // Update window mode - w->mode = win_calc_mode(w); + // Update window mode + w->mode = win_calc_mode(w); - // Destroy all reg_ignore above when frame opaque state changes on - // SOLID mode - if (was_painted && w->mode != mode_old) { - w->reg_ignore_valid = false; - } + // Destroy all reg_ignore above when frame opaque state changes on + // SOLID mode + if (was_painted && w->mode != mode_old) { + w->reg_ignore_valid = false; + } - // Add window to damaged area if its opacity changes - // If was_painted == false, and to_paint is also false, we don't care - // If was_painted == false, but to_paint is true, damage will be added in the loop below - if (was_painted && w->opacity != opacity_old) { - add_damage_from_win(ps, w); - } - } + // Add window to damaged area if its opacity changes + // If was_painted == false, and to_paint is also false, we don't care + // If was_painted == false, but to_paint is true, damage will be added in + // the loop below + if (was_painted && w->opacity != opacity_old) { + add_damage_from_win(ps, w); + } + } - // Opacity will not change, from now on. - rc_region_t *last_reg_ignore = rc_region_new(); + // Opacity will not change, from now on. + rc_region_t *last_reg_ignore = rc_region_new(); - bool unredir_possible = false; - // Trace whether it's the highest window to paint - bool is_highest = true; - bool reg_ignore_valid = true; - for (win *w = ps->list; w; w = next) { - __label__ skip_window; - bool to_paint = true; - // w->to_paint remembers whether this window is painted last time - const bool was_painted = w->to_paint; + bool unredir_possible = false; + // Trace whether it's the highest window to paint + bool is_highest = true; + bool reg_ignore_valid = true; + for (win *w = ps->list; w; w = next) { + __label__ skip_window; + bool to_paint = true; + // w->to_paint remembers whether this window is painted last time + const bool was_painted = w->to_paint; - // In case calling the fade callback function destroys this window - next = w->next; + // In case calling the fade callback function destroys this window + next = w->next; - // Destroy reg_ignore if some window above us invalidated it - if (!reg_ignore_valid) - rc_region_unref(&w->reg_ignore); + // Destroy reg_ignore if some window above us invalidated it + if (!reg_ignore_valid) + rc_region_unref(&w->reg_ignore); - //log_trace("%d %d %s", w->a.map_state, w->ever_damaged, w->name); + // log_trace("%d %d %s", w->a.map_state, w->ever_damaged, w->name); - // Give up if it's not damaged or invisible, or it's unmapped and its - // pixmap is gone (for example due to a ConfigureNotify), or when it's - // excluded - if (!w->ever_damaged - || w->g.x + w->g.width < 1 || w->g.y + w->g.height < 1 - || w->g.x >= ps->root_width || w->g.y >= ps->root_height - || w->state == WSTATE_UNMAPPED - || (double) w->opacity * MAX_ALPHA < 1 - || w->paint_excluded) - to_paint = false; - //log_trace("%s %d %d %d", w->name, to_paint, w->opacity, w->paint_excluded); + // Give up if it's not damaged or invisible, or it's unmapped and its + // pixmap is gone (for example due to a ConfigureNotify), or when it's + // excluded + if (!w->ever_damaged || w->g.x + w->g.width < 1 || + w->g.y + w->g.height < 1 || w->g.x >= ps->root_width || + w->g.y >= ps->root_height || w->state == WSTATE_UNMAPPED || + (double)w->opacity * MAX_ALPHA < 1 || w->paint_excluded) + to_paint = false; + // log_trace("%s %d %d %d", w->name, to_paint, w->opacity, + // w->paint_excluded); - // Add window to damaged area if its painting status changes - // or opacity changes - if (to_paint != was_painted) { - w->reg_ignore_valid = false; - add_damage_from_win(ps, w); - } + // Add window to damaged area if its painting status changes + // or opacity changes + if (to_paint != was_painted) { + w->reg_ignore_valid = false; + add_damage_from_win(ps, w); + } - // to_paint will never change afterward - if (!to_paint) - goto skip_window; + // to_paint will never change afterward + if (!to_paint) + goto skip_window; - // Calculate shadow opacity - w->shadow_opacity = ps->o.shadow_opacity * w->opacity * ps->o.frame_opacity; + // Calculate shadow opacity + w->shadow_opacity = ps->o.shadow_opacity * w->opacity * ps->o.frame_opacity; - // Generate ignore region for painting to reduce GPU load - if (!w->reg_ignore) - w->reg_ignore = rc_region_ref(last_reg_ignore); + // Generate ignore region for painting to reduce GPU load + if (!w->reg_ignore) + w->reg_ignore = rc_region_ref(last_reg_ignore); - // If the window is solid, we add the window region to the - // ignored region - // Otherwise last_reg_ignore shouldn't change - if (w->mode == WMODE_SOLID && !ps->o.force_win_blend) { - region_t *tmp = rc_region_new(); - if (w->frame_opacity == 1) - *tmp = win_get_bounding_shape_global_by_val(w); - else { - win_get_region_noframe_local(w, tmp); - pixman_region32_intersect(tmp, tmp, &w->bounding_shape); - pixman_region32_translate(tmp, w->g.x, w->g.y); - } + // If the window is solid, we add the window region to the + // ignored region + // Otherwise last_reg_ignore shouldn't change + if (w->mode == WMODE_SOLID && !ps->o.force_win_blend) { + region_t *tmp = rc_region_new(); + if (w->frame_opacity == 1) + *tmp = win_get_bounding_shape_global_by_val(w); + else { + win_get_region_noframe_local(w, tmp); + pixman_region32_intersect(tmp, tmp, &w->bounding_shape); + pixman_region32_translate(tmp, w->g.x, w->g.y); + } - pixman_region32_union(tmp, tmp, last_reg_ignore); - rc_region_unref(&last_reg_ignore); - last_reg_ignore = tmp; - } + pixman_region32_union(tmp, tmp, last_reg_ignore); + rc_region_unref(&last_reg_ignore); + last_reg_ignore = tmp; + } - // (Un)redirect screen - // We could definitely unredirect the screen when there's no window to - // paint, but this is typically unnecessary, may cause flickering when - // fading is enabled, and could create inconsistency when the wallpaper - // is not correctly set. - if (ps->o.unredir_if_possible && is_highest) { - if (win_is_solid(ps, w) - && (w->frame_opacity == 1 || !win_has_frame(w)) - && win_is_fullscreen(ps, w) - && !w->unredir_if_possible_excluded) - unredir_possible = true; - } + // (Un)redirect screen + // We could definitely unredirect the screen when there's no window to + // paint, but this is typically unnecessary, may cause flickering when + // fading is enabled, and could create inconsistency when the wallpaper + // is not correctly set. + if (ps->o.unredir_if_possible && is_highest) { + if (win_is_solid(ps, w) && + (w->frame_opacity == 1 || !win_has_frame(w)) && + win_is_fullscreen(ps, w) && !w->unredir_if_possible_excluded) + unredir_possible = true; + } - // Reset flags - w->flags = 0; - w->prev_trans = t; - t = w; + // Reset flags + w->flags = 0; + w->prev_trans = t; + t = w; - // If the screen is not redirected and the window has redir_ignore set, - // this window should not cause the screen to become redirected - if (!(ps->o.wintype_option[w->window_type].redir_ignore && !ps->redirected)) { - is_highest = false; - } + // If the screen is not redirected and the window has redir_ignore set, + // this window should not cause the screen to become redirected + if (!(ps->o.wintype_option[w->window_type].redir_ignore && !ps->redirected)) { + is_highest = false; + } - skip_window: - reg_ignore_valid = reg_ignore_valid && w->reg_ignore_valid; - w->reg_ignore_valid = true; + skip_window: + reg_ignore_valid = reg_ignore_valid && w->reg_ignore_valid; + w->reg_ignore_valid = true; - win_check_fade_finished(ps, &w); + win_check_fade_finished(ps, &w); - // Avoid setting w->to_paint if w is freed - if (w) { - w->to_paint = to_paint; - } - } + // Avoid setting w->to_paint if w is freed + if (w) { + w->to_paint = to_paint; + } + } - rc_region_unref(&last_reg_ignore); + rc_region_unref(&last_reg_ignore); - // If possible, unredirect all windows and stop painting - if (ps->o.redirected_force != UNSET) - unredir_possible = !ps->o.redirected_force; - else if (ps->o.unredir_if_possible && is_highest && !ps->redirected) - // If there's no window to paint, and the screen isn't redirected, - // don't redirect it. - unredir_possible = true; - if (unredir_possible) { - if (ps->redirected) { - if (!ps->o.unredir_if_possible_delay || ps->tmout_unredir_hit) - redir_stop(ps); - else if (!ev_is_active(&ps->unredir_timer)) { - ev_timer_set(&ps->unredir_timer, - ps->o.unredir_if_possible_delay / 1000.0, 0); - ev_timer_start(ps->loop, &ps->unredir_timer); - } - } - } else { - ev_timer_stop(ps->loop, &ps->unredir_timer); - if (!redir_start(ps)) { - return NULL; - } - } + // If possible, unredirect all windows and stop painting + if (ps->o.redirected_force != UNSET) + unredir_possible = !ps->o.redirected_force; + else if (ps->o.unredir_if_possible && is_highest && !ps->redirected) + // If there's no window to paint, and the screen isn't redirected, + // don't redirect it. + unredir_possible = true; + if (unredir_possible) { + if (ps->redirected) { + if (!ps->o.unredir_if_possible_delay || ps->tmout_unredir_hit) + redir_stop(ps); + else if (!ev_is_active(&ps->unredir_timer)) { + ev_timer_set(&ps->unredir_timer, + ps->o.unredir_if_possible_delay / 1000.0, 0); + ev_timer_start(ps->loop, &ps->unredir_timer); + } + } + } else { + ev_timer_stop(ps->loop, &ps->unredir_timer); + if (!redir_start(ps)) { + return NULL; + } + } - return t; + return t; } /* @@ -682,317 +642,305 @@ xr_take_screenshot(session_t *ps) { /** * Rebuild cached screen_reg. */ -static void -rebuild_screen_reg(session_t *ps) { - get_screen_region(ps, &ps->screen_reg); +static void rebuild_screen_reg(session_t *ps) { + get_screen_region(ps, &ps->screen_reg); } /** * Rebuild shadow_exclude_reg. */ -static void -rebuild_shadow_exclude_reg(session_t *ps) { - bool ret = parse_geometry(ps, ps->o.shadow_exclude_reg_str, - &ps->shadow_exclude_reg); - if (!ret) - exit(1); +static void rebuild_shadow_exclude_reg(session_t *ps) { + bool ret = parse_geometry(ps, ps->o.shadow_exclude_reg_str, &ps->shadow_exclude_reg); + if (!ret) + exit(1); } -static void -repair_win(session_t *ps, win *w) { - if (w->a.map_state != XCB_MAP_STATE_VIEWABLE) - return; +static void repair_win(session_t *ps, win *w) { + if (w->a.map_state != XCB_MAP_STATE_VIEWABLE) + return; - region_t parts; - pixman_region32_init(&parts); + region_t parts; + pixman_region32_init(&parts); - if (!w->ever_damaged) { - win_extents(w, &parts); - set_ignore_cookie(ps, - xcb_damage_subtract(ps->c, w->damage, XCB_NONE, XCB_NONE)); - } else { - xcb_xfixes_region_t tmp = xcb_generate_id(ps->c); - xcb_xfixes_create_region(ps->c, tmp, 0, NULL); - set_ignore_cookie(ps, - xcb_damage_subtract(ps->c, w->damage, XCB_NONE, tmp)); - xcb_xfixes_translate_region(ps->c, tmp, - w->g.x + w->g.border_width, - w->g.y + w->g.border_width); - x_fetch_region(ps->c, tmp, &parts); - xcb_xfixes_destroy_region(ps->c, tmp); - } + if (!w->ever_damaged) { + win_extents(w, &parts); + set_ignore_cookie( + ps, xcb_damage_subtract(ps->c, w->damage, XCB_NONE, XCB_NONE)); + } else { + xcb_xfixes_region_t tmp = xcb_generate_id(ps->c); + xcb_xfixes_create_region(ps->c, tmp, 0, NULL); + set_ignore_cookie(ps, xcb_damage_subtract(ps->c, w->damage, XCB_NONE, tmp)); + xcb_xfixes_translate_region(ps->c, tmp, w->g.x + w->g.border_width, + w->g.y + w->g.border_width); + x_fetch_region(ps->c, tmp, &parts); + xcb_xfixes_destroy_region(ps->c, tmp); + } - w->ever_damaged = true; - w->pixmap_damaged = true; + w->ever_damaged = true; + w->pixmap_damaged = true; - // Why care about damage when screen is unredirected? - // We will force full-screen repaint on redirection. - if (!ps->redirected) { - pixman_region32_fini(&parts); - return; - } + // Why care about damage when screen is unredirected? + // We will force full-screen repaint on redirection. + if (!ps->redirected) { + pixman_region32_fini(&parts); + return; + } - // Remove the part in the damage area that could be ignored - if (w->reg_ignore && win_is_region_ignore_valid(ps, w)) - pixman_region32_subtract(&parts, &parts, w->reg_ignore); + // Remove the part in the damage area that could be ignored + if (w->reg_ignore && win_is_region_ignore_valid(ps, w)) + pixman_region32_subtract(&parts, &parts, w->reg_ignore); - add_damage(ps, &parts); - pixman_region32_fini(&parts); + add_damage(ps, &parts); + pixman_region32_fini(&parts); } -static void -restack_win(session_t *ps, win *w, xcb_window_t new_above) { - xcb_window_t old_above; +static void restack_win(session_t *ps, win *w, xcb_window_t new_above) { + xcb_window_t old_above; - if (w->next) { - old_above = w->next->id; - } else { - old_above = XCB_NONE; - } - log_debug("Restack %#010x (%s), old_above: %#010x, new_above: %#010x", - w->id, w->name, old_above, new_above); + if (w->next) { + old_above = w->next->id; + } else { + old_above = XCB_NONE; + } + log_debug("Restack %#010x (%s), old_above: %#010x, new_above: %#010x", w->id, + w->name, old_above, new_above); - if (old_above != new_above) { - w->reg_ignore_valid = false; - rc_region_unref(&w->reg_ignore); - if (w->next) { - w->next->reg_ignore_valid = false; - rc_region_unref(&w->next->reg_ignore); - } + if (old_above != new_above) { + w->reg_ignore_valid = false; + rc_region_unref(&w->reg_ignore); + if (w->next) { + w->next->reg_ignore_valid = false; + rc_region_unref(&w->next->reg_ignore); + } - win **prev = NULL, **prev_old = NULL; + win **prev = NULL, **prev_old = NULL; - bool found = false; - for (prev = &ps->list; *prev; prev = &(*prev)->next) { - if ((*prev)->id == new_above && (*prev)->state != WSTATE_DESTROYING) { - found = true; - break; - } - } + bool found = false; + for (prev = &ps->list; *prev; prev = &(*prev)->next) { + if ((*prev)->id == new_above && (*prev)->state != WSTATE_DESTROYING) { + found = true; + break; + } + } - if (new_above && !found) { - log_error("(%#010x, %#010x): Failed to found new above window.", w->id, new_above); - return; - } + if (new_above && !found) { + log_error("(%#010x, %#010x): Failed to found new above window.", + w->id, new_above); + return; + } - for (prev_old = &ps->list; *prev_old; prev_old = &(*prev_old)->next) { - if ((*prev_old) == w) { - break; - } - } + for (prev_old = &ps->list; *prev_old; prev_old = &(*prev_old)->next) { + if ((*prev_old) == w) { + break; + } + } - *prev_old = w->next; - w->next = *prev; - *prev = w; + *prev_old = w->next; + w->next = *prev; + *prev = w; - // add damage for this window - add_damage_from_win(ps, w); + // add damage for this window + add_damage_from_win(ps, w); #ifdef DEBUG_RESTACK - log_trace("Window stack modified. Current stack:"); - for (win *c = ps->list; c; c = c->next) { - const char *desc = ""; - if (c->state == WSTATE_DESTROYING) { - desc = "(D) "; - } - log_trace("%#010x \"%s\" %s", c->id, c->name, desc); - } + log_trace("Window stack modified. Current stack:"); + for (win *c = ps->list; c; c = c->next) { + const char *desc = ""; + if (c->state == WSTATE_DESTROYING) { + desc = "(D) "; + } + log_trace("%#010x \"%s\" %s", c->id, c->name, desc); + } #endif - } + } } /// Handle configure event of a root window void configure_root(session_t *ps, int width, int height) { - // On root window changes - bool has_root_change = false; - if (ps->o.experimental_backends) { - has_root_change = ps->backend_data->ops->root_change != NULL; - if (!has_root_change) { - // deinit/reinit backend if the backend cannot handle root change - ps->backend_data->ops->deinit(ps->backend_data); - ps->backend_data = NULL; - } - } else { - free_paint(ps, &ps->tgt_buffer); - } + // On root window changes + bool has_root_change = false; + if (ps->o.experimental_backends) { + has_root_change = ps->backend_data->ops->root_change != NULL; + if (!has_root_change) { + // deinit/reinit backend if the backend cannot handle root change + ps->backend_data->ops->deinit(ps->backend_data); + ps->backend_data = NULL; + } + } else { + free_paint(ps, &ps->tgt_buffer); + } - ps->root_width = width; - ps->root_height = height; + ps->root_width = width; + ps->root_height = height; - rebuild_screen_reg(ps); - rebuild_shadow_exclude_reg(ps); - for (int i = 0; i < ps->ndamage; i++) { - pixman_region32_clear(&ps->damage_ring[i]); - } - ps->damage = ps->damage_ring + ps->ndamage - 1; + rebuild_screen_reg(ps); + rebuild_shadow_exclude_reg(ps); + for (int i = 0; i < ps->ndamage; i++) { + pixman_region32_clear(&ps->damage_ring[i]); + } + ps->damage = ps->damage_ring + ps->ndamage - 1; - // Invalidate reg_ignore from the top - rc_region_unref(&ps->list->reg_ignore); - ps->list->reg_ignore_valid = false; + // Invalidate reg_ignore from the top + rc_region_unref(&ps->list->reg_ignore); + ps->list->reg_ignore_valid = false; #ifdef CONFIG_OPENGL - // GLX root change callback - if (BKEND_GLX == ps->o.backend) - glx_on_root_change(ps); + // GLX root change callback + if (BKEND_GLX == ps->o.backend) + glx_on_root_change(ps); #endif - if (ps->o.experimental_backends) { - if (has_root_change) { - ps->backend_data->ops->root_change(ps->backend_data, ps); - } else { - ps->backend_data = backend_list[ps->o.backend]->init(ps); - ps->backend_data->ops = backend_list[ps->o.backend]; - if (!ps->backend_data) { - log_fatal("Failed to re-initialize backend after root change, aborting..."); - ps->quit = true; - // TODO only event handlers should request ev_break, otherwise it's too hard to - // keep track of what can break the event loop - ev_break(ps->loop, EVBREAK_ALL); - return; - } - } - } - force_repaint(ps); - return; + if (ps->o.experimental_backends) { + if (has_root_change) { + ps->backend_data->ops->root_change(ps->backend_data, ps); + } else { + ps->backend_data = backend_list[ps->o.backend]->init(ps); + ps->backend_data->ops = backend_list[ps->o.backend]; + if (!ps->backend_data) { + log_fatal("Failed to re-initialize backend after root " + "change, aborting..."); + ps->quit = true; + // TODO only event handlers should request ev_break, + // otherwise it's too hard to keep track of what can break + // the event loop + ev_break(ps->loop, EVBREAK_ALL); + return; + } + } + } + force_repaint(ps); + return; } /// Handle configure event of a regular window -void -configure_win(session_t *ps, xcb_configure_notify_event_t *ce) { - win *w = find_win(ps, ce->window); - region_t damage; - pixman_region32_init(&damage); +void configure_win(session_t *ps, xcb_configure_notify_event_t *ce) { + win *w = find_win(ps, ce->window); + region_t damage; + pixman_region32_init(&damage); - if (!w) { - return; - } + if (!w) { + return; + } - if (w->state == WSTATE_UNMAPPED || - w->state == WSTATE_UNMAPPING || - w->state == WSTATE_DESTROYING) { - /* save the configure event for when the window maps */ - w->need_configure = true; - w->queue_configure = *ce; - restack_win(ps, w, ce->above_sibling); - } else { - if (!w->need_configure) { - restack_win(ps, w, ce->above_sibling); - } + if (w->state == WSTATE_UNMAPPED || w->state == WSTATE_UNMAPPING || + w->state == WSTATE_DESTROYING) { + /* save the configure event for when the window maps */ + w->need_configure = true; + w->queue_configure = *ce; + restack_win(ps, w, ce->above_sibling); + } else { + if (!w->need_configure) { + restack_win(ps, w, ce->above_sibling); + } - bool factor_change = false; - w->need_configure = false; - win_extents(w, &damage); + bool factor_change = false; + w->need_configure = false; + win_extents(w, &damage); - // If window geometry change, free old extents - if (w->g.x != ce->x || w->g.y != ce->y - || w->g.width != ce->width || w->g.height != ce->height - || w->g.border_width != ce->border_width) - factor_change = true; + // If window geometry change, free old extents + if (w->g.x != ce->x || w->g.y != ce->y || w->g.width != ce->width || + w->g.height != ce->height || w->g.border_width != ce->border_width) + factor_change = true; - w->g.x = ce->x; - w->g.y = ce->y; + w->g.x = ce->x; + w->g.y = ce->y; - if (w->g.width != ce->width || w->g.height != ce->height - || w->g.border_width != ce->border_width) { - w->g.width = ce->width; - w->g.height = ce->height; - w->g.border_width = ce->border_width; - win_on_win_size_change(ps, w); - win_update_bounding_shape(ps, w); - } + if (w->g.width != ce->width || w->g.height != ce->height || + w->g.border_width != ce->border_width) { + w->g.width = ce->width; + w->g.height = ce->height; + w->g.border_width = ce->border_width; + win_on_win_size_change(ps, w); + win_update_bounding_shape(ps, w); + } - region_t new_extents; - pixman_region32_init(&new_extents); - win_extents(w, &new_extents); - pixman_region32_union(&damage, &damage, &new_extents); - pixman_region32_fini(&new_extents); + region_t new_extents; + pixman_region32_init(&new_extents); + win_extents(w, &new_extents); + pixman_region32_union(&damage, &damage, &new_extents); + pixman_region32_fini(&new_extents); - if (factor_change) { - win_on_factor_change(ps, w); - add_damage(ps, &damage); - win_update_screen(ps, w); - } - } + if (factor_change) { + win_on_factor_change(ps, w); + add_damage(ps, &damage); + win_update_screen(ps, w); + } + } - pixman_region32_fini(&damage); + pixman_region32_fini(&damage); - // override_redirect flag cannot be changed after window creation, as far - // as I know, so there's no point to re-match windows here. - w->a.override_redirect = ce->override_redirect; + // override_redirect flag cannot be changed after window creation, as far + // as I know, so there's no point to re-match windows here. + w->a.override_redirect = ce->override_redirect; } -static void -circulate_win(session_t *ps, xcb_circulate_notify_event_t *ce) { - win *w = find_win(ps, ce->window); - xcb_window_t new_above; +static void circulate_win(session_t *ps, xcb_circulate_notify_event_t *ce) { + win *w = find_win(ps, ce->window); + xcb_window_t new_above; - if (!w) return; + if (!w) + return; - if (ce->place == PlaceOnTop) { - new_above = ps->list->id; - } else { - new_above = XCB_NONE; - } + if (ce->place == PlaceOnTop) { + new_above = ps->list->id; + } else { + new_above = XCB_NONE; + } - restack_win(ps, w, new_above); + restack_win(ps, w, new_above); } -static inline void -root_damaged(session_t *ps) { - if (ps->root_tile_paint.pixmap) { - free_root_tile(ps); - } +static inline void root_damaged(session_t *ps) { + if (ps->root_tile_paint.pixmap) { + free_root_tile(ps); + } - if (ps->o.experimental_backends) { - if (ps->root_image) { - ps->backend_data->ops->release_image(ps->backend_data, ps->root_image); - } - auto pixmap = x_get_root_back_pixmap(ps); - if (pixmap != XCB_NONE) { - ps->root_image = - ps->backend_data->ops->bind_pixmap(ps->backend_data, pixmap, - x_get_visual_info(ps->c, ps->vis), false); - ps->backend_data->ops->image_op(ps->backend_data, IMAGE_OP_RESIZE_TILE, - ps->root_image, NULL, NULL, (int[]){ps->root_width, ps->root_height}); - } - } + if (ps->o.experimental_backends) { + if (ps->root_image) { + ps->backend_data->ops->release_image(ps->backend_data, ps->root_image); + } + auto pixmap = x_get_root_back_pixmap(ps); + if (pixmap != XCB_NONE) { + ps->root_image = ps->backend_data->ops->bind_pixmap( + ps->backend_data, pixmap, x_get_visual_info(ps->c, ps->vis), false); + ps->backend_data->ops->image_op( + ps->backend_data, IMAGE_OP_RESIZE_TILE, ps->root_image, NULL, + NULL, (int[]){ps->root_width, ps->root_height}); + } + } - // Mark screen damaged - force_repaint(ps); + // Mark screen damaged + force_repaint(ps); } /** * Xlib error handler function. */ -static int -xerror(Display attr_unused *dpy, XErrorEvent *ev) { - if (!should_ignore(ps_g, ev->serial)) - x_print_error(ev->serial, ev->request_code, ev->minor_code, ev->error_code); - return 0; +static int xerror(Display attr_unused *dpy, XErrorEvent *ev) { + if (!should_ignore(ps_g, ev->serial)) + x_print_error(ev->serial, ev->request_code, ev->minor_code, ev->error_code); + return 0; } /** * XCB error handler function. */ -void -ev_xcb_error(session_t *ps, xcb_generic_error_t *err) { - if (!should_ignore(ps, err->sequence)) - x_print_error(err->sequence, err->major_code, err->minor_code, err->error_code); +void ev_xcb_error(session_t *ps, xcb_generic_error_t *err) { + if (!should_ignore(ps, err->sequence)) + x_print_error(err->sequence, err->major_code, err->minor_code, err->error_code); } -static void -expose_root(session_t *ps, const rect_t *rects, int nrects) { - region_t region; - pixman_region32_init_rects(®ion, rects, nrects); - add_damage(ps, ®ion); +static void expose_root(session_t *ps, const rect_t *rects, int nrects) { + region_t region; + pixman_region32_init_rects(®ion, rects, nrects); + add_damage(ps, ®ion); } /** * Force a full-screen repaint. */ -void -force_repaint(session_t *ps) { - assert(pixman_region32_not_empty(&ps->screen_reg)); - queue_redraw(ps); - add_damage(ps, &ps->screen_reg); +void force_repaint(session_t *ps) { + assert(pixman_region32_not_empty(&ps->screen_reg)); + queue_redraw(ps); + add_damage(ps, &ps->screen_reg); } #ifdef CONFIG_DBUS @@ -1003,13 +951,12 @@ force_repaint(session_t *ps) { /** * Set w->shadow_force of a window. */ -void -win_set_shadow_force(session_t *ps, win *w, switch_t val) { - if (val != w->shadow_force) { - w->shadow_force = val; - win_determine_shadow(ps, w); - queue_redraw(ps); - } +void win_set_shadow_force(session_t *ps, win *w, switch_t val) { + if (val != w->shadow_force) { + w->shadow_force = val; + win_determine_shadow(ps, w); + queue_redraw(ps); + } } /** @@ -1017,56 +964,54 @@ win_set_shadow_force(session_t *ps, win *w, switch_t val) { * * Doesn't affect fading already in progress */ -void -win_set_fade_force(session_t *ps, win *w, switch_t val) { - w->fade_force = val; +void win_set_fade_force(session_t *ps, win *w, switch_t val) { + w->fade_force = val; } /** * Set w->focused_force of a window. */ -void -win_set_focused_force(session_t *ps, win *w, switch_t val) { - if (val != w->focused_force) { - w->focused_force = val; - win_update_focused(ps, w); - queue_redraw(ps); - } +void win_set_focused_force(session_t *ps, win *w, switch_t val) { + if (val != w->focused_force) { + w->focused_force = val; + win_update_focused(ps, w); + queue_redraw(ps); + } } /** * Set w->invert_color_force of a window. */ -void -win_set_invert_color_force(session_t *ps, win *w, switch_t val) { - if (val != w->invert_color_force) { - w->invert_color_force = val; - win_determine_invert_color(ps, w); - queue_redraw(ps); - } +void win_set_invert_color_force(session_t *ps, win *w, switch_t val) { + if (val != w->invert_color_force) { + w->invert_color_force = val; + win_determine_invert_color(ps, w); + queue_redraw(ps); + } } /** * Enable focus tracking. */ -void -opts_init_track_focus(session_t *ps) { - // Already tracking focus - if (ps->o.track_focus) - return; +void opts_init_track_focus(session_t *ps) { + // Already tracking focus + if (ps->o.track_focus) + return; - ps->o.track_focus = true; + ps->o.track_focus = true; - if (!ps->o.use_ewmh_active_win) { - // Start listening to FocusChange events - for (win *w = ps->list; w; w = w->next) - if (w->a.map_state == XCB_MAP_STATE_VIEWABLE) - xcb_change_window_attributes(ps->c, w->id, XCB_CW_EVENT_MASK, - (const uint32_t[]) { determine_evmask(ps, w->id, WIN_EVMODE_FRAME) }); - } + if (!ps->o.use_ewmh_active_win) { + // Start listening to FocusChange events + for (win *w = ps->list; w; w = w->next) + if (w->a.map_state == XCB_MAP_STATE_VIEWABLE) + xcb_change_window_attributes( + ps->c, w->id, XCB_CW_EVENT_MASK, + (const uint32_t[]){ + determine_evmask(ps, w->id, WIN_EVMODE_FRAME)}); + } - // Recheck focus - recheck_focus(ps); + // Recheck focus + recheck_focus(ps); } /** @@ -1074,127 +1019,109 @@ opts_init_track_focus(session_t *ps) { * * Don't affect fading already in progress */ -void -opts_set_no_fading_openclose(session_t *ps, bool newval) { - ps->o.no_fading_openclose = newval; +void opts_set_no_fading_openclose(session_t *ps, bool newval) { + ps->o.no_fading_openclose = newval; } //!@} #endif -static inline int attr_unused -ev_serial(xcb_generic_event_t *ev) { - return ev->full_sequence; +static inline int attr_unused ev_serial(xcb_generic_event_t *ev) { + return ev->full_sequence; } -static inline const char * attr_unused -ev_name(session_t *ps, xcb_generic_event_t *ev) { - static char buf[128]; - switch (ev->response_type & 0x7f) { - CASESTRRET(FocusIn); - CASESTRRET(FocusOut); - CASESTRRET(CreateNotify); - CASESTRRET(ConfigureNotify); - CASESTRRET(DestroyNotify); - CASESTRRET(MapNotify); - CASESTRRET(UnmapNotify); - CASESTRRET(ReparentNotify); - CASESTRRET(CirculateNotify); - CASESTRRET(Expose); - CASESTRRET(PropertyNotify); - CASESTRRET(ClientMessage); - } +static inline const char *attr_unused ev_name(session_t *ps, xcb_generic_event_t *ev) { + static char buf[128]; + switch (ev->response_type & 0x7f) { + CASESTRRET(FocusIn); + CASESTRRET(FocusOut); + CASESTRRET(CreateNotify); + CASESTRRET(ConfigureNotify); + CASESTRRET(DestroyNotify); + CASESTRRET(MapNotify); + CASESTRRET(UnmapNotify); + CASESTRRET(ReparentNotify); + CASESTRRET(CirculateNotify); + CASESTRRET(Expose); + CASESTRRET(PropertyNotify); + CASESTRRET(ClientMessage); + } - if (ps->damage_event + XCB_DAMAGE_NOTIFY == ev->response_type) - return "Damage"; + if (ps->damage_event + XCB_DAMAGE_NOTIFY == ev->response_type) + return "Damage"; - if (ps->shape_exists && ev->response_type == ps->shape_event) - return "ShapeNotify"; + if (ps->shape_exists && ev->response_type == ps->shape_event) + return "ShapeNotify"; - if (ps->xsync_exists) { - int o = ev->response_type - ps->xsync_event; - switch (o) { - CASESTRRET(XSyncCounterNotify); - CASESTRRET(XSyncAlarmNotify); - } - } + if (ps->xsync_exists) { + int o = ev->response_type - ps->xsync_event; + switch (o) { + CASESTRRET(XSyncCounterNotify); + CASESTRRET(XSyncAlarmNotify); + } + } - sprintf(buf, "Event %d", ev->response_type); + sprintf(buf, "Event %d", ev->response_type); - return buf; + return buf; } -static inline xcb_window_t attr_unused -ev_window(session_t *ps, xcb_generic_event_t *ev) { - switch (ev->response_type) { - case FocusIn: - case FocusOut: - return ((xcb_focus_in_event_t *)ev)->event; - case CreateNotify: - return ((xcb_create_notify_event_t *)ev)->window; - case ConfigureNotify: - return ((xcb_configure_notify_event_t *)ev)->window; - case DestroyNotify: - return ((xcb_destroy_notify_event_t *)ev)->window; - case MapNotify: - return ((xcb_map_notify_event_t *)ev)->window; - case UnmapNotify: - return ((xcb_unmap_notify_event_t *)ev)->window; - case ReparentNotify: - return ((xcb_reparent_notify_event_t *)ev)->window; - case CirculateNotify: - return ((xcb_circulate_notify_event_t *)ev)->window; - case Expose: - return ((xcb_expose_event_t *)ev)->window; - case PropertyNotify: - return ((xcb_property_notify_event_t *)ev)->window; - case ClientMessage: - return ((xcb_client_message_event_t *)ev)->window; - default: - if (ps->damage_event + XCB_DAMAGE_NOTIFY == ev->response_type) { - return ((xcb_damage_notify_event_t *)ev)->drawable; - } +static inline xcb_window_t attr_unused ev_window(session_t *ps, xcb_generic_event_t *ev) { + switch (ev->response_type) { + case FocusIn: + case FocusOut: return ((xcb_focus_in_event_t *)ev)->event; + case CreateNotify: return ((xcb_create_notify_event_t *)ev)->window; + case ConfigureNotify: return ((xcb_configure_notify_event_t *)ev)->window; + case DestroyNotify: return ((xcb_destroy_notify_event_t *)ev)->window; + case MapNotify: return ((xcb_map_notify_event_t *)ev)->window; + case UnmapNotify: return ((xcb_unmap_notify_event_t *)ev)->window; + case ReparentNotify: return ((xcb_reparent_notify_event_t *)ev)->window; + case CirculateNotify: return ((xcb_circulate_notify_event_t *)ev)->window; + case Expose: return ((xcb_expose_event_t *)ev)->window; + case PropertyNotify: return ((xcb_property_notify_event_t *)ev)->window; + case ClientMessage: return ((xcb_client_message_event_t *)ev)->window; + default: + if (ps->damage_event + XCB_DAMAGE_NOTIFY == ev->response_type) { + return ((xcb_damage_notify_event_t *)ev)->drawable; + } - if (ps->shape_exists && ev->response_type == ps->shape_event) { - return ((xcb_shape_notify_event_t *) ev)->affected_window; - } + if (ps->shape_exists && ev->response_type == ps->shape_event) { + return ((xcb_shape_notify_event_t *)ev)->affected_window; + } - return 0; - } + return 0; + } } -static inline const char * -ev_focus_mode_name(xcb_focus_in_event_t* ev) { - switch (ev->mode) { - CASESTRRET(NotifyNormal); - CASESTRRET(NotifyWhileGrabbed); - CASESTRRET(NotifyGrab); - CASESTRRET(NotifyUngrab); - } +static inline const char *ev_focus_mode_name(xcb_focus_in_event_t *ev) { + switch (ev->mode) { + CASESTRRET(NotifyNormal); + CASESTRRET(NotifyWhileGrabbed); + CASESTRRET(NotifyGrab); + CASESTRRET(NotifyUngrab); + } - return "Unknown"; + return "Unknown"; } -static inline const char * -ev_focus_detail_name(xcb_focus_in_event_t* ev) { - switch (ev->detail) { - CASESTRRET(NotifyAncestor); - CASESTRRET(NotifyVirtual); - CASESTRRET(NotifyInferior); - CASESTRRET(NotifyNonlinear); - CASESTRRET(NotifyNonlinearVirtual); - CASESTRRET(NotifyPointer); - CASESTRRET(NotifyPointerRoot); - CASESTRRET(NotifyDetailNone); - } +static inline const char *ev_focus_detail_name(xcb_focus_in_event_t *ev) { + switch (ev->detail) { + CASESTRRET(NotifyAncestor); + CASESTRRET(NotifyVirtual); + CASESTRRET(NotifyInferior); + CASESTRRET(NotifyNonlinear); + CASESTRRET(NotifyNonlinearVirtual); + CASESTRRET(NotifyPointer); + CASESTRRET(NotifyPointerRoot); + CASESTRRET(NotifyDetailNone); + } - return "Unknown"; + return "Unknown"; } -static inline void attr_unused -ev_focus_report(xcb_focus_in_event_t *ev) { - log_trace("{ mode: %s, detail: %s }\n", ev_focus_mode_name(ev), - ev_focus_detail_name(ev)); +static inline void attr_unused ev_focus_report(xcb_focus_in_event_t *ev) { + log_trace("{ mode: %s, detail: %s }\n", ev_focus_mode_name(ev), + ev_focus_detail_name(ev)); } // === Events === @@ -1210,141 +1137,135 @@ ev_focus_accept(XFocusChangeEvent *ev) { } */ -static inline void -ev_focus_in(session_t *ps, xcb_focus_in_event_t *ev) { +static inline void ev_focus_in(session_t *ps, xcb_focus_in_event_t *ev) { #ifdef DEBUG_EVENTS - ev_focus_report(ev); + ev_focus_report(ev); #endif - recheck_focus(ps); + recheck_focus(ps); } -inline static void -ev_focus_out(session_t *ps, xcb_focus_out_event_t *ev) { +inline static void ev_focus_out(session_t *ps, xcb_focus_out_event_t *ev) { #ifdef DEBUG_EVENTS - ev_focus_report(ev); + ev_focus_report(ev); #endif - recheck_focus(ps); + recheck_focus(ps); } -inline static void -ev_create_notify(session_t *ps, xcb_create_notify_event_t *ev) { - assert(ev->parent == ps->root); - add_win(ps, ev->window, 0); +inline static void ev_create_notify(session_t *ps, xcb_create_notify_event_t *ev) { + assert(ev->parent == ps->root); + add_win(ps, ev->window, 0); } -inline static void -ev_configure_notify(session_t *ps, xcb_configure_notify_event_t *ev) { - log_trace("{ send_event: %d, id: %#010x, above: %#010x, override_redirect: %d }", - ev->event, ev->window, ev->above_sibling, ev->override_redirect); - if (ev->window == ps->root) { - configure_root(ps, ev->width, ev->height); - } else { - configure_win(ps, ev); - } +inline static void ev_configure_notify(session_t *ps, xcb_configure_notify_event_t *ev) { + log_trace("{ send_event: %d, id: %#010x, above: %#010x, override_redirect: %d }", + ev->event, ev->window, ev->above_sibling, ev->override_redirect); + if (ev->window == ps->root) { + configure_root(ps, ev->width, ev->height); + } else { + configure_win(ps, ev); + } } -inline static void -ev_destroy_notify(session_t *ps, xcb_destroy_notify_event_t *ev) { - win *w = find_win(ps, ev->window); - if (w) { - unmap_win(ps, &w, true); - } +inline static void ev_destroy_notify(session_t *ps, xcb_destroy_notify_event_t *ev) { + win *w = find_win(ps, ev->window); + if (w) { + unmap_win(ps, &w, true); + } } -inline static void -ev_map_notify(session_t *ps, xcb_map_notify_event_t *ev) { - map_win_by_id(ps, ev->window); - // FocusIn/Out may be ignored when the window is unmapped, so we must - // recheck focus here - if (ps->o.track_focus) { - recheck_focus(ps); - } +inline static void ev_map_notify(session_t *ps, xcb_map_notify_event_t *ev) { + map_win_by_id(ps, ev->window); + // FocusIn/Out may be ignored when the window is unmapped, so we must + // recheck focus here + if (ps->o.track_focus) { + recheck_focus(ps); + } } -inline static void -ev_unmap_notify(session_t *ps, xcb_unmap_notify_event_t *ev) { - win *w = find_win(ps, ev->window); - if (w) { - unmap_win(ps, &w, false); - } +inline static void ev_unmap_notify(session_t *ps, xcb_unmap_notify_event_t *ev) { + win *w = find_win(ps, ev->window); + if (w) { + unmap_win(ps, &w, false); + } } -inline static void -ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t *ev) { - log_trace("{ new_parent: %#010x, override_redirect: %d }", - ev->parent, ev->override_redirect); +inline static void ev_reparent_notify(session_t *ps, xcb_reparent_notify_event_t *ev) { + log_trace("{ new_parent: %#010x, override_redirect: %d }", ev->parent, + ev->override_redirect); - if (ev->parent == ps->root) { - // new window - add_win(ps, ev->window, 0); - } else { - // otherwise, find and destroy the window first - win *w = find_win(ps, ev->window); - if (w) { - unmap_win(ps, &w, true); - } + if (ev->parent == ps->root) { + // new window + add_win(ps, ev->window, 0); + } else { + // otherwise, find and destroy the window first + win *w = find_win(ps, ev->window); + if (w) { + unmap_win(ps, &w, true); + } - // Reset event mask in case something wrong happens - xcb_change_window_attributes(ps->c, ev->window, XCB_CW_EVENT_MASK, - (const uint32_t[]) { determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN) }); + // Reset event mask in case something wrong happens + xcb_change_window_attributes( + ps->c, ev->window, XCB_CW_EVENT_MASK, + (const uint32_t[]){determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN)}); - // Check if the window is an undetected client window - // Firstly, check if it's a known client window - if (!find_toplevel(ps, ev->window)) { - // If not, look for its frame window - win *w_top = find_toplevel2(ps, ev->parent); - // If found, and the client window has not been determined, or its - // frame may not have a correct client, continue - if (w_top && (!w_top->client_win - || w_top->client_win == w_top->id)) { - // If it has WM_STATE, mark it the client window - if (wid_has_prop(ps, ev->window, ps->atom_client)) { - w_top->wmwin = false; - win_unmark_client(ps, w_top); - win_mark_client(ps, w_top, ev->window); - } - // Otherwise, watch for WM_STATE on it - else { - xcb_change_window_attributes(ps->c, ev->window, XCB_CW_EVENT_MASK, (const uint32_t[]) { - determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN) | XCB_EVENT_MASK_PROPERTY_CHANGE }); - } - } - } - } + // Check if the window is an undetected client window + // Firstly, check if it's a known client window + if (!find_toplevel(ps, ev->window)) { + // If not, look for its frame window + win *w_top = find_toplevel2(ps, ev->parent); + // If found, and the client window has not been determined, or its + // frame may not have a correct client, continue + if (w_top && (!w_top->client_win || w_top->client_win == w_top->id)) { + // If it has WM_STATE, mark it the client window + if (wid_has_prop(ps, ev->window, ps->atom_client)) { + w_top->wmwin = false; + win_unmark_client(ps, w_top); + win_mark_client(ps, w_top, ev->window); + } + // Otherwise, watch for WM_STATE on it + else { + xcb_change_window_attributes( + ps->c, ev->window, XCB_CW_EVENT_MASK, + (const uint32_t[]){ + determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN) | + XCB_EVENT_MASK_PROPERTY_CHANGE}); + } + } + } + } } -inline static void -ev_circulate_notify(session_t *ps, xcb_circulate_notify_event_t *ev) { - circulate_win(ps, ev); +inline static void ev_circulate_notify(session_t *ps, xcb_circulate_notify_event_t *ev) { + circulate_win(ps, ev); } -inline static void -ev_expose(session_t *ps, xcb_expose_event_t *ev) { - if (ev->window == ps->root || (ps->overlay && ev->window == ps->overlay)) { - int more = ev->count + 1; - if (ps->n_expose == ps->size_expose) { - if (ps->expose_rects) { - ps->expose_rects = crealloc(ps->expose_rects, ps->size_expose + more); - ps->size_expose += more; - } else { - ps->expose_rects = ccalloc(more, rect_t); - ps->size_expose = more; - } - } +inline static void ev_expose(session_t *ps, xcb_expose_event_t *ev) { + if (ev->window == ps->root || (ps->overlay && ev->window == ps->overlay)) { + int more = ev->count + 1; + if (ps->n_expose == ps->size_expose) { + if (ps->expose_rects) { + ps->expose_rects = + crealloc(ps->expose_rects, ps->size_expose + more); + ps->size_expose += more; + } else { + ps->expose_rects = ccalloc(more, rect_t); + ps->size_expose = more; + } + } - ps->expose_rects[ps->n_expose].x1 = ev->x; - ps->expose_rects[ps->n_expose].y1 = ev->y; - ps->expose_rects[ps->n_expose].x2 = ev->x + ev->width; - ps->expose_rects[ps->n_expose].y2 = ev->y + ev->height; - ps->n_expose++; + ps->expose_rects[ps->n_expose].x1 = ev->x; + ps->expose_rects[ps->n_expose].y1 = ev->y; + ps->expose_rects[ps->n_expose].x2 = ev->x + ev->width; + ps->expose_rects[ps->n_expose].y2 = ev->y + ev->height; + ps->n_expose++; - if (ev->count == 0) { - expose_root(ps, ps->expose_rects, ps->n_expose); - ps->n_expose = 0; - } - } + if (ev->count == 0) { + expose_root(ps, ps->expose_rects, ps->n_expose); + ps->n_expose = 0; + } + } } /** @@ -1353,517 +1274,486 @@ ev_expose(session_t *ps, xcb_expose_event_t *ev) { * Does not change anything if we fail to get the attribute or the window * returned could not be found. */ -static void -update_ewmh_active_win(session_t *ps) { - // Search for the window - xcb_window_t wid = wid_get_prop_window(ps, ps->root, ps->atom_ewmh_active_win); - win *w = find_win_all(ps, wid); +static void update_ewmh_active_win(session_t *ps) { + // Search for the window + xcb_window_t wid = wid_get_prop_window(ps, ps->root, ps->atom_ewmh_active_win); + win *w = find_win_all(ps, wid); - // Mark the window focused. No need to unfocus the previous one. - if (w) win_set_focused(ps, w, true); + // Mark the window focused. No need to unfocus the previous one. + if (w) + win_set_focused(ps, w, true); } -inline static void -ev_property_notify(session_t *ps, xcb_property_notify_event_t *ev) { +inline static void ev_property_notify(session_t *ps, xcb_property_notify_event_t *ev) { #ifdef DEBUG_EVENTS - { - // Print out changed atom - xcb_get_atom_name_reply_t *reply = - xcb_get_atom_name_reply(ps->c, xcb_get_atom_name(ps->c, ev->atom), NULL); - const char *name = "?"; - int name_len = 1; - if (reply) { - name = xcb_get_atom_name_name(reply); - name_len = xcb_get_atom_name_name_length(reply); - } + { + // Print out changed atom + xcb_get_atom_name_reply_t *reply = + xcb_get_atom_name_reply(ps->c, xcb_get_atom_name(ps->c, ev->atom), NULL); + const char *name = "?"; + int name_len = 1; + if (reply) { + name = xcb_get_atom_name_name(reply); + name_len = xcb_get_atom_name_name_length(reply); + } - log_trace("{ atom = %.*s }", name_len, name); - free(reply); - } + log_trace("{ atom = %.*s }", name_len, name); + free(reply); + } #endif - if (ps->root == ev->window) { - if (ps->o.track_focus && ps->o.use_ewmh_active_win - && ps->atom_ewmh_active_win == ev->atom) { - update_ewmh_active_win(ps); - } else { - // Destroy the root "image" if the wallpaper probably changed - if (x_is_root_back_pixmap_atom(ps, ev->atom)) { - root_damaged(ps); - } - } + if (ps->root == ev->window) { + if (ps->o.track_focus && ps->o.use_ewmh_active_win && + ps->atom_ewmh_active_win == ev->atom) { + update_ewmh_active_win(ps); + } else { + // Destroy the root "image" if the wallpaper probably changed + if (x_is_root_back_pixmap_atom(ps, ev->atom)) { + root_damaged(ps); + } + } - // Unconcerned about any other proprties on root window - return; - } + // Unconcerned about any other proprties on root window + return; + } - // If WM_STATE changes - if (ev->atom == ps->atom_client) { - // Check whether it could be a client window - if (!find_toplevel(ps, ev->window)) { - // Reset event mask anyway - xcb_change_window_attributes(ps->c, ev->window, XCB_CW_EVENT_MASK, (const uint32_t[]) { - determine_evmask(ps, ev->window, WIN_EVMODE_UNKNOWN) }); + // If WM_STATE changes + if (ev->atom == ps->atom_client) { + // Check whether it could be a client window + if (!find_toplevel(ps, ev->window)) { + // Reset event mask anyway + xcb_change_window_attributes(ps->c, ev->window, XCB_CW_EVENT_MASK, + (const uint32_t[]){determine_evmask( + ps, ev->window, WIN_EVMODE_UNKNOWN)}); - win *w_top = find_toplevel2(ps, ev->window); - // Initialize client_win as early as possible - if (w_top && (!w_top->client_win || w_top->client_win == w_top->id) - && wid_has_prop(ps, ev->window, ps->atom_client)) { - w_top->wmwin = false; - win_unmark_client(ps, w_top); - win_mark_client(ps, w_top, ev->window); - } - } - } + win *w_top = find_toplevel2(ps, ev->window); + // Initialize client_win as early as possible + if (w_top && (!w_top->client_win || w_top->client_win == w_top->id) && + wid_has_prop(ps, ev->window, ps->atom_client)) { + w_top->wmwin = false; + win_unmark_client(ps, w_top); + win_mark_client(ps, w_top, ev->window); + } + } + } - // If _NET_WM_WINDOW_TYPE changes... God knows why this would happen, but - // there are always some stupid applications. (#144) - if (ev->atom == ps->atom_win_type) { - win *w = NULL; - if ((w = find_toplevel(ps, ev->window))) - win_update_wintype(ps, w); - } + // If _NET_WM_WINDOW_TYPE changes... God knows why this would happen, but + // there are always some stupid applications. (#144) + if (ev->atom == ps->atom_win_type) { + win *w = NULL; + if ((w = find_toplevel(ps, ev->window))) + win_update_wintype(ps, w); + } - // If _NET_WM_OPACITY changes - if (ev->atom == ps->atom_opacity) { - win *w = find_win(ps, ev->window) ?: find_toplevel(ps, ev->window); - if (w) { - win_update_opacity_prop(ps, w); - // we cannot receive OPACITY change when window is destroyed - assert(w->state != WSTATE_DESTROYING); - if (w->state == WSTATE_MAPPED) { - // See the winstate_t transition table - w->state = WSTATE_FADING; - } - w->opacity_tgt = win_calc_opacity_target(ps, w); - } - } + // If _NET_WM_OPACITY changes + if (ev->atom == ps->atom_opacity) { + win *w = find_win(ps, ev->window) ?: find_toplevel(ps, ev->window); + if (w) { + win_update_opacity_prop(ps, w); + // we cannot receive OPACITY change when window is destroyed + assert(w->state != WSTATE_DESTROYING); + if (w->state == WSTATE_MAPPED) { + // See the winstate_t transition table + w->state = WSTATE_FADING; + } + w->opacity_tgt = win_calc_opacity_target(ps, w); + } + } - // If frame extents property changes - if (ps->o.frame_opacity && ev->atom == ps->atom_frame_extents) { - win *w = find_toplevel(ps, ev->window); - if (w) { - win_update_frame_extents(ps, w, ev->window); - // If frame extents change, the window needs repaint - add_damage_from_win(ps, w); - } - } + // If frame extents property changes + if (ps->o.frame_opacity && ev->atom == ps->atom_frame_extents) { + win *w = find_toplevel(ps, ev->window); + if (w) { + win_update_frame_extents(ps, w, ev->window); + // If frame extents change, the window needs repaint + add_damage_from_win(ps, w); + } + } - // If name changes - if (ps->o.track_wdata - && (ps->atom_name == ev->atom || ps->atom_name_ewmh == ev->atom)) { - win *w = find_toplevel(ps, ev->window); - if (w && 1 == win_get_name(ps, w)) { - win_on_factor_change(ps, w); - } - } + // If name changes + if (ps->o.track_wdata && (ps->atom_name == ev->atom || ps->atom_name_ewmh == ev->atom)) { + win *w = find_toplevel(ps, ev->window); + if (w && 1 == win_get_name(ps, w)) { + win_on_factor_change(ps, w); + } + } - // If class changes - if (ps->o.track_wdata && ps->atom_class == ev->atom) { - win *w = find_toplevel(ps, ev->window); - if (w) { - win_get_class(ps, w); - win_on_factor_change(ps, w); - } - } + // If class changes + if (ps->o.track_wdata && ps->atom_class == ev->atom) { + win *w = find_toplevel(ps, ev->window); + if (w) { + win_get_class(ps, w); + win_on_factor_change(ps, w); + } + } - // If role changes - if (ps->o.track_wdata && ps->atom_role == ev->atom) { - win *w = find_toplevel(ps, ev->window); - if (w && 1 == win_get_role(ps, w)) { - win_on_factor_change(ps, w); - } - } + // If role changes + if (ps->o.track_wdata && ps->atom_role == ev->atom) { + win *w = find_toplevel(ps, ev->window); + if (w && 1 == win_get_role(ps, w)) { + win_on_factor_change(ps, w); + } + } - // If _COMPTON_SHADOW changes - if (ps->o.respect_prop_shadow && ps->atom_compton_shadow == ev->atom) { - win *w = find_win(ps, ev->window); - if (w) - win_update_prop_shadow(ps, w); - } + // If _COMPTON_SHADOW changes + if (ps->o.respect_prop_shadow && ps->atom_compton_shadow == ev->atom) { + win *w = find_win(ps, ev->window); + if (w) + win_update_prop_shadow(ps, w); + } - // If a leader property changes - if ((ps->o.detect_transient && ps->atom_transient == ev->atom) - || (ps->o.detect_client_leader && ps->atom_client_leader == ev->atom)) { - win *w = find_toplevel(ps, ev->window); - if (w) { - win_update_leader(ps, w); - } - } + // If a leader property changes + if ((ps->o.detect_transient && ps->atom_transient == ev->atom) || + (ps->o.detect_client_leader && ps->atom_client_leader == ev->atom)) { + win *w = find_toplevel(ps, ev->window); + if (w) { + win_update_leader(ps, w); + } + } - // Check for other atoms we are tracking - for (latom_t *platom = ps->track_atom_lst; platom; platom = platom->next) { - if (platom->atom == ev->atom) { - win *w = find_win(ps, ev->window); - if (!w) - w = find_toplevel(ps, ev->window); - if (w) - win_on_factor_change(ps, w); - break; - } - } + // Check for other atoms we are tracking + for (latom_t *platom = ps->track_atom_lst; platom; platom = platom->next) { + if (platom->atom == ev->atom) { + win *w = find_win(ps, ev->window); + if (!w) + w = find_toplevel(ps, ev->window); + if (w) + win_on_factor_change(ps, w); + break; + } + } } -inline static void -ev_damage_notify(session_t *ps, xcb_damage_notify_event_t *de) { - /* - if (ps->root == de->drawable) { - root_damaged(); - return; - } */ +inline static void ev_damage_notify(session_t *ps, xcb_damage_notify_event_t *de) { + /* + if (ps->root == de->drawable) { + root_damaged(); + return; + } */ - win *w = find_win(ps, de->drawable); + win *w = find_win(ps, de->drawable); - if (!w) return; + if (!w) + return; - repair_win(ps, w); + repair_win(ps, w); } -inline static void -ev_shape_notify(session_t *ps, xcb_shape_notify_event_t *ev) { - win *w = find_win(ps, ev->affected_window); - if (!w || w->a.map_state == XCB_MAP_STATE_UNMAPPED) return; +inline static void ev_shape_notify(session_t *ps, xcb_shape_notify_event_t *ev) { + win *w = find_win(ps, ev->affected_window); + if (!w || w->a.map_state == XCB_MAP_STATE_UNMAPPED) + return; - /* - * Empty bounding_shape may indicated an - * unmapped/destroyed window, in which case - * seemingly BadRegion errors would be triggered - * if we attempt to rebuild border_size - */ - // Mark the old border_size as damaged - region_t tmp = win_get_bounding_shape_global_by_val(w); - add_damage(ps, &tmp); - pixman_region32_fini(&tmp); + /* + * Empty bounding_shape may indicated an + * unmapped/destroyed window, in which case + * seemingly BadRegion errors would be triggered + * if we attempt to rebuild border_size + */ + // Mark the old border_size as damaged + region_t tmp = win_get_bounding_shape_global_by_val(w); + add_damage(ps, &tmp); + pixman_region32_fini(&tmp); - win_update_bounding_shape(ps, w); + win_update_bounding_shape(ps, w); - // Mark the new border_size as damaged - tmp = win_get_bounding_shape_global_by_val(w); - add_damage(ps, &tmp); - pixman_region32_fini(&tmp); + // Mark the new border_size as damaged + tmp = win_get_bounding_shape_global_by_val(w); + add_damage(ps, &tmp); + pixman_region32_fini(&tmp); - w->reg_ignore_valid = false; + w->reg_ignore_valid = false; } /** * Handle ScreenChangeNotify events from X RandR extension. */ -static void -ev_screen_change_notify(session_t *ps, - xcb_randr_screen_change_notify_event_t attr_unused *ev) { - if (ps->o.xinerama_shadow_crop) - cxinerama_upd_scrs(ps); +static void ev_screen_change_notify(session_t *ps, + xcb_randr_screen_change_notify_event_t attr_unused *ev) { + if (ps->o.xinerama_shadow_crop) + cxinerama_upd_scrs(ps); - if (ps->o.sw_opti && !ps->o.refresh_rate) { - update_refresh_rate(ps); - if (!ps->refresh_rate) { - log_warn("Refresh rate detection failed. swopti will be temporarily disabled"); - } - } + if (ps->o.sw_opti && !ps->o.refresh_rate) { + update_refresh_rate(ps); + if (!ps->refresh_rate) { + log_warn("Refresh rate detection failed. swopti will be " + "temporarily disabled"); + } + } } inline static void -ev_selection_clear(session_t *ps, - xcb_selection_clear_event_t attr_unused *ev) { - // The only selection we own is the _NET_WM_CM_Sn selection. - // If we lose that one, we should exit. - log_fatal("Another composite manager started and took the _NET_WM_CM_Sn selection."); - exit(1); +ev_selection_clear(session_t *ps, xcb_selection_clear_event_t attr_unused *ev) { + // The only selection we own is the _NET_WM_CM_Sn selection. + // If we lose that one, we should exit. + log_fatal("Another composite manager started and took the _NET_WM_CM_Sn " + "selection."); + exit(1); } /** * Get a window's name from window ID. */ -static inline void attr_unused -ev_window_name(session_t *ps, xcb_window_t wid, char **name) { - *name = ""; - if (wid) { - *name = "(Failed to get title)"; - if (ps->root == wid) - *name = "(Root window)"; - else if (ps->overlay == wid) - *name = "(Overlay)"; - else { - win *w = find_win(ps, wid); - if (!w) - w = find_toplevel(ps, wid); +static inline void attr_unused ev_window_name(session_t *ps, xcb_window_t wid, char **name) { + *name = ""; + if (wid) { + *name = "(Failed to get title)"; + if (ps->root == wid) + *name = "(Root window)"; + else if (ps->overlay == wid) + *name = "(Overlay)"; + else { + win *w = find_win(ps, wid); + if (!w) + w = find_toplevel(ps, wid); - if (w) - win_get_name(ps, w); - if (w && w->name) - *name = w->name; - else - *name = "unknown"; - } - } + if (w) + win_get_name(ps, w); + if (w && w->name) + *name = w->name; + else + *name = "unknown"; + } + } } -static void -ev_handle(session_t *ps, xcb_generic_event_t *ev) { - if ((ev->response_type & 0x7f) != KeymapNotify) { - discard_ignore(ps, ev->full_sequence); - } +static void ev_handle(session_t *ps, xcb_generic_event_t *ev) { + if ((ev->response_type & 0x7f) != KeymapNotify) { + discard_ignore(ps, ev->full_sequence); + } #ifdef DEBUG_EVENTS - if (ev->response_type != ps->damage_event + XCB_DAMAGE_NOTIFY) { - xcb_window_t wid = ev_window(ps, ev); - char *window_name = NULL; - ev_window_name(ps, wid, &window_name); + if (ev->response_type != ps->damage_event + XCB_DAMAGE_NOTIFY) { + xcb_window_t wid = ev_window(ps, ev); + char *window_name = NULL; + ev_window_name(ps, wid, &window_name); - log_trace("event %10.10s serial %#010x window %#010lx \"%s\"", - ev_name(ps, ev), ev_serial(ev), wid, window_name); - } + log_trace("event %10.10s serial %#010x window %#010lx \"%s\"", + ev_name(ps, ev), ev_serial(ev), wid, window_name); + } #endif - // Check if a custom XEvent constructor was registered in xlib for this event - // type, and call it discarding the constructed XEvent if any. XESetWireToEvent - // might be used by libraries to intercept messages from the X server e.g. the - // OpenGL lib waiting for DRI2 events. + // Check if a custom XEvent constructor was registered in xlib for this event + // type, and call it discarding the constructed XEvent if any. XESetWireToEvent + // might be used by libraries to intercept messages from the X server e.g. the + // OpenGL lib waiting for DRI2 events. - // XXX This exists to workaround compton issue #33, #34, #47 - // For even more details, see: - // https://bugs.freedesktop.org/show_bug.cgi?id=35945 - // https://lists.freedesktop.org/archives/xcb/2011-November/007337.html - auto proc = XESetWireToEvent(ps->dpy, ev->response_type, 0); - if (proc) { - XESetWireToEvent(ps->dpy, ev->response_type, proc); - XEvent dummy; + // XXX This exists to workaround compton issue #33, #34, #47 + // For even more details, see: + // https://bugs.freedesktop.org/show_bug.cgi?id=35945 + // https://lists.freedesktop.org/archives/xcb/2011-November/007337.html + auto proc = XESetWireToEvent(ps->dpy, ev->response_type, 0); + if (proc) { + XESetWireToEvent(ps->dpy, ev->response_type, proc); + XEvent dummy; - // Stop Xlib from complaining about lost sequence numbers. - // proc might also just be Xlib internal event processing functions, and - // because they probably won't see all X replies, they will complain about - // missing sequence numbers. - // - // We only need the low 16 bits - ev->sequence = (uint16_t)(LastKnownRequestProcessed(ps->dpy) & 0xffff); - proc(ps->dpy, &dummy, (xEvent *)ev); - } + // Stop Xlib from complaining about lost sequence numbers. + // proc might also just be Xlib internal event processing functions, and + // because they probably won't see all X replies, they will complain about + // missing sequence numbers. + // + // We only need the low 16 bits + ev->sequence = (uint16_t)(LastKnownRequestProcessed(ps->dpy) & 0xffff); + proc(ps->dpy, &dummy, (xEvent *)ev); + } - // XXX redraw needs to be more fine grained - queue_redraw(ps); + // XXX redraw needs to be more fine grained + queue_redraw(ps); - switch (ev->response_type) { - case FocusIn: - ev_focus_in(ps, (xcb_focus_in_event_t *)ev); - break; - case FocusOut: - ev_focus_out(ps, (xcb_focus_out_event_t *)ev); - break; - case CreateNotify: - ev_create_notify(ps, (xcb_create_notify_event_t *)ev); - break; - case ConfigureNotify: - ev_configure_notify(ps, (xcb_configure_notify_event_t *)ev); - break; - case DestroyNotify: - ev_destroy_notify(ps, (xcb_destroy_notify_event_t *)ev); - break; - case MapNotify: - ev_map_notify(ps, (xcb_map_notify_event_t *)ev); - break; - case UnmapNotify: - ev_unmap_notify(ps, (xcb_unmap_notify_event_t *)ev); - break; - case ReparentNotify: - ev_reparent_notify(ps, (xcb_reparent_notify_event_t *)ev); - break; - case CirculateNotify: - ev_circulate_notify(ps, (xcb_circulate_notify_event_t *)ev); - break; - case Expose: - ev_expose(ps, (xcb_expose_event_t *)ev); - break; - case PropertyNotify: - ev_property_notify(ps, (xcb_property_notify_event_t *)ev); - break; - case SelectionClear: - ev_selection_clear(ps, (xcb_selection_clear_event_t *)ev); - break; - case 0: - ev_xcb_error(ps, (xcb_generic_error_t *)ev); - break; - default: - if (ps->shape_exists && ev->response_type == ps->shape_event) { - ev_shape_notify(ps, (xcb_shape_notify_event_t *) ev); - break; - } - if (ps->randr_exists && ev->response_type == (ps->randr_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY)) { - ev_screen_change_notify(ps, (xcb_randr_screen_change_notify_event_t *) ev); - break; - } - if (ps->damage_event + XCB_DAMAGE_NOTIFY == ev->response_type) { - ev_damage_notify(ps, (xcb_damage_notify_event_t *) ev); - break; - } - } + switch (ev->response_type) { + case FocusIn: ev_focus_in(ps, (xcb_focus_in_event_t *)ev); break; + case FocusOut: ev_focus_out(ps, (xcb_focus_out_event_t *)ev); break; + case CreateNotify: ev_create_notify(ps, (xcb_create_notify_event_t *)ev); break; + case ConfigureNotify: + ev_configure_notify(ps, (xcb_configure_notify_event_t *)ev); + break; + case DestroyNotify: + ev_destroy_notify(ps, (xcb_destroy_notify_event_t *)ev); + break; + case MapNotify: ev_map_notify(ps, (xcb_map_notify_event_t *)ev); break; + case UnmapNotify: ev_unmap_notify(ps, (xcb_unmap_notify_event_t *)ev); break; + case ReparentNotify: + ev_reparent_notify(ps, (xcb_reparent_notify_event_t *)ev); + break; + case CirculateNotify: + ev_circulate_notify(ps, (xcb_circulate_notify_event_t *)ev); + break; + case Expose: ev_expose(ps, (xcb_expose_event_t *)ev); break; + case PropertyNotify: + ev_property_notify(ps, (xcb_property_notify_event_t *)ev); + break; + case SelectionClear: + ev_selection_clear(ps, (xcb_selection_clear_event_t *)ev); + break; + case 0: ev_xcb_error(ps, (xcb_generic_error_t *)ev); break; + default: + if (ps->shape_exists && ev->response_type == ps->shape_event) { + ev_shape_notify(ps, (xcb_shape_notify_event_t *)ev); + break; + } + if (ps->randr_exists && + ev->response_type == (ps->randr_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY)) { + ev_screen_change_notify( + ps, (xcb_randr_screen_change_notify_event_t *)ev); + break; + } + if (ps->damage_event + XCB_DAMAGE_NOTIFY == ev->response_type) { + ev_damage_notify(ps, (xcb_damage_notify_event_t *)ev); + break; + } + } } // === Main === - /** * Register a window as symbol, and initialize GLX context if wanted. */ -static bool -register_cm(session_t *ps) { - assert(!ps->reg_win); +static bool register_cm(session_t *ps) { + assert(!ps->reg_win); - ps->reg_win = XCreateSimpleWindow(ps->dpy, ps->root, 0, 0, 1, 1, 0, - XCB_NONE, XCB_NONE); + ps->reg_win = + XCreateSimpleWindow(ps->dpy, ps->root, 0, 0, 1, 1, 0, XCB_NONE, XCB_NONE); - if (!ps->reg_win) { - log_fatal("Failed to create window."); - return false; - } + if (!ps->reg_win) { + log_fatal("Failed to create window."); + return false; + } - // Unredirect the window if it's redirected, just in case - if (ps->redirected) - xcb_composite_unredirect_window(ps->c, ps->reg_win, XCB_COMPOSITE_REDIRECT_MANUAL); + // Unredirect the window if it's redirected, just in case + if (ps->redirected) + xcb_composite_unredirect_window(ps->c, ps->reg_win, + XCB_COMPOSITE_REDIRECT_MANUAL); - { - XClassHint *h = XAllocClassHint(); - if (h) { - h->res_name = "compton"; - h->res_class = "xcompmgr"; - } - Xutf8SetWMProperties(ps->dpy, ps->reg_win, "xcompmgr", "xcompmgr", - NULL, 0, NULL, NULL, h); - cxfree(h); - } + { + XClassHint *h = XAllocClassHint(); + if (h) { + h->res_name = "compton"; + h->res_class = "xcompmgr"; + } + Xutf8SetWMProperties(ps->dpy, ps->reg_win, "xcompmgr", "xcompmgr", NULL, + 0, NULL, NULL, h); + cxfree(h); + } - // Set _NET_WM_PID - { - uint32_t pid = getpid(); - xcb_change_property(ps->c, XCB_PROP_MODE_REPLACE, ps->reg_win, - get_atom(ps, "_NET_WM_PID"), XCB_ATOM_CARDINAL, 32, 1, &pid); - } + // Set _NET_WM_PID + { + uint32_t pid = getpid(); + xcb_change_property(ps->c, XCB_PROP_MODE_REPLACE, ps->reg_win, + get_atom(ps, "_NET_WM_PID"), XCB_ATOM_CARDINAL, 32, 1, + &pid); + } - // Set COMPTON_VERSION - if (!wid_set_text_prop(ps, ps->reg_win, get_atom(ps, "COMPTON_VERSION"), - COMPTON_VERSION)) { - log_error("Failed to set COMPTON_VERSION."); - } + // Set COMPTON_VERSION + if (!wid_set_text_prop(ps, ps->reg_win, get_atom(ps, "COMPTON_VERSION"), + COMPTON_VERSION)) { + log_error("Failed to set COMPTON_VERSION."); + } - // Acquire X Selection _NET_WM_CM_S? - if (!ps->o.no_x_selection) { - unsigned len = strlen(REGISTER_PROP) + 2; - int s = ps->scr; - Atom atom; + // Acquire X Selection _NET_WM_CM_S? + if (!ps->o.no_x_selection) { + unsigned len = strlen(REGISTER_PROP) + 2; + int s = ps->scr; + Atom atom; - while (s >= 10) { - ++len; - s /= 10; - } + while (s >= 10) { + ++len; + s /= 10; + } - auto buf = ccalloc(len, char); - snprintf(buf, len, REGISTER_PROP "%d", ps->scr); - buf[len - 1] = '\0'; - atom = get_atom(ps, buf); - free(buf); + auto buf = ccalloc(len, char); + snprintf(buf, len, REGISTER_PROP "%d", ps->scr); + buf[len - 1] = '\0'; + atom = get_atom(ps, buf); + free(buf); - xcb_get_selection_owner_reply_t *reply = - xcb_get_selection_owner_reply(ps->c, - xcb_get_selection_owner(ps->c, atom), NULL); + xcb_get_selection_owner_reply_t *reply = xcb_get_selection_owner_reply( + ps->c, xcb_get_selection_owner(ps->c, atom), NULL); - if (reply && reply->owner != XCB_NONE) { - free(reply); - log_fatal("Another composite manager is already running"); - return false; - } - free(reply); - xcb_set_selection_owner(ps->c, ps->reg_win, atom, 0); - } + if (reply && reply->owner != XCB_NONE) { + free(reply); + log_fatal("Another composite manager is already running"); + return false; + } + free(reply); + xcb_set_selection_owner(ps->c, ps->reg_win, atom, 0); + } - return true; + return true; } /** * Write PID to a file. */ -static inline bool -write_pid(session_t *ps) { - if (!ps->o.write_pid_path) - return true; +static inline bool write_pid(session_t *ps) { + if (!ps->o.write_pid_path) + return true; - FILE *f = fopen(ps->o.write_pid_path, "w"); - if (unlikely(!f)) { - log_error("Failed to write PID to \"%s\".", ps->o.write_pid_path); - return false; - } + FILE *f = fopen(ps->o.write_pid_path, "w"); + if (unlikely(!f)) { + log_error("Failed to write PID to \"%s\".", ps->o.write_pid_path); + return false; + } - fprintf(f, "%ld\n", (long) getpid()); - fclose(f); + fprintf(f, "%ld\n", (long)getpid()); + fclose(f); - return true; + return true; } /** * Fetch all required atoms and save them to a session. */ -static void -init_atoms(session_t *ps) { - ps->atom_opacity = get_atom(ps, "_NET_WM_WINDOW_OPACITY"); - ps->atom_frame_extents = get_atom(ps, "_NET_FRAME_EXTENTS"); - ps->atom_client = get_atom(ps, "WM_STATE"); - ps->atom_name = XCB_ATOM_WM_NAME; - ps->atom_name_ewmh = get_atom(ps, "_NET_WM_NAME"); - ps->atom_class = XCB_ATOM_WM_CLASS; - ps->atom_role = get_atom(ps, "WM_WINDOW_ROLE"); - ps->atom_transient = XCB_ATOM_WM_TRANSIENT_FOR; - ps->atom_client_leader = get_atom(ps, "WM_CLIENT_LEADER"); - ps->atom_ewmh_active_win = get_atom(ps, "_NET_ACTIVE_WINDOW"); - ps->atom_compton_shadow = get_atom(ps, "_COMPTON_SHADOW"); +static void init_atoms(session_t *ps) { + ps->atom_opacity = get_atom(ps, "_NET_WM_WINDOW_OPACITY"); + ps->atom_frame_extents = get_atom(ps, "_NET_FRAME_EXTENTS"); + ps->atom_client = get_atom(ps, "WM_STATE"); + ps->atom_name = XCB_ATOM_WM_NAME; + ps->atom_name_ewmh = get_atom(ps, "_NET_WM_NAME"); + ps->atom_class = XCB_ATOM_WM_CLASS; + ps->atom_role = get_atom(ps, "WM_WINDOW_ROLE"); + ps->atom_transient = XCB_ATOM_WM_TRANSIENT_FOR; + ps->atom_client_leader = get_atom(ps, "WM_CLIENT_LEADER"); + ps->atom_ewmh_active_win = get_atom(ps, "_NET_ACTIVE_WINDOW"); + ps->atom_compton_shadow = get_atom(ps, "_COMPTON_SHADOW"); - ps->atom_win_type = get_atom(ps, "_NET_WM_WINDOW_TYPE"); - ps->atoms_wintypes[WINTYPE_UNKNOWN] = 0; - ps->atoms_wintypes[WINTYPE_DESKTOP] = get_atom(ps, - "_NET_WM_WINDOW_TYPE_DESKTOP"); - ps->atoms_wintypes[WINTYPE_DOCK] = get_atom(ps, - "_NET_WM_WINDOW_TYPE_DOCK"); - ps->atoms_wintypes[WINTYPE_TOOLBAR] = get_atom(ps, - "_NET_WM_WINDOW_TYPE_TOOLBAR"); - ps->atoms_wintypes[WINTYPE_MENU] = get_atom(ps, - "_NET_WM_WINDOW_TYPE_MENU"); - ps->atoms_wintypes[WINTYPE_UTILITY] = get_atom(ps, - "_NET_WM_WINDOW_TYPE_UTILITY"); - ps->atoms_wintypes[WINTYPE_SPLASH] = get_atom(ps, - "_NET_WM_WINDOW_TYPE_SPLASH"); - ps->atoms_wintypes[WINTYPE_DIALOG] = get_atom(ps, - "_NET_WM_WINDOW_TYPE_DIALOG"); - ps->atoms_wintypes[WINTYPE_NORMAL] = get_atom(ps, - "_NET_WM_WINDOW_TYPE_NORMAL"); - ps->atoms_wintypes[WINTYPE_DROPDOWN_MENU] = get_atom(ps, - "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"); - ps->atoms_wintypes[WINTYPE_POPUP_MENU] = get_atom(ps, - "_NET_WM_WINDOW_TYPE_POPUP_MENU"); - ps->atoms_wintypes[WINTYPE_TOOLTIP] = get_atom(ps, - "_NET_WM_WINDOW_TYPE_TOOLTIP"); - ps->atoms_wintypes[WINTYPE_NOTIFY] = get_atom(ps, - "_NET_WM_WINDOW_TYPE_NOTIFICATION"); - ps->atoms_wintypes[WINTYPE_COMBO] = get_atom(ps, - "_NET_WM_WINDOW_TYPE_COMBO"); - ps->atoms_wintypes[WINTYPE_DND] = get_atom(ps, - "_NET_WM_WINDOW_TYPE_DND"); + ps->atom_win_type = get_atom(ps, "_NET_WM_WINDOW_TYPE"); + ps->atoms_wintypes[WINTYPE_UNKNOWN] = 0; + ps->atoms_wintypes[WINTYPE_DESKTOP] = get_atom(ps, "_NET_WM_WINDOW_TYPE_DESKTOP"); + ps->atoms_wintypes[WINTYPE_DOCK] = get_atom(ps, "_NET_WM_WINDOW_TYPE_DOCK"); + ps->atoms_wintypes[WINTYPE_TOOLBAR] = get_atom(ps, "_NET_WM_WINDOW_TYPE_TOOLBAR"); + ps->atoms_wintypes[WINTYPE_MENU] = get_atom(ps, "_NET_WM_WINDOW_TYPE_MENU"); + ps->atoms_wintypes[WINTYPE_UTILITY] = get_atom(ps, "_NET_WM_WINDOW_TYPE_UTILITY"); + ps->atoms_wintypes[WINTYPE_SPLASH] = get_atom(ps, "_NET_WM_WINDOW_TYPE_SPLASH"); + ps->atoms_wintypes[WINTYPE_DIALOG] = get_atom(ps, "_NET_WM_WINDOW_TYPE_DIALOG"); + ps->atoms_wintypes[WINTYPE_NORMAL] = get_atom(ps, "_NET_WM_WINDOW_TYPE_NORMAL"); + ps->atoms_wintypes[WINTYPE_DROPDOWN_MENU] = + get_atom(ps, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"); + ps->atoms_wintypes[WINTYPE_POPUP_MENU] = + get_atom(ps, "_NET_WM_WINDOW_TYPE_POPUP_MENU"); + ps->atoms_wintypes[WINTYPE_TOOLTIP] = get_atom(ps, "_NET_WM_WINDOW_TYPE_TOOLTIP"); + ps->atoms_wintypes[WINTYPE_NOTIFY] = + get_atom(ps, "_NET_WM_WINDOW_TYPE_NOTIFICATION"); + ps->atoms_wintypes[WINTYPE_COMBO] = get_atom(ps, "_NET_WM_WINDOW_TYPE_COMBO"); + ps->atoms_wintypes[WINTYPE_DND] = get_atom(ps, "_NET_WM_WINDOW_TYPE_DND"); } /** * Update refresh rate info with X Randr extension. */ -static void -update_refresh_rate(session_t *ps) { - xcb_randr_get_screen_info_reply_t *randr_info = - xcb_randr_get_screen_info_reply(ps->c, - xcb_randr_get_screen_info(ps->c, ps->root), NULL); +static void update_refresh_rate(session_t *ps) { + xcb_randr_get_screen_info_reply_t *randr_info = xcb_randr_get_screen_info_reply( + ps->c, xcb_randr_get_screen_info(ps->c, ps->root), NULL); - if (!randr_info) - return; - ps->refresh_rate = randr_info->rate; - free(randr_info); + if (!randr_info) + return; + ps->refresh_rate = randr_info->rate; + free(randr_info); - if (ps->refresh_rate) - ps->refresh_intv = US_PER_SEC / ps->refresh_rate; - else - ps->refresh_intv = 0; + if (ps->refresh_rate) + ps->refresh_intv = US_PER_SEC / ps->refresh_rate; + else + ps->refresh_intv = 0; } /** @@ -1871,26 +1761,26 @@ update_refresh_rate(session_t *ps) { * * @return true for success, false otherwise */ -static bool -swopti_init(session_t *ps) { - log_warn("--sw-opti is going to be deprecated. If you get real benefits from using " - "this option, please open an issue to let us know."); - // Prepare refresh rate - // Check if user provides one - ps->refresh_rate = ps->o.refresh_rate; - if (ps->refresh_rate) - ps->refresh_intv = US_PER_SEC / ps->refresh_rate; +static bool swopti_init(session_t *ps) { + log_warn("--sw-opti is going to be deprecated. If you get real benefits from " + "using " + "this option, please open an issue to let us know."); + // Prepare refresh rate + // Check if user provides one + ps->refresh_rate = ps->o.refresh_rate; + if (ps->refresh_rate) + ps->refresh_intv = US_PER_SEC / ps->refresh_rate; - // Auto-detect refresh rate otherwise - if (!ps->refresh_rate && ps->randr_exists) { - update_refresh_rate(ps); - } + // Auto-detect refresh rate otherwise + if (!ps->refresh_rate && ps->randr_exists) { + update_refresh_rate(ps); + } - // Turn off vsync_sw if we can't get the refresh rate - if (!ps->refresh_rate) - return false; + // Turn off vsync_sw if we can't get the refresh rate + if (!ps->refresh_rate) + return false; - return true; + return true; } /** @@ -1899,78 +1789,77 @@ swopti_init(session_t *ps) { * @param ps current session * @param[in,out] ptv pointer to the timeout */ -static double -swopti_handle_timeout(session_t *ps) { - if (!ps->refresh_intv) - return 0; +static double swopti_handle_timeout(session_t *ps) { + if (!ps->refresh_intv) + return 0; - // Get the microsecond offset of the time when the we reach the timeout - // I don't think a 32-bit long could overflow here. - long offset = (get_time_timeval().tv_usec - ps->paint_tm_offset) % ps->refresh_intv; - // XXX this formula dones't work if refresh rate is not a whole number - if (offset < 0) - offset += ps->refresh_intv; + // Get the microsecond offset of the time when the we reach the timeout + // I don't think a 32-bit long could overflow here. + long offset = (get_time_timeval().tv_usec - ps->paint_tm_offset) % ps->refresh_intv; + // XXX this formula dones't work if refresh rate is not a whole number + if (offset < 0) + offset += ps->refresh_intv; - // If the target time is sufficiently close to a refresh time, don't add - // an offset, to avoid certain blocking conditions. - if (offset < SWOPTI_TOLERANCE - || offset > ps->refresh_intv - SWOPTI_TOLERANCE) - return 0; + // If the target time is sufficiently close to a refresh time, don't add + // an offset, to avoid certain blocking conditions. + if (offset < SWOPTI_TOLERANCE || offset > ps->refresh_intv - SWOPTI_TOLERANCE) + return 0; - // Add an offset so we wait until the next refresh after timeout - return (ps->refresh_intv - offset) / 1e6; + // Add an offset so we wait until the next refresh after timeout + return (ps->refresh_intv - offset) / 1e6; } /** * Initialize X composite overlay window. */ -static bool -init_overlay(session_t *ps) { - xcb_composite_get_overlay_window_reply_t *reply = - xcb_composite_get_overlay_window_reply(ps->c, - xcb_composite_get_overlay_window(ps->c, ps->root), NULL); - if (reply) { - ps->overlay = reply->overlay_win; - free(reply); - } else { - ps->overlay = XCB_NONE; - } - if (ps->overlay) { - // Set window region of the overlay window, code stolen from - // compiz-0.8.8 - xcb_generic_error_t *e; - e = XCB_SYNCED_VOID(xcb_shape_mask, ps->c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, - ps->overlay, 0, 0, 0); - if (e) { - log_fatal("Failed to set the bounding shape of overlay, giving up."); - exit(1); - } - e = XCB_SYNCED_VOID(xcb_shape_rectangles, ps->c, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT, - XCB_CLIP_ORDERING_UNSORTED, ps->overlay, 0, 0, 0, NULL); - if (e) { - log_fatal("Failed to set the input shape of overlay, giving up."); - exit(1); - } +static bool init_overlay(session_t *ps) { + xcb_composite_get_overlay_window_reply_t *reply = + xcb_composite_get_overlay_window_reply( + ps->c, xcb_composite_get_overlay_window(ps->c, ps->root), NULL); + if (reply) { + ps->overlay = reply->overlay_win; + free(reply); + } else { + ps->overlay = XCB_NONE; + } + if (ps->overlay) { + // Set window region of the overlay window, code stolen from + // compiz-0.8.8 + xcb_generic_error_t *e; + e = XCB_SYNCED_VOID(xcb_shape_mask, ps->c, XCB_SHAPE_SO_SET, + XCB_SHAPE_SK_BOUNDING, ps->overlay, 0, 0, 0); + if (e) { + log_fatal("Failed to set the bounding shape of overlay, giving " + "up."); + exit(1); + } + e = XCB_SYNCED_VOID(xcb_shape_rectangles, ps->c, XCB_SHAPE_SO_SET, + XCB_SHAPE_SK_INPUT, XCB_CLIP_ORDERING_UNSORTED, + ps->overlay, 0, 0, 0, NULL); + if (e) { + log_fatal("Failed to set the input shape of overlay, giving up."); + exit(1); + } - // Listen to Expose events on the overlay - xcb_change_window_attributes(ps->c, ps->overlay, XCB_CW_EVENT_MASK, - (const uint32_t[]) { XCB_EVENT_MASK_EXPOSURE }); + // Listen to Expose events on the overlay + xcb_change_window_attributes(ps->c, ps->overlay, XCB_CW_EVENT_MASK, + (const uint32_t[]){XCB_EVENT_MASK_EXPOSURE}); - // Retrieve DamageNotify on root window if we are painting on an - // overlay - // root_damage = XDamageCreate(ps->dpy, root, XDamageReportNonEmpty); + // Retrieve DamageNotify on root window if we are painting on an + // overlay + // root_damage = XDamageCreate(ps->dpy, root, XDamageReportNonEmpty); - // Unmap overlay, firstly. But this typically does not work because - // the window isn't created yet. - // xcb_unmap_window(c, ps->overlay); - // XFlush(ps->dpy); - } else { - log_error("Cannot get X Composite overlay window. Falling " - "back to painting on root window."); - } - log_debug("overlay = %#010x", ps->overlay); + // Unmap overlay, firstly. But this typically does not work because + // the window isn't created yet. + // xcb_unmap_window(c, ps->overlay); + // XFlush(ps->dpy); + } else { + log_error("Cannot get X Composite overlay window. Falling " + "back to painting on root window."); + } + log_debug("overlay = %#010x", ps->overlay); - return ps->overlay; + return ps->overlay; } /** @@ -1978,299 +1867,293 @@ init_overlay(session_t *ps) { * * @return whether the operation succeeded or not */ -static bool -redir_start(session_t *ps) { - if (!ps->redirected) { - log_debug("Screen redirected."); +static bool redir_start(session_t *ps) { + if (!ps->redirected) { + log_debug("Screen redirected."); - // Map overlay window. Done firstly according to this: - // https://bugzilla.gnome.org/show_bug.cgi?id=597014 - if (ps->overlay) { - xcb_map_window(ps->c, ps->overlay); - } + // Map overlay window. Done firstly according to this: + // https://bugzilla.gnome.org/show_bug.cgi?id=597014 + if (ps->overlay) { + xcb_map_window(ps->c, ps->overlay); + } - xcb_composite_redirect_subwindows(ps->c, ps->root, XCB_COMPOSITE_REDIRECT_MANUAL); + xcb_composite_redirect_subwindows(ps->c, ps->root, + XCB_COMPOSITE_REDIRECT_MANUAL); - x_sync(ps->c); + x_sync(ps->c); - if (ps->o.experimental_backends) { - // Reinitialize win_data - ps->backend_data = backend_list[ps->o.backend]->init(ps); - ps->backend_data->ops = backend_list[ps->o.backend]; - if (!ps->backend_data) { - log_fatal("Failed to initialize backend, aborting..."); - ps->quit = true; - ev_break(ps->loop, EVBREAK_ALL); - return false; - } + if (ps->o.experimental_backends) { + // Reinitialize win_data + ps->backend_data = backend_list[ps->o.backend]->init(ps); + ps->backend_data->ops = backend_list[ps->o.backend]; + if (!ps->backend_data) { + log_fatal("Failed to initialize backend, aborting..."); + ps->quit = true; + ev_break(ps->loop, EVBREAK_ALL); + return false; + } - for (win *w = ps->list; w; w = w->next) { - if (w->a.map_state == XCB_MAP_STATE_VIEWABLE) { - auto pixmap = xcb_generate_id(ps->c); - 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); - if (w->shadow) { - w->shadow_image = - ps->backend_data->ops->render_shadow(ps->backend_data, w->widthb, - w->heightb, ps->gaussian_map, - ps->o.shadow_red, ps->o.shadow_green, - ps->o.shadow_blue, ps->o.shadow_opacity); - } - } - } - } + for (win *w = ps->list; w; w = w->next) { + if (w->a.map_state == XCB_MAP_STATE_VIEWABLE) { + auto pixmap = xcb_generate_id(ps->c); + 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); + if (w->shadow) { + w->shadow_image = ps->backend_data->ops->render_shadow( + ps->backend_data, w->widthb, w->heightb, + ps->gaussian_map, ps->o.shadow_red, + ps->o.shadow_green, ps->o.shadow_blue, + ps->o.shadow_opacity); + } + } + } + } + if (ps->o.experimental_backends) { + ps->ndamage = ps->backend_data->ops->max_buffer_age; + } else { + ps->ndamage = maximum_buffer_age(ps); + } + ps->damage_ring = ccalloc(ps->ndamage, region_t); + ps->damage = ps->damage_ring + ps->ndamage - 1; - if (ps->o.experimental_backends) { - ps->ndamage = ps->backend_data->ops->max_buffer_age; - } else { - ps->ndamage = maximum_buffer_age(ps); - } - ps->damage_ring = ccalloc(ps->ndamage, region_t); - ps->damage = ps->damage_ring + ps->ndamage - 1; + for (int i = 0; i < ps->ndamage; i++) { + pixman_region32_init(&ps->damage_ring[i]); + } - for (int i = 0; i < ps->ndamage; i++) { - pixman_region32_init(&ps->damage_ring[i]); - } + /* + // Unredirect GL context window as this may have an effect on VSync: + // < http://dri.freedesktop.org/wiki/CompositeSwap > + xcb_composite_unredirect_window(c, ps->reg_win, + XCB_COMPOSITE_REDIRECT_MANUAL); if (ps->o.paint_on_overlay && ps->overlay) + { xcb_composite_unredirect_window(c, ps->overlay, + XCB_COMPOSITE_REDIRECT_MANUAL); + } */ - /* - // Unredirect GL context window as this may have an effect on VSync: - // < http://dri.freedesktop.org/wiki/CompositeSwap > - xcb_composite_unredirect_window(c, ps->reg_win, XCB_COMPOSITE_REDIRECT_MANUAL); - if (ps->o.paint_on_overlay && ps->overlay) { - xcb_composite_unredirect_window(c, ps->overlay, - XCB_COMPOSITE_REDIRECT_MANUAL); - } */ + // Must call XSync() here + x_sync(ps->c); - // Must call XSync() here - x_sync(ps->c); + ps->redirected = true; - ps->redirected = true; + root_damaged(ps); - root_damaged(ps); - - // Repaint the whole screen - force_repaint(ps); - } - return true; + // Repaint the whole screen + force_repaint(ps); + } + return true; } /** * Unredirect all windows. */ -static void -redir_stop(session_t *ps) { - if (ps->redirected) { - log_debug("Screen unredirected."); - // Destroy all Pictures as they expire once windows are unredirected - // If we don't destroy them here, looks like the resources are just - // kept inaccessible somehow - for (win *w = ps->list, *next; w; w = next) { - next = w->next; - // Wrapping up fading in progress - win_skip_fading(ps, &w); +static void redir_stop(session_t *ps) { + if (ps->redirected) { + log_debug("Screen unredirected."); + // Destroy all Pictures as they expire once windows are unredirected + // If we don't destroy them here, looks like the resources are just + // kept inaccessible somehow + for (win *w = ps->list, *next; w; w = next) { + next = w->next; + // Wrapping up fading in progress + win_skip_fading(ps, &w); - // `w` might be freed by win_check_fade_finished - if (!w) { - continue; - } - if (ps->o.experimental_backends) { - if (w->state == WSTATE_MAPPED) { - ps->backend_data->ops->release_image(ps->backend_data, w->win_image); - if (w->shadow_image) { - ps->backend_data->ops->release_image(ps->backend_data, w->shadow_image); - } - w->win_image = NULL; - w->shadow_image = NULL; - } else { - assert(!w->win_image); - assert(!w->shadow_image); - } - if (ps->root_image) { - ps->backend_data->ops->release_image(ps->backend_data, ps->root_image); - ps->root_image = NULL; - } - } else { - free_paint(ps, &w->paint); - } - } + // `w` might be freed by win_check_fade_finished + if (!w) { + continue; + } + if (ps->o.experimental_backends) { + if (w->state == WSTATE_MAPPED) { + ps->backend_data->ops->release_image( + ps->backend_data, w->win_image); + if (w->shadow_image) { + ps->backend_data->ops->release_image( + ps->backend_data, w->shadow_image); + } + w->win_image = NULL; + w->shadow_image = NULL; + } else { + assert(!w->win_image); + assert(!w->shadow_image); + } + if (ps->root_image) { + ps->backend_data->ops->release_image( + ps->backend_data, ps->root_image); + ps->root_image = NULL; + } + } else { + free_paint(ps, &w->paint); + } + } - xcb_composite_unredirect_subwindows(ps->c, ps->root, XCB_COMPOSITE_REDIRECT_MANUAL); - // Unmap overlay window - if (ps->overlay) - xcb_unmap_window(ps->c, ps->overlay); + xcb_composite_unredirect_subwindows(ps->c, ps->root, + XCB_COMPOSITE_REDIRECT_MANUAL); + // Unmap overlay window + if (ps->overlay) + xcb_unmap_window(ps->c, ps->overlay); - if (ps->o.experimental_backends) { - // deinit backend - ps->backend_data->ops->deinit(ps->backend_data); - ps->backend_data = NULL; - } + if (ps->o.experimental_backends) { + // deinit backend + ps->backend_data->ops->deinit(ps->backend_data); + ps->backend_data = NULL; + } - // Free the damage ring - for (int i = 0; i < ps->ndamage; ++i) { - pixman_region32_fini(&ps->damage_ring[i]); - } - ps->ndamage = 0; - free(ps->damage_ring); - ps->damage_ring = ps->damage = NULL; + // Free the damage ring + for (int i = 0; i < ps->ndamage; ++i) { + pixman_region32_fini(&ps->damage_ring[i]); + } + ps->ndamage = 0; + free(ps->damage_ring); + ps->damage_ring = ps->damage = NULL; - // Must call XSync() here - x_sync(ps->c); + // Must call XSync() here + x_sync(ps->c); - ps->redirected = false; - } + ps->redirected = false; + } } // Handle queued events before we go to sleep -static void -handle_queued_x_events(EV_P_ ev_prepare *w, int revents) { - session_t *ps = session_ptr(w, event_check); - xcb_generic_event_t *ev; - while ((ev = xcb_poll_for_queued_event(ps->c))) { - ev_handle(ps, ev); - free(ev); - }; - // Flush because if we go into sleep when there is still - // requests in the outgoing buffer, they will not be sent - // for an indefinite amount of time. - // Use XFlush here too, we might still use some Xlib functions - // because OpenGL. - XFlush(ps->dpy); - xcb_flush(ps->c); - int err = xcb_connection_has_error(ps->c); - if (err) { - log_fatal("X11 server connection broke (error %d)", err); - exit(1); - } +static void handle_queued_x_events(EV_P_ ev_prepare *w, int revents) { + session_t *ps = session_ptr(w, event_check); + xcb_generic_event_t *ev; + while ((ev = xcb_poll_for_queued_event(ps->c))) { + ev_handle(ps, ev); + free(ev); + }; + // Flush because if we go into sleep when there is still + // requests in the outgoing buffer, they will not be sent + // for an indefinite amount of time. + // Use XFlush here too, we might still use some Xlib functions + // because OpenGL. + XFlush(ps->dpy); + xcb_flush(ps->c); + int err = xcb_connection_has_error(ps->c); + if (err) { + log_fatal("X11 server connection broke (error %d)", err); + exit(1); + } } /** * Unredirection timeout callback. */ -static void -tmout_unredir_callback(EV_P_ ev_timer *w, int revents) { - session_t *ps = session_ptr(w, unredir_timer); - ps->tmout_unredir_hit = true; - queue_redraw(ps); +static void tmout_unredir_callback(EV_P_ ev_timer *w, int revents) { + session_t *ps = session_ptr(w, unredir_timer); + ps->tmout_unredir_hit = true; + queue_redraw(ps); } -static void -fade_timer_callback(EV_P_ ev_timer *w, int revents) { - session_t *ps = session_ptr(w, fade_timer); - queue_redraw(ps); +static void fade_timer_callback(EV_P_ ev_timer *w, int revents) { + session_t *ps = session_ptr(w, fade_timer); + queue_redraw(ps); } -static void -_draw_callback(EV_P_ session_t *ps, int revents) { - if (ps->o.benchmark) { - if (ps->o.benchmark_wid) { - win *wi = find_win(ps, ps->o.benchmark_wid); - if (!wi) { - log_fatal("Couldn't find specified benchmark window."); - exit(1); - } - add_damage_from_win(ps, wi); - } - else { - force_repaint(ps); - } - } +static void _draw_callback(EV_P_ session_t *ps, int revents) { + if (ps->o.benchmark) { + if (ps->o.benchmark_wid) { + win *wi = find_win(ps, ps->o.benchmark_wid); + if (!wi) { + log_fatal("Couldn't find specified benchmark window."); + exit(1); + } + add_damage_from_win(ps, wi); + } else { + force_repaint(ps); + } + } - bool fade_running = false; - win *t = paint_preprocess(ps, &fade_running); - ps->tmout_unredir_hit = false; + bool fade_running = false; + win *t = paint_preprocess(ps, &fade_running); + ps->tmout_unredir_hit = false; - // Start/stop fade timer depends on whether window are fading - if (!fade_running && ev_is_active(&ps->fade_timer)) - ev_timer_stop(ps->loop, &ps->fade_timer); - else if (fade_running && !ev_is_active(&ps->fade_timer)) { - ev_timer_set(&ps->fade_timer, fade_timeout(ps), 0); - ev_timer_start(ps->loop, &ps->fade_timer); - } + // Start/stop fade timer depends on whether window are fading + if (!fade_running && ev_is_active(&ps->fade_timer)) + ev_timer_stop(ps->loop, &ps->fade_timer); + else if (fade_running && !ev_is_active(&ps->fade_timer)) { + ev_timer_set(&ps->fade_timer, fade_timeout(ps), 0); + ev_timer_start(ps->loop, &ps->fade_timer); + } - // If the screen is unredirected, free all_damage to stop painting - if (ps->redirected && ps->o.stoppaint_force != ON) { - static int paint = 0; - if (ps->o.experimental_backends) { - paint_all_new(ps, t, false); - } else { - paint_all(ps, t, false); - } + // If the screen is unredirected, free all_damage to stop painting + if (ps->redirected && ps->o.stoppaint_force != ON) { + static int paint = 0; + if (ps->o.experimental_backends) { + paint_all_new(ps, t, false); + } else { + paint_all(ps, t, false); + } - paint++; - if (ps->o.benchmark && paint >= ps->o.benchmark) - exit(0); - } + paint++; + if (ps->o.benchmark && paint >= ps->o.benchmark) + exit(0); + } - if (!fade_running) - ps->fade_time = 0L; + if (!fade_running) + ps->fade_time = 0L; - ps->redraw_needed = false; + ps->redraw_needed = false; } -static void -draw_callback(EV_P_ ev_idle *w, int revents) { - // This function is not used if we are using --swopti - session_t *ps = session_ptr(w, draw_idle); +static void draw_callback(EV_P_ ev_idle *w, int revents) { + // This function is not used if we are using --swopti + session_t *ps = session_ptr(w, draw_idle); - _draw_callback(EV_A_ ps, revents); + _draw_callback(EV_A_ ps, revents); - // Don't do painting non-stop unless we are in benchmark mode - if (!ps->o.benchmark) - ev_idle_stop(ps->loop, &ps->draw_idle); + // Don't do painting non-stop unless we are in benchmark mode + if (!ps->o.benchmark) + ev_idle_stop(ps->loop, &ps->draw_idle); } -static void -delayed_draw_timer_callback(EV_P_ ev_timer *w, int revents) { - session_t *ps = session_ptr(w, delayed_draw_timer); - _draw_callback(EV_A_ ps, revents); +static void delayed_draw_timer_callback(EV_P_ ev_timer *w, int revents) { + session_t *ps = session_ptr(w, delayed_draw_timer); + _draw_callback(EV_A_ ps, revents); - // We might have stopped the ev_idle in delayed_draw_callback, - // so we restart it if we are in benchmark mode - if (ps->o.benchmark) - ev_idle_start(EV_A_ &ps->draw_idle); + // We might have stopped the ev_idle in delayed_draw_callback, + // so we restart it if we are in benchmark mode + if (ps->o.benchmark) + ev_idle_start(EV_A_ & ps->draw_idle); } -static void -delayed_draw_callback(EV_P_ ev_idle *w, int revents) { - // This function is only used if we are using --swopti - session_t *ps = session_ptr(w, draw_idle); - assert(ps->redraw_needed); - assert(!ev_is_active(&ps->delayed_draw_timer)); +static void delayed_draw_callback(EV_P_ ev_idle *w, int revents) { + // This function is only used if we are using --swopti + session_t *ps = session_ptr(w, draw_idle); + assert(ps->redraw_needed); + assert(!ev_is_active(&ps->delayed_draw_timer)); - double delay = swopti_handle_timeout(ps); - if (delay < 1e-6) { - if (!ps->o.benchmark) { - ev_idle_stop(ps->loop, &ps->draw_idle); - } - return _draw_callback(EV_A_ ps, revents); - } + double delay = swopti_handle_timeout(ps); + if (delay < 1e-6) { + if (!ps->o.benchmark) { + ev_idle_stop(ps->loop, &ps->draw_idle); + } + return _draw_callback(EV_A_ ps, revents); + } - // This is a little bit hacky. When we get to this point in code, we need - // to update the screen , but we will only be updating after a delay, So - // we want to stop the ev_idle, so this callback doesn't get call repeatedly - // during the delay, we also want queue_redraw to not restart the ev_idle. - // So we stop ev_idle and leave ps->redraw_needed to be true. (effectively, - // ps->redraw_needed means if redraw is needed or if draw is in progress). - // - // We do this anyway even if we are in benchmark mode. That means we will - // have to restart draw_idle after the draw actually happened when we are in - // benchmark mode. - ev_idle_stop(ps->loop, &ps->draw_idle); + // This is a little bit hacky. When we get to this point in code, we need + // to update the screen , but we will only be updating after a delay, So + // we want to stop the ev_idle, so this callback doesn't get call repeatedly + // during the delay, we also want queue_redraw to not restart the ev_idle. + // So we stop ev_idle and leave ps->redraw_needed to be true. (effectively, + // ps->redraw_needed means if redraw is needed or if draw is in progress). + // + // We do this anyway even if we are in benchmark mode. That means we will + // have to restart draw_idle after the draw actually happened when we are in + // benchmark mode. + ev_idle_stop(ps->loop, &ps->draw_idle); - ev_timer_set(&ps->delayed_draw_timer, delay, 0); - ev_timer_start(ps->loop, &ps->delayed_draw_timer); + ev_timer_set(&ps->delayed_draw_timer, delay, 0); + ev_timer_start(ps->loop, &ps->delayed_draw_timer); } -static void -x_event_callback(EV_P_ ev_io *w, int revents) { - session_t *ps = (session_t *)w; - xcb_generic_event_t *ev = xcb_poll_for_event(ps->c); - if (ev) { - ev_handle(ps, ev); - free(ev); - } +static void x_event_callback(EV_P_ ev_io *w, int revents) { + session_t *ps = (session_t *)w; + xcb_generic_event_t *ev = xcb_poll_for_event(ps->c); + if (ev) { + ev_handle(ps, ev); + free(ev); + } } /** @@ -2278,19 +2161,17 @@ x_event_callback(EV_P_ ev_io *w, int revents) { * * This will result in compton resetting itself after next paint. */ -static void -reset_enable(EV_P_ ev_signal *w, int revents) { - session_t *ps = session_ptr(w, usr1_signal); - log_info("compton is resetting..."); - ev_break(ps->loop, EVBREAK_ALL); +static void reset_enable(EV_P_ ev_signal *w, int revents) { + session_t *ps = session_ptr(w, usr1_signal); + log_info("compton is resetting..."); + ev_break(ps->loop, EVBREAK_ALL); } -static void -exit_enable(EV_P_ ev_signal *w, int revents) { - session_t *ps = session_ptr(w, int_signal); - log_info("compton is quitting..."); - ps->quit = true; - ev_break(ps->loop, EVBREAK_ALL); +static void exit_enable(EV_P_ ev_signal *w, int revents) { + session_t *ps = session_ptr(w, int_signal); + log_info("compton is quitting..."); + ps->quit = true; + ev_break(ps->loop, EVBREAK_ALL); } /** @@ -2303,569 +2184,577 @@ exit_enable(EV_P_ ev_signal *w, int revents) { * @param all_xerros whether we should report all X errors * @param fork whether we will fork after initialization */ -static session_t * -session_init(int argc, char **argv, Display *dpy, const char *config_file, - bool all_xerrors, bool fork) { - static const session_t s_def = { - .backend_data = NULL, - .dpy = NULL, - .scr = 0, - .c = NULL, - .vis = 0, - .depth = 0, - .root = XCB_NONE, - .root_height = 0, - .root_width = 0, - // .root_damage = XCB_NONE, - .overlay = XCB_NONE, - .root_tile_fill = false, - .root_tile_paint = PAINT_INIT, - .tgt_picture = XCB_NONE, - .tgt_buffer = PAINT_INIT, - .reg_win = XCB_NONE, +static session_t *session_init(int argc, char **argv, Display *dpy, + const char *config_file, bool all_xerrors, bool fork) { + static const session_t s_def = { + .backend_data = NULL, + .dpy = NULL, + .scr = 0, + .c = NULL, + .vis = 0, + .depth = 0, + .root = XCB_NONE, + .root_height = 0, + .root_width = 0, + // .root_damage = XCB_NONE, + .overlay = XCB_NONE, + .root_tile_fill = false, + .root_tile_paint = PAINT_INIT, + .tgt_picture = XCB_NONE, + .tgt_buffer = PAINT_INIT, + .reg_win = XCB_NONE, #ifdef CONFIG_OPENGL - .glx_prog_win = GLX_PROG_MAIN_INIT, + .glx_prog_win = GLX_PROG_MAIN_INIT, #endif - .o = { - .backend = BKEND_XRENDER, - .glx_no_stencil = false, - .mark_wmwin_focused = false, - .mark_ovredir_focused = false, - .detect_rounded_corners = false, - .resize_damage = 0, - .unredir_if_possible = false, - .unredir_if_possible_blacklist = NULL, - .unredir_if_possible_delay = 0, - .redirected_force = UNSET, - .stoppaint_force = UNSET, - .dbus = false, - .benchmark = 0, - .benchmark_wid = XCB_NONE, - .logpath = NULL, + .o = + { + .backend = BKEND_XRENDER, + .glx_no_stencil = false, + .mark_wmwin_focused = false, + .mark_ovredir_focused = false, + .detect_rounded_corners = false, + .resize_damage = 0, + .unredir_if_possible = false, + .unredir_if_possible_blacklist = NULL, + .unredir_if_possible_delay = 0, + .redirected_force = UNSET, + .stoppaint_force = UNSET, + .dbus = false, + .benchmark = 0, + .benchmark_wid = XCB_NONE, + .logpath = NULL, - .refresh_rate = 0, - .sw_opti = false, - .vsync = VSYNC_NONE, - .vsync_aggressive = false, + .refresh_rate = 0, + .sw_opti = false, + .vsync = VSYNC_NONE, + .vsync_aggressive = false, - .shadow_red = 0.0, - .shadow_green = 0.0, - .shadow_blue = 0.0, - .shadow_radius = 18, - .shadow_offset_x = -15, - .shadow_offset_y = -15, - .shadow_opacity = .75, - .shadow_blacklist = NULL, - .shadow_ignore_shaped = false, - .respect_prop_shadow = false, - .xinerama_shadow_crop = false, + .shadow_red = 0.0, + .shadow_green = 0.0, + .shadow_blue = 0.0, + .shadow_radius = 18, + .shadow_offset_x = -15, + .shadow_offset_y = -15, + .shadow_opacity = .75, + .shadow_blacklist = NULL, + .shadow_ignore_shaped = false, + .respect_prop_shadow = false, + .xinerama_shadow_crop = false, - .fade_in_step = 0.028, - .fade_out_step = 0.03, - .fade_delta = 10, - .no_fading_openclose = false, - .no_fading_destroyed_argb = false, - .fade_blacklist = NULL, + .fade_in_step = 0.028, + .fade_out_step = 0.03, + .fade_delta = 10, + .no_fading_openclose = false, + .no_fading_destroyed_argb = false, + .fade_blacklist = NULL, - .inactive_opacity = 1.0, - .inactive_opacity_override = false, - .active_opacity = 1.0, - .frame_opacity = 1.0, - .detect_client_opacity = false, + .inactive_opacity = 1.0, + .inactive_opacity_override = false, + .active_opacity = 1.0, + .frame_opacity = 1.0, + .detect_client_opacity = false, - .blur_background = false, - .blur_background_frame = false, - .blur_background_fixed = false, - .blur_background_blacklist = NULL, - .blur_kerns = { NULL }, - .inactive_dim = 0.0, - .inactive_dim_fixed = false, - .invert_color_list = NULL, - .opacity_rules = NULL, + .blur_background = false, + .blur_background_frame = false, + .blur_background_fixed = false, + .blur_background_blacklist = NULL, + .blur_kerns = {NULL}, + .inactive_dim = 0.0, + .inactive_dim_fixed = false, + .invert_color_list = NULL, + .opacity_rules = NULL, - .use_ewmh_active_win = false, - .focus_blacklist = NULL, - .detect_transient = false, - .detect_client_leader = false, + .use_ewmh_active_win = false, + .focus_blacklist = NULL, + .detect_transient = false, + .detect_client_leader = false, - .track_focus = false, - .track_wdata = false, - .track_leader = false, - }, + .track_focus = false, + .track_wdata = false, + .track_leader = false, + }, - .time_start = { 0, 0 }, - .redirected = false, - .alpha_picts = NULL, - .fade_time = 0L, - .ignore_head = NULL, - .ignore_tail = NULL, - .quit = false, + .time_start = {0, 0}, + .redirected = false, + .alpha_picts = NULL, + .fade_time = 0L, + .ignore_head = NULL, + .ignore_tail = NULL, + .quit = false, - .expose_rects = NULL, - .size_expose = 0, - .n_expose = 0, + .expose_rects = NULL, + .size_expose = 0, + .n_expose = 0, - .list = NULL, - .active_win = NULL, - .active_leader = XCB_NONE, + .list = NULL, + .active_win = NULL, + .active_leader = XCB_NONE, - .black_picture = XCB_NONE, - .cshadow_picture = XCB_NONE, - .white_picture = XCB_NONE, - .gaussian_map = NULL, + .black_picture = XCB_NONE, + .cshadow_picture = XCB_NONE, + .white_picture = XCB_NONE, + .gaussian_map = NULL, - .refresh_rate = 0, - .refresh_intv = 0UL, - .paint_tm_offset = 0L, + .refresh_rate = 0, + .refresh_intv = 0UL, + .paint_tm_offset = 0L, #ifdef CONFIG_VSYNC_DRM - .drm_fd = -1, + .drm_fd = -1, #endif - .xfixes_event = 0, - .xfixes_error = 0, - .damage_event = 0, - .damage_error = 0, - .render_event = 0, - .render_error = 0, - .composite_event = 0, - .composite_error = 0, - .composite_opcode = 0, - .shape_exists = false, - .shape_event = 0, - .shape_error = 0, - .randr_exists = 0, - .randr_event = 0, - .randr_error = 0, + .xfixes_event = 0, + .xfixes_error = 0, + .damage_event = 0, + .damage_error = 0, + .render_event = 0, + .render_error = 0, + .composite_event = 0, + .composite_error = 0, + .composite_opcode = 0, + .shape_exists = false, + .shape_event = 0, + .shape_error = 0, + .randr_exists = 0, + .randr_event = 0, + .randr_error = 0, #ifdef CONFIG_OPENGL - .glx_exists = false, - .glx_event = 0, - .glx_error = 0, + .glx_exists = false, + .glx_event = 0, + .glx_error = 0, #endif - .xrfilter_convolution_exists = false, + .xrfilter_convolution_exists = false, - .atom_opacity = XCB_NONE, - .atom_frame_extents = XCB_NONE, - .atom_client = XCB_NONE, - .atom_name = XCB_NONE, - .atom_name_ewmh = XCB_NONE, - .atom_class = XCB_NONE, - .atom_role = XCB_NONE, - .atom_transient = XCB_NONE, - .atom_ewmh_active_win = XCB_NONE, - .atom_compton_shadow = XCB_NONE, - .atom_win_type = XCB_NONE, - .atoms_wintypes = { 0 }, - .track_atom_lst = NULL, + .atom_opacity = XCB_NONE, + .atom_frame_extents = XCB_NONE, + .atom_client = XCB_NONE, + .atom_name = XCB_NONE, + .atom_name_ewmh = XCB_NONE, + .atom_class = XCB_NONE, + .atom_role = XCB_NONE, + .atom_transient = XCB_NONE, + .atom_ewmh_active_win = XCB_NONE, + .atom_compton_shadow = XCB_NONE, + .atom_win_type = XCB_NONE, + .atoms_wintypes = {0}, + .track_atom_lst = NULL, #ifdef CONFIG_DBUS - .dbus_data = NULL, + .dbus_data = NULL, #endif - }; + }; - log_init_tls(); - auto stderr_logger = stderr_logger_new(); - if (stderr_logger) { - // stderr logger might fail to create if we are already - // daemonized. - log_add_target_tls(stderr_logger); - } + log_init_tls(); + auto stderr_logger = stderr_logger_new(); + if (stderr_logger) { + // stderr logger might fail to create if we are already + // daemonized. + log_add_target_tls(stderr_logger); + } - // Allocate a session and copy default values into it - session_t *ps = cmalloc(session_t); - *ps = s_def; - ps->loop = EV_DEFAULT; - pixman_region32_init(&ps->screen_reg); + // Allocate a session and copy default values into it + session_t *ps = cmalloc(session_t); + *ps = s_def; + ps->loop = EV_DEFAULT; + pixman_region32_init(&ps->screen_reg); - ps->ignore_tail = &ps->ignore_head; - gettimeofday(&ps->time_start, NULL); + ps->ignore_tail = &ps->ignore_head; + gettimeofday(&ps->time_start, NULL); - ps->o.show_all_xerrors = all_xerrors; + ps->o.show_all_xerrors = all_xerrors; - // Use the same Display across reset, primarily for resource leak checking - ps->dpy = dpy; - ps->c = XGetXCBConnection(ps->dpy); + // Use the same Display across reset, primarily for resource leak checking + ps->dpy = dpy; + ps->c = XGetXCBConnection(ps->dpy); - const xcb_query_extension_reply_t *ext_info; + const xcb_query_extension_reply_t *ext_info; - XSetErrorHandler(xerror); + XSetErrorHandler(xerror); - ps->scr = DefaultScreen(ps->dpy); - ps->root = RootWindow(ps->dpy, ps->scr); + ps->scr = DefaultScreen(ps->dpy); + ps->root = RootWindow(ps->dpy, ps->scr); - ps->vis = XVisualIDFromVisual(DefaultVisual(ps->dpy, ps->scr)); - ps->depth = DefaultDepth(ps->dpy, ps->scr); + ps->vis = XVisualIDFromVisual(DefaultVisual(ps->dpy, ps->scr)); + ps->depth = DefaultDepth(ps->dpy, ps->scr); - // Start listening to events on root earlier to catch all possible - // root geometry changes - auto e = xcb_request_check( - ps->c, xcb_change_window_attributes_checked( - ps->c, ps->root, XCB_CW_EVENT_MASK, - (const uint32_t[]){XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | - XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | - XCB_EVENT_MASK_PROPERTY_CHANGE})); - if (e) { - log_error("Failed to setup root window event mask"); - free(e); - } + // Start listening to events on root earlier to catch all possible + // root geometry changes + auto e = xcb_request_check( + ps->c, xcb_change_window_attributes_checked( + ps->c, ps->root, XCB_CW_EVENT_MASK, + (const uint32_t[]){XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | + XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | + XCB_EVENT_MASK_PROPERTY_CHANGE})); + if (e) { + log_error("Failed to setup root window event mask"); + free(e); + } - ps->root_width = DisplayWidth(ps->dpy, ps->scr); - ps->root_height = DisplayHeight(ps->dpy, ps->scr); + ps->root_width = DisplayWidth(ps->dpy, ps->scr); + ps->root_height = DisplayHeight(ps->dpy, ps->scr); - xcb_prefetch_extension_data(ps->c, &xcb_render_id); - xcb_prefetch_extension_data(ps->c, &xcb_composite_id); - xcb_prefetch_extension_data(ps->c, &xcb_damage_id); - xcb_prefetch_extension_data(ps->c, &xcb_shape_id); - xcb_prefetch_extension_data(ps->c, &xcb_xfixes_id); - xcb_prefetch_extension_data(ps->c, &xcb_randr_id); - xcb_prefetch_extension_data(ps->c, &xcb_xinerama_id); - xcb_prefetch_extension_data(ps->c, &xcb_present_id); - xcb_prefetch_extension_data(ps->c, &xcb_sync_id); + xcb_prefetch_extension_data(ps->c, &xcb_render_id); + xcb_prefetch_extension_data(ps->c, &xcb_composite_id); + xcb_prefetch_extension_data(ps->c, &xcb_damage_id); + xcb_prefetch_extension_data(ps->c, &xcb_shape_id); + xcb_prefetch_extension_data(ps->c, &xcb_xfixes_id); + xcb_prefetch_extension_data(ps->c, &xcb_randr_id); + xcb_prefetch_extension_data(ps->c, &xcb_xinerama_id); + xcb_prefetch_extension_data(ps->c, &xcb_present_id); + xcb_prefetch_extension_data(ps->c, &xcb_sync_id); - ext_info = xcb_get_extension_data(ps->c, &xcb_render_id); - if (!ext_info || !ext_info->present) { - log_fatal("No render extension"); - exit(1); - } - ps->render_event = ext_info->first_event; - ps->render_error = ext_info->first_error; + ext_info = xcb_get_extension_data(ps->c, &xcb_render_id); + if (!ext_info || !ext_info->present) { + log_fatal("No render extension"); + exit(1); + } + ps->render_event = ext_info->first_event; + ps->render_error = ext_info->first_error; - ext_info = xcb_get_extension_data(ps->c, &xcb_composite_id); - if (!ext_info || !ext_info->present) { - log_fatal("No composite extension"); - exit(1); - } - ps->composite_opcode = ext_info->major_opcode; - ps->composite_event = ext_info->first_event; - ps->composite_error = ext_info->first_error; + ext_info = xcb_get_extension_data(ps->c, &xcb_composite_id); + if (!ext_info || !ext_info->present) { + log_fatal("No composite extension"); + exit(1); + } + ps->composite_opcode = ext_info->major_opcode; + ps->composite_event = ext_info->first_event; + ps->composite_error = ext_info->first_error; - { - xcb_composite_query_version_reply_t *reply = - xcb_composite_query_version_reply(ps->c, - xcb_composite_query_version(ps->c, XCB_COMPOSITE_MAJOR_VERSION, XCB_COMPOSITE_MINOR_VERSION), - NULL); + { + xcb_composite_query_version_reply_t *reply = xcb_composite_query_version_reply( + ps->c, + xcb_composite_query_version(ps->c, XCB_COMPOSITE_MAJOR_VERSION, + XCB_COMPOSITE_MINOR_VERSION), + NULL); - if (!reply || (reply->major_version == 0 && reply->minor_version < 2)) { - log_fatal("Your X server doesn't have Composite >= 0.2 support, compton cannot run."); - exit(1); - } - free(reply); - } + if (!reply || (reply->major_version == 0 && reply->minor_version < 2)) { + log_fatal("Your X server doesn't have Composite >= 0.2 support, " + "compton cannot run."); + exit(1); + } + free(reply); + } - ext_info = xcb_get_extension_data(ps->c, &xcb_damage_id); - if (!ext_info || !ext_info->present) { - log_fatal("No damage extension"); - exit(1); - } - ps->damage_event = ext_info->first_event; - ps->damage_error = ext_info->first_error; - xcb_discard_reply(ps->c, - xcb_damage_query_version(ps->c, XCB_DAMAGE_MAJOR_VERSION, XCB_DAMAGE_MINOR_VERSION).sequence); + ext_info = xcb_get_extension_data(ps->c, &xcb_damage_id); + if (!ext_info || !ext_info->present) { + log_fatal("No damage extension"); + exit(1); + } + ps->damage_event = ext_info->first_event; + ps->damage_error = ext_info->first_error; + xcb_discard_reply(ps->c, xcb_damage_query_version(ps->c, XCB_DAMAGE_MAJOR_VERSION, + XCB_DAMAGE_MINOR_VERSION) + .sequence); - ext_info = xcb_get_extension_data(ps->c, &xcb_xfixes_id); - if (!ext_info || !ext_info->present) { - log_fatal("No XFixes extension"); - exit(1); - } - ps->xfixes_event = ext_info->first_event; - ps->xfixes_error = ext_info->first_error; - xcb_discard_reply(ps->c, - xcb_xfixes_query_version(ps->c, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION).sequence); + ext_info = xcb_get_extension_data(ps->c, &xcb_xfixes_id); + if (!ext_info || !ext_info->present) { + log_fatal("No XFixes extension"); + exit(1); + } + ps->xfixes_event = ext_info->first_event; + ps->xfixes_error = ext_info->first_error; + xcb_discard_reply(ps->c, xcb_xfixes_query_version(ps->c, XCB_XFIXES_MAJOR_VERSION, + XCB_XFIXES_MINOR_VERSION) + .sequence); - // Parse configuration file - win_option_mask_t winopt_mask[NUM_WINTYPES] = {{0}}; - bool shadow_enabled = false, fading_enable = false, hasneg = false; - char *config_file_to_free = NULL; - config_file = config_file_to_free = - parse_config(&ps->o, config_file, &shadow_enabled, - &fading_enable, &hasneg, winopt_mask); + // Parse configuration file + win_option_mask_t winopt_mask[NUM_WINTYPES] = {{0}}; + bool shadow_enabled = false, fading_enable = false, hasneg = false; + char *config_file_to_free = NULL; + config_file = config_file_to_free = parse_config( + &ps->o, config_file, &shadow_enabled, &fading_enable, &hasneg, winopt_mask); - if (IS_ERR(config_file_to_free)) { - return NULL; - } + if (IS_ERR(config_file_to_free)) { + return NULL; + } - // Parse all of the rest command line options - get_cfg(&ps->o, argc, argv, shadow_enabled, fading_enable, hasneg, winopt_mask); + // Parse all of the rest command line options + get_cfg(&ps->o, argc, argv, shadow_enabled, fading_enable, hasneg, winopt_mask); - if (ps->o.logpath) { - auto l = file_logger_new(ps->o.logpath); - if (l) { - log_info("Switching to log file: %s", ps->o.logpath); - if (stderr_logger) { - log_remove_target_tls(stderr_logger); - stderr_logger = NULL; - } - log_add_target_tls(l); - stderr_logger = NULL; - } else { - log_error("Failed to setup log file %s, I will keep using stderr", ps->o.logpath); - } - } + if (ps->o.logpath) { + auto l = file_logger_new(ps->o.logpath); + if (l) { + log_info("Switching to log file: %s", ps->o.logpath); + if (stderr_logger) { + log_remove_target_tls(stderr_logger); + stderr_logger = NULL; + } + log_add_target_tls(l); + stderr_logger = NULL; + } else { + log_error("Failed to setup log file %s, I will keep using stderr", + ps->o.logpath); + } + } - // Get needed atoms for c2 condition lists - if (!(c2_list_postprocess(ps, ps->o.unredir_if_possible_blacklist) && - c2_list_postprocess(ps, ps->o.paint_blacklist) && - c2_list_postprocess(ps, ps->o.shadow_blacklist) && - c2_list_postprocess(ps, ps->o.fade_blacklist) && - c2_list_postprocess(ps, ps->o.blur_background_blacklist) && - c2_list_postprocess(ps, ps->o.invert_color_list) && - c2_list_postprocess(ps, ps->o.opacity_rules) && - c2_list_postprocess(ps, ps->o.focus_blacklist))) { - log_error("Post-processing of conditionals failed, some of your rules might not work"); - } + // Get needed atoms for c2 condition lists + if (!(c2_list_postprocess(ps, ps->o.unredir_if_possible_blacklist) && + c2_list_postprocess(ps, ps->o.paint_blacklist) && + c2_list_postprocess(ps, ps->o.shadow_blacklist) && + c2_list_postprocess(ps, ps->o.fade_blacklist) && + c2_list_postprocess(ps, ps->o.blur_background_blacklist) && + c2_list_postprocess(ps, ps->o.invert_color_list) && + c2_list_postprocess(ps, ps->o.opacity_rules) && + c2_list_postprocess(ps, ps->o.focus_blacklist))) { + log_error("Post-processing of conditionals failed, some of your rules " + "might not work"); + } - ps->gaussian_map = gaussian_kernel(ps->o.shadow_radius); - sum_kernel_preprocess(ps->gaussian_map); + ps->gaussian_map = gaussian_kernel(ps->o.shadow_radius); + sum_kernel_preprocess(ps->gaussian_map); - rebuild_shadow_exclude_reg(ps); + rebuild_shadow_exclude_reg(ps); - // Query X Shape - ext_info = xcb_get_extension_data(ps->c, &xcb_shape_id); - if (ext_info && ext_info->present) { - ps->shape_event = ext_info->first_event; - ps->shape_error = ext_info->first_error; - ps->shape_exists = true; - } + // Query X Shape + ext_info = xcb_get_extension_data(ps->c, &xcb_shape_id); + if (ext_info && ext_info->present) { + ps->shape_event = ext_info->first_event; + ps->shape_error = ext_info->first_error; + ps->shape_exists = true; + } - ext_info = xcb_get_extension_data(ps->c, &xcb_randr_id); - if (ext_info && ext_info->present) { - ps->randr_exists = true; - ps->randr_event = ext_info->first_event; - ps->randr_error = ext_info->first_error; - } + ext_info = xcb_get_extension_data(ps->c, &xcb_randr_id); + if (ext_info && ext_info->present) { + ps->randr_exists = true; + ps->randr_event = ext_info->first_event; + ps->randr_error = ext_info->first_error; + } - ext_info = xcb_get_extension_data(ps->c, &xcb_present_id); - if (ext_info && ext_info->present) { - auto r = - xcb_present_query_version_reply(ps->c, - xcb_present_query_version(ps->c, - XCB_PRESENT_MAJOR_VERSION, - XCB_PRESENT_MINOR_VERSION), - NULL); - if (r) { - ps->present_exists = true; - free(r); - } - } + ext_info = xcb_get_extension_data(ps->c, &xcb_present_id); + if (ext_info && ext_info->present) { + auto r = xcb_present_query_version_reply( + ps->c, + xcb_present_query_version(ps->c, XCB_PRESENT_MAJOR_VERSION, + XCB_PRESENT_MINOR_VERSION), + NULL); + if (r) { + ps->present_exists = true; + free(r); + } + } - // Query X Sync - ext_info = xcb_get_extension_data(ps->c, &xcb_sync_id); - if (ext_info && ext_info->present) { - ps->xsync_error = ext_info->first_error; - ps->xsync_event = ext_info->first_event; - // Need X Sync 3.1 for fences - auto r = xcb_sync_initialize_reply(ps->c, - xcb_sync_initialize(ps->c, - XCB_SYNC_MAJOR_VERSION, - XCB_SYNC_MINOR_VERSION), - NULL); - if (r && (r->major_version > 3 || - (r->major_version == 3 && r->minor_version >= 1))) { - ps->xsync_exists = true; - free(r); - } - } + // Query X Sync + ext_info = xcb_get_extension_data(ps->c, &xcb_sync_id); + if (ext_info && ext_info->present) { + ps->xsync_error = ext_info->first_error; + ps->xsync_event = ext_info->first_event; + // Need X Sync 3.1 for fences + auto r = xcb_sync_initialize_reply( + ps->c, + xcb_sync_initialize(ps->c, XCB_SYNC_MAJOR_VERSION, XCB_SYNC_MINOR_VERSION), + NULL); + if (r && (r->major_version > 3 || + (r->major_version == 3 && r->minor_version >= 1))) { + ps->xsync_exists = true; + free(r); + } + } - ps->sync_fence = XCB_NONE; - if (!ps->xsync_exists && ps->o.xrender_sync_fence) { - log_error("XSync extension not found. No XSync fence sync is " - "possible. (xrender-sync-fence can't be enabled)"); - ps->o.xrender_sync_fence = false; - } + ps->sync_fence = XCB_NONE; + if (!ps->xsync_exists && ps->o.xrender_sync_fence) { + log_error("XSync extension not found. No XSync fence sync is " + "possible. (xrender-sync-fence can't be enabled)"); + ps->o.xrender_sync_fence = false; + } - if (ps->o.xrender_sync_fence) { - ps->sync_fence = xcb_generate_id(ps->c); - e = xcb_request_check(ps->c, xcb_sync_create_fence(ps->c, ps->root, ps->sync_fence, 0)); - if (e) { - log_error("Failed to create a XSync fence. xrender-sync-fence will be disabled"); - ps->o.xrender_sync_fence = false; - ps->sync_fence = XCB_NONE; - free(e); - } - } + if (ps->o.xrender_sync_fence) { + ps->sync_fence = xcb_generate_id(ps->c); + e = xcb_request_check( + ps->c, xcb_sync_create_fence(ps->c, ps->root, ps->sync_fence, 0)); + if (e) { + log_error("Failed to create a XSync fence. xrender-sync-fence " + "will be disabled"); + ps->o.xrender_sync_fence = false; + ps->sync_fence = XCB_NONE; + free(e); + } + } - // Query X RandR - if ((ps->o.sw_opti && !ps->o.refresh_rate) || ps->o.xinerama_shadow_crop) { - if (!ps->randr_exists) { - log_fatal("No XRandR extension. sw-opti, refresh-rate or xinerama-shadow-crop " - "cannot be enabled."); - exit(1); - } - } + // Query X RandR + if ((ps->o.sw_opti && !ps->o.refresh_rate) || ps->o.xinerama_shadow_crop) { + if (!ps->randr_exists) { + log_fatal("No XRandR extension. sw-opti, refresh-rate or " + "xinerama-shadow-crop " + "cannot be enabled."); + exit(1); + } + } - // Query X Xinerama extension - if (ps->o.xinerama_shadow_crop) { - ext_info = xcb_get_extension_data(ps->c, &xcb_xinerama_id); - ps->xinerama_exists = ext_info && ext_info->present; - } + // Query X Xinerama extension + if (ps->o.xinerama_shadow_crop) { + ext_info = xcb_get_extension_data(ps->c, &xcb_xinerama_id); + ps->xinerama_exists = ext_info && ext_info->present; + } - rebuild_screen_reg(ps); + rebuild_screen_reg(ps); - // Overlay must be initialized before double buffer, and before creation - // of OpenGL context. - init_overlay(ps); + // Overlay must be initialized before double buffer, and before creation + // of OpenGL context. + init_overlay(ps); - // Initialize filters, must be preceded by OpenGL context creation - if (!ps->o.experimental_backends && !init_render(ps)) { - log_fatal("Failed to initialize the backend"); - exit(1); - } + // Initialize filters, must be preceded by OpenGL context creation + if (!ps->o.experimental_backends && !init_render(ps)) { + log_fatal("Failed to initialize the backend"); + exit(1); + } - if (ps->o.print_diagnostics) { - print_diagnostics(ps, config_file); - free(config_file_to_free); - exit(0); - } - free(config_file_to_free); + if (ps->o.print_diagnostics) { + print_diagnostics(ps, config_file); + free(config_file_to_free); + exit(0); + } + free(config_file_to_free); - if (bkend_use_glx(ps) && !ps->o.experimental_backends) { - auto glx_logger = glx_string_marker_logger_new(); - if (glx_logger) { - log_info("Enabling gl string marker"); - log_add_target_tls(glx_logger); - } - } + if (bkend_use_glx(ps) && !ps->o.experimental_backends) { + auto glx_logger = glx_string_marker_logger_new(); + if (glx_logger) { + log_info("Enabling gl string marker"); + log_add_target_tls(glx_logger); + } + } - if (ps->o.experimental_backends) { - if (ps->o.monitor_repaint && !backend_list[ps->o.backend]->fill) { - log_warn("--monitor-repaint is not supported by the backend, disabling"); - ps->o.monitor_repaint = false; - } - } + if (ps->o.experimental_backends) { + if (ps->o.monitor_repaint && !backend_list[ps->o.backend]->fill) { + log_warn("--monitor-repaint is not supported by the backend, " + "disabling"); + ps->o.monitor_repaint = false; + } + } - // Initialize software optimization - if (ps->o.sw_opti) - ps->o.sw_opti = swopti_init(ps); + // Initialize software optimization + if (ps->o.sw_opti) + ps->o.sw_opti = swopti_init(ps); - // Monitor screen changes if vsync_sw is enabled and we are using - // an auto-detected refresh rate, or when Xinerama features are enabled - if (ps->randr_exists && ((ps->o.sw_opti && !ps->o.refresh_rate) - || ps->o.xinerama_shadow_crop)) - xcb_randr_select_input(ps->c, ps->root, XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE); + // Monitor screen changes if vsync_sw is enabled and we are using + // an auto-detected refresh rate, or when Xinerama features are enabled + if (ps->randr_exists && + ((ps->o.sw_opti && !ps->o.refresh_rate) || ps->o.xinerama_shadow_crop)) + xcb_randr_select_input(ps->c, ps->root, XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE); - cxinerama_upd_scrs(ps); + cxinerama_upd_scrs(ps); - // Create registration window - if (!ps->reg_win && !register_cm(ps)) - exit(1); + // Create registration window + if (!ps->reg_win && !register_cm(ps)) + exit(1); - init_atoms(ps); + init_atoms(ps); - { - xcb_render_create_picture_value_list_t pa = { - .subwindowmode = IncludeInferiors, - }; + { + xcb_render_create_picture_value_list_t pa = { + .subwindowmode = IncludeInferiors, + }; - ps->root_picture = x_create_picture_with_visual_and_pixmap(ps->c, - ps->vis, ps->root, XCB_RENDER_CP_SUBWINDOW_MODE, &pa); - if (ps->overlay != XCB_NONE) { - ps->tgt_picture = x_create_picture_with_visual_and_pixmap(ps->c, - ps->vis, ps->overlay, XCB_RENDER_CP_SUBWINDOW_MODE, &pa); - } else - ps->tgt_picture = ps->root_picture; - } + ps->root_picture = x_create_picture_with_visual_and_pixmap( + ps->c, ps->vis, ps->root, XCB_RENDER_CP_SUBWINDOW_MODE, &pa); + if (ps->overlay != XCB_NONE) { + ps->tgt_picture = x_create_picture_with_visual_and_pixmap( + ps->c, ps->vis, ps->overlay, XCB_RENDER_CP_SUBWINDOW_MODE, &pa); + } else + ps->tgt_picture = ps->root_picture; + } - ev_io_init(&ps->xiow, x_event_callback, ConnectionNumber(ps->dpy), EV_READ); - ev_io_start(ps->loop, &ps->xiow); - ev_init(&ps->unredir_timer, tmout_unredir_callback); - if (ps->o.sw_opti) - ev_idle_init(&ps->draw_idle, delayed_draw_callback); - else - ev_idle_init(&ps->draw_idle, draw_callback); + ev_io_init(&ps->xiow, x_event_callback, ConnectionNumber(ps->dpy), EV_READ); + ev_io_start(ps->loop, &ps->xiow); + ev_init(&ps->unredir_timer, tmout_unredir_callback); + if (ps->o.sw_opti) + ev_idle_init(&ps->draw_idle, delayed_draw_callback); + else + ev_idle_init(&ps->draw_idle, draw_callback); - ev_init(&ps->fade_timer, fade_timer_callback); - ev_init(&ps->delayed_draw_timer, delayed_draw_timer_callback); + ev_init(&ps->fade_timer, fade_timer_callback); + ev_init(&ps->delayed_draw_timer, delayed_draw_timer_callback); - // Set up SIGUSR1 signal handler to reset program - ev_signal_init(&ps->usr1_signal, reset_enable, SIGUSR1); - ev_signal_init(&ps->int_signal, exit_enable, SIGINT); - ev_signal_start(ps->loop, &ps->usr1_signal); - ev_signal_start(ps->loop, &ps->int_signal); + // Set up SIGUSR1 signal handler to reset program + ev_signal_init(&ps->usr1_signal, reset_enable, SIGUSR1); + ev_signal_init(&ps->int_signal, exit_enable, SIGINT); + ev_signal_start(ps->loop, &ps->usr1_signal); + ev_signal_start(ps->loop, &ps->int_signal); - // xcb can read multiple events from the socket when a request with reply is - // made. - // - // Use an ev_prepare to make sure we cannot accidentally forget to handle them - // before we go to sleep. - // - // If we don't drain the queue before goes to sleep (i.e. blocking on socket - // input), we will be sleeping with events available in queue. Which might - // cause us to block indefinitely because arrival of new events could be - // dependent on processing of existing events (e.g. if we don't process damage - // event and do damage subtract, new damage event won't be generated). - // - // So we make use of a ev_prepare handle, which is called right before libev - // goes into sleep, to handle all the queued X events. - ev_prepare_init(&ps->event_check, handle_queued_x_events); - // Make sure nothing can cause xcb to read from the X socket after events are - // handled and before we going to sleep. - ev_set_priority(&ps->event_check, EV_MINPRI); - ev_prepare_start(ps->loop, &ps->event_check); + // xcb can read multiple events from the socket when a request with reply is + // made. + // + // Use an ev_prepare to make sure we cannot accidentally forget to handle them + // before we go to sleep. + // + // If we don't drain the queue before goes to sleep (i.e. blocking on socket + // input), we will be sleeping with events available in queue. Which might + // cause us to block indefinitely because arrival of new events could be + // dependent on processing of existing events (e.g. if we don't process damage + // event and do damage subtract, new damage event won't be generated). + // + // So we make use of a ev_prepare handle, which is called right before libev + // goes into sleep, to handle all the queued X events. + ev_prepare_init(&ps->event_check, handle_queued_x_events); + // Make sure nothing can cause xcb to read from the X socket after events are + // handled and before we going to sleep. + ev_set_priority(&ps->event_check, EV_MINPRI); + ev_prepare_start(ps->loop, &ps->event_check); - xcb_grab_server(ps->c); + xcb_grab_server(ps->c); - // Initialize DBus. We need to do this early, because add_win might call dbus functions - if (ps->o.dbus) { + // Initialize DBus. We need to do this early, because add_win might call dbus + // functions + if (ps->o.dbus) { #ifdef CONFIG_DBUS - cdbus_init(ps, DisplayString(ps->dpy)); - if (!ps->dbus_data) { - ps->o.dbus = false; - } + cdbus_init(ps, DisplayString(ps->dpy)); + if (!ps->dbus_data) { + ps->o.dbus = false; + } #else - log_fatal("DBus support not compiled in!"); - exit(1); + log_fatal("DBus support not compiled in!"); + exit(1); #endif - } + } - { - xcb_window_t *children; - int nchildren; + { + xcb_window_t *children; + int nchildren; - xcb_query_tree_reply_t *reply = xcb_query_tree_reply(ps->c, - xcb_query_tree(ps->c, ps->root), NULL); + xcb_query_tree_reply_t *reply = + xcb_query_tree_reply(ps->c, xcb_query_tree(ps->c, ps->root), NULL); - if (reply) { - children = xcb_query_tree_children(reply); - nchildren = xcb_query_tree_children_length(reply); - } else { - children = NULL; - nchildren = 0; - } + if (reply) { + children = xcb_query_tree_children(reply); + nchildren = xcb_query_tree_children_length(reply); + } else { + children = NULL; + nchildren = 0; + } - for (int i = 0; i < nchildren; i++) { - add_win(ps, children[i], i ? children[i-1] : XCB_NONE); - } + for (int i = 0; i < nchildren; i++) { + add_win(ps, children[i], i ? children[i - 1] : XCB_NONE); + } - for (win *i = ps->list; i; i = i->next) { - if (i->a.map_state == XCB_MAP_STATE_VIEWABLE) { - map_win(ps, i); - } - } + for (win *i = ps->list; i; i = i->next) { + if (i->a.map_state == XCB_MAP_STATE_VIEWABLE) { + map_win(ps, i); + } + } - free(reply); - log_trace("Initial stack:"); - for (win *c = ps->list; c; c = c->next) { - log_trace("%#010x \"%s\"", c->id, c->name); - } - } + free(reply); + log_trace("Initial stack:"); + for (win *c = ps->list; c; c = c->next) { + log_trace("%#010x \"%s\"", c->id, c->name); + } + } - if (ps->o.track_focus) { - recheck_focus(ps); - } + if (ps->o.track_focus) { + recheck_focus(ps); + } - e = xcb_request_check(ps->c, xcb_ungrab_server(ps->c)); - if (e) { - log_error("Failed to ungrad server"); - free(e); - } + e = xcb_request_check(ps->c, xcb_ungrab_server(ps->c)); + if (e) { + log_error("Failed to ungrad server"); + free(e); + } - write_pid(ps); + write_pid(ps); - if (fork && stderr_logger) { - // Remove the stderr logger if we will fork - log_remove_target_tls(stderr_logger); - } - return ps; + if (fork && stderr_logger) { + // Remove the stderr logger if we will fork + log_remove_target_tls(stderr_logger); + } + return ps; } /** @@ -2876,150 +2765,149 @@ session_init(int argc, char **argv, Display *dpy, const char *config_file, * * @param ps session to destroy */ -static void -session_destroy(session_t *ps) { - redir_stop(ps); +static void session_destroy(session_t *ps) { + redir_stop(ps); - // Stop listening to events on root window - xcb_change_window_attributes(ps->c, ps->root, XCB_CW_EVENT_MASK, - (const uint32_t[]) { 0 }); + // Stop listening to events on root window + xcb_change_window_attributes(ps->c, ps->root, XCB_CW_EVENT_MASK, + (const uint32_t[]){0}); #ifdef CONFIG_DBUS - // Kill DBus connection - if (ps->o.dbus) { - assert(ps->dbus_data); - cdbus_destroy(ps); - } + // Kill DBus connection + if (ps->o.dbus) { + assert(ps->dbus_data); + cdbus_destroy(ps); + } #endif - // Free window linked list - { - win *next = NULL; - win *list = ps->list; - ps->list = NULL; + // Free window linked list + { + win *next = NULL; + win *list = ps->list; + ps->list = NULL; - for (win *w = list; w; w = next) { - next = w->next; + for (win *w = list; w; w = next) { + next = w->next; - if (w->state != WSTATE_DESTROYING) { - win_ev_stop(ps, w); - } + if (w->state != WSTATE_DESTROYING) { + win_ev_stop(ps, w); + } - free_win_res(ps, w); - free(w); - } - } + free_win_res(ps, w); + free(w); + } + } - // Free blacklists - free_wincondlst(&ps->o.shadow_blacklist); - free_wincondlst(&ps->o.fade_blacklist); - free_wincondlst(&ps->o.focus_blacklist); - free_wincondlst(&ps->o.invert_color_list); - free_wincondlst(&ps->o.blur_background_blacklist); - free_wincondlst(&ps->o.opacity_rules); - free_wincondlst(&ps->o.paint_blacklist); - free_wincondlst(&ps->o.unredir_if_possible_blacklist); + // Free blacklists + free_wincondlst(&ps->o.shadow_blacklist); + free_wincondlst(&ps->o.fade_blacklist); + free_wincondlst(&ps->o.focus_blacklist); + free_wincondlst(&ps->o.invert_color_list); + free_wincondlst(&ps->o.blur_background_blacklist); + free_wincondlst(&ps->o.opacity_rules); + free_wincondlst(&ps->o.paint_blacklist); + free_wincondlst(&ps->o.unredir_if_possible_blacklist); - // Free tracked atom list - { - latom_t *next = NULL; - for (latom_t *this = ps->track_atom_lst; this; this = next) { - next = this->next; - free(this); - } + // Free tracked atom list + { + latom_t *next = NULL; + for (latom_t *this = ps->track_atom_lst; this; this = next) { + next = this->next; + free(this); + } - ps->track_atom_lst = NULL; - } + ps->track_atom_lst = NULL; + } - // Free ignore linked list - { - ignore_t *next = NULL; - for (ignore_t *ign = ps->ignore_head; ign; ign = next) { - next = ign->next; + // Free ignore linked list + { + ignore_t *next = NULL; + for (ignore_t *ign = ps->ignore_head; ign; ign = next) { + next = ign->next; - free(ign); - } + free(ign); + } - // Reset head and tail - ps->ignore_head = NULL; - ps->ignore_tail = &ps->ignore_head; - } + // Reset head and tail + ps->ignore_head = NULL; + ps->ignore_tail = &ps->ignore_head; + } - // Free tgt_{buffer,picture} and root_picture - if (ps->tgt_buffer.pict == ps->tgt_picture) - ps->tgt_buffer.pict = XCB_NONE; + // Free tgt_{buffer,picture} and root_picture + if (ps->tgt_buffer.pict == ps->tgt_picture) + ps->tgt_buffer.pict = XCB_NONE; - if (ps->tgt_picture == ps->root_picture) - ps->tgt_picture = XCB_NONE; - else - free_picture(ps->c, &ps->tgt_picture); + if (ps->tgt_picture == ps->root_picture) + ps->tgt_picture = XCB_NONE; + else + free_picture(ps->c, &ps->tgt_picture); - free_picture(ps->c, &ps->root_picture); - free_paint(ps, &ps->tgt_buffer); + free_picture(ps->c, &ps->root_picture); + free_paint(ps, &ps->tgt_buffer); - pixman_region32_fini(&ps->screen_reg); - free(ps->expose_rects); + pixman_region32_fini(&ps->screen_reg); + free(ps->expose_rects); - free(ps->o.write_pid_path); - free(ps->o.logpath); - for (int i = 0; i < MAX_BLUR_PASS; ++i) { - free(ps->o.blur_kerns[i]); - free(ps->blur_kerns_cache[i]); - } - free(ps->o.glx_fshader_win_str); - free_xinerama_info(ps); + free(ps->o.write_pid_path); + free(ps->o.logpath); + for (int i = 0; i < MAX_BLUR_PASS; ++i) { + free(ps->o.blur_kerns[i]); + free(ps->blur_kerns_cache[i]); + } + free(ps->o.glx_fshader_win_str); + free_xinerama_info(ps); #ifdef CONFIG_VSYNC_DRM - // Close file opened for DRM VSync - if (ps->drm_fd >= 0) { - close(ps->drm_fd); - ps->drm_fd = -1; - } + // Close file opened for DRM VSync + if (ps->drm_fd >= 0) { + close(ps->drm_fd); + ps->drm_fd = -1; + } #endif - // Release overlay window - if (ps->overlay) { - xcb_composite_release_overlay_window(ps->c, ps->overlay); - ps->overlay = XCB_NONE; - } + // Release overlay window + if (ps->overlay) { + xcb_composite_release_overlay_window(ps->c, ps->overlay); + ps->overlay = XCB_NONE; + } - if (ps->sync_fence) { - xcb_sync_destroy_fence(ps->c, ps->sync_fence); - ps->sync_fence = XCB_NONE; - } + if (ps->sync_fence) { + xcb_sync_destroy_fence(ps->c, ps->sync_fence); + ps->sync_fence = XCB_NONE; + } - // Free reg_win - if (ps->reg_win) { - xcb_destroy_window(ps->c, ps->reg_win); - ps->reg_win = XCB_NONE; - } + // Free reg_win + if (ps->reg_win) { + xcb_destroy_window(ps->c, ps->reg_win); + ps->reg_win = XCB_NONE; + } - if (ps->o.experimental_backends) { - // backend is deinitialized in redir_stop - assert(ps->backend_data == NULL); - } else { - deinit_render(ps); - } + if (ps->o.experimental_backends) { + // backend is deinitialized in redir_stop + assert(ps->backend_data == NULL); + } else { + deinit_render(ps); + } - // Flush all events - x_sync(ps->c); - ev_io_stop(ps->loop, &ps->xiow); - free_conv(ps->gaussian_map); + // Flush all events + x_sync(ps->c); + ev_io_stop(ps->loop, &ps->xiow); + free_conv(ps->gaussian_map); #ifdef DEBUG_XRC - // Report about resource leakage - xrc_report_xid(); + // Report about resource leakage + xrc_report_xid(); #endif - // Stop libev event handlers - ev_timer_stop(ps->loop, &ps->unredir_timer); - ev_timer_stop(ps->loop, &ps->fade_timer); - ev_idle_stop(ps->loop, &ps->draw_idle); - ev_prepare_stop(ps->loop, &ps->event_check); - ev_signal_stop(ps->loop, &ps->usr1_signal); - ev_signal_stop(ps->loop, &ps->int_signal); + // Stop libev event handlers + ev_timer_stop(ps->loop, &ps->unredir_timer); + ev_timer_stop(ps->loop, &ps->fade_timer); + ev_idle_stop(ps->loop, &ps->draw_idle); + ev_prepare_stop(ps->loop, &ps->event_check); + ev_signal_stop(ps->loop, &ps->usr1_signal); + ev_signal_stop(ps->loop, &ps->int_signal); - log_deinit_tls(); + log_deinit_tls(); } /** @@ -3027,113 +2915,111 @@ session_destroy(session_t *ps) { * * @param ps current session */ -static void -session_run(session_t *ps) { - if (ps->o.sw_opti) - ps->paint_tm_offset = get_time_timeval().tv_usec; +static void session_run(session_t *ps) { + if (ps->o.sw_opti) + ps->paint_tm_offset = get_time_timeval().tv_usec; - // In benchmark mode, we want draw_idle handler to always be active - if (ps->o.benchmark) { - ev_idle_start(ps->loop, &ps->draw_idle); - } else { - // Let's draw our first frame! - queue_redraw(ps); - } - ev_run(ps->loop, 0); + // In benchmark mode, we want draw_idle handler to always be active + if (ps->o.benchmark) { + ev_idle_start(ps->loop, &ps->draw_idle); + } else { + // Let's draw our first frame! + queue_redraw(ps); + } + ev_run(ps->loop, 0); } /** * The function that everybody knows. */ -int -main(int argc, char **argv) { - // Set locale so window names with special characters are interpreted - // correctly - setlocale(LC_ALL, ""); +int main(int argc, char **argv) { + // Set locale so window names with special characters are interpreted + // correctly + setlocale(LC_ALL, ""); - int exit_code; - char *config_file = NULL; - bool all_xerrors = false, need_fork = false; - if (get_early_config(argc, argv, &config_file, &all_xerrors, &need_fork, &exit_code)) { - return exit_code; - } + int exit_code; + char *config_file = NULL; + bool all_xerrors = false, need_fork = false; + if (get_early_config(argc, argv, &config_file, &all_xerrors, &need_fork, &exit_code)) { + return exit_code; + } - int pfds[2]; - if (need_fork) { - if (pipe2(pfds, O_CLOEXEC)) { - perror("pipe2"); - return 1; - } - auto pid = fork(); - if (pid < 0) { - perror("fork"); - return 1; - } - if (pid > 0) { - // We are the parent - close(pfds[1]); - // We wait for the child to tell us it has finished initialization - // by sending us something via the pipe. - int tmp; - if (read(pfds[0], &tmp, sizeof tmp) <= 0) { - // Failed to read, the child has most likely died - // We can probably waitpid() here. - return 1; - } else { - // We are done - return 0; - } - } - // We are the child - close(pfds[0]); - } + int pfds[2]; + if (need_fork) { + if (pipe2(pfds, O_CLOEXEC)) { + perror("pipe2"); + return 1; + } + auto pid = fork(); + if (pid < 0) { + perror("fork"); + return 1; + } + if (pid > 0) { + // We are the parent + close(pfds[1]); + // We wait for the child to tell us it has finished initialization + // by sending us something via the pipe. + int tmp; + if (read(pfds[0], &tmp, sizeof tmp) <= 0) { + // Failed to read, the child has most likely died + // We can probably waitpid() here. + return 1; + } else { + // We are done + return 0; + } + } + // We are the child + close(pfds[0]); + } - // Main loop - bool quit = false; - Display *dpy = XOpenDisplay(NULL); - if (!dpy) { - log_fatal("Can't open display."); - return 1; - } - XSetEventQueueOwner(dpy, XCBOwnsEventQueue); + // Main loop + bool quit = false; + Display *dpy = XOpenDisplay(NULL); + if (!dpy) { + log_fatal("Can't open display."); + return 1; + } + XSetEventQueueOwner(dpy, XCBOwnsEventQueue); - do { - ps_g = session_init(argc, argv, dpy, config_file, all_xerrors, need_fork); - if (!ps_g) { - log_fatal("Failed to create new compton session."); - return 1; - } - if (need_fork) { - // Finishing up daemonization - // Close files - if (fclose(stdout) || fclose(stderr) || fclose(stdin)) { - log_fatal("Failed to close standard input/output"); - return 1; - } - // Make us the session and process group leader so we don't get killed when - // our parent die. - setsid(); - // Notify the parent that we are done. This might cause the parent to quit, - // so only do this after setsid() - int tmp = 1; - write(pfds[1], &tmp, sizeof tmp); - close(pfds[1]); - // We only do this once - need_fork = false; - } - session_run(ps_g); - quit = ps_g->quit; - session_destroy(ps_g); - free(ps_g); - ps_g = NULL; - } while (!quit); + do { + ps_g = session_init(argc, argv, dpy, config_file, all_xerrors, need_fork); + if (!ps_g) { + log_fatal("Failed to create new compton session."); + return 1; + } + if (need_fork) { + // Finishing up daemonization + // Close files + if (fclose(stdout) || fclose(stderr) || fclose(stdin)) { + log_fatal("Failed to close standard input/output"); + return 1; + } + // Make us the session and process group leader so we don't get + // killed when our parent die. + setsid(); + // Notify the parent that we are done. This might cause the parent + // to quit, so only do this after setsid() + int tmp = 1; + write(pfds[1], &tmp, sizeof tmp); + close(pfds[1]); + // We only do this once + need_fork = false; + } + session_run(ps_g); + quit = ps_g->quit; + session_destroy(ps_g); + free(ps_g); + ps_g = NULL; + } while (!quit); - if (dpy) { - XCloseDisplay(dpy); - } - free(config_file); + if (dpy) { + XCloseDisplay(dpy); + } + free(config_file); - return 0; + return 0; } // vim: set et sw=2 : diff --git a/src/compton.h b/src/compton.h index 52c03b2..572d048 100644 --- a/src/compton.h +++ b/src/compton.h @@ -6,24 +6,24 @@ // === Includes === -#include -#include #include +#include +#include #include #include -#include "common.h" #include "backend/backend.h" -#include "win.h" -#include "x.h" #include "c2.h" -#include "log.h" // XXX clean up -#include "region.h" +#include "common.h" #include "compiler.h" +#include "config.h" +#include "log.h" // XXX clean up +#include "region.h" +#include "render.h" #include "types.h" #include "utils.h" -#include "render.h" -#include "config.h" +#include "win.h" +#include "x.h" // == Functions == // TODO move static inline functions that are only used in compton.c, into @@ -36,21 +36,19 @@ void add_damage(session_t *ps, const region_t *damage); long determine_evmask(session_t *ps, xcb_window_t wid, win_evmode_t mode); -xcb_window_t -find_client_win(session_t *ps, xcb_window_t w); +xcb_window_t find_client_win(session_t *ps, xcb_window_t w); win *find_toplevel2(session_t *ps, xcb_window_t wid); /** * Set a switch_t array of all unset wintypes to true. */ -static inline void -wintype_arr_enable_unset(switch_t arr[]) { - wintype_t i; +static inline void wintype_arr_enable_unset(switch_t arr[]) { + wintype_t i; - for (i = 0; i < NUM_WINTYPES; ++i) - if (UNSET == arr[i]) - arr[i] = ON; + for (i = 0; i < NUM_WINTYPES; ++i) + if (UNSET == arr[i]) + arr[i] = ON; } /** @@ -60,81 +58,76 @@ wintype_arr_enable_unset(switch_t arr[]) { * @param count amount of elements in the array * @param wid window ID to search for */ -static inline bool -array_wid_exists(const xcb_window_t *arr, int count, xcb_window_t wid) { - while (count--) { - if (arr[count] == wid) { - return true; - } - } +static inline bool array_wid_exists(const xcb_window_t *arr, int count, xcb_window_t wid) { + while (count--) { + if (arr[count] == wid) { + return true; + } + } - return false; + return false; } /** * Destroy a condition list. */ -static inline void -free_wincondlst(c2_lptr_t **pcondlst) { - while ((*pcondlst = c2_free_lptr(*pcondlst))) - continue; +static inline void free_wincondlst(c2_lptr_t **pcondlst) { + while ((*pcondlst = c2_free_lptr(*pcondlst))) + continue; } #ifndef CONFIG_OPENGL -static inline void -free_paint_glx(session_t *ps, paint_t *p) {} -static inline void -free_win_res_glx(session_t *ps, win *w) {} +static inline void free_paint_glx(session_t *ps, paint_t *p) { +} +static inline void free_win_res_glx(session_t *ps, win *w) { +} #endif /** * Create a XTextProperty of a single string. */ -static inline XTextProperty * -make_text_prop(session_t *ps, char *str) { - XTextProperty *pprop = ccalloc(1, XTextProperty); +static inline XTextProperty *make_text_prop(session_t *ps, char *str) { + XTextProperty *pprop = ccalloc(1, XTextProperty); - if (XmbTextListToTextProperty(ps->dpy, &str, 1, XStringStyle, pprop)) { - cxfree(pprop->value); - free(pprop); - pprop = NULL; - } + if (XmbTextListToTextProperty(ps->dpy, &str, 1, XStringStyle, pprop)) { + cxfree(pprop->value); + free(pprop); + pprop = NULL; + } - return pprop; + return pprop; } - /** * Set a single-string text property on a window. */ static inline bool wid_set_text_prop(session_t *ps, xcb_window_t wid, xcb_atom_t prop_atom, char *str) { - XTextProperty *pprop = make_text_prop(ps, str); - if (!pprop) { - log_error("Failed to make text property: %s.", str); - return false; - } + XTextProperty *pprop = make_text_prop(ps, str); + if (!pprop) { + log_error("Failed to make text property: %s.", str); + return false; + } - XSetTextProperty(ps->dpy, wid, pprop, prop_atom); - cxfree(pprop->value); - cxfree(pprop); + XSetTextProperty(ps->dpy, wid, pprop, prop_atom); + cxfree(pprop->value); + cxfree(pprop); - return true; + return true; } /** * Dump an drawable's info. */ -static inline void -dump_drawable(session_t *ps, xcb_drawable_t drawable) { - auto r = xcb_get_geometry_reply(ps->c, xcb_get_geometry(ps->c, drawable), NULL); - if (!r) { - log_trace("Drawable %#010x: Failed", drawable); - return; - } - log_trace("Drawable %#010x: x = %u, y = %u, wid = %u, hei = %d, b = %u, d = %u", - drawable, r->x, r->y, r->width, r->height, r->border_width, r->depth); - free(r); +static inline void dump_drawable(session_t *ps, xcb_drawable_t drawable) { + auto r = xcb_get_geometry_reply(ps->c, xcb_get_geometry(ps->c, drawable), NULL); + if (!r) { + log_trace("Drawable %#010x: Failed", drawable); + return; + } + log_trace("Drawable %#010x: x = %u, y = %u, wid = %u, hei = %d, b = %u, d = %u", + drawable, r->x, r->y, r->width, r->height, r->border_width, r->depth); + free(r); } // vim: set et sw=2 : diff --git a/src/config.c b/src/config.c index 8bad574..fac6795 100644 --- a/src/config.c +++ b/src/config.c @@ -2,22 +2,22 @@ // Copyright (c) 2011-2013, Christopher Jeffrey // Copyright (c) 2013 Richard Grenville -#include -#include -#include -#include #include -#include // for xcb_render_fixed_t, XXX +#include +#include +#include +#include +#include // for xcb_render_fixed_t, XXX -#include "compiler.h" -#include "common.h" -#include "utils.h" #include "c2.h" -#include "string_utils.h" +#include "common.h" +#include "compiler.h" +#include "kernel.h" #include "log.h" #include "region.h" +#include "string_utils.h" #include "types.h" -#include "kernel.h" +#include "utils.h" #include "win.h" #include "config.h" @@ -25,22 +25,21 @@ /** * Parse a long number. */ -bool -parse_long(const char *s, long *dest) { - const char *endptr = NULL; - long val = strtol(s, (char **) &endptr, 0); - if (!endptr || endptr == s) { - log_error("Invalid number: %s", s); - return false; - } - while (isspace(*endptr)) - ++endptr; - if (*endptr) { - log_error("Trailing characters: %s", s); - return false; - } - *dest = val; - return true; +bool parse_long(const char *s, long *dest) { + const char *endptr = NULL; + long val = strtol(s, (char **)&endptr, 0); + if (!endptr || endptr == s) { + log_error("Invalid number: %s", s); + return false; + } + while (isspace(*endptr)) + ++endptr; + if (*endptr) { + log_error("Trailing characters: %s", s); + return false; + } + *dest = val; + return true; } /** @@ -51,19 +50,18 @@ parse_long(const char *s, long *dest) { * @param[out] dest return the number parsed from the string * @return pointer to the last character parsed */ -const char * -parse_readnum(const char *src, double *dest) { - const char *pc = NULL; - double val = strtod_simple(src, &pc); - if (!pc || pc == src) { - log_error("No number found: %s", src); - return src; - } - while (*pc && (isspace(*pc) || *pc == ',')) { - ++pc; - } - *dest = val; - return pc; +const char *parse_readnum(const char *src, double *dest) { + const char *pc = NULL; + double val = strtod_simple(src, &pc); + if (!pc || pc == src) { + log_error("No number found: %s", src); + return src; + } + while (*pc && (isspace(*pc) || *pc == ',')) { + ++pc; + } + *dest = val; + return pc; } /** @@ -73,93 +71,92 @@ parse_readnum(const char *src, double *dest) { * @param[out] endptr return where the end of kernel is in the string * @param[out] hasneg whether the kernel has negative values */ -conv * -parse_blur_kern(const char *src, const char **endptr, bool *hasneg) { - int width = 0, height = 0; - *hasneg = false; +conv *parse_blur_kern(const char *src, const char **endptr, bool *hasneg) { + int width = 0, height = 0; + *hasneg = false; - const char *pc = NULL; + const char *pc = NULL; - // Get matrix width and height - double val = 0.0; - if (src == (pc = parse_readnum(src, &val))) - goto err1; - src = pc; - width = val; - if (src == (pc = parse_readnum(src, &val))) - goto err1; - src = pc; - height = val; + // Get matrix width and height + double val = 0.0; + if (src == (pc = parse_readnum(src, &val))) + goto err1; + src = pc; + width = val; + if (src == (pc = parse_readnum(src, &val))) + goto err1; + src = pc; + height = val; - // Validate matrix width and height - if (width <= 0 || height <= 0) { - log_error("Blue kernel width/height can't be negative."); - goto err1; - } - if (!(width % 2 && height % 2)) { - log_error("Blur kernel width/height must be odd."); - goto err1; - } - if (width > 16 || height > 16) - log_warn("Blur kernel width/height too large, may slow down" - "rendering, and/or consume lots of memory"); + // Validate matrix width and height + if (width <= 0 || height <= 0) { + log_error("Blue kernel width/height can't be negative."); + goto err1; + } + if (!(width % 2 && height % 2)) { + log_error("Blur kernel width/height must be odd."); + goto err1; + } + if (width > 16 || height > 16) + log_warn("Blur kernel width/height too large, may slow down" + "rendering, and/or consume lots of memory"); - // Allocate memory - conv *matrix = cvalloc(sizeof(conv) + width * height * sizeof(double)); + // Allocate memory + conv *matrix = cvalloc(sizeof(conv) + width * height * sizeof(double)); - // Read elements - int skip = height / 2 * width + width / 2; - for (int i = 0; i < width * height; ++i) { - // Ignore the center element - if (i == skip) { - matrix->data[i] = 0; - continue; - } - if (src == (pc = parse_readnum(src, &val))) { - goto err2; - } - src = pc; - if (val < 0) { - *hasneg = true; - } - matrix->data[i] = val; - } + // Read elements + int skip = height / 2 * width + width / 2; + for (int i = 0; i < width * height; ++i) { + // Ignore the center element + if (i == skip) { + matrix->data[i] = 0; + continue; + } + if (src == (pc = parse_readnum(src, &val))) { + goto err2; + } + src = pc; + if (val < 0) { + *hasneg = true; + } + matrix->data[i] = val; + } - // Detect trailing characters - for (;*pc && *pc != ';'; pc++) { - if (!isspace(*pc) && *pc != ',') { - // TODO isspace is locale aware, be careful - log_error("Trailing characters in blur kernel string."); - goto err2; - } - } + // Detect trailing characters + for (; *pc && *pc != ';'; pc++) { + if (!isspace(*pc) && *pc != ',') { + // TODO isspace is locale aware, be careful + log_error("Trailing characters in blur kernel string."); + goto err2; + } + } - // Jump over spaces after ';' - if (*pc == ';') { - pc++; - while (*pc && isspace(*pc)) { - ++pc; - } - } + // Jump over spaces after ';' + if (*pc == ';') { + pc++; + while (*pc && isspace(*pc)) { + ++pc; + } + } - // Require an end of string if endptr is not provided, otherwise - // copy end pointer to endptr - if (endptr) { - *endptr = pc; - } else if (*pc) { - log_error("Only one blur kernel expected."); - goto err2; - } + // Require an end of string if endptr is not provided, otherwise + // copy end pointer to endptr + if (endptr) { + *endptr = pc; + } else if (*pc) { + log_error("Only one blur kernel expected."); + goto err2; + } - // Fill in width and height - matrix->w = width; - matrix->h = height; - return matrix; + // Fill in width and height + matrix->w = width; + matrix->h = height; + return matrix; err2: - free(matrix); + free(matrix); err1: - return NULL; + return NULL; } /** @@ -172,63 +169,104 @@ err1: * @param[out] hasneg whether any of the kernels have negative values * @return if the `src` string is a valid kernel list string */ -bool -parse_blur_kern_lst(const char *src, conv **dest, int max, bool *hasneg) { - // TODO just return a predefined kernels, not parse predefined strings... - static const struct { - const char *name; - const char *kern_str; - } CONV_KERN_PREDEF[] = { - { "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," }, - { "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," }, - { "3x3gaussian", "3,3,0.243117,0.493069,0.243117,0.493069,0.493069,0.243117,0.493069,0.243117," }, - { "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," }, - { "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," }, - }; +bool parse_blur_kern_lst(const char *src, conv **dest, int max, bool *hasneg) { + // TODO just return a predefined kernels, not parse predefined strings... + static const struct { + const char *name; + const char *kern_str; + } CONV_KERN_PREDEF[] = { + {"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,"}, + {"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,"}, + {"3x3gaussian", "3,3,0.243117,0.493069,0.243117,0.493069,0.493069,0.243117,0." + "493069,0.243117,"}, + {"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,"}, + {"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; - for (unsigned int i = 0; - i < sizeof(CONV_KERN_PREDEF) / sizeof(CONV_KERN_PREDEF[0]); ++i) { - if (!strcmp(CONV_KERN_PREDEF[i].name, src)) - return parse_blur_kern_lst(CONV_KERN_PREDEF[i].kern_str, dest, max, hasneg); - } + *hasneg = false; + for (unsigned int i = 0; + i < sizeof(CONV_KERN_PREDEF) / sizeof(CONV_KERN_PREDEF[0]); ++i) { + if (!strcmp(CONV_KERN_PREDEF[i].name, src)) + return parse_blur_kern_lst(CONV_KERN_PREDEF[i].kern_str, dest, + max, hasneg); + } - int i = 0; - const char *pc = src; + int i = 0; + const char *pc = src; - // Free old kernels - for (i = 0; i < max; ++i) { - free(dest[i]); - dest[i] = NULL; - } + // Free old kernels + for (i = 0; i < max; ++i) { + free(dest[i]); + dest[i] = NULL; + } - // Continue parsing until the end of source string - i = 0; - while (pc && *pc && i < max - 1) { - bool tmp_hasneg; - dest[i] = parse_blur_kern(pc, &pc, &tmp_hasneg); - if (!dest[i]) { - return false; - } - i++; - *hasneg |= tmp_hasneg; - } + // Continue parsing until the end of source string + i = 0; + while (pc && *pc && i < max - 1) { + bool tmp_hasneg; + dest[i] = parse_blur_kern(pc, &pc, &tmp_hasneg); + if (!dest[i]) { + return false; + } + i++; + *hasneg |= tmp_hasneg; + } - if (i > 1) { - log_warn("You are seeing this message because your are using multipassblur. Please " - "report an issue to us so we know multipass blur is actually been used. " - "Otherwise it might be removed in future releases"); - } + if (i > 1) { + log_warn("You are seeing this message because your are using " + "multipassblur. Please " + "report an issue to us so we know multipass blur is actually " + "been used. " + "Otherwise it might be removed in future releases"); + } - if (*pc) { - log_error("Too many blur kernels!"); - return false; - } + if (*pc) { + log_error("Too many blur kernels!"); + return false; + } - return true; + return true; } /** @@ -236,187 +274,184 @@ parse_blur_kern_lst(const char *src, conv **dest, int max, bool *hasneg) { * * ps->root_width and ps->root_height must be valid */ -bool -parse_geometry(session_t *ps, const char *src, region_t *dest) { - pixman_region32_clear(dest); - if (!src) - return true; - if (!ps->root_width || !ps->root_height) - return true; +bool parse_geometry(session_t *ps, const char *src, region_t *dest) { + pixman_region32_clear(dest); + if (!src) + return true; + if (!ps->root_width || !ps->root_height) + return true; - geometry_t geom = { .wid = ps->root_width, .hei = ps->root_height, .x = 0, .y = 0 }; - long val = 0L; - char *endptr = NULL; + geometry_t geom = {.wid = ps->root_width, .hei = ps->root_height, .x = 0, .y = 0}; + long val = 0L; + char *endptr = NULL; - src = skip_space(src); - if (!*src) - goto parse_geometry_end; + src = skip_space(src); + if (!*src) + goto parse_geometry_end; - // Parse width - // Must be base 10, because "0x0..." may appear - if (!('+' == *src || '-' == *src)) { - val = strtol(src, &endptr, 10); - assert(endptr); - if (src != endptr) { - geom.wid = val; - if (geom.wid < 0) { - log_error("Invalid width: %s", src); - return false; - } - src = endptr; - } - src = skip_space(src); - } + // Parse width + // Must be base 10, because "0x0..." may appear + if (!('+' == *src || '-' == *src)) { + val = strtol(src, &endptr, 10); + assert(endptr); + if (src != endptr) { + geom.wid = val; + if (geom.wid < 0) { + log_error("Invalid width: %s", src); + return false; + } + src = endptr; + } + src = skip_space(src); + } - // Parse height - if ('x' == *src) { - ++src; - val = strtol(src, &endptr, 10); - assert(endptr); - if (src != endptr) { - geom.hei = val; - if (geom.hei < 0) { - log_error("Invalid height: %s", src); - return false; - } - src = endptr; - } - src = skip_space(src); - } + // Parse height + if ('x' == *src) { + ++src; + val = strtol(src, &endptr, 10); + assert(endptr); + if (src != endptr) { + geom.hei = val; + if (geom.hei < 0) { + log_error("Invalid height: %s", src); + return false; + } + src = endptr; + } + src = skip_space(src); + } - // Parse x - if ('+' == *src || '-' == *src) { - val = strtol(src, &endptr, 10); - if (endptr && src != endptr) { - geom.x = val; - if (*src == '-') - geom.x += ps->root_width - geom.wid; - src = endptr; - } - src = skip_space(src); - } + // Parse x + if ('+' == *src || '-' == *src) { + val = strtol(src, &endptr, 10); + if (endptr && src != endptr) { + geom.x = val; + if (*src == '-') + geom.x += ps->root_width - geom.wid; + src = endptr; + } + src = skip_space(src); + } - // Parse y - if ('+' == *src || '-' == *src) { - val = strtol(src, &endptr, 10); - if (endptr && src != endptr) { - geom.y = val; - if (*src == '-') - geom.y += ps->root_height - geom.hei; - src = endptr; - } - src = skip_space(src); - } + // Parse y + if ('+' == *src || '-' == *src) { + val = strtol(src, &endptr, 10); + if (endptr && src != endptr) { + geom.y = val; + if (*src == '-') + geom.y += ps->root_height - geom.hei; + src = endptr; + } + src = skip_space(src); + } - if (*src) { - log_error("Trailing characters: %s", src); - return false; - } + if (*src) { + log_error("Trailing characters: %s", src); + return false; + } parse_geometry_end: - pixman_region32_union_rect(dest, dest, geom.x, geom.y, geom.wid, geom.hei); - return true; + pixman_region32_union_rect(dest, dest, geom.x, geom.y, geom.wid, geom.hei); + return true; } /** * Parse a list of opacity rules. */ bool parse_rule_opacity(c2_lptr_t **res, const char *src) { - // Find opacity value - char *endptr = NULL; - long val = strtol(src, &endptr, 0); - if (!endptr || endptr == src) { - log_error("No opacity specified: %s", src); - return false; - } - if (val > 100 || val < 0) { - log_error("Opacity %ld invalid: %s", val, src); - return false; - } + // Find opacity value + char *endptr = NULL; + long val = strtol(src, &endptr, 0); + if (!endptr || endptr == src) { + log_error("No opacity specified: %s", src); + return false; + } + if (val > 100 || val < 0) { + log_error("Opacity %ld invalid: %s", val, src); + return false; + } - // Skip over spaces - while (*endptr && isspace(*endptr)) - ++endptr; - if (':' != *endptr) { - log_error("Opacity terminator not found: %s", src); - return false; - } - ++endptr; + // Skip over spaces + while (*endptr && isspace(*endptr)) + ++endptr; + if (':' != *endptr) { + log_error("Opacity terminator not found: %s", src); + return false; + } + ++endptr; - // Parse pattern - // I hope 1-100 is acceptable for (void *) - return c2_parse(res, endptr, (void *) val); + // Parse pattern + // I hope 1-100 is acceptable for (void *) + return c2_parse(res, endptr, (void *)val); } /** * Add a pattern to a condition linked list. */ -bool -condlst_add(c2_lptr_t **pcondlst, const char *pattern) { - if (!pattern) - return false; +bool condlst_add(c2_lptr_t **pcondlst, const char *pattern) { + if (!pattern) + return false; - if (!c2_parse(pcondlst, pattern, NULL)) - exit(1); + if (!c2_parse(pcondlst, pattern, NULL)) + exit(1); - return true; + return true; } -void set_default_winopts(options_t *opt, win_option_mask_t *mask, bool shadow_enable, bool fading_enable) { - // Apply default wintype options. - if (!mask[WINTYPE_DESKTOP].shadow) { - // Desktop windows are always drawn without shadow by default. - mask[WINTYPE_DESKTOP].shadow = true; - opt->wintype_option[WINTYPE_DESKTOP].shadow = false; - } +void set_default_winopts(options_t *opt, win_option_mask_t *mask, bool shadow_enable, + bool fading_enable) { + // Apply default wintype options. + if (!mask[WINTYPE_DESKTOP].shadow) { + // Desktop windows are always drawn without shadow by default. + mask[WINTYPE_DESKTOP].shadow = true; + opt->wintype_option[WINTYPE_DESKTOP].shadow = false; + } - // Focused/unfocused state only apply to a few window types, all other windows - // are always considered focused. - const wintype_t nofocus_type[] = - { WINTYPE_UNKNOWN, WINTYPE_NORMAL, WINTYPE_UTILITY }; - for (unsigned long i = 0; i < ARR_SIZE(nofocus_type); i++) { - if (!mask[nofocus_type[i]].focus) { - mask[nofocus_type[i]].focus = true; - opt->wintype_option[nofocus_type[i]].focus = false; - } - } - for (unsigned long i = 0; i < NUM_WINTYPES; i++) { - if (!mask[i].shadow) { - mask[i].shadow = true; - opt->wintype_option[i].shadow = shadow_enable; - } - if (!mask[i].fade) { - mask[i].fade = true; - opt->wintype_option[i].fade = fading_enable; - } - if (!mask[i].focus) { - mask[i].focus = true; - opt->wintype_option[i].focus = true; - } - if (!mask[i].full_shadow) { - mask[i].full_shadow = true; - opt->wintype_option[i].full_shadow = false; - } - if (!mask[i].redir_ignore) { - mask[i].redir_ignore = true; - opt->wintype_option[i].redir_ignore = false; - } - if (!mask[i].opacity) { - mask[i].opacity = true; - // Opacity is not set to a concrete number here because the opacity logic - // is complicated, and needs an "unset" state - opt->wintype_option[i].opacity = NAN; - } - } + // Focused/unfocused state only apply to a few window types, all other windows + // are always considered focused. + const wintype_t nofocus_type[] = {WINTYPE_UNKNOWN, WINTYPE_NORMAL, WINTYPE_UTILITY}; + for (unsigned long i = 0; i < ARR_SIZE(nofocus_type); i++) { + if (!mask[nofocus_type[i]].focus) { + mask[nofocus_type[i]].focus = true; + opt->wintype_option[nofocus_type[i]].focus = false; + } + } + for (unsigned long i = 0; i < NUM_WINTYPES; i++) { + if (!mask[i].shadow) { + mask[i].shadow = true; + opt->wintype_option[i].shadow = shadow_enable; + } + if (!mask[i].fade) { + mask[i].fade = true; + opt->wintype_option[i].fade = fading_enable; + } + if (!mask[i].focus) { + mask[i].focus = true; + opt->wintype_option[i].focus = true; + } + if (!mask[i].full_shadow) { + mask[i].full_shadow = true; + opt->wintype_option[i].full_shadow = false; + } + if (!mask[i].redir_ignore) { + mask[i].redir_ignore = true; + opt->wintype_option[i].redir_ignore = false; + } + if (!mask[i].opacity) { + mask[i].opacity = true; + // Opacity is not set to a concrete number here because the + // opacity logic is complicated, and needs an "unset" state + opt->wintype_option[i].opacity = NAN; + } + } } -char *parse_config(options_t *opt, const char *config_file, - bool *shadow_enable, bool *fading_enable, bool *hasneg, - win_option_mask_t *winopt_mask) { - char *ret = NULL; +char *parse_config(options_t *opt, const char *config_file, bool *shadow_enable, + bool *fading_enable, bool *hasneg, win_option_mask_t *winopt_mask) { + char *ret = NULL; #ifdef CONFIG_LIBCONFIG - ret = parse_config_libconfig(opt, config_file, shadow_enable, fading_enable, - hasneg, winopt_mask); + ret = parse_config_libconfig(opt, config_file, shadow_enable, fading_enable, + hasneg, winopt_mask); #endif - return ret; + return ret; } diff --git a/src/config.h b/src/config.h index 3c31d21..65a736a 100644 --- a/src/config.h +++ b/src/config.h @@ -7,24 +7,24 @@ /// Common functions and definitions for configuration parsing /// Used for command line arguments and config files -#include -#include #include +#include +#include #include +#include // for xcb_render_fixed_t, XXX #include -#include // for xcb_render_fixed_t, XXX #include #ifdef CONFIG_LIBCONFIG #include #endif -#include "region.h" -#include "log.h" #include "compiler.h" -#include "win.h" -#include "types.h" #include "kernel.h" +#include "log.h" +#include "region.h" +#include "types.h" +#include "win.h" 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]; attr_warn_unused_result bool parse_long(const char *, long *); -attr_warn_unused_result bool -parse_blur_kern_lst(const char *, conv **, int, bool *hasneg); +attr_warn_unused_result bool 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_rule_opacity(c2_lptr_t **, const char *); diff --git a/src/config_libconfig.c b/src/config_libconfig.c index dae94b7..b03e601 100644 --- a/src/config_libconfig.c +++ b/src/config_libconfig.c @@ -1,22 +1,22 @@ // SPDX-License-Identifier: MIT // Copyright (c) 2012-2014 Richard Grenville -#include #include #include #include +#include -#include -#include #include +#include +#include -#include "err.h" #include "common.h" #include "compiler.h" #include "config.h" -#include "string_utils.h" -#include "options.h" +#include "err.h" #include "log.h" +#include "options.h" +#include "string_utils.h" #include "utils.h" #include "win.h" @@ -27,37 +27,32 @@ * * So it takes a pointer to bool. */ -static inline int -lcfg_lookup_bool(const config_t *config, const char *path, bool *value) { - int ival; +static inline int lcfg_lookup_bool(const config_t *config, const char *path, bool *value) { + int ival; - int ret = config_lookup_bool(config, path, &ival); - if (ret) - *value = ival; + int ret = config_lookup_bool(config, path, &ival); + if (ret) + *value = ival; - return ret; + return ret; } /// Search for config file under a base directory -FILE * -open_config_file_at(const char *base, char **out_path) { - static const char *config_paths[] = { - "/compton.conf", - "/compton/compton.conf" - }; - for (size_t i = 0; i < ARR_SIZE(config_paths); i++) { - char *path = mstrjoin(base, config_paths[i]); - FILE *ret = fopen(path, "r"); - if (ret && out_path) { - *out_path = path; - } else { - free(path); - } - if (ret) { - return ret; - } - } - return NULL; +FILE *open_config_file_at(const char *base, char **out_path) { + static const char *config_paths[] = {"/compton.conf", "/compton/compton.conf"}; + for (size_t i = 0; i < ARR_SIZE(config_paths); i++) { + char *path = mstrjoin(base, config_paths[i]); + FILE *ret = fopen(path, "r"); + if (ret && out_path) { + *out_path = path; + } else { + free(path); + } + if (ret) { + return ret; + } + } + return NULL; } /** @@ -65,73 +60,71 @@ open_config_file_at(const char *base, char **out_path) { * * Follows the XDG specification to search for the configuration file. */ -FILE * -open_config_file(const char *cpath, char **ppath) { - static const char config_filename_legacy[] = "/.compton.conf"; +FILE *open_config_file(const char *cpath, char **ppath) { + static const char config_filename_legacy[] = "/.compton.conf"; - if (cpath) { - FILE *ret = fopen(cpath, "r"); - if (ret && ppath) - *ppath = strdup(cpath); - return ret; - } + if (cpath) { + FILE *ret = fopen(cpath, "r"); + if (ret && ppath) + *ppath = strdup(cpath); + return ret; + } - // First search for config file in user config directory - auto config_home = xdgConfigHome(NULL); - auto ret = open_config_file_at(config_home, ppath); - free((void *)config_home); - if (ret) { - return ret; - } + // First search for config file in user config directory + auto config_home = xdgConfigHome(NULL); + auto ret = open_config_file_at(config_home, ppath); + free((void *)config_home); + if (ret) { + return ret; + } - // Fall back to legacy config file in user home directory - const char *home = getenv("HOME"); - if (home && strlen(home)) { - auto path = mstrjoin(home, config_filename_legacy); - ret = fopen(path, "r"); - if (ret && ppath) { - *ppath = path; - } else { - free(path); - } - if (ret) { - return ret; - } - } + // Fall back to legacy config file in user home directory + const char *home = getenv("HOME"); + if (home && strlen(home)) { + auto path = mstrjoin(home, config_filename_legacy); + ret = fopen(path, "r"); + if (ret && ppath) { + *ppath = path; + } else { + free(path); + } + if (ret) { + return ret; + } + } - // Fall back to config file in system config directory - auto config_dirs = xdgConfigDirectories(NULL); - for (int i = 0; config_dirs[i]; i++) { - ret = open_config_file_at(config_dirs[i], ppath); - if (ret) { - free((void *)config_dirs); - return ret; - } - } - free((void *)config_dirs); + // Fall back to config file in system config directory + auto config_dirs = xdgConfigDirectories(NULL); + for (int i = 0; config_dirs[i]; i++) { + ret = open_config_file_at(config_dirs[i], ppath); + if (ret) { + free((void *)config_dirs); + return ret; + } + } + free((void *)config_dirs); - return NULL; + return NULL; } /** * Parse a condition list in configuration file. */ -void -parse_cfg_condlst(const config_t *pcfg, c2_lptr_t **pcondlst, - const char *name) { - config_setting_t *setting = config_lookup(pcfg, name); - if (setting) { - // Parse an array of options - if (config_setting_is_array(setting)) { - int i = config_setting_length(setting); - while (i--) - condlst_add(pcondlst, config_setting_get_string_elem(setting, i)); - } - // Treat it as a single pattern if it's a string - else if (CONFIG_TYPE_STRING == config_setting_type(setting)) { - condlst_add(pcondlst, config_setting_get_string(setting)); - } - } +void parse_cfg_condlst(const config_t *pcfg, c2_lptr_t **pcondlst, const char *name) { + config_setting_t *setting = config_lookup(pcfg, name); + if (setting) { + // Parse an array of options + if (config_setting_is_array(setting)) { + int i = config_setting_length(setting); + while (i--) + condlst_add(pcondlst, + config_setting_get_string_elem(setting, i)); + } + // Treat it as a single pattern if it's a string + else if (CONFIG_TYPE_STRING == config_setting_type(setting)) { + condlst_add(pcondlst, config_setting_get_string(setting)); + } + } } /** @@ -139,22 +132,24 @@ parse_cfg_condlst(const config_t *pcfg, c2_lptr_t **pcondlst, */ static inline void parse_cfg_condlst_opct(options_t *opt, const config_t *pcfg, const char *name) { - config_setting_t *setting = config_lookup(pcfg, name); - if (setting) { - // Parse an array of options - if (config_setting_is_array(setting)) { - int i = config_setting_length(setting); - while (i--) - if (!parse_rule_opacity(&opt->opacity_rules, - config_setting_get_string_elem(setting, i))) - exit(1); - } - // Treat it as a single pattern if it's a string - else if (config_setting_type(setting) == CONFIG_TYPE_STRING) { - if (!parse_rule_opacity(&opt->opacity_rules, config_setting_get_string(setting))) - exit(1); - } - } + config_setting_t *setting = config_lookup(pcfg, name); + if (setting) { + // Parse an array of options + if (config_setting_is_array(setting)) { + int i = config_setting_length(setting); + while (i--) + if (!parse_rule_opacity( + &opt->opacity_rules, + config_setting_get_string_elem(setting, i))) + exit(1); + } + // Treat it as a single pattern if it's a string + else if (config_setting_type(setting) == CONFIG_TYPE_STRING) { + if (!parse_rule_opacity(&opt->opacity_rules, + config_setting_get_string(setting))) + exit(1); + } + } } /** @@ -163,316 +158,311 @@ parse_cfg_condlst_opct(options_t *opt, const config_t *pcfg, const char *name) { * Returns the actually config_file name */ 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) -{ - char *path = NULL; - FILE *f; - config_t cfg; - int ival = 0; - bool bval; - double dval = 0.0; - // libconfig manages string memory itself, so no need to manually free - // anything - const char *sval = NULL; + bool *fading_enable, bool *conv_kern_hasneg, + win_option_mask_t *winopt_mask) { + char *path = NULL; + FILE *f; + config_t cfg; + int ival = 0; + bool bval; + double dval = 0.0; + // libconfig manages string memory itself, so no need to manually free + // anything + const char *sval = NULL; - f = open_config_file(config_file, &path); - if (!f) { - free(path); - if (config_file) { - log_fatal("Failed to read configuration file \"%s\".", config_file); - return ERR_PTR(-1); - } - return NULL; - } + f = open_config_file(config_file, &path); + if (!f) { + free(path); + if (config_file) { + log_fatal("Failed to read configuration file \"%s\".", config_file); + return ERR_PTR(-1); + } + return NULL; + } - config_init(&cfg); - { - // dirname() could modify the original string, thus we must pass a - // copy - char *path2 = strdup(path); - char *parent = dirname(path2); + config_init(&cfg); + { + // dirname() could modify the original string, thus we must pass a + // copy + char *path2 = strdup(path); + char *parent = dirname(path2); - if (parent) - config_set_include_dir(&cfg, parent); + if (parent) + config_set_include_dir(&cfg, parent); - free(path2); - } + free(path2); + } - { - int read_result = config_read(&cfg, f); - fclose(f); - f = NULL; - if (read_result == CONFIG_FALSE) { - log_fatal("Error when reading configuration file \"%s\", line %d: %s", - path, config_error_line(&cfg), config_error_text(&cfg)); - goto err; - } - } - config_set_auto_convert(&cfg, 1); + { + int read_result = config_read(&cfg, f); + fclose(f); + f = NULL; + if (read_result == CONFIG_FALSE) { + log_fatal("Error when reading configuration file \"%s\", line " + "%d: %s", + path, config_error_line(&cfg), config_error_text(&cfg)); + goto err; + } + } + config_set_auto_convert(&cfg, 1); - // Get options from the configuration file. We don't do range checking - // right now. It will be done later + // Get options from the configuration file. We don't do range checking + // right now. It will be done later - // -D (fade_delta) - if (config_lookup_int(&cfg, "fade-delta", &ival)) - opt->fade_delta = ival; - // -I (fade_in_step) - if (config_lookup_float(&cfg, "fade-in-step", &dval)) - opt->fade_in_step = normalize_d(dval); - // -O (fade_out_step) - if (config_lookup_float(&cfg, "fade-out-step", &dval)) - opt->fade_out_step = normalize_d(dval); - // -r (shadow_radius) - config_lookup_int(&cfg, "shadow-radius", &opt->shadow_radius); - // -o (shadow_opacity) - config_lookup_float(&cfg, "shadow-opacity", &opt->shadow_opacity); - // -l (shadow_offset_x) - config_lookup_int(&cfg, "shadow-offset-x", &opt->shadow_offset_x); - // -t (shadow_offset_y) - config_lookup_int(&cfg, "shadow-offset-y", &opt->shadow_offset_y); - // -i (inactive_opacity) - if (config_lookup_float(&cfg, "inactive-opacity", &dval)) - opt->inactive_opacity = normalize_d(dval); - // --active_opacity - if (config_lookup_float(&cfg, "active-opacity", &dval)) - opt->active_opacity = normalize_d(dval); - // -e (frame_opacity) - config_lookup_float(&cfg, "frame-opacity", &opt->frame_opacity); - // -c (shadow_enable) - if (config_lookup_bool(&cfg, "shadow", &ival)) - *shadow_enable = ival; - // -C (no_dock_shadow) - if (config_lookup_bool(&cfg, "no-dock-shadow", &ival)) { - log_warn("Option `no-dock-shadow` is deprecated, and will be removed." - " Please use the wintype option `shadow` of `dock` instead."); - opt->wintype_option[WINTYPE_DOCK].shadow = false; - winopt_mask[WINTYPE_DOCK].shadow = true; - } - // -G (no_dnd_shadow) - if (config_lookup_bool(&cfg, "no-dnd-shadow", &ival)) { - log_warn("Option `no-dnd-shadow` is deprecated, and will be removed." - " Please use the wintype option `shadow` of `dnd` instead."); - opt->wintype_option[WINTYPE_DND].shadow = false; - winopt_mask[WINTYPE_DND].shadow = true; - }; - // -m (menu_opacity) - if (config_lookup_float(&cfg, "menu-opacity", &dval)) { - log_warn("Option `menu-opacity` is deprecated, and will be 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_POPUP_MENU].opacity = dval; - winopt_mask[WINTYPE_DROPDOWN_MENU].opacity = true; - winopt_mask[WINTYPE_POPUP_MENU].opacity = true; - } - // -f (fading_enable) - if (config_lookup_bool(&cfg, "fading", &ival)) - *fading_enable = ival; - // --no-fading-open-close - lcfg_lookup_bool(&cfg, "no-fading-openclose", &opt->no_fading_openclose); - // --no-fading-destroyed-argb - lcfg_lookup_bool(&cfg, "no-fading-destroyed-argb", - &opt->no_fading_destroyed_argb); - // --shadow-red - config_lookup_float(&cfg, "shadow-red", &opt->shadow_red); - // --shadow-green - config_lookup_float(&cfg, "shadow-green", &opt->shadow_green); - // --shadow-blue - config_lookup_float(&cfg, "shadow-blue", &opt->shadow_blue); - // --shadow-exclude-reg - if (config_lookup_string(&cfg, "shadow-exclude-reg", &sval)) - opt->shadow_exclude_reg_str = strdup(sval); - // --inactive-opacity-override - lcfg_lookup_bool(&cfg, "inactive-opacity-override", - &opt->inactive_opacity_override); - // --inactive-dim - config_lookup_float(&cfg, "inactive-dim", &opt->inactive_dim); - // --mark-wmwin-focused - lcfg_lookup_bool(&cfg, "mark-wmwin-focused", &opt->mark_wmwin_focused); - // --mark-ovredir-focused - lcfg_lookup_bool(&cfg, "mark-ovredir-focused", - &opt->mark_ovredir_focused); - // --shadow-ignore-shaped - lcfg_lookup_bool(&cfg, "shadow-ignore-shaped", - &opt->shadow_ignore_shaped); - // --detect-rounded-corners - lcfg_lookup_bool(&cfg, "detect-rounded-corners", - &opt->detect_rounded_corners); - // --xinerama-shadow-crop - lcfg_lookup_bool(&cfg, "xinerama-shadow-crop", - &opt->xinerama_shadow_crop); - // --detect-client-opacity - lcfg_lookup_bool(&cfg, "detect-client-opacity", - &opt->detect_client_opacity); - // --refresh-rate - config_lookup_int(&cfg, "refresh-rate", &opt->refresh_rate); - // --vsync - if (config_lookup_string(&cfg, "vsync", &sval)) { - opt->vsync = parse_vsync(sval); - if (opt->vsync >= NUM_VSYNC) { - log_fatal("Cannot parse vsync"); - goto err; - } - } - // --backend - if (config_lookup_string(&cfg, "backend", &sval)) { - opt->backend = parse_backend(sval); - if (opt->backend >= NUM_BKEND) { - log_fatal("Cannot parse backend"); - goto err; - } - } - // --log-level - if (config_lookup_string(&cfg, "log-level", &sval)) { - auto level = string_to_log_level(sval); - if (level == LOG_LEVEL_INVALID) { - log_warn("Invalid log level, defaults to WARN"); - } else { - log_set_level_tls(level); - } - } - // --log-file - if (config_lookup_string(&cfg, "log-file", &sval)) { - if (*sval != '/') { - log_warn("The log-file in your configuration file is not an absolute path"); - } - opt->logpath = strdup(sval); - } - // --sw-opti - lcfg_lookup_bool(&cfg, "sw-opti", &opt->sw_opti); - // --use-ewmh-active-win - lcfg_lookup_bool(&cfg, "use-ewmh-active-win", - &opt->use_ewmh_active_win); - // --unredir-if-possible - lcfg_lookup_bool(&cfg, "unredir-if-possible", - &opt->unredir_if_possible); - // --unredir-if-possible-delay - if (config_lookup_int(&cfg, "unredir-if-possible-delay", &ival)) - opt->unredir_if_possible_delay = ival; - // --inactive-dim-fixed - lcfg_lookup_bool(&cfg, "inactive-dim-fixed", &opt->inactive_dim_fixed); - // --detect-transient - lcfg_lookup_bool(&cfg, "detect-transient", &opt->detect_transient); - // --detect-client-leader - lcfg_lookup_bool(&cfg, "detect-client-leader", - &opt->detect_client_leader); - // --shadow-exclude - parse_cfg_condlst(&cfg, &opt->shadow_blacklist, "shadow-exclude"); - // --fade-exclude - parse_cfg_condlst(&cfg, &opt->fade_blacklist, "fade-exclude"); - // --focus-exclude - parse_cfg_condlst(&cfg, &opt->focus_blacklist, "focus-exclude"); - // --invert-color-include - parse_cfg_condlst(&cfg, &opt->invert_color_list, "invert-color-include"); - // --blur-background-exclude - parse_cfg_condlst(&cfg, &opt->blur_background_blacklist, "blur-background-exclude"); - // --opacity-rule - parse_cfg_condlst_opct(opt, &cfg, "opacity-rule"); - // --unredir-if-possible-exclude - parse_cfg_condlst(&cfg, &opt->unredir_if_possible_blacklist, "unredir-if-possible-exclude"); - // --blur-background - lcfg_lookup_bool(&cfg, "blur-background", &opt->blur_background); - // --blur-background-frame - lcfg_lookup_bool(&cfg, "blur-background-frame", - &opt->blur_background_frame); - // --blur-background-fixed - lcfg_lookup_bool(&cfg, "blur-background-fixed", - &opt->blur_background_fixed); - // --blur-kern - if (config_lookup_string(&cfg, "blur-kern", &sval) && - !parse_blur_kern_lst(sval, opt->blur_kerns, MAX_BLUR_PASS, conv_kern_hasneg)) { - log_fatal("Cannot parse \"blur-kern\""); - goto err; - } - // --resize-damage - config_lookup_int(&cfg, "resize-damage", &opt->resize_damage); - // --glx-no-stencil - lcfg_lookup_bool(&cfg, "glx-no-stencil", &opt->glx_no_stencil); - // --glx-no-rebind-pixmap - lcfg_lookup_bool(&cfg, "glx-no-rebind-pixmap", &opt->glx_no_rebind_pixmap); - // --glx-swap-method - if (config_lookup_string(&cfg, "glx-swap-method", &sval)) { - opt->glx_swap_method = parse_glx_swap_method(sval); - if (opt->glx_swap_method == -2) { - log_fatal("Cannot parse \"glx-swap-method\""); - goto err; - } - } - // --glx-use-gpushader4 - if (config_lookup_bool(&cfg, "glx-use-gpushader4", &ival) && ival) { - log_warn("glx-use-gpushader4 is deprecated since v6, please remove it from" - "your config file"); - } - // --xrender-sync - if (config_lookup_bool(&cfg, "xrender-sync", &ival) && ival) { - log_warn("Please use xrender-sync-fence instead of xrender-sync."); - opt->xrender_sync_fence = true; - } - // --xrender-sync-fence - lcfg_lookup_bool(&cfg, "xrender-sync-fence", &opt->xrender_sync_fence); + // -D (fade_delta) + if (config_lookup_int(&cfg, "fade-delta", &ival)) + opt->fade_delta = ival; + // -I (fade_in_step) + if (config_lookup_float(&cfg, "fade-in-step", &dval)) + opt->fade_in_step = normalize_d(dval); + // -O (fade_out_step) + if (config_lookup_float(&cfg, "fade-out-step", &dval)) + opt->fade_out_step = normalize_d(dval); + // -r (shadow_radius) + config_lookup_int(&cfg, "shadow-radius", &opt->shadow_radius); + // -o (shadow_opacity) + config_lookup_float(&cfg, "shadow-opacity", &opt->shadow_opacity); + // -l (shadow_offset_x) + config_lookup_int(&cfg, "shadow-offset-x", &opt->shadow_offset_x); + // -t (shadow_offset_y) + config_lookup_int(&cfg, "shadow-offset-y", &opt->shadow_offset_y); + // -i (inactive_opacity) + if (config_lookup_float(&cfg, "inactive-opacity", &dval)) + opt->inactive_opacity = normalize_d(dval); + // --active_opacity + if (config_lookup_float(&cfg, "active-opacity", &dval)) + opt->active_opacity = normalize_d(dval); + // -e (frame_opacity) + config_lookup_float(&cfg, "frame-opacity", &opt->frame_opacity); + // -c (shadow_enable) + if (config_lookup_bool(&cfg, "shadow", &ival)) + *shadow_enable = ival; + // -C (no_dock_shadow) + if (config_lookup_bool(&cfg, "no-dock-shadow", &ival)) { + log_warn("Option `no-dock-shadow` is deprecated, and will be removed." + " Please use the wintype option `shadow` of `dock` instead."); + opt->wintype_option[WINTYPE_DOCK].shadow = false; + winopt_mask[WINTYPE_DOCK].shadow = true; + } + // -G (no_dnd_shadow) + if (config_lookup_bool(&cfg, "no-dnd-shadow", &ival)) { + log_warn("Option `no-dnd-shadow` is deprecated, and will be removed." + " Please use the wintype option `shadow` of `dnd` instead."); + opt->wintype_option[WINTYPE_DND].shadow = false; + winopt_mask[WINTYPE_DND].shadow = true; + }; + // -m (menu_opacity) + if (config_lookup_float(&cfg, "menu-opacity", &dval)) { + log_warn("Option `menu-opacity` is deprecated, and will be " + "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_POPUP_MENU].opacity = dval; + winopt_mask[WINTYPE_DROPDOWN_MENU].opacity = true; + winopt_mask[WINTYPE_POPUP_MENU].opacity = true; + } + // -f (fading_enable) + if (config_lookup_bool(&cfg, "fading", &ival)) + *fading_enable = ival; + // --no-fading-open-close + lcfg_lookup_bool(&cfg, "no-fading-openclose", &opt->no_fading_openclose); + // --no-fading-destroyed-argb + lcfg_lookup_bool(&cfg, "no-fading-destroyed-argb", &opt->no_fading_destroyed_argb); + // --shadow-red + config_lookup_float(&cfg, "shadow-red", &opt->shadow_red); + // --shadow-green + config_lookup_float(&cfg, "shadow-green", &opt->shadow_green); + // --shadow-blue + config_lookup_float(&cfg, "shadow-blue", &opt->shadow_blue); + // --shadow-exclude-reg + if (config_lookup_string(&cfg, "shadow-exclude-reg", &sval)) + opt->shadow_exclude_reg_str = strdup(sval); + // --inactive-opacity-override + lcfg_lookup_bool(&cfg, "inactive-opacity-override", &opt->inactive_opacity_override); + // --inactive-dim + config_lookup_float(&cfg, "inactive-dim", &opt->inactive_dim); + // --mark-wmwin-focused + lcfg_lookup_bool(&cfg, "mark-wmwin-focused", &opt->mark_wmwin_focused); + // --mark-ovredir-focused + lcfg_lookup_bool(&cfg, "mark-ovredir-focused", &opt->mark_ovredir_focused); + // --shadow-ignore-shaped + lcfg_lookup_bool(&cfg, "shadow-ignore-shaped", &opt->shadow_ignore_shaped); + // --detect-rounded-corners + lcfg_lookup_bool(&cfg, "detect-rounded-corners", &opt->detect_rounded_corners); + // --xinerama-shadow-crop + lcfg_lookup_bool(&cfg, "xinerama-shadow-crop", &opt->xinerama_shadow_crop); + // --detect-client-opacity + lcfg_lookup_bool(&cfg, "detect-client-opacity", &opt->detect_client_opacity); + // --refresh-rate + config_lookup_int(&cfg, "refresh-rate", &opt->refresh_rate); + // --vsync + if (config_lookup_string(&cfg, "vsync", &sval)) { + opt->vsync = parse_vsync(sval); + if (opt->vsync >= NUM_VSYNC) { + log_fatal("Cannot parse vsync"); + goto err; + } + } + // --backend + if (config_lookup_string(&cfg, "backend", &sval)) { + opt->backend = parse_backend(sval); + if (opt->backend >= NUM_BKEND) { + log_fatal("Cannot parse backend"); + goto err; + } + } + // --log-level + if (config_lookup_string(&cfg, "log-level", &sval)) { + auto level = string_to_log_level(sval); + if (level == LOG_LEVEL_INVALID) { + log_warn("Invalid log level, defaults to WARN"); + } else { + log_set_level_tls(level); + } + } + // --log-file + if (config_lookup_string(&cfg, "log-file", &sval)) { + if (*sval != '/') { + log_warn("The log-file in your configuration file is not an " + "absolute path"); + } + opt->logpath = strdup(sval); + } + // --sw-opti + lcfg_lookup_bool(&cfg, "sw-opti", &opt->sw_opti); + // --use-ewmh-active-win + lcfg_lookup_bool(&cfg, "use-ewmh-active-win", &opt->use_ewmh_active_win); + // --unredir-if-possible + lcfg_lookup_bool(&cfg, "unredir-if-possible", &opt->unredir_if_possible); + // --unredir-if-possible-delay + if (config_lookup_int(&cfg, "unredir-if-possible-delay", &ival)) + opt->unredir_if_possible_delay = ival; + // --inactive-dim-fixed + lcfg_lookup_bool(&cfg, "inactive-dim-fixed", &opt->inactive_dim_fixed); + // --detect-transient + lcfg_lookup_bool(&cfg, "detect-transient", &opt->detect_transient); + // --detect-client-leader + lcfg_lookup_bool(&cfg, "detect-client-leader", &opt->detect_client_leader); + // --shadow-exclude + parse_cfg_condlst(&cfg, &opt->shadow_blacklist, "shadow-exclude"); + // --fade-exclude + parse_cfg_condlst(&cfg, &opt->fade_blacklist, "fade-exclude"); + // --focus-exclude + parse_cfg_condlst(&cfg, &opt->focus_blacklist, "focus-exclude"); + // --invert-color-include + parse_cfg_condlst(&cfg, &opt->invert_color_list, "invert-color-include"); + // --blur-background-exclude + parse_cfg_condlst(&cfg, &opt->blur_background_blacklist, "blur-background-exclude"); + // --opacity-rule + parse_cfg_condlst_opct(opt, &cfg, "opacity-rule"); + // --unredir-if-possible-exclude + parse_cfg_condlst(&cfg, &opt->unredir_if_possible_blacklist, + "unredir-if-possible-exclude"); + // --blur-background + lcfg_lookup_bool(&cfg, "blur-background", &opt->blur_background); + // --blur-background-frame + lcfg_lookup_bool(&cfg, "blur-background-frame", &opt->blur_background_frame); + // --blur-background-fixed + lcfg_lookup_bool(&cfg, "blur-background-fixed", &opt->blur_background_fixed); + // --blur-kern + if (config_lookup_string(&cfg, "blur-kern", &sval) && + !parse_blur_kern_lst(sval, opt->blur_kerns, MAX_BLUR_PASS, conv_kern_hasneg)) { + log_fatal("Cannot parse \"blur-kern\""); + goto err; + } + // --resize-damage + config_lookup_int(&cfg, "resize-damage", &opt->resize_damage); + // --glx-no-stencil + lcfg_lookup_bool(&cfg, "glx-no-stencil", &opt->glx_no_stencil); + // --glx-no-rebind-pixmap + lcfg_lookup_bool(&cfg, "glx-no-rebind-pixmap", &opt->glx_no_rebind_pixmap); + // --glx-swap-method + if (config_lookup_string(&cfg, "glx-swap-method", &sval)) { + opt->glx_swap_method = parse_glx_swap_method(sval); + if (opt->glx_swap_method == -2) { + log_fatal("Cannot parse \"glx-swap-method\""); + goto err; + } + } + // --glx-use-gpushader4 + if (config_lookup_bool(&cfg, "glx-use-gpushader4", &ival) && ival) { + log_warn("glx-use-gpushader4 is deprecated since v6, please remove it " + "from" + "your config file"); + } + // --xrender-sync + if (config_lookup_bool(&cfg, "xrender-sync", &ival) && ival) { + log_warn("Please use xrender-sync-fence instead of xrender-sync."); + opt->xrender_sync_fence = true; + } + // --xrender-sync-fence + lcfg_lookup_bool(&cfg, "xrender-sync-fence", &opt->xrender_sync_fence); - if (lcfg_lookup_bool(&cfg, "clear-shadow", &bval)) - log_warn("\"clear-shadow\" is removed as an option, and is always" - " enabled now. Consider removing it from your config file"); - if (lcfg_lookup_bool(&cfg, "paint-on-overlay", &bval)) - log_warn("\"paint-on-overlay\" has been removed as an option, and " - "is enabled whenever possible"); + if (lcfg_lookup_bool(&cfg, "clear-shadow", &bval)) + log_warn("\"clear-shadow\" is removed as an option, and is always" + " enabled now. Consider removing it from your config file"); + if (lcfg_lookup_bool(&cfg, "paint-on-overlay", &bval)) + log_warn("\"paint-on-overlay\" has been removed as an option, and " + "is enabled whenever possible"); - if (config_lookup_float(&cfg, "alpha-step", &dval)) - log_warn("\"alpha-step\" has been removed, compton now tries to make use" - " of all alpha values"); + if (config_lookup_float(&cfg, "alpha-step", &dval)) + log_warn("\"alpha-step\" has been removed, compton now tries to make use" + " of all alpha values"); - const char *deprecation_message = "has been removed. If you encounter problems " - "without this feature, please feel free to open a bug report"; - if (lcfg_lookup_bool(&cfg, "glx-use-copysubbuffermesa", &bval) && bval) - log_warn("\"glx-use-copysubbuffermesa\" %s", deprecation_message); - if (lcfg_lookup_bool(&cfg, "glx-copy-from-front", &bval) && bval) - log_warn("\"glx-copy-from-front\" %s", deprecation_message); + const char *deprecation_message = + "has been removed. If you encounter problems " + "without this feature, please feel free to open a bug report"; + if (lcfg_lookup_bool(&cfg, "glx-use-copysubbuffermesa", &bval) && bval) + log_warn("\"glx-use-copysubbuffermesa\" %s", deprecation_message); + if (lcfg_lookup_bool(&cfg, "glx-copy-from-front", &bval) && bval) + log_warn("\"glx-copy-from-front\" %s", deprecation_message); - // Wintype settings + // Wintype settings - // XXX ! Refactor all the wintype_* arrays into a struct - for (wintype_t i = 0; i < NUM_WINTYPES; ++i) { - char *str = mstrjoin("wintypes.", WINTYPES[i]); - config_setting_t *setting = config_lookup(&cfg, str); - free(str); + // XXX ! Refactor all the wintype_* arrays into a struct + for (wintype_t i = 0; i < NUM_WINTYPES; ++i) { + char *str = mstrjoin("wintypes.", WINTYPES[i]); + config_setting_t *setting = config_lookup(&cfg, str); + free(str); - win_option_t *o = &opt->wintype_option[i]; - win_option_mask_t *mask = &winopt_mask[i]; - if (setting) { - if (config_setting_lookup_bool(setting, "shadow", &ival)) { - o->shadow = ival; - mask->shadow = true; - } - if (config_setting_lookup_bool(setting, "fade", &ival)) { - o->fade = ival; - mask->fade = true; - } - if (config_setting_lookup_bool(setting, "focus", &ival)) { - o->focus = ival; - mask->focus = true; - } - if (config_setting_lookup_bool(setting, "full-shadow", &ival)) { - o->full_shadow = ival; - mask->full_shadow = true; - } - if (config_setting_lookup_bool(setting, "redir-ignore", &ival)) { - o->redir_ignore = ival; - mask->redir_ignore = true; - } + win_option_t *o = &opt->wintype_option[i]; + win_option_mask_t *mask = &winopt_mask[i]; + if (setting) { + if (config_setting_lookup_bool(setting, "shadow", &ival)) { + o->shadow = ival; + mask->shadow = true; + } + if (config_setting_lookup_bool(setting, "fade", &ival)) { + o->fade = ival; + mask->fade = true; + } + if (config_setting_lookup_bool(setting, "focus", &ival)) { + o->focus = ival; + mask->focus = true; + } + if (config_setting_lookup_bool(setting, "full-shadow", &ival)) { + o->full_shadow = ival; + mask->full_shadow = true; + } + if (config_setting_lookup_bool(setting, "redir-ignore", &ival)) { + o->redir_ignore = ival; + mask->redir_ignore = true; + } - double fval; - if (config_setting_lookup_float(setting, "opacity", &fval)) { - o->opacity = normalize_d(fval); - mask->opacity = true; - } - } - } + double fval; + if (config_setting_lookup_float(setting, "opacity", &fval)) { + o->opacity = normalize_d(fval); + mask->opacity = true; + } + } + } - config_destroy(&cfg); - return path; + config_destroy(&cfg); + return path; err: - config_destroy(&cfg); - free(path); - return ERR_PTR(-1); + config_destroy(&cfg); + free(path); + return ERR_PTR(-1); } diff --git a/src/dbus.c b/src/dbus.c index 6ddd9bb..6fb62a7 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -9,212 +9,207 @@ * */ -#include -#include -#include -#include -#include -#include #include +#include #include +#include +#include +#include +#include +#include #include "common.h" -#include "config.h" #include "compiler.h" -#include "utils.h" -#include "types.h" -#include "win.h" -#include "string_utils.h" +#include "config.h" #include "log.h" +#include "string_utils.h" +#include "types.h" +#include "utils.h" +#include "win.h" #include "dbus.h" struct cdbus_data { - /// DBus connection. - DBusConnection *dbus_conn; - /// DBus service name. - char *dbus_service; + /// DBus connection. + DBusConnection *dbus_conn; + /// DBus service name. + char *dbus_service; }; // Window type typedef uint32_t cdbus_window_t; -#define CDBUS_TYPE_WINDOW DBUS_TYPE_UINT32 -#define CDBUS_TYPE_WINDOW_STR DBUS_TYPE_UINT32_AS_STRING +#define CDBUS_TYPE_WINDOW DBUS_TYPE_UINT32 +#define CDBUS_TYPE_WINDOW_STR DBUS_TYPE_UINT32_AS_STRING typedef uint16_t cdbus_enum_t; -#define CDBUS_TYPE_ENUM DBUS_TYPE_UINT16 -#define CDBUS_TYPE_ENUM_STR DBUS_TYPE_UINT16_AS_STRING +#define CDBUS_TYPE_ENUM DBUS_TYPE_UINT16 +#define CDBUS_TYPE_ENUM_STR DBUS_TYPE_UINT16_AS_STRING -#define CDBUS_SERVICE_NAME "com.github.chjj.compton" -#define CDBUS_INTERFACE_NAME CDBUS_SERVICE_NAME -#define CDBUS_OBJECT_NAME "/com/github/chjj/compton" -#define CDBUS_ERROR_PREFIX CDBUS_INTERFACE_NAME ".error" -#define CDBUS_ERROR_UNKNOWN CDBUS_ERROR_PREFIX ".unknown" -#define CDBUS_ERROR_UNKNOWN_S "Well, I don't know what happened. Do you?" -#define CDBUS_ERROR_BADMSG CDBUS_ERROR_PREFIX ".bad_message" -#define CDBUS_ERROR_BADMSG_S "Unrecognized command. Beware compton " \ - "cannot make you a sandwich." -#define CDBUS_ERROR_BADARG CDBUS_ERROR_PREFIX ".bad_argument" -#define CDBUS_ERROR_BADARG_S "Failed to parse argument %d: %s" -#define CDBUS_ERROR_BADWIN CDBUS_ERROR_PREFIX ".bad_window" -#define CDBUS_ERROR_BADWIN_S "Requested window %#010x not found." -#define CDBUS_ERROR_BADTGT CDBUS_ERROR_PREFIX ".bad_target" -#define CDBUS_ERROR_BADTGT_S "Target \"%s\" not found." -#define CDBUS_ERROR_FORBIDDEN CDBUS_ERROR_PREFIX ".forbidden" +#define CDBUS_SERVICE_NAME "com.github.chjj.compton" +#define CDBUS_INTERFACE_NAME CDBUS_SERVICE_NAME +#define CDBUS_OBJECT_NAME "/com/github/chjj/compton" +#define CDBUS_ERROR_PREFIX CDBUS_INTERFACE_NAME ".error" +#define CDBUS_ERROR_UNKNOWN CDBUS_ERROR_PREFIX ".unknown" +#define CDBUS_ERROR_UNKNOWN_S "Well, I don't know what happened. Do you?" +#define CDBUS_ERROR_BADMSG CDBUS_ERROR_PREFIX ".bad_message" +#define CDBUS_ERROR_BADMSG_S \ + "Unrecognized command. Beware compton " \ + "cannot make you a sandwich." +#define CDBUS_ERROR_BADARG CDBUS_ERROR_PREFIX ".bad_argument" +#define CDBUS_ERROR_BADARG_S "Failed to parse argument %d: %s" +#define CDBUS_ERROR_BADWIN CDBUS_ERROR_PREFIX ".bad_window" +#define CDBUS_ERROR_BADWIN_S "Requested window %#010x not found." +#define CDBUS_ERROR_BADTGT CDBUS_ERROR_PREFIX ".bad_target" +#define CDBUS_ERROR_BADTGT_S "Target \"%s\" not found." +#define CDBUS_ERROR_FORBIDDEN CDBUS_ERROR_PREFIX ".forbidden" #define CDBUS_ERROR_FORBIDDEN_S "Incorrect password, access denied." -#define CDBUS_ERROR_CUSTOM CDBUS_ERROR_PREFIX ".custom" -#define CDBUS_ERROR_CUSTOM_S "%s" +#define CDBUS_ERROR_CUSTOM CDBUS_ERROR_PREFIX ".custom" +#define CDBUS_ERROR_CUSTOM_S "%s" -#define cdbus_reply_err(ps, srcmsg, err_name, err_format, ...) \ - cdbus_reply_errm((ps), dbus_message_new_error_printf((srcmsg), (err_name), (err_format), ## __VA_ARGS__)) +#define cdbus_reply_err(ps, srcmsg, err_name, err_format, ...) \ + cdbus_reply_errm((ps), dbus_message_new_error_printf( \ + (srcmsg), (err_name), (err_format), ##__VA_ARGS__)) -static DBusHandlerResult -cdbus_process(DBusConnection *conn, DBusMessage *m, void *); +static DBusHandlerResult cdbus_process(DBusConnection *conn, DBusMessage *m, void *); -static dbus_bool_t -cdbus_callback_add_timeout(DBusTimeout *timeout, void *data); +static dbus_bool_t cdbus_callback_add_timeout(DBusTimeout *timeout, void *data); -static void -cdbus_callback_remove_timeout(DBusTimeout *timeout, void *data); +static void cdbus_callback_remove_timeout(DBusTimeout *timeout, void *data); -static void -cdbus_callback_timeout_toggled(DBusTimeout *timeout, void *data); +static void cdbus_callback_timeout_toggled(DBusTimeout *timeout, void *data); -static dbus_bool_t -cdbus_callback_add_watch(DBusWatch *watch, void *data); +static dbus_bool_t cdbus_callback_add_watch(DBusWatch *watch, void *data); -static void -cdbus_callback_remove_watch(DBusWatch *watch, void *data); +static void cdbus_callback_remove_watch(DBusWatch *watch, void *data); -static void -cdbus_callback_watch_toggled(DBusWatch *watch, void *data); +static void cdbus_callback_watch_toggled(DBusWatch *watch, void *data); /** * Initialize D-Bus connection. */ -bool -cdbus_init(session_t *ps, const char *uniq) { - auto cd = cmalloc(struct cdbus_data); - cd->dbus_service = NULL; +bool cdbus_init(session_t *ps, const char *uniq) { + auto cd = cmalloc(struct cdbus_data); + cd->dbus_service = NULL; - // Set ps->dbus_data here because add_watch functions need it - ps->dbus_data = cd; + // Set ps->dbus_data here because add_watch functions need it + ps->dbus_data = cd; - DBusError err = { }; + DBusError err = {}; - // Initialize - dbus_error_init(&err); + // Initialize + dbus_error_init(&err); - // Connect to D-Bus - // Use dbus_bus_get_private() so we can fully recycle it ourselves - cd->dbus_conn = dbus_bus_get_private(DBUS_BUS_SESSION, &err); - if (dbus_error_is_set(&err)) { - log_error("D-Bus connection failed (%s).", err.message); - dbus_error_free(&err); - goto fail; - } + // Connect to D-Bus + // Use dbus_bus_get_private() so we can fully recycle it ourselves + cd->dbus_conn = dbus_bus_get_private(DBUS_BUS_SESSION, &err); + if (dbus_error_is_set(&err)) { + log_error("D-Bus connection failed (%s).", err.message); + dbus_error_free(&err); + goto fail; + } - if (!cd->dbus_conn) { - log_error("D-Bus connection failed for unknown reason."); - goto fail; - } + if (!cd->dbus_conn) { + log_error("D-Bus connection failed for unknown reason."); + goto fail; + } - // Avoid exiting on disconnect - dbus_connection_set_exit_on_disconnect(cd->dbus_conn, false); + // Avoid exiting on disconnect + dbus_connection_set_exit_on_disconnect(cd->dbus_conn, false); - // Request service name - { - // Build service name - size_t service_len = strlen(CDBUS_SERVICE_NAME)+strlen(uniq)+2; - char *service = ccalloc(service_len, char); - snprintf(service, service_len, "%s.%s", CDBUS_SERVICE_NAME, uniq); + // Request service name + { + // Build service name + size_t service_len = strlen(CDBUS_SERVICE_NAME) + strlen(uniq) + 2; + char *service = ccalloc(service_len, char); + snprintf(service, service_len, "%s.%s", CDBUS_SERVICE_NAME, uniq); - // Make a valid dbus name by converting non alphanumeric characters to underscore - char *tmp = service + strlen(CDBUS_SERVICE_NAME)+1; - while (*tmp) { - if (!isalnum(*tmp)) { - *tmp = '_'; - } - tmp++; - } - cd->dbus_service = service; + // Make a valid dbus name by converting non alphanumeric characters to + // underscore + char *tmp = service + strlen(CDBUS_SERVICE_NAME) + 1; + while (*tmp) { + if (!isalnum(*tmp)) { + *tmp = '_'; + } + tmp++; + } + cd->dbus_service = service; - // Request for the name - int ret = dbus_bus_request_name(cd->dbus_conn, service, - DBUS_NAME_FLAG_DO_NOT_QUEUE, &err); + // Request for the name + int ret = dbus_bus_request_name(cd->dbus_conn, service, + DBUS_NAME_FLAG_DO_NOT_QUEUE, &err); - if (dbus_error_is_set(&err)) { - log_error("Failed to obtain D-Bus name (%s).", err.message); - dbus_error_free(&err); - goto fail; - } + if (dbus_error_is_set(&err)) { + log_error("Failed to obtain D-Bus name (%s).", err.message); + dbus_error_free(&err); + goto fail; + } - if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret - && DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER != ret) { - log_error("Failed to become the primary owner of requested D-Bus name (%d).", ret); - goto fail; - } - } + if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret && + DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER != ret) { + log_error("Failed to become the primary owner of requested D-Bus " + "name (%d).", + ret); + goto fail; + } + } + // Add watch handlers + if (!dbus_connection_set_watch_functions(cd->dbus_conn, cdbus_callback_add_watch, + cdbus_callback_remove_watch, + cdbus_callback_watch_toggled, ps, NULL)) { + log_error("Failed to add D-Bus watch functions."); + goto fail; + } - // Add watch handlers - if (!dbus_connection_set_watch_functions(cd->dbus_conn, - cdbus_callback_add_watch, cdbus_callback_remove_watch, - cdbus_callback_watch_toggled, ps, NULL)) { - log_error("Failed to add D-Bus watch functions."); - goto fail; - } + // Add timeout handlers + if (!dbus_connection_set_timeout_functions( + cd->dbus_conn, cdbus_callback_add_timeout, cdbus_callback_remove_timeout, + cdbus_callback_timeout_toggled, ps, NULL)) { + log_error("Failed to add D-Bus timeout functions."); + goto fail; + } - // Add timeout handlers - if (!dbus_connection_set_timeout_functions(cd->dbus_conn, - cdbus_callback_add_timeout, cdbus_callback_remove_timeout, - cdbus_callback_timeout_toggled, ps, NULL)) { - log_error("Failed to add D-Bus timeout functions."); - goto fail; - } - - // Add match - dbus_bus_add_match(cd->dbus_conn, - "type='method_call',interface='" CDBUS_INTERFACE_NAME "'", &err); - if (dbus_error_is_set(&err)) { - log_error("Failed to add D-Bus match."); - dbus_error_free(&err); - goto fail; - } - dbus_connection_add_filter(cd->dbus_conn, cdbus_process, ps, NULL); - return true; + // Add match + dbus_bus_add_match(cd->dbus_conn, + "type='method_call',interface='" CDBUS_INTERFACE_NAME "'", &err); + if (dbus_error_is_set(&err)) { + log_error("Failed to add D-Bus match."); + dbus_error_free(&err); + goto fail; + } + dbus_connection_add_filter(cd->dbus_conn, cdbus_process, ps, NULL); + return true; fail: - ps->dbus_data = NULL; - free(cd->dbus_service); - free(cd); - return false; + ps->dbus_data = NULL; + free(cd->dbus_service); + free(cd); + return false; } /** * Destroy D-Bus connection. */ -void -cdbus_destroy(session_t *ps) { - struct cdbus_data *cd = ps->dbus_data; - if (cd->dbus_conn) { - // Release DBus name firstly - if (cd->dbus_service) { - DBusError err = { }; - dbus_error_init(&err); +void cdbus_destroy(session_t *ps) { + struct cdbus_data *cd = ps->dbus_data; + if (cd->dbus_conn) { + // Release DBus name firstly + if (cd->dbus_service) { + DBusError err = {}; + dbus_error_init(&err); - dbus_bus_release_name(cd->dbus_conn, cd->dbus_service, &err); - if (dbus_error_is_set(&err)) { - log_error("Failed to release DBus name (%s).", err.message); - dbus_error_free(&err); - } - free(cd->dbus_service); - } + dbus_bus_release_name(cd->dbus_conn, cd->dbus_service, &err); + if (dbus_error_is_set(&err)) { + log_error("Failed to release DBus name (%s).", err.message); + dbus_error_free(&err); + } + free(cd->dbus_service); + } - // Close and unref the connection - dbus_connection_close(cd->dbus_conn); - dbus_connection_unref(cd->dbus_conn); - } - free(cd); + // Close and unref the connection + dbus_connection_close(cd->dbus_conn); + dbus_connection_unref(cd->dbus_conn); + } + free(cd); } /** @name DBusTimeout handling @@ -222,66 +217,62 @@ cdbus_destroy(session_t *ps) { ///@{ typedef struct ev_dbus_timer { - ev_timer w; - DBusTimeout *t; + ev_timer w; + DBusTimeout *t; } ev_dbus_timer; /** * Callback for handling a D-Bus timeout. */ -static void -cdbus_callback_handle_timeout(EV_P_ ev_timer *w, int revents) { - ev_dbus_timer *t = (void *)w; - dbus_timeout_handle(t->t); +static void cdbus_callback_handle_timeout(EV_P_ ev_timer *w, int revents) { + ev_dbus_timer *t = (void *)w; + dbus_timeout_handle(t->t); } /** * Callback for adding D-Bus timeout. */ -static dbus_bool_t -cdbus_callback_add_timeout(DBusTimeout *timeout, void *data) { - session_t *ps = data; +static dbus_bool_t cdbus_callback_add_timeout(DBusTimeout *timeout, void *data) { + session_t *ps = data; - auto t = ccalloc(1, ev_dbus_timer); - double i = dbus_timeout_get_interval(timeout) / 1000.0; - ev_timer_init(&t->w, cdbus_callback_handle_timeout, i, i); - t->t = timeout; - dbus_timeout_set_data(timeout, t, NULL); + auto t = ccalloc(1, ev_dbus_timer); + double i = dbus_timeout_get_interval(timeout) / 1000.0; + ev_timer_init(&t->w, cdbus_callback_handle_timeout, i, i); + t->t = timeout; + dbus_timeout_set_data(timeout, t, NULL); - if (dbus_timeout_get_enabled(timeout)) - ev_timer_start(ps->loop, &t->w); + if (dbus_timeout_get_enabled(timeout)) + ev_timer_start(ps->loop, &t->w); - return true; + return true; } /** * Callback for removing D-Bus timeout. */ -static void -cdbus_callback_remove_timeout(DBusTimeout *timeout, void *data) { - session_t *ps = data; +static void cdbus_callback_remove_timeout(DBusTimeout *timeout, void *data) { + session_t *ps = data; - ev_dbus_timer *t = dbus_timeout_get_data(timeout); - assert(t); - ev_timer_stop(ps->loop, &t->w); - free(t); + ev_dbus_timer *t = dbus_timeout_get_data(timeout); + assert(t); + ev_timer_stop(ps->loop, &t->w); + free(t); } /** * Callback for toggling a D-Bus timeout. */ -static void -cdbus_callback_timeout_toggled(DBusTimeout *timeout, void *data) { - session_t *ps = data; - ev_dbus_timer *t = dbus_timeout_get_data(timeout); +static void cdbus_callback_timeout_toggled(DBusTimeout *timeout, void *data) { + session_t *ps = data; + ev_dbus_timer *t = dbus_timeout_get_data(timeout); - assert(t); - ev_timer_stop(ps->loop, &t->w); - if (dbus_timeout_get_enabled(timeout)) { - double i = dbus_timeout_get_interval(timeout) / 1000.0; - ev_timer_set(&t->w, i, i); - ev_timer_start(ps->loop, &t->w); - } + assert(t); + ev_timer_stop(ps->loop, &t->w); + if (dbus_timeout_get_enabled(timeout)) { + double i = dbus_timeout_get_interval(timeout) / 1000.0; + ev_timer_set(&t->w, i, i); + ev_timer_start(ps->loop, &t->w); + } } ///@} @@ -291,82 +282,79 @@ cdbus_callback_timeout_toggled(DBusTimeout *timeout, void *data) { ///@{ typedef struct ev_dbus_io { - ev_io w; - struct cdbus_data *cd; - DBusWatch *dw; + ev_io w; + struct cdbus_data *cd; + DBusWatch *dw; } ev_dbus_io; void cdbus_io_callback(EV_P_ ev_io *w, int revents) { - ev_dbus_io *dw = (void *)w; - DBusWatchFlags flags = 0; - if (revents & EV_READ) - flags |= DBUS_WATCH_READABLE; - if (revents & EV_WRITE) - flags |= DBUS_WATCH_WRITABLE; - dbus_watch_handle(dw->dw, flags); - while (dbus_connection_dispatch(dw->cd->dbus_conn) != DBUS_DISPATCH_COMPLETE); + ev_dbus_io *dw = (void *)w; + DBusWatchFlags flags = 0; + if (revents & EV_READ) + flags |= DBUS_WATCH_READABLE; + if (revents & EV_WRITE) + flags |= DBUS_WATCH_WRITABLE; + dbus_watch_handle(dw->dw, flags); + while (dbus_connection_dispatch(dw->cd->dbus_conn) != DBUS_DISPATCH_COMPLETE) + ; } /** * Determine the poll condition of a DBusWatch. */ -static inline int -cdbus_get_watch_cond(DBusWatch *watch) { - const unsigned flags = dbus_watch_get_flags(watch); - int condition = 0; - if (flags & DBUS_WATCH_READABLE) - condition |= EV_READ; - if (flags & DBUS_WATCH_WRITABLE) - condition |= EV_WRITE; +static inline int cdbus_get_watch_cond(DBusWatch *watch) { + const unsigned flags = dbus_watch_get_flags(watch); + int condition = 0; + if (flags & DBUS_WATCH_READABLE) + condition |= EV_READ; + if (flags & DBUS_WATCH_WRITABLE) + condition |= EV_WRITE; - return condition; + return condition; } /** * Callback for adding D-Bus watch. */ -static dbus_bool_t -cdbus_callback_add_watch(DBusWatch *watch, void *data) { - session_t *ps = data; +static dbus_bool_t cdbus_callback_add_watch(DBusWatch *watch, void *data) { + session_t *ps = data; - auto w = ccalloc(1, ev_dbus_io); - w->dw = watch; - w->cd = ps->dbus_data; - ev_io_init(&w->w, cdbus_io_callback, dbus_watch_get_unix_fd(watch), - cdbus_get_watch_cond(watch)); + auto w = ccalloc(1, ev_dbus_io); + w->dw = watch; + w->cd = ps->dbus_data; + ev_io_init(&w->w, cdbus_io_callback, dbus_watch_get_unix_fd(watch), + cdbus_get_watch_cond(watch)); - // Leave disabled watches alone - if (dbus_watch_get_enabled(watch)) - ev_io_start(ps->loop, &w->w); + // Leave disabled watches alone + if (dbus_watch_get_enabled(watch)) + ev_io_start(ps->loop, &w->w); - dbus_watch_set_data(watch, w, NULL); + dbus_watch_set_data(watch, w, NULL); - // Always return true - return true; + // Always return true + return true; } /** * Callback for removing D-Bus watch. */ -static void -cdbus_callback_remove_watch(DBusWatch *watch, void *data) { - session_t *ps = data; - ev_dbus_io *w = dbus_watch_get_data(watch); - ev_io_stop(ps->loop, &w->w); - free(w); +static void cdbus_callback_remove_watch(DBusWatch *watch, void *data) { + session_t *ps = data; + ev_dbus_io *w = dbus_watch_get_data(watch); + ev_io_stop(ps->loop, &w->w); + free(w); } /** * Callback for toggling D-Bus watch status. */ -static void -cdbus_callback_watch_toggled(DBusWatch *watch, void *data) { - session_t *ps = data; - ev_io *w = dbus_watch_get_data(watch); - if (dbus_watch_get_enabled(watch)) - ev_io_start(ps->loop, w); - else - ev_io_stop(ps->loop, w); +static void cdbus_callback_watch_toggled(DBusWatch *watch, void *data) { + session_t *ps = data; + ev_io *w = dbus_watch_get_data(watch); + if (dbus_watch_get_enabled(watch)) + ev_io_start(ps->loop, w); + else + ev_io_stop(ps->loop, w); } ///@} @@ -378,157 +366,142 @@ cdbus_callback_watch_toggled(DBusWatch *watch, void *data) { /** * Callback to append a bool argument to a message. */ -static bool -cdbus_apdarg_bool(session_t *ps, DBusMessage *msg, const void *data) { - assert(data); +static bool cdbus_apdarg_bool(session_t *ps, DBusMessage *msg, const void *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, - DBUS_TYPE_INVALID)) { - log_error("Failed to append argument."); - return false; - } + if (!dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &val, DBUS_TYPE_INVALID)) { + log_error("Failed to append argument."); + return false; + } - return true; + return true; } /** * Callback to append an int32 argument to a message. */ -static bool -cdbus_apdarg_int32(session_t *ps, DBusMessage *msg, const void *data) { - if (!dbus_message_append_args(msg, DBUS_TYPE_INT32, data, - DBUS_TYPE_INVALID)) { - log_error("Failed to append argument."); - return false; - } +static bool cdbus_apdarg_int32(session_t *ps, DBusMessage *msg, const void *data) { + if (!dbus_message_append_args(msg, DBUS_TYPE_INT32, data, DBUS_TYPE_INVALID)) { + log_error("Failed to append argument."); + return false; + } - return true; + return true; } /** * Callback to append an uint32 argument to a message. */ -static bool -cdbus_apdarg_uint32(session_t *ps, DBusMessage *msg, const void *data) { - if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, data, - DBUS_TYPE_INVALID)) { - log_error("Failed to append argument."); - return false; - } +static bool cdbus_apdarg_uint32(session_t *ps, DBusMessage *msg, const void *data) { + if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, data, DBUS_TYPE_INVALID)) { + log_error("Failed to append argument."); + return false; + } - return true; + return true; } /** * Callback to append a double argument to a message. */ -static bool -cdbus_apdarg_double(session_t *ps, DBusMessage *msg, const void *data) { - if (!dbus_message_append_args(msg, DBUS_TYPE_DOUBLE, data, - DBUS_TYPE_INVALID)) { - log_error("Failed to append argument."); - return false; - } +static bool cdbus_apdarg_double(session_t *ps, DBusMessage *msg, const void *data) { + if (!dbus_message_append_args(msg, DBUS_TYPE_DOUBLE, data, DBUS_TYPE_INVALID)) { + log_error("Failed to append argument."); + return false; + } - return true; + return true; } /** * Callback to append a Window argument to a message. */ -static bool -cdbus_apdarg_wid(session_t *ps, DBusMessage *msg, const void *data) { - assert(data); - cdbus_window_t val = *(const xcb_window_t *)data; +static bool cdbus_apdarg_wid(session_t *ps, DBusMessage *msg, const void *data) { + assert(data); + cdbus_window_t val = *(const xcb_window_t *)data; - if (!dbus_message_append_args(msg, CDBUS_TYPE_WINDOW, &val, - DBUS_TYPE_INVALID)) { - log_error("Failed to append argument."); - return false; - } + if (!dbus_message_append_args(msg, CDBUS_TYPE_WINDOW, &val, DBUS_TYPE_INVALID)) { + log_error("Failed to append argument."); + return false; + } - return true; + return true; } /** * Callback to append an cdbus_enum_t argument to a message. */ -static bool -cdbus_apdarg_enum(session_t *ps, DBusMessage *msg, const void *data) { - assert(data); - if (!dbus_message_append_args(msg, CDBUS_TYPE_ENUM, data, - DBUS_TYPE_INVALID)) { - log_error("Failed to append argument."); - return false; - } +static bool cdbus_apdarg_enum(session_t *ps, DBusMessage *msg, const void *data) { + assert(data); + if (!dbus_message_append_args(msg, CDBUS_TYPE_ENUM, data, DBUS_TYPE_INVALID)) { + log_error("Failed to append argument."); + return false; + } - return true; + return true; } /** * Callback to append a string argument to a message. */ -static bool -cdbus_apdarg_string(session_t *ps, DBusMessage *msg, const void *data) { - const char *str = data; - if (!str) - str = ""; +static bool cdbus_apdarg_string(session_t *ps, DBusMessage *msg, const void *data) { + const char *str = data; + if (!str) + str = ""; - if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &str, - DBUS_TYPE_INVALID)) { - log_error("Failed to append argument."); - return false; - } + if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID)) { + log_error("Failed to append argument."); + return false; + } - return true; + return true; } /** * Callback to append all window IDs to a message. */ -static bool -cdbus_apdarg_wids(session_t *ps, DBusMessage *msg, const void *data) { - // Get the number of wids we are to include - unsigned count = 0; - for (win *w = ps->list; w; w = w->next) { - if (w->state != WSTATE_DESTROYING) { - ++count; - } - } +static bool cdbus_apdarg_wids(session_t *ps, DBusMessage *msg, const void *data) { + // Get the number of wids we are to include + unsigned count = 0; + for (win *w = ps->list; w; w = w->next) { + if (w->state != WSTATE_DESTROYING) { + ++count; + } + } - if (!count) { - // Nothing to append - return true; - } + if (!count) { + // Nothing to append + return true; + } - // Allocate memory for an array of window IDs - auto arr = ccalloc(count, cdbus_window_t); + // Allocate memory for an array of window IDs + auto arr = ccalloc(count, cdbus_window_t); - // Build the array - { - cdbus_window_t *pcur = arr; - for (win *w = ps->list; w; w = w->next) { - if (w->state != WSTATE_DESTROYING) { - *pcur = w->id; - ++pcur; - assert(pcur <= arr + count); - } - } - assert(pcur == arr + count); - } + // Build the array + { + cdbus_window_t *pcur = arr; + for (win *w = ps->list; w; w = w->next) { + if (w->state != WSTATE_DESTROYING) { + *pcur = w->id; + ++pcur; + assert(pcur <= arr + count); + } + } + assert(pcur == arr + count); + } - // Append arguments - if (!dbus_message_append_args(msg, DBUS_TYPE_ARRAY, CDBUS_TYPE_WINDOW, - &arr, count, DBUS_TYPE_INVALID)) { - log_error("Failed to append argument."); - free(arr); - return false; - } + // Append arguments + if (!dbus_message_append_args(msg, DBUS_TYPE_ARRAY, CDBUS_TYPE_WINDOW, &arr, + count, DBUS_TYPE_INVALID)) { + log_error("Failed to append argument."); + free(arr); + return false; + } - free(arr); - return true; + free(arr); + return true; } ///@} @@ -541,47 +514,44 @@ cdbus_apdarg_wids(session_t *ps, DBusMessage *msg, const void *data) { * add an argument * @param data data pointer to pass to the function */ -static bool -cdbus_signal(session_t *ps, const char *name, - bool (*func)(session_t *ps, DBusMessage *msg, const void *data), - const void *data) { - struct cdbus_data *cd = ps->dbus_data; - DBusMessage* msg = NULL; +static bool cdbus_signal(session_t *ps, const char *name, + bool (*func)(session_t *ps, DBusMessage *msg, const void *data), + const void *data) { + struct cdbus_data *cd = ps->dbus_data; + DBusMessage *msg = NULL; - // Create a signal - msg = dbus_message_new_signal(CDBUS_OBJECT_NAME, CDBUS_INTERFACE_NAME, - name); - if (!msg) { - log_error("Failed to create D-Bus signal."); - return false; - } + // Create a signal + msg = dbus_message_new_signal(CDBUS_OBJECT_NAME, CDBUS_INTERFACE_NAME, name); + if (!msg) { + log_error("Failed to create D-Bus signal."); + return false; + } - // Append arguments onto message - if (func && !func(ps, msg, data)) { - dbus_message_unref(msg); - return false; - } + // Append arguments onto message + if (func && !func(ps, msg, data)) { + dbus_message_unref(msg); + return false; + } - // Send the message and flush the connection - if (!dbus_connection_send(cd->dbus_conn, msg, NULL)) { - log_error("Failed to send D-Bus signal."); - dbus_message_unref(msg); - return false; - } - dbus_connection_flush(cd->dbus_conn); + // Send the message and flush the connection + if (!dbus_connection_send(cd->dbus_conn, msg, NULL)) { + log_error("Failed to send D-Bus signal."); + dbus_message_unref(msg); + return false; + } + dbus_connection_flush(cd->dbus_conn); - // Free the message - dbus_message_unref(msg); + // Free the message + dbus_message_unref(msg); - return true; + return true; } /** * Send a signal with a Window ID as argument. */ -static inline bool -cdbus_signal_wid(session_t *ps, const char *name, xcb_window_t wid) { - return cdbus_signal(ps, name, cdbus_apdarg_wid, &wid); +static inline bool cdbus_signal_wid(session_t *ps, const char *name, xcb_window_t wid) { + return cdbus_signal(ps, name, cdbus_apdarg_wid, &wid); } /** @@ -593,94 +563,86 @@ cdbus_signal_wid(session_t *ps, const char *name, xcb_window_t wid) { * add an argument * @param data data pointer to pass to the function */ -static bool -cdbus_reply(session_t *ps, DBusMessage *srcmsg, - bool (*func)(session_t *ps, DBusMessage *msg, const void *data), - const void *data) { - struct cdbus_data *cd = ps->dbus_data; - DBusMessage* msg = NULL; +static bool cdbus_reply(session_t *ps, DBusMessage *srcmsg, + bool (*func)(session_t *ps, DBusMessage *msg, const void *data), + const void *data) { + struct cdbus_data *cd = ps->dbus_data; + DBusMessage *msg = NULL; - // Create a reply - msg = dbus_message_new_method_return(srcmsg); - if (!msg) { - log_error("Failed to create D-Bus reply."); - return false; - } + // Create a reply + msg = dbus_message_new_method_return(srcmsg); + if (!msg) { + log_error("Failed to create D-Bus reply."); + return false; + } - // Append arguments onto message - if (func && !func(ps, msg, data)) { - dbus_message_unref(msg); - return false; - } + // Append arguments onto message + if (func && !func(ps, msg, data)) { + dbus_message_unref(msg); + return false; + } - // Send the message and flush the connection - if (!dbus_connection_send(cd->dbus_conn, msg, NULL)) { - log_error("Failed to send D-Bus reply."); - dbus_message_unref(msg); - return false; - } - dbus_connection_flush(cd->dbus_conn); + // Send the message and flush the connection + if (!dbus_connection_send(cd->dbus_conn, msg, NULL)) { + log_error("Failed to send D-Bus reply."); + dbus_message_unref(msg); + return false; + } + dbus_connection_flush(cd->dbus_conn); - // Free the message - dbus_message_unref(msg); + // Free the message + dbus_message_unref(msg); - return true; + return true; } /** * Send a reply with a bool argument. */ -static inline bool -cdbus_reply_bool(session_t *ps, DBusMessage *srcmsg, bool bval) { - return cdbus_reply(ps, srcmsg, cdbus_apdarg_bool, &bval); +static inline bool cdbus_reply_bool(session_t *ps, DBusMessage *srcmsg, bool bval) { + return cdbus_reply(ps, srcmsg, cdbus_apdarg_bool, &bval); } /** * Send a reply with an int32 argument. */ -static inline bool -cdbus_reply_int32(session_t *ps, DBusMessage *srcmsg, int32_t val) { - return cdbus_reply(ps, srcmsg, cdbus_apdarg_int32, &val); +static inline bool cdbus_reply_int32(session_t *ps, DBusMessage *srcmsg, int32_t val) { + return cdbus_reply(ps, srcmsg, cdbus_apdarg_int32, &val); } /** * Send a reply with an uint32 argument. */ -static inline bool -cdbus_reply_uint32(session_t *ps, DBusMessage *srcmsg, uint32_t val) { - return cdbus_reply(ps, srcmsg, cdbus_apdarg_uint32, &val); +static inline bool cdbus_reply_uint32(session_t *ps, DBusMessage *srcmsg, uint32_t val) { + return cdbus_reply(ps, srcmsg, cdbus_apdarg_uint32, &val); } /** * Send a reply with a double argument. */ -static inline bool -cdbus_reply_double(session_t *ps, DBusMessage *srcmsg, double val) { - return cdbus_reply(ps, srcmsg, cdbus_apdarg_double, &val); +static inline bool cdbus_reply_double(session_t *ps, DBusMessage *srcmsg, double val) { + return cdbus_reply(ps, srcmsg, cdbus_apdarg_double, &val); } /** * Send a reply with a wid argument. */ -static inline bool -cdbus_reply_wid(session_t *ps, DBusMessage *srcmsg, xcb_window_t wid) { - return cdbus_reply(ps, srcmsg, cdbus_apdarg_wid, &wid); +static inline bool cdbus_reply_wid(session_t *ps, DBusMessage *srcmsg, xcb_window_t wid) { + return cdbus_reply(ps, srcmsg, cdbus_apdarg_wid, &wid); } /** * Send a reply with a string argument. */ -static inline bool -cdbus_reply_string(session_t *ps, DBusMessage *srcmsg, const char *str) { - return cdbus_reply(ps, srcmsg, cdbus_apdarg_string, str); +static inline bool cdbus_reply_string(session_t *ps, DBusMessage *srcmsg, const char *str) { + return cdbus_reply(ps, srcmsg, cdbus_apdarg_string, str); } /** * Send a reply with a enum argument. */ -static inline bool -cdbus_reply_enum(session_t *ps, DBusMessage *srcmsg, cdbus_enum_t eval) { - return cdbus_reply(ps, srcmsg, cdbus_apdarg_enum, &eval); +static inline bool cdbus_reply_enum(session_t *ps, DBusMessage *srcmsg, cdbus_enum_t eval) { + return cdbus_reply(ps, srcmsg, cdbus_apdarg_enum, &eval); } /** @@ -689,26 +651,25 @@ cdbus_reply_enum(session_t *ps, DBusMessage *srcmsg, cdbus_enum_t eval) { * @param ps current session * @param msg the new error DBusMessage */ -static bool -cdbus_reply_errm(session_t *ps, DBusMessage *msg) { - struct cdbus_data *cd = ps->dbus_data; - if (!msg) { - log_error("Failed to create D-Bus reply."); - return false; - } +static bool cdbus_reply_errm(session_t *ps, DBusMessage *msg) { + struct cdbus_data *cd = ps->dbus_data; + if (!msg) { + log_error("Failed to create D-Bus reply."); + return false; + } - // Send the message and flush the connection - if (!dbus_connection_send(cd->dbus_conn, msg, NULL)) { - log_error("Failed to send D-Bus reply."); - dbus_message_unref(msg); - return false; - } - dbus_connection_flush(cd->dbus_conn); + // Send the message and flush the connection + if (!dbus_connection_send(cd->dbus_conn, msg, NULL)) { + log_error("Failed to send D-Bus reply."); + dbus_message_unref(msg); + return false; + } + dbus_connection_flush(cd->dbus_conn); - // Free the message - dbus_message_unref(msg); + // Free the message + dbus_message_unref(msg); - return true; + return true; } /** @@ -719,35 +680,34 @@ cdbus_reply_errm(session_t *ps, DBusMessage *msg) { * @param pdest pointer to the target * @return true if successful, false otherwise. */ -static bool -cdbus_msg_get_arg(DBusMessage *msg, int count, const int type, void *pdest) { - assert(count >= 0); +static bool cdbus_msg_get_arg(DBusMessage *msg, int count, const int type, void *pdest) { + assert(count >= 0); - DBusMessageIter iter = { }; - if (!dbus_message_iter_init(msg, &iter)) { - log_error("Message has no argument."); - return false; - } + DBusMessageIter iter = {}; + if (!dbus_message_iter_init(msg, &iter)) { + log_error("Message has no argument."); + return false; + } - { - const int oldcount = count; - while (count) { - if (!dbus_message_iter_next(&iter)) { - log_error("Failed to find argument %d.", oldcount); - return false; - } - --count; - } - } + { + const int oldcount = count; + while (count) { + if (!dbus_message_iter_next(&iter)) { + log_error("Failed to find argument %d.", oldcount); + return false; + } + --count; + } + } - if (type != dbus_message_iter_get_arg_type(&iter)) { - log_error("Argument has incorrect type."); - return false; - } + if (type != dbus_message_iter_get_arg_type(&iter)) { + log_error("Argument has incorrect type."); + return false; + } - dbus_message_iter_get_basic(&iter, pdest); + dbus_message_iter_get_basic(&iter, pdest); - return true; + return true; } /** @name Message processing @@ -757,350 +717,340 @@ cdbus_msg_get_arg(DBusMessage *msg, int count, const int type, void *pdest) { /** * Process a list_win D-Bus request. */ -static bool -cdbus_process_list_win(session_t *ps, DBusMessage *msg) { - cdbus_reply(ps, msg, cdbus_apdarg_wids, NULL); +static bool cdbus_process_list_win(session_t *ps, DBusMessage *msg) { + cdbus_reply(ps, msg, cdbus_apdarg_wids, NULL); - return true; + return true; } /** * Process a win_get D-Bus request. */ -static bool -cdbus_process_win_get(session_t *ps, DBusMessage *msg) { - cdbus_window_t wid = XCB_NONE; - const char *target = NULL; - DBusError err = { }; +static bool cdbus_process_win_get(session_t *ps, DBusMessage *msg) { + cdbus_window_t wid = XCB_NONE; + const char *target = NULL; + DBusError err = {}; - if (!dbus_message_get_args(msg, &err, - CDBUS_TYPE_WINDOW, &wid, - DBUS_TYPE_STRING, &target, - DBUS_TYPE_INVALID)) { - log_error("Failed to parse argument of \"win_get\" (%s).", err.message); - dbus_error_free(&err); - return false; - } + if (!dbus_message_get_args(msg, &err, CDBUS_TYPE_WINDOW, &wid, DBUS_TYPE_STRING, + &target, DBUS_TYPE_INVALID)) { + log_error("Failed to parse argument of \"win_get\" (%s).", err.message); + dbus_error_free(&err); + return false; + } - win *w = find_win(ps, wid); + win *w = find_win(ps, wid); - if (!w) { - log_error("Window %#010x not found.", wid); - cdbus_reply_err(ps, msg, CDBUS_ERROR_BADWIN, CDBUS_ERROR_BADWIN_S, wid); - return true; - } + if (!w) { + log_error("Window %#010x not found.", wid); + cdbus_reply_err(ps, msg, CDBUS_ERROR_BADWIN, CDBUS_ERROR_BADWIN_S, wid); + return true; + } -#define cdbus_m_win_get_do(tgt, apdarg_func) \ - if (!strcmp(MSTR(tgt), target)) { \ - apdarg_func(ps, msg, w->tgt); \ - return true; \ - } +#define cdbus_m_win_get_do(tgt, apdarg_func) \ + if (!strcmp(MSTR(tgt), target)) { \ + apdarg_func(ps, msg, w->tgt); \ + return true; \ + } - cdbus_m_win_get_do(id, cdbus_reply_wid); + cdbus_m_win_get_do(id, cdbus_reply_wid); - // next - if (!strcmp("next", target)) { - cdbus_reply_wid(ps, msg, (w->next ? w->next->id: 0)); - return true; - } + // next + if (!strcmp("next", target)) { + cdbus_reply_wid(ps, msg, (w->next ? w->next->id : 0)); + return true; + } - // map_state - if (!strcmp("map_state", target)) { - cdbus_reply_bool(ps, msg, w->a.map_state); - return true; - } + // map_state + if (!strcmp("map_state", target)) { + cdbus_reply_bool(ps, msg, w->a.map_state); + return true; + } - cdbus_m_win_get_do(mode, cdbus_reply_enum); - cdbus_m_win_get_do(client_win, cdbus_reply_wid); - cdbus_m_win_get_do(ever_damaged, cdbus_reply_bool); - cdbus_m_win_get_do(window_type, cdbus_reply_enum); - cdbus_m_win_get_do(wmwin, cdbus_reply_bool); - cdbus_m_win_get_do(leader, cdbus_reply_wid); - // focused_real - if (!strcmp("focused_real", target)) { - cdbus_reply_bool(ps, msg, win_is_focused_real(ps, w)); - return true; - } - cdbus_m_win_get_do(fade_force, cdbus_reply_enum); - cdbus_m_win_get_do(shadow_force, cdbus_reply_enum); - cdbus_m_win_get_do(focused_force, cdbus_reply_enum); - cdbus_m_win_get_do(invert_color_force, cdbus_reply_enum); - cdbus_m_win_get_do(name, cdbus_reply_string); - cdbus_m_win_get_do(class_instance, cdbus_reply_string); - cdbus_m_win_get_do(class_general, cdbus_reply_string); - cdbus_m_win_get_do(role, cdbus_reply_string); + cdbus_m_win_get_do(mode, cdbus_reply_enum); + cdbus_m_win_get_do(client_win, cdbus_reply_wid); + cdbus_m_win_get_do(ever_damaged, cdbus_reply_bool); + cdbus_m_win_get_do(window_type, cdbus_reply_enum); + cdbus_m_win_get_do(wmwin, cdbus_reply_bool); + cdbus_m_win_get_do(leader, cdbus_reply_wid); + // focused_real + if (!strcmp("focused_real", target)) { + cdbus_reply_bool(ps, msg, win_is_focused_real(ps, w)); + return true; + } + cdbus_m_win_get_do(fade_force, cdbus_reply_enum); + cdbus_m_win_get_do(shadow_force, cdbus_reply_enum); + cdbus_m_win_get_do(focused_force, cdbus_reply_enum); + cdbus_m_win_get_do(invert_color_force, cdbus_reply_enum); + cdbus_m_win_get_do(name, cdbus_reply_string); + cdbus_m_win_get_do(class_instance, cdbus_reply_string); + cdbus_m_win_get_do(class_general, cdbus_reply_string); + cdbus_m_win_get_do(role, cdbus_reply_string); - cdbus_m_win_get_do(opacity, cdbus_reply_uint32); - cdbus_m_win_get_do(opacity_tgt, cdbus_reply_uint32); - cdbus_m_win_get_do(has_opacity_prop, cdbus_reply_bool); - cdbus_m_win_get_do(opacity_prop, cdbus_reply_uint32); - cdbus_m_win_get_do(opacity_is_set, cdbus_reply_bool); - cdbus_m_win_get_do(opacity_set, cdbus_reply_uint32); + cdbus_m_win_get_do(opacity, cdbus_reply_uint32); + cdbus_m_win_get_do(opacity_tgt, cdbus_reply_uint32); + cdbus_m_win_get_do(has_opacity_prop, cdbus_reply_bool); + cdbus_m_win_get_do(opacity_prop, cdbus_reply_uint32); + cdbus_m_win_get_do(opacity_is_set, cdbus_reply_bool); + cdbus_m_win_get_do(opacity_set, cdbus_reply_uint32); - cdbus_m_win_get_do(frame_opacity, cdbus_reply_double); - if (!strcmp("left_width", target)) { - cdbus_reply_uint32(ps, msg, w->frame_extents.left); - return true; - } - if (!strcmp("right_width", target)) { - cdbus_reply_uint32(ps, msg, w->frame_extents.right); - return true; - } - if (!strcmp("top_width", target)) { - cdbus_reply_uint32(ps, msg, w->frame_extents.top); - return true; - } - if (!strcmp("bottom_width", target)) { - cdbus_reply_uint32(ps, msg, w->frame_extents.bottom); - return true; - } + cdbus_m_win_get_do(frame_opacity, cdbus_reply_double); + if (!strcmp("left_width", target)) { + cdbus_reply_uint32(ps, msg, w->frame_extents.left); + return true; + } + if (!strcmp("right_width", target)) { + cdbus_reply_uint32(ps, msg, w->frame_extents.right); + return true; + } + if (!strcmp("top_width", target)) { + cdbus_reply_uint32(ps, msg, w->frame_extents.top); + return true; + } + if (!strcmp("bottom_width", target)) { + cdbus_reply_uint32(ps, msg, w->frame_extents.bottom); + return true; + } - cdbus_m_win_get_do(shadow, cdbus_reply_bool); - cdbus_m_win_get_do(invert_color, cdbus_reply_bool); - cdbus_m_win_get_do(blur_background, cdbus_reply_bool); + cdbus_m_win_get_do(shadow, cdbus_reply_bool); + cdbus_m_win_get_do(invert_color, cdbus_reply_bool); + cdbus_m_win_get_do(blur_background, cdbus_reply_bool); #undef cdbus_m_win_get_do - log_error(CDBUS_ERROR_BADTGT_S, target); - cdbus_reply_err(ps, msg, CDBUS_ERROR_BADTGT, 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); - return true; + return true; } /** * Process a win_set D-Bus request. */ -static bool -cdbus_process_win_set(session_t *ps, DBusMessage *msg) { - cdbus_window_t wid = XCB_NONE; - const char *target = NULL; - DBusError err = { }; +static bool cdbus_process_win_set(session_t *ps, DBusMessage *msg) { + cdbus_window_t wid = XCB_NONE; + const char *target = NULL; + DBusError err = {}; - if (!dbus_message_get_args(msg, &err, - CDBUS_TYPE_WINDOW, &wid, - DBUS_TYPE_STRING, &target, - DBUS_TYPE_INVALID)) { - log_error("(): Failed to parse argument of \"win_set\" (%s).", err.message); - dbus_error_free(&err); - return false; - } + if (!dbus_message_get_args(msg, &err, CDBUS_TYPE_WINDOW, &wid, DBUS_TYPE_STRING, + &target, DBUS_TYPE_INVALID)) { + log_error("(): Failed to parse argument of \"win_set\" (%s).", err.message); + dbus_error_free(&err); + return false; + } - win *w = find_win(ps, wid); + win *w = find_win(ps, wid); - if (!w) { - log_error("Window %#010x not found.", wid); - cdbus_reply_err(ps, msg, CDBUS_ERROR_BADWIN, CDBUS_ERROR_BADWIN_S, wid); - return true; - } + if (!w) { + log_error("Window %#010x not found.", wid); + cdbus_reply_err(ps, msg, CDBUS_ERROR_BADWIN, CDBUS_ERROR_BADWIN_S, wid); + return true; + } -#define cdbus_m_win_set_do(tgt, type, real_type) \ - if (!strcmp(MSTR(tgt), target)) { \ - real_type val; \ - if (!cdbus_msg_get_arg(msg, 2, type, &val)) \ - return false; \ - w->tgt = val; \ - goto cdbus_process_win_set_success; \ - } +#define cdbus_m_win_set_do(tgt, type, real_type) \ + if (!strcmp(MSTR(tgt), target)) { \ + real_type val; \ + if (!cdbus_msg_get_arg(msg, 2, type, &val)) \ + return false; \ + w->tgt = val; \ + goto cdbus_process_win_set_success; \ + } - if (!strcmp("shadow_force", target)) { - cdbus_enum_t val = UNSET; - if (!cdbus_msg_get_arg(msg, 2, CDBUS_TYPE_ENUM, &val)) - return false; - win_set_shadow_force(ps, w, val); - goto cdbus_process_win_set_success; - } + if (!strcmp("shadow_force", target)) { + cdbus_enum_t val = UNSET; + if (!cdbus_msg_get_arg(msg, 2, CDBUS_TYPE_ENUM, &val)) + return false; + win_set_shadow_force(ps, w, val); + goto cdbus_process_win_set_success; + } - if (!strcmp("fade_force", target)) { - cdbus_enum_t val = UNSET; - if (!cdbus_msg_get_arg(msg, 2, CDBUS_TYPE_ENUM, &val)) - return false; - win_set_fade_force(ps, w, val); - goto cdbus_process_win_set_success; - } + if (!strcmp("fade_force", target)) { + cdbus_enum_t val = UNSET; + if (!cdbus_msg_get_arg(msg, 2, CDBUS_TYPE_ENUM, &val)) + return false; + win_set_fade_force(ps, w, val); + goto cdbus_process_win_set_success; + } - if (!strcmp("focused_force", target)) { - cdbus_enum_t val = UNSET; - if (!cdbus_msg_get_arg(msg, 2, CDBUS_TYPE_ENUM, &val)) - return false; - win_set_focused_force(ps, w, val); - goto cdbus_process_win_set_success; - } + if (!strcmp("focused_force", target)) { + cdbus_enum_t val = UNSET; + if (!cdbus_msg_get_arg(msg, 2, CDBUS_TYPE_ENUM, &val)) + return false; + win_set_focused_force(ps, w, val); + goto cdbus_process_win_set_success; + } - if (!strcmp("invert_color_force", target)) { - cdbus_enum_t val = UNSET; - if (!cdbus_msg_get_arg(msg, 2, CDBUS_TYPE_ENUM, &val)) - return false; - win_set_invert_color_force(ps, w, val); - goto cdbus_process_win_set_success; - } + if (!strcmp("invert_color_force", target)) { + cdbus_enum_t val = UNSET; + if (!cdbus_msg_get_arg(msg, 2, CDBUS_TYPE_ENUM, &val)) + return false; + win_set_invert_color_force(ps, w, val); + goto cdbus_process_win_set_success; + } #undef cdbus_m_win_set_do - log_error(CDBUS_ERROR_BADTGT_S, target); - cdbus_reply_err(ps, msg, CDBUS_ERROR_BADTGT, 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); - return true; + return true; cdbus_process_win_set_success: - if (!dbus_message_get_no_reply(msg)) - cdbus_reply_bool(ps, msg, true); - return true; + if (!dbus_message_get_no_reply(msg)) + cdbus_reply_bool(ps, msg, true); + return true; } /** * Process a find_win D-Bus request. */ -static bool -cdbus_process_find_win(session_t *ps, DBusMessage *msg) { - const char *target = NULL; +static bool cdbus_process_find_win(session_t *ps, DBusMessage *msg) { + const char *target = NULL; - if (!cdbus_msg_get_arg(msg, 0, DBUS_TYPE_STRING, &target)) - return false; + if (!cdbus_msg_get_arg(msg, 0, DBUS_TYPE_STRING, &target)) + return false; - xcb_window_t wid = XCB_NONE; + xcb_window_t wid = XCB_NONE; - // Find window by client window - if (!strcmp("client", target)) { - cdbus_window_t client = XCB_NONE; - if (!cdbus_msg_get_arg(msg, 1, CDBUS_TYPE_WINDOW, &client)) - return false; - win *w = find_toplevel(ps, client); - if (w) - wid = w->id; - } - // Find focused window - else if (!strcmp("focused", target)) { - win *w = find_focused(ps); - if (w) - wid = w->id; - } - else { - log_error(CDBUS_ERROR_BADTGT_S, target); - cdbus_reply_err(ps, msg, CDBUS_ERROR_BADTGT, CDBUS_ERROR_BADTGT_S, target); + // Find window by client window + if (!strcmp("client", target)) { + cdbus_window_t client = XCB_NONE; + if (!cdbus_msg_get_arg(msg, 1, CDBUS_TYPE_WINDOW, &client)) + return false; + win *w = find_toplevel(ps, client); + if (w) + wid = w->id; + } + // Find focused window + else if (!strcmp("focused", target)) { + win *w = find_focused(ps); + if (w) + wid = w->id; + } else { + log_error(CDBUS_ERROR_BADTGT_S, target); + cdbus_reply_err(ps, msg, CDBUS_ERROR_BADTGT, CDBUS_ERROR_BADTGT_S, target); - return true; - } + return true; + } - cdbus_reply_wid(ps, msg, wid); + cdbus_reply_wid(ps, msg, wid); - return true; + return true; } /** * Process a opts_get D-Bus request. */ -static bool -cdbus_process_opts_get(session_t *ps, DBusMessage *msg) { - const char *target = NULL; +static bool cdbus_process_opts_get(session_t *ps, DBusMessage *msg) { + const char *target = NULL; - if (!cdbus_msg_get_arg(msg, 0, DBUS_TYPE_STRING, &target)) - return false; + if (!cdbus_msg_get_arg(msg, 0, DBUS_TYPE_STRING, &target)) + return false; -#define cdbus_m_opts_get_do(tgt, apdarg_func) \ - if (!strcmp(MSTR(tgt), target)) { \ - apdarg_func(ps, msg, ps->o.tgt); \ - return true; \ - } +#define cdbus_m_opts_get_do(tgt, apdarg_func) \ + if (!strcmp(MSTR(tgt), target)) { \ + apdarg_func(ps, msg, ps->o.tgt); \ + return true; \ + } -#define cdbus_m_opts_get_stub(tgt, apdarg_func, ret) \ - if (!strcmp(MSTR(tgt), target)) { \ - apdarg_func(ps, msg, ret); \ - return true; \ - } +#define cdbus_m_opts_get_stub(tgt, apdarg_func, ret) \ + if (!strcmp(MSTR(tgt), target)) { \ + apdarg_func(ps, msg, ret); \ + return true; \ + } - // version - if (!strcmp("version", target)) { - cdbus_reply_string(ps, msg, COMPTON_VERSION); - return true; - } + // version + if (!strcmp("version", target)) { + cdbus_reply_string(ps, msg, COMPTON_VERSION); + return true; + } - // pid - if (!strcmp("pid", target)) { - cdbus_reply_int32(ps, msg, getpid()); - return true; - } + // pid + if (!strcmp("pid", target)) { + cdbus_reply_int32(ps, msg, getpid()); + return true; + } - // display - if (!strcmp("display", target)) { - cdbus_reply_string(ps, msg, DisplayString(ps->dpy)); - return true; - } + // display + if (!strcmp("display", target)) { + cdbus_reply_string(ps, msg, DisplayString(ps->dpy)); + return true; + } - cdbus_m_opts_get_stub(config_file, cdbus_reply_string, "Unknown"); - cdbus_m_opts_get_do(write_pid_path, cdbus_reply_string); - cdbus_m_opts_get_do(mark_wmwin_focused, cdbus_reply_bool); - cdbus_m_opts_get_do(mark_ovredir_focused, cdbus_reply_bool); - cdbus_m_opts_get_do(detect_rounded_corners, cdbus_reply_bool); - cdbus_m_opts_get_stub(paint_on_overlay, cdbus_reply_bool, ps->overlay != XCB_NONE); - // paint_on_overlay_id: Get ID of the X composite overlay window - if (!strcmp("paint_on_overlay_id", target)) { - cdbus_reply_uint32(ps, msg, ps->overlay); - return true; - } - cdbus_m_opts_get_do(unredir_if_possible, cdbus_reply_bool); - cdbus_m_opts_get_do(unredir_if_possible_delay, cdbus_reply_int32); - cdbus_m_opts_get_do(redirected_force, cdbus_reply_enum); - cdbus_m_opts_get_do(stoppaint_force, cdbus_reply_enum); - cdbus_m_opts_get_do(logpath, cdbus_reply_string); - cdbus_m_opts_get_stub(synchronize, cdbus_reply_bool, false); + cdbus_m_opts_get_stub(config_file, cdbus_reply_string, "Unknown"); + cdbus_m_opts_get_do(write_pid_path, cdbus_reply_string); + cdbus_m_opts_get_do(mark_wmwin_focused, cdbus_reply_bool); + cdbus_m_opts_get_do(mark_ovredir_focused, cdbus_reply_bool); + cdbus_m_opts_get_do(detect_rounded_corners, cdbus_reply_bool); + cdbus_m_opts_get_stub(paint_on_overlay, cdbus_reply_bool, ps->overlay != XCB_NONE); + // paint_on_overlay_id: Get ID of the X composite overlay window + if (!strcmp("paint_on_overlay_id", target)) { + cdbus_reply_uint32(ps, msg, ps->overlay); + return true; + } + cdbus_m_opts_get_do(unredir_if_possible, cdbus_reply_bool); + cdbus_m_opts_get_do(unredir_if_possible_delay, cdbus_reply_int32); + cdbus_m_opts_get_do(redirected_force, cdbus_reply_enum); + cdbus_m_opts_get_do(stoppaint_force, cdbus_reply_enum); + cdbus_m_opts_get_do(logpath, cdbus_reply_string); + cdbus_m_opts_get_stub(synchronize, cdbus_reply_bool, false); - cdbus_m_opts_get_do(refresh_rate, cdbus_reply_int32); - cdbus_m_opts_get_do(sw_opti, cdbus_reply_bool); - if (!strcmp("vsync", target)) { - assert(ps->o.vsync < sizeof(VSYNC_STRS) / sizeof(VSYNC_STRS[0])); - cdbus_reply_string(ps, msg, VSYNC_STRS[ps->o.vsync]); - return true; - } - if (!strcmp("backend", target)) { - assert(ps->o.backend < sizeof(BACKEND_STRS) / sizeof(BACKEND_STRS[0])); - cdbus_reply_string(ps, msg, BACKEND_STRS[ps->o.backend]); - return true; - } - cdbus_m_opts_get_stub(dbe, cdbus_reply_bool, false); - cdbus_m_opts_get_do(vsync_aggressive, cdbus_reply_bool); + cdbus_m_opts_get_do(refresh_rate, cdbus_reply_int32); + cdbus_m_opts_get_do(sw_opti, cdbus_reply_bool); + if (!strcmp("vsync", target)) { + assert(ps->o.vsync < sizeof(VSYNC_STRS) / sizeof(VSYNC_STRS[0])); + cdbus_reply_string(ps, msg, VSYNC_STRS[ps->o.vsync]); + return true; + } + if (!strcmp("backend", target)) { + assert(ps->o.backend < sizeof(BACKEND_STRS) / sizeof(BACKEND_STRS[0])); + cdbus_reply_string(ps, msg, BACKEND_STRS[ps->o.backend]); + return true; + } + cdbus_m_opts_get_stub(dbe, cdbus_reply_bool, false); + cdbus_m_opts_get_do(vsync_aggressive, cdbus_reply_bool); - cdbus_m_opts_get_do(shadow_red, cdbus_reply_double); - cdbus_m_opts_get_do(shadow_green, cdbus_reply_double); - cdbus_m_opts_get_do(shadow_blue, cdbus_reply_double); - cdbus_m_opts_get_do(shadow_radius, cdbus_reply_int32); - cdbus_m_opts_get_do(shadow_offset_x, cdbus_reply_int32); - cdbus_m_opts_get_do(shadow_offset_y, cdbus_reply_int32); - cdbus_m_opts_get_do(shadow_opacity, cdbus_reply_double); - cdbus_m_opts_get_stub(clear_shadow, cdbus_reply_bool, true); - cdbus_m_opts_get_do(xinerama_shadow_crop, cdbus_reply_bool); + cdbus_m_opts_get_do(shadow_red, cdbus_reply_double); + cdbus_m_opts_get_do(shadow_green, cdbus_reply_double); + cdbus_m_opts_get_do(shadow_blue, cdbus_reply_double); + cdbus_m_opts_get_do(shadow_radius, cdbus_reply_int32); + cdbus_m_opts_get_do(shadow_offset_x, cdbus_reply_int32); + cdbus_m_opts_get_do(shadow_offset_y, cdbus_reply_int32); + cdbus_m_opts_get_do(shadow_opacity, cdbus_reply_double); + cdbus_m_opts_get_stub(clear_shadow, cdbus_reply_bool, true); + cdbus_m_opts_get_do(xinerama_shadow_crop, cdbus_reply_bool); - cdbus_m_opts_get_do(fade_delta, cdbus_reply_int32); - cdbus_m_opts_get_do(fade_in_step, cdbus_reply_int32); - cdbus_m_opts_get_do(fade_out_step, cdbus_reply_int32); - cdbus_m_opts_get_do(no_fading_openclose, cdbus_reply_bool); + cdbus_m_opts_get_do(fade_delta, cdbus_reply_int32); + cdbus_m_opts_get_do(fade_in_step, cdbus_reply_int32); + cdbus_m_opts_get_do(fade_out_step, cdbus_reply_int32); + cdbus_m_opts_get_do(no_fading_openclose, cdbus_reply_bool); - cdbus_m_opts_get_do(blur_background, cdbus_reply_bool); - cdbus_m_opts_get_do(blur_background_frame, cdbus_reply_bool); - cdbus_m_opts_get_do(blur_background_fixed, cdbus_reply_bool); + cdbus_m_opts_get_do(blur_background, cdbus_reply_bool); + cdbus_m_opts_get_do(blur_background_frame, cdbus_reply_bool); + cdbus_m_opts_get_do(blur_background_fixed, cdbus_reply_bool); - cdbus_m_opts_get_do(inactive_dim, cdbus_reply_double); - cdbus_m_opts_get_do(inactive_dim_fixed, cdbus_reply_bool); + cdbus_m_opts_get_do(inactive_dim, cdbus_reply_double); + cdbus_m_opts_get_do(inactive_dim_fixed, cdbus_reply_bool); - cdbus_m_opts_get_do(use_ewmh_active_win, cdbus_reply_bool); - cdbus_m_opts_get_do(detect_transient, cdbus_reply_bool); - cdbus_m_opts_get_do(detect_client_leader, cdbus_reply_bool); + cdbus_m_opts_get_do(use_ewmh_active_win, cdbus_reply_bool); + cdbus_m_opts_get_do(detect_transient, cdbus_reply_bool); + cdbus_m_opts_get_do(detect_client_leader, cdbus_reply_bool); #ifdef CONFIG_OPENGL - cdbus_m_opts_get_stub(glx_use_copysubbuffermesa, cdbus_reply_bool, false); - cdbus_m_opts_get_stub(glx_copy_from_front, cdbus_reply_bool, false); - cdbus_m_opts_get_do(glx_no_stencil, cdbus_reply_bool); - cdbus_m_opts_get_do(glx_no_rebind_pixmap, cdbus_reply_bool); - cdbus_m_opts_get_do(glx_swap_method, cdbus_reply_int32); + cdbus_m_opts_get_stub(glx_use_copysubbuffermesa, cdbus_reply_bool, false); + cdbus_m_opts_get_stub(glx_copy_from_front, cdbus_reply_bool, false); + cdbus_m_opts_get_do(glx_no_stencil, cdbus_reply_bool); + cdbus_m_opts_get_do(glx_no_rebind_pixmap, cdbus_reply_bool); + cdbus_m_opts_get_do(glx_swap_method, cdbus_reply_int32); #endif - cdbus_m_opts_get_do(track_focus, cdbus_reply_bool); - cdbus_m_opts_get_do(track_wdata, cdbus_reply_bool); - cdbus_m_opts_get_do(track_leader, cdbus_reply_bool); + cdbus_m_opts_get_do(track_focus, cdbus_reply_bool); + cdbus_m_opts_get_do(track_wdata, cdbus_reply_bool); + cdbus_m_opts_get_do(track_leader, cdbus_reply_bool); #undef cdbus_m_opts_get_do #undef cdbus_m_opts_get_stub - log_error(CDBUS_ERROR_BADTGT_S, target); - cdbus_reply_err(ps, msg, CDBUS_ERROR_BADTGT, 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); - return true; + return true; } // XXX Remove this after header clean up @@ -1109,298 +1059,279 @@ void queue_redraw(session_t *ps); /** * Process a opts_set D-Bus request. */ -static bool -cdbus_process_opts_set(session_t *ps, DBusMessage *msg) { - const char *target = NULL; +static bool cdbus_process_opts_set(session_t *ps, DBusMessage *msg) { + const char *target = NULL; - if (!cdbus_msg_get_arg(msg, 0, DBUS_TYPE_STRING, &target)) - return false; + if (!cdbus_msg_get_arg(msg, 0, DBUS_TYPE_STRING, &target)) + return false; -#define cdbus_m_opts_set_do(tgt, type, real_type) \ - if (!strcmp(MSTR(tgt), target)) { \ - real_type val; \ - if (!cdbus_msg_get_arg(msg, 1, type, &val)) \ - return false; \ - ps->o.tgt = val; \ - goto cdbus_process_opts_set_success; \ - } +#define cdbus_m_opts_set_do(tgt, type, real_type) \ + if (!strcmp(MSTR(tgt), target)) { \ + real_type val; \ + if (!cdbus_msg_get_arg(msg, 1, type, &val)) \ + return false; \ + ps->o.tgt = val; \ + goto cdbus_process_opts_set_success; \ + } - // fade_delta - if (!strcmp("fade_delta", target)) { - int32_t val = 0.0; - if (!cdbus_msg_get_arg(msg, 1, DBUS_TYPE_INT32, &val)) - return false; - ps->o.fade_delta = max_i(val, 1); - goto cdbus_process_opts_set_success; - } + // fade_delta + if (!strcmp("fade_delta", target)) { + int32_t val = 0.0; + if (!cdbus_msg_get_arg(msg, 1, DBUS_TYPE_INT32, &val)) + return false; + ps->o.fade_delta = max_i(val, 1); + goto cdbus_process_opts_set_success; + } - // fade_in_step - if (!strcmp("fade_in_step", target)) { - double val = 0.0; - if (!cdbus_msg_get_arg(msg, 1, DBUS_TYPE_DOUBLE, &val)) - return false; - ps->o.fade_in_step = normalize_d(val); - goto cdbus_process_opts_set_success; - } + // fade_in_step + if (!strcmp("fade_in_step", target)) { + double val = 0.0; + if (!cdbus_msg_get_arg(msg, 1, DBUS_TYPE_DOUBLE, &val)) + return false; + ps->o.fade_in_step = normalize_d(val); + goto cdbus_process_opts_set_success; + } - // fade_out_step - if (!strcmp("fade_out_step", target)) { - double val = 0.0; - if (!cdbus_msg_get_arg(msg, 1, DBUS_TYPE_DOUBLE, &val)) - return false; - ps->o.fade_out_step = normalize_d(val); - goto cdbus_process_opts_set_success; - } + // fade_out_step + if (!strcmp("fade_out_step", target)) { + double val = 0.0; + if (!cdbus_msg_get_arg(msg, 1, DBUS_TYPE_DOUBLE, &val)) + return false; + ps->o.fade_out_step = normalize_d(val); + goto cdbus_process_opts_set_success; + } - // no_fading_openclose - if (!strcmp("no_fading_openclose", target)) { - dbus_bool_t val = FALSE; - if (!cdbus_msg_get_arg(msg, 1, DBUS_TYPE_BOOLEAN, &val)) - return false; - opts_set_no_fading_openclose(ps, val); - goto cdbus_process_opts_set_success; - } + // no_fading_openclose + if (!strcmp("no_fading_openclose", target)) { + dbus_bool_t val = FALSE; + if (!cdbus_msg_get_arg(msg, 1, DBUS_TYPE_BOOLEAN, &val)) + return false; + opts_set_no_fading_openclose(ps, val); + goto cdbus_process_opts_set_success; + } - // unredir_if_possible - if (!strcmp("unredir_if_possible", target)) { - dbus_bool_t val = FALSE; - if (!cdbus_msg_get_arg(msg, 1, DBUS_TYPE_BOOLEAN, &val)) - return false; - if (ps->o.unredir_if_possible != val) { - ps->o.unredir_if_possible = val; - queue_redraw(ps); - } - goto cdbus_process_opts_set_success; - } + // unredir_if_possible + if (!strcmp("unredir_if_possible", target)) { + dbus_bool_t val = FALSE; + if (!cdbus_msg_get_arg(msg, 1, DBUS_TYPE_BOOLEAN, &val)) + return false; + if (ps->o.unredir_if_possible != val) { + ps->o.unredir_if_possible = val; + queue_redraw(ps); + } + goto cdbus_process_opts_set_success; + } - // clear_shadow - if (!strcmp("clear_shadow", target)) - goto cdbus_process_opts_set_success; + // clear_shadow + if (!strcmp("clear_shadow", target)) + goto cdbus_process_opts_set_success; - // track_focus - if (!strcmp("track_focus", target)) { - dbus_bool_t val = FALSE; - if (!cdbus_msg_get_arg(msg, 1, DBUS_TYPE_BOOLEAN, &val)) - return false; - // You could enable this option, but never turn if off - if (val) { - opts_init_track_focus(ps); - } - goto cdbus_process_opts_set_success; - } + // track_focus + if (!strcmp("track_focus", target)) { + dbus_bool_t val = FALSE; + if (!cdbus_msg_get_arg(msg, 1, DBUS_TYPE_BOOLEAN, &val)) + return false; + // You could enable this option, but never turn if off + if (val) { + opts_init_track_focus(ps); + } + goto cdbus_process_opts_set_success; + } - // redirected_force - if (!strcmp("redirected_force", target)) { - cdbus_enum_t val = UNSET; - if (!cdbus_msg_get_arg(msg, 1, CDBUS_TYPE_ENUM, &val)) - return false; - ps->o.redirected_force = val; - force_repaint(ps); - goto cdbus_process_opts_set_success; - } + // redirected_force + if (!strcmp("redirected_force", target)) { + cdbus_enum_t val = UNSET; + if (!cdbus_msg_get_arg(msg, 1, CDBUS_TYPE_ENUM, &val)) + return false; + ps->o.redirected_force = val; + force_repaint(ps); + goto cdbus_process_opts_set_success; + } - // stoppaint_force - cdbus_m_opts_set_do(stoppaint_force, CDBUS_TYPE_ENUM, cdbus_enum_t); + // stoppaint_force + cdbus_m_opts_set_do(stoppaint_force, CDBUS_TYPE_ENUM, cdbus_enum_t); #undef cdbus_m_opts_set_do - log_error(CDBUS_ERROR_BADTGT_S, target); - cdbus_reply_err(ps, msg, CDBUS_ERROR_BADTGT, 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); - return true; + return true; cdbus_process_opts_set_success: - if (!dbus_message_get_no_reply(msg)) - cdbus_reply_bool(ps, msg, true); - return true; + if (!dbus_message_get_no_reply(msg)) + cdbus_reply_bool(ps, msg, true); + return true; } /** * Process an Introspect D-Bus request. */ -static bool -cdbus_process_introspect(session_t *ps, DBusMessage *msg) { - static const char *str_introspect = - "\n" - "\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - "\n"; +static bool cdbus_process_introspect(session_t *ps, DBusMessage *msg) { + static const char *str_introspect = + "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "\n"; - cdbus_reply_string(ps, msg, str_introspect); + cdbus_reply_string(ps, msg, str_introspect); - return true; + return true; } ///@} /** * Process a message from D-Bus. */ -static DBusHandlerResult -cdbus_process(DBusConnection *c, DBusMessage *msg, void *ud) { - session_t *ps = ud; - bool handled = false; +static DBusHandlerResult cdbus_process(DBusConnection *c, DBusMessage *msg, void *ud) { + session_t *ps = ud; + bool handled = false; -#define cdbus_m_ismethod(method) \ - dbus_message_is_method_call(msg, CDBUS_INTERFACE_NAME, method) +#define cdbus_m_ismethod(method) \ + dbus_message_is_method_call(msg, CDBUS_INTERFACE_NAME, method) - if (cdbus_m_ismethod("reset")) { - ps->reset = true; - if (!dbus_message_get_no_reply(msg)) - cdbus_reply_bool(ps, msg, true); - handled = true; - } - else if (cdbus_m_ismethod("repaint")) { - force_repaint(ps); - if (!dbus_message_get_no_reply(msg)) - cdbus_reply_bool(ps, msg, true); - handled = true; - } - else if (cdbus_m_ismethod("list_win")) { - handled = cdbus_process_list_win(ps, msg); - } - else if (cdbus_m_ismethod("win_get")) { - handled = cdbus_process_win_get(ps, msg); - } - else if (cdbus_m_ismethod("win_set")) { - handled = cdbus_process_win_set(ps, msg); - } - else if (cdbus_m_ismethod("find_win")) { - handled = cdbus_process_find_win(ps, msg); - } - else if (cdbus_m_ismethod("opts_get")) { - handled = cdbus_process_opts_get(ps, msg); - } - else if (cdbus_m_ismethod("opts_set")) { - handled = cdbus_process_opts_set(ps, msg); - } + if (cdbus_m_ismethod("reset")) { + ps->reset = true; + if (!dbus_message_get_no_reply(msg)) + cdbus_reply_bool(ps, msg, true); + handled = true; + } else if (cdbus_m_ismethod("repaint")) { + force_repaint(ps); + if (!dbus_message_get_no_reply(msg)) + cdbus_reply_bool(ps, msg, true); + handled = true; + } else if (cdbus_m_ismethod("list_win")) { + handled = cdbus_process_list_win(ps, msg); + } else if (cdbus_m_ismethod("win_get")) { + handled = cdbus_process_win_get(ps, msg); + } else if (cdbus_m_ismethod("win_set")) { + handled = cdbus_process_win_set(ps, msg); + } else if (cdbus_m_ismethod("find_win")) { + handled = cdbus_process_find_win(ps, msg); + } else if (cdbus_m_ismethod("opts_get")) { + handled = cdbus_process_opts_get(ps, msg); + } else if (cdbus_m_ismethod("opts_set")) { + handled = cdbus_process_opts_set(ps, msg); + } #undef cdbus_m_ismethod - else if (dbus_message_is_method_call(msg, - "org.freedesktop.DBus.Introspectable", "Introspect")) { - handled = cdbus_process_introspect(ps, msg); - } - else if (dbus_message_is_method_call(msg, - "org.freedesktop.DBus.Peer", "Ping")) { - cdbus_reply(ps, msg, NULL, NULL); - handled = true; - } - else if (dbus_message_is_method_call(msg, - "org.freedesktop.DBus.Peer", "GetMachineId")) { - char *uuid = dbus_get_local_machine_id(); - if (uuid) { - cdbus_reply_string(ps, msg, uuid); - dbus_free(uuid); - handled = true; - } - } - else if (dbus_message_is_signal(msg, "org.freedesktop.DBus", "NameAcquired") - || dbus_message_is_signal(msg, "org.freedesktop.DBus", "NameLost")) { - handled = true; - } - else { - if (DBUS_MESSAGE_TYPE_ERROR == dbus_message_get_type(msg)) { - log_error("Error message of path \"%s\" " - "interface \"%s\", member \"%s\", error \"%s\"", - dbus_message_get_path(msg), dbus_message_get_interface(msg), - dbus_message_get_member(msg), dbus_message_get_error_name(msg)); - } - else { - log_error("Illegal message of type \"%s\", path \"%s\" " - "interface \"%s\", member \"%s\"", - cdbus_repr_msgtype(msg), dbus_message_get_path(msg), - dbus_message_get_interface(msg), dbus_message_get_member(msg)); - } - if (DBUS_MESSAGE_TYPE_METHOD_CALL == dbus_message_get_type(msg) - && !dbus_message_get_no_reply(msg)) - cdbus_reply_err(ps, msg, CDBUS_ERROR_BADMSG, CDBUS_ERROR_BADMSG_S); - handled = true; - } + else if (dbus_message_is_method_call(msg, "org.freedesktop.DBus.Introspectable", + "Introspect")) { + handled = cdbus_process_introspect(ps, msg); + } else if (dbus_message_is_method_call(msg, "org.freedesktop.DBus.Peer", "Ping")) { + cdbus_reply(ps, msg, NULL, NULL); + handled = true; + } else if (dbus_message_is_method_call(msg, "org.freedesktop.DBus.Peer", + "GetMachineId")) { + char *uuid = dbus_get_local_machine_id(); + if (uuid) { + cdbus_reply_string(ps, msg, uuid); + dbus_free(uuid); + handled = true; + } + } else if (dbus_message_is_signal(msg, "org.freedesktop.DBus", "NameAcquired") || + dbus_message_is_signal(msg, "org.freedesktop.DBus", "NameLost")) { + handled = true; + } else { + if (DBUS_MESSAGE_TYPE_ERROR == dbus_message_get_type(msg)) { + log_error( + "Error message of path \"%s\" " + "interface \"%s\", member \"%s\", error \"%s\"", + dbus_message_get_path(msg), dbus_message_get_interface(msg), + dbus_message_get_member(msg), dbus_message_get_error_name(msg)); + } else { + log_error("Illegal message of type \"%s\", path \"%s\" " + "interface \"%s\", member \"%s\"", + cdbus_repr_msgtype(msg), dbus_message_get_path(msg), + dbus_message_get_interface(msg), + dbus_message_get_member(msg)); + } + if (DBUS_MESSAGE_TYPE_METHOD_CALL == dbus_message_get_type(msg) && + !dbus_message_get_no_reply(msg)) + cdbus_reply_err(ps, msg, CDBUS_ERROR_BADMSG, CDBUS_ERROR_BADMSG_S); + handled = true; + } - // If the message could not be processed, and an reply is expected, return - // an empty reply. - if (!handled && DBUS_MESSAGE_TYPE_METHOD_CALL == dbus_message_get_type(msg) - && !dbus_message_get_no_reply(msg)) { - cdbus_reply_err(ps, msg, CDBUS_ERROR_UNKNOWN, CDBUS_ERROR_UNKNOWN_S); - handled = true; - } + // If the message could not be processed, and an reply is expected, return + // an empty reply. + if (!handled && DBUS_MESSAGE_TYPE_METHOD_CALL == dbus_message_get_type(msg) && + !dbus_message_get_no_reply(msg)) { + cdbus_reply_err(ps, msg, CDBUS_ERROR_UNKNOWN, CDBUS_ERROR_UNKNOWN_S); + handled = true; + } - return handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + return handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } /** @name Core callbacks */ ///@{ -void -cdbus_ev_win_added(session_t *ps, win *w) { - struct cdbus_data *cd = ps->dbus_data; - if (cd->dbus_conn) - cdbus_signal_wid(ps, "win_added", w->id); +void cdbus_ev_win_added(session_t *ps, win *w) { + struct cdbus_data *cd = ps->dbus_data; + if (cd->dbus_conn) + cdbus_signal_wid(ps, "win_added", w->id); } -void -cdbus_ev_win_destroyed(session_t *ps, win *w) { - struct cdbus_data *cd = ps->dbus_data; - if (cd->dbus_conn) - cdbus_signal_wid(ps, "win_destroyed", w->id); +void cdbus_ev_win_destroyed(session_t *ps, win *w) { + struct cdbus_data *cd = ps->dbus_data; + if (cd->dbus_conn) + cdbus_signal_wid(ps, "win_destroyed", w->id); } -void -cdbus_ev_win_mapped(session_t *ps, win *w) { - struct cdbus_data *cd = ps->dbus_data; - if (cd->dbus_conn) - cdbus_signal_wid(ps, "win_mapped", w->id); +void cdbus_ev_win_mapped(session_t *ps, win *w) { + struct cdbus_data *cd = ps->dbus_data; + if (cd->dbus_conn) + cdbus_signal_wid(ps, "win_mapped", w->id); } -void -cdbus_ev_win_unmapped(session_t *ps, win *w) { - struct cdbus_data *cd = ps->dbus_data; - if (cd->dbus_conn) - cdbus_signal_wid(ps, "win_unmapped", w->id); +void cdbus_ev_win_unmapped(session_t *ps, win *w) { + struct cdbus_data *cd = ps->dbus_data; + if (cd->dbus_conn) + cdbus_signal_wid(ps, "win_unmapped", w->id); } -void -cdbus_ev_win_focusout(session_t *ps, win *w) { - struct cdbus_data *cd = ps->dbus_data; - if (cd->dbus_conn) - cdbus_signal_wid(ps, "win_focusout", w->id); +void cdbus_ev_win_focusout(session_t *ps, win *w) { + struct cdbus_data *cd = ps->dbus_data; + if (cd->dbus_conn) + cdbus_signal_wid(ps, "win_focusout", w->id); } -void -cdbus_ev_win_focusin(session_t *ps, win *w) { - struct cdbus_data *cd = ps->dbus_data; - if (cd->dbus_conn) - cdbus_signal_wid(ps, "win_focusin", w->id); +void cdbus_ev_win_focusin(session_t *ps, win *w) { + struct cdbus_data *cd = ps->dbus_data; + if (cd->dbus_conn) + cdbus_signal_wid(ps, "win_focusin", w->id); } //!@} diff --git a/src/opengl.c b/src/opengl.c index 6561280..1ff59ac 100644 --- a/src/opengl.c +++ b/src/opengl.c @@ -9,681 +9,674 @@ * */ -#include -#include -#include -#include #include +#include +#include +#include +#include -#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/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" -static inline XVisualInfo * -get_visualinfo_from_visual(session_t *ps, xcb_visualid_t visual) { - XVisualInfo vreq = { .visualid = visual }; - int nitems = 0; +static inline XVisualInfo *get_visualinfo_from_visual(session_t *ps, xcb_visualid_t visual) { + XVisualInfo vreq = {.visualid = visual}; + int nitems = 0; - return XGetVisualInfo(ps->dpy, VisualIDMask, &vreq, &nitems); + return XGetVisualInfo(ps->dpy, VisualIDMask, &vreq, &nitems); } /** * Initialize OpenGL. */ -bool -glx_init(session_t *ps, bool need_render) { - bool success = false; - XVisualInfo *pvis = NULL; +bool glx_init(session_t *ps, bool need_render) { + bool success = false; + XVisualInfo *pvis = NULL; - // Check for GLX extension - if (!ps->glx_exists) { - if (glXQueryExtension(ps->dpy, &ps->glx_event, &ps->glx_error)) - ps->glx_exists = true; - else { - log_error("No GLX extension."); - goto glx_init_end; - } - } + // Check for GLX extension + if (!ps->glx_exists) { + if (glXQueryExtension(ps->dpy, &ps->glx_event, &ps->glx_error)) + ps->glx_exists = true; + else { + log_error("No GLX extension."); + goto glx_init_end; + } + } - if (ps->o.glx_swap_method > CGLX_MAX_BUFFER_AGE) { - log_error("glx-swap-method is too big"); - goto glx_init_end; - } + if (ps->o.glx_swap_method > CGLX_MAX_BUFFER_AGE) { + log_error("glx-swap-method is too big"); + goto glx_init_end; + } - // Get XVisualInfo - pvis = get_visualinfo_from_visual(ps, ps->vis); - if (!pvis) { - log_error("Failed to acquire XVisualInfo for current visual."); - goto glx_init_end; - } + // Get XVisualInfo + pvis = get_visualinfo_from_visual(ps, ps->vis); + if (!pvis) { + log_error("Failed to acquire XVisualInfo for current visual."); + goto glx_init_end; + } - // Ensure the visual is double-buffered - if (need_render) { - int value = 0; - if (Success != glXGetConfig(ps->dpy, pvis, GLX_USE_GL, &value) || !value) { - log_error("Root visual is not a GL visual."); - goto glx_init_end; - } + // Ensure the visual is double-buffered + if (need_render) { + int value = 0; + if (Success != glXGetConfig(ps->dpy, pvis, GLX_USE_GL, &value) || !value) { + log_error("Root visual is not a GL visual."); + goto glx_init_end; + } - if (Success != glXGetConfig(ps->dpy, pvis, GLX_DOUBLEBUFFER, &value) - || !value) { - log_error("Root visual is not a double buffered GL visual."); - goto glx_init_end; - } - } + if (Success != glXGetConfig(ps->dpy, pvis, GLX_DOUBLEBUFFER, &value) || !value) { + log_error("Root visual is not a double buffered GL visual."); + goto glx_init_end; + } + } - // Ensure GLX_EXT_texture_from_pixmap exists - if (need_render && !glxext.has_GLX_EXT_texture_from_pixmap) - goto glx_init_end; + // Ensure GLX_EXT_texture_from_pixmap exists + if (need_render && !glxext.has_GLX_EXT_texture_from_pixmap) + goto glx_init_end; - // Initialize GLX data structure - if (!ps->psglx) { - static const glx_session_t CGLX_SESSION_DEF = CGLX_SESSION_INIT; - ps->psglx = cmalloc(glx_session_t); - memcpy(ps->psglx, &CGLX_SESSION_DEF, sizeof(glx_session_t)); + // Initialize GLX data structure + if (!ps->psglx) { + static const glx_session_t CGLX_SESSION_DEF = CGLX_SESSION_INIT; + ps->psglx = cmalloc(glx_session_t); + memcpy(ps->psglx, &CGLX_SESSION_DEF, sizeof(glx_session_t)); - for (int i = 0; i < MAX_BLUR_PASS; ++i) { - glx_blur_pass_t *ppass = &ps->psglx->blur_passes[i]; - ppass->unifm_factor_center = -1; - ppass->unifm_offset_x = -1; - ppass->unifm_offset_y = -1; - } - } + for (int i = 0; i < MAX_BLUR_PASS; ++i) { + glx_blur_pass_t *ppass = &ps->psglx->blur_passes[i]; + ppass->unifm_factor_center = -1; + ppass->unifm_offset_x = -1; + ppass->unifm_offset_y = -1; + } + } - glx_session_t *psglx = ps->psglx; + glx_session_t *psglx = ps->psglx; - if (!psglx->context) { - // Get GLX context + if (!psglx->context) { + // Get GLX context #ifndef DEBUG_GLX_DEBUG_CONTEXT - psglx->context = glXCreateContext(ps->dpy, pvis, None, GL_TRUE); + psglx->context = glXCreateContext(ps->dpy, pvis, None, GL_TRUE); #else - { - GLXFBConfig fbconfig = get_fbconfig_from_visualinfo(ps, pvis); - if (!fbconfig) { - log_error("Failed to get GLXFBConfig for root visual %#lx.", pvis->visualid); - goto glx_init_end; - } + { + GLXFBConfig fbconfig = get_fbconfig_from_visualinfo(ps, pvis); + if (!fbconfig) { + log_error("Failed to get GLXFBConfig for root visual " + "%#lx.", + pvis->visualid); + goto glx_init_end; + } - f_glXCreateContextAttribsARB p_glXCreateContextAttribsARB = - (f_glXCreateContextAttribsARB) - glXGetProcAddress((const GLubyte *) "glXCreateContextAttribsARB"); - if (!p_glXCreateContextAttribsARB) { - log_error("Failed to get glXCreateContextAttribsARB()."); - goto glx_init_end; - } + f_glXCreateContextAttribsARB p_glXCreateContextAttribsARB = + (f_glXCreateContextAttribsARB)glXGetProcAddress( + (const GLubyte *)"glXCreateContextAttribsARB"); + if (!p_glXCreateContextAttribsARB) { + log_error("Failed to get glXCreateContextAttribsARB()."); + goto glx_init_end; + } - static const int attrib_list[] = { - GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB, - None - }; - psglx->context = p_glXCreateContextAttribsARB(ps->dpy, fbconfig, NULL, - GL_TRUE, attrib_list); - } + static const int attrib_list[] = { + GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB, None}; + psglx->context = p_glXCreateContextAttribsARB( + ps->dpy, fbconfig, NULL, GL_TRUE, attrib_list); + } #endif - if (!psglx->context) { - log_error("Failed to get GLX context."); - goto glx_init_end; - } + if (!psglx->context) { + log_error("Failed to get GLX context."); + goto glx_init_end; + } - // Attach GLX context - if (!glXMakeCurrent(ps->dpy, get_tgt_window(ps), psglx->context)) { - log_error("Failed to attach GLX context."); - goto glx_init_end; - } + // Attach GLX context + if (!glXMakeCurrent(ps->dpy, get_tgt_window(ps), psglx->context)) { + log_error("Failed to attach GLX context."); + goto glx_init_end; + } #ifdef DEBUG_GLX_DEBUG_CONTEXT - { - f_DebugMessageCallback p_DebugMessageCallback = - (f_DebugMessageCallback) - glXGetProcAddress((const GLubyte *) "glDebugMessageCallback"); - if (!p_DebugMessageCallback) { - log_error("Failed to get glDebugMessageCallback(0."); - goto glx_init_end; - } - p_DebugMessageCallback(glx_debug_msg_callback, ps); - } + { + f_DebugMessageCallback p_DebugMessageCallback = + (f_DebugMessageCallback)glXGetProcAddress( + (const GLubyte *)"glDebugMessageCallback"); + if (!p_DebugMessageCallback) { + log_error("Failed to get glDebugMessageCallback(0."); + goto glx_init_end; + } + p_DebugMessageCallback(glx_debug_msg_callback, ps); + } #endif + } - } + // Ensure we have a stencil buffer. X Fixes does not guarantee rectangles + // in regions don't overlap, so we must use stencil buffer to make sure + // we don't paint a region for more than one time, I think? + if (need_render && !ps->o.glx_no_stencil) { + GLint val = 0; + glGetIntegerv(GL_STENCIL_BITS, &val); + if (!val) { + log_error("Target window doesn't have stencil buffer."); + goto glx_init_end; + } + } - // Ensure we have a stencil buffer. X Fixes does not guarantee rectangles - // in regions don't overlap, so we must use stencil buffer to make sure - // we don't paint a region for more than one time, I think? - if (need_render && !ps->o.glx_no_stencil) { - GLint val = 0; - glGetIntegerv(GL_STENCIL_BITS, &val); - if (!val) { - log_error("Target window doesn't have stencil buffer."); - goto glx_init_end; - } - } + // Check GL_ARB_texture_non_power_of_two, requires a GLX context and + // must precede FBConfig fetching + if (need_render) + psglx->has_texture_non_power_of_two = + gl_has_extension("GL_ARB_texture_non_power_of_two"); - // Check GL_ARB_texture_non_power_of_two, requires a GLX context and - // must precede FBConfig fetching - if (need_render) - psglx->has_texture_non_power_of_two = gl_has_extension( - "GL_ARB_texture_non_power_of_two"); + // Render preparations + if (need_render) { + glx_on_root_change(ps); - // Render preparations - if (need_render) { - glx_on_root_change(ps); + glDisable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glDisable(GL_BLEND); - glDisable(GL_DEPTH_TEST); - glDepthMask(GL_FALSE); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glDisable(GL_BLEND); + if (!ps->o.glx_no_stencil) { + // Initialize stencil buffer + glClear(GL_STENCIL_BUFFER_BIT); + glDisable(GL_STENCIL_TEST); + glStencilMask(0x1); + glStencilFunc(GL_EQUAL, 0x1, 0x1); + } - if (!ps->o.glx_no_stencil) { - // Initialize stencil buffer - glClear(GL_STENCIL_BUFFER_BIT); - glDisable(GL_STENCIL_TEST); - glStencilMask(0x1); - glStencilFunc(GL_EQUAL, 0x1, 0x1); - } + // Clear screen + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + // glXSwapBuffers(ps->dpy, get_tgt_window(ps)); + } - // Clear screen - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - // glXSwapBuffers(ps->dpy, get_tgt_window(ps)); - } - - success = true; + success = true; glx_init_end: - cxfree(pvis); + cxfree(pvis); - if (!success) - glx_destroy(ps); + if (!success) + glx_destroy(ps); - return success; + return success; } -static void -glx_free_prog_main(session_t *ps, glx_prog_main_t *pprogram) { - if (!pprogram) - return; - if (pprogram->prog) { - glDeleteProgram(pprogram->prog); - pprogram->prog = 0; - } - pprogram->unifm_opacity = -1; - pprogram->unifm_invert_color = -1; - pprogram->unifm_tex = -1; +static void glx_free_prog_main(session_t *ps, glx_prog_main_t *pprogram) { + if (!pprogram) + return; + if (pprogram->prog) { + glDeleteProgram(pprogram->prog); + pprogram->prog = 0; + } + pprogram->unifm_opacity = -1; + pprogram->unifm_invert_color = -1; + pprogram->unifm_tex = -1; } /** * Destroy GLX related resources. */ -void -glx_destroy(session_t *ps) { - if (!ps->psglx) - return; +void glx_destroy(session_t *ps) { + if (!ps->psglx) + return; - // Free all GLX resources of windows - for (win *w = ps->list; w; w = w->next) - free_win_res_glx(ps, w); + // Free all GLX resources of windows + for (win *w = ps->list; w; w = w->next) + free_win_res_glx(ps, w); - // Free GLSL shaders/programs - for (int i = 0; i < MAX_BLUR_PASS; ++i) { - glx_blur_pass_t *ppass = &ps->psglx->blur_passes[i]; - if (ppass->frag_shader) - glDeleteShader(ppass->frag_shader); - if (ppass->prog) - glDeleteProgram(ppass->prog); - } + // Free GLSL shaders/programs + for (int i = 0; i < MAX_BLUR_PASS; ++i) { + glx_blur_pass_t *ppass = &ps->psglx->blur_passes[i]; + if (ppass->frag_shader) + glDeleteShader(ppass->frag_shader); + if (ppass->prog) + glDeleteProgram(ppass->prog); + } - glx_free_prog_main(ps, &ps->glx_prog_win); + glx_free_prog_main(ps, &ps->glx_prog_win); - gl_check_err(); + gl_check_err(); - // Destroy GLX context - if (ps->psglx->context) { - glXDestroyContext(ps->dpy, ps->psglx->context); - ps->psglx->context = NULL; - } + // Destroy GLX context + if (ps->psglx->context) { + glXDestroyContext(ps->dpy, ps->psglx->context); + ps->psglx->context = NULL; + } - free(ps->psglx); - ps->psglx = NULL; + free(ps->psglx); + ps->psglx = NULL; } /** * Callback to run on root window size change. */ -void -glx_on_root_change(session_t *ps) { - glViewport(0, 0, ps->root_width, ps->root_height); +void glx_on_root_change(session_t *ps) { + glViewport(0, 0, ps->root_width, ps->root_height); - // Initialize matrix, copied from dcompmgr - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, ps->root_width, 0, ps->root_height, -1000.0, 1000.0); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); + // Initialize matrix, copied from dcompmgr + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, ps->root_width, 0, ps->root_height, -1000.0, 1000.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); } /** * Initialize GLX blur filter. */ -bool -glx_init_blur(session_t *ps) { - assert(ps->o.blur_kerns[0]); +bool glx_init_blur(session_t *ps) { + assert(ps->o.blur_kerns[0]); - // Allocate PBO if more than one blur kernel is present - if (ps->o.blur_kerns[1]) { - // Try to generate a framebuffer - GLuint fbo = 0; - glGenFramebuffers(1, &fbo); - if (!fbo) { - log_error("Failed to generate Framebuffer. Cannot do multi-pass blur with GLX" - " backend."); - return false; - } - glDeleteFramebuffers(1, &fbo); - } + // Allocate PBO if more than one blur kernel is present + if (ps->o.blur_kerns[1]) { + // Try to generate a framebuffer + GLuint fbo = 0; + glGenFramebuffers(1, &fbo); + if (!fbo) { + log_error("Failed to generate Framebuffer. Cannot do multi-pass " + "blur with GLX" + " backend."); + return false; + } + glDeleteFramebuffers(1, &fbo); + } - { - char *lc_numeric_old = strdup(setlocale(LC_NUMERIC, NULL)); - // Enforce LC_NUMERIC locale "C" here to make sure decimal point is sane - // Thanks to hiciu for reporting. - setlocale(LC_NUMERIC, "C"); + { + char *lc_numeric_old = strdup(setlocale(LC_NUMERIC, NULL)); + // Enforce LC_NUMERIC locale "C" here to make sure decimal point is sane + // Thanks to hiciu for reporting. + setlocale(LC_NUMERIC, "C"); - static const char *FRAG_SHADER_BLUR_PREFIX = - "#version 110\n" - "%s" - "uniform float offset_x;\n" - "uniform float offset_y;\n" - "uniform float factor_center;\n" - "uniform %s tex_scr;\n" - "\n" - "void main() {\n" - " vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);\n"; - 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"; - static const char *FRAG_SHADER_BLUR_SUFFIX = - " sum += %s(tex_scr, vec2(gl_TexCoord[0].x, gl_TexCoord[0].y)) * factor_center;\n" - " gl_FragColor = sum / (factor_center + float(%.7g));\n" - "}\n"; + static const char *FRAG_SHADER_BLUR_PREFIX = + "#version 110\n" + "%s" + "uniform float offset_x;\n" + "uniform float offset_y;\n" + "uniform float factor_center;\n" + "uniform %s tex_scr;\n" + "\n" + "void main() {\n" + " vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);\n"; + 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"; + static const char *FRAG_SHADER_BLUR_SUFFIX = + " sum += %s(tex_scr, vec2(gl_TexCoord[0].x, gl_TexCoord[0].y)) * " + "factor_center;\n" + " gl_FragColor = sum / (factor_center + float(%.7g));\n" + "}\n"; - const bool use_texture_rect = !ps->psglx->has_texture_non_power_of_two; - const char *sampler_type = (use_texture_rect ? - "sampler2DRect": "sampler2D"); - const char *texture_func = (use_texture_rect ? - "texture2DRect": "texture2D"); - const char *shader_add = FRAG_SHADER_BLUR_ADD; - char *extension = NULL; - if (use_texture_rect) { - mstrextend(&extension, "#extension GL_ARB_texture_rectangle : require\n"); - } - if (!extension) { - extension = strdup(""); - } + const bool use_texture_rect = !ps->psglx->has_texture_non_power_of_two; + const char *sampler_type = (use_texture_rect ? "sampler2DRect" : "sampler2D"); + const char *texture_func = (use_texture_rect ? "texture2DRect" : "texture2D"); + const char *shader_add = FRAG_SHADER_BLUR_ADD; + char *extension = NULL; + if (use_texture_rect) { + mstrextend(&extension, "#extension GL_ARB_texture_rectangle : " + "require\n"); + } + if (!extension) { + extension = strdup(""); + } - for (int i = 0; i < MAX_BLUR_PASS && ps->o.blur_kerns[i]; ++i) { - auto kern = ps->o.blur_kerns[i]; - glx_blur_pass_t *ppass = &ps->psglx->blur_passes[i]; + for (int i = 0; i < MAX_BLUR_PASS && ps->o.blur_kerns[i]; ++i) { + auto kern = ps->o.blur_kerns[i]; + glx_blur_pass_t *ppass = &ps->psglx->blur_passes[i]; - // Build shader - { - int width = kern->w, height = kern->h; - int nele = width * height - 1; - unsigned int len = strlen(FRAG_SHADER_BLUR_PREFIX) + - strlen(sampler_type) + - strlen(extension) + - (strlen(shader_add) + strlen(texture_func) + 42) * nele + - strlen(FRAG_SHADER_BLUR_SUFFIX) + - strlen(texture_func) + 12 + 1; - char *shader_str = ccalloc(len, char); - char *pc = shader_str; - sprintf(pc, FRAG_SHADER_BLUR_PREFIX, extension, sampler_type); - pc += strlen(pc); - assert(strlen(shader_str) < len); + // Build shader + { + int width = kern->w, height = kern->h; + int nele = width * height - 1; + unsigned int len = + strlen(FRAG_SHADER_BLUR_PREFIX) + + strlen(sampler_type) + strlen(extension) + + (strlen(shader_add) + strlen(texture_func) + 42) * nele + + strlen(FRAG_SHADER_BLUR_SUFFIX) + + strlen(texture_func) + 12 + 1; + char *shader_str = ccalloc(len, char); + char *pc = shader_str; + sprintf(pc, FRAG_SHADER_BLUR_PREFIX, extension, sampler_type); + pc += strlen(pc); + assert(strlen(shader_str) < len); - double sum = 0.0; - for (int j = 0; j < height; ++j) { - for (int k = 0; k < width; ++k) { - if (height / 2 == j && width / 2 == k) - continue; - double val = kern->data[j * width + k]; - if (val == 0) { - continue; - } - sum += val; - sprintf(pc, shader_add, val, texture_func, k - width / 2, j - height / 2); - pc += strlen(pc); - assert(strlen(shader_str) < len); - } - } + double sum = 0.0; + for (int j = 0; j < height; ++j) { + for (int k = 0; k < width; ++k) { + if (height / 2 == j && width / 2 == k) + continue; + double val = kern->data[j * width + k]; + if (val == 0) { + continue; + } + sum += val; + sprintf(pc, shader_add, val, texture_func, + k - width / 2, j - height / 2); + pc += strlen(pc); + assert(strlen(shader_str) < len); + } + } - sprintf(pc, FRAG_SHADER_BLUR_SUFFIX, texture_func, sum); - assert(strlen(shader_str) < len); - ppass->frag_shader = gl_create_shader(GL_FRAGMENT_SHADER, shader_str); - free(shader_str); - } + sprintf(pc, FRAG_SHADER_BLUR_SUFFIX, texture_func, sum); + assert(strlen(shader_str) < len); + ppass->frag_shader = + gl_create_shader(GL_FRAGMENT_SHADER, shader_str); + free(shader_str); + } - if (!ppass->frag_shader) { - log_error("Failed to create fragment shader %d.", i); - free(extension); - free(lc_numeric_old); - return false; - } + if (!ppass->frag_shader) { + log_error("Failed to create fragment shader %d.", i); + free(extension); + free(lc_numeric_old); + return false; + } - // Build program - ppass->prog = gl_create_program(&ppass->frag_shader, 1); - if (!ppass->prog) { - log_error("Failed to create GLSL program."); - free(extension); - free(lc_numeric_old); - return false; - } + // Build program + ppass->prog = gl_create_program(&ppass->frag_shader, 1); + if (!ppass->prog) { + log_error("Failed to create GLSL program."); + free(extension); + free(lc_numeric_old); + return false; + } - // Get uniform addresses -#define P_GET_UNIFM_LOC(name, target) { \ - ppass->target = glGetUniformLocation(ppass->prog, name); \ - if (ppass->target < 0) { \ - log_error("Failed to get location of %d-th uniform '" name "'. Might be troublesome.", i); \ - } \ - } + // Get uniform addresses +#define P_GET_UNIFM_LOC(name, target) \ + { \ + ppass->target = glGetUniformLocation(ppass->prog, name); \ + if (ppass->target < 0) { \ + log_error("Failed to get location of %d-th uniform '" name \ + "'. Might be troublesome.", \ + i); \ + } \ + } - P_GET_UNIFM_LOC("factor_center", unifm_factor_center); - P_GET_UNIFM_LOC("offset_x", unifm_offset_x); - P_GET_UNIFM_LOC("offset_y", unifm_offset_y); + P_GET_UNIFM_LOC("factor_center", unifm_factor_center); + P_GET_UNIFM_LOC("offset_x", unifm_offset_x); + P_GET_UNIFM_LOC("offset_y", unifm_offset_y); #undef P_GET_UNIFM_LOC - } - free(extension); + } + free(extension); - // Restore LC_NUMERIC - setlocale(LC_NUMERIC, lc_numeric_old); - free(lc_numeric_old); - } + // Restore LC_NUMERIC + setlocale(LC_NUMERIC, lc_numeric_old); + free(lc_numeric_old); + } + gl_check_err(); - gl_check_err(); - - return true; + return true; } /** * Load a GLSL main program from shader strings. */ -bool -glx_load_prog_main(session_t *ps, - const char *vshader_str, const char *fshader_str, - glx_prog_main_t *pprogram) { - assert(pprogram); +bool glx_load_prog_main(session_t *ps, const char *vshader_str, const char *fshader_str, + glx_prog_main_t *pprogram) { + assert(pprogram); - // Build program - pprogram->prog = gl_create_program_from_str(vshader_str, fshader_str); - if (!pprogram->prog) { - log_error("Failed to create GLSL program."); - return false; - } + // Build program + pprogram->prog = gl_create_program_from_str(vshader_str, fshader_str); + if (!pprogram->prog) { + log_error("Failed to create GLSL program."); + return false; + } - // Get uniform addresses -#define P_GET_UNIFM_LOC(name, target) { \ - pprogram->target = glGetUniformLocation(pprogram->prog, name); \ - if (pprogram->target < 0) { \ - log_error("Failed to get location of uniform '" name "'. Might be troublesome."); \ - } \ - } - P_GET_UNIFM_LOC("opacity", unifm_opacity); - P_GET_UNIFM_LOC("invert_color", unifm_invert_color); - P_GET_UNIFM_LOC("tex", unifm_tex); + // Get uniform addresses +#define P_GET_UNIFM_LOC(name, target) \ + { \ + pprogram->target = glGetUniformLocation(pprogram->prog, name); \ + if (pprogram->target < 0) { \ + log_error("Failed to get location of uniform '" name \ + "'. Might be troublesome."); \ + } \ + } + P_GET_UNIFM_LOC("opacity", unifm_opacity); + P_GET_UNIFM_LOC("invert_color", unifm_invert_color); + P_GET_UNIFM_LOC("tex", unifm_tex); #undef P_GET_UNIFM_LOC - gl_check_err(); + gl_check_err(); - return true; + return true; } /** * Bind a X pixmap to an OpenGL texture. */ -bool -glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap, - 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) - return true; +bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap, 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) + return true; - if (!pixmap) { - log_error("Binding to an empty pixmap %#010x. This can't work.", pixmap); - return false; - } + if (!pixmap) { + log_error("Binding to an empty pixmap %#010x. This can't work.", pixmap); + return false; + } - assert(fbcfg); - glx_texture_t *ptex = *pptex; - bool need_release = true; + assert(fbcfg); + glx_texture_t *ptex = *pptex; + bool need_release = true; - // Release pixmap if parameters are inconsistent - if (ptex && ptex->texture && ptex->pixmap != pixmap) { - glx_release_pixmap(ps, ptex); - } + // Release pixmap if parameters are inconsistent + if (ptex && ptex->texture && ptex->pixmap != pixmap) { + glx_release_pixmap(ps, ptex); + } - // Allocate structure - if (!ptex) { - static const glx_texture_t GLX_TEX_DEF = { - .texture = 0, - .glpixmap = 0, - .pixmap = 0, - .target = 0, - .width = 0, - .height = 0, - .y_inverted = false, - }; + // Allocate structure + if (!ptex) { + static const glx_texture_t GLX_TEX_DEF = { + .texture = 0, + .glpixmap = 0, + .pixmap = 0, + .target = 0, + .width = 0, + .height = 0, + .y_inverted = false, + }; - ptex = cmalloc(glx_texture_t); - memcpy(ptex, &GLX_TEX_DEF, sizeof(glx_texture_t)); - *pptex = ptex; - } + ptex = cmalloc(glx_texture_t); + memcpy(ptex, &GLX_TEX_DEF, sizeof(glx_texture_t)); + *pptex = ptex; + } - // Create GLX pixmap - unsigned depth = 0; - if (!ptex->glpixmap) { - need_release = false; + // Create GLX pixmap + unsigned depth = 0; + if (!ptex->glpixmap) { + need_release = false; - // Retrieve pixmap parameters, if they aren't provided - if (!(width && height)) { - Window rroot = None; - int rx = 0, ry = 0; - unsigned rbdwid = 0; - if (!XGetGeometry(ps->dpy, pixmap, &rroot, &rx, &ry, - &width, &height, &rbdwid, &depth)) { - log_error("Failed to query info of pixmap %#010x.", pixmap); - return false; - } - if (depth > OPENGL_MAX_DEPTH) { - log_error("Requested depth %d higher than %d.", depth, - OPENGL_MAX_DEPTH); - return false; - } - } + // Retrieve pixmap parameters, if they aren't provided + if (!(width && height)) { + Window rroot = None; + int rx = 0, ry = 0; + unsigned rbdwid = 0; + if (!XGetGeometry(ps->dpy, pixmap, &rroot, &rx, &ry, &width, + &height, &rbdwid, &depth)) { + log_error("Failed to query info of pixmap %#010x.", pixmap); + return false; + } + if (depth > OPENGL_MAX_DEPTH) { + log_error("Requested depth %d higher than %d.", depth, + OPENGL_MAX_DEPTH); + return false; + } + } - // Determine texture target, copied from compiz - // The assumption we made here is the target never changes based on any - // pixmap-specific parameters, and this may change in the future - GLenum tex_tgt = 0; - if (GLX_TEXTURE_2D_BIT_EXT & fbcfg->texture_tgts - && ps->psglx->has_texture_non_power_of_two) - tex_tgt = GLX_TEXTURE_2D_EXT; - else if (GLX_TEXTURE_RECTANGLE_BIT_EXT & fbcfg->texture_tgts) - tex_tgt = GLX_TEXTURE_RECTANGLE_EXT; - else if (!(GLX_TEXTURE_2D_BIT_EXT & fbcfg->texture_tgts)) - tex_tgt = GLX_TEXTURE_RECTANGLE_EXT; - else - tex_tgt = GLX_TEXTURE_2D_EXT; + // Determine texture target, copied from compiz + // The assumption we made here is the target never changes based on any + // pixmap-specific parameters, and this may change in the future + GLenum tex_tgt = 0; + if (GLX_TEXTURE_2D_BIT_EXT & fbcfg->texture_tgts && + ps->psglx->has_texture_non_power_of_two) + tex_tgt = GLX_TEXTURE_2D_EXT; + else if (GLX_TEXTURE_RECTANGLE_BIT_EXT & fbcfg->texture_tgts) + tex_tgt = GLX_TEXTURE_RECTANGLE_EXT; + else if (!(GLX_TEXTURE_2D_BIT_EXT & fbcfg->texture_tgts)) + tex_tgt = GLX_TEXTURE_RECTANGLE_EXT; + else + tex_tgt = GLX_TEXTURE_2D_EXT; - log_debug("depth %d, tgt %#x, rgba %d", depth, tex_tgt, - (GLX_TEXTURE_FORMAT_RGBA_EXT == fbcfg->texture_fmt)); + log_debug("depth %d, tgt %#x, rgba %d", depth, tex_tgt, + (GLX_TEXTURE_FORMAT_RGBA_EXT == fbcfg->texture_fmt)); - GLint attrs[] = { - GLX_TEXTURE_FORMAT_EXT, - fbcfg->texture_fmt, - GLX_TEXTURE_TARGET_EXT, - tex_tgt, - 0, - }; + GLint attrs[] = { + GLX_TEXTURE_FORMAT_EXT, + fbcfg->texture_fmt, + GLX_TEXTURE_TARGET_EXT, + tex_tgt, + 0, + }; - ptex->glpixmap = glXCreatePixmap(ps->dpy, fbcfg->cfg, pixmap, attrs); - ptex->pixmap = pixmap; - ptex->target = (GLX_TEXTURE_2D_EXT == tex_tgt ? GL_TEXTURE_2D: - GL_TEXTURE_RECTANGLE); - ptex->width = width; - ptex->height = height; - ptex->y_inverted = fbcfg->y_inverted; - } - if (!ptex->glpixmap) { - log_error("Failed to allocate GLX pixmap."); - return false; - } + ptex->glpixmap = glXCreatePixmap(ps->dpy, fbcfg->cfg, pixmap, attrs); + ptex->pixmap = pixmap; + ptex->target = + (GLX_TEXTURE_2D_EXT == tex_tgt ? GL_TEXTURE_2D : GL_TEXTURE_RECTANGLE); + ptex->width = width; + ptex->height = height; + ptex->y_inverted = fbcfg->y_inverted; + } + if (!ptex->glpixmap) { + log_error("Failed to allocate GLX pixmap."); + return false; + } - glEnable(ptex->target); + glEnable(ptex->target); - // Create texture - if (!ptex->texture) { - need_release = false; + // Create texture + if (!ptex->texture) { + need_release = false; - GLuint texture = 0; - glGenTextures(1, &texture); - glBindTexture(ptex->target, texture); + GLuint texture = 0; + glGenTextures(1, &texture); + glBindTexture(ptex->target, texture); - glTexParameteri(ptex->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(ptex->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - if (repeat) { - glTexParameteri(ptex->target, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(ptex->target, GL_TEXTURE_WRAP_T, GL_REPEAT); - } else { - glTexParameteri(ptex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(ptex->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } + glTexParameteri(ptex->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(ptex->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + if (repeat) { + glTexParameteri(ptex->target, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(ptex->target, GL_TEXTURE_WRAP_T, GL_REPEAT); + } else { + glTexParameteri(ptex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(ptex->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } - glBindTexture(ptex->target, 0); + glBindTexture(ptex->target, 0); - ptex->texture = texture; - } - if (!ptex->texture) { - log_error("Failed to allocate texture."); - return false; - } + ptex->texture = texture; + } + if (!ptex->texture) { + log_error("Failed to allocate texture."); + return false; + } - glBindTexture(ptex->target, ptex->texture); + glBindTexture(ptex->target, ptex->texture); - // The specification requires rebinding whenever the content changes... - // We can't follow this, too slow. - if (need_release) - glXReleaseTexImageEXT(ps->dpy, ptex->glpixmap, GLX_FRONT_LEFT_EXT); + // The specification requires rebinding whenever the content changes... + // We can't follow this, too slow. + if (need_release) + glXReleaseTexImageEXT(ps->dpy, ptex->glpixmap, GLX_FRONT_LEFT_EXT); - glXBindTexImageEXT(ps->dpy, ptex->glpixmap, GLX_FRONT_LEFT_EXT, NULL); + glXBindTexImageEXT(ps->dpy, ptex->glpixmap, GLX_FRONT_LEFT_EXT, NULL); - // Cleanup - glBindTexture(ptex->target, 0); - glDisable(ptex->target); + // Cleanup + glBindTexture(ptex->target, 0); + glDisable(ptex->target); - gl_check_err(); + gl_check_err(); - return true; + return true; } /** * @brief Release binding of a texture. */ -void -glx_release_pixmap(session_t *ps, glx_texture_t *ptex) { - // Release binding - if (ptex->glpixmap && ptex->texture) { - glBindTexture(ptex->target, ptex->texture); - glXReleaseTexImageEXT(ps->dpy, ptex->glpixmap, GLX_FRONT_LEFT_EXT); - glBindTexture(ptex->target, 0); - } +void glx_release_pixmap(session_t *ps, glx_texture_t *ptex) { + // Release binding + if (ptex->glpixmap && ptex->texture) { + glBindTexture(ptex->target, ptex->texture); + glXReleaseTexImageEXT(ps->dpy, ptex->glpixmap, GLX_FRONT_LEFT_EXT); + glBindTexture(ptex->target, 0); + } - // Free GLX Pixmap - if (ptex->glpixmap) { - glXDestroyPixmap(ps->dpy, ptex->glpixmap); - ptex->glpixmap = 0; - } + // Free GLX Pixmap + if (ptex->glpixmap) { + glXDestroyPixmap(ps->dpy, ptex->glpixmap); + ptex->glpixmap = 0; + } - gl_check_err(); + gl_check_err(); } /** * Set clipping region on the target window. */ -void -glx_set_clip(session_t *ps, const region_t *reg) { - // Quit if we aren't using stencils - if (ps->o.glx_no_stencil) - return; +void glx_set_clip(session_t *ps, const region_t *reg) { + // Quit if we aren't using stencils + if (ps->o.glx_no_stencil) + return; - glDisable(GL_STENCIL_TEST); - glDisable(GL_SCISSOR_TEST); + glDisable(GL_STENCIL_TEST); + glDisable(GL_SCISSOR_TEST); - if (!reg) - return; + if (!reg) + return; - int nrects; - const rect_t *rects = pixman_region32_rectangles((region_t *)reg, &nrects); + int nrects; + const rect_t *rects = pixman_region32_rectangles((region_t *)reg, &nrects); - if (nrects == 1) { - glEnable(GL_SCISSOR_TEST); - glScissor(rects[0].x1, ps->root_height-rects[0].y2, - rects[0].x2-rects[0].x1, rects[0].y2-rects[0].y1); - } + if (nrects == 1) { + glEnable(GL_SCISSOR_TEST); + glScissor(rects[0].x1, ps->root_height - rects[0].y2, + rects[0].x2 - rects[0].x1, rects[0].y2 - rects[0].y1); + } - gl_check_err(); + gl_check_err(); } -#define P_PAINTREG_START(var) \ - region_t reg_new; \ - int nrects; \ - const rect_t *rects; \ - pixman_region32_init_rect(®_new, dx, dy, width, height); \ - pixman_region32_intersect(®_new, ®_new, (region_t *)reg_tgt); \ - rects = pixman_region32_rectangles(®_new, &nrects); \ - glBegin(GL_QUADS); \ - \ - for (int ri = 0; ri < nrects; ++ri) { \ - rect_t var = rects[ri]; +#define P_PAINTREG_START(var) \ + region_t reg_new; \ + int nrects; \ + const rect_t *rects; \ + pixman_region32_init_rect(®_new, dx, dy, width, height); \ + pixman_region32_intersect(®_new, ®_new, (region_t *)reg_tgt); \ + rects = pixman_region32_rectangles(®_new, &nrects); \ + glBegin(GL_QUADS); \ + \ + for (int ri = 0; ri < nrects; ++ri) { \ + rect_t var = rects[ri]; -#define P_PAINTREG_END() \ - } \ - glEnd(); \ - \ - pixman_region32_fini(®_new); +#define P_PAINTREG_END() \ + } \ + glEnd(); \ + \ + pixman_region32_fini(®_new); -static inline GLuint -glx_gen_texture(session_t *ps, GLenum tex_tgt, int width, int height) { - GLuint tex = 0; - glGenTextures(1, &tex); - if (!tex) return 0; - glEnable(tex_tgt); - glBindTexture(tex_tgt, tex); - glTexParameteri(tex_tgt, GL_TEXTURE_MIN_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_T, GL_CLAMP_TO_EDGE); - glTexImage2D(tex_tgt, 0, GL_RGB, width, height, 0, GL_RGB, - GL_UNSIGNED_BYTE, NULL); - glBindTexture(tex_tgt, 0); +static inline GLuint glx_gen_texture(session_t *ps, GLenum tex_tgt, int width, int height) { + GLuint tex = 0; + glGenTextures(1, &tex); + if (!tex) + return 0; + glEnable(tex_tgt); + glBindTexture(tex_tgt, tex); + glTexParameteri(tex_tgt, GL_TEXTURE_MIN_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_T, GL_CLAMP_TO_EDGE); + glTexImage2D(tex_tgt, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + glBindTexture(tex_tgt, 0); - return tex; + return tex; } -static inline void -glx_copy_region_to_tex(session_t *ps, GLenum tex_tgt, int basex, int basey, - int dx, int dy, int width, int height) { - if (width > 0 && height > 0) - glCopyTexSubImage2D(tex_tgt, 0, dx - basex, dy - basey, - dx, ps->root_height - dy - height, width, height); +static inline void glx_copy_region_to_tex(session_t *ps, GLenum tex_tgt, int basex, + int basey, int dx, int dy, int width, int height) { + if (width > 0 && height > 0) + glCopyTexSubImage2D(tex_tgt, 0, dx - basex, dy - basey, dx, + ps->root_height - dy - height, width, height); } /** @@ -691,447 +684,442 @@ 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 */ -bool -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) { - assert(ps->psglx->blur_passes[0].prog); - const bool more_passes = ps->psglx->blur_passes[1].prog; - const bool have_scissors = glIsEnabled(GL_SCISSOR_TEST); - const bool have_stencil = glIsEnabled(GL_STENCIL_TEST); - bool ret = false; +bool 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) { + assert(ps->psglx->blur_passes[0].prog); + const bool more_passes = ps->psglx->blur_passes[1].prog; + const bool have_scissors = glIsEnabled(GL_SCISSOR_TEST); + const bool have_stencil = glIsEnabled(GL_STENCIL_TEST); + bool ret = false; - // Calculate copy region size - glx_blur_cache_t ibc = { .width = 0, .height = 0 }; - if (!pbc) - pbc = &ibc; + // Calculate copy region size + glx_blur_cache_t ibc = {.width = 0, .height = 0}; + if (!pbc) + pbc = &ibc; - int mdx = dx, mdy = dy, mwidth = width, mheight = height; - //log_trace("%d, %d, %d, %d", mdx, mdy, mwidth, mheight); + int mdx = dx, mdy = dy, mwidth = width, mheight = height; + // log_trace("%d, %d, %d, %d", mdx, mdy, mwidth, mheight); - /* - if (ps->o.resize_damage > 0) { - int inc_x = 0, inc_y = 0; - for (int i = 0; i < MAX_BLUR_PASS; ++i) { - XFixed *kern = ps->o.blur_kerns[i]; - if (!kern) break; - inc_x += XFIXED_TO_DOUBLE(kern[0]) / 2; - inc_y += XFIXED_TO_DOUBLE(kern[1]) / 2; - } - inc_x = min_i(ps->o.resize_damage, inc_x); - inc_y = min_i(ps->o.resize_damage, inc_y); + /* + if (ps->o.resize_damage > 0) { + int inc_x = 0, inc_y = 0; + for (int i = 0; i < MAX_BLUR_PASS; ++i) { + XFixed *kern = ps->o.blur_kerns[i]; + if (!kern) break; + inc_x += XFIXED_TO_DOUBLE(kern[0]) / 2; + inc_y += XFIXED_TO_DOUBLE(kern[1]) / 2; + } + inc_x = min_i(ps->o.resize_damage, inc_x); + inc_y = min_i(ps->o.resize_damage, inc_y); - mdx = max_i(dx - inc_x, 0); - mdy = max_i(dy - inc_y, 0); - int mdx2 = min_i(dx + width + inc_x, ps->root_width), - mdy2 = min_i(dy + height + inc_y, ps->root_height); - mwidth = mdx2 - mdx; - mheight = mdy2 - mdy; - } - */ + mdx = max_i(dx - inc_x, 0); + mdy = max_i(dy - inc_y, 0); + int mdx2 = min_i(dx + width + inc_x, ps->root_width), + mdy2 = min_i(dy + height + inc_y, ps->root_height); + mwidth = mdx2 - mdx; + mheight = mdy2 - mdy; + } + */ - GLenum tex_tgt = GL_TEXTURE_RECTANGLE; - if (ps->psglx->has_texture_non_power_of_two) - tex_tgt = GL_TEXTURE_2D; + GLenum tex_tgt = GL_TEXTURE_RECTANGLE; + if (ps->psglx->has_texture_non_power_of_two) + tex_tgt = GL_TEXTURE_2D; - // Free textures if size inconsistency discovered - if (mwidth != pbc->width || mheight != pbc->height) - free_glx_bc_resize(ps, pbc); + // Free textures if size inconsistency discovered + if (mwidth != pbc->width || mheight != pbc->height) + free_glx_bc_resize(ps, pbc); - // Generate FBO and textures if needed - if (!pbc->textures[0]) - pbc->textures[0] = glx_gen_texture(ps, tex_tgt, mwidth, mheight); - GLuint tex_scr = pbc->textures[0]; - if (more_passes && !pbc->textures[1]) - pbc->textures[1] = glx_gen_texture(ps, tex_tgt, mwidth, mheight); - pbc->width = mwidth; - pbc->height = mheight; - GLuint tex_scr2 = pbc->textures[1]; - if (more_passes && !pbc->fbo) - glGenFramebuffers(1, &pbc->fbo); - const GLuint fbo = pbc->fbo; + // Generate FBO and textures if needed + if (!pbc->textures[0]) + pbc->textures[0] = glx_gen_texture(ps, tex_tgt, mwidth, mheight); + GLuint tex_scr = pbc->textures[0]; + if (more_passes && !pbc->textures[1]) + pbc->textures[1] = glx_gen_texture(ps, tex_tgt, mwidth, mheight); + pbc->width = mwidth; + pbc->height = mheight; + GLuint tex_scr2 = pbc->textures[1]; + if (more_passes && !pbc->fbo) + glGenFramebuffers(1, &pbc->fbo); + const GLuint fbo = pbc->fbo; - if (!tex_scr || (more_passes && !tex_scr2)) { - log_error("Failed to allocate texture."); - goto glx_blur_dst_end; - } - if (more_passes && !fbo) { - log_error("Failed to allocate framebuffer."); - goto glx_blur_dst_end; - } + if (!tex_scr || (more_passes && !tex_scr2)) { + log_error("Failed to allocate texture."); + goto glx_blur_dst_end; + } + if (more_passes && !fbo) { + log_error("Failed to allocate framebuffer."); + goto glx_blur_dst_end; + } - // Read destination pixels into a texture - glEnable(tex_tgt); - glBindTexture(tex_tgt, tex_scr); - glx_copy_region_to_tex(ps, tex_tgt, mdx, mdy, mdx, mdy, mwidth, mheight); - /* - if (tex_scr2) { - glBindTexture(tex_tgt, tex_scr2); - glx_copy_region_to_tex(ps, tex_tgt, mdx, mdy, mdx, mdy, mwidth, dx - mdx); - glx_copy_region_to_tex(ps, tex_tgt, mdx, mdy, mdx, dy + height, - mwidth, mdy + mheight - dy - height); - glx_copy_region_to_tex(ps, tex_tgt, mdx, mdy, mdx, dy, dx - mdx, height); - glx_copy_region_to_tex(ps, tex_tgt, mdx, mdy, dx + width, dy, - mdx + mwidth - dx - width, height); - } */ + // Read destination pixels into a texture + glEnable(tex_tgt); + glBindTexture(tex_tgt, tex_scr); + glx_copy_region_to_tex(ps, tex_tgt, mdx, mdy, mdx, mdy, mwidth, mheight); + /* + if (tex_scr2) { + glBindTexture(tex_tgt, tex_scr2); + glx_copy_region_to_tex(ps, tex_tgt, mdx, mdy, mdx, mdy, mwidth, dx - mdx); + glx_copy_region_to_tex(ps, tex_tgt, mdx, mdy, mdx, dy + height, + mwidth, mdy + mheight - dy - height); + glx_copy_region_to_tex(ps, tex_tgt, mdx, mdy, mdx, dy, dx - mdx, height); + glx_copy_region_to_tex(ps, tex_tgt, mdx, mdy, dx + width, dy, + mdx + mwidth - dx - width, height); + } */ - // Texture scaling factor - GLfloat texfac_x = 1.0f, texfac_y = 1.0f; - if (GL_TEXTURE_2D == tex_tgt) { - texfac_x /= mwidth; - texfac_y /= mheight; - } + // Texture scaling factor + GLfloat texfac_x = 1.0f, texfac_y = 1.0f; + if (GL_TEXTURE_2D == tex_tgt) { + texfac_x /= mwidth; + texfac_y /= mheight; + } - // Paint it back - if (more_passes) { - glDisable(GL_STENCIL_TEST); - glDisable(GL_SCISSOR_TEST); - } + // Paint it back + if (more_passes) { + glDisable(GL_STENCIL_TEST); + glDisable(GL_SCISSOR_TEST); + } - bool last_pass = false; - for (int i = 0; !last_pass; ++i) { - last_pass = !ps->psglx->blur_passes[i + 1].prog; - assert(i < MAX_BLUR_PASS - 1); - const glx_blur_pass_t *ppass = &ps->psglx->blur_passes[i]; - assert(ppass->prog); + bool last_pass = false; + for (int i = 0; !last_pass; ++i) { + last_pass = !ps->psglx->blur_passes[i + 1].prog; + assert(i < MAX_BLUR_PASS - 1); + const glx_blur_pass_t *ppass = &ps->psglx->blur_passes[i]; + assert(ppass->prog); - assert(tex_scr); - glBindTexture(tex_tgt, tex_scr); + assert(tex_scr); + glBindTexture(tex_tgt, tex_scr); - if (!last_pass) { - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, tex_scr2, 0); - glDrawBuffer(GL_COLOR_ATTACHMENT0); - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) - != GL_FRAMEBUFFER_COMPLETE) { - log_error("Framebuffer attachment failed."); - goto glx_blur_dst_end; - } - } - else { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glDrawBuffer(GL_BACK); - if (have_scissors) - glEnable(GL_SCISSOR_TEST); - if (have_stencil) - glEnable(GL_STENCIL_TEST); - } + if (!last_pass) { + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, tex_scr2, 0); + glDrawBuffer(GL_COLOR_ATTACHMENT0); + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + log_error("Framebuffer attachment failed."); + goto glx_blur_dst_end; + } + } else { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glDrawBuffer(GL_BACK); + if (have_scissors) + glEnable(GL_SCISSOR_TEST); + if (have_stencil) + glEnable(GL_STENCIL_TEST); + } - // Color negation for testing... - // glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - // glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE); - // glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_ONE_MINUS_SRC_COLOR); + // Color negation for testing... + // glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + // glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE); + // glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_ONE_MINUS_SRC_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glUseProgram(ppass->prog); - if (ppass->unifm_offset_x >= 0) - glUniform1f(ppass->unifm_offset_x, texfac_x); - if (ppass->unifm_offset_y >= 0) - glUniform1f(ppass->unifm_offset_y, texfac_y); - if (ppass->unifm_factor_center >= 0) - glUniform1f(ppass->unifm_factor_center, factor_center); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glUseProgram(ppass->prog); + if (ppass->unifm_offset_x >= 0) + glUniform1f(ppass->unifm_offset_x, texfac_x); + if (ppass->unifm_offset_y >= 0) + glUniform1f(ppass->unifm_offset_y, texfac_y); + if (ppass->unifm_factor_center >= 0) + glUniform1f(ppass->unifm_factor_center, factor_center); - { - P_PAINTREG_START(crect) { - const GLfloat rx = (crect.x1 - mdx) * texfac_x; - const GLfloat ry = (mheight - (crect.y1 - mdy)) * texfac_y; - const GLfloat rxe = rx + (crect.x2 - crect.x1) * texfac_x; - const GLfloat rye = ry - (crect.y2 - crect.y1) * texfac_y; - GLfloat rdx = crect.x1 - mdx; - GLfloat rdy = mheight - crect.y1 + mdy; - if (last_pass) { - rdx = crect.x1; - rdy = ps->root_height - crect.y1; - } - GLfloat rdxe = rdx + (crect.x2 - crect.x1); - GLfloat rdye = rdy - (crect.y2 - crect.y1); + { + P_PAINTREG_START(crect) { + const GLfloat rx = (crect.x1 - mdx) * texfac_x; + const GLfloat ry = (mheight - (crect.y1 - mdy)) * texfac_y; + const GLfloat rxe = rx + (crect.x2 - crect.x1) * texfac_x; + const GLfloat rye = ry - (crect.y2 - crect.y1) * texfac_y; + GLfloat rdx = crect.x1 - mdx; + GLfloat rdy = mheight - crect.y1 + mdy; + if (last_pass) { + rdx = crect.x1; + rdy = ps->root_height - crect.y1; + } + GLfloat rdxe = rdx + (crect.x2 - crect.x1); + GLfloat rdye = rdy - (crect.y2 - crect.y1); - //log_trace("%f, %f, %f, %f -> %f, %f, %f, %f", rx, ry, rxe, rye, rdx, - // rdy, rdxe, rdye); + // log_trace("%f, %f, %f, %f -> %f, %f, %f, %f", rx, ry, + // rxe, rye, rdx, + // rdy, rdxe, rdye); - glTexCoord2f(rx, ry); - glVertex3f(rdx, rdy, z); + glTexCoord2f(rx, ry); + glVertex3f(rdx, rdy, z); - glTexCoord2f(rxe, ry); - glVertex3f(rdxe, rdy, z); + glTexCoord2f(rxe, ry); + glVertex3f(rdxe, rdy, z); - glTexCoord2f(rxe, rye); - glVertex3f(rdxe, rdye, z); + glTexCoord2f(rxe, rye); + glVertex3f(rdxe, rdye, z); - glTexCoord2f(rx, rye); - glVertex3f(rdx, rdye, z); - } P_PAINTREG_END(); - } + glTexCoord2f(rx, rye); + glVertex3f(rdx, rdye, z); + } + P_PAINTREG_END(); + } - glUseProgram(0); + glUseProgram(0); - // Swap tex_scr and tex_scr2 - { - GLuint tmp = tex_scr2; - tex_scr2 = tex_scr; - tex_scr = tmp; - } - } + // Swap tex_scr and tex_scr2 + { + GLuint tmp = tex_scr2; + tex_scr2 = tex_scr; + tex_scr = tmp; + } + } - ret = true; + ret = true; glx_blur_dst_end: - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glBindTexture(tex_tgt, 0); - glDisable(tex_tgt); - if (have_scissors) - glEnable(GL_SCISSOR_TEST); - if (have_stencil) - glEnable(GL_STENCIL_TEST); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindTexture(tex_tgt, 0); + glDisable(tex_tgt); + if (have_scissors) + glEnable(GL_SCISSOR_TEST); + if (have_stencil) + glEnable(GL_STENCIL_TEST); - if (&ibc == pbc) { - free_glx_bc(ps, pbc); - } + if (&ibc == pbc) { + free_glx_bc(ps, pbc); + } - gl_check_err(); + gl_check_err(); - return ret; + return ret; } -bool -glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z, - GLfloat factor, const region_t *reg_tgt) { - // It's possible to dim in glx_render(), but it would be over-complicated - // considering all those mess in color negation and modulation - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glColor4f(0.0f, 0.0f, 0.0f, factor); +bool glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z, + GLfloat factor, const region_t *reg_tgt) { + // It's possible to dim in glx_render(), but it would be over-complicated + // considering all those mess in color negation and modulation + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glColor4f(0.0f, 0.0f, 0.0f, factor); - { - P_PAINTREG_START(crect) { - // XXX what does all of these variables mean? - GLint rdx = crect.x1; - GLint rdy = ps->root_height - crect.y1; - GLint rdxe = rdx + (crect.x2 - crect.x1); - GLint rdye = rdy - (crect.y2 - crect.y1); + { + P_PAINTREG_START(crect) { + // XXX what does all of these variables mean? + GLint rdx = crect.x1; + GLint rdy = ps->root_height - crect.y1; + GLint rdxe = rdx + (crect.x2 - crect.x1); + GLint rdye = rdy - (crect.y2 - crect.y1); - glVertex3i(rdx, rdy, z); - glVertex3i(rdxe, rdy, z); - glVertex3i(rdxe, rdye, z); - glVertex3i(rdx, rdye, z); - } - P_PAINTREG_END(); - } + glVertex3i(rdx, rdy, z); + glVertex3i(rdxe, rdy, z); + glVertex3i(rdxe, rdye, z); + glVertex3i(rdx, rdye, z); + } + P_PAINTREG_END(); + } - glColor4f(0.0f, 0.0f, 0.0f, 0.0f); - glDisable(GL_BLEND); + glColor4f(0.0f, 0.0f, 0.0f, 0.0f); + glDisable(GL_BLEND); - gl_check_err(); + gl_check_err(); - return true; + return true; } /** * @brief Render a region with texture data. */ -bool -glx_render(session_t *ps, const glx_texture_t *ptex, - int x, int y, int dx, int dy, int width, int height, int z, - double opacity, bool argb, bool neg, - const region_t *reg_tgt, const glx_prog_main_t *pprogram - ) { - if (!ptex || !ptex->texture) { - log_error("Missing texture."); - return false; - } +bool glx_render(session_t *ps, const glx_texture_t *ptex, int x, int y, int dx, int dy, + int width, int height, int z, double opacity, bool argb, bool neg, + const region_t *reg_tgt, const glx_prog_main_t *pprogram) { + if (!ptex || !ptex->texture) { + log_error("Missing texture."); + return false; + } - const bool has_prog = pprogram && pprogram->prog; - bool dual_texture = false; + const bool has_prog = pprogram && pprogram->prog; + bool dual_texture = false; - // It's required by legacy versions of OpenGL to enable texture target - // before specifying environment. Thanks to madsy for telling me. - glEnable(ptex->target); + // It's required by legacy versions of OpenGL to enable texture target + // before specifying environment. Thanks to madsy for telling me. + glEnable(ptex->target); - // Enable blending if needed - if (opacity < 1.0 || argb) { + // Enable blending if needed + if (opacity < 1.0 || argb) { - glEnable(GL_BLEND); + glEnable(GL_BLEND); - // Needed for handling opacity of ARGB texture - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + // Needed for handling opacity of ARGB texture + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - // This is all weird, but X Render is using premultiplied ARGB format, and - // we need to use those things to correct it. Thanks to derhass for help. - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glColor4f(opacity, opacity, opacity, opacity); - } + // This is all weird, but X Render is using premultiplied ARGB format, and + // we need to use those things to correct it. Thanks to derhass for help. + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glColor4f(opacity, opacity, opacity, opacity); + } - if (!has_prog) - { - // The default, fixed-function path - // Color negation - if (neg) { - // Simple color negation - if (!glIsEnabled(GL_BLEND)) { - glEnable(GL_COLOR_LOGIC_OP); - glLogicOp(GL_COPY_INVERTED); - } - // ARGB texture color negation - else if (argb) { - dual_texture = true; + if (!has_prog) { + // The default, fixed-function path + // Color negation + if (neg) { + // Simple color negation + if (!glIsEnabled(GL_BLEND)) { + glEnable(GL_COLOR_LOGIC_OP); + glLogicOp(GL_COPY_INVERTED); + } + // ARGB texture color negation + else if (argb) { + dual_texture = true; - // Use two texture stages because the calculation is too complicated, - // thanks to madsy for providing code - // Texture stage 0 - glActiveTexture(GL_TEXTURE0); + // Use two texture stages because the calculation is too + // complicated, thanks to madsy for providing code Texture + // stage 0 + glActiveTexture(GL_TEXTURE0); - // Negation for premultiplied color: color = A - C - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_SUBTRACT); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_ALPHA); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); + // Negation for premultiplied color: color = A - C + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_SUBTRACT); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_ALPHA); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); - // Pass texture alpha through - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); + // Pass texture alpha through + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); - // Texture stage 1 - glActiveTexture(GL_TEXTURE1); - glEnable(ptex->target); - glBindTexture(ptex->target, ptex->texture); + // Texture stage 1 + glActiveTexture(GL_TEXTURE1); + glEnable(ptex->target); + glBindTexture(ptex->target, ptex->texture); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - // Modulation with constant factor - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_ALPHA); + // Modulation with constant factor + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_ALPHA); - // Modulation with constant factor - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PRIMARY_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); + // Modulation with constant factor + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PRIMARY_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); - glActiveTexture(GL_TEXTURE0); - } - // RGB blend color negation - else { - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + glActiveTexture(GL_TEXTURE0); + } + // RGB blend color negation + else { + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - // Modulation with constant factor - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); - 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_SOURCE1_RGB, GL_PRIMARY_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); + // Modulation with constant factor + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); + 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_SOURCE1_RGB, GL_PRIMARY_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); - // Modulation with constant factor - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PRIMARY_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); - } - } - } - else { - // Programmable path - assert(pprogram->prog); - glUseProgram(pprogram->prog); - if (pprogram->unifm_opacity >= 0) - glUniform1f(pprogram->unifm_opacity, opacity); - if (pprogram->unifm_invert_color >= 0) - glUniform1i(pprogram->unifm_invert_color, neg); - if (pprogram->unifm_tex >= 0) - glUniform1i(pprogram->unifm_tex, 0); - } + // Modulation with constant factor + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PRIMARY_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); + } + } + } else { + // Programmable path + assert(pprogram->prog); + glUseProgram(pprogram->prog); + if (pprogram->unifm_opacity >= 0) + glUniform1f(pprogram->unifm_opacity, opacity); + if (pprogram->unifm_invert_color >= 0) + glUniform1i(pprogram->unifm_invert_color, neg); + if (pprogram->unifm_tex >= 0) + glUniform1i(pprogram->unifm_tex, 0); + } - //log_trace("Draw: %d, %d, %d, %d -> %d, %d (%d, %d) z %d", x, y, width, height, - // dx, dy, ptex->width, ptex->height, z); + // log_trace("Draw: %d, %d, %d, %d -> %d, %d (%d, %d) z %d", x, y, width, height, + // dx, dy, ptex->width, ptex->height, z); - // Bind texture - glBindTexture(ptex->target, ptex->texture); - if (dual_texture) { - glActiveTexture(GL_TEXTURE1); - glBindTexture(ptex->target, ptex->texture); - glActiveTexture(GL_TEXTURE0); - } + // Bind texture + glBindTexture(ptex->target, ptex->texture); + if (dual_texture) { + glActiveTexture(GL_TEXTURE1); + glBindTexture(ptex->target, ptex->texture); + glActiveTexture(GL_TEXTURE0); + } - // Painting - { - P_PAINTREG_START(crect) { - // XXX explain these variables - GLfloat rx = (double) (crect.x1 - dx + x); - GLfloat ry = (double) (crect.y1 - dy + y); - GLfloat rxe = rx + (double) (crect.x2 - crect.x1); - GLfloat rye = ry + (double) (crect.y2 - crect.y1); - // Rectangle textures have [0-w] [0-h] while 2D texture has [0-1] [0-1] - // Thanks to amonakov for pointing out! - if (GL_TEXTURE_2D == ptex->target) { - rx = rx / ptex->width; - ry = ry / ptex->height; - rxe = rxe / ptex->width; - rye = rye / ptex->height; - } - GLint rdx = crect.x1; - GLint rdy = ps->root_height - crect.y1; - GLint rdxe = rdx + (crect.x2 - crect.x1); - GLint rdye = rdy - (crect.y2 - crect.y1); + // Painting + { + P_PAINTREG_START(crect) { + // XXX explain these variables + GLfloat rx = (double)(crect.x1 - dx + x); + GLfloat ry = (double)(crect.y1 - dy + y); + GLfloat rxe = rx + (double)(crect.x2 - crect.x1); + GLfloat rye = ry + (double)(crect.y2 - crect.y1); + // Rectangle textures have [0-w] [0-h] while 2D texture has [0-1] + // [0-1] Thanks to amonakov for pointing out! + if (GL_TEXTURE_2D == ptex->target) { + rx = rx / ptex->width; + ry = ry / ptex->height; + rxe = rxe / ptex->width; + rye = rye / ptex->height; + } + GLint rdx = crect.x1; + GLint rdy = ps->root_height - crect.y1; + GLint rdxe = rdx + (crect.x2 - crect.x1); + GLint rdye = rdy - (crect.y2 - crect.y1); - // Invert Y if needed, this may not work as expected, though. I don't - // have such a FBConfig to test with. - if (!ptex->y_inverted) { - ry = 1.0 - ry; - rye = 1.0 - rye; - } + // Invert Y if needed, this may not work as expected, though. I + // don't have such a FBConfig to test with. + if (!ptex->y_inverted) { + ry = 1.0 - ry; + rye = 1.0 - rye; + } - //log_trace("Rect %d: %f, %f, %f, %f -> %d, %d, %d, %d", ri, rx, ry, rxe, rye, - // rdx, rdy, rdxe, rdye); + // log_trace("Rect %d: %f, %f, %f, %f -> %d, %d, %d, %d", ri, rx, + // ry, rxe, rye, + // rdx, rdy, rdxe, rdye); -#define P_TEXCOORD(cx, cy) { \ - if (dual_texture) { \ - glMultiTexCoord2f(GL_TEXTURE0, cx, cy); \ - glMultiTexCoord2f(GL_TEXTURE1, cx, cy); \ - } \ - else glTexCoord2f(cx, cy); \ -} - P_TEXCOORD(rx, ry); - glVertex3i(rdx, rdy, z); - - P_TEXCOORD(rxe, ry); - glVertex3i(rdxe, rdy, z); - - P_TEXCOORD(rxe, rye); - glVertex3i(rdxe, rdye, z); - - P_TEXCOORD(rx, rye); - glVertex3i(rdx, rdye, z); - } P_PAINTREG_END(); - } - - // Cleanup - glBindTexture(ptex->target, 0); - glColor4f(0.0f, 0.0f, 0.0f, 0.0f); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glDisable(GL_BLEND); - glDisable(GL_COLOR_LOGIC_OP); - glDisable(ptex->target); - - if (dual_texture) { - glActiveTexture(GL_TEXTURE1); - glBindTexture(ptex->target, 0); - glDisable(ptex->target); - glActiveTexture(GL_TEXTURE0); - } - - if (has_prog) - glUseProgram(0); - - gl_check_err(); - - return true; +#define P_TEXCOORD(cx, cy) \ + { \ + if (dual_texture) { \ + glMultiTexCoord2f(GL_TEXTURE0, cx, cy); \ + glMultiTexCoord2f(GL_TEXTURE1, cx, cy); \ + } else \ + glTexCoord2f(cx, cy); \ + } + P_TEXCOORD(rx, ry); + glVertex3i(rdx, rdy, z); + + P_TEXCOORD(rxe, ry); + glVertex3i(rdxe, rdy, z); + + P_TEXCOORD(rxe, rye); + glVertex3i(rdxe, rdye, z); + + P_TEXCOORD(rx, rye); + glVertex3i(rdx, rdye, z); + } + P_PAINTREG_END(); + } + + // Cleanup + glBindTexture(ptex->target, 0); + glColor4f(0.0f, 0.0f, 0.0f, 0.0f); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glDisable(GL_BLEND); + glDisable(GL_COLOR_LOGIC_OP); + glDisable(ptex->target); + + if (dual_texture) { + glActiveTexture(GL_TEXTURE1); + glBindTexture(ptex->target, 0); + glDisable(ptex->target); + glActiveTexture(GL_TEXTURE0); + } + + if (has_prog) + glUseProgram(0); + + gl_check_err(); + + return true; } diff --git a/src/opengl.h b/src/opengl.h index 2fe075e..d01294c 100644 --- a/src/opengl.h +++ b/src/opengl.h @@ -12,193 +12,160 @@ #pragma once #include "common.h" +#include "compiler.h" +#include "log.h" #include "region.h" #include "render.h" -#include "compiler.h" #include "win.h" -#include "log.h" -#include -#include -#include -#include +#include #include #include -#include +#include +#include +#include +#include -bool -glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z, - GLfloat factor, const region_t *reg_tgt); +bool glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z, + GLfloat factor, const region_t *reg_tgt); -bool -glx_render(session_t *ps, const glx_texture_t *ptex, - int x, int y, int dx, int dy, int width, int height, int z, - double opacity, bool argb, bool neg, - const region_t *reg_tgt, - const glx_prog_main_t *pprogram); +bool glx_render(session_t *ps, const glx_texture_t *ptex, int x, int y, int dx, int dy, + int width, int height, int z, double opacity, bool argb, bool neg, + const region_t *reg_tgt, const glx_prog_main_t *pprogram); -bool -glx_init(session_t *ps, bool need_render); +bool glx_init(session_t *ps, bool need_render); -void -glx_destroy(session_t *ps); +void glx_destroy(session_t *ps); -void -glx_on_root_change(session_t *ps); +void glx_on_root_change(session_t *ps); -bool -glx_init_blur(session_t *ps); +bool glx_init_blur(session_t *ps); #ifdef CONFIG_OPENGL -bool -glx_load_prog_main(session_t *ps, - const char *vshader_str, const char *fshader_str, - glx_prog_main_t *pprogram); +bool glx_load_prog_main(session_t *ps, const char *vshader_str, const char *fshader_str, + glx_prog_main_t *pprogram); #endif -bool -glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap, - unsigned width, unsigned height, bool repeat, const struct glx_fbconfig_info *); +bool glx_bind_pixmap(session_t *ps, glx_texture_t **pptex, xcb_pixmap_t pixmap, unsigned width, + unsigned height, bool repeat, const struct glx_fbconfig_info *); -void -glx_release_pixmap(session_t *ps, glx_texture_t *ptex); +void glx_release_pixmap(session_t *ps, glx_texture_t *ptex); -void glx_paint_pre(session_t *ps, region_t *preg) -attr_nonnull(1, 2); +void glx_paint_pre(session_t *ps, region_t *preg) attr_nonnull(1, 2); /** * Check if a texture is binded, or is binded to the given pixmap. */ -static inline bool -glx_tex_binded(const glx_texture_t *ptex, xcb_pixmap_t pixmap) { - return ptex && ptex->glpixmap && ptex->texture - && (!pixmap || pixmap == ptex->pixmap); +static inline bool glx_tex_binded(const glx_texture_t *ptex, xcb_pixmap_t pixmap) { + return ptex && ptex->glpixmap && ptex->texture && (!pixmap || pixmap == ptex->pixmap); } -void -glx_set_clip(session_t *ps, const region_t *reg); +void glx_set_clip(session_t *ps, const region_t *reg); -bool -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); +bool 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); -GLuint -glx_create_shader(GLenum shader_type, const char *shader_str); +GLuint glx_create_shader(GLenum shader_type, const char *shader_str); -GLuint -glx_create_program(const GLuint * const shaders, int nshaders); +GLuint glx_create_program(const GLuint *const shaders, int nshaders); -GLuint -glx_create_program_from_str(const char *vert_shader_str, - const char *frag_shader_str); +GLuint glx_create_program_from_str(const char *vert_shader_str, const char *frag_shader_str); -unsigned char * -glx_take_screenshot(session_t *ps, int *out_length); +unsigned char *glx_take_screenshot(session_t *ps, int *out_length); /** * Check if there's a GLX context. */ -static inline bool -glx_has_context(session_t *ps) { - return ps->psglx && ps->psglx->context; +static inline bool glx_has_context(session_t *ps) { + return ps->psglx && ps->psglx->context; } /** * Ensure we have a GLX context. */ -static inline bool -ensure_glx_context(session_t *ps) { - // Create GLX context - if (!glx_has_context(ps)) - glx_init(ps, false); +static inline bool ensure_glx_context(session_t *ps) { + // Create GLX context + if (!glx_has_context(ps)) + glx_init(ps, false); - return ps->psglx->context; + return ps->psglx->context; } /** * Free a GLX texture. */ -static inline void -free_texture_r(session_t *ps, GLuint *ptexture) { - if (*ptexture) { - assert(glx_has_context(ps)); - glDeleteTextures(1, ptexture); - *ptexture = 0; - } +static inline void free_texture_r(session_t *ps, GLuint *ptexture) { + if (*ptexture) { + assert(glx_has_context(ps)); + glDeleteTextures(1, ptexture); + *ptexture = 0; + } } /** * Free a GLX Framebuffer object. */ -static inline void -free_glx_fbo(session_t *ps, GLuint *pfbo) { - if (*pfbo) { - glDeleteFramebuffers(1, pfbo); - *pfbo = 0; - } - assert(!*pfbo); +static inline void free_glx_fbo(session_t *ps, GLuint *pfbo) { + if (*pfbo) { + glDeleteFramebuffers(1, pfbo); + *pfbo = 0; + } + assert(!*pfbo); } /** * Free data in glx_blur_cache_t on resize. */ -static inline void -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[1]); - pbc->width = 0; - pbc->height = 0; +static inline void 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[1]); + pbc->width = 0; + pbc->height = 0; } /** * Free a glx_blur_cache_t */ -static inline void -free_glx_bc(session_t *ps, glx_blur_cache_t *pbc) { - free_glx_fbo(ps, &pbc->fbo); - free_glx_bc_resize(ps, pbc); +static inline void free_glx_bc(session_t *ps, glx_blur_cache_t *pbc) { + free_glx_fbo(ps, &pbc->fbo); + free_glx_bc_resize(ps, pbc); } /** * Free a glx_texture_t. */ -static inline void -free_texture(session_t *ps, glx_texture_t **pptex) { - glx_texture_t *ptex = *pptex; +static inline void free_texture(session_t *ps, glx_texture_t **pptex) { + glx_texture_t *ptex = *pptex; - // Quit if there's nothing - if (!ptex) - return; + // Quit if there's nothing + if (!ptex) + return; - glx_release_pixmap(ps, ptex); + glx_release_pixmap(ps, ptex); - free_texture_r(ps, &ptex->texture); + free_texture_r(ps, &ptex->texture); - // Free structure itself - free(ptex); - *pptex = NULL; - assert(!*pptex); + // Free structure itself + free(ptex); + *pptex = NULL; + assert(!*pptex); } /** * Free GLX part of paint_t. */ -static inline void -free_paint_glx(session_t *ps, paint_t *ppaint) { - free_texture(ps, &ppaint->ptex); +static inline void free_paint_glx(session_t *ps, paint_t *ppaint) { + free_texture(ps, &ppaint->ptex); } /** * Free GLX part of win. */ -static inline void -free_win_res_glx(session_t *ps, win *w) { - free_paint_glx(ps, &w->paint); - free_paint_glx(ps, &w->shadow_paint); +static inline void free_win_res_glx(session_t *ps, win *w) { + free_paint_glx(ps, &w->paint); + free_paint_glx(ps, &w->shadow_paint); #ifdef CONFIG_OPENGL - free_glx_bc(ps, &w->glx_blur_cache); - free(w->paint.fbcfg); + free_glx_bc(ps, &w->glx_blur_cache); + free(w->paint.fbcfg); #endif } diff --git a/src/string_utils.c b/src/string_utils.c index a19235f..38eb92d 100644 --- a/src/string_utils.c +++ b/src/string_utils.c @@ -55,31 +55,31 @@ void mstrextend(char **psrc1, const char *src2) { /// Parse a floating point number of form (+|-)?[0-9]*(\.[0-9]*) double strtod_simple(const char *src, const char **end) { - double neg = 1; - if (*src == '-') { - neg = -1; - src++; - } else if (*src == '+') { - src++; - } + double neg = 1; + if (*src == '-') { + neg = -1; + src++; + } else if (*src == '+') { + src++; + } - double ret = 0; - while (*src >= '0' && *src <= '9') { - ret = ret * 10 + (*src - '0'); - src++; - } + double ret = 0; + while (*src >= '0' && *src <= '9') { + ret = ret * 10 + (*src - '0'); + src++; + } - if (*src == '.') { - double frac = 0, mult = 0.1; - src++; - while (*src >= '0' && *src <= '9') { - frac += mult * (*src - '0'); - mult *= 0.1; - src++; - } - ret += frac; - } + if (*src == '.') { + double frac = 0, mult = 0.1; + src++; + while (*src >= '0' && *src <= '9') { + frac += mult * (*src - '0'); + mult *= 0.1; + src++; + } + ret += frac; + } - *end = src; - return ret * neg; + *end = src; + return ret * neg; } diff --git a/src/string_utils.h b/src/string_utils.h index 8581104..8f40bb1 100644 --- a/src/string_utils.h +++ b/src/string_utils.h @@ -7,51 +7,46 @@ #define mstrncmp(s1, s2) strncmp((s1), (s2), strlen(s1)) char *mstrjoin(const char *src1, const char *src2); -char * -mstrjoin3(const char *src1, const char *src2, const char *src3); +char *mstrjoin3(const char *src1, const char *src2, const char *src3); void mstrextend(char **psrc1, const char *src2); /// Parse a floating point number of form (+|-)?[0-9]*(\.[0-9]*) double strtod_simple(const char *, const char **); static inline int uitostr(unsigned int n, char *buf) { - int ret = 0; - unsigned int tmp = n; - while (tmp > 0) { - tmp /= 10; - ret++; - } + int ret = 0; + unsigned int tmp = n; + while (tmp > 0) { + tmp /= 10; + ret++; + } - if (ret == 0) - ret = 1; + if (ret == 0) + ret = 1; - int pos = ret; - while (pos--) { - buf[pos] = n%10 + '0'; - n /= 10; - } - return ret; + int pos = ret; + while (pos--) { + buf[pos] = n % 10 + '0'; + n /= 10; + } + return ret; } -static inline const char * -skip_space_const(const char *src) { - if (!src) - return NULL; - while (*src && isspace(*src)) - src++; - return src; +static inline const char *skip_space_const(const char *src) { + if (!src) + return NULL; + while (*src && isspace(*src)) + src++; + return src; } -static inline char * -skip_space_mut(char *src) { - if (!src) - return NULL; - while (*src && isspace(*src)) - src++; - return src; +static inline char *skip_space_mut(char *src) { + if (!src) + return NULL; + while (*src && isspace(*src)) + src++; + return src; } -#define skip_space(x) _Generic((x), \ - char *: skip_space_mut, \ - const char *: skip_space_const \ -)(x) +#define skip_space(x) \ + _Generic((x), char * : skip_space_mut, const char * : skip_space_const)(x) diff --git a/src/types.h b/src/types.h index a879b80..eb749f6 100644 --- a/src/types.h +++ b/src/types.h @@ -9,27 +9,28 @@ /// Enumeration type to represent switches. typedef enum { - OFF = 0, // false - ON, // true - UNSET + OFF = 0, // false + ON, // true + UNSET } switch_t; /// Structure representing a X geometry. typedef struct { - int wid; - int hei; - int x; - int y; + int wid; + int hei; + int x; + int y; } geometry_t; /// A structure representing margins around a rectangle. typedef struct { - unsigned int top; - unsigned int left; - unsigned int bottom; - unsigned int right; + unsigned int top; + unsigned int left; + unsigned int bottom; + unsigned int right; } margin_t; typedef uint32_t opacity_t; -#define MARGIN_INIT { 0, 0, 0, 0 } +#define MARGIN_INIT \ + { 0, 0, 0, 0 } diff --git a/src/vsync.c b/src/vsync.c index 1ea1811..2525a7d 100644 --- a/src/vsync.c +++ b/src/vsync.c @@ -12,12 +12,12 @@ #endif #ifdef CONFIG_VSYNC_DRM -#include -#include -#include #include #include +#include #include +#include +#include #endif #include "config.h" @@ -27,26 +27,24 @@ /** * 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 -vsync_drm_wait(session_t *ps) { - int ret = -1; - drm_wait_vblank_t vbl; +static int vsync_drm_wait(session_t *ps) { + int ret = -1; + drm_wait_vblank_t vbl; - vbl.request.type = _DRM_VBLANK_RELATIVE, - vbl.request.sequence = 1; + vbl.request.type = _DRM_VBLANK_RELATIVE, vbl.request.sequence = 1; - do { - ret = ioctl(ps->drm_fd, DRM_IOCTL_WAIT_VBLANK, &vbl); - vbl.request.type &= ~_DRM_VBLANK_RELATIVE; - } while (ret && errno == EINTR); + do { + ret = ioctl(ps->drm_fd, DRM_IOCTL_WAIT_VBLANK, &vbl); + vbl.request.type &= ~_DRM_VBLANK_RELATIVE; + } while (ret && errno == EINTR); - if (ret) - log_error("VBlank ioctl did not work, unimplemented in this drmver?"); - - return ret; + if (ret) + log_error("VBlank ioctl did not work, unimplemented in this drmver?"); + return ret; } #endif @@ -55,126 +53,120 @@ vsync_drm_wait(session_t *ps) { * * @return true for success, false otherwise */ -static bool -vsync_drm_init(session_t *ps) { +static bool vsync_drm_init(session_t *ps) { #ifdef CONFIG_VSYNC_DRM - // Should we always open card0? - if (ps->drm_fd < 0 && (ps->drm_fd = open("/dev/dri/card0", O_RDWR)) < 0) { - log_error("Failed to open device."); - return false; - } + // Should we always open card0? + if (ps->drm_fd < 0 && (ps->drm_fd = open("/dev/dri/card0", O_RDWR)) < 0) { + log_error("Failed to open device."); + return false; + } - if (vsync_drm_wait(ps)) - return false; + if (vsync_drm_wait(ps)) + return false; - return true; + return true; #else - log_error("compton is not compiled with DRM VSync support."); - return false; + log_error("compton is not compiled with DRM VSync support."); + return false; #endif } /** * 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 * * @return true for success, false otherwise */ -static bool -vsync_opengl_init(session_t *ps) { +static bool vsync_opengl_init(session_t *ps) { #ifdef CONFIG_OPENGL - if (!ensure_glx_context(ps)) - return false; + if (!ensure_glx_context(ps)) + return false; - return glxext.has_GLX_SGI_video_sync; + return glxext.has_GLX_SGI_video_sync; #else - log_error("compton is not compiled with OpenGL VSync support."); - return false; + log_error("compton is not compiled with OpenGL VSync support."); + return false; #endif } -static bool -vsync_opengl_oml_init(session_t *ps) { +static bool vsync_opengl_oml_init(session_t *ps) { #ifdef CONFIG_OPENGL - if (!ensure_glx_context(ps)) - return false; + if (!ensure_glx_context(ps)) + return false; - return glxext.has_GLX_OML_sync_control; + return glxext.has_GLX_OML_sync_control; #else - log_error("compton is not compiled with OpenGL VSync support."); - return false; + log_error("compton is not compiled with OpenGL VSync support."); + return false; #endif } #ifdef CONFIG_OPENGL -static inline bool -vsync_opengl_swc_swap_interval(session_t *ps, unsigned int interval) { - if (glxext.has_GLX_MESA_swap_control) - return glXSwapIntervalMESA(interval) == 0; - else if (glxext.has_GLX_SGI_swap_control) - return glXSwapIntervalSGI(interval) == 0; - else if (glxext.has_GLX_EXT_swap_control) { - GLXDrawable d = glXGetCurrentDrawable(); - if (d == None) { - // We don't have a context?? - return false; - } - glXSwapIntervalEXT(ps->dpy, glXGetCurrentDrawable(), interval); - return true; - } - return false; +static inline bool vsync_opengl_swc_swap_interval(session_t *ps, unsigned int interval) { + if (glxext.has_GLX_MESA_swap_control) + return glXSwapIntervalMESA(interval) == 0; + else if (glxext.has_GLX_SGI_swap_control) + return glXSwapIntervalSGI(interval) == 0; + else if (glxext.has_GLX_EXT_swap_control) { + GLXDrawable d = glXGetCurrentDrawable(); + if (d == None) { + // We don't have a context?? + return false; + } + glXSwapIntervalEXT(ps->dpy, glXGetCurrentDrawable(), interval); + return true; + } + return false; } #endif -static bool -vsync_opengl_swc_init(session_t *ps) { +static bool vsync_opengl_swc_init(session_t *ps) { #ifdef CONFIG_OPENGL - if (!bkend_use_glx(ps)) { - log_warn("OpenGL swap control requires the GLX backend."); - return false; - } + if (!bkend_use_glx(ps)) { + log_warn("OpenGL swap control requires the GLX backend."); + return false; + } - if (!vsync_opengl_swc_swap_interval(ps, 1)) { - log_error("Failed to load a swap control extension."); - return false; - } + if (!vsync_opengl_swc_swap_interval(ps, 1)) { + log_error("Failed to load a swap control extension."); + return false; + } - return true; + return true; #else - log_error("compton is not compiled with OpenGL VSync support."); - return false; + log_error("compton is not compiled with OpenGL VSync support."); + return false; #endif } -static bool -vsync_opengl_mswc_init(session_t *ps) { - log_warn("opengl-mswc is deprecated, please use opengl-swc instead."); - return vsync_opengl_swc_init(ps); +static bool vsync_opengl_mswc_init(session_t *ps) { + log_warn("opengl-mswc is deprecated, please use opengl-swc instead."); + return vsync_opengl_swc_init(ps); } bool (*const VSYNC_FUNCS_INIT[NUM_VSYNC])(session_t *ps) = { - [VSYNC_DRM ] = vsync_drm_init, - [VSYNC_OPENGL ] = vsync_opengl_init, - [VSYNC_OPENGL_OML ] = vsync_opengl_oml_init, - [VSYNC_OPENGL_SWC ] = vsync_opengl_swc_init, - [VSYNC_OPENGL_MSWC ] = vsync_opengl_mswc_init, + [VSYNC_DRM] = vsync_drm_init, + [VSYNC_OPENGL] = vsync_opengl_init, + [VSYNC_OPENGL_OML] = vsync_opengl_oml_init, + [VSYNC_OPENGL_SWC] = vsync_opengl_swc_init, + [VSYNC_OPENGL_MSWC] = vsync_opengl_mswc_init, }; #ifdef CONFIG_OPENGL /** * Wait for next VSync, OpenGL method. */ -static int -vsync_opengl_wait(session_t *ps) { - unsigned vblank_count = 0; +static int vsync_opengl_wait(session_t *ps) { + unsigned vblank_count = 0; - glXGetVideoSyncSGI(&vblank_count); - glXWaitVideoSyncSGI(2, (vblank_count + 1) % 2, &vblank_count); - // I see some code calling glXSwapIntervalSGI(1) afterwards, is it required? + glXGetVideoSyncSGI(&vblank_count); + glXWaitVideoSyncSGI(2, (vblank_count + 1) % 2, &vblank_count); + // I see some code calling glXSwapIntervalSGI(1) afterwards, is it required? - return 0; + return 0; } /** @@ -182,15 +174,13 @@ vsync_opengl_wait(session_t *ps) { * * https://mail.gnome.org/archives/clutter-list/2012-November/msg00031.html */ -static int -vsync_opengl_oml_wait(session_t *ps) { - int64_t ust = 0, msc = 0, sbc = 0; +static int vsync_opengl_oml_wait(session_t *ps) { + int64_t ust = 0, msc = 0, sbc = 0; - glXGetSyncValuesOML(ps->dpy, ps->reg_win, &ust, &msc, &sbc); - glXWaitForMscOML(ps->dpy, ps->reg_win, 0, 2, (msc + 1) % 2, - &ust, &msc, &sbc); + glXGetSyncValuesOML(ps->dpy, ps->reg_win, &ust, &msc, &sbc); + glXWaitForMscOML(ps->dpy, ps->reg_win, 0, 2, (msc + 1) % 2, &ust, &msc, &sbc); - return 0; + return 0; } #endif @@ -198,27 +188,25 @@ vsync_opengl_oml_wait(session_t *ps) { /// Function pointers to wait for VSync. int (*const VSYNC_FUNCS_WAIT[NUM_VSYNC])(session_t *ps) = { #ifdef CONFIG_VSYNC_DRM - [VSYNC_DRM ] = vsync_drm_wait, + [VSYNC_DRM] = vsync_drm_wait, #endif #ifdef CONFIG_OPENGL - [VSYNC_OPENGL ] = vsync_opengl_wait, - [VSYNC_OPENGL_OML ] = vsync_opengl_oml_wait, + [VSYNC_OPENGL] = vsync_opengl_wait, + [VSYNC_OPENGL_OML] = vsync_opengl_oml_wait, #endif }; #ifdef CONFIG_OPENGL -static void -vsync_opengl_swc_deinit(session_t *ps) { - vsync_opengl_swc_swap_interval(ps, 0); +static void vsync_opengl_swc_deinit(session_t *ps) { + vsync_opengl_swc_swap_interval(ps, 0); } #endif - /// Function pointers to deinitialize VSync. void (*const VSYNC_FUNCS_DEINIT[NUM_VSYNC])(session_t *ps) = { #ifdef CONFIG_OPENGL - [VSYNC_OPENGL_SWC ] = vsync_opengl_swc_deinit, - [VSYNC_OPENGL_MSWC ] = vsync_opengl_swc_deinit, + [VSYNC_OPENGL_SWC] = vsync_opengl_swc_deinit, + [VSYNC_OPENGL_MSWC] = vsync_opengl_swc_deinit, #endif }; @@ -226,36 +214,34 @@ void (*const VSYNC_FUNCS_DEINIT[NUM_VSYNC])(session_t *ps) = { * Initialize current VSync method. */ bool vsync_init(session_t *ps) { - // Mesa turns on swap control by default, undo that + // Mesa turns on swap control by default, undo that #ifdef CONFIG_OPENGL - if (bkend_use_glx(ps)) - vsync_opengl_swc_swap_interval(ps, 0); + if (bkend_use_glx(ps)) + vsync_opengl_swc_swap_interval(ps, 0); #endif - if (ps->o.vsync && VSYNC_FUNCS_INIT[ps->o.vsync] - && !VSYNC_FUNCS_INIT[ps->o.vsync](ps)) { - ps->o.vsync = VSYNC_NONE; - return false; - } - else - return true; + if (ps->o.vsync && VSYNC_FUNCS_INIT[ps->o.vsync] && !VSYNC_FUNCS_INIT[ps->o.vsync](ps)) { + ps->o.vsync = VSYNC_NONE; + return false; + } else + return true; } /** * Wait for next VSync. */ void vsync_wait(session_t *ps) { - if (!ps->o.vsync) - return; + if (!ps->o.vsync) + return; - if (VSYNC_FUNCS_WAIT[ps->o.vsync]) - VSYNC_FUNCS_WAIT[ps->o.vsync](ps); + if (VSYNC_FUNCS_WAIT[ps->o.vsync]) + VSYNC_FUNCS_WAIT[ps->o.vsync](ps); } /** * Deinitialize current VSync method. */ void vsync_deinit(session_t *ps) { - if (ps->o.vsync && VSYNC_FUNCS_DEINIT[ps->o.vsync]) - VSYNC_FUNCS_DEINIT[ps->o.vsync](ps); + if (ps->o.vsync && VSYNC_FUNCS_DEINIT[ps->o.vsync]) + VSYNC_FUNCS_DEINIT[ps->o.vsync](ps); } diff --git a/src/win.c b/src/win.c index 763a05b..4f5aa6b 100644 --- a/src/win.c +++ b/src/win.c @@ -4,29 +4,29 @@ #include #include -#include -#include -#include -#include -#include -#include #include -#include +#include #include +#include +#include +#include +#include +#include +#include -#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 "c2.h" +#include "common.h" +#include "compiler.h" +#include "compton.h" +#include "config.h" +#include "log.h" +#include "region.h" #include "render.h" +#include "string_utils.h" +#include "types.h" +#include "utils.h" +#include "x.h" #ifdef CONFIG_DBUS #include "dbus.h" @@ -44,32 +44,30 @@ /// Generate a "return by value" function, from a function that returns the /// region via a region_t pointer argument. /// Function signature has to be (win *, region_t *) -#define gen_by_val(fun) region_t fun##_by_val(const win *w) { \ - region_t ret; \ - pixman_region32_init(&ret); \ - fun(w, &ret); \ - return ret; \ -} +#define gen_by_val(fun) \ + region_t fun##_by_val(const win *w) { \ + region_t ret; \ + pixman_region32_init(&ret); \ + fun(w, &ret); \ + return ret; \ + } /** * Clear leader cache of all windows. */ -static inline void -clear_cache_win_leaders(session_t *ps) { - for (win *w = ps->list; w; w = w->next) - w->cache_leader = XCB_NONE; +static inline void clear_cache_win_leaders(session_t *ps) { + for (win *w = ps->list; w; w = w->next) + w->cache_leader = XCB_NONE; } -static inline void -wid_set_opacity_prop(session_t *ps, xcb_window_t wid, opacity_t val) { - const uint32_t v = val; - xcb_change_property(ps->c, XCB_PROP_MODE_REPLACE, wid, ps->atom_opacity, - XCB_ATOM_CARDINAL, 32, 1, &v); +static inline void wid_set_opacity_prop(session_t *ps, xcb_window_t wid, opacity_t val) { + const uint32_t v = val; + xcb_change_property(ps->c, XCB_PROP_MODE_REPLACE, wid, ps->atom_opacity, + XCB_ATOM_CARDINAL, 32, 1, &v); } -static inline void -wid_rm_opacity_prop(session_t *ps, xcb_window_t wid) { - xcb_delete_property(ps->c, wid, ps->atom_opacity); +static inline void wid_rm_opacity_prop(session_t *ps, xcb_window_t wid) { + xcb_delete_property(ps->c, wid, ps->atom_opacity); } /** @@ -77,17 +75,16 @@ wid_rm_opacity_prop(session_t *ps, xcb_window_t wid) { * * @param leader leader window ID */ -static inline void -group_update_focused(session_t *ps, xcb_window_t leader) { - if (!leader) - return; +static inline void group_update_focused(session_t *ps, xcb_window_t leader) { + if (!leader) + return; - for (win *w = ps->list; w; w = w->next) { - if (win_get_leader(ps, w) == leader && w->state != WSTATE_DESTROYING) - win_update_focused(ps, w); - } + for (win *w = ps->list; w; w = w->next) { + if (win_get_leader(ps, w) == leader && w->state != WSTATE_DESTROYING) + win_update_focused(ps, w); + } - return; + return; } /** @@ -96,69 +93,70 @@ group_update_focused(session_t *ps, xcb_window_t leader) { * @param leader leader window ID * @return true if the window group is focused, false otherwise */ -static inline bool -group_is_focused(session_t *ps, xcb_window_t leader) { - if (!leader) - return false; +static inline bool group_is_focused(session_t *ps, xcb_window_t leader) { + if (!leader) + return false; - for (win *w = ps->list; w; w = w->next) { - if (win_get_leader(ps, w) == leader && w->state != WSTATE_DESTROYING - && win_is_focused_real(ps, w)) - return true; - } + for (win *w = ps->list; w; w = w->next) { + if (win_get_leader(ps, w) == leader && w->state != WSTATE_DESTROYING && + win_is_focused_real(ps, w)) + return true; + } - return false; + return false; } /** * Get a rectangular region a window occupies, excluding shadow. */ static void win_get_region_local(const win *w, region_t *res) { - pixman_region32_fini(res); - pixman_region32_init_rect(res, 0, 0, w->widthb, w->heightb); + pixman_region32_fini(res); + pixman_region32_init_rect(res, 0, 0, w->widthb, w->heightb); } - /** * Get a rectangular region a window occupies, excluding frame and shadow. */ void win_get_region_noframe_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); - int x = extents.left; - int y = extents.top; - int width = max_i(w->g.width - extents.left - extents.right, 0); - int height = max_i(w->g.height - extents.top - extents.bottom, 0); + int x = extents.left; + int y = extents.top; + int width = max_i(w->g.width - extents.left - extents.right, 0); + int height = max_i(w->g.height - extents.top - extents.bottom, 0); - pixman_region32_fini(res); - if (width > 0 && height > 0) - pixman_region32_init_rect(res, x, y, width, height); + pixman_region32_fini(res); + if (width > 0 && height > 0) + 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) { - const margin_t extents = win_calc_frame_extents(w); - pixman_region32_fini(res); - pixman_region32_init_rects(res, (rect_t[]){ - // top - {.x1 = 0, .y1 = 0, .x2 = w->g.width, .y2 = extents.top}, - // bottom - {.x1 = 0, .y1 = w->g.height - extents.bottom, .x2 = w->g.width, .y2 = w->g.height}, - //left - {.x1 = 0, .y1 = 0, .x2 = extents.left, .y2 = w->g.height}, - // right - {.x1 = w->g.width - extents.right, .y1 = 0, .x2 = w->g.width, .y2 = w->g.height}, - }, 4); + const margin_t extents = win_calc_frame_extents(w); + pixman_region32_fini(res); + pixman_region32_init_rects( + res, + (rect_t[]){ + // top + {.x1 = 0, .y1 = 0, .x2 = w->g.width, .y2 = extents.top}, + // bottom + {.x1 = 0, .y1 = w->g.height - extents.bottom, .x2 = w->g.width, .y2 = w->g.height}, + // left + {.x1 = 0, .y1 = 0, .x2 = extents.left, .y2 = w->g.height}, + // right + {.x1 = w->g.width - extents.right, .y1 = 0, .x2 = w->g.width, .y2 = w->g.height}, + }, + 4); - // limit the frame region to inside the window - region_t reg_win; - pixman_region32_init_rect(®_win, 0, 0, w->g.width, w->g.height); - pixman_region32_intersect(res, ®_win, res); - pixman_region32_fini(®_win); + // limit the frame region to inside the window + region_t reg_win; + pixman_region32_init_rect(®_win, 0, 0, w->g.width, w->g.height); + pixman_region32_intersect(res, ®_win, res); + 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. @@ -167,13 +165,13 @@ gen_by_val(win_get_region_frame_local) * @param w struct _win element representing the window */ void add_damage_from_win(session_t *ps, win *w) { - // XXX there was a cached extents region, investigate - // if that's better - region_t extents; - pixman_region32_init(&extents); - win_extents(w, &extents); - add_damage(ps, &extents); - pixman_region32_fini(&extents); + // XXX there was a cached extents region, investigate + // if that's better + region_t extents; + pixman_region32_init(&extents); + win_extents(w, &extents); + add_damage(ps, &extents); + pixman_region32_fini(&extents); } /** @@ -181,166 +179,167 @@ void add_damage_from_win(session_t *ps, win *w) { * XXX This is really dumb */ static bool attr_pure win_has_rounded_corners(const win *w) { - if (!w->bounding_shaped) { - return false; - } + if (!w->bounding_shaped) { + return false; + } - // Quit if border_size() returns XCB_NONE - if (!pixman_region32_not_empty((region_t *)&w->bounding_shape)) { - return false; - } + // Quit if border_size() returns XCB_NONE + if (!pixman_region32_not_empty((region_t *)&w->bounding_shape)) { + return false; + } - // Determine the minimum width/height of a rectangle that could mark - // a window as having rounded corners - unsigned short minwidth = max_i(w->widthb * (1 - ROUNDED_PERCENT), - w->widthb - ROUNDED_PIXELS); - unsigned short minheight = max_i(w->heightb * (1 - ROUNDED_PERCENT), - w->heightb - ROUNDED_PIXELS); + // Determine the minimum width/height of a rectangle that could mark + // a window as having rounded corners + unsigned short minwidth = + max_i(w->widthb * (1 - ROUNDED_PERCENT), w->widthb - ROUNDED_PIXELS); + unsigned short minheight = + max_i(w->heightb * (1 - ROUNDED_PERCENT), w->heightb - ROUNDED_PIXELS); - // Get the rectangles in the bounding region - int nrects = 0; - const rect_t *rects = pixman_region32_rectangles((region_t *)&w->bounding_shape, &nrects); + // Get the rectangles in the bounding region + int nrects = 0; + const rect_t *rects = + pixman_region32_rectangles((region_t *)&w->bounding_shape, &nrects); - // Look for a rectangle large enough for this window be considered - // having rounded corners - for (int i = 0; i < nrects; ++i) { - if (rects[i].x2 - rects[i].x1 >= minwidth && rects[i].y2 - rects[i].y1 >= minheight) { - return true; - } - } - return false; + // Look for a rectangle large enough for this window be considered + // having rounded corners + for (int i = 0; i < nrects; ++i) { + if (rects[i].x2 - rects[i].x1 >= minwidth && + rects[i].y2 - rects[i].y1 >= minheight) { + return true; + } + } + return false; } int win_get_name(session_t *ps, win *w) { - XTextProperty text_prop = { NULL, XCB_NONE, 0, 0 }; - char **strlst = NULL; - int nstr = 0; + XTextProperty text_prop = {NULL, XCB_NONE, 0, 0}; + char **strlst = NULL; + int nstr = 0; - if (!w->client_win) - return 0; + if (!w->client_win) + return 0; - 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); + 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); - if (!(XGetWMName(ps->dpy, w->client_win, &text_prop) && text_prop.value)) { - return -1; - } - if (Success != - XmbTextPropertyToTextList(ps->dpy, &text_prop, &strlst, &nstr) - || !nstr || !strlst) { - if (strlst) - XFreeStringList(strlst); - cxfree(text_prop.value); - return -1; - } - cxfree(text_prop.value); - } + if (!(XGetWMName(ps->dpy, w->client_win, &text_prop) && text_prop.value)) { + return -1; + } + if (Success != XmbTextPropertyToTextList(ps->dpy, &text_prop, &strlst, &nstr) || + !nstr || !strlst) { + if (strlst) + XFreeStringList(strlst); + cxfree(text_prop.value); + return -1; + } + cxfree(text_prop.value); + } - int ret = 0; - if (!w->name || strcmp(w->name, strlst[0]) != 0) { - ret = 1; - free(w->name); - w->name = strdup(strlst[0]); - } + int ret = 0; + if (!w->name || strcmp(w->name, strlst[0]) != 0) { + ret = 1; + free(w->name); + w->name = strdup(strlst[0]); + } - XFreeStringList(strlst); + XFreeStringList(strlst); - log_trace("(%#010x): client = %#010x, name = \"%s\", " - "ret = %d", w->id, w->client_win, w->name, ret); - return ret; + log_trace("(%#010x): client = %#010x, name = \"%s\", " + "ret = %d", + w->id, w->client_win, w->name, ret); + return ret; } int win_get_role(session_t *ps, win *w) { - char **strlst = NULL; - int nstr = 0; + char **strlst = NULL; + int nstr = 0; - if (!wid_get_text_prop(ps, w->client_win, ps->atom_role, &strlst, &nstr)) - return -1; + if (!wid_get_text_prop(ps, w->client_win, ps->atom_role, &strlst, &nstr)) + return -1; - int ret = 0; - if (!w->role || strcmp(w->role, strlst[0]) != 0) { - ret = 1; - free(w->role); - w->role = strdup(strlst[0]); - } + int ret = 0; + if (!w->role || strcmp(w->role, strlst[0]) != 0) { + ret = 1; + free(w->role); + w->role = strdup(strlst[0]); + } - XFreeStringList(strlst); + XFreeStringList(strlst); - log_trace("(%#010x): client = %#010x, role = \"%s\", " - "ret = %d", w->id, w->client_win, w->role, ret); - return ret; + log_trace("(%#010x): client = %#010x, role = \"%s\", " + "ret = %d", + w->id, w->client_win, w->role, ret); + return ret; } /** * Check if a window is bounding-shaped. */ static inline bool win_bounding_shaped(const session_t *ps, xcb_window_t wid) { - if (ps->shape_exists) { - xcb_shape_query_extents_reply_t *reply; - Bool bounding_shaped; + if (ps->shape_exists) { + xcb_shape_query_extents_reply_t *reply; + Bool bounding_shaped; - reply = xcb_shape_query_extents_reply(ps->c, - xcb_shape_query_extents(ps->c, wid), NULL); - bounding_shaped = reply && reply->bounding_shaped; - free(reply); + reply = xcb_shape_query_extents_reply( + ps->c, xcb_shape_query_extents(ps->c, wid), NULL); + bounding_shaped = reply && reply->bounding_shaped; + free(reply); - return bounding_shaped; - } + return bounding_shaped; + } - return false; + return false; } -static wintype_t -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); +static wintype_t 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); - for (unsigned i = 0; i < prop.nitems; ++i) { - for (wintype_t j = 1; j < NUM_WINTYPES; ++j) { - if (ps->atoms_wintypes[j] == (xcb_atom_t)prop.p32[i]) { - free_winprop(&prop); - return j; - } - } - } + for (unsigned i = 0; i < prop.nitems; ++i) { + for (wintype_t j = 1; j < NUM_WINTYPES; ++j) { + if (ps->atoms_wintypes[j] == (xcb_atom_t)prop.p32[i]) { + free_winprop(&prop); + return j; + } + } + } - free_winprop(&prop); + free_winprop(&prop); - return WINTYPE_UNKNOWN; + return WINTYPE_UNKNOWN; } static bool -wid_get_opacity_prop(session_t *ps, xcb_window_t wid, opacity_t def, - opacity_t *out) { - bool ret = false; - *out = def; +wid_get_opacity_prop(session_t *ps, xcb_window_t wid, opacity_t def, opacity_t *out) { + bool ret = false; + *out = def; - winprop_t prop = wid_get_prop(ps, wid, ps->atom_opacity, 1L, XCB_ATOM_CARDINAL, 32); + winprop_t prop = wid_get_prop(ps, wid, ps->atom_opacity, 1L, XCB_ATOM_CARDINAL, 32); - if (prop.nitems) { - *out = *prop.c32; - ret = true; - } + if (prop.nitems) { + *out = *prop.c32; + ret = true; + } - free_winprop(&prop); + free_winprop(&prop); - return ret; + return ret; } // XXX should distinguish between frame has alpha and window body has alpha bool win_has_alpha(const win *w) { - return w->pictfmt && - w->pictfmt->type == XCB_RENDER_PICT_TYPE_DIRECT && - w->pictfmt->direct.alpha_mask; + return w->pictfmt && w->pictfmt->type == XCB_RENDER_PICT_TYPE_DIRECT && + w->pictfmt->direct.alpha_mask; } winmode_t win_calc_mode(const win *w) { - if (win_has_alpha(w) || w->opacity < 1.0) { - return WMODE_TRANS; - } - if (w->frame_opacity != 1.0) { - return WMODE_FRAME_TRANS; - } - return WMODE_SOLID; + if (win_has_alpha(w) || w->opacity < 1.0) { + return WMODE_TRANS; + } + if (w->frame_opacity != 1.0) { + return WMODE_FRAME_TRANS; + } + return WMODE_SOLID; } /** @@ -364,76 +363,76 @@ winmode_t win_calc_mode(const win *w) { * @return target opacity */ double win_calc_opacity_target(session_t *ps, const win *w) { - double opacity = 1; + double opacity = 1; - if (w->state == WSTATE_UNMAPPED) { - // be consistent - return 0; - } - if (w->state == WSTATE_UNMAPPING || w->state == WSTATE_DESTROYING) { - return 0; - } - // Try obeying opacity property and window type opacity firstly - if (w->has_opacity_prop) { - opacity = ((double)w->opacity_prop) / OPAQUE; - } else if (!safe_isnan(ps->o.wintype_option[w->window_type].opacity)) { - opacity = ps->o.wintype_option[w->window_type].opacity; - } else { - // Respect active_opacity only when the window is physically focused - if (win_is_focused_real(ps, w)) - opacity = ps->o.active_opacity; - else if (!w->focused) - // Respect inactive_opacity in some cases - opacity = ps->o.inactive_opacity; - } + if (w->state == WSTATE_UNMAPPED) { + // be consistent + return 0; + } + if (w->state == WSTATE_UNMAPPING || w->state == WSTATE_DESTROYING) { + return 0; + } + // Try obeying opacity property and window type opacity firstly + if (w->has_opacity_prop) { + opacity = ((double)w->opacity_prop) / OPAQUE; + } else if (!safe_isnan(ps->o.wintype_option[w->window_type].opacity)) { + opacity = ps->o.wintype_option[w->window_type].opacity; + } else { + // Respect active_opacity only when the window is physically focused + if (win_is_focused_real(ps, w)) + opacity = ps->o.active_opacity; + else if (!w->focused) + // Respect inactive_opacity in some cases + opacity = ps->o.inactive_opacity; + } - // respect inactive override - if (ps->o.inactive_opacity_override && !w->focused) - opacity = ps->o.inactive_opacity; + // respect inactive override + if (ps->o.inactive_opacity_override && !w->focused) + opacity = ps->o.inactive_opacity; - return opacity; + return opacity; } /** * Determine whether a window is to be dimmed. */ bool win_should_dim(session_t *ps, const win *w) { - // Make sure we do nothing if the window is unmapped / being destroyed - if (w->state == WSTATE_UNMAPPED) { - return false; - } + // Make sure we do nothing if the window is unmapped / being destroyed + if (w->state == WSTATE_UNMAPPED) { + return false; + } - if (ps->o.inactive_dim && !(w->focused)) { - return true; - } else { - return false; - } + if (ps->o.inactive_dim && !(w->focused)) { + return true; + } else { + return false; + } } /** * Determine if a window should fade on opacity change. */ bool win_should_fade(session_t *ps, const win *w) { - // To prevent it from being overwritten by last-paint value if the window is - if (w->fade_force != UNSET) { - return w->fade_force; - } - if (ps->o.no_fading_openclose && w->in_openclose) { - return false; - } - if (ps->o.no_fading_destroyed_argb && w->state == WSTATE_DESTROYING && - win_has_alpha(w) && w->client_win && w->client_win != w->id) { - // deprecated - return false; - } - // Ignore other possible causes of fading state changes after window - // gets unmapped - //if (w->a.map_state != XCB_MAP_STATE_VIEWABLE) { - //} - if (c2_match(ps, w, ps->o.fade_blacklist, NULL)) { - return false; - } - return ps->o.wintype_option[w->window_type].fade; + // To prevent it from being overwritten by last-paint value if the window is + if (w->fade_force != UNSET) { + return w->fade_force; + } + if (ps->o.no_fading_openclose && w->in_openclose) { + return false; + } + if (ps->o.no_fading_destroyed_argb && w->state == WSTATE_DESTROYING && + win_has_alpha(w) && w->client_win && w->client_win != w->id) { + // deprecated + return false; + } + // Ignore other possible causes of fading state changes after window + // gets unmapped + // if (w->a.map_state != XCB_MAP_STATE_VIEWABLE) { + //} + if (c2_match(ps, w, ps->o.fade_blacklist, NULL)) { + return false; + } + return ps->o.wintype_option[w->window_type].fade; } /** @@ -442,16 +441,16 @@ bool win_should_fade(session_t *ps, const win *w) { * The property must be set on the outermost window, usually the WM frame. */ void win_update_prop_shadow_raw(session_t *ps, win *w) { - winprop_t prop = - wid_get_prop(ps, w->id, ps->atom_compton_shadow, 1, XCB_ATOM_CARDINAL, 32); + winprop_t prop = + wid_get_prop(ps, w->id, ps->atom_compton_shadow, 1, XCB_ATOM_CARDINAL, 32); - if (!prop.nitems) { - w->prop_shadow = -1; - } else { - w->prop_shadow = *prop.c32; - } + if (!prop.nitems) { + w->prop_shadow = -1; + } else { + w->prop_shadow = *prop.c32; + } - free_winprop(&prop); + free_winprop(&prop); } /** @@ -459,38 +458,38 @@ void win_update_prop_shadow_raw(session_t *ps, win *w) { * things. */ void win_update_prop_shadow(session_t *ps, win *w) { - long attr_shadow_old = w->prop_shadow; + long attr_shadow_old = w->prop_shadow; - win_update_prop_shadow_raw(ps, w); + win_update_prop_shadow_raw(ps, w); - if (w->prop_shadow != attr_shadow_old) - win_determine_shadow(ps, w); + if (w->prop_shadow != attr_shadow_old) + win_determine_shadow(ps, w); } void win_set_shadow(session_t *ps, win *w, bool shadow_new) { - if (w->shadow == shadow_new) - return; + if (w->shadow == shadow_new) + return; - region_t extents; - pixman_region32_init(&extents); - win_extents(w, &extents); + region_t extents; + pixman_region32_init(&extents); + win_extents(w, &extents); - w->shadow = shadow_new; + w->shadow = shadow_new; - // Window extents need update on shadow state change - // Shadow geometry currently doesn't change on shadow state change - // calc_shadow_geometry(ps, w); - // Mark the old extents as damaged if the shadow is removed - if (!w->shadow) - add_damage(ps, &extents); + // Window extents need update on shadow state change + // Shadow geometry currently doesn't change on shadow state change + // calc_shadow_geometry(ps, w); + // Mark the old extents as damaged if the shadow is removed + if (!w->shadow) + add_damage(ps, &extents); - pixman_region32_clear(&extents); - // Mark the new extents as damaged if the shadow is added - if (w->shadow) { - win_extents(w, &extents); - add_damage_from_win(ps, w); - } - pixman_region32_fini(&extents); + pixman_region32_clear(&extents); + // Mark the new extents as damaged if the shadow is added + if (w->shadow) { + win_extents(w, &extents); + add_damage_from_win(ps, w); + } + pixman_region32_fini(&extents); } /** @@ -498,68 +497,66 @@ void win_set_shadow(session_t *ps, win *w, bool shadow_new) { * on shadow state. */ void win_determine_shadow(session_t *ps, win *w) { - bool shadow_new = w->shadow; + bool shadow_new = w->shadow; - if (UNSET != w->shadow_force) - shadow_new = w->shadow_force; - else if (w->a.map_state == XCB_MAP_STATE_VIEWABLE) - shadow_new = (ps->o.wintype_option[w->window_type].shadow && - !c2_match(ps, w, ps->o.shadow_blacklist, NULL) && - !(ps->o.shadow_ignore_shaped && w->bounding_shaped && - !w->rounded_corners) && - !(ps->o.respect_prop_shadow && 0 == w->prop_shadow)); + if (UNSET != w->shadow_force) + shadow_new = w->shadow_force; + else if (w->a.map_state == XCB_MAP_STATE_VIEWABLE) + shadow_new = (ps->o.wintype_option[w->window_type].shadow && + !c2_match(ps, w, ps->o.shadow_blacklist, NULL) && + !(ps->o.shadow_ignore_shaped && w->bounding_shaped && + !w->rounded_corners) && + !(ps->o.respect_prop_shadow && 0 == w->prop_shadow)); - win_set_shadow(ps, w, shadow_new); + win_set_shadow(ps, w, shadow_new); } void win_set_invert_color(session_t *ps, win *w, bool invert_color_new) { - if (w->invert_color == invert_color_new) - return; + if (w->invert_color == invert_color_new) + return; - w->invert_color = invert_color_new; + w->invert_color = invert_color_new; - add_damage_from_win(ps, w); + add_damage_from_win(ps, w); } /** * Determine if a window should have color inverted. */ void win_determine_invert_color(session_t *ps, win *w) { - bool invert_color_new = w->invert_color; + bool invert_color_new = w->invert_color; - if (UNSET != w->invert_color_force) - invert_color_new = w->invert_color_force; - else if (w->a.map_state == XCB_MAP_STATE_VIEWABLE) - invert_color_new = - c2_match(ps, w, ps->o.invert_color_list, NULL); + if (UNSET != w->invert_color_force) + invert_color_new = w->invert_color_force; + else if (w->a.map_state == XCB_MAP_STATE_VIEWABLE) + invert_color_new = 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); } void win_set_blur_background(session_t *ps, win *w, bool blur_background_new) { - if (w->blur_background == blur_background_new) - return; + if (w->blur_background == blur_background_new) + return; - w->blur_background = blur_background_new; + w->blur_background = blur_background_new; - // Only consider window damaged if it's previously painted with background - // blurred - if (!win_is_solid(ps, w) || (ps->o.blur_background_frame && w->frame_opacity != 1)) - add_damage_from_win(ps, w); + // Only consider window damaged if it's previously painted with background + // blurred + if (!win_is_solid(ps, w) || (ps->o.blur_background_frame && w->frame_opacity != 1)) + add_damage_from_win(ps, w); } /** * Determine if a window should have background blurred. */ void win_determine_blur_background(session_t *ps, win *w) { - if (w->a.map_state != XCB_MAP_STATE_VIEWABLE) - return; + if (w->a.map_state != XCB_MAP_STATE_VIEWABLE) + return; - bool blur_background_new = - ps->o.blur_background && - !c2_match(ps, w, ps->o.blur_background_blacklist, NULL); + bool blur_background_new = ps->o.blur_background && + !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); } /** @@ -569,38 +566,38 @@ void win_determine_blur_background(session_t *ps, win *w) { * a good idea. */ void win_update_opacity_rule(session_t *ps, win *w) { - if (w->a.map_state != XCB_MAP_STATE_VIEWABLE) - return; + if (w->a.map_state != XCB_MAP_STATE_VIEWABLE) + return; - double opacity = 1.0; - bool is_set = false; - void *val = NULL; - if (c2_match(ps, w, ps->o.opacity_rules, &val)) { - opacity = ((double)(long)val) / 100.0; - is_set = true; - } + double opacity = 1.0; + bool is_set = false; + void *val = NULL; + if (c2_match(ps, w, ps->o.opacity_rules, &val)) { + opacity = ((double)(long)val) / 100.0; + is_set = true; + } - if (is_set == w->opacity_is_set && opacity == w->opacity_set) - return; + if (is_set == w->opacity_is_set && opacity == w->opacity_set) + return; - w->opacity_set = opacity; - w->opacity_is_set = is_set; - if (!is_set) - wid_rm_opacity_prop(ps, w->id); - else - wid_set_opacity_prop(ps, w->id, opacity * OPAQUE); + w->opacity_set = opacity; + w->opacity_is_set = is_set; + if (!is_set) + wid_rm_opacity_prop(ps, w->id); + else + wid_set_opacity_prop(ps, w->id, opacity * OPAQUE); } /** * Function to be called on window type changes. */ void win_on_wtype_change(session_t *ps, win *w) { - win_determine_shadow(ps, w); - win_update_focused(ps, w); - if (ps->o.invert_color_list) - win_determine_invert_color(ps, w); - if (ps->o.opacity_rules) - win_update_opacity_rule(ps, w); + win_determine_shadow(ps, w); + win_update_focused(ps, w); + if (ps->o.invert_color_list) + win_determine_invert_color(ps, w); + if (ps->o.opacity_rules) + win_update_opacity_rule(ps, w); } /** @@ -609,84 +606,85 @@ void win_on_wtype_change(session_t *ps, win *w) { * TODO need better name */ void win_on_factor_change(session_t *ps, win *w) { - if (ps->o.shadow_blacklist) - win_determine_shadow(ps, w); - if (ps->o.invert_color_list) - win_determine_invert_color(ps, w); - if (ps->o.focus_blacklist) - win_update_focused(ps, w); - if (ps->o.blur_background_blacklist) - win_determine_blur_background(ps, w); - if (ps->o.opacity_rules) - win_update_opacity_rule(ps, w); - if (w->a.map_state == XCB_MAP_STATE_VIEWABLE && ps->o.paint_blacklist) - w->paint_excluded = - c2_match(ps, w, ps->o.paint_blacklist, NULL); - if (w->a.map_state == XCB_MAP_STATE_VIEWABLE && ps->o.unredir_if_possible_blacklist) - w->unredir_if_possible_excluded = c2_match( - ps, w, ps->o.unredir_if_possible_blacklist, NULL); - w->reg_ignore_valid = false; + if (ps->o.shadow_blacklist) + win_determine_shadow(ps, w); + if (ps->o.invert_color_list) + win_determine_invert_color(ps, w); + if (ps->o.focus_blacklist) + win_update_focused(ps, w); + if (ps->o.blur_background_blacklist) + win_determine_blur_background(ps, w); + if (ps->o.opacity_rules) + win_update_opacity_rule(ps, w); + if (w->a.map_state == XCB_MAP_STATE_VIEWABLE && ps->o.paint_blacklist) + w->paint_excluded = c2_match(ps, w, ps->o.paint_blacklist, NULL); + if (w->a.map_state == XCB_MAP_STATE_VIEWABLE && ps->o.unredir_if_possible_blacklist) + w->unredir_if_possible_excluded = + c2_match(ps, w, ps->o.unredir_if_possible_blacklist, NULL); + w->reg_ignore_valid = false; } /** * Update cache data in struct _win that depends on window size. */ void win_on_win_size_change(session_t *ps, win *w) { - w->widthb = w->g.width + w->g.border_width * 2; - w->heightb = w->g.height + w->g.border_width * 2; - w->shadow_dx = ps->o.shadow_offset_x; - w->shadow_dy = ps->o.shadow_offset_y; - w->shadow_width = w->widthb + ps->o.shadow_radius * 2; - w->shadow_height = w->heightb + ps->o.shadow_radius * 2; - w->flags |= WFLAG_SIZE_CHANGE; - // Invalidate the shadow we built - if (ps->o.experimental_backends && ps->redirected) { - if (w->state == WSTATE_MAPPED || - w->state == WSTATE_MAPPING || - w->state == WSTATE_FADING) { - ps->backend_data->ops->release_image(ps->backend_data, w->win_image); - if (w->shadow_image) { - ps->backend_data->ops->release_image(ps->backend_data, w->shadow_image); - } - auto pixmap = xcb_generate_id(ps->c); - 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); - if (w->shadow) { - w->shadow_image = ps->backend_data->ops->render_shadow(ps->backend_data, w->widthb, - w->heightb, ps->gaussian_map, - ps->o.shadow_red, ps->o.shadow_green, - ps->o.shadow_blue, ps->o.shadow_opacity); - } - } else { - assert(w->state == WSTATE_UNMAPPED); - } - } else { - free_paint(ps, &w->shadow_paint); - } + w->widthb = w->g.width + w->g.border_width * 2; + w->heightb = w->g.height + w->g.border_width * 2; + w->shadow_dx = ps->o.shadow_offset_x; + w->shadow_dy = ps->o.shadow_offset_y; + w->shadow_width = w->widthb + ps->o.shadow_radius * 2; + w->shadow_height = w->heightb + ps->o.shadow_radius * 2; + w->flags |= WFLAG_SIZE_CHANGE; + // Invalidate the shadow we built + if (ps->o.experimental_backends && ps->redirected) { + if (w->state == WSTATE_MAPPED || w->state == WSTATE_MAPPING || + w->state == WSTATE_FADING) { + ps->backend_data->ops->release_image(ps->backend_data, w->win_image); + if (w->shadow_image) { + ps->backend_data->ops->release_image(ps->backend_data, + w->shadow_image); + } + auto pixmap = xcb_generate_id(ps->c); + 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); + if (w->shadow) { + w->shadow_image = ps->backend_data->ops->render_shadow( + ps->backend_data, w->widthb, w->heightb, + ps->gaussian_map, ps->o.shadow_red, ps->o.shadow_green, + ps->o.shadow_blue, ps->o.shadow_opacity); + } + } else { + assert(w->state == WSTATE_UNMAPPED); + } + } else { + free_paint(ps, &w->shadow_paint); + } } /** * Update window type. */ void win_update_wintype(session_t *ps, win *w) { - const wintype_t wtype_old = w->window_type; + const wintype_t wtype_old = w->window_type; - // Detect window type here - w->window_type = wid_get_prop_wintype(ps, w->client_win); + // Detect window type here + w->window_type = wid_get_prop_wintype(ps, w->client_win); - // Conform to EWMH standard, if _NET_WM_WINDOW_TYPE is not present, take - // override-redirect windows or windows without WM_TRANSIENT_FOR as - // _NET_WM_WINDOW_TYPE_NORMAL, otherwise as _NET_WM_WINDOW_TYPE_DIALOG. - if (WINTYPE_UNKNOWN == w->window_type) { - if (w->a.override_redirect || - !wid_has_prop(ps, w->client_win, ps->atom_transient)) - w->window_type = WINTYPE_NORMAL; - else - w->window_type = WINTYPE_DIALOG; - } + // Conform to EWMH standard, if _NET_WM_WINDOW_TYPE is not present, take + // override-redirect windows or windows without WM_TRANSIENT_FOR as + // _NET_WM_WINDOW_TYPE_NORMAL, otherwise as _NET_WM_WINDOW_TYPE_DIALOG. + if (WINTYPE_UNKNOWN == w->window_type) { + if (w->a.override_redirect || + !wid_has_prop(ps, w->client_win, ps->atom_transient)) + w->window_type = WINTYPE_NORMAL; + else + w->window_type = WINTYPE_DIALOG; + } - if (w->window_type != wtype_old) - win_on_wtype_change(ps, w); + if (w->window_type != wtype_old) + win_on_wtype_change(ps, w); } /** @@ -697,44 +695,44 @@ void win_update_wintype(session_t *ps, win *w) { * @param client window ID of the client window */ void win_mark_client(session_t *ps, win *w, xcb_window_t client) { - w->client_win = client; + w->client_win = client; - // If the window isn't mapped yet, stop here, as the function will be - // called in map_win() - if (w->a.map_state != XCB_MAP_STATE_VIEWABLE) - return; + // If the window isn't mapped yet, stop here, as the function will be + // called in map_win() + if (w->a.map_state != XCB_MAP_STATE_VIEWABLE) + return; - auto e = xcb_request_check( - ps->c, xcb_change_window_attributes( - ps->c, client, XCB_CW_EVENT_MASK, - (const uint32_t[]){determine_evmask(ps, client, WIN_EVMODE_CLIENT)})); - if (e) { - log_error("Failed to change event mask of window %#010x", client); - free(e); - } + auto e = xcb_request_check( + ps->c, xcb_change_window_attributes( + ps->c, client, XCB_CW_EVENT_MASK, + (const uint32_t[]){determine_evmask(ps, client, WIN_EVMODE_CLIENT)})); + if (e) { + log_error("Failed to change event mask of window %#010x", client); + free(e); + } - win_update_wintype(ps, w); + win_update_wintype(ps, w); - // Get frame widths. The window is in damaged area already. - if (ps->o.frame_opacity != 1) - win_update_frame_extents(ps, w, client); + // Get frame widths. The window is in damaged area already. + if (ps->o.frame_opacity != 1) + win_update_frame_extents(ps, w, client); - // Get window group - if (ps->o.track_leader) - win_update_leader(ps, w); + // Get window group + if (ps->o.track_leader) + win_update_leader(ps, w); - // Get window name and class if we are tracking them - if (ps->o.track_wdata) { - win_get_name(ps, w); - win_get_class(ps, w); - win_get_role(ps, w); - } + // Get window name and class if we are tracking them + if (ps->o.track_wdata) { + win_get_name(ps, w); + win_get_class(ps, w); + win_get_role(ps, w); + } - // Update everything related to conditions - win_on_factor_change(ps, w); + // Update everything related to conditions + win_on_factor_change(ps, w); - // Update window focus state - win_update_focused(ps, w); + // Update window focus state + win_update_focused(ps, w); } /** @@ -744,13 +742,14 @@ void win_mark_client(session_t *ps, win *w, xcb_window_t client) { * @param w struct _win of the parent window */ void win_unmark_client(session_t *ps, win *w) { - xcb_window_t client = w->client_win; + xcb_window_t client = w->client_win; - w->client_win = XCB_NONE; + w->client_win = XCB_NONE; - // Recheck event mask - xcb_change_window_attributes(ps->c, client, XCB_CW_EVENT_MASK, - (const uint32_t[]) { determine_evmask(ps, client, WIN_EVMODE_UNKNOWN) }); + // Recheck event mask + xcb_change_window_attributes( + ps->c, client, XCB_CW_EVENT_MASK, + (const uint32_t[]){determine_evmask(ps, client, WIN_EVMODE_UNKNOWN)}); } /** @@ -760,338 +759,338 @@ void win_unmark_client(session_t *ps, win *w) { * @param w struct _win of the parent window */ void win_recheck_client(session_t *ps, win *w) { - // Initialize wmwin to false - w->wmwin = false; + // Initialize wmwin to false + w->wmwin = false; - // Look for the client window + // Look for the client window - // Always recursively look for a window with WM_STATE, as Fluxbox - // sets override-redirect flags on all frame windows. - xcb_window_t cw = find_client_win(ps, w->id); - if (cw) - log_trace("(%#010x): client %#010x", w->id, cw); - // Set a window's client window to itself if we couldn't find a - // client window - if (!cw) { - cw = w->id; - w->wmwin = !w->a.override_redirect; - log_trace("(%#010x): client self (%s)", w->id, - (w->wmwin ? "wmwin" : "override-redirected")); - } + // Always recursively look for a window with WM_STATE, as Fluxbox + // sets override-redirect flags on all frame windows. + xcb_window_t cw = find_client_win(ps, w->id); + if (cw) + log_trace("(%#010x): client %#010x", w->id, cw); + // Set a window's client window to itself if we couldn't find a + // client window + if (!cw) { + cw = w->id; + w->wmwin = !w->a.override_redirect; + log_trace("(%#010x): client self (%s)", w->id, + (w->wmwin ? "wmwin" : "override-redirected")); + } - // Unmark the old one - if (w->client_win && w->client_win != cw) - win_unmark_client(ps, w); + // Unmark the old one + if (w->client_win && w->client_win != cw) + win_unmark_client(ps, w); - // Mark the new one - win_mark_client(ps, w, cw); + // Mark the new one + win_mark_client(ps, w, cw); } /** * Free all resources in a struct _win. */ void free_win_res(session_t *ps, win *w) { - // No need to call backend release_image here because - // finish_unmap_win should've done that for us. - // XXX unless we are called by session_destroy - // assert(w->win_data == NULL); - free_win_res_glx(ps, w); - free_paint(ps, &w->paint); - free_paint(ps, &w->shadow_paint); - // Above should be done during unmapping - // Except when we are called by session_destroy + // No need to call backend release_image here because + // finish_unmap_win should've done that for us. + // XXX unless we are called by session_destroy + // assert(w->win_data == NULL); + free_win_res_glx(ps, w); + free_paint(ps, &w->paint); + free_paint(ps, &w->shadow_paint); + // Above should be done during unmapping + // Except when we are called by session_destroy - pixman_region32_fini(&w->bounding_shape); - // BadDamage may be thrown if the window is destroyed - set_ignore_cookie(ps, - xcb_damage_destroy(ps->c, w->damage)); - rc_region_unref(&w->reg_ignore); - free(w->name); - free(w->class_instance); - free(w->class_general); - free(w->role); + pixman_region32_fini(&w->bounding_shape); + // BadDamage may be thrown if the window is destroyed + set_ignore_cookie(ps, xcb_damage_destroy(ps->c, w->damage)); + rc_region_unref(&w->reg_ignore); + free(w->name); + free(w->class_instance); + free(w->class_general); + free(w->role); } // TODO: probably split into win_new (in win.c) and add_win (in compton.c) void add_win(session_t *ps, xcb_window_t id, xcb_window_t prev) { - static const win win_def = { - // No need to initialize. (or, you can think that - // they are initialized right here). - // The following ones are updated during paint or paint preprocess - .shadow_opacity = 0.0, - .to_paint = false, - .frame_opacity = 1.0, - .dim = false, - .invert_color = false, - .blur_background = false, - .reg_ignore = NULL, - // The following ones are updated for other reasons - .pixmap_damaged = false, // updated by damage events - .state = WSTATE_UNMAPPED, // updated by window state changes - .in_openclose = true, // set to false after first map is done, - // true here because window is just created - .need_configure = false, // set to true when window is configured - // while unmapped. - .queue_configure = {}, // same as above - .reg_ignore_valid = false,// set to true when damaged - .flags = 0, // updated by property/attributes/etc change + static const win win_def = { + // No need to initialize. (or, you can think that + // they are initialized right here). + // The following ones are updated during paint or paint preprocess + .shadow_opacity = 0.0, + .to_paint = false, + .frame_opacity = 1.0, + .dim = false, + .invert_color = false, + .blur_background = false, + .reg_ignore = NULL, + // The following ones are updated for other reasons + .pixmap_damaged = false, // updated by damage events + .state = WSTATE_UNMAPPED, // updated by window state changes + .in_openclose = true, // set to false after first map is done, + // true here because window is just created + .need_configure = false, // set to true when window is configured + // while unmapped. + .queue_configure = {}, // same as above + .reg_ignore_valid = false, // set to true when damaged + .flags = 0, // updated by property/attributes/etc change - // Runtime variables, updated by dbus - .fade_force = UNSET, - .shadow_force = UNSET, - .focused_force = UNSET, - .invert_color_force = UNSET, + // Runtime variables, updated by dbus + .fade_force = UNSET, + .shadow_force = UNSET, + .focused_force = UNSET, + .invert_color_force = UNSET, - // Initialized in this function - .next = NULL, - .id = XCB_NONE, - .a = {0}, - .pictfmt = NULL, - .widthb = 0, - .heightb = 0, - .shadow_dx = 0, - .shadow_dy = 0, - .shadow_width = 0, - .shadow_height = 0, - .damage = XCB_NONE, + // Initialized in this function + .next = NULL, + .id = XCB_NONE, + .a = {0}, + .pictfmt = NULL, + .widthb = 0, + .heightb = 0, + .shadow_dx = 0, + .shadow_dy = 0, + .shadow_width = 0, + .shadow_height = 0, + .damage = XCB_NONE, - // Not initialized until mapped, this variables - // have no meaning or have no use until the window - // is mapped - .win_image = NULL, - .shadow_image = NULL, - .prev_trans = NULL, - .shadow = false, - .xinerama_scr = -1, - .mode = WMODE_TRANS, - .ever_damaged = false, - .client_win = XCB_NONE, - .leader = XCB_NONE, - .cache_leader = XCB_NONE, - .window_type = WINTYPE_UNKNOWN, - .wmwin = false, - .focused = false, - .opacity = 0, - .opacity_tgt = 0, - .has_opacity_prop = false, - .opacity_prop = OPAQUE, - .opacity_is_set = false, - .opacity_set = 1, - .frame_extents = MARGIN_INIT, // in win_mark_client - .bounding_shaped = false, - .bounding_shape = {0}, - .rounded_corners = false, - .paint_excluded = false, - .unredir_if_possible_excluded = false, - .prop_shadow = -1, - // following 4 are set in win_mark_client - .name = NULL, - .class_instance = NULL, - .class_general = NULL, - .role = NULL, + // Not initialized until mapped, this variables + // have no meaning or have no use until the window + // is mapped + .win_image = NULL, + .shadow_image = NULL, + .prev_trans = NULL, + .shadow = false, + .xinerama_scr = -1, + .mode = WMODE_TRANS, + .ever_damaged = false, + .client_win = XCB_NONE, + .leader = XCB_NONE, + .cache_leader = XCB_NONE, + .window_type = WINTYPE_UNKNOWN, + .wmwin = false, + .focused = false, + .opacity = 0, + .opacity_tgt = 0, + .has_opacity_prop = false, + .opacity_prop = OPAQUE, + .opacity_is_set = false, + .opacity_set = 1, + .frame_extents = MARGIN_INIT, // in win_mark_client + .bounding_shaped = false, + .bounding_shape = {0}, + .rounded_corners = false, + .paint_excluded = false, + .unredir_if_possible_excluded = false, + .prop_shadow = -1, + // following 4 are set in win_mark_client + .name = NULL, + .class_instance = NULL, + .class_general = NULL, + .role = NULL, - // Initialized during paint - .paint = PAINT_INIT, - .shadow_paint = PAINT_INIT, - }; + // Initialized during paint + .paint = PAINT_INIT, + .shadow_paint = PAINT_INIT, + }; - // Reject overlay window and already added windows - if (id == ps->overlay) { - return; - } + // Reject overlay window and already added windows + if (id == ps->overlay) { + return; + } - auto duplicated_win = find_win(ps, id); - if (duplicated_win) { - log_debug("Window %#010x (recorded name: %s) added multiple times", id, - duplicated_win->name); - return; - } + auto duplicated_win = find_win(ps, id); + if (duplicated_win) { + log_debug("Window %#010x (recorded name: %s) added multiple times", id, + duplicated_win->name); + return; + } - 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_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_geometry_reply_t *g = xcb_get_geometry_reply(ps->c, gcookie, NULL); - if (!a || !g || a->map_state == XCB_MAP_STATE_UNVIEWABLE) { - // Failed to get window attributes or geometry probably means - // the window is gone already. Unviewable means the window is - // already reparented elsewhere. - // BTW, we don't care about Input Only windows, except for stacking - // proposes, so we need to keep track of them still. - free(a); - free(g); - return; - } + 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_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_geometry_reply_t *g = xcb_get_geometry_reply(ps->c, gcookie, NULL); + if (!a || !g || a->map_state == XCB_MAP_STATE_UNVIEWABLE) { + // Failed to get window attributes or geometry probably means + // the window is gone already. Unviewable means the window is + // already reparented elsewhere. + // BTW, we don't care about Input Only windows, except for stacking + // proposes, so we need to keep track of them still. + free(a); + free(g); + return; + } - // Allocate and initialize the new win structure - auto new = cmalloc(win); + // Allocate and initialize the new win structure + auto new = cmalloc(win); - // Fill structure - // We only need to initialize the part that are not initialized - // by map_win - *new = win_def; - new->id = id; - new->a = *a; - new->g = *g; - pixman_region32_init(&new->bounding_shape); + // Fill structure + // We only need to initialize the part that are not initialized + // by map_win + *new = win_def; + new->id = id; + new->a = *a; + new->g = *g; + pixman_region32_init(&new->bounding_shape); - free(g); - free(a); + free(g); + free(a); - // Create Damage for window (if not Input Only) - if (new->a._class != XCB_WINDOW_CLASS_INPUT_ONLY) { - new->damage = xcb_generate_id(ps->c); - xcb_generic_error_t *e = xcb_request_check(ps->c, - xcb_damage_create_checked(ps->c, new->damage, id, XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY)); - if (e) { - free(e); - free(new); - return; - } + // Create Damage for window (if not Input Only) + if (new->a._class != XCB_WINDOW_CLASS_INPUT_ONLY) { + new->damage = xcb_generate_id(ps->c); + xcb_generic_error_t *e = xcb_request_check( + ps->c, xcb_damage_create_checked(ps->c, new->damage, id, + XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY)); + if (e) { + free(e); + free(new); + return; + } - new->pictfmt = x_get_pictform_for_visual(ps->c, new->a.visual); - } + new->pictfmt = x_get_pictform_for_visual(ps->c, new->a.visual); + } - win_on_win_size_change(ps, new); + win_on_win_size_change(ps, new); - // Find window insertion point - win **p = NULL; - if (prev) { - for (p = &ps->list; *p; p = &(*p)->next) { - if ((*p)->id == prev && (*p)->state != WSTATE_DESTROYING) - break; - } - } else { - p = &ps->list; - } - new->next = *p; - *p = new; + // Find window insertion point + win **p = NULL; + if (prev) { + for (p = &ps->list; *p; p = &(*p)->next) { + if ((*p)->id == prev && (*p)->state != WSTATE_DESTROYING) + break; + } + } else { + p = &ps->list; + } + new->next = *p; + *p = new; #ifdef CONFIG_DBUS - // Send D-Bus signal - if (ps->o.dbus) { - cdbus_ev_win_added(ps, new); - } + // Send D-Bus signal + if (ps->o.dbus) { + cdbus_ev_win_added(ps, new); + } #endif - return; + return; } /** * Update focused state of a window. */ void win_update_focused(session_t *ps, win *w) { - if (UNSET != w->focused_force) { - w->focused = w->focused_force; - } else { - w->focused = win_is_focused_real(ps, w); + if (UNSET != w->focused_force) { + w->focused = w->focused_force; + } else { + w->focused = win_is_focused_real(ps, w); - // Use wintype_focus, and treat WM windows and override-redirected - // windows specially - if (ps->o.wintype_option[w->window_type].focus - || (ps->o.mark_wmwin_focused && w->wmwin) - || (ps->o.mark_ovredir_focused && - w->id == w->client_win && !w->wmwin) - || (w->a.map_state == XCB_MAP_STATE_VIEWABLE && - c2_match(ps, w, ps->o.focus_blacklist, NULL))) - w->focused = true; + // Use wintype_focus, and treat WM windows and override-redirected + // windows specially + if (ps->o.wintype_option[w->window_type].focus || + (ps->o.mark_wmwin_focused && w->wmwin) || + (ps->o.mark_ovredir_focused && w->id == w->client_win && !w->wmwin) || + (w->a.map_state == XCB_MAP_STATE_VIEWABLE && + c2_match(ps, w, ps->o.focus_blacklist, NULL))) + w->focused = true; - // If window grouping detection is enabled, mark the window active if - // its group is - if (ps->o.track_leader && ps->active_leader - && win_get_leader(ps, w) == ps->active_leader) { - w->focused = true; - } - } + // If window grouping detection is enabled, mark the window active if + // its group is + if (ps->o.track_leader && ps->active_leader && + win_get_leader(ps, w) == ps->active_leader) { + w->focused = true; + } + } - // Always recalculate the window target opacity, since some opacity-related - // options depend on the output value of win_is_focused_real() instead of - // w->focused - double opacity_tgt_old = w->opacity_tgt; - w->opacity_tgt = win_calc_opacity_target(ps, w); - if (opacity_tgt_old != w->opacity_tgt && w->state == WSTATE_MAPPED) { - // Only MAPPED can transition to FADING - assert(w->state != WSTATE_DESTROYING && w->state != WSTATE_UNMAPPING && - w->state != WSTATE_UNMAPPED); - w->state = WSTATE_FADING; - } + // Always recalculate the window target opacity, since some opacity-related + // options depend on the output value of win_is_focused_real() instead of + // w->focused + double opacity_tgt_old = w->opacity_tgt; + w->opacity_tgt = win_calc_opacity_target(ps, w); + if (opacity_tgt_old != w->opacity_tgt && w->state == WSTATE_MAPPED) { + // Only MAPPED can transition to FADING + assert(w->state != WSTATE_DESTROYING && w->state != WSTATE_UNMAPPING && + w->state != WSTATE_UNMAPPED); + w->state = WSTATE_FADING; + } } /** * Set leader of a window. */ static inline void win_set_leader(session_t *ps, win *w, xcb_window_t nleader) { - // If the leader changes - if (w->leader != nleader) { - xcb_window_t cache_leader_old = win_get_leader(ps, w); + // If the leader changes + if (w->leader != nleader) { + xcb_window_t cache_leader_old = win_get_leader(ps, w); - w->leader = nleader; + w->leader = nleader; - // Forcefully do this to deal with the case when a child window - // gets mapped before parent, or when the window is a waypoint - clear_cache_win_leaders(ps); + // Forcefully do this to deal with the case when a child window + // gets mapped before parent, or when the window is a waypoint + clear_cache_win_leaders(ps); - // Update the old and new window group and active_leader if the window - // could affect their state. - xcb_window_t cache_leader = win_get_leader(ps, w); - if (win_is_focused_real(ps, w) && cache_leader_old != cache_leader) { - ps->active_leader = cache_leader; + // Update the old and new window group and active_leader if the window + // could affect their state. + xcb_window_t cache_leader = win_get_leader(ps, w); + if (win_is_focused_real(ps, w) && cache_leader_old != cache_leader) { + ps->active_leader = cache_leader; - group_update_focused(ps, cache_leader_old); - group_update_focused(ps, cache_leader); - } - // Otherwise, at most the window itself is affected - else { - win_update_focused(ps, w); - } + group_update_focused(ps, cache_leader_old); + group_update_focused(ps, cache_leader); + } + // Otherwise, at most the window itself is affected + else { + win_update_focused(ps, w); + } - // Update everything related to conditions - win_on_factor_change(ps, w); - } + // Update everything related to conditions + win_on_factor_change(ps, w); + } } /** * Update leader of a window. */ void win_update_leader(session_t *ps, win *w) { - xcb_window_t leader = XCB_NONE; + xcb_window_t leader = XCB_NONE; - // Read the leader properties - if (ps->o.detect_transient && !leader) - leader = wid_get_prop_window(ps, w->client_win, ps->atom_transient); + // Read the leader properties + if (ps->o.detect_transient && !leader) + leader = wid_get_prop_window(ps, w->client_win, ps->atom_transient); - if (ps->o.detect_client_leader && !leader) - leader = wid_get_prop_window(ps, w->client_win, ps->atom_client_leader); + if (ps->o.detect_client_leader && !leader) + leader = wid_get_prop_window(ps, w->client_win, ps->atom_client_leader); - win_set_leader(ps, w, leader); + win_set_leader(ps, w, leader); - log_trace("(%#010x): client %#010x, leader %#010x, cache %#010x", - w->id, w->client_win, w->leader, win_get_leader(ps, w)); + log_trace("(%#010x): client %#010x, leader %#010x, cache %#010x", w->id, + w->client_win, w->leader, win_get_leader(ps, w)); } /** * Internal function of win_get_leader(). */ xcb_window_t win_get_leader_raw(session_t *ps, win *w, int recursions) { - // Rebuild the cache if needed - if (!w->cache_leader && (w->client_win || w->leader)) { - // Leader defaults to client window - if (!(w->cache_leader = w->leader)) - w->cache_leader = w->client_win; + // Rebuild the cache if needed + if (!w->cache_leader && (w->client_win || w->leader)) { + // Leader defaults to client window + if (!(w->cache_leader = w->leader)) + w->cache_leader = w->client_win; - // If the leader of this window isn't itself, look for its ancestors - if (w->cache_leader && w->cache_leader != w->client_win) { - win *wp = find_toplevel(ps, w->cache_leader); - if (wp) { - // Dead loop? - if (recursions > WIN_GET_LEADER_MAX_RECURSION) - return XCB_NONE; + // If the leader of this window isn't itself, look for its ancestors + if (w->cache_leader && w->cache_leader != w->client_win) { + win *wp = find_toplevel(ps, w->cache_leader); + if (wp) { + // Dead loop? + if (recursions > WIN_GET_LEADER_MAX_RECURSION) + return XCB_NONE; - w->cache_leader = win_get_leader_raw(ps, wp, recursions + 1); - } - } - } + w->cache_leader = win_get_leader_raw(ps, wp, recursions + 1); + } + } + } - return w->cache_leader; + return w->cache_leader; } /** @@ -1099,109 +1098,105 @@ xcb_window_t win_get_leader_raw(session_t *ps, win *w, int recursions) { * win structure. */ bool win_get_class(session_t *ps, win *w) { - char **strlst = NULL; - int nstr = 0; + char **strlst = NULL; + int nstr = 0; - // Can't do anything if there's no client window - if (!w->client_win) - return false; + // Can't do anything if there's no client window + if (!w->client_win) + return false; - // Free and reset old strings - free(w->class_instance); - free(w->class_general); - w->class_instance = NULL; - w->class_general = NULL; + // Free and reset old strings + free(w->class_instance); + free(w->class_general); + w->class_instance = NULL; + w->class_general = NULL; - // Retrieve the property string list - if (!wid_get_text_prop(ps, w->client_win, ps->atom_class, &strlst, &nstr)) - return false; + // Retrieve the property string list + if (!wid_get_text_prop(ps, w->client_win, ps->atom_class, &strlst, &nstr)) + return false; - // Copy the strings if successful - w->class_instance = strdup(strlst[0]); + // Copy the strings if successful + w->class_instance = strdup(strlst[0]); - if (nstr > 1) - w->class_general = strdup(strlst[1]); + if (nstr > 1) + w->class_general = strdup(strlst[1]); - XFreeStringList(strlst); + XFreeStringList(strlst); - log_trace("(%#010x): client = %#010x, " - "instance = \"%s\", general = \"%s\"", - w->id, w->client_win, w->class_instance, w->class_general); + log_trace("(%#010x): client = %#010x, " + "instance = \"%s\", general = \"%s\"", + w->id, w->client_win, w->class_instance, w->class_general); - return true; + return true; } - - /** * Handle window focus change. */ -static void -win_on_focus_change(session_t *ps, win *w) { - // If window grouping detection is enabled - if (ps->o.track_leader) { - xcb_window_t leader = win_get_leader(ps, w); +static void win_on_focus_change(session_t *ps, win *w) { + // If window grouping detection is enabled + if (ps->o.track_leader) { + xcb_window_t leader = win_get_leader(ps, w); - // If the window gets focused, replace the old active_leader - if (win_is_focused_real(ps, w) && leader != ps->active_leader) { - xcb_window_t active_leader_old = ps->active_leader; + // If the window gets focused, replace the old active_leader + if (win_is_focused_real(ps, w) && leader != ps->active_leader) { + xcb_window_t active_leader_old = ps->active_leader; - ps->active_leader = leader; + ps->active_leader = leader; - group_update_focused(ps, active_leader_old); - group_update_focused(ps, leader); - } - // If the group get unfocused, remove it from active_leader - else if (!win_is_focused_real(ps, w) && leader && leader == ps->active_leader - && !group_is_focused(ps, leader)) { - ps->active_leader = XCB_NONE; - group_update_focused(ps, leader); - } + group_update_focused(ps, active_leader_old); + group_update_focused(ps, leader); + } + // If the group get unfocused, remove it from active_leader + else if (!win_is_focused_real(ps, w) && leader && + leader == ps->active_leader && !group_is_focused(ps, leader)) { + ps->active_leader = XCB_NONE; + group_update_focused(ps, leader); + } - // The window itself must be updated anyway - win_update_focused(ps, w); - } - // Otherwise, only update the window itself - else { - win_update_focused(ps, w); - } + // The window itself must be updated anyway + win_update_focused(ps, w); + } + // Otherwise, only update the window itself + else { + win_update_focused(ps, w); + } - // Update everything related to conditions - win_on_factor_change(ps, w); + // Update everything related to conditions + win_on_factor_change(ps, w); #ifdef CONFIG_DBUS - // Send D-Bus signal - if (ps->o.dbus) { - if (win_is_focused_real(ps, w)) - cdbus_ev_win_focusin(ps, w); - else - cdbus_ev_win_focusout(ps, w); - } + // Send D-Bus signal + if (ps->o.dbus) { + if (win_is_focused_real(ps, w)) + cdbus_ev_win_focusin(ps, w); + else + cdbus_ev_win_focusout(ps, w); + } #endif } /** * Set real focused state of a window. */ -void -win_set_focused(session_t *ps, win *w, bool focused) { - // Unmapped windows will have their focused state reset on map - if (w->a.map_state == XCB_MAP_STATE_UNMAPPED) - return; +void win_set_focused(session_t *ps, win *w, bool focused) { + // Unmapped windows will have their focused state reset on map + if (w->a.map_state == XCB_MAP_STATE_UNMAPPED) + return; - if (win_is_focused_real(ps, w) == focused) return; + if (win_is_focused_real(ps, w) == focused) + return; - if (focused) { - if (ps->active_win) - win_set_focused(ps, ps->active_win, false); - ps->active_win = w; - } - else if (w == ps->active_win) - ps->active_win = NULL; + if (focused) { + if (ps->active_win) + win_set_focused(ps, ps->active_win, false); + ps->active_win = w; + } else if (w == ps->active_win) + ps->active_win = NULL; - assert(win_is_focused_real(ps, w) == focused); + assert(win_is_focused_real(ps, w) == focused); - win_on_focus_change(ps, w); + win_on_focus_change(ps, w); } /** @@ -1211,370 +1206,369 @@ win_set_focused(session_t *ps, win *w, bool focused) { * function. */ void win_extents(const win *w, region_t *res) { - pixman_region32_clear(res); - pixman_region32_union_rect(res, res, w->g.x, w->g.y, w->widthb, w->heightb); + pixman_region32_clear(res); + pixman_region32_union_rect(res, res, w->g.x, w->g.y, w->widthb, w->heightb); - if (w->shadow) - pixman_region32_union_rect(res, res, w->g.x + w->shadow_dx, - w->g.y + w->shadow_dy, w->shadow_width, w->shadow_height); + if (w->shadow) + pixman_region32_union_rect(res, res, w->g.x + w->shadow_dx, + 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. - * - * Mark the window shape as updated - */ -void win_update_bounding_shape(session_t *ps, win *w) { - if (ps->shape_exists) - w->bounding_shaped = win_bounding_shaped(ps, w->id); - - pixman_region32_clear(&w->bounding_shape); - // Start with the window rectangular region - win_get_region_local(w, &w->bounding_shape); - - // Only request for a bounding region if the window is shaped - // (while loop is used to avoid goto, not an actual loop) - while (w->bounding_shaped) { - /* - * if window doesn't exist anymore, this will generate an error - * as well as not generate a region. + /** + * Update the out-dated bounding shape of a window. + * + * Mark the window shape as updated */ + void win_update_bounding_shape(session_t *ps, win *w) { + if (ps->shape_exists) + w->bounding_shaped = win_bounding_shaped(ps, w->id); - xcb_shape_get_rectangles_reply_t *r = xcb_shape_get_rectangles_reply(ps->c, - xcb_shape_get_rectangles(ps->c, w->id, XCB_SHAPE_SK_BOUNDING), NULL); + pixman_region32_clear(&w->bounding_shape); + // Start with the window rectangular region + win_get_region_local(w, &w->bounding_shape); - if (!r) - break; + // Only request for a bounding region if the window is shaped + // (while loop is used to avoid goto, not an actual loop) + while (w->bounding_shaped) { + /* + * if window doesn't exist anymore, this will generate an error + * as well as not generate a region. + */ - xcb_rectangle_t *xrects = xcb_shape_get_rectangles_rectangles(r); - int nrects = xcb_shape_get_rectangles_rectangles_length(r); - rect_t *rects = from_x_rects(nrects, xrects); - free(r); + xcb_shape_get_rectangles_reply_t *r = xcb_shape_get_rectangles_reply( + ps->c, xcb_shape_get_rectangles(ps->c, w->id, XCB_SHAPE_SK_BOUNDING), NULL); - region_t br; - pixman_region32_init_rects(&br, rects, nrects); - free(rects); + if (!r) + break; - // Add border width because we are using a different origin. - // X thinks the top left of the inner window is the origin - // (for the bounding shape, althought xcb_get_geometry thinks - // the outer top left (outer means outside of the window - // border) is the origin), - // We think the top left of the border is the origin - pixman_region32_translate(&br, w->g.border_width, w->g.border_width); + xcb_rectangle_t *xrects = xcb_shape_get_rectangles_rectangles(r); + int nrects = xcb_shape_get_rectangles_rectangles_length(r); + rect_t *rects = from_x_rects(nrects, xrects); + free(r); - // Intersect the bounding region we got with the window rectangle, to - // make sure the bounding region is not bigger than the window - // rectangle - pixman_region32_intersect(&w->bounding_shape, &w->bounding_shape, &br); - pixman_region32_fini(&br); - break; - } + region_t br; + pixman_region32_init_rects(&br, rects, nrects); + free(rects); - if (w->bounding_shaped && ps->o.detect_rounded_corners) { - w->rounded_corners = win_has_rounded_corners(w); - } + // Add border width because we are using a different origin. + // X thinks the top left of the inner window is the origin + // (for the bounding shape, althought xcb_get_geometry thinks + // the outer top left (outer means outside of the window + // border) is the origin), + // We think the top left of the border is the origin + pixman_region32_translate(&br, w->g.border_width, w->g.border_width); - // Window shape changed, we should free old wpaint and shadow pict - if (ps->o.experimental_backends) { - //log_trace("free out dated pict"); - // Window shape changed, we should free win_data - if (ps->redirected && w->state != WSTATE_UNMAPPED) { - // Note we only do this when screen is redirected, because - // otherwise win_data is not valid - assert(w->state != WSTATE_UNMAPPING && w->state != WSTATE_DESTROYING); - ps->backend_data->ops->release_image(ps->backend_data, w->win_image); - if (w->shadow_image) { - ps->backend_data->ops->release_image(ps->backend_data, w->shadow_image); - } - auto pixmap = xcb_generate_id(ps->c); - 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); - if (w->shadow) { - w->shadow_image = ps->backend_data->ops->render_shadow(ps->backend_data, w->widthb, - w->heightb, ps->gaussian_map, - ps->o.shadow_red, ps->o.shadow_green, - ps->o.shadow_blue, ps->o.shadow_opacity); - } - } - } else { - free_paint(ps, &w->paint); - free_paint(ps, &w->shadow_paint); - } + // Intersect the bounding region we got with the window rectangle, to + // make sure the bounding region is not bigger than the window + // rectangle + pixman_region32_intersect(&w->bounding_shape, &w->bounding_shape, &br); + pixman_region32_fini(&br); + break; + } - win_on_factor_change(ps, w); + if (w->bounding_shaped && ps->o.detect_rounded_corners) { + w->rounded_corners = win_has_rounded_corners(w); + } + + // Window shape changed, we should free old wpaint and shadow pict + if (ps->o.experimental_backends) { + // log_trace("free out dated pict"); + // Window shape changed, we should free win_data + if (ps->redirected && w->state != WSTATE_UNMAPPED) { + // Note we only do this when screen is redirected, because + // otherwise win_data is not valid + assert(w->state != WSTATE_UNMAPPING && w->state != WSTATE_DESTROYING); + ps->backend_data->ops->release_image(ps->backend_data, w->win_image); + if (w->shadow_image) { + ps->backend_data->ops->release_image(ps->backend_data, + w->shadow_image); + } + auto pixmap = xcb_generate_id(ps->c); + 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); + if (w->shadow) { + w->shadow_image = ps->backend_data->ops->render_shadow( + ps->backend_data, w->widthb, w->heightb, + ps->gaussian_map, ps->o.shadow_red, ps->o.shadow_green, + ps->o.shadow_blue, ps->o.shadow_opacity); + } + } + } else { + free_paint(ps, &w->paint); + free_paint(ps, &w->shadow_paint); + } + + win_on_factor_change(ps, w); } /** * Reread opacity property of a window. */ void win_update_opacity_prop(session_t *ps, win *w) { - // get frame opacity first - w->has_opacity_prop = - wid_get_opacity_prop(ps, w->id, OPAQUE, &w->opacity_prop); + // get frame opacity first + w->has_opacity_prop = wid_get_opacity_prop(ps, w->id, OPAQUE, &w->opacity_prop); - if (w->has_opacity_prop) - // opacity found - return; + if (w->has_opacity_prop) + // opacity found + return; - if (ps->o.detect_client_opacity && w->client_win && w->id == w->client_win) - // checking client opacity not allowed - return; + if (ps->o.detect_client_opacity && w->client_win && w->id == w->client_win) + // checking client opacity not allowed + return; - // get client opacity - w->has_opacity_prop = - wid_get_opacity_prop(ps, w->client_win, OPAQUE, &w->opacity_prop); + // get client opacity + w->has_opacity_prop = + wid_get_opacity_prop(ps, w->client_win, OPAQUE, &w->opacity_prop); } /** * Retrieve frame extents from a window. */ -void -win_update_frame_extents(session_t *ps, win *w, xcb_window_t client) { - winprop_t prop = wid_get_prop(ps, client, ps->atom_frame_extents, - 4L, XCB_ATOM_CARDINAL, 32); +void win_update_frame_extents(session_t *ps, win *w, xcb_window_t client) { + winprop_t prop = + wid_get_prop(ps, client, ps->atom_frame_extents, 4L, XCB_ATOM_CARDINAL, 32); - if (prop.nitems == 4) { - const uint32_t * const extents = prop.c32; - const bool changed = w->frame_extents.left != extents[0] || - w->frame_extents.right != extents[1] || - w->frame_extents.top != extents[2] || - w->frame_extents.bottom != extents[3]; - w->frame_extents.left = extents[0]; - w->frame_extents.right = extents[1]; - w->frame_extents.top = extents[2]; - w->frame_extents.bottom = extents[3]; + if (prop.nitems == 4) { + const uint32_t *const extents = prop.c32; + const bool changed = w->frame_extents.left != extents[0] || + w->frame_extents.right != extents[1] || + w->frame_extents.top != extents[2] || + w->frame_extents.bottom != extents[3]; + w->frame_extents.left = extents[0]; + w->frame_extents.right = extents[1]; + w->frame_extents.top = extents[2]; + w->frame_extents.bottom = extents[3]; - // If frame_opacity != 1, then frame of this window - // is not included in reg_ignore of underneath windows - if (ps->o.frame_opacity == 1 && changed) - w->reg_ignore_valid = false; - } + // If frame_opacity != 1, then frame of this window + // is not included in reg_ignore of underneath windows + if (ps->o.frame_opacity == 1 && changed) + w->reg_ignore_valid = false; + } - log_trace("(%#010x): %d, %d, %d, %d", w->id, - w->frame_extents.left, w->frame_extents.right, - w->frame_extents.top, w->frame_extents.bottom); + log_trace("(%#010x): %d, %d, %d, %d", w->id, w->frame_extents.left, + w->frame_extents.right, w->frame_extents.top, w->frame_extents.bottom); - free_winprop(&prop); + free_winprop(&prop); } bool win_is_region_ignore_valid(session_t *ps, const win *w) { - for(win *i = ps->list; w; w = w->next) { - if (i == w) - break; - if (!i->reg_ignore_valid) - return false; - } - return true; + for (win *i = ps->list; w; w = w->next) { + if (i == w) + break; + if (!i->reg_ignore_valid) + return false; + } + return true; } /** * Stop listening for events on a particular window. */ 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) { - xcb_change_window_attributes(ps->c, w->client_win, XCB_CW_EVENT_MASK, (const uint32_t[]) { 0 }); - } + if (w->client_win) { + xcb_change_window_attributes(ps->c, w->client_win, XCB_CW_EVENT_MASK, + (const uint32_t[]){0}); + } - if (ps->shape_exists) { - xcb_shape_select_input(ps->c, w->id, 0); - } + if (ps->shape_exists) { + xcb_shape_select_input(ps->c, w->id, 0); + } } -static void -finish_unmap_win(session_t *ps, win **_w) { - win *w = *_w; - w->ever_damaged = false; - w->reg_ignore_valid = false; - w->state = WSTATE_UNMAPPED; - w->flags = 0; +static void finish_unmap_win(session_t *ps, win **_w) { + win *w = *_w; + w->ever_damaged = false; + w->reg_ignore_valid = false; + w->state = WSTATE_UNMAPPED; + w->flags = 0; - if (ps->o.experimental_backends) { - // We are in unmap_win, we definitely was viewable - if (ps->redirected) { - assert(w->win_image); - ps->backend_data->ops->release_image(ps->backend_data, w->win_image); - if (w->shadow_image) { - ps->backend_data->ops->release_image(ps->backend_data, w->shadow_image); - } - w->win_image = NULL; - w->shadow_image = NULL; - } - } else { - free_paint(ps, &w->paint); - free_paint(ps, &w->shadow_paint); - } + if (ps->o.experimental_backends) { + // We are in unmap_win, we definitely was viewable + if (ps->redirected) { + assert(w->win_image); + ps->backend_data->ops->release_image(ps->backend_data, w->win_image); + if (w->shadow_image) { + ps->backend_data->ops->release_image(ps->backend_data, + w->shadow_image); + } + w->win_image = NULL; + w->shadow_image = NULL; + } + } else { + free_paint(ps, &w->paint); + free_paint(ps, &w->shadow_paint); + } } -static void -finish_destroy_win(session_t *ps, win **_w) { - win *w = *_w; - win **prev = NULL; +static void finish_destroy_win(session_t *ps, win **_w) { + win *w = *_w; + win **prev = NULL; - if (w->state != WSTATE_UNMAPPED) { - // Only UNMAPPED state has window resources freed, otherwise - // we need to call finish_unmap_win to free them. - finish_unmap_win(ps, _w); - } + if (w->state != WSTATE_UNMAPPED) { + // Only UNMAPPED state has window resources freed, otherwise + // we need to call finish_unmap_win to free them. + finish_unmap_win(ps, _w); + } - // Invalidate reg_ignore of windows below this one - // TODO what if w->next is not mapped?? - // TODO seriously figure out how reg_ignore behaves. - // I think if `w` is unmapped, and destroyed after - // paint happened at least once, w->reg_ignore_valid would - // be true, and there is no need to invalid w->next->reg_ignore - // when w is destroyed. - if (w->next) { - // should be `= w->reg_ignore_valid && w->next->reg_ignore_valid`, - // but keep it this way until we think about reg_ignore. - w->next->reg_ignore_valid = false; - } + // Invalidate reg_ignore of windows below this one + // TODO what if w->next is not mapped?? + // TODO seriously figure out how reg_ignore behaves. + // I think if `w` is unmapped, and destroyed after + // paint happened at least once, w->reg_ignore_valid would + // be true, and there is no need to invalid w->next->reg_ignore + // when w is destroyed. + if (w->next) { + // should be `= w->reg_ignore_valid && w->next->reg_ignore_valid`, + // but keep it this way until we think about reg_ignore. + w->next->reg_ignore_valid = false; + } - log_trace("Trying to destroy (%#010x)", w->id); - for (prev = &ps->list; *prev; prev = &(*prev)->next) { - if (w == *prev) { - log_trace("Found (%#010x \"%s\")", w->id, w->name); - *prev = w->next; + log_trace("Trying to destroy (%#010x)", w->id); + for (prev = &ps->list; *prev; prev = &(*prev)->next) { + if (w == *prev) { + log_trace("Found (%#010x \"%s\")", w->id, w->name); + *prev = w->next; - if (w == ps->active_win) { - ps->active_win = NULL; - } + if (w == ps->active_win) { + ps->active_win = NULL; + } - if (!ps->o.experimental_backends) { - free_win_res(ps, w); - } + if (!ps->o.experimental_backends) { + free_win_res(ps, w); + } - // Drop w from all prev_trans to avoid accessing freed memory in - // repair_win() - // TODO there can only be one prev_trans pointing to w - for (win *w2 = ps->list; w2; w2 = w2->next) { - if (w == w2->prev_trans) { - w2->prev_trans = NULL; - } - } - free(w); - *_w = NULL; - return; - } - } - log_warn("Destroyed window is not in window list"); - assert(false); + // Drop w from all prev_trans to avoid accessing freed memory in + // repair_win() + // TODO there can only be one prev_trans pointing to w + for (win *w2 = ps->list; w2; w2 = w2->next) { + if (w == w2->prev_trans) { + w2->prev_trans = NULL; + } + } + free(w); + *_w = NULL; + return; + } + } + log_warn("Destroyed window is not in window list"); + assert(false); } -static void -finish_map_win(session_t *ps, win **_w) { - win *w = *_w; - w->in_openclose = false; - w->state = WSTATE_MAPPED; +static void finish_map_win(session_t *ps, win **_w) { + win *w = *_w; + w->in_openclose = false; + w->state = WSTATE_MAPPED; } -void -unmap_win(session_t *ps, win **_w, bool destroy) { - win *w = *_w; +void unmap_win(session_t *ps, win **_w, bool destroy) { + win *w = *_w; - winstate_t target_state = destroy ? WSTATE_DESTROYING : WSTATE_UNMAPPING; + winstate_t target_state = destroy ? WSTATE_DESTROYING : WSTATE_UNMAPPING; - if (unlikely(!w)) { - return; - } + if (unlikely(!w)) { + return; + } - if (!destroy && w->a._class == XCB_WINDOW_CLASS_INPUT_ONLY) { - // We don't care about mapping / unmapping of Input Only windows. - // But we need to remember to destroy them, so future window with - // the same id won't be handled incorrectly. - // Issue #119 was caused by this. - return; - } + if (!destroy && w->a._class == XCB_WINDOW_CLASS_INPUT_ONLY) { + // We don't care about mapping / unmapping of Input Only windows. + // But we need to remember to destroy them, so future window with + // the same id won't be handled incorrectly. + // Issue #119 was caused by this. + return; + } - log_trace("Unmapping %#010x \"%s\", destroy = %d", w->id, (w ? w->name: NULL), destroy); + log_trace("Unmapping %#010x \"%s\", destroy = %d", w->id, (w ? w->name : NULL), destroy); - if (unlikely(w->state == WSTATE_DESTROYING && !destroy)) { - log_warn("Trying to undestroy a window?"); - assert(false); - } + if (unlikely(w->state == WSTATE_DESTROYING && !destroy)) { + log_warn("Trying to undestroy a window?"); + assert(false); + } - // If the window is already in the state we want - if (unlikely(w->state == target_state)) { - log_warn("%s a window twice", destroy ? "Destroying" : "Unmapping"); - return; - } + // If the window is already in the state we want + if (unlikely(w->state == target_state)) { + log_warn("%s a window twice", destroy ? "Destroying" : "Unmapping"); + return; + } - if (unlikely(w->state == WSTATE_UNMAPPED) || w->a._class == XCB_WINDOW_CLASS_INPUT_ONLY) { - if (unlikely(!destroy)) { - log_warn("Unmapping an already unmapped window %#010x %s twice", w->id, w->name); - return; - } - // Window is already unmapped, or is an Input Only window, just destroy it - finish_destroy_win(ps, _w); - return; - } + if (unlikely(w->state == WSTATE_UNMAPPED) || w->a._class == XCB_WINDOW_CLASS_INPUT_ONLY) { + if (unlikely(!destroy)) { + log_warn("Unmapping an already unmapped window %#010x %s twice", + w->id, w->name); + return; + } + // Window is already unmapped, or is an Input Only window, just destroy it + finish_destroy_win(ps, _w); + return; + } - // Set focus out - win_set_focused(ps, w, false); + // Set focus out + win_set_focused(ps, w, false); - w->a.map_state = XCB_MAP_STATE_UNMAPPED; - w->state = target_state; - w->opacity_tgt = win_calc_opacity_target(ps, w); + w->a.map_state = XCB_MAP_STATE_UNMAPPED; + w->state = target_state; + w->opacity_tgt = win_calc_opacity_target(ps, w); - w->in_openclose = destroy; + w->in_openclose = destroy; - // don't care about properties anymore - if (!destroy) { - win_ev_stop(ps, w); - } + // don't care about properties anymore + if (!destroy) { + win_ev_stop(ps, w); + } #ifdef CONFIG_DBUS - // Send D-Bus signal - if (ps->o.dbus) { - if (destroy) { - cdbus_ev_win_destroyed(ps, w); - } else { - cdbus_ev_win_unmapped(ps, w); - } - } + // Send D-Bus signal + if (ps->o.dbus) { + if (destroy) { + cdbus_ev_win_destroyed(ps, w); + } else { + cdbus_ev_win_unmapped(ps, w); + } + } #endif - if (!ps->redirected) { - win_skip_fading(ps, _w); - } + if (!ps->redirected) { + win_skip_fading(ps, _w); + } } /** * Execute fade callback of a window if fading finished. */ -void -win_check_fade_finished(session_t *ps, win **_w) { - win *w = *_w; - if (w->state == WSTATE_MAPPED || w->state == WSTATE_UNMAPPED) { - // No fading in progress - assert(w->opacity_tgt == w->opacity); - return; - } - if (w->opacity == w->opacity_tgt) { - switch (w->state) { - case WSTATE_UNMAPPING: return finish_unmap_win(ps, _w); - case WSTATE_DESTROYING: return finish_destroy_win(ps, _w); - case WSTATE_MAPPING: return finish_map_win(ps, _w); - case WSTATE_FADING: w->state = WSTATE_MAPPED; break; - default: unreachable; - } - } +void win_check_fade_finished(session_t *ps, win **_w) { + win *w = *_w; + if (w->state == WSTATE_MAPPED || w->state == WSTATE_UNMAPPED) { + // No fading in progress + assert(w->opacity_tgt == w->opacity); + return; + } + if (w->opacity == w->opacity_tgt) { + switch (w->state) { + case WSTATE_UNMAPPING: return finish_unmap_win(ps, _w); + case WSTATE_DESTROYING: return finish_destroy_win(ps, _w); + case WSTATE_MAPPING: return finish_map_win(ps, _w); + case WSTATE_FADING: w->state = WSTATE_MAPPED; break; + default: unreachable; + } + } } /// Skip the current in progress fading of window, /// transition the window straight to its end state void win_skip_fading(session_t *ps, win **_w) { - win *w = *_w; - if (w->state == WSTATE_MAPPED || w->state == WSTATE_UNMAPPED) { - assert(w->opacity_tgt == w->opacity); - return; - } - w->opacity = w->opacity_tgt; - win_check_fade_finished(ps, _w); + win *w = *_w; + if (w->state == WSTATE_MAPPED || w->state == WSTATE_UNMAPPED) { + assert(w->opacity_tgt == w->opacity); + return; + } + w->opacity = w->opacity_tgt; + win_check_fade_finished(ps, _w); } /** @@ -1586,22 +1580,23 @@ void win_skip_fading(session_t *ps, win **_w) { * TODO use xrandr */ void win_update_screen(session_t *ps, win *w) { - w->xinerama_scr = -1; + w->xinerama_scr = -1; - if (!ps->xinerama_scrs) - return; + if (!ps->xinerama_scrs) + return; - 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); - for (int i = 0; i < length; i++) { - xcb_xinerama_screen_info_t *s = &scrs[i]; - if (s->x_org <= w->g.x && s->y_org <= w->g.y - && s->x_org + s->width >= w->g.x + w->widthb - && s->y_org + s->height >= w->g.y + w->heightb) { - w->xinerama_scr = i; - return; - } - } + 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); + for (int i = 0; i < length; i++) { + xcb_xinerama_screen_info_t *s = &scrs[i]; + if (s->x_org <= w->g.x && s->y_org <= w->g.y && + s->x_org + s->width >= w->g.x + w->widthb && + s->y_org + s->height >= w->g.y + w->heightb) { + w->xinerama_scr = i; + return; + } + } } // TODO remove this @@ -1609,140 +1604,141 @@ void configure_win(session_t *, xcb_configure_notify_event_t *); /// Map an already registered window void map_win(session_t *ps, win *w) { - assert(w); + assert(w); - // Don't care about window mapping if it's an InputOnly window - // Also, try avoiding mapping a window twice - if (w->a._class == XCB_WINDOW_CLASS_INPUT_ONLY) { - return; - } + // Don't care about window mapping if it's an InputOnly window + // Also, try avoiding mapping a window twice + if (w->a._class == XCB_WINDOW_CLASS_INPUT_ONLY) { + return; + } - log_debug("Mapping (%#010x \"%s\")", w->id, w->name); + log_debug("Mapping (%#010x \"%s\")", w->id, w->name); - if (w->state != WSTATE_UNMAPPED && w->state != WSTATE_UNMAPPING) { - log_warn("Mapping an already mapped window"); - return; - } + if (w->state != WSTATE_UNMAPPED && w->state != WSTATE_UNMAPPING) { + log_warn("Mapping an already mapped window"); + return; + } - // XXX ??? - assert(!win_is_focused_real(ps, w)); + // XXX ??? + assert(!win_is_focused_real(ps, w)); - // XXX Can we assume map_state is always viewable? - w->a.map_state = XCB_MAP_STATE_VIEWABLE; + // XXX Can we assume map_state is always viewable? + w->a.map_state = XCB_MAP_STATE_VIEWABLE; - win_update_screen(ps, w); + win_update_screen(ps, w); - // Set window event mask before reading properties so that no property - // changes are lost - xcb_change_window_attributes(ps->c, w->id, XCB_CW_EVENT_MASK, - (const uint32_t[]) { determine_evmask(ps, w->id, WIN_EVMODE_FRAME) }); + // Set window event mask before reading properties so that no property + // changes are lost + xcb_change_window_attributes( + ps->c, w->id, XCB_CW_EVENT_MASK, + (const uint32_t[]){determine_evmask(ps, w->id, WIN_EVMODE_FRAME)}); - // Notify compton when the shape of a window changes - if (ps->shape_exists) { - xcb_shape_select_input(ps->c, w->id, 1); - } + // Notify compton when the shape of a window changes + if (ps->shape_exists) { + xcb_shape_select_input(ps->c, w->id, 1); + } - // Update window mode here to check for ARGB windows - w->mode = win_calc_mode(w); + // Update window mode here to check for ARGB windows + w->mode = win_calc_mode(w); - // Detect client window here instead of in add_win() as the client - // window should have been prepared at this point - if (!w->client_win) { - win_recheck_client(ps, w); - } else { - // Re-mark client window here - win_mark_client(ps, w, w->client_win); - } - assert(w->client_win); + // Detect client window here instead of in add_win() as the client + // window should have been prepared at this point + if (!w->client_win) { + win_recheck_client(ps, w); + } else { + // Re-mark client window here + win_mark_client(ps, w, w->client_win); + } + assert(w->client_win); - log_debug("Window (%#010x) has type %s", w->id, WINTYPES[w->window_type]); + log_debug("Window (%#010x) has type %s", w->id, WINTYPES[w->window_type]); - // Update window focus state - win_update_focused(ps, w); + // Update window focus state + win_update_focused(ps, w); - // Update opacity and dim state - win_update_opacity_prop(ps, w); + // Update opacity and dim state + win_update_opacity_prop(ps, w); - // Check for _COMPTON_SHADOW - if (ps->o.respect_prop_shadow) { - win_update_prop_shadow_raw(ps, w); - } + // Check for _COMPTON_SHADOW + if (ps->o.respect_prop_shadow) { + win_update_prop_shadow_raw(ps, w); + } - // Many things above could affect shadow - win_determine_shadow(ps, w); + // Many things above could affect shadow + win_determine_shadow(ps, w); - // XXX We need to make sure that win_data is available - // iff `state` is MAPPED - w->state = WSTATE_MAPPING; - w->opacity_tgt = win_calc_opacity_target(ps, w); + // XXX We need to make sure that win_data is available + // iff `state` is MAPPED + w->state = WSTATE_MAPPING; + w->opacity_tgt = win_calc_opacity_target(ps, w); - // TODO win_update_bounding_shape below will immediately - // reinit w->win_data, not very efficient - if (ps->redirected && ps->o.experimental_backends) { - auto pixmap = xcb_generate_id(ps->c); - 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); - if (w->shadow) { - w->shadow_image = - ps->backend_data->ops->render_shadow(ps->backend_data, w->widthb, - w->heightb, ps->gaussian_map, - ps->o.shadow_red, ps->o.shadow_green, - 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); + // TODO win_update_bounding_shape below will immediately + // reinit w->win_data, not very efficient + if (ps->redirected && ps->o.experimental_backends) { + auto pixmap = xcb_generate_id(ps->c); + 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); + if (w->shadow) { + w->shadow_image = ps->backend_data->ops->render_shadow( + ps->backend_data, w->widthb, w->heightb, ps->gaussian_map, + ps->o.shadow_red, ps->o.shadow_green, 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); - win_determine_blur_background(ps, w); + win_determine_blur_background(ps, w); - w->ever_damaged = false; + w->ever_damaged = false; - /* if any configure events happened while - the window was unmapped, then configure - the window to its correct place */ - if (w->need_configure) { - configure_win(ps, &w->queue_configure); - } + /* if any configure events happened while + the window was unmapped, then configure + the window to its correct place */ + if (w->need_configure) { + configure_win(ps, &w->queue_configure); + } - // We stopped listening on ShapeNotify events - // when the window is unmapped (XXX we shouldn't), - // so the shape of the window might have changed, - // update. (Issue #35) - win_update_bounding_shape(ps, w); + // We stopped listening on ShapeNotify events + // when the window is unmapped (XXX we shouldn't), + // so the shape of the window might have changed, + // update. (Issue #35) + win_update_bounding_shape(ps, w); #ifdef CONFIG_DBUS - // Send D-Bus signal - if (ps->o.dbus) { - cdbus_ev_win_mapped(ps, w); - } + // Send D-Bus signal + if (ps->o.dbus) { + cdbus_ev_win_mapped(ps, w); + } #endif - if (!ps->redirected) { - win_skip_fading(ps, &w); - assert(w); - } + if (!ps->redirected) { + win_skip_fading(ps, &w); + assert(w); + } } void map_win_by_id(session_t *ps, xcb_window_t id) { - // Unmap overlay window if it got mapped but we are currently not - // in redirected state. - if (ps->overlay && id == ps->overlay && !ps->redirected) { - log_debug("Overlay is mapped while we are not redirected"); - auto e = xcb_request_check(ps->c, xcb_unmap_window(ps->c, ps->overlay)); - if (e) { - log_error("Failed to unmap the overlay window"); - free(e); - } - // We don't track the overlay window, so we can return - return; - } + // Unmap overlay window if it got mapped but we are currently not + // in redirected state. + if (ps->overlay && id == ps->overlay && !ps->redirected) { + log_debug("Overlay is mapped while we are not redirected"); + auto e = xcb_request_check(ps->c, xcb_unmap_window(ps->c, ps->overlay)); + if (e) { + log_error("Failed to unmap the overlay window"); + free(e); + } + // We don't track the overlay window, so we can return + return; + } - win *w = find_win(ps, id); - if (!w) { - return; - } + win *w = find_win(ps, id); + if (!w) { + return; + } - map_win(ps, w); + map_win(ps, w); } - // vim: set et sw=2 : diff --git a/src/win.h b/src/win.h index 88f9b71..dcaf422 100644 --- a/src/win.h +++ b/src/win.h @@ -3,22 +3,22 @@ // Copyright (c) 2013 Richard Grenville #pragma once #include -#include -#include #include +#include +#include // FIXME shouldn't need this #ifdef CONFIG_OPENGL #include #endif -#include "x.h" +#include "c2.h" #include "compiler.h" #include "region.h" -#include "types.h" -#include "c2.h" #include "render.h" +#include "types.h" #include "utils.h" +#include "x.h" typedef struct session session_t; typedef struct _glx_texture glx_texture_t; @@ -27,41 +27,41 @@ typedef struct _glx_texture glx_texture_t; // FIXME this type should be in opengl.h // it is very unideal for it to be here typedef struct { - /// Framebuffer used for blurring. - GLuint fbo; - /// Textures used for blurring. - GLuint textures[2]; - /// Width of the textures. - int width; - /// Height of the textures. - int height; + /// Framebuffer used for blurring. + GLuint fbo; + /// Textures used for blurring. + GLuint textures[2]; + /// Width of the textures. + int width; + /// Height of the textures. + int height; } glx_blur_cache_t; #endif typedef enum { - WINTYPE_UNKNOWN, - WINTYPE_DESKTOP, - WINTYPE_DOCK, - WINTYPE_TOOLBAR, - WINTYPE_MENU, - WINTYPE_UTILITY, - WINTYPE_SPLASH, - WINTYPE_DIALOG, - WINTYPE_NORMAL, - WINTYPE_DROPDOWN_MENU, - WINTYPE_POPUP_MENU, - WINTYPE_TOOLTIP, - WINTYPE_NOTIFY, - WINTYPE_COMBO, - WINTYPE_DND, - NUM_WINTYPES + WINTYPE_UNKNOWN, + WINTYPE_DESKTOP, + WINTYPE_DOCK, + WINTYPE_TOOLBAR, + WINTYPE_MENU, + WINTYPE_UTILITY, + WINTYPE_SPLASH, + WINTYPE_DIALOG, + WINTYPE_NORMAL, + WINTYPE_DROPDOWN_MENU, + WINTYPE_POPUP_MENU, + WINTYPE_TOOLTIP, + WINTYPE_NOTIFY, + WINTYPE_COMBO, + WINTYPE_DND, + NUM_WINTYPES } wintype_t; /// Enumeration type of window painting mode. typedef enum { - WMODE_TRANS, // The window body is (potentially) transparent - WMODE_FRAME_TRANS, // The window body is opaque, but the frame is not - WMODE_SOLID, // The window is opaque including the frame + WMODE_TRANS, // The window body is (potentially) transparent + WMODE_FRAME_TRANS, // The window body is opaque, but the frame is not + WMODE_SOLID, // The window is opaque including the frame } winmode_t; /// Transition table: @@ -90,18 +90,18 @@ typedef enum { /// | |unmapped |destroyed | |change | | | | /// +-------------+---------+----------+-------+-------+--------+--------+---------+ typedef enum { - // The window is being faded out because it's unmapped. - WSTATE_UNMAPPING, - // The window is being faded out because it's destroyed, - WSTATE_DESTROYING, - // The window is being faded in - WSTATE_MAPPING, - // Window opacity is not at the target level - WSTATE_FADING, - // The window is mapped, no fading is in progress. - WSTATE_MAPPED, - // The window is unmapped, no fading is in progress. - WSTATE_UNMAPPED, + // The window is being faded out because it's unmapped. + WSTATE_UNMAPPING, + // The window is being faded out because it's destroyed, + WSTATE_DESTROYING, + // The window is being faded in + WSTATE_MAPPING, + // Window opacity is not at the target level + WSTATE_FADING, + // The window is mapped, no fading is in progress. + WSTATE_MAPPED, + // The window is unmapped, no fading is in progress. + WSTATE_UNMAPPED, } winstate_t; /** @@ -118,167 +118,167 @@ typedef enum { /// Structure representing a top-level window compton manages. typedef struct win win; struct win { - /// backend data attached to this window. Only available when - /// `state` is not UNMAPPED - void *win_image; - void *shadow_image; - /// Pointer to the next lower window in window stack. - win *next; - /// Pointer to the next higher window to paint. - win *prev_trans; - // TODO rethink reg_ignore + /// backend data attached to this window. Only available when + /// `state` is not UNMAPPED + void *win_image; + void *shadow_image; + /// Pointer to the next lower window in window stack. + win *next; + /// Pointer to the next higher window to paint. + win *prev_trans; + // TODO rethink reg_ignore - // Core members - /// ID of the top-level frame window. - xcb_window_t id; - /// The "mapped state" of this window, doesn't necessary - /// match X mapped state, because of fading. - winstate_t state; - /// Window attributes. - xcb_get_window_attributes_reply_t a; - xcb_get_geometry_reply_t g; - /// Xinerama screen this window is on. - int xinerama_scr; - /// Window visual pict format; - const xcb_render_pictforminfo_t *pictfmt; - /// Window painting mode. - winmode_t mode; - /// Whether the window has been damaged at least once. - bool ever_damaged; - /// Whether the window was damaged after last paint. - bool pixmap_damaged; - /// Damage of the window. - xcb_damage_damage_t damage; - /// Paint info of the window. - paint_t paint; + // Core members + /// ID of the top-level frame window. + xcb_window_t id; + /// The "mapped state" of this window, doesn't necessary + /// match X mapped state, because of fading. + winstate_t state; + /// Window attributes. + xcb_get_window_attributes_reply_t a; + xcb_get_geometry_reply_t g; + /// Xinerama screen this window is on. + int xinerama_scr; + /// Window visual pict format; + const xcb_render_pictforminfo_t *pictfmt; + /// Window painting mode. + winmode_t mode; + /// Whether the window has been damaged at least once. + bool ever_damaged; + /// Whether the window was damaged after last paint. + bool pixmap_damaged; + /// Damage of the window. + xcb_damage_damage_t damage; + /// Paint info of the window. + paint_t paint; - /// Bounding shape of the window. In local coordinates. - /// See above about coordinate systems. - region_t bounding_shape; - /// Window flags. Definitions above. - int_fast16_t flags; - /// Whether there's a pending ConfigureNotify happening - /// when the window is unmapped. - bool need_configure; - /// Queued ConfigureNotify when the window is unmapped. - xcb_configure_notify_event_t queue_configure; - /// The region of screen that will be obscured when windows above is painted, - /// in global coordinates. - /// We use this to reduce the pixels that needed to be paint when painting - /// this window and anything underneath. Depends on window frame - /// opacity state, window geometry, window mapped/unmapped state, - /// window mode of the windows above. DOES NOT INCLUDE the body of THIS WINDOW. - /// NULL means reg_ignore has not been calculated for this window. - rc_region_t *reg_ignore; - /// Whether the reg_ignore of all windows beneath this window are valid - bool reg_ignore_valid; - /// Cached width/height of the window including border. - int widthb, heightb; - /// Whether the window is bounding-shaped. - bool bounding_shaped; - /// Whether the window just have rounded corners. - bool rounded_corners; - /// Whether this window is to be painted. - bool to_paint; - /// Whether the window is painting excluded. - bool paint_excluded; - /// Whether the window is unredirect-if-possible excluded. - bool unredir_if_possible_excluded; - /// Whether this window is in open/close state. - bool in_openclose; + /// Bounding shape of the window. In local coordinates. + /// See above about coordinate systems. + region_t bounding_shape; + /// Window flags. Definitions above. + int_fast16_t flags; + /// Whether there's a pending ConfigureNotify happening + /// when the window is unmapped. + bool need_configure; + /// Queued ConfigureNotify when the window is unmapped. + xcb_configure_notify_event_t queue_configure; + /// The region of screen that will be obscured when windows above is painted, + /// in global coordinates. + /// We use this to reduce the pixels that needed to be paint when painting + /// this window and anything underneath. Depends on window frame + /// opacity state, window geometry, window mapped/unmapped state, + /// window mode of the windows above. DOES NOT INCLUDE the body of THIS WINDOW. + /// NULL means reg_ignore has not been calculated for this window. + rc_region_t *reg_ignore; + /// Whether the reg_ignore of all windows beneath this window are valid + bool reg_ignore_valid; + /// Cached width/height of the window including border. + int widthb, heightb; + /// Whether the window is bounding-shaped. + bool bounding_shaped; + /// Whether the window just have rounded corners. + bool rounded_corners; + /// Whether this window is to be painted. + bool to_paint; + /// Whether the window is painting excluded. + bool paint_excluded; + /// Whether the window is unredirect-if-possible excluded. + bool unredir_if_possible_excluded; + /// Whether this window is in open/close state. + bool in_openclose; - // Client window related members - /// ID of the top-level client window of the window. - xcb_window_t client_win; - /// Type of the window. - wintype_t window_type; - /// Whether it looks like a WM window. We consider a window WM window if - /// it does not have a decedent with WM_STATE and it is not override- - /// redirected itself. - bool wmwin; - /// Leader window ID of the window. - xcb_window_t leader; - /// Cached topmost window ID of the window. - xcb_window_t cache_leader; + // Client window related members + /// ID of the top-level client window of the window. + xcb_window_t client_win; + /// Type of the window. + wintype_t window_type; + /// Whether it looks like a WM window. We consider a window WM window if + /// it does not have a decedent with WM_STATE and it is not override- + /// redirected itself. + bool wmwin; + /// Leader window ID of the window. + xcb_window_t leader; + /// Cached topmost window ID of the window. + xcb_window_t cache_leader; - // Focus-related members - /// Whether the window is to be considered focused. - bool focused; - /// Override value of window focus state. Set by D-Bus method calls. - switch_t focused_force; + // Focus-related members + /// Whether the window is to be considered focused. + bool focused; + /// Override value of window focus state. Set by D-Bus method calls. + switch_t focused_force; - // Blacklist related members - /// Name of the window. - char *name; - /// Window instance class of the window. - char *class_instance; - /// Window general class of the window. - char *class_general; - /// WM_WINDOW_ROLE value of the window. - char *role; + // Blacklist related members + /// Name of the window. + char *name; + /// Window instance class of the window. + char *class_instance; + /// Window general class of the window. + char *class_general; + /// WM_WINDOW_ROLE value of the window. + char *role; - // Opacity-related members - /// Current window opacity. - double opacity; - /// Target window opacity. - double opacity_tgt; - /// true if window (or client window, for broken window managers - /// not transferring client window's _NET_WM_OPACITY value) has opacity prop - bool has_opacity_prop; - /// Cached value of opacity window attribute. - opacity_t opacity_prop; - /// true if opacity is set by some rules - bool opacity_is_set; - /// Last window opacity value we set. - double opacity_set; + // Opacity-related members + /// Current window opacity. + double opacity; + /// Target window opacity. + double opacity_tgt; + /// true if window (or client window, for broken window managers + /// not transferring client window's _NET_WM_OPACITY value) has opacity prop + bool has_opacity_prop; + /// Cached value of opacity window attribute. + opacity_t opacity_prop; + /// true if opacity is set by some rules + bool opacity_is_set; + /// Last window opacity value we set. + double opacity_set; - // Fading-related members - /// Override value of window fade state. Set by D-Bus method calls. - switch_t fade_force; + // Fading-related members + /// Override value of window fade state. Set by D-Bus method calls. + switch_t fade_force; - // Frame-opacity-related members - /// Current window frame opacity. Affected by window opacity. - double frame_opacity; - /// Frame extents. Acquired from _NET_FRAME_EXTENTS. - margin_t frame_extents; + // Frame-opacity-related members + /// Current window frame opacity. Affected by window opacity. + double frame_opacity; + /// Frame extents. Acquired from _NET_FRAME_EXTENTS. + margin_t frame_extents; - // Shadow-related members - /// Whether a window has shadow. Calculated. - bool shadow; - /// Override value of window shadow state. Set by D-Bus method calls. - switch_t shadow_force; - /// Opacity of the shadow. Affected by window opacity and frame opacity. - double shadow_opacity; - /// X offset of shadow. Affected by commandline argument. - int shadow_dx; - /// Y offset of shadow. Affected by commandline argument. - int shadow_dy; - /// Width of shadow. Affected by window size and commandline argument. - int shadow_width; - /// Height of shadow. Affected by window size and commandline argument. - int shadow_height; - /// Picture to render shadow. Affected by window size. - paint_t shadow_paint; - /// The value of _COMPTON_SHADOW attribute of the window. Below 0 for - /// none. - long prop_shadow; + // Shadow-related members + /// Whether a window has shadow. Calculated. + bool shadow; + /// Override value of window shadow state. Set by D-Bus method calls. + switch_t shadow_force; + /// Opacity of the shadow. Affected by window opacity and frame opacity. + double shadow_opacity; + /// X offset of shadow. Affected by commandline argument. + int shadow_dx; + /// Y offset of shadow. Affected by commandline argument. + int shadow_dy; + /// Width of shadow. Affected by window size and commandline argument. + int shadow_width; + /// Height of shadow. Affected by window size and commandline argument. + int shadow_height; + /// Picture to render shadow. Affected by window size. + paint_t shadow_paint; + /// The value of _COMPTON_SHADOW attribute of the window. Below 0 for + /// none. + long prop_shadow; - // Dim-related members - /// Whether the window is to be dimmed. - bool dim; + // Dim-related members + /// Whether the window is to be dimmed. + bool dim; - /// Whether to invert window color. - bool invert_color; - /// Override value of window color inversion state. Set by D-Bus method - /// calls. - switch_t invert_color_force; + /// Whether to invert window color. + bool invert_color; + /// Override value of window color inversion state. Set by D-Bus method + /// calls. + switch_t invert_color_force; - /// Whether to blur window background. - bool blur_background; + /// Whether to blur window background. + bool blur_background; #ifdef CONFIG_OPENGL - /// Textures and FBO background blur use. - glx_blur_cache_t glx_blur_cache; + /// Textures and FBO background blur use. + glx_blur_cache_t glx_blur_cache; #endif }; @@ -363,8 +363,7 @@ region_t win_get_region_frame_local_by_val(const win *w); /** * Retrieve frame extents from a window. */ -void -win_update_frame_extents(session_t *ps, win *w, xcb_window_t client); +void 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); /// Unmap or destroy a window 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. */ -void -win_check_fade_finished(session_t *ps, win **_w); +void win_check_fade_finished(session_t *ps, win **_w); // Stop receiving events (except ConfigureNotify, XXX why?) from a window void win_ev_stop(session_t *ps, const win *w); @@ -390,9 +388,8 @@ void win_skip_fading(session_t *ps, win **_w); * * This function updates w->cache_leader if necessary. */ -static inline xcb_window_t -win_get_leader(session_t *ps, win *w) { - return win_get_leader_raw(ps, w, 0); +static inline xcb_window_t win_get_leader(session_t *ps, win *w) { + return win_get_leader_raw(ps, w, 0); } /// check if window has ARGB visual @@ -404,35 +401,31 @@ bool attr_pure win_is_region_ignore_valid(session_t *ps, const win *w); /// Free all resources in a struct win void free_win_res(session_t *ps, win *w); -static inline region_t -win_get_bounding_shape_global_by_val(win *w) { - region_t ret; - pixman_region32_init(&ret); - pixman_region32_copy(&ret, &w->bounding_shape); - pixman_region32_translate(&ret, w->g.x, w->g.y); - return ret; +static inline region_t win_get_bounding_shape_global_by_val(win *w) { + region_t ret; + pixman_region32_init(&ret); + pixman_region32_copy(&ret, &w->bounding_shape); + pixman_region32_translate(&ret, w->g.x, w->g.y); + return ret; } /** * Calculate the extents of the frame of the given window based on EWMH * _NET_FRAME_EXTENTS and the X window border width. */ -static inline margin_t attr_pure -win_calc_frame_extents(const win *w) { - margin_t result = w->frame_extents; - result.top = max_i(result.top, w->g.border_width); - result.left = max_i(result.left, w->g.border_width); - result.bottom = max_i(result.bottom, w->g.border_width); - result.right = max_i(result.right, w->g.border_width); - return result; +static inline margin_t attr_pure win_calc_frame_extents(const win *w) { + margin_t result = w->frame_extents; + result.top = max_i(result.top, w->g.border_width); + result.left = max_i(result.left, w->g.border_width); + result.bottom = max_i(result.bottom, w->g.border_width); + result.right = max_i(result.right, w->g.border_width); + return result; } /** * Check whether a window has WM frames. */ -static inline bool attr_pure -win_has_frame(const win *w) { - return w->g.border_width - || w->frame_extents.top || w->frame_extents.left - || w->frame_extents.right || w->frame_extents.bottom; +static inline bool attr_pure win_has_frame(const win *w) { + return w->g.border_width || w->frame_extents.top || w->frame_extents.left || + w->frame_extents.right || w->frame_extents.bottom; } diff --git a/src/x.c b/src/x.c index 663a986..857dd54 100644 --- a/src/x.c +++ b/src/x.c @@ -4,23 +4,23 @@ #include #include -#include -#include -#include -#include +#include #include #include #include -#include +#include +#include +#include +#include -#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 "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. @@ -37,34 +37,28 @@ * @return a winprop_t structure containing the attribute * and number of items. A blank one on failure. */ -winprop_t -wid_get_prop_adv(const session_t *ps, xcb_window_t w, xcb_atom_t atom, long offset, - long length, xcb_atom_t rtype, int rformat) { - xcb_get_property_reply_t *r = xcb_get_property_reply(ps->c, - xcb_get_property(ps->c, 0, w, atom, rtype, offset, length), NULL); +winprop_t wid_get_prop_adv(const session_t *ps, xcb_window_t w, xcb_atom_t atom, + long offset, long length, xcb_atom_t rtype, int rformat) { + xcb_get_property_reply_t *r = xcb_get_property_reply( + ps->c, xcb_get_property(ps->c, 0, w, atom, rtype, offset, length), NULL); - if (r && xcb_get_property_value_length(r) && - (rtype == XCB_GET_PROPERTY_TYPE_ANY || r->type == rtype) && - (!rformat || r->format == rformat) && - (r->format == 8 || r->format == 16 || r->format == 32)) - { - int len = xcb_get_property_value_length(r); - return (winprop_t) { - .ptr = xcb_get_property_value(r), - .nitems = len/(r->format/8), - .type = r->type, - .format = r->format, - .r = r, - }; - } + if (r && xcb_get_property_value_length(r) && + (rtype == XCB_GET_PROPERTY_TYPE_ANY || r->type == rtype) && + (!rformat || r->format == rformat) && + (r->format == 8 || r->format == 16 || r->format == 32)) { + int len = xcb_get_property_value_length(r); + return (winprop_t){ + .ptr = xcb_get_property_value(r), + .nitems = len / (r->format / 8), + .type = r->type, + .format = r->format, + .r = r, + }; + } - free(r); - return (winprop_t) { - .ptr = NULL, - .nitems = 0, - .type = XCB_GET_PROPERTY_TYPE_ANY, - .format = 0 - }; + free(r); + return (winprop_t){ + .ptr = NULL, .nitems = 0, .type = XCB_GET_PROPERTY_TYPE_ANY, .format = 0}; } /** @@ -72,44 +66,42 @@ 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 */ -xcb_window_t -wid_get_prop_window(session_t *ps, xcb_window_t wid, xcb_atom_t aprop) { - // Get the attribute - xcb_window_t p = XCB_NONE; - winprop_t prop = wid_get_prop(ps, wid, aprop, 1L, XCB_ATOM_WINDOW, 32); +xcb_window_t wid_get_prop_window(session_t *ps, xcb_window_t wid, xcb_atom_t aprop) { + // Get the attribute + xcb_window_t p = XCB_NONE; + winprop_t prop = wid_get_prop(ps, wid, aprop, 1L, XCB_ATOM_WINDOW, 32); - // Return it - if (prop.nitems) { - p = *prop.p32; - } + // Return it + if (prop.nitems) { + p = *prop.p32; + } - free_winprop(&prop); + free_winprop(&prop); - return p; + return p; } /** * 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, - char ***pstrlst, int *pnstr) { - XTextProperty text_prop = { NULL, XCB_NONE, 0, 0 }; +bool wid_get_text_prop(session_t *ps, xcb_window_t wid, xcb_atom_t prop, char ***pstrlst, + int *pnstr) { + XTextProperty text_prop = {NULL, XCB_NONE, 0, 0}; - if (!(XGetTextProperty(ps->dpy, wid, &text_prop, prop) && text_prop.value)) - return false; + if (!(XGetTextProperty(ps->dpy, wid, &text_prop, prop) && text_prop.value)) + return false; - if (Success != - XmbTextPropertyToTextList(ps->dpy, &text_prop, pstrlst, pnstr) - || !*pnstr) { - *pnstr = 0; - if (*pstrlst) - XFreeStringList(*pstrlst); - cxfree(text_prop.value); - return false; - } + if (Success != XmbTextPropertyToTextList(ps->dpy, &text_prop, pstrlst, pnstr) || + !*pnstr) { + *pnstr = 0; + if (*pstrlst) + XFreeStringList(*pstrlst); + cxfree(text_prop.value); + return false; + } - cxfree(text_prop.value); - return true; + cxfree(text_prop.value); + return true; } // A cache of pict formats. We assume they don't change during the lifetime @@ -117,128 +109,120 @@ bool wid_get_text_prop(session_t *ps, xcb_window_t wid, xcb_atom_t prop, static thread_local xcb_render_query_pict_formats_reply_t *g_pictfmts = NULL; static inline void x_get_server_pictfmts(xcb_connection_t *c) { - if (g_pictfmts) - return; - xcb_generic_error_t *e = NULL; - // Get window picture format - g_pictfmts = - xcb_render_query_pict_formats_reply(c, - xcb_render_query_pict_formats(c), &e); - if (e || !g_pictfmts) { - log_fatal("failed to get pict formats\n"); - abort(); - } + if (g_pictfmts) + return; + xcb_generic_error_t *e = NULL; + // Get window picture format + g_pictfmts = + xcb_render_query_pict_formats_reply(c, xcb_render_query_pict_formats(c), &e); + if (e || !g_pictfmts) { + log_fatal("failed to get pict formats\n"); + abort(); + } } const xcb_render_pictforminfo_t * x_get_pictform_for_visual(xcb_connection_t *c, xcb_visualid_t visual) { - x_get_server_pictfmts(c); + x_get_server_pictfmts(c); - xcb_render_pictvisual_t *pv = xcb_render_util_find_visual_format(g_pictfmts, visual); - for(xcb_render_pictforminfo_iterator_t i = - xcb_render_query_pict_formats_formats_iterator(g_pictfmts); i.rem; - xcb_render_pictforminfo_next(&i)) { - if (i.data->id == pv->format) { - return i.data; - } - } - return NULL; + xcb_render_pictvisual_t *pv = xcb_render_util_find_visual_format(g_pictfmts, visual); + for (xcb_render_pictforminfo_iterator_t i = + xcb_render_query_pict_formats_formats_iterator(g_pictfmts); + i.rem; xcb_render_pictforminfo_next(&i)) { + if (i.data->id == pv->format) { + return i.data; + } + } + return NULL; } -static xcb_visualid_t attr_pure -x_get_visual_for_pictfmt(xcb_render_query_pict_formats_reply_t *r, - xcb_render_pictformat_t fmt) { - for (auto screen = xcb_render_query_pict_formats_screens_iterator(r); - screen.rem; xcb_render_pictscreen_next(&screen)) { - for (auto depth = xcb_render_pictscreen_depths_iterator(screen.data); - depth.rem; xcb_render_pictdepth_next(&depth)) { - for (auto pv = xcb_render_pictdepth_visuals_iterator(depth.data); pv.rem; - xcb_render_pictvisual_next(&pv)) { - if (pv.data->format == fmt) { - return pv.data->visual; - } - } - } - } - return XCB_NONE; +static xcb_visualid_t attr_pure x_get_visual_for_pictfmt(xcb_render_query_pict_formats_reply_t *r, + xcb_render_pictformat_t fmt) { + for (auto screen = xcb_render_query_pict_formats_screens_iterator(r); screen.rem; + xcb_render_pictscreen_next(&screen)) { + for (auto depth = xcb_render_pictscreen_depths_iterator(screen.data); + depth.rem; xcb_render_pictdepth_next(&depth)) { + for (auto pv = xcb_render_pictdepth_visuals_iterator(depth.data); + pv.rem; xcb_render_pictvisual_next(&pv)) { + if (pv.data->format == fmt) { + return pv.data->visual; + } + } + } + } + return XCB_NONE; } -xcb_visualid_t -x_get_visual_for_standard(xcb_connection_t *c, xcb_pict_standard_t std) { - x_get_server_pictfmts(c); +xcb_visualid_t x_get_visual_for_standard(xcb_connection_t *c, xcb_pict_standard_t std) { + x_get_server_pictfmts(c); - auto pictfmt = - xcb_render_util_find_standard_format(g_pictfmts, std); + auto pictfmt = 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) { - auto setup = xcb_get_setup(c); - for (auto screen = xcb_setup_roots_iterator(setup); screen.rem; 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 xcb_visualtype_t *visuals = xcb_depth_visuals(depth.data); - for (int i = 0; i < len; i++) { - if (visual == visuals[i].visual_id) { - return depth.data->depth; - } - } - } - } - return -1; + auto setup = xcb_get_setup(c); + for (auto screen = xcb_setup_roots_iterator(setup); screen.rem; + 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 xcb_visualtype_t *visuals = xcb_depth_visuals(depth.data); + for (int i = 0; i < len; i++) { + if (visual == visuals[i].visual_id) { + return depth.data->depth; + } + } + } + } + return -1; } xcb_render_picture_t -x_create_picture_with_pictfmt_and_pixmap( - xcb_connection_t *c, const xcb_render_pictforminfo_t * pictfmt, - xcb_pixmap_t pixmap, unsigned long valuemask, - const xcb_render_create_picture_value_list_t *attr) -{ - void *buf = NULL; - if (attr) { - xcb_render_create_picture_value_list_serialize(&buf, valuemask, attr); - if (!buf) { - log_error("failed to serialize picture attributes"); - return XCB_NONE; - } - } +x_create_picture_with_pictfmt_and_pixmap(xcb_connection_t *c, + const xcb_render_pictforminfo_t *pictfmt, + xcb_pixmap_t pixmap, unsigned long valuemask, + const xcb_render_create_picture_value_list_t *attr) { + void *buf = NULL; + if (attr) { + xcb_render_create_picture_value_list_serialize(&buf, valuemask, attr); + if (!buf) { + log_error("failed to serialize picture attributes"); + return XCB_NONE; + } + } - xcb_render_picture_t tmp_picture = xcb_generate_id(c); - xcb_generic_error_t *e = - xcb_request_check(c, xcb_render_create_picture_checked(c, tmp_picture, - pixmap, pictfmt->id, valuemask, buf)); - free(buf); - if (e) { - x_print_error(e->full_sequence, e->major_code, e->minor_code, e->error_code); - log_error("failed to create picture"); - return XCB_NONE; - } - return tmp_picture; + xcb_render_picture_t tmp_picture = xcb_generate_id(c); + xcb_generic_error_t *e = + xcb_request_check(c, xcb_render_create_picture_checked( + c, tmp_picture, pixmap, pictfmt->id, valuemask, buf)); + free(buf); + if (e) { + x_print_error(e->full_sequence, e->major_code, e->minor_code, e->error_code); + log_error("failed to create picture"); + return XCB_NONE; + } + return tmp_picture; } xcb_render_picture_t -x_create_picture_with_visual_and_pixmap( - xcb_connection_t *c, xcb_visualid_t visual, - xcb_pixmap_t pixmap, unsigned long valuemask, - const xcb_render_create_picture_value_list_t *attr) -{ - 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); +x_create_picture_with_visual_and_pixmap(xcb_connection_t *c, xcb_visualid_t visual, + xcb_pixmap_t pixmap, unsigned long valuemask, + const xcb_render_create_picture_value_list_t *attr) { + 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); } xcb_render_picture_t -x_create_picture_with_standard_and_pixmap( - xcb_connection_t *c, xcb_pict_standard_t standard, - xcb_pixmap_t pixmap, unsigned long valuemask, - const xcb_render_create_picture_value_list_t *attr) -{ - x_get_server_pictfmts(c); +x_create_picture_with_standard_and_pixmap(xcb_connection_t *c, xcb_pict_standard_t standard, + xcb_pixmap_t pixmap, unsigned long valuemask, + const xcb_render_create_picture_value_list_t *attr) { + x_get_server_pictfmts(c); - auto pictfmt = - xcb_render_util_find_standard_format(g_pictfmts, standard); - assert(pictfmt); - return x_create_picture_with_pictfmt_and_pixmap(c, pictfmt, pixmap, valuemask, attr); + auto pictfmt = xcb_render_util_find_standard_format(g_pictfmts, standard); + assert(pictfmt); + return x_create_picture_with_pictfmt_and_pixmap(c, pictfmt, pixmap, valuemask, attr); } /** @@ -246,98 +230,90 @@ x_create_picture_with_standard_and_pixmap( */ xcb_render_picture_t 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_create_picture_value_list_t *attr) -{ - int depth = pictfmt->depth; + const xcb_render_pictforminfo_t *pictfmt, unsigned long valuemask, + const xcb_render_create_picture_value_list_t *attr) { + int depth = pictfmt->depth; - xcb_pixmap_t tmp_pixmap = x_create_pixmap(c, depth, d, wid, hei); - if (!tmp_pixmap) - return XCB_NONE; + xcb_pixmap_t tmp_pixmap = x_create_pixmap(c, depth, d, wid, hei); + if (!tmp_pixmap) + return XCB_NONE; - xcb_render_picture_t picture = - x_create_picture_with_pictfmt_and_pixmap(c, pictfmt, tmp_pixmap, valuemask, attr); + xcb_render_picture_t picture = x_create_picture_with_pictfmt_and_pixmap( + c, pictfmt, tmp_pixmap, valuemask, attr); - xcb_free_pixmap(c, tmp_pixmap); + xcb_free_pixmap(c, tmp_pixmap); - return picture; + return picture; } xcb_render_picture_t x_create_picture_with_visual(xcb_connection_t *c, xcb_drawable_t d, int w, int h, - xcb_visualid_t visual, unsigned long valuemask, - const xcb_render_create_picture_value_list_t *attr) -{ - auto pictfmt = x_get_pictform_for_visual(c, visual); - return x_create_picture_with_pictfmt(c, d, w, h, pictfmt, valuemask, attr); + xcb_visualid_t visual, unsigned long valuemask, + const xcb_render_create_picture_value_list_t *attr) { + auto pictfmt = x_get_pictform_for_visual(c, visual); + 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) { - xcb_generic_error_t *e = NULL; - xcb_xfixes_fetch_region_reply_t *xr = xcb_xfixes_fetch_region_reply(c, - xcb_xfixes_fetch_region(c, r), &e); - if (!xr) { - log_error("Failed to fetch rectangles"); - return false; - } + xcb_generic_error_t *e = NULL; + xcb_xfixes_fetch_region_reply_t *xr = + xcb_xfixes_fetch_region_reply(c, xcb_xfixes_fetch_region(c, r), &e); + if (!xr) { + log_error("Failed to fetch rectangles"); + return false; + } - int nrect = xcb_xfixes_fetch_region_rectangles_length(xr); - auto b = ccalloc(nrect, pixman_box32_t); - xcb_rectangle_t *xrect = xcb_xfixes_fetch_region_rectangles(xr); - for (int i = 0; i < nrect; i++) { - b[i] = (pixman_box32_t) { - .x1 = xrect[i].x, - .y1 = xrect[i].y, - .x2 = xrect[i].x + xrect[i].width, - .y2 = xrect[i].y + xrect[i].height - }; - } - bool ret = pixman_region32_init_rects(res, b, nrect); - free(b); - free(xr); - return ret; + int nrect = xcb_xfixes_fetch_region_rectangles_length(xr); + auto b = ccalloc(nrect, pixman_box32_t); + xcb_rectangle_t *xrect = xcb_xfixes_fetch_region_rectangles(xr); + for (int i = 0; i < nrect; i++) { + b[i] = (pixman_box32_t){.x1 = xrect[i].x, + .y1 = xrect[i].y, + .x2 = xrect[i].x + xrect[i].width, + .y2 = xrect[i].y + xrect[i].height}; + } + bool ret = pixman_region32_init_rects(res, b, nrect); + free(b); + free(xr); + return ret; } void x_set_picture_clip_region(xcb_connection_t *c, xcb_render_picture_t pict, - int clip_x_origin, int clip_y_origin, const region_t *reg) { - int nrects; - const rect_t *rects = pixman_region32_rectangles((region_t *)reg, &nrects); - auto xrects = ccalloc(nrects, xcb_rectangle_t); - for (int i = 0; i < nrects; i++) - xrects[i] = (xcb_rectangle_t){ - .x = rects[i].x1, - .y = rects[i].y1, - .width = rects[i].x2 - rects[i].x1, - .height = rects[i].y2 - rects[i].y1, - }; + int clip_x_origin, int clip_y_origin, const region_t *reg) { + int nrects; + const rect_t *rects = pixman_region32_rectangles((region_t *)reg, &nrects); + auto xrects = ccalloc(nrects, xcb_rectangle_t); + for (int i = 0; i < nrects; i++) + xrects[i] = (xcb_rectangle_t){ + .x = rects[i].x1, + .y = rects[i].y1, + .width = rects[i].x2 - rects[i].x1, + .height = rects[i].y2 - rects[i].y1, + }; - xcb_generic_error_t *e = - xcb_request_check(c, xcb_render_set_picture_clip_rectangles_checked(c, pict, - clip_x_origin, clip_y_origin, nrects, xrects)); - if (e) - log_error("Failed to set clip region"); - free(e); - free(xrects); - return; + xcb_generic_error_t *e = + xcb_request_check(c, xcb_render_set_picture_clip_rectangles_checked( + c, pict, clip_x_origin, clip_y_origin, nrects, xrects)); + if (e) + log_error("Failed to set clip region"); + free(e); + free(xrects); + return; } void x_clear_picture_clip_region(xcb_connection_t *c, xcb_render_picture_t pict) { - xcb_render_change_picture_value_list_t v = { - .clipmask = XCB_NONE - }; - xcb_generic_error_t *e = - xcb_request_check(c, xcb_render_change_picture(c, pict, - XCB_RENDER_CP_CLIP_MASK, &v)); - if (e) - log_error("failed to clear clip region"); - free(e); - return; + xcb_render_change_picture_value_list_t v = {.clipmask = XCB_NONE}; + xcb_generic_error_t *e = xcb_request_check( + c, xcb_render_change_picture(c, pict, XCB_RENDER_CP_CLIP_MASK, &v)); + if (e) + log_error("failed to clear clip region"); + free(e); + return; } -enum { - XSyncBadCounter = 0, - XSyncBadAlarm = 1, - XSyncBadFence = 2, +enum { XSyncBadCounter = 0, + XSyncBadAlarm = 1, + XSyncBadFence = 2, }; /** @@ -345,106 +321,102 @@ enum { * * XXX consider making this error to string */ -void -x_print_error(unsigned long serial, uint8_t major, uint8_t minor, uint8_t error_code) { - session_t * const ps = ps_g; +void x_print_error(unsigned long serial, uint8_t major, uint8_t minor, uint8_t error_code) { + session_t *const ps = ps_g; - int o = 0; - const char *name = "Unknown"; + int o = 0; + const char *name = "Unknown"; - if (major == ps->composite_opcode - && minor == XCB_COMPOSITE_REDIRECT_SUBWINDOWS) { - log_fatal("Another composite manager is already running " - "(and does not handle _NET_WM_CM_Sn correctly)"); - exit(1); - } + if (major == ps->composite_opcode && minor == XCB_COMPOSITE_REDIRECT_SUBWINDOWS) { + log_fatal("Another composite manager is already running " + "(and does not handle _NET_WM_CM_Sn correctly)"); + exit(1); + } -#define CASESTRRET2(s) case s: name = #s; break +#define CASESTRRET2(s) \ + case s: name = #s; break - o = error_code - ps->xfixes_error; - switch (o) { - CASESTRRET2(XCB_XFIXES_BAD_REGION); - } + o = error_code - ps->xfixes_error; + switch (o) { CASESTRRET2(XCB_XFIXES_BAD_REGION); } - o = error_code - ps->damage_error; - switch (o) { - CASESTRRET2(XCB_DAMAGE_BAD_DAMAGE); - } + o = error_code - ps->damage_error; + switch (o) { CASESTRRET2(XCB_DAMAGE_BAD_DAMAGE); } - o = error_code - ps->render_error; - switch (o) { - CASESTRRET2(XCB_RENDER_PICT_FORMAT); - CASESTRRET2(XCB_RENDER_PICTURE); - CASESTRRET2(XCB_RENDER_PICT_OP); - CASESTRRET2(XCB_RENDER_GLYPH_SET); - CASESTRRET2(XCB_RENDER_GLYPH); - } + o = error_code - ps->render_error; + switch (o) { + CASESTRRET2(XCB_RENDER_PICT_FORMAT); + CASESTRRET2(XCB_RENDER_PICTURE); + CASESTRRET2(XCB_RENDER_PICT_OP); + CASESTRRET2(XCB_RENDER_GLYPH_SET); + CASESTRRET2(XCB_RENDER_GLYPH); + } #ifdef CONFIG_OPENGL - if (ps->glx_exists) { - o = error_code - ps->glx_error; - switch (o) { - CASESTRRET2(GLX_BAD_SCREEN); - CASESTRRET2(GLX_BAD_ATTRIBUTE); - CASESTRRET2(GLX_NO_EXTENSION); - CASESTRRET2(GLX_BAD_VISUAL); - CASESTRRET2(GLX_BAD_CONTEXT); - CASESTRRET2(GLX_BAD_VALUE); - CASESTRRET2(GLX_BAD_ENUM); - } - } + if (ps->glx_exists) { + o = error_code - ps->glx_error; + switch (o) { + CASESTRRET2(GLX_BAD_SCREEN); + CASESTRRET2(GLX_BAD_ATTRIBUTE); + CASESTRRET2(GLX_NO_EXTENSION); + CASESTRRET2(GLX_BAD_VISUAL); + CASESTRRET2(GLX_BAD_CONTEXT); + CASESTRRET2(GLX_BAD_VALUE); + CASESTRRET2(GLX_BAD_ENUM); + } + } #endif - if (ps->xsync_exists) { - o = error_code - ps->xsync_error; - switch (o) { - CASESTRRET2(XSyncBadCounter); - CASESTRRET2(XSyncBadAlarm); - CASESTRRET2(XSyncBadFence); - } - } + if (ps->xsync_exists) { + o = error_code - ps->xsync_error; + switch (o) { + CASESTRRET2(XSyncBadCounter); + CASESTRRET2(XSyncBadAlarm); + CASESTRRET2(XSyncBadFence); + } + } - switch (error_code) { - CASESTRRET2(BadAccess); - CASESTRRET2(BadAlloc); - CASESTRRET2(BadAtom); - CASESTRRET2(BadColor); - CASESTRRET2(BadCursor); - CASESTRRET2(BadDrawable); - CASESTRRET2(BadFont); - CASESTRRET2(BadGC); - CASESTRRET2(BadIDChoice); - CASESTRRET2(BadImplementation); - CASESTRRET2(BadLength); - CASESTRRET2(BadMatch); - CASESTRRET2(BadName); - CASESTRRET2(BadPixmap); - CASESTRRET2(BadRequest); - CASESTRRET2(BadValue); - CASESTRRET2(BadWindow); - } + switch (error_code) { + CASESTRRET2(BadAccess); + CASESTRRET2(BadAlloc); + CASESTRRET2(BadAtom); + CASESTRRET2(BadColor); + CASESTRRET2(BadCursor); + CASESTRRET2(BadDrawable); + CASESTRRET2(BadFont); + CASESTRRET2(BadGC); + CASESTRRET2(BadIDChoice); + CASESTRRET2(BadImplementation); + CASESTRRET2(BadLength); + CASESTRRET2(BadMatch); + CASESTRRET2(BadName); + CASESTRRET2(BadPixmap); + CASESTRRET2(BadRequest); + CASESTRRET2(BadValue); + CASESTRRET2(BadWindow); + } #undef CASESTRRET2 - log_debug("X error %d %s request %d minor %d serial %lu", - error_code, name, major, minor, serial); + log_debug("X error %d %s request %d minor %d serial %lu", error_code, name, major, + minor, serial); } /** * Create a pixmap and check that creation succeeded. */ -xcb_pixmap_t -x_create_pixmap(xcb_connection_t *c, uint8_t depth, xcb_drawable_t drawable, uint16_t width, uint16_t height) { - xcb_pixmap_t pix = xcb_generate_id(c); - 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); - if (err == NULL) - return pix; +xcb_pixmap_t x_create_pixmap(xcb_connection_t *c, uint8_t depth, xcb_drawable_t drawable, + uint16_t width, uint16_t height) { + xcb_pixmap_t pix = xcb_generate_id(c); + 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); + if (err == NULL) + return pix; - log_error("Failed to create pixmap:"); - x_print_error(err->sequence, err->major_code, err->minor_code, err->error_code); - free(err); - return XCB_NONE; + log_error("Failed to create pixmap:"); + x_print_error(err->sequence, err->major_code, err->minor_code, err->error_code); + free(err); + return XCB_NONE; } /** @@ -453,55 +425,54 @@ 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 * are better ways. */ -bool -x_validate_pixmap(xcb_connection_t *c, xcb_pixmap_t pixmap) { - if (pixmap == XCB_NONE) { - return false; - } +bool x_validate_pixmap(xcb_connection_t *c, xcb_pixmap_t pixmap) { + if (pixmap == XCB_NONE) { + return false; + } - auto r = xcb_get_geometry_reply(c, xcb_get_geometry(c, pixmap), NULL); - if (!r) { - return false; - } + auto r = xcb_get_geometry_reply(c, xcb_get_geometry(c, pixmap), NULL); + if (!r) { + return false; + } - bool ret = r->width && r->height; - free(r); - return ret; + bool ret = r->width && r->height; + free(r); + return ret; } /// Names of root window properties that could point to a pixmap of /// background. static const char *background_props_str[] = { - "_XROOTPMAP_ID", - "_XSETROOT_ID", - 0, + "_XROOTPMAP_ID", + "_XSETROOT_ID", + 0, }; xcb_pixmap_t x_get_root_back_pixmap(session_t *ps) { - xcb_pixmap_t pixmap = XCB_NONE; + xcb_pixmap_t pixmap = XCB_NONE; - // Get the values of background attributes - for (int p = 0; background_props_str[p]; p++) { - xcb_atom_t prop_atom = get_atom(ps, background_props_str[p]); - winprop_t prop = - wid_get_prop(ps, ps->root, prop_atom, 1, XCB_ATOM_PIXMAP, 32); - if (prop.nitems) { - pixmap = *prop.p32; - free_winprop(&prop); - break; - } - free_winprop(&prop); - } + // Get the values of background attributes + for (int p = 0; background_props_str[p]; p++) { + xcb_atom_t prop_atom = get_atom(ps, background_props_str[p]); + winprop_t prop = + wid_get_prop(ps, ps->root, prop_atom, 1, XCB_ATOM_PIXMAP, 32); + if (prop.nitems) { + pixmap = *prop.p32; + free_winprop(&prop); + break; + } + free_winprop(&prop); + } - return pixmap; + return pixmap; } bool x_is_root_back_pixmap_atom(session_t *ps, xcb_atom_t atom) { - for (int p = 0; background_props_str[p]; p++) { - xcb_atom_t prop_atom = get_atom(ps, background_props_str[p]); - if (prop_atom == atom) - return true; - } - return false; + for (int p = 0; background_props_str[p]; p++) { + xcb_atom_t prop_atom = get_atom(ps, background_props_str[p]); + if (prop_atom == atom) + return true; + } + return false; } /** @@ -509,36 +480,36 @@ bool x_is_root_back_pixmap_atom(session_t *ps, xcb_atom_t atom) { * are completed. */ bool x_fence_sync(xcb_connection_t *c, xcb_sync_fence_t f) { - // TODO(richardgv): If everybody just follows the rules stated in X Sync - // prototype, we need only one fence per screen, but let's stay a bit - // cautious right now + // TODO(richardgv): If everybody just follows the rules stated in X Sync + // prototype, we need only one fence per screen, but let's stay a bit + // cautious right now - auto e = xcb_request_check(c, xcb_sync_trigger_fence_checked(c, f)); - if (e) { - log_error("Failed to trigger the fence."); - free(e); - return false; - } + auto e = xcb_request_check(c, xcb_sync_trigger_fence_checked(c, f)); + if (e) { + log_error("Failed to trigger the fence."); + free(e); + return false; + } - e = xcb_request_check(c, xcb_sync_await_fence_checked(c, 1, &f)); - if (e) { - log_error("Failed to await on a fence."); - free(e); - return false; - } + e = xcb_request_check(c, xcb_sync_await_fence_checked(c, 1, &f)); + if (e) { + log_error("Failed to await on a fence."); + free(e); + return false; + } - e = xcb_request_check(c, xcb_sync_reset_fence_checked(c, f)); - if (e) { - log_error("Failed to reset the fence."); - free(e); - return false; - } - return true; + e = xcb_request_check(c, xcb_sync_reset_fence_checked(c, f)); + if (e) { + log_error("Failed to reset the fence."); + free(e); + return false; + } + return true; } // xcb-render specific macros -#define XFIXED_TO_DOUBLE(value) (((double) (value)) / 65536) -#define DOUBLE_TO_XFIXED(value) ((xcb_render_fixed_t) (((double) (value)) * 65536)) +#define XFIXED_TO_DOUBLE(value) (((double)(value)) / 65536) +#define DOUBLE_TO_XFIXED(value) ((xcb_render_fixed_t)(((double)(value)) * 65536)) /** * Convert a struct conv to a X picture convolution filter, normalizing the kernel @@ -552,35 +523,35 @@ 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 * @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 *size) { - if (*size < (size_t)(kernel->w * kernel->h + 2)) { - *size = kernel->w * kernel->h + 2; - *ret = crealloc(*ret, *size); - } - auto buf = *ret; - buf[0] = DOUBLE_TO_XFIXED(kernel->w); - buf[1] = DOUBLE_TO_XFIXED(kernel->h); - double sum = center; - for (int i = 0; i < kernel->w * kernel->h; i++) { - sum += kernel->data[i]; - } +size_t x_picture_filter_from_conv(const conv *kernel, double center, + xcb_render_fixed_t **ret, size_t *size) { + if (*size < (size_t)(kernel->w * kernel->h + 2)) { + *size = kernel->w * kernel->h + 2; + *ret = crealloc(*ret, *size); + } + auto buf = *ret; + buf[0] = DOUBLE_TO_XFIXED(kernel->w); + buf[1] = DOUBLE_TO_XFIXED(kernel->h); + double sum = center; + for (int i = 0; i < kernel->w * kernel->h; i++) { + sum += kernel->data[i]; + } - // Note for floating points a / b != a * (1 / b), but this shouldn't have any real - // impact on the result - double factor = sum != 0 ? 1.0 / sum : 1; - for (int i = 0; i < kernel->w * kernel->h; i++) { - buf[i + 2] = DOUBLE_TO_XFIXED(kernel->data[i] * factor); - } + // Note for floating points a / b != a * (1 / b), but this shouldn't have any real + // impact on the result + double factor = sum != 0 ? 1.0 / sum : 1; + for (int i = 0; i < kernel->w * kernel->h; i++) { + 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); - return kernel->w * kernel->h + 2; + buf[kernel->h / 2 * kernel->w + kernel->w / 2 + 2] = + DOUBLE_TO_XFIXED(center * factor); + return kernel->w * kernel->h + 2; } /// Generate a search criteria for fbconfig from a X visual. /// Returns {-1, -1, -1, -1, -1, -1} on failure -struct xvisual_info -x_get_visual_info(xcb_connection_t *c, xcb_visualid_t visual) { +struct xvisual_info x_get_visual_info(xcb_connection_t *c, xcb_visualid_t visual) { auto pictfmt = x_get_pictform_for_visual(c, visual); auto depth = x_get_visual_depth(c, visual); if (!pictfmt || depth == -1) { diff --git a/src/x.h b/src/x.h index 2e8b258..2797e81 100644 --- a/src/x.h +++ b/src/x.h @@ -137,16 +137,17 @@ x_create_picture_with_standard_and_pixmap(xcb_connection_t *, xcb_pict_standard_ /** * Create an picture. */ -xcb_render_picture_t attr_nonnull(1, 5) - x_create_picture_with_pictfmt(xcb_connection_t *, xcb_drawable_t, int wid, int hei, - const xcb_render_pictforminfo_t *pictfmt, - unsigned long valuemask, - const xcb_render_create_picture_value_list_t *attr); +xcb_render_picture_t +x_create_picture_with_pictfmt(xcb_connection_t *, xcb_drawable_t, int wid, int hei, + const xcb_render_pictforminfo_t *pictfmt, unsigned long valuemask, + const xcb_render_create_picture_value_list_t *attr) + attr_nonnull(1, 5); -xcb_render_picture_t attr_nonnull(1) - x_create_picture_with_visual(xcb_connection_t *, xcb_drawable_t, int w, int h, - xcb_visualid_t visual, unsigned long valuemask, - const xcb_render_create_picture_value_list_t *attr); +xcb_render_picture_t +x_create_picture_with_visual(xcb_connection_t *, xcb_drawable_t, int w, int h, + xcb_visualid_t visual, unsigned long valuemask, + const xcb_render_create_picture_value_list_t *attr) + attr_nonnull(1); /// 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); @@ -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. /// Returns {-1, -1, -1, -1, -1, -1} on failure -struct xvisual_info -x_get_visual_info(xcb_connection_t *c, xcb_visualid_t visual); +struct xvisual_info x_get_visual_info(xcb_connection_t *c, xcb_visualid_t visual); -xcb_visualid_t -x_get_visual_for_standard(xcb_connection_t *c, xcb_pict_standard_t std); +xcb_visualid_t x_get_visual_for_standard(xcb_connection_t *c, xcb_pict_standard_t std); diff --git a/src/xrescheck.c b/src/xrescheck.c index b4cca7e..1785fc8 100644 --- a/src/xrescheck.c +++ b/src/xrescheck.c @@ -8,64 +8,58 @@ static xrc_xid_record_t *gs_xid_records = NULL; -#define HASH_ADD_XID(head, xidfield, add) \ - HASH_ADD(hh, head, xidfield, sizeof(xid), add) +#define HASH_ADD_XID(head, xidfield, add) HASH_ADD(hh, head, xidfield, sizeof(xid), add) -#define HASH_FIND_XID(head, findxid, out) \ - HASH_FIND(hh, head, findxid, sizeof(xid), out) +#define HASH_FIND_XID(head, findxid, out) HASH_FIND(hh, head, findxid, sizeof(xid), out) -#define M_CPY_POS_DATA(prec) \ - prec->file = file; \ - prec->func = func; \ - prec->line = line; \ +#define M_CPY_POS_DATA(prec) \ + prec->file = file; \ + prec->func = func; \ + prec->line = line; /** * @brief Add a record of given XID to the allocation table. */ -void -xrc_add_xid_(XID xid, const char *type, M_POS_DATA_PARAMS) { - auto prec = ccalloc(1, xrc_xid_record_t); - prec->xid = xid; - prec->type = type; - M_CPY_POS_DATA(prec); +void xrc_add_xid_(XID xid, const char *type, M_POS_DATA_PARAMS) { + auto prec = ccalloc(1, xrc_xid_record_t); + prec->xid = xid; + prec->type = type; + M_CPY_POS_DATA(prec); - HASH_ADD_XID(gs_xid_records, xid, prec); + HASH_ADD_XID(gs_xid_records, xid, prec); } /** * @brief Delete a record of given XID in the allocation table. */ -void -xrc_delete_xid_(XID xid, M_POS_DATA_PARAMS) { - xrc_xid_record_t *prec = NULL; - HASH_FIND_XID(gs_xid_records, &xid, prec); - if (!prec) { - log_error("XRC: %s:%d %s(): Can't find XID %#010lx we want to delete.", - file, line, func, xid); - return; - } - HASH_DEL(gs_xid_records, prec); - free(prec); +void xrc_delete_xid_(XID xid, M_POS_DATA_PARAMS) { + xrc_xid_record_t *prec = NULL; + HASH_FIND_XID(gs_xid_records, &xid, prec); + if (!prec) { + log_error("XRC: %s:%d %s(): Can't find XID %#010lx we want to delete.", + file, line, func, xid); + return; + } + HASH_DEL(gs_xid_records, prec); + free(prec); } /** * @brief Report about issues found in the XID allocation table. */ -void -xrc_report_xid(void) { - 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", - prec->file, prec->line, prec->func, prec->xid, prec->type); +void xrc_report_xid(void) { + 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", prec->file, + prec->line, prec->func, prec->xid, prec->type); } /** * @brief Clear the XID allocation table. */ -void -xrc_clear_xid(void) { - xrc_xid_record_t *prec = NULL, *ptmp = NULL; - HASH_ITER(hh, gs_xid_records, prec, ptmp) { - HASH_DEL(gs_xid_records, prec); - free(prec); - } +void xrc_clear_xid(void) { + xrc_xid_record_t *prec = NULL, *ptmp = NULL; + HASH_ITER(hh, gs_xid_records, prec, ptmp) { + HASH_DEL(gs_xid_records, prec); + free(prec); + } } diff --git a/src/xrescheck.h b/src/xrescheck.h index e982615..5ad5c46 100644 --- a/src/xrescheck.h +++ b/src/xrescheck.h @@ -6,60 +6,57 @@ #include "uthash.h" typedef struct { - XID xid; - const char *type; - const char *file; - const char *func; - int line; - UT_hash_handle hh; + XID xid; + const char *type; + const char *file; + const char *func; + int line; + UT_hash_handle hh; } xrc_xid_record_t; #define M_POS_DATA_PARAMS const char *file, int line, const char *func #define M_POS_DATA_PASSTHROUGH file, line, func #define M_POS_DATA __FILE__, __LINE__, __func__ -void -xrc_add_xid_(XID xid, const char *type, M_POS_DATA_PARAMS); +void 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) -void -xrc_delete_xid_(XID xid, M_POS_DATA_PARAMS); +void xrc_delete_xid_(XID xid, M_POS_DATA_PARAMS); #define xrc_delete_xid(xid) xrc_delete_xid_(xid, M_POS_DATA) -void -xrc_report_xid(void); +void xrc_report_xid(void); -void -xrc_clear_xid(void); +void xrc_clear_xid(void); // Pixmap -static inline void -xcb_create_pixmap_(xcb_connection_t *c, uint8_t depth, xcb_pixmap_t pixmap, - xcb_drawable_t drawable, uint16_t width, uint16_t height, M_POS_DATA_PARAMS) { - xcb_create_pixmap(c, depth, pixmap, drawable, width, height); - xrc_add_xid_(pixmap, "Pixmap", M_POS_DATA_PASSTHROUGH); +static inline void xcb_create_pixmap_(xcb_connection_t *c, uint8_t depth, + xcb_pixmap_t pixmap, xcb_drawable_t drawable, + uint16_t width, uint16_t height, M_POS_DATA_PARAMS) { + xcb_create_pixmap(c, depth, pixmap, drawable, width, height); + xrc_add_xid_(pixmap, "Pixmap", M_POS_DATA_PASSTHROUGH); } -#define xcb_create_pixmap(c, depth, pixmap, drawable, width, height) \ - xcb_create_pixmap_(c, depth, pixmap, drawable, width, height, M_POS_DATA) +#define xcb_create_pixmap(c, depth, pixmap, drawable, width, height) \ + xcb_create_pixmap_(c, depth, pixmap, drawable, width, height, M_POS_DATA) 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_void_cookie_t ret = xcb_composite_name_window_pixmap(c, window, pixmap); - xrc_add_xid_(pixmap, "PixmapC", M_POS_DATA_PASSTHROUGH); - return ret; +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); + xrc_add_xid_(pixmap, "PixmapC", M_POS_DATA_PASSTHROUGH); + return ret; } -#define xcb_composite_name_window_pixmap(dpy, window, pixmap) \ - xcb_composite_name_window_pixmap_(dpy, window, pixmap, M_POS_DATA) +#define xcb_composite_name_window_pixmap(dpy, window, pixmap) \ + xcb_composite_name_window_pixmap_(dpy, window, pixmap, M_POS_DATA) static inline void xcb_free_pixmap_(xcb_connection_t *c, xcb_pixmap_t pixmap, M_POS_DATA_PARAMS) { - xcb_free_pixmap(c, pixmap); - xrc_delete_xid_(pixmap, M_POS_DATA_PASSTHROUGH); + xcb_free_pixmap(c, pixmap); + xrc_delete_xid_(pixmap, M_POS_DATA_PASSTHROUGH); } #define xcb_free_pixmap(c, pixmap) xcb_free_pixmap_(c, pixmap, M_POS_DATA);