diff options
Diffstat (limited to 'twin/compton-tde/c2.h')
-rw-r--r-- | twin/compton-tde/c2.h | 354 |
1 files changed, 354 insertions, 0 deletions
diff --git a/twin/compton-tde/c2.h b/twin/compton-tde/c2.h new file mode 100644 index 000000000..9e04c09a8 --- /dev/null +++ b/twin/compton-tde/c2.h @@ -0,0 +1,354 @@ +/* + * Compton - a compositor for X11 + * + * Based on `xcompmgr` - Copyright (c) 2003, Keith Packard + * + * Copyright (c) 2011-2013, Christopher Jeffrey + * See LICENSE for more information. + * + */ + +#include "common.h" + +#include <fnmatch.h> +#include <ctype.h> + +// libpcre +#ifdef CONFIG_REGEX_PCRE +#include <pcre.h> + +// For compatiblity with <libpcre-8.20 +#ifndef PCRE_STUDY_JIT_COMPILE +#define PCRE_STUDY_JIT_COMPILE 0 +#define LPCRE_FREE_STUDY(extra) pcre_free(extra) +#else +#define LPCRE_FREE_STUDY(extra) pcre_free_study(extra) +#endif + +#endif + +#define C2_MAX_LEVELS 10 + +typedef struct _c2_b c2_b_t; +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; +// }; +} c2_ptr_t; + +/// Initializer for c2_ptr_t. +#define C2_PTR_INIT { \ + .isbranch = false, \ + .l = NULL, \ +} + +const static 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_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; +}; + +/// Initializer for c2_b_t. +#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; + Atom 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; +#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, \ +} + +const static 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; +}; + +/// Initializer for c2_lptr_t. +#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; +} c2_predef_t; + +// Predefined targets. +const static 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 }, +}; + +#define mstrncmp(s1, s2) strncmp((s1), (s2), strlen(s1)) + +/** + * 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; + + 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); +} + +/** + * 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)); +} + +/** + * 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 = malloc(sizeof(c2_b_t)) + }; + + p.b->opr1 = p1; + p.b->opr2 = p2; + p.b->op = op; + + 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; + } + + assert(0); + return 0; +} + +/** + * Compare precedence of two condition branch operators. + * + * Associativity is left-to-right, forever. + * + * @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 int +c2_parse_grp(session_t *ps, const char *pattern, int offset, c2_ptr_t *presult, int level); + +static int +c2_parse_target(session_t *ps, 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(session_t *ps, const char *pattern, int offset, c2_ptr_t *presult); + +static int +c2_parse_legacy(session_t *ps, const char *pattern, int offset, c2_ptr_t *presult); + +static bool +c2_l_postprocess(session_t *ps, c2_l_t *pleaf); + +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 const char * +c2h_dump_str_tgt(const c2_l_t *pleaf); + +static const char * +c2h_dump_str_type(const c2_l_t *pleaf); + +static void +c2_dump_raw(c2_ptr_t p); + +/** + * Wrapper of c2_dump_raw(). + */ +static inline void +c2_dump(c2_ptr_t p) { + c2_dump_raw(p); + printf("\n"); + fflush(stdout); +} + +static Atom +c2_get_atom_type(const c2_l_t *pleaf); + +static bool +c2_match_once(session_t *ps, win *w, const c2_ptr_t cond); + |