1
0
Fork 0
mirror of https://github.com/yshui/picom.git synced 2024-11-11 13:51:02 -05:00

c2: start to separate some state out of session_t

This is just the beginning, c2_match still needs session_t, everything
is just so tangled...

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2024-02-13 22:47:12 +00:00
parent b99c7db73e
commit d19a7bc091
No known key found for this signature in database
GPG key ID: D3A4405BE6CC17F4
5 changed files with 90 additions and 64 deletions

View file

@ -14,6 +14,7 @@
#include <fnmatch.h> #include <fnmatch.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <uthash.h>
// libpcre // libpcre
#ifdef CONFIG_REGEX_PCRE #ifdef CONFIG_REGEX_PCRE
@ -53,6 +54,16 @@ typedef struct {
}; };
} c2_ptr_t; } c2_ptr_t;
struct c2_tracked_property {
UT_hash_handle hh;
xcb_atom_t property;
};
struct c2_state {
struct c2_tracked_property *tracked_properties;
struct atom *atoms;
};
/// Initializer for c2_ptr_t. /// Initializer for c2_ptr_t.
#define C2_PTR_INIT \ #define C2_PTR_INIT \
{ .isbranch = false, .l = NULL, } { .isbranch = false, .l = NULL, }
@ -1039,7 +1050,7 @@ fail:
/** /**
* Do postprocessing on a condition leaf. * Do postprocessing on a condition leaf.
*/ */
static bool c2_l_postprocess(session_t *ps, c2_l_t *pleaf) { static bool c2_l_postprocess(struct c2_state *state, xcb_connection_t *c, c2_l_t *pleaf) {
// Give a pattern type to a leaf with exists operator, if needed // Give a pattern type to a leaf with exists operator, if needed
if (C2_L_OEXISTS == pleaf->op && !pleaf->ptntype) { if (C2_L_OEXISTS == pleaf->op && !pleaf->ptntype) {
pleaf->ptntype = (C2_L_TSTRING == pleaf->type ? C2_L_PTSTRING : C2_L_PTINT); pleaf->ptntype = (C2_L_TSTRING == pleaf->type ? C2_L_PTSTRING : C2_L_PTINT);
@ -1047,27 +1058,21 @@ static bool c2_l_postprocess(session_t *ps, c2_l_t *pleaf) {
// Get target atom if it's not a predefined one // Get target atom if it's not a predefined one
if (pleaf->predef == C2_L_PUNDEFINED) { if (pleaf->predef == C2_L_PUNDEFINED) {
pleaf->tgtatom = get_atom(ps->atoms, pleaf->tgt, ps->c.c); pleaf->tgtatom = get_atom(state->atoms, pleaf->tgt, c);
if (!pleaf->tgtatom) { if (!pleaf->tgtatom) {
log_error("Failed to get atom for target \"%s\".", pleaf->tgt); log_error("Failed to get atom for target \"%s\".", pleaf->tgt);
return false; return false;
} }
} }
// Insert target Atom into atom track list // Insert target atom into tracked property name list
if (pleaf->tgtatom) { if (pleaf->tgtatom) {
bool found = false; struct c2_tracked_property *property;
for (latom_t *platom = ps->track_atom_lst; platom; platom = platom->next) { HASH_FIND_INT(state->tracked_properties, &pleaf->tgtatom, property);
if (pleaf->tgtatom == platom->atom) { if (property == NULL) {
found = true; property = cmalloc(struct c2_tracked_property);
break; property->property = pleaf->tgtatom;
} HASH_ADD_INT(state->tracked_properties, property, property);
}
if (!found) {
auto pnew = cmalloc(latom_t);
pnew->next = ps->track_atom_lst;
pnew->atom = pleaf->tgtatom;
ps->track_atom_lst = pnew;
} }
} }
@ -1123,20 +1128,19 @@ static bool c2_l_postprocess(session_t *ps, c2_l_t *pleaf) {
return true; return true;
} }
static bool c2_tree_postprocess(session_t *ps, c2_ptr_t node) { static bool c2_tree_postprocess(struct c2_state *state, xcb_connection_t *c, c2_ptr_t node) {
if (!node.isbranch) { if (!node.isbranch) {
return c2_l_postprocess(ps, node.l); return c2_l_postprocess(state, c, node.l);
} }
if (!c2_tree_postprocess(ps, node.b->opr1)) {
return false; return c2_tree_postprocess(state, c, node.b->opr1) &&
} c2_tree_postprocess(state, c, node.b->opr2);
return c2_tree_postprocess(ps, node.b->opr2);
} }
bool c2_list_postprocess(session_t *ps, c2_lptr_t *list) { bool c2_list_postprocess(struct c2_state *state, xcb_connection_t *c, c2_lptr_t *list) {
c2_lptr_t *head = list; c2_lptr_t *head = list;
while (head) { while (head) {
if (!c2_tree_postprocess(ps, head->ptr)) { if (!c2_tree_postprocess(state, c, head->ptr)) {
return false; return false;
} }
head = head->next; head = head->next;
@ -1729,3 +1733,24 @@ bool c2_list_foreach(const c2_lptr_t *condlist, c2_list_foreach_cb_t cb, void *d
void *c2_list_get_data(const c2_lptr_t *condlist) { void *c2_list_get_data(const c2_lptr_t *condlist) {
return condlist->data; return condlist->data;
} }
struct c2_state *c2_state_new(struct atom *atoms) {
auto ret = ccalloc(1, struct c2_state);
ret->atoms = atoms;
return ret;
}
void c2_state_free(struct c2_state *state) {
struct c2_tracked_property *property, *tmp;
HASH_ITER(hh, state->tracked_properties, property, tmp) {
HASH_DEL(state->tracked_properties, property);
free(property);
}
free(state);
}
bool c2_is_property_tracked(struct c2_state *state, xcb_atom_t property) {
struct c2_tracked_property *p;
HASH_FIND_INT(state->tracked_properties, &property, p);
return p != NULL;
}

View file

@ -13,9 +13,12 @@
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <xcb/xproto.h>
typedef struct _c2_lptr c2_lptr_t; typedef struct _c2_lptr c2_lptr_t;
typedef struct session session_t; typedef struct session session_t;
struct c2_state;
struct atom;
struct managed_win; struct managed_win;
typedef void (*c2_userdata_free)(void *); typedef void (*c2_userdata_free)(void *);
@ -23,10 +26,19 @@ c2_lptr_t *c2_parse(c2_lptr_t **pcondlst, const char *pattern, void *data);
c2_lptr_t *c2_free_lptr(c2_lptr_t *lp, c2_userdata_free f); c2_lptr_t *c2_free_lptr(c2_lptr_t *lp, c2_userdata_free f);
/// Create a new c2_state object. This is used for maintaining the internal state
/// used for c2 condition matching. This state object holds a reference to the
/// pass atom object, thus the atom object should be kept alive as long as the
/// state object is alive.
struct c2_state *c2_state_new(struct atom *atoms);
void c2_state_free(struct c2_state *state);
/// Returns true if value of the property is used in any condition.
bool c2_is_property_tracked(struct c2_state *state, xcb_atom_t property);
bool c2_match(session_t *ps, const struct managed_win *w, const c2_lptr_t *condlst, bool c2_match(session_t *ps, const struct managed_win *w, const c2_lptr_t *condlst,
void **pdata); void **pdata);
bool c2_list_postprocess(session_t *ps, c2_lptr_t *list); bool c2_list_postprocess(struct c2_state *state, xcb_connection_t *c, c2_lptr_t *list);
typedef bool (*c2_list_foreach_cb_t)(const c2_lptr_t *cond, void *data); typedef bool (*c2_list_foreach_cb_t)(const c2_lptr_t *cond, void *data);
bool c2_list_foreach(const c2_lptr_t *list, c2_list_foreach_cb_t cb, void *data); bool c2_list_foreach(const c2_lptr_t *list, c2_list_foreach_cb_t cb, void *data);
/// Return user data stored in a condition. /// Return user data stored in a condition.

View file

@ -234,6 +234,8 @@ typedef struct session {
uint64_t root_flags; uint64_t root_flags;
/// Program options. /// Program options.
options_t o; options_t o;
/// State object for c2.
struct c2_state *c2_state;
/// Whether we have hit unredirection timeout. /// Whether we have hit unredirection timeout.
bool tmout_unredir_hit; bool tmout_unredir_hit;
/// If the backend is busy. This means two things: /// If the backend is busy. This means two things:
@ -376,8 +378,6 @@ typedef struct session {
struct atom *atoms; struct atom *atoms;
/// Array of atoms of all possible window types. /// Array of atoms of all possible window types.
xcb_atom_t atoms_wintypes[NUM_WINTYPES]; xcb_atom_t atoms_wintypes[NUM_WINTYPES];
/// Linked list of additional atoms to track.
latom_t *track_atom_lst;
#ifdef CONFIG_DBUS #ifdef CONFIG_DBUS
// === DBus related === // === DBus related ===

View file

@ -11,6 +11,7 @@
#include <xcb/xcb_event.h> #include <xcb/xcb_event.h>
#include "atom.h" #include "atom.h"
#include "c2.h"
#include "common.h" #include "common.h"
#include "compiler.h" #include "compiler.h"
#include "config.h" #include "config.h"
@ -573,20 +574,17 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
} }
// Check for other atoms we are tracking // Check for other atoms we are tracking
for (latom_t *platom = ps->track_atom_lst; platom; platom = platom->next) { if (c2_is_property_tracked(ps->c2_state, ev->atom)) {
if (platom->atom == ev->atom) { auto w = find_managed_win(ps, ev->window);
auto w = find_managed_win(ps, ev->window); if (!w) {
if (!w) { w = find_toplevel(ps, ev->window);
w = find_toplevel(ps, ev->window); }
} if (w) {
if (w) { // Set FACTOR_CHANGED so rules based on properties will be
// Set FACTOR_CHANGED so rules based on properties will be // re-evaluated.
// re-evaluated. // Don't need to set property stale here, since that only
// Don't need to set property stale here, since that only // concerns properties we explicitly check.
// concerns properties we explicitly check. win_set_flags(w, WIN_FLAGS_FACTOR_CHANGED);
win_set_flags(w, WIN_FLAGS_FACTOR_CHANGED);
}
break;
} }
} }
} }

View file

@ -2071,7 +2071,6 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
.xrfilter_convolution_exists = false, .xrfilter_convolution_exists = false,
.atoms_wintypes = {0}, .atoms_wintypes = {0},
.track_atom_lst = NULL,
#ifdef CONFIG_DBUS #ifdef CONFIG_DBUS
.dbus_data = NULL, .dbus_data = NULL,
@ -2266,19 +2265,21 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
SET_WM_TYPE_ATOM(DND); SET_WM_TYPE_ATOM(DND);
#undef SET_WM_TYPE_ATOM #undef SET_WM_TYPE_ATOM
ps->c2_state = c2_state_new(ps->atoms);
// Get needed atoms for c2 condition lists // Get needed atoms for c2 condition lists
if (!(c2_list_postprocess(ps, ps->o.unredir_if_possible_blacklist) && if (!(c2_list_postprocess(ps->c2_state, ps->c.c, ps->o.unredir_if_possible_blacklist) &&
c2_list_postprocess(ps, ps->o.paint_blacklist) && c2_list_postprocess(ps->c2_state, ps->c.c, ps->o.paint_blacklist) &&
c2_list_postprocess(ps, ps->o.shadow_blacklist) && c2_list_postprocess(ps->c2_state, ps->c.c, ps->o.shadow_blacklist) &&
c2_list_postprocess(ps, ps->o.shadow_clip_list) && c2_list_postprocess(ps->c2_state, ps->c.c, ps->o.shadow_clip_list) &&
c2_list_postprocess(ps, ps->o.fade_blacklist) && c2_list_postprocess(ps->c2_state, ps->c.c, ps->o.fade_blacklist) &&
c2_list_postprocess(ps, ps->o.blur_background_blacklist) && c2_list_postprocess(ps->c2_state, ps->c.c, ps->o.blur_background_blacklist) &&
c2_list_postprocess(ps, ps->o.invert_color_list) && c2_list_postprocess(ps->c2_state, ps->c.c, ps->o.invert_color_list) &&
c2_list_postprocess(ps, ps->o.window_shader_fg_rules) && c2_list_postprocess(ps->c2_state, ps->c.c, ps->o.window_shader_fg_rules) &&
c2_list_postprocess(ps, ps->o.opacity_rules) && c2_list_postprocess(ps->c2_state, ps->c.c, ps->o.opacity_rules) &&
c2_list_postprocess(ps, ps->o.rounded_corners_blacklist) && c2_list_postprocess(ps->c2_state, ps->c.c, ps->o.rounded_corners_blacklist) &&
c2_list_postprocess(ps, ps->o.corner_radius_rules) && c2_list_postprocess(ps->c2_state, ps->c.c, ps->o.corner_radius_rules) &&
c2_list_postprocess(ps, ps->o.focus_blacklist))) { c2_list_postprocess(ps->c2_state, ps->c.c, ps->o.focus_blacklist))) {
log_error("Post-processing of conditionals failed, some of your rules " log_error("Post-processing of conditionals failed, some of your rules "
"might not work"); "might not work");
} }
@ -2693,17 +2694,7 @@ static void session_destroy(session_t *ps) {
c2_list_free(&ps->o.rounded_corners_blacklist, NULL); c2_list_free(&ps->o.rounded_corners_blacklist, NULL);
c2_list_free(&ps->o.corner_radius_rules, NULL); c2_list_free(&ps->o.corner_radius_rules, NULL);
c2_list_free(&ps->o.window_shader_fg_rules, free); c2_list_free(&ps->o.window_shader_fg_rules, free);
c2_state_free(ps->c2_state);
// 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;
}
// Free tgt_{buffer,picture} and root_picture // Free tgt_{buffer,picture} and root_picture
if (ps->tgt_buffer.pict == ps->tgt_picture) { if (ps->tgt_buffer.pict == ps->tgt_picture) {