Add node flag: hidden

Fixes #229.
This commit is contained in:
Bastien Dejean 2016-04-16 18:13:31 +02:00
parent 828c93fb29
commit 331cc9e2d5
15 changed files with 256 additions and 93 deletions

View file

@ -248,6 +248,7 @@ void setup(void)
ewmh->_NET_CLOSE_WINDOW,
ewmh->_NET_WM_DESKTOP,
ewmh->_NET_WM_STATE,
ewmh->_NET_WM_STATE_HIDDEN,
ewmh->_NET_WM_STATE_FULLSCREEN,
ewmh->_NET_WM_STATE_BELOW,
ewmh->_NET_WM_STATE_ABOVE,

View file

@ -1,3 +1,2 @@
- Add support for showing/hiding nodes.
- Add zoom feature (view point distinct from root).
- Use BSD `sys/{queue/tree}.h` for {list,tree} structures?

View file

@ -2,12 +2,12 @@
.\" Title: bspwm
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
.\" Date: 04/14/2016
.\" Date: 04/16/2016
.\" Manual: Bspwm Manual
.\" Source: Bspwm 0.9.1-26-g789cb8a
.\" Source: Bspwm 0.9.1-32-g828c93f
.\" Language: English
.\"
.TH "BSPWM" "1" "04/14/2016" "Bspwm 0\&.9\&.1\-26\-g789cb8a" "Bspwm Manual"
.TH "BSPWM" "1" "04/16/2016" "Bspwm 0\&.9\&.1\-32\-g828c93f" "Bspwm Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@ -98,7 +98,7 @@ NODE_SEL := (DIR|CYCLE_DIR|PATH|last|older|newer|focused|biggest|<node_id>)[\&.[
STATE := tiled|pseudo_tiled|floating|fullscreen
FLAG := urgent|sticky|private|locked
FLAG := hidden|sticky|private|locked|urgent
LAYER := below|normal|above
@ -243,7 +243,7 @@ Only consider windows in or not in the given state\&.
Only consider windows that have or don\(cqt have the same class as the current window\&.
.RE
.PP
[!](private|urgent|sticky|locked)
[!](hidden|sticky|private|locked|urgent)
.RS 4
Only consider windows that have or don\(cqt have the given flag set\&.
.RE
@ -458,11 +458,9 @@ Fills its monitor rectangle and has no borders\&. It is send in the ABOVE layer
.RE
.SH "NODE FLAGS"
.PP
locked
hidden
.RS 4
Ignores the
\fBnode \-\-close\fR
message\&.
Is hidden and doesn\(cqt occupy any tiling space\&.
.RE
.PP
sticky
@ -475,6 +473,13 @@ private
Tries to keep the same tiling position/size\&.
.RE
.PP
locked
.RS 4
Ignores the
\fBnode \-\-close\fR
message\&.
.RE
.PP
urgent
.RS 4
Has its urgency hint set\&. This flag is set externally\&.
@ -609,7 +614,7 @@ Set the state of the selected window\&. If
is present and the current state matches the given state, then the argument is interpreted as the last state\&.
.RE
.PP
\fB\-g\fR, \fB\-\-flag\fR locked|sticky|private[=on|off]
\fB\-g\fR, \fB\-\-flag\fR hidden|sticky|private|locked[=on|off]
.RS 4
Set or toggle the given flag for the selected node\&.
.RE
@ -887,7 +892,7 @@ rule \fICOMMANDS\fR
\fBCommands\fR
.RS 4
.PP
\fB\-a\fR, \fB\-\-add\fR (<class_name>|*)[:(<instance_name>|*)] [\fB\-o\fR|\fB\-\-one\-shot\fR] [monitor=MONITOR_SEL|desktop=DESKTOP_SEL|node=NODE_SEL] [state=STATE] [layer=LAYER] [split_dir=DIR] [split_ratio=RATIO] [(locked|sticky|private|center|follow|manage|focus|border)=(on|off)]
\fB\-a\fR, \fB\-\-add\fR (<class_name>|*)[:(<instance_name>|*)] [\fB\-o\fR|\fB\-\-one\-shot\fR] [monitor=MONITOR_SEL|desktop=DESKTOP_SEL|node=NODE_SEL] [state=STATE] [layer=LAYER] [split_dir=DIR] [split_ratio=RATIO] [(hidden|sticky|private|locked|center|follow|manage|focus|border)=(on|off)]
.RS 4
Create a new rule\&.
.RE
@ -1290,7 +1295,7 @@ The geometry of a window changed\&.
The state of a window changed\&.
.RE
.PP
\fInode_flag <monitor_id> <desktop_id> <node_id> sticky|private|locked|urgent on|off\fR
\fInode_flag <monitor_id> <desktop_id> <node_id> hidden|sticky|private|locked|urgent on|off\fR
.RS 4
One of the flags of a node changed\&.
.RE

View file

@ -70,7 +70,7 @@ NODE_SEL := (DIR|CYCLE_DIR|PATH|last|older|newer|focused|biggest|<node_id>)[.[!]
STATE := tiled|pseudo_tiled|floating|fullscreen
FLAG := urgent|sticky|private|locked
FLAG := hidden|sticky|private|locked|urgent
LAYER := below|normal|above
@ -153,7 +153,7 @@ Modifiers
[!]same_class::
Only consider windows that have or don't have the same class as the current window.
[!](private|urgent|sticky|locked)::
[!](hidden|sticky|private|locked|urgent)::
Only consider windows that have or don't have the given flag set.
[!](below|normal|above)::
@ -282,8 +282,8 @@ fullscreen::
Node Flags
----------
locked::
Ignores the *node --close* message.
hidden::
Is hidden and doesn't occupy any tiling space.
sticky::
Stays in the focused desktop of its monitor.
@ -291,6 +291,9 @@ sticky::
private::
Tries to keep the same tiling position/size.
locked::
Ignores the *node --close* message.
urgent::
Has its urgency hint set. This flag is set externally.
@ -367,7 +370,7 @@ Commands
*-t*, *--state* [~](tiled|pseudo_tiled|floating|fullscreen)::
Set the state of the selected window. If *~* is present and the current state matches the given state, then the argument is interpreted as the last state.
*-g*, *--flag* locked|sticky|private[=on|off]::
*-g*, *--flag* hidden|sticky|private|locked[=on|off]::
Set or toggle the given flag for the selected node.
*-l*, *--layer* below|normal|above::
@ -521,7 +524,7 @@ rule 'COMMANDS'
Commands
^^^^^^^^
*-a*, *--add* (<class_name>|\*)[:(<instance_name>|\*)] [*-o*|*--one-shot*] [monitor=MONITOR_SEL|desktop=DESKTOP_SEL|node=NODE_SEL] [state=STATE] [layer=LAYER] [split_dir=DIR] [split_ratio=RATIO] [(locked|sticky|private|center|follow|manage|focus|border)=(on|off)]::
*-a*, *--add* (<class_name>|\*)[:(<instance_name>|\*)] [*-o*|*--one-shot*] [monitor=MONITOR_SEL|desktop=DESKTOP_SEL|node=NODE_SEL] [state=STATE] [layer=LAYER] [split_dir=DIR] [split_ratio=RATIO] [(hidden|sticky|private|locked|center|follow|manage|focus|border)=(on|off)]::
Create a new rule.
*-r*, *--remove* ^<n>|head|tail|(<class_name>|\*)[:(<instance_name>|*)]...::
@ -766,7 +769,7 @@ Events
'node_state <monitor_id> <desktop_id> <node_id> tiled|pseudo_tiled|floating|fullscreen on|off'::
The state of a window changed.
'node_flag <monitor_id> <desktop_id> <node_id> sticky|private|locked|urgent on|off'::
'node_flag <monitor_id> <desktop_id> <node_id> hidden|sticky|private|locked|urgent on|off'::
One of the flags of a node changed.
'node_layer <monitor_id> <desktop_id> <node_id> below|normal|above'::

View file

@ -400,6 +400,14 @@ void handle_state(monitor_t *m, desktop_t *d, node_t *n, xcb_atom_t state, unsig
} else if (action == XCB_EWMH_WM_STATE_TOGGLE) {
set_layer(m, d, n, n->client->layer == LAYER_ABOVE ? n->client->last_layer : LAYER_ABOVE);
}
} else if (state == ewmh->_NET_WM_STATE_HIDDEN) {
if (action == XCB_EWMH_WM_STATE_ADD) {
set_hidden(m, d, n, true);
} else if (action == XCB_EWMH_WM_STATE_REMOVE) {
set_hidden(m, d, n, false);
} else if (action == XCB_EWMH_WM_STATE_TOGGLE) {
set_hidden(m, d, n, !n->hidden);
}
} else if (state == ewmh->_NET_WM_STATE_STICKY) {
if (action == XCB_EWMH_WM_STATE_ADD) {
set_sticky(m, d, n, true);
@ -432,7 +440,6 @@ void handle_state(monitor_t *m, desktop_t *d, node_t *n, xcb_atom_t state, unsig
HANDLE_WM_STATE(SHADED)
HANDLE_WM_STATE(SKIP_TASKBAR)
HANDLE_WM_STATE(SKIP_PAGER)
HANDLE_WM_STATE(HIDDEN)
}
#undef HANDLE_WM_STATE
}

View file

@ -163,7 +163,8 @@ void empty_history(void)
node_t *history_last_node(desktop_t *d, node_t *n)
{
for (history_t *h = history_tail; h != NULL; h = h->prev) {
if (h->latest && h->loc.node != NULL && !is_descendant(h->loc.node, n) && h->loc.desktop == d) {
if (h->latest && h->loc.node != NULL && !h->loc.node->hidden &&
!is_descendant(h->loc.node, n) && h->loc.desktop == d) {
return h->loc.node;
}
}
@ -201,6 +202,7 @@ bool history_find_node(history_dir_t hdi, coordinates_t *ref, coordinates_t *dst
if (!h->latest ||
h->loc.node == NULL ||
h->loc.node == ref->node ||
h->loc.node->hidden ||
!node_matches(&h->loc, ref, sel)) {
continue;
}

View file

@ -312,12 +312,15 @@ void cmd_node(char **args, int num, FILE *rsp)
break;
}
}
if (streq("locked", key)) {
set_locked(trg.monitor, trg.desktop, trg.node, (a == ALTER_SET ? b : !trg.node->locked));
if (streq("hidden", key)) {
set_hidden(trg.monitor, trg.desktop, trg.node, (a == ALTER_SET ? b : !trg.node->hidden));
changed = true;
} else if (streq("sticky", key)) {
set_sticky(trg.monitor, trg.desktop, trg.node, (a == ALTER_SET ? b : !trg.node->sticky));
} else if (streq("private", key)) {
set_private(trg.monitor, trg.desktop, trg.node, (a == ALTER_SET ? b : !trg.node->private));
} else if (streq("locked", key)) {
set_locked(trg.monitor, trg.desktop, trg.node, (a == ALTER_SET ? b : !trg.node->locked));
} else {
fail(rsp, "node %s: Invalid key: '%s'.\n", *(args - 1), key);
break;

View file

@ -441,9 +441,10 @@ bool parse_node_modifiers(char *desc, node_select_t *sel)
GET_MOD(pseudo_tiled)
GET_MOD(floating)
GET_MOD(fullscreen)
GET_MOD(locked)
GET_MOD(hidden)
GET_MOD(sticky)
GET_MOD(private)
GET_MOD(locked)
GET_MOD(urgent)
GET_MOD(same_class)
GET_MOD(below)

10
query.c
View file

@ -118,6 +118,7 @@ void query_node(node_t *n, FILE *rsp)
fprintf(rsp, "\"splitRatio\":%lf,", n->split_ratio);
fprintf(rsp, "\"birthRotation\":%i,", n->birth_rotation);
fprintf(rsp, "\"vacant\":%s,", BOOL_STR(n->vacant));
fprintf(rsp, "\"hidden\":%s,", BOOL_STR(n->hidden));
fprintf(rsp, "\"sticky\":%s,", BOOL_STR(n->sticky));
fprintf(rsp, "\"private\":%s,", BOOL_STR(n->private));
fprintf(rsp, "\"locked\":%s,", BOOL_STR(n->locked));
@ -162,7 +163,7 @@ void query_client(client_t *c, FILE *rsp)
fprintf(rsp, "\"layer\":\"%s\",", LAYER_STR(c->layer));
fprintf(rsp, "\"lastLayer\":\"%s\",", LAYER_STR(c->last_layer));
fprintf(rsp, "\"urgent\":%s,", BOOL_STR(c->urgent));
fprintf(rsp, "\"visible\":%s,", BOOL_STR(c->visible));
fprintf(rsp, "\"shown\":%s,", BOOL_STR(c->shown));
fprintf(rsp, "\"tiledRectangle\":");
query_rectangle(c->tiled_rectangle, rsp);
fprintf(rsp,",");
@ -240,6 +241,9 @@ int query_node_ids_in(node_t *n, desktop_t *d, monitor_t *m, coordinates_t loc,
(sel == NULL || node_matches(&trg, &ref, *sel))) {
fprintf(rsp, "0x%08X\n", n->id);
count++;
if (sel != NULL) {
return count;
}
}
count += query_node_ids_in(n->first_child, d, m, loc, sel, rsp);
count += query_node_ids_in(n->second_child, d, m, loc, sel, rsp);
@ -344,9 +348,10 @@ node_select_t make_node_select(void)
.pseudo_tiled = OPTION_NONE,
.floating = OPTION_NONE,
.fullscreen = OPTION_NONE,
.locked = OPTION_NONE,
.hidden = OPTION_NONE,
.sticky = OPTION_NONE,
.private = OPTION_NONE,
.locked = OPTION_NONE,
.urgent = OPTION_NONE,
.same_class = OPTION_NONE,
.below = OPTION_NONE,
@ -801,6 +806,7 @@ bool node_matches(coordinates_t *loc, coordinates_t *ref, node_select_t sel)
: sel.p == OPTION_FALSE) { \
return false; \
}
NFLAG(hidden)
NFLAG(sticky)
NFLAG(private)
NFLAG(locked)

View file

@ -343,6 +343,7 @@ node_t *restore_node(jsmntok_t **t, char *json)
RESTORE_DOUBLE(splitRatio, &n->split_ratio)
RESTORE_INT(birthRotation, &n->birth_rotation)
RESTORE_BOOL(vacant, &n->vacant)
RESTORE_BOOL(hidden, &n->hidden)
RESTORE_BOOL(sticky, &n->sticky)
RESTORE_BOOL(private, &n->private)
RESTORE_BOOL(locked, &n->locked)
@ -433,7 +434,7 @@ client_t *restore_client(jsmntok_t **t, char *json)
RESTORE_ANY(lastLayer, &c->last_layer, parse_stack_layer)
RESTORE_UINT(borderWidth, &c->border_width)
RESTORE_BOOL(urgent, &c->urgent)
RESTORE_BOOL(visible, &c->visible)
RESTORE_BOOL(shown, &c->shown)
} else if (keyeq("tiledRectangle", *t, json)) {
(*t)++;
restore_rectangle(&c->tiled_rectangle, t, json);

5
rule.c
View file

@ -342,13 +342,14 @@ void parse_key_value(char *key, char *value, rule_consequence_t *csq)
csq->split_ratio = rat;
}
} else if (parse_bool(value, &v)) {
if (streq("locked", key))
csq->locked = true;
if (streq("hidden", key))
csq->hidden = true;
#define SETCSQ(name) \
else if (streq(#name, key)) \
csq->name = v;
SETCSQ(sticky)
SETCSQ(private)
SETCSQ(locked)
SETCSQ(center)
SETCSQ(follow)
SETCSQ(manage)

217
tree.c
View file

@ -395,12 +395,11 @@ node_t *insert_node(monitor_t *m, desktop_t *d, node_t *n, node_t *f)
}
cancel_presel(m, d, f);
}
if (f->vacant) {
propagate_vacant_state(m, d, f);
}
}
if (d->focus == NULL && !IS_RECEPTACLE(n)) {
propagate_flags_upward(m, d, n);
if (d->focus == NULL && is_focusable(n)) {
d->focus = n;
}
@ -415,7 +414,7 @@ void insert_receptacle(monitor_t *m, desktop_t *d, node_t *n)
bool activate_node(monitor_t *m, desktop_t *d, node_t *n)
{
if (d == mon->desk || IS_RECEPTACLE(n)) {
if (d == mon->desk || (n != NULL && !is_focusable(n))) {
return false;
}
@ -473,7 +472,7 @@ void transfer_sticky_nodes(monitor_t *m, desktop_t *ds, desktop_t *dd, node_t *n
bool focus_node(monitor_t *m, desktop_t *d, node_t *n)
{
if (IS_RECEPTACLE(n)) {
if (n != NULL && !is_focusable(n)) {
return false;
}
@ -561,12 +560,16 @@ void hide_node(node_t *n)
if (n == NULL) {
return;
} else {
if (n->presel != NULL) {
window_hide(n->presel->feedback);
if (!n->hidden) {
if (n->presel != NULL) {
window_hide(n->presel->feedback);
}
if (n->client != NULL) {
window_hide(n->id);
}
}
if (n->client != NULL) {
window_hide(n->id);
n->client->visible = false;
n->client->shown = false;
}
hide_node(n->first_child);
hide_node(n->second_child);
@ -578,12 +581,16 @@ void show_node(node_t *n)
if (n == NULL) {
return;
} else {
if (n->client != NULL) {
window_show(n->id);
n->client->visible = true;
if (!n->hidden) {
if (n->client != NULL) {
window_show(n->id);
}
if (n->presel != NULL) {
window_show(n->presel->feedback);
}
}
if (n->presel != NULL) {
window_show(n->presel->feedback);
if (n->client != NULL) {
n->client->shown = true;
}
show_node(n->first_child);
show_node(n->second_child);
@ -598,7 +605,7 @@ node_t *make_node(uint32_t id)
node_t *n = malloc(sizeof(node_t));
n->id = id;
n->parent = n->first_child = n->second_child = NULL;
n->vacant = n->sticky = n->private = n->locked = false;
n->vacant = n->hidden = n->sticky = n->private = n->locked = false;
n->split_ratio = split_ratio;
n->split_type = TYPE_VERTICAL;
n->birth_rotation = 0;
@ -609,13 +616,16 @@ node_t *make_node(uint32_t id)
client_t *make_client(void)
{
client_t *c = calloc(1, sizeof(client_t));
client_t *c = malloc(sizeof(client_t));
c->state = c->last_state = STATE_TILED;
c->layer = c->last_layer = LAYER_NORMAL;
snprintf(c->class_name, sizeof(c->class_name), "%s", MISSING_VALUE);
snprintf(c->instance_name, sizeof(c->instance_name), "%s", MISSING_VALUE);
c->border_width = border_width;
c->wm_flags = 0;
c->icccm_props.input_hint = true;
c->icccm_props.take_focus = false;
c->size_hints.flags = 0;
return c;
}
@ -661,6 +671,16 @@ void initialize_client(node_t *n)
xcb_icccm_get_wm_normal_hints_reply(dpy, xcb_icccm_get_wm_normal_hints(dpy, win), &c->size_hints, NULL);
}
bool is_focusable(node_t *n)
{
for (node_t *f = first_extrema(n); f != NULL; f = next_leaf(f, n)) {
if (f->client != NULL && !f->hidden) {
return true;
}
}
return false;
}
bool is_leaf(node_t *n)
{
return (n != NULL && n->first_child == NULL && n->second_child == NULL);
@ -724,7 +744,7 @@ node_t *second_extrema(node_t *n)
node_t *first_focusable_leaf(node_t *n)
{
for (node_t *f = first_extrema(n); f != NULL; f = next_leaf(f, n)) {
if (f->client != NULL) {
if (f->client != NULL && !f->hidden) {
return f;
}
}
@ -764,7 +784,7 @@ node_t *prev_leaf(node_t *n, node_t *r)
node_t *next_tiled_leaf(node_t *n, node_t *r)
{
node_t *next = next_leaf(n, r);
if (next == NULL || (next->client != NULL && IS_TILED(next->client))) {
if (next == NULL || (next->client != NULL && !next->vacant)) {
return next;
} else {
return next_tiled_leaf(next, r);
@ -774,7 +794,7 @@ node_t *next_tiled_leaf(node_t *n, node_t *r)
node_t *prev_tiled_leaf(node_t *n, node_t *r)
{
node_t *prev = prev_leaf(n, r);
if (prev == NULL || (prev->client != NULL && IS_TILED(prev->client))) {
if (prev == NULL || (prev->client != NULL && !prev->vacant)) {
return prev;
} else {
return prev_tiled_leaf(prev, r);
@ -1001,6 +1021,7 @@ node_t *nearest_from_distance(monitor_t *m, desktop_t *d, node_t *n, direction_t
coordinates_t loc = {m, d, a};
if (a == n ||
a->client == NULL ||
a->hidden ||
!node_matches(&loc, &ref, sel) ||
(n->client != NULL && (IS_TILED(a->client) != IS_TILED(n->client))) ||
(IS_TILED(a->client) && !is_adjacent(n, a, dir))) {
@ -1222,7 +1243,7 @@ void unlink_node(monitor_t *m, desktop_t *d, node_t *n)
}
free(p);
propagate_vacant_state(m, d, b);
propagate_flags_upward(m, d, b);
}
}
@ -1353,10 +1374,8 @@ bool swap_nodes(monitor_t *m1, desktop_t *d1, node_t *n1, monitor_t *m2, desktop
n1->birth_rotation = br2;
n2->birth_rotation = br1;
if (n1->vacant != n2->vacant) {
propagate_vacant_state(m2, d2, n1);
propagate_vacant_state(m1, d1, n2);
}
propagate_flags_upward(m2, d2, n1);
propagate_flags_upward(m1, d1, n2);
if (d1 != d2) {
if (d1->root == n1) {
@ -1518,7 +1537,7 @@ node_t *closest_node(monitor_t *m, desktop_t *d, node_t *n, cycle_dir_t dir, nod
coordinates_t ref = {m, d, n};
while (f != n) {
coordinates_t loc = {m, d, f};
if (f->client != NULL && node_matches(&loc, &ref, sel)) {
if (f->client != NULL && !f->hidden && node_matches(&loc, &ref, sel)) {
return f;
}
f = (dir == CYCLE_PREV ? prev_leaf(f, d->root) : next_leaf(f, d->root));
@ -1560,24 +1579,41 @@ void circulate_leaves(monitor_t *m, desktop_t *d, node_t *n, circulate_dir_t dir
}
}
void set_vacant_state(monitor_t *m, desktop_t *d, node_t *n, bool value)
void set_vacant(monitor_t *m, desktop_t *d, node_t *n, bool value)
{
if (n->vacant == value) {
return;
}
propagate_vacant_downward(m, d, n, value);
propagate_vacant_upward(m, d, n);
}
void set_vacant_local(monitor_t *m, desktop_t *d, node_t *n, bool value)
{
n->vacant = value;
if (value) {
unrotate_brother(n);
cancel_presel(m, d, n);
} else {
rotate_brother(n);
}
if (value) {
cancel_presel(m, d, n);
}
propagate_vacant_state(m, d, n);
}
void propagate_vacant_state(monitor_t *m, desktop_t *d, node_t *n)
void propagate_vacant_downward(monitor_t *m, desktop_t *d, node_t *n, bool value)
{
if (n == NULL) {
return;
}
set_vacant_local(m, d, n, value);
propagate_vacant_downward(m, d, n->first_child, value);
propagate_vacant_downward(m, d, n->second_child, value);
}
void propagate_vacant_upward(monitor_t *m, desktop_t *d, node_t *n)
{
if (n == NULL) {
return;
@ -1585,13 +1621,11 @@ void propagate_vacant_state(monitor_t *m, desktop_t *d, node_t *n)
node_t *p = n->parent;
while (p != NULL) {
p->vacant = (p->first_child->vacant && p->second_child->vacant);
if (p->vacant) {
cancel_presel(m, d, p);
}
p = p->parent;
if (p != NULL) {
set_vacant_local(m, d, p, (p->first_child->vacant && p->second_child->vacant));
}
propagate_vacant_upward(m, d, p);
}
bool set_layer(monitor_t *m, desktop_t *d, node_t *n, stack_layer_t l)
@ -1679,7 +1713,7 @@ void set_floating(monitor_t *m, desktop_t *d, node_t *n, bool value)
}
cancel_presel(m, d, n);
set_vacant_state(m, d, n, value);
set_vacant(m, d, n, value);
if (!value && d->focus == n) {
neutralize_occluding_windows(m, d, n);
@ -1697,7 +1731,7 @@ void set_fullscreen(monitor_t *m, desktop_t *d, node_t *n, bool value)
client_t *c = n->client;
cancel_presel(m, d, n);
set_vacant_state(m, d, n, value);
set_vacant(m, d, n, value);
if (value) {
c->wm_flags |= WM_FLAG_FULLSCREEN;
@ -1732,19 +1766,89 @@ void neutralize_occluding_windows(monitor_t *m, desktop_t *d, node_t *n)
}
}
void set_locked(monitor_t *m, desktop_t *d, node_t *n, bool value)
void propagate_flags_upward(monitor_t *m, desktop_t *d, node_t *n)
{
if (n == NULL || n->locked == value) {
if (n == NULL) {
return;
}
n->locked = value;
node_t *p = n->parent;
put_status(SBSC_MASK_NODE_FLAG, "node_flag 0x%08X 0x%08X 0x%08X locked %s\n", m->id, d->id, n->id, ON_OFF_STR(value));
if (n == m->desk->focus) {
put_status(SBSC_MASK_REPORT);
if (p != NULL) {
set_vacant_local(m, d, p, (p->first_child->vacant && p->second_child->vacant));
set_hidden_local(m, d, p, (p->first_child->hidden && p->second_child->hidden));
}
propagate_flags_upward(m, d, p);
}
void set_hidden(monitor_t *m, desktop_t *d, node_t *n, bool value)
{
if (n == NULL || n->hidden == value) {
return;
}
bool held_focus = is_descendant(d->focus, n);
propagate_hidden_downward(m, d, n, value);
propagate_hidden_upward(m, d, n);
put_status(SBSC_MASK_NODE_FLAG, "node_flag 0x%08X 0x%08X 0x%08X hidden %s\n", m->id, d->id, n->id, ON_OFF_STR(value));
if (held_focus || d->focus == NULL) {
if (d->focus != NULL) {
d->focus = NULL;
draw_border(n, false, (mon == m));
}
if (d == mon->desk) {
focus_node(m, d, d->focus);
} else {
activate_node(m, d, d->focus);
}
}
}
void set_hidden_local(monitor_t *m, desktop_t *d, node_t *n, bool value)
{
n->hidden = value;
if (n->client != NULL) {
window_set_visibility(n->id, !value);
if (IS_TILED(n->client)) {
set_vacant(m, d, n, value);
}
if (value) {
n->client->wm_flags |= WM_FLAG_HIDDEN;
} else {
n->client->wm_flags &= ~WM_FLAG_HIDDEN;
}
}
}
void propagate_hidden_downward(monitor_t *m, desktop_t *d, node_t *n, bool value)
{
if (n == NULL) {
return;
}
set_hidden_local(m, d, n, value);
propagate_hidden_downward(m, d, n->first_child, value);
propagate_hidden_downward(m, d, n->second_child, value);
}
void propagate_hidden_upward(monitor_t *m, desktop_t *d, node_t *n)
{
if (n == NULL) {
return;
}
node_t *p = n->parent;
if (p != NULL) {
set_hidden_local(m, d, p, p->first_child->hidden && p->second_child->hidden);
}
propagate_hidden_upward(m, d, p);
}
void set_sticky(monitor_t *m, desktop_t *d, node_t *n, bool value)
@ -1797,6 +1901,21 @@ void set_private(monitor_t *m, desktop_t *d, node_t *n, bool value)
}
}
void set_locked(monitor_t *m, desktop_t *d, node_t *n, bool value)
{
if (n == NULL || n->locked == value) {
return;
}
n->locked = value;
put_status(SBSC_MASK_NODE_FLAG, "node_flag 0x%08X 0x%08X 0x%08X locked %s\n", m->id, d->id, n->id, ON_OFF_STR(value));
if (n == m->desk->focus) {
put_status(SBSC_MASK_REPORT);
}
}
void set_urgent(monitor_t *m, desktop_t *d, node_t *n, bool value)
{
if (value && mon->desk->focus == n) {

14
tree.h
View file

@ -44,6 +44,7 @@ void show_node(node_t *n);
node_t *make_node(uint32_t id);
client_t *make_client(void);
void initialize_client(node_t *n);
bool is_focusable(node_t *n);
bool is_leaf(node_t *n);
bool is_first_child(node_t *n);
bool is_second_child(node_t *n);
@ -86,16 +87,23 @@ bool swap_nodes(monitor_t *m1, desktop_t *d1, node_t *n1, monitor_t *m2, desktop
bool transfer_node(monitor_t *ms, desktop_t *ds, node_t *ns, monitor_t *md, desktop_t *dd, node_t *nd);
node_t *closest_node(monitor_t *m, desktop_t *d, node_t *n, cycle_dir_t dir, node_select_t sel);
void circulate_leaves(monitor_t *m, desktop_t *d, node_t *n, circulate_dir_t dir);
void set_vacant_state(monitor_t *m, desktop_t *d, node_t *n, bool value);
void propagate_vacant_state(monitor_t *m, desktop_t *d, node_t *n);
void set_vacant(monitor_t *m, desktop_t *d, node_t *n, bool value);
void set_vacant_local(monitor_t *m, desktop_t *d, node_t *n, bool value);
void propagate_vacant_downward(monitor_t *m, desktop_t *d, node_t *n, bool value);
void propagate_vacant_upward(monitor_t *m, desktop_t *d, node_t *n);
bool set_layer(monitor_t *m, desktop_t *d, node_t *n, stack_layer_t l);
bool set_state(monitor_t *m, desktop_t *d, node_t *n, client_state_t s);
void set_floating(monitor_t *m, desktop_t *d, node_t *n, bool value);
void set_fullscreen(monitor_t *m, desktop_t *d, node_t *n, bool value);
void neutralize_occluding_windows(monitor_t *m, desktop_t *d, node_t *n);
void set_locked(monitor_t *m, desktop_t *d, node_t *n, bool value);
void propagate_flags_upward(monitor_t *m, desktop_t *d, node_t *n);
void set_hidden(monitor_t *m, desktop_t *d, node_t *n, bool value);
void set_hidden_local(monitor_t *m, desktop_t *d, node_t *n, bool value);
void propagate_hidden_downward(monitor_t *m, desktop_t *d, node_t *n, bool value);
void propagate_hidden_upward(monitor_t *m, desktop_t *d, node_t *n);
void set_sticky(monitor_t *m, desktop_t *d, node_t *n, bool value);
void set_private(monitor_t *m, desktop_t *d, node_t *n, bool value);
void set_locked(monitor_t *m, desktop_t *d, node_t *n, bool value);
void set_urgent(monitor_t *m, desktop_t *d, node_t *n, bool value);
bool contains(xcb_rectangle_t a, xcb_rectangle_t b);
xcb_rectangle_t get_rectangle(desktop_t *d, node_t *n);

View file

@ -148,9 +148,10 @@ typedef struct {
option_bool_t pseudo_tiled;
option_bool_t floating;
option_bool_t fullscreen;
option_bool_t locked;
option_bool_t hidden;
option_bool_t sticky;
option_bool_t private;
option_bool_t locked;
option_bool_t urgent;
option_bool_t same_class;
option_bool_t below;
@ -181,7 +182,7 @@ typedef struct {
char instance_name[3 * SMALEN / 2];
unsigned int border_width;
bool urgent;
bool visible;
bool shown;
client_state_t state;
client_state_t last_state;
stack_layer_t layer;
@ -209,6 +210,7 @@ struct node_t {
presel_t *presel;
xcb_rectangle_t rectangle;
bool vacant;
bool hidden;
bool sticky;
bool private;
bool locked;
@ -309,9 +311,10 @@ typedef struct {
double split_ratio;
stack_layer_t *layer;
client_state_t *state;
bool locked;
bool hidden;
bool sticky;
bool private;
bool locked;
bool center;
bool follow;
bool manage;

View file

@ -167,18 +167,22 @@ void manage_window(xcb_window_t win, rule_consequence_t *csq, int fd)
c->last_state = c->state;
}
set_locked(m, d, n, csq->locked);
set_hidden(m, d, n, csq->hidden);
set_sticky(m, d, n, csq->sticky);
set_private(m, d, n, csq->private);
set_locked(m, d, n, csq->locked);
arrange(m, d);
bool give_focus = (csq->focus && (d == mon->desk || csq->follow));
bool focused = false;
if (give_focus) {
focus_node(m, d, n);
} else if (csq->focus) {
activate_node(m, d, n);
if (!csq->hidden && csq->focus) {
if (d == mon->desk || csq->follow) {
focused = true;
focus_node(m, d, n);
} else {
activate_node(m, d, n);
}
} else {
stack(d, n, false);
}
@ -193,7 +197,7 @@ void manage_window(xcb_window_t win, rule_consequence_t *csq, int fd)
}
/* the same function is already called in `focus_node` but has no effects on unmapped windows */
if (give_focus) {
if (focused) {
xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, win, XCB_CURRENT_TIME);
}
@ -654,7 +658,7 @@ void query_pointer(xcb_window_t *win, xcb_point_t *pt)
*win = qpr->child;
xcb_point_t pt = {qpr->root_x, qpr->root_y};
for (stacking_list_t *s = stack_tail; s != NULL; s = s->prev) {
if (!s->node->client->visible) {
if (!s->node->client->shown || s->node->hidden) {
continue;
}
xcb_rectangle_t rect = get_rectangle(NULL, s->node);