feat: add stayfocused window rule

This commit is contained in:
prankstr 2026-01-16 10:40:28 +01:00
parent bc1f310e1c
commit d362822546
2 changed files with 22 additions and 1 deletions

View file

@ -83,6 +83,7 @@ typedef struct {
int32_t width;
int32_t height;
int32_t nofocus;
int32_t stayfocused;
int32_t nofadein;
int32_t nofadeout;
int32_t no_force_center;
@ -1732,6 +1733,7 @@ void parse_option(Config *config, char *key, char *value) {
rule->noswallow = -1;
rule->noblur = -1;
rule->nofocus = -1;
rule->stayfocused = -1;
rule->nofadein = -1;
rule->nofadeout = -1;
rule->no_force_center = -1;
@ -1789,6 +1791,8 @@ void parse_option(Config *config, char *key, char *value) {
rule->offsety = atoi(val);
} else if (strcmp(key, "nofocus") == 0) {
rule->nofocus = atoi(val);
} else if (strcmp(key, "stayfocused") == 0) {
rule->stayfocused = atoi(val);
} else if (strcmp(key, "nofadein") == 0) {
rule->nofadein = atoi(val);
} else if (strcmp(key, "nofadeout") == 0) {

View file

@ -388,6 +388,7 @@ struct Client {
bool scratchpad_switching_mon;
bool fake_no_border;
int32_t nofocus;
int32_t stayfocused;
int32_t nofadein;
int32_t nofadeout;
int32_t no_force_center;
@ -1214,6 +1215,7 @@ static void apply_rule_properties(Client *c, const ConfigWinRule *r) {
APPLY_INT_PROP(c, r, force_tearing);
APPLY_INT_PROP(c, r, noswallow);
APPLY_INT_PROP(c, r, nofocus);
APPLY_INT_PROP(c, r, stayfocused);
APPLY_INT_PROP(c, r, nofadein);
APPLY_INT_PROP(c, r, nofadeout);
APPLY_INT_PROP(c, r, no_force_center);
@ -3187,6 +3189,11 @@ void focusclient(Client *c, int32_t lift) {
if (c && c->nofocus)
return;
/* Don't change focus away from a stayfocused window while it's visible */
if (selmon && selmon->sel && selmon->sel != c && selmon->sel->stayfocused &&
VISIBLEON(selmon->sel, selmon) && client_surface(selmon->sel)->mapped)
return;
/* Raise client in stacking order if requested */
if (c && lift)
wlr_scene_node_raise_to_top(&c->scene->node); // 将视图提升到顶层
@ -3232,6 +3239,10 @@ void focusclient(Client *c, int32_t lift) {
// change border color
c->isurgent = 0;
// set exclusive_focus for stayfocused windows
if (c->stayfocused)
exclusive_focus = c;
}
// update other monitor focus disappear
@ -3261,7 +3272,9 @@ void focusclient(Client *c, int32_t lift) {
l->layer_surface->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP &&
l == exclusive_focus) {
return;
} else if (w && w == exclusive_focus && client_wants_focus(w)) {
} else if (w && w == exclusive_focus &&
(client_wants_focus(w) || w->stayfocused) && w->mon &&
VISIBLEON(w, w->mon) && client_surface(w)->mapped) {
return;
/* Don't deactivate old_keyboard_focus_surface client if the new
* one wants focus, as this causes issues with winecfg and
@ -3720,6 +3733,7 @@ void init_client_properties(Client *c) {
c->focused_opacity = focused_opacity;
c->unfocused_opacity = unfocused_opacity;
c->nofocus = 0;
c->stayfocused = 0;
c->nofadein = 0;
c->nofadeout = 0;
c->no_force_center = 0;
@ -5432,6 +5446,9 @@ void unmapnotify(struct wl_listener *listener, void *data) {
}
}
if (c->stayfocused && c == exclusive_focus)
exclusive_focus = NULL;
if (c->mon && c->mon == selmon) {
Client *nextfocus = focustop(selmon);