mirror of
https://github.com/vale981/bspwm
synced 2025-03-04 17:31:39 -05:00
parent
828c93fb29
commit
331cc9e2d5
15 changed files with 256 additions and 93 deletions
1
bspwm.c
1
bspwm.c
|
@ -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,
|
||||
|
|
|
@ -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?
|
||||
|
|
29
doc/bspwm.1
29
doc/bspwm.1
|
@ -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
|
||||
|
|
|
@ -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'::
|
||||
|
|
9
events.c
9
events.c
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
3
parse.c
3
parse.c
|
@ -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
10
query.c
|
@ -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)
|
||||
|
|
|
@ -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
5
rule.c
|
@ -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)
|
||||
|
|
199
tree.c
199
tree.c
|
@ -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->hidden) {
|
||||
if (n->presel != NULL) {
|
||||
window_hide(n->presel->feedback);
|
||||
}
|
||||
if (n->client != NULL) {
|
||||
window_hide(n->id);
|
||||
n->client->visible = false;
|
||||
}
|
||||
}
|
||||
if (n->client != NULL) {
|
||||
n->client->shown = false;
|
||||
}
|
||||
hide_node(n->first_child);
|
||||
hide_node(n->second_child);
|
||||
|
@ -578,13 +581,17 @@ void show_node(node_t *n)
|
|||
if (n == NULL) {
|
||||
return;
|
||||
} else {
|
||||
if (!n->hidden) {
|
||||
if (n->client != NULL) {
|
||||
window_show(n->id);
|
||||
n->client->visible = true;
|
||||
}
|
||||
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_downward(monitor_t *m, desktop_t *d, node_t *n, bool value)
|
||||
{
|
||||
if (n == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
void propagate_vacant_state(monitor_t *m, desktop_t *d, node_t *n)
|
||||
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
14
tree.h
|
@ -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);
|
||||
|
|
9
types.h
9
types.h
|
@ -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;
|
||||
|
|
16
window.c
16
window.c
|
@ -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) {
|
||||
if (!csq->hidden && csq->focus) {
|
||||
if (d == mon->desk || csq->follow) {
|
||||
focused = true;
|
||||
focus_node(m, d, n);
|
||||
} else if (csq->focus) {
|
||||
} 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);
|
||||
|
|
Loading…
Add table
Reference in a new issue