local -a commands=(node desktop monitor query rule wm subscribe config quit) \
resize_handle=(top bottom top_left top_right bottom_left bottom_right left right) \
node_state=(tiled pseudo_tiled floating fullscreen) \
- flag=(hidden sticky private locked urgent) \
+ flag=(hidden sticky private locked marked urgent) \
layer=(below normal above) \
dir=(north west south east) \
cycle_dir=(next prev)
local -a jump=($dir first second brother parent 1 2) \
- node_desc=($dir $cycle_dir last older newer focused pointed biggest) \
+ node_desc=($dir $cycle_dir last newest older newer focused pointed biggest) \
node_mod=($node_state $flag $layer focused automatic local \
active leaf window same_class descendant_of ancestor_of) \
- desktop_desc=($cycle_dir last older newer focused) \
+ desktop_desc=($cycle_dir last newest older newer focused) \
desktop_mod=(focused occupied local urgent) \
- monitor_desc=($dir $cycle_dir primary last older newer focused pointed) \
+ monitor_desc=($dir $cycle_dir primary last newest older newer focused pointed) \
monitor_mod=(focused occupied) \
presel_dir=($dir cancel)
local quote="${compstate[quote]}" context state state_descr line
.\" Title: bspwm
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
-.\" Date: 02/04/2018
+.\" Date: 03/07/2018
.\" Manual: Bspwm Manual
-.\" Source: Bspwm 0.9.3-47-ga5acc9a
+.\" Source: Bspwm 0.9.3-52-gf83f7ef
.\" Language: English
.\"
-.TH "BSPWM" "1" "02/04/2018" "Bspwm 0\&.9\&.3\-47\-ga5acc9a" "Bspwm Manual"
+.TH "BSPWM" "1" "03/07/2018" "Bspwm 0\&.9\&.3\-52\-gf83f7ef" "Bspwm Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.RS 4
.\}
.nf
-NODE_SEL := [NODE_SEL#](DIR|CYCLE_DIR|PATH|last|
+NODE_SEL := [NODE_SEL#](DIR|CYCLE_DIR|PATH|last|newest|
older|newer|focused|pointed|
biggest|<node_id>)[\&.[!]focused][\&.[!]automatic][\&.[!]local][\&.[!]active]
[\&.[!]leaf][\&.[!]window][\&.[!]STATE][\&.[!]FLAG][\&.[!]LAYER]
STATE := tiled|pseudo_tiled|floating|fullscreen
-FLAG := hidden|sticky|private|locked|urgent
+FLAG := hidden|sticky|private|locked|marked|urgent
LAYER := below|normal|above
Selects the previously focused node relative to the reference node\&.
.RE
.PP
+newest
+.RS 4
+Selects the newest node in the history of the focused node\&.
+.RE
+.PP
older
.RS 4
Selects the node older than the reference node in the history\&.
Only consider nodes that are or aren\(cqt ancestors of the reference node\&.
.RE
.PP
-[!](hidden|sticky|private|locked|urgent)
+[!](hidden|sticky|private|locked|marked|urgent)
.RS 4
Only consider windows that have or don\(cqt have the given flag set\&.
.RE
.RS 4
.\}
.nf
-DESKTOP_SEL := [DESKTOP_SEL#](CYCLE_DIR|last|older|newer|
+DESKTOP_SEL := [DESKTOP_SEL#](CYCLE_DIR|last|newest|older|newer|
[MONITOR_SEL:](focused|^<n>)|
<desktop_id>|<desktop_name>)[\&.[!]occupied][\&.[!]focused][\&.[!]urgent][\&.[!]local]
.fi
Selects the previously focused desktop relative to the reference desktop\&.
.RE
.PP
+newest
+.RS 4
+Selects the newest desktop in the history of the focused desktops\&.
+.RE
+.PP
older
.RS 4
Selects the desktop older than the reference desktop in the history\&.
.RS 4
.\}
.nf
-MONITOR_SEL := [MONITOR_SEL#](DIR|CYCLE_DIR|last|older|newer|
+MONITOR_SEL := [MONITOR_SEL#](DIR|CYCLE_DIR|last|newest|older|newer|
focused|pointed|primary|^<n>|
<monitor_id>|<monitor_name>)[\&.[!]occupied][\&.[!]focused]
.fi
Selects the previously focused monitor relative to the reference monitor\&.
.RE
.PP
+newest
+.RS 4
+Selects the newest monitor in the history of the focused monitors\&.
+.RE
+.PP
older
.RS 4
Selects the monitor older than the reference monitor in the history\&.
message\&.
.RE
.PP
+marked
+.RS 4
+Is marked (useful for deferred operations)\&.
+.RE
+.PP
urgent
.RS 4
Has its urgency hint set\&. This flag is set externally\&.
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 hidden|sticky|private|locked[=on|off]
+\fB\-g\fR, \fB\-\-flag\fR hidden|sticky|private|locked|marked[=on|off]
.RS 4
Set or toggle the given flag for the selected node\&.
.RE
\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] [(hidden|sticky|private|locked|center|follow|manage|focus|border)=(on|off)] [rectangle=WxH+X+Y]
+\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|marked|center|follow|manage|focus|border)=(on|off)] [rectangle=WxH+X+Y]
.RS 4
Create a new rule\&.
.RE
The state of a window changed\&.
.RE
.PP
-\fInode_flag <monitor_id> <desktop_id> <node_id> hidden|sticky|private|locked|urgent on|off\fR
+\fInode_flag <monitor_id> <desktop_id> <node_id> hidden|sticky|private|locked|marked|urgent on|off\fR
.RS 4
One of the flags of a node changed\&.
.RE
Select a node.
----
-NODE_SEL := [NODE_SEL#](DIR|CYCLE_DIR|PATH|last|
+NODE_SEL := [NODE_SEL#](DIR|CYCLE_DIR|PATH|last|newest|
older|newer|focused|pointed|
biggest|<node_id>)[.[!]focused][.[!]automatic][.[!]local][.[!]active]
[.[!]leaf][.[!]window][.[!]STATE][.[!]FLAG][.[!]LAYER]
STATE := tiled|pseudo_tiled|floating|fullscreen
-FLAG := hidden|sticky|private|locked|urgent
+FLAG := hidden|sticky|private|locked|marked|urgent
LAYER := below|normal|above
last::
Selects the previously focused node relative to the reference node.
+newest::
+ Selects the newest node in the history of the focused node.
+
older::
Selects the node older than the reference node in the history.
[!]ancestor_of::
Only consider nodes that are or aren't ancestors of the reference node.
-[!](hidden|sticky|private|locked|urgent)::
+[!](hidden|sticky|private|locked|marked|urgent)::
Only consider windows that have or don't have the given flag set.
[!](below|normal|above)::
Select a desktop.
----
-DESKTOP_SEL := [DESKTOP_SEL#](CYCLE_DIR|last|older|newer|
+DESKTOP_SEL := [DESKTOP_SEL#](CYCLE_DIR|last|newest|older|newer|
[MONITOR_SEL:](focused|^<n>)|
<desktop_id>|<desktop_name>)[.[!]occupied][.[!]focused][.[!]urgent][.[!]local]
----
last::
Selects the previously focused desktop relative to the reference desktop.
+newest::
+ Selects the newest desktop in the history of the focused desktops.
+
older::
Selects the desktop older than the reference desktop in the history.
Select a monitor.
----
-MONITOR_SEL := [MONITOR_SEL#](DIR|CYCLE_DIR|last|older|newer|
+MONITOR_SEL := [MONITOR_SEL#](DIR|CYCLE_DIR|last|newest|older|newer|
focused|pointed|primary|^<n>|
<monitor_id>|<monitor_name>)[.[!]occupied][.[!]focused]
----
last::
Selects the previously focused monitor relative to the reference monitor.
+newest::
+ Selects the newest monitor in the history of the focused monitors.
+
older::
Selects the monitor older than the reference monitor in the history.
locked::
Ignores the *node --close* message.
+marked::
+ Is marked (useful for deferred operations).
+
urgent::
Has its urgency hint set. This flag is set externally.
*-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* hidden|sticky|private|locked[=on|off]::
+*-g*, *--flag* hidden|sticky|private|locked|marked[=on|off]::
Set or toggle the given flag for the selected node.
*-l*, *--layer* below|normal|above::
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] [(hidden|sticky|private|locked|center|follow|manage|focus|border)=(on|off)] [rectangle=WxH+X+Y]::
+*-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|marked|center|follow|manage|focus|border)=(on|off)] [rectangle=WxH+X+Y]::
Create a new rule.
*-r*, *--remove* ^<n>|head|tail|(<class_name>|\*)[:(<instance_name>|*)]...::
'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> hidden|sticky|private|locked|urgent on|off'::
+'node_flag <monitor_id> <desktop_id> <node_id> hidden|sticky|private|locked|marked|urgent on|off'::
One of the flags of a node changed.
'node_layer <monitor_id> <desktop_id> <node_id> below|normal|above'::
super + m
bspc desktop -l next
-# if the current node is automatic, send it to the last manual, otherwise pull the last leaf
+# send the newest marked node to the newest preselected node
super + y
- bspc query -N -n focused.automatic && bspc node -n last.!automatic || bspc node last.leaf -n focused
+ bspc newest.marked.local -n newest.!automatic.local
# swap the current node and the biggest node
super + g
bspc node -t {tiled,pseudo_tiled,floating,fullscreen}
# set the node flags
-super + ctrl + {x,y,z}
- bspc node -g {locked,sticky,private}
+super + ctrl + {m,x,y,z}
+ bspc node -g {marked,locked,sticky,private}
#
# focus/swap
return NULL;
}
+bool history_find_newest_node(coordinates_t *ref, coordinates_t *dst, node_select_t sel)
+{
+ for (history_t *h = history_tail; h != NULL; h = h->prev) {
+ if (h->loc.node == NULL ||
+ h->loc.node->hidden ||
+ !node_matches(&h->loc, ref, sel)) {
+ continue;
+ }
+ *dst = h->loc;
+ return true;
+ }
+
+ return false;
+}
+
bool history_find_node(history_dir_t hdi, coordinates_t *ref, coordinates_t *dst, node_select_t sel)
{
if (history_needle == NULL || record_history) {
return false;
}
+bool history_find_newest_desktop(coordinates_t *ref, coordinates_t *dst, desktop_select_t sel)
+{
+ for (history_t *h = history_tail; h != NULL; h = h->prev) {
+ if (desktop_matches(&h->loc, ref, sel)) {
+ *dst = h->loc;
+ return true;
+ }
+ }
+
+ return false;
+}
+
bool history_find_desktop(history_dir_t hdi, coordinates_t *ref, coordinates_t *dst, desktop_select_t sel)
{
if (history_needle == NULL || record_history) {
return false;
}
+bool history_find_newest_monitor(coordinates_t *ref, coordinates_t *dst, monitor_select_t sel)
+{
+ for (history_t *h = history_tail; h != NULL; h = h->prev) {
+ if (monitor_matches(&h->loc, ref, sel)) {
+ *dst = h->loc;
+ return true;
+ }
+ }
+
+ return false;
+}
+
bool history_find_monitor(history_dir_t hdi, coordinates_t *ref, coordinates_t *dst, monitor_select_t sel)
{
if (history_needle == NULL || record_history) {
node_t *history_last_node(desktop_t *d, node_t *n);
desktop_t *history_last_desktop(monitor_t *m, desktop_t *d);
monitor_t *history_last_monitor(monitor_t *m);
+bool history_find_newest_node(coordinates_t *ref, coordinates_t *dst, node_select_t sel);
bool history_find_node(history_dir_t hdi, coordinates_t *ref, coordinates_t *dst, node_select_t sel);
+bool history_find_newest_desktop(coordinates_t *ref, coordinates_t *dst, desktop_select_t sel);
bool history_find_desktop(history_dir_t hdi, coordinates_t *ref, coordinates_t *dst, desktop_select_t sel);
+bool history_find_newest_monitor(coordinates_t *ref, coordinates_t *dst, monitor_select_t sel);
bool history_find_monitor(history_dir_t hdi, coordinates_t *ref, coordinates_t *dst, monitor_select_t sel);
uint32_t history_rank(node_t *n);
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 if (streq("marked", key)) {
+ set_marked(trg.monitor, trg.desktop, trg.node, (a == ALTER_SET ? b : !trg.node->marked));
} else {
fail(rsp, "node %s: Invalid key: '%s'.\n", *(args - 1), key);
break;
GET_MOD(sticky)
GET_MOD(private)
GET_MOD(locked)
+ GET_MOD(marked)
GET_MOD(urgent)
GET_MOD(same_class)
GET_MOD(descendant_of)
fprintf(rsp, "\"sticky\":%s,", BOOL_STR(n->sticky));
fprintf(rsp, "\"private\":%s,", BOOL_STR(n->private));
fprintf(rsp, "\"locked\":%s,", BOOL_STR(n->locked));
+ fprintf(rsp, "\"marked\":%s,", BOOL_STR(n->marked));
fprintf(rsp, "\"presel\":");
query_presel(n->presel, rsp);
fprintf(rsp,",");
rect_buf = malloc(1);
*rect_buf = '\0';
}
- asprintf(buf, "monitor=%s desktop=%s node=%s state=%s layer=%s split_dir=%s split_ratio=%lf hidden=%s sticky=%s private=%s locked=%s center=%s follow=%s manage=%s focus=%s border=%s rectangle=%s",
+ asprintf(buf, "monitor=%s desktop=%s node=%s state=%s layer=%s split_dir=%s split_ratio=%lf hidden=%s sticky=%s private=%s locked=%s marked=%s center=%s follow=%s manage=%s focus=%s border=%s rectangle=%s",
csq->monitor_desc, csq->desktop_desc, csq->node_desc,
csq->state == NULL ? "" : STATE_STR(*csq->state),
csq->layer == NULL ? "" : LAYER_STR(*csq->layer),
csq->split_dir, csq->split_ratio,
ON_OFF_STR(csq->hidden), ON_OFF_STR(csq->sticky), ON_OFF_STR(csq->private),
- ON_OFF_STR(csq->locked), ON_OFF_STR(csq->center), ON_OFF_STR(csq->follow),
+ ON_OFF_STR(csq->locked), ON_OFF_STR(csq->marked), ON_OFF_STR(csq->center), ON_OFF_STR(csq->follow),
ON_OFF_STR(csq->manage), ON_OFF_STR(csq->focus), ON_OFF_STR(csq->border), rect_buf);
free(rect_buf);
}
.sticky = OPTION_NONE,
.private = OPTION_NONE,
.locked = OPTION_NONE,
+ .marked = OPTION_NONE,
.urgent = OPTION_NONE,
.same_class = OPTION_NONE,
.descendant_of = OPTION_NONE,
history_find_node(hdi, ref, dst, sel);
} else if (streq("last", desc)) {
history_find_node(HISTORY_OLDER, ref, dst, sel);
+ } else if (streq("newest", desc)) {
+ history_find_newest_node(ref, dst, sel);
} else if (streq("biggest", desc)) {
find_biggest(ref, dst, sel);
} else if (streq("pointed", desc)) {
history_find_desktop(hdi, ref, dst, sel);
} else if (streq("last", desc)) {
history_find_desktop(HISTORY_OLDER, ref, dst, sel);
+ } else if (streq("newest", desc)) {
+ history_find_newest_desktop(ref, dst, sel);
} else if (streq("focused", desc)) {
coordinates_t loc = {mon, mon->desk, NULL};
if (desktop_matches(&loc, ref, sel)) {
history_find_monitor(hdi, ref, dst, sel);
} else if (streq("last", desc)) {
history_find_monitor(HISTORY_OLDER, ref, dst, sel);
+ } else if (streq("newest", desc)) {
+ history_find_newest_monitor(ref, dst, sel);
} else if (streq("primary", desc)) {
if (pri_mon != NULL) {
coordinates_t loc = {pri_mon, NULL, NULL};
NFLAG(sticky)
NFLAG(private)
NFLAG(locked)
+ NFLAG(marked)
#undef NFLAG
if (loc->node->client == NULL &&
RESTORE_BOOL(sticky, &n->sticky)
RESTORE_BOOL(private, &n->private)
RESTORE_BOOL(locked, &n->locked)
+ RESTORE_BOOL(marked, &n->marked)
} else if (keyeq("presel", *t, json)) {
(*t)++;
n->presel = restore_presel(t, json);
SETCSQ(sticky)
SETCSQ(private)
SETCSQ(locked)
+ SETCSQ(marked)
SETCSQ(center)
SETCSQ(follow)
SETCSQ(manage)
fprintf(stream, ":T@");
}
int i = 0;
- char flags[4];
+ char flags[5];
if (n->sticky) {
flags[i++] = 'S';
}
if (n->locked) {
flags[i++] = 'L';
}
+ if (n->marked) {
+ flags[i++] = 'M';
+ }
flags[i] = '\0';
fprintf(stream, ":G%s", flags);
}
d->root = c;
}
cancel_presel(m, d, f);
+ set_marked(m, d, n, false);
}
}
node_t *n = calloc(1, sizeof(node_t));
n->id = id;
n->parent = n->first_child = n->second_child = NULL;
- n->vacant = n->hidden = n->sticky = n->private = n->locked = false;
+ n->vacant = n->hidden = n->sticky = n->private = n->locked = n->marked = false;
n->split_ratio = split_ratio;
n->split_type = TYPE_VERTICAL;
n->birth_rotation = 0;
}
}
+void set_marked(monitor_t *m, desktop_t *d, node_t *n, bool value)
+{
+ if (n == NULL || n->marked == value) {
+ return;
+ }
+
+ n->marked = value;
+
+ put_status(SBSC_MASK_NODE_FLAG, "node_flag 0x%08X 0x%08X 0x%08X marked %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) {
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_marked(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(monitor_t *m, desktop_t *d, node_t *n);
option_bool_t sticky;
option_bool_t private;
option_bool_t locked;
+ option_bool_t marked;
option_bool_t urgent;
option_bool_t same_class;
option_bool_t descendant_of;
bool sticky;
bool private;
bool locked;
+ bool marked;
node_t *first_child;
node_t *second_child;
node_t *parent;
bool sticky;
bool private;
bool locked;
+ bool marked;
bool center;
bool follow;
bool manage;
set_sticky(m, d, n, csq->sticky);
set_private(m, d, n, csq->private);
set_locked(m, d, n, csq->locked);
+ set_marked(m, d, n, csq->marked);
arrange(m, d);