From 6f8f2bbf94bed9da21f84561df0dc90456c70af4 Mon Sep 17 00:00:00 2001 From: HuntedByTheIRS Date: Fri, 3 Jul 2026 04:13:54 -0400 Subject: [PATCH] Revert "parser: add CfgApplyEffects struct and extend CfgRule with fullscreen, can_float, can_fullscreen, apply_effects" This reverts commit 690c328c3806dfb155816e13312b1e6f122fdc83. --- example/config.lua | 28 +--------- include/client.h | 21 -------- parser/parser.c | 39 +------------- parser/parser.h | 27 ++-------- src/peachwm.c | 130 +++++++++++++++++---------------------------- 5 files changed, 59 insertions(+), 186 deletions(-) diff --git a/example/config.lua b/example/config.lua index 43955db..cceeadf 100644 --- a/example/config.lua +++ b/example/config.lua @@ -34,32 +34,8 @@ input = { } rules = { - -- Each rule matches when ALL provided fields (app_id, title, etc.) - -- match the window. Per-rule apply_effects toggles are overlays on - -- the global effects block — both must be ON for the effect to apply. - { - app_id = "firefox", - floating = false, - can_float = true, -- false prevents togglefloating for this window - fullscreen = false, - can_fullscreen = true, - tags = "any", -- "any" → all tags; or a bitmask like 1 << 3 - monitor = "default", -- "default" → current monitor; or a number to pin - apply_effects = { - rounding = true, - shadows = false, - transparency = false, - blur = false, - gaps = true, - smartgaps = false, - border = true, - sloppy_focus = false, - }, - }, - - -- { app_id = "Gimp", floating = true, monitor = -1 }, - -- { app_id = "firefox", tags = 1 << 8, floating = false, monitor = -1 }, - -- { title = "Calculator", floating = true, tags = "any" }, + -- { app_id = "Gimp", floating = true, monitor = -1 }, + -- { app_id = "firefox", tags = 1 << 8, floating = false, monitor = -1 }, } monitors = { diff --git a/include/client.h b/include/client.h index af1827f..9902152 100644 --- a/include/client.h +++ b/include/client.h @@ -19,18 +19,6 @@ struct wlr_scene_shadow; /* Client types */ enum { XDGShell, LayerShell, X11 }; -/* Per-client rule effects — standalone typedef (no parser.h include to avoid circular deps) */ -typedef struct { - bool rounding; - bool shadows; - bool transparency; - bool blur; - bool gaps; - bool smartgaps; - bool border; - bool sloppy_focus; -} ClientRuleEffects; - typedef struct Client { /* Must keep this field first — union-cast discriminant */ unsigned int type; /* XDGShell or X11 */ @@ -62,15 +50,6 @@ typedef struct Client { struct wlr_scene_tree *scene_surface; struct wlr_xdg_toplevel_decoration_v1 *decoration; - /* Per-rule constraints and effects */ - bool can_float; - bool can_fullscreen; - ClientRuleEffects rule_effects; - - /* Deferred monitor/tags — set by applyrules, used by setmon in mapnotify */ - Monitor *pending_mon; - uint32_t pending_tags; - /* COLD — wl_listeners (set up once, rarely touched after) */ struct wl_listener commit; struct wl_listener map; diff --git a/parser/parser.c b/parser/parser.c index d4f0be5..7a41921 100644 --- a/parser/parser.c +++ b/parser/parser.c @@ -296,44 +296,9 @@ parse_rules(lua_State *L, Config *cfg) memset(r, 0, sizeof(*r)); lua_get_string(L, "app_id", r->app_id, sizeof(r->app_id)); lua_get_string(L, "title", r->title, sizeof(r->title)); - r->fullscreen = lua_get_bool(L, "fullscreen", false); - r->can_float = lua_get_bool(L, "can_float", true); - r->can_fullscreen= lua_get_bool(L, "can_fullscreen", true); - - /* tags: "any" → 0 (all tags), number → as-is, missing → 0 */ - lua_getfield(L, -1, "tags"); - if (lua_isstring(L, -1) && !strcmp(lua_tostring(L, -1), "any")) - r->tags = 0; - else - r->tags = (uint32_t)(lua_isnumber(L, -1) - ? (int)lua_tointeger(L, -1) : 0); - lua_pop(L, 1); - + r->tags = (uint32_t)lua_get_int(L, "tags", 0); r->floating = lua_get_bool(L, "floating", false); - - /* monitor: "default" → -1 (current), number → as-is, missing → -1 */ - lua_getfield(L, -1, "monitor"); - if (lua_isstring(L, -1) && !strcmp(lua_tostring(L, -1), "default")) - r->monitor = -1; - else - r->monitor = lua_isnumber(L, -1) - ? (int)lua_tointeger(L, -1) : -1; - lua_pop(L, 1); - - /* Default: all effects follow global (true = no override) */ - memset(&r->apply_effects, 1, sizeof(r->apply_effects)); - lua_getfield(L, -1, "apply_effects"); - if (lua_istable(L, -1)) { - r->apply_effects.rounding = lua_get_bool(L, "rounding", true); - r->apply_effects.shadows = lua_get_bool(L, "shadows", true); - r->apply_effects.transparency = lua_get_bool(L, "transparency", true); - r->apply_effects.blur = lua_get_bool(L, "blur", true); - r->apply_effects.gaps = lua_get_bool(L, "gaps", true); - r->apply_effects.smartgaps = lua_get_bool(L, "smartgaps", true); - r->apply_effects.border = lua_get_bool(L, "border", true); - r->apply_effects.sloppy_focus = lua_get_bool(L, "sloppy_focus", true); - } - lua_pop(L, 1); + r->monitor = lua_get_int(L, "monitor", -1); lua_pop(L, 1); } diff --git a/parser/parser.h b/parser/parser.h index a385b68..f0dbd39 100644 --- a/parser/parser.h +++ b/parser/parser.h @@ -45,31 +45,14 @@ typedef struct { int tap_button_map; /* libinput enum value */ } CfgInput; -/* Per-rule effect toggles — which effects to apply to matched windows */ - -typedef struct { - bool rounding; - bool shadows; - bool transparency; - bool blur; - bool gaps; - bool smartgaps; - bool border; - bool sloppy_focus; -} CfgApplyEffects; - /* Window Rules */ typedef struct { - char app_id[CFG_MAX_STRLEN]; - char title[CFG_MAX_STRLEN]; /* empty string = wildcard */ - uint32_t tags; - bool floating; - bool fullscreen; - bool can_float; - bool can_fullscreen; - CfgApplyEffects apply_effects; - int monitor; /* -1 = current */ + char app_id[CFG_MAX_STRLEN]; + char title[CFG_MAX_STRLEN]; /* empty string = wildcard */ + uint32_t tags; + bool floating; + int monitor; /* -1 = current */ } CfgRule; /* Monitor Rules */ diff --git a/src/peachwm.c b/src/peachwm.c index 1ddfbb3..6f4ad1d 100644 --- a/src/peachwm.c +++ b/src/peachwm.c @@ -469,19 +469,11 @@ static void applyrules(Client *c) { appid = client_get_appid(c); title = client_get_title(c); - c->can_float = true; - c->can_fullscreen = true; - memset(&c->rule_effects, 0xFF, sizeof(c->rule_effects)); - for (ri = 0; ri < cfg.nrules; ri++) { const CfgRule *r = &cfg.rules[ri]; if ((!r->title[0] || strstr(title, r->title)) && (!r->app_id[0] || strstr(appid, r->app_id))) { c->isfloating = r->floating; - c->isfullscreen = r->fullscreen; - c->can_float = r->can_float; - c->can_fullscreen = r->can_fullscreen; - memcpy(&c->rule_effects, &r->apply_effects, sizeof(c->rule_effects)); newtags |= r->tags; i = 0; wl_list_for_each(m, &mons, link) { @@ -492,8 +484,7 @@ static void applyrules(Client *c) { } c->isfloating |= client_is_float_type(c); - c->pending_mon = mon; - c->pending_tags = newtags; + setmon(c, mon, newtags); } static void client_arr_add(Client *c) { @@ -534,8 +525,6 @@ static void fstack_arr_remove(Client *c) { } } -/* TODO: per-client gaps/smartgaps via c->rule_effects.gaps | smartgaps — - * requires layout.c changes since gaps are per-monitor, not per-client */ void arrange(Monitor *m) { Client *c; @@ -957,9 +946,10 @@ static void commitnotify(struct wl_listener *listener, void *data) { * a wrong monitor. */ applyrules(c); - if (c->pending_mon) { - client_set_scale(client_surface(c), c->pending_mon->wlr_output->scale); + if (c->mon) { + client_set_scale(client_surface(c), c->mon->wlr_output->scale); } + setmon(c, nullptr, 0); /* Make sure to reapply rules in mapnotify() */ wlr_xdg_toplevel_set_wm_capabilities( c->surface.xdg->toplevel, WLR_XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN); @@ -1605,7 +1595,7 @@ void focusclient(Client *c, int lift) { /* Activate the new client */ client_activate_surface(client_surface(c), 1); - if (cfg.sloppyfocus && c->rule_effects.sloppy_focus && warp_focus) + if (cfg.sloppyfocus && warp_focus) wlr_cursor_warp(cursor, nullptr, c->geom.x + c->geom.width / 2, c->geom.y + c->geom.height / 2); } @@ -2219,22 +2209,18 @@ static void mapnotify(struct wl_listener *listener, void *data) { goto unset_fullscreen; } - applyrules(c); - /* Create single border background rect */ - if (c->rule_effects.border) { - c->border_bg = wlr_scene_rect_create(c->scene, 0, 0, - c->isurgent ? cfg.appearance.urgent_color : cfg.appearance.border_color); - c->border_bg->node.data = c; - } + c->border_bg = wlr_scene_rect_create(c->scene, 0, 0, + c->isurgent ? cfg.appearance.urgent_color : cfg.appearance.border_color); + c->border_bg->node.data = c; { - int r = c->rule_effects.rounding ? config_get_corner_radius() : 0; + int r = config_get_corner_radius(); c->corner_radius = r; } /* Create drop shadow */ - if (cfg.effects.windows.shadows.shadows && c->rule_effects.shadows && !client_is_unmanaged(c)) { + if (cfg.effects.windows.shadows.shadows && !client_is_unmanaged(c)) { float sc[4]; parse_color_hex(cfg.effects.windows.shadows.shadow_color, sc); sc[3] *= cfg.effects.windows.shadows.shadow_opacity; @@ -2252,8 +2238,7 @@ static void mapnotify(struct wl_listener *listener, void *data) { - cfg.effects.windows.shadows.shadow_expand, cfg.effects.windows.shadows.shadow_offset_y - cfg.effects.windows.shadows.shadow_expand); - if (c->border_bg) - wlr_scene_node_place_below(&c->shadow->node, &c->border_bg->node); + wlr_scene_node_place_below(&c->shadow->node, &c->border_bg->node); } } @@ -2263,39 +2248,31 @@ static void mapnotify(struct wl_listener *listener, void *data) { : wlr_scene_subsurface_tree_create(c->scene, client_surface(c)); c->scene_surface->node.data = c; - /* Create blur node (only if per-client rule allows) */ - if (c->rule_effects.blur) { - c->blur = wlr_scene_blur_create(c->scene, - (int)(c->geom.width - 2 * c->bw), - (int)(c->geom.height - 2 * c->bw)); - if (c->blur) { - wlr_scene_node_set_position(&c->blur->node, c->bw, c->bw); - /* Place blur BELOW surface so it samples background BEFORE the sharp surface composites */ - wlr_scene_node_place_below(&c->blur->node, &c->scene_surface->node); - if (c->shadow) - wlr_scene_node_place_above(&c->blur->node, &c->shadow->node); - wlr_scene_blur_set_corner_radius(c->blur, c->corner_radius); - wlr_scene_blur_set_alpha(c->blur, 1.0f); - wlr_scene_blur_set_strength(c->blur, 1.0f); - /* Set transparency mask source so SceneFX only renders blur where window has alpha < 1.0 */ - struct wlr_scene_node *child; - wl_list_for_each(child, &c->scene_surface->children, link) { - if (child->type == WLR_SCENE_NODE_BUFFER) { - wlr_scene_blur_set_transparency_mask_source(c->blur, - wlr_scene_buffer_from_node(child)); - break; - } + /* Create blur node (always created, visibility controlled via set_enabled) */ + c->blur = wlr_scene_blur_create(c->scene, + (int)(c->geom.width - 2 * c->bw), + (int)(c->geom.height - 2 * c->bw)); + if (c->blur) { + wlr_scene_node_set_position(&c->blur->node, c->bw, c->bw); + /* Place blur BELOW surface so it samples background BEFORE the sharp surface composites */ + wlr_scene_node_place_below(&c->blur->node, &c->scene_surface->node); + if (c->shadow) + wlr_scene_node_place_above(&c->blur->node, &c->shadow->node); + wlr_scene_blur_set_corner_radius(c->blur, c->corner_radius); + wlr_scene_blur_set_alpha(c->blur, 1.0f); + wlr_scene_blur_set_strength(c->blur, 1.0f); + /* Set transparency mask source so SceneFX only renders blur where window has alpha < 1.0 */ + struct wlr_scene_node *child; + wl_list_for_each(child, &c->scene_surface->children, link) { + if (child->type == WLR_SCENE_NODE_BUFFER) { + wlr_scene_blur_set_transparency_mask_source(c->blur, + wlr_scene_buffer_from_node(child)); + break; } } } - /* Deferred setmon — scene nodes now exist */ - setmon(c, c->pending_mon, c->pending_tags); - - if (c->isfullscreen) - setfullscreen(c, 1); - if (c->border_bg) - wlr_scene_node_raise_to_top(&c->border_bg->node); + wlr_scene_node_raise_to_top(&c->border_bg->node); /* Initialize client geometry with room for border */ client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | @@ -2309,12 +2286,15 @@ static void mapnotify(struct wl_listener *listener, void *data) { client_arr_add(c); fstack_arr_add(c); - /* Override monitor/tags for parented clients (dialogs, popups): - * they inherit the parent's monitor and tags; applyrules(c) already - * ran above for rule_effects (border, shadow, blur, corner_radius). */ + /* Set initial monitor, tags, floating status, and focus: + * we always consider floating, clients that have parent and thus + * we set the same tags and monitor as its parent. + * If there is no parent, apply rules */ if ((p = client_get_parent(c))) { c->isfloating = 1; setmon(c, p->mon, p->tags); + } else { + applyrules(c); } /* Auto-send to scratchpad if scratchpad is visible */ if (c->mon && c->mon->scratchpad_visible && !c->isscratchpad && @@ -2595,7 +2575,7 @@ static void pointerfocus(Client *c, struct wlr_surface *surface, double sx, doub struct timespec now; if (surface != seat->pointer_state.focused_surface && cfg.sloppyfocus && - time && c && !client_is_unmanaged(c) && c->rule_effects.sloppy_focus) { + time && c && !client_is_unmanaged(c)) { warp_focus = false; focusclient(c, 0); warp_focus = true; @@ -2697,7 +2677,7 @@ static void rendermon(struct wl_listener *listener, void *data) { { Client *c; wl_list_for_each(c, &clients, link) { - if (c->mon == m && c->scene_surface && c->corner_radius > 0 && c->rule_effects.rounding && !c->isfullscreen) { + if (c->mon == m && c->scene_surface && c->corner_radius > 0 && !c->isfullscreen) { apply_surface_corners(&c->scene_surface->node, c->corner_radius); } } @@ -2709,7 +2689,7 @@ static void rendermon(struct wl_listener *listener, void *data) { wl_list_for_each(c, &clients, link) { if (c->mon != m) continue; - if (!cfg.effects.windows.transparency.enabled || !c->rule_effects.transparency) + if (!cfg.effects.windows.transparency.enabled) continue; if (!VISIBLEON(c, m)) continue; @@ -2809,7 +2789,7 @@ void resize(Client *c, struct wlr_box geo, int interact) { } /* Update single border rect with clipped region hole */ - if (c->border_bg && c->rule_effects.border) { + if (c->border_bg) { int bw_i = (int)c->bw; int cw = (int)c->geom.width; int ch = (int)c->geom.height; @@ -2842,7 +2822,6 @@ void resize(Client *c, struct wlr_box geo, int interact) { /* Update drop shadow */ if (c->shadow) { bool shadow_visible = cfg.effects.windows.shadows.shadows - && c->rule_effects.shadows && (cfg.effects.windows.shadows.fullscreen_shadows || !c->isfullscreen) && (!cfg.effects.windows.shadows.only_floating || c->isfloating); if (!cfg.effects.windows.shadows.nogaps_shadows && !c->mon->gaps) @@ -2931,7 +2910,6 @@ void resize(Client *c, struct wlr_box geo, int interact) { /* scratchpad windows */ if (c->isscratchpad) blur_enabled = false; - blur_enabled = blur_enabled && c->rule_effects.blur; wlr_scene_node_set_enabled(&c->blur->node, blur_enabled); } @@ -3064,7 +3042,7 @@ static void setfullscreen(Client *c, int fullscreen) { if (c->blur) wlr_scene_node_set_enabled(&c->blur->node, false); } else { - c->corner_radius = c->rule_effects.rounding ? config_get_corner_radius() : 0; + c->corner_radius = config_get_corner_radius(); if (c->border_bg) { wlr_scene_node_set_enabled(&c->border_bg->node, true); } @@ -3308,7 +3286,7 @@ reapply_client_appearance(void) wl_list_for_each(c, &clients, link) { c->bw = !c->isfullscreen ? cfg.appearance.border_px : 0; if (!client_is_unmanaged(c)) { - int r = (c->isfullscreen || !c->rule_effects.rounding) ? 0 : config_get_corner_radius(); + int r = c->isfullscreen ? 0 : config_get_corner_radius(); c->corner_radius = r; if (c->border_bg) { if (r > 0 && !c->isfullscreen) { @@ -3322,7 +3300,7 @@ reapply_client_appearance(void) } } /* Shadow re-apply on config reload */ - if (cfg.effects.windows.shadows.shadows && c->rule_effects.shadows) { + if (cfg.effects.windows.shadows.shadows) { if (!c->shadow) { float sc[4]; parse_color_hex(cfg.effects.windows.shadows.shadow_color, sc); @@ -3341,9 +3319,8 @@ reapply_client_appearance(void) - cfg.effects.windows.shadows.shadow_expand, cfg.effects.windows.shadows.shadow_offset_y - cfg.effects.windows.shadows.shadow_expand); - if (c->border_bg) - wlr_scene_node_place_below(&c->shadow->node, - &c->border_bg->node); + wlr_scene_node_place_below(&c->shadow->node, + &c->border_bg->node); } } } else { @@ -3352,7 +3329,7 @@ reapply_client_appearance(void) } } /* Blur re-apply on config reload */ - if (cfg.effects.windows.transparency.blur.enabled && c->rule_effects.blur) { + if (cfg.effects.windows.transparency.blur.enabled) { if (!c->blur) { c->blur = wlr_scene_blur_create(c->scene, (int)(c->geom.width - 2 * (int)c->bw), @@ -3403,9 +3380,6 @@ reapply_client_rules(void) wl_list_for_each(c, &clients, link) { if (client_is_unmanaged(c)) continue; - c->can_float = true; - c->can_fullscreen = true; - memset(&c->rule_effects, 0xFF, sizeof(c->rule_effects)); const char *appid = client_get_appid(c); const char *title = client_get_title(c); for (int ri = 0; ri < cfg.nrules; ri++) { @@ -3413,10 +3387,6 @@ reapply_client_rules(void) if ((!r->title[0] || strstr(title, r->title)) && (!r->app_id[0] || strstr(appid, r->app_id))) { c->isfloating = r->floating | client_is_float_type(c); - c->isfullscreen = r->fullscreen; - c->can_float = r->can_float; - c->can_fullscreen = r->can_fullscreen; - memcpy(&c->rule_effects, &r->apply_effects, sizeof(c->rule_effects)); if (r->tags) { dwindle_remove_client(c); master_remove_client(c); @@ -3836,13 +3806,13 @@ static void tagmon(const Arg *arg) { void togglefloating(const Arg *arg) { Client *sel = focustop(selmon); /* return if fullscreen or scratchpad (strictly floating) */ - if (sel && !sel->isfullscreen && !sel->isscratchpad && sel->can_float) + if (sel && !sel->isfullscreen && !sel->isscratchpad) setfloating(sel, !sel->isfloating); } void togglefullscreen(const Arg *arg) { Client *sel = focustop(selmon); - if (sel && sel->can_fullscreen) + if (sel) setfullscreen(sel, !sel->isfullscreen); }