Skip to content

Commit

Permalink
c2: beginning to separate some state out of session_t
Browse files Browse the repository at this point in the history
This is just the beginning, c2_match still needs session_t, everything
is just so tangled...

Signed-off-by: Yuxuan Shui <[email protected]>
  • Loading branch information
yshui committed Feb 13, 2024
1 parent 4f79224 commit c9e64c4
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 55 deletions.
60 changes: 46 additions & 14 deletions src/c2.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <fnmatch.h>
#include <stdio.h>
#include <string.h>
#include "uthash.h"

// libpcre
#ifdef CONFIG_REGEX_PCRE
Expand All @@ -29,6 +30,7 @@
#include "common.h"
#include "compiler.h"
#include "config.h"
#include "list.h"
#include "log.h"
#include "string_utils.h"
#include "utils.h"
Expand All @@ -53,6 +55,16 @@ typedef struct {
};
} 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.
#define C2_PTR_INIT \
{ .isbranch = false, .l = NULL, }
Expand Down Expand Up @@ -1039,15 +1051,15 @@ static int c2_parse_legacy(const char *pattern, int offset, c2_ptr_t *presult) {
/**
* 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, 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 == C2_L_PUNDEFINED) {
pleaf->tgtatom = get_atom(ps->atoms, pleaf->tgt);
pleaf->tgtatom = get_atom(state->atoms, pleaf->tgt);
if (!pleaf->tgtatom) {
log_error("Failed to get atom for target \"%s\".", pleaf->tgt);
return false;
Expand All @@ -1057,17 +1069,16 @@ static bool c2_l_postprocess(session_t *ps, c2_l_t *pleaf) {
// 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) {
HASH_ITER2(state->tracked_properties, property) {
if (pleaf->tgtatom == property->property) {
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;
auto pnew = cmalloc(struct c2_tracked_property);
pnew->property = pleaf->tgtatom;
HASH_ADD_INT(state->tracked_properties, property, pnew);
}
}

Expand Down Expand Up @@ -1123,20 +1134,20 @@ static bool c2_l_postprocess(session_t *ps, c2_l_t *pleaf) {
return true;
}

static bool c2_tree_postprocess(session_t *ps, c2_ptr_t node) {
static bool c2_tree_postprocess(struct c2_state *state, c2_ptr_t node) {
if (!node.isbranch) {
return c2_l_postprocess(ps, node.l);
return c2_l_postprocess(state, node.l);
}
if (!c2_tree_postprocess(ps, node.b->opr1)) {
if (!c2_tree_postprocess(state, node.b->opr1)) {
return false;
}
return c2_tree_postprocess(ps, node.b->opr2);
return c2_tree_postprocess(state, node.b->opr2);
}

bool c2_list_postprocess(session_t *ps, c2_lptr_t *list) {
bool c2_list_postprocess(struct c2_state *state, c2_lptr_t *list) {
c2_lptr_t *head = list;
while (head) {
if (!c2_tree_postprocess(ps, head->ptr)) {
if (!c2_tree_postprocess(state, head->ptr)) {
return false;
}
head = head->next;
Expand Down Expand Up @@ -1732,3 +1743,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) {
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;
}
14 changes: 13 additions & 1 deletion src/c2.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,32 @@

#include <stdbool.h>
#include <stddef.h>
#include <xcb/xproto.h>

typedef struct _c2_lptr c2_lptr_t;
typedef struct session session_t;
struct c2_state;
struct atom;
struct managed_win;

typedef void (*c2_userdata_free)(void *);
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);

/// 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,
void **pdata);

bool c2_list_postprocess(session_t *ps, c2_lptr_t *list);
bool c2_list_postprocess(struct c2_state *state, c2_lptr_t *list);
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);
/// Return user data stored in a condition.
Expand Down
4 changes: 2 additions & 2 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ typedef struct session {
uint64_t root_flags;
/// Program options.
options_t o;
/// State object for c2.
struct c2_state *c2_state;
/// Whether we have hit unredirection timeout.
bool tmout_unredir_hit;
/// If the backend is busy. This means two things:
Expand Down Expand Up @@ -376,8 +378,6 @@ typedef struct session {
struct atom *atoms;
/// 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 ===
Expand Down
26 changes: 12 additions & 14 deletions src/event.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <xcb/xcb_event.h>

#include "atom.h"
#include "c2.h"
#include "common.h"
#include "compiler.h"
#include "config.h"
Expand Down Expand Up @@ -566,20 +567,17 @@ static inline void ev_property_notify(session_t *ps, xcb_property_notify_event_t
}

// Check for other atoms we are tracking
for (latom_t *platom = ps->track_atom_lst; platom; platom = platom->next) {
if (platom->atom == ev->atom) {
auto w = find_managed_win(ps, ev->window);
if (!w) {
w = find_toplevel(ps, ev->window);
}
if (w) {
// Set FACTOR_CHANGED so rules based on properties will be
// re-evaluated.
// Don't need to set property stale here, since that only
// concerns properties we explicitly check.
win_set_flags(w, WIN_FLAGS_FACTOR_CHANGED);
}
break;
if (c2_is_property_tracked(ps->c2_state, ev->atom)) {
auto w = find_managed_win(ps, ev->window);
if (!w) {
w = find_toplevel(ps, ev->window);
}
if (w) {
// Set FACTOR_CHANGED so rules based on properties will be
// re-evaluated.
// Don't need to set property stale here, since that only
// concerns properties we explicitly check.
win_set_flags(w, WIN_FLAGS_FACTOR_CHANGED);
}
}
}
Expand Down
39 changes: 15 additions & 24 deletions src/picom.c
Original file line number Diff line number Diff line change
Expand Up @@ -2060,7 +2060,6 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
.xrfilter_convolution_exists = false,

.atoms_wintypes = {0},
.track_atom_lst = NULL,

#ifdef CONFIG_DBUS
.dbus_data = NULL,
Expand Down Expand Up @@ -2255,19 +2254,21 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
SET_WM_TYPE_ATOM(DND);
#undef SET_WM_TYPE_ATOM

ps->c2_state = c2_state_new(ps->atoms);

// 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.shadow_clip_list) &&
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.window_shader_fg_rules) &&
c2_list_postprocess(ps, ps->o.opacity_rules) &&
c2_list_postprocess(ps, ps->o.rounded_corners_blacklist) &&
c2_list_postprocess(ps, ps->o.corner_radius_rules) &&
c2_list_postprocess(ps, ps->o.focus_blacklist))) {
if (!(c2_list_postprocess(ps->c2_state, ps->o.unredir_if_possible_blacklist) &&
c2_list_postprocess(ps->c2_state, ps->o.paint_blacklist) &&
c2_list_postprocess(ps->c2_state, ps->o.shadow_blacklist) &&
c2_list_postprocess(ps->c2_state, ps->o.shadow_clip_list) &&
c2_list_postprocess(ps->c2_state, ps->o.fade_blacklist) &&
c2_list_postprocess(ps->c2_state, ps->o.blur_background_blacklist) &&
c2_list_postprocess(ps->c2_state, ps->o.invert_color_list) &&
c2_list_postprocess(ps->c2_state, ps->o.window_shader_fg_rules) &&
c2_list_postprocess(ps->c2_state, ps->o.opacity_rules) &&
c2_list_postprocess(ps->c2_state, ps->o.rounded_corners_blacklist) &&
c2_list_postprocess(ps->c2_state, ps->o.corner_radius_rules) &&
c2_list_postprocess(ps->c2_state, ps->o.focus_blacklist))) {
log_error("Post-processing of conditionals failed, some of your rules "
"might not work");
}
Expand Down Expand Up @@ -2687,17 +2688,7 @@ static void session_destroy(session_t *ps) {
c2_list_free(&ps->o.rounded_corners_blacklist, NULL);
c2_list_free(&ps->o.corner_radius_rules, NULL);
c2_list_free(&ps->o.window_shader_fg_rules, free);

// 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;
}
c2_state_free(ps->c2_state);

// Free tgt_{buffer,picture} and root_picture
if (ps->tgt_buffer.pict == ps->tgt_picture) {
Expand Down

0 comments on commit c9e64c4

Please sign in to comment.