Fixes #764.
The insertion mode tells *bspwm* how it should alter the tree in order to insert new windows on a given insertion point.
-By default the insertion point is the focused window and its default insertion mode is *automatic*.
-
-### Automatic Mode
-
-The *automatic* mode, as opposed to the *manual* mode, doesn't require any user choice: the new window will *take the space* of the insertion point.
-
-For example, let's consider the following scenario:
-
-```
- a a a
- / \ / \ / \
- 1 b ---> 1 c ---> 1 d
- / \ / \ / \
- 2 3 4 b 5 c
- ^ ^ / \ ^ / \
- 3 2 b 4
- / \
- 3 2
-
- +-----------------------+ +-----------------------+ +-----------------------+
- | | | | | | | | |
- | | 2 | | | 4 | | | 5 |
- | | ^ | | | ^ | | | ^ |
- | 1 |-----------| | 1 |-----------| | 1 |-----------|
- | | | | | | | | | 3 | |
- | | 3 | | | 3 | 2 | | |-----| 4 |
- | | | | | | | | | 2 | |
- +-----------------------+ +-----------------------+ +-----------------------+
-
- X Y Z
-```
-
-In state *X*, the insertion point, *2* is in automatic mode.
-
-When we add a new window, *4*, the whole tree rooted at *b* is reattached, as the second child of a new internal node, *c*.
-
-The splitting parameters of *b* (type: *horizontal*, ratio: *½*) are copied to *c* and *b* is rotated by 90° clockwise.
-
-The tiling rectangle of *4* in state *Y* is equal to the tiling rectangle of *2* in state *X*.
-
-Then the insertion of *5*, with *4* as insertion point, leads to *Z*.
-
-The automatic mode generates window spirals that rotate clockwise (resp. anti-clockwise) if the insertion point is the first (resp. second) child of its parent.
+By default the insertion point is the focused window and its insertion mode is *automatic*.
### Manual Mode
After doing so the insertion point goes into *manual* mode.
-For example, let's consider the following scenario:
+Let's consider the following scenario:
```
a a a
The ratio of the preselection (that ends up being the ratio of the split of the new internal node) can be changed with the *node -o|--presel-ratio* message.
+### Automatic Mode
+
+The *automatic* mode, as opposed to the *manual* mode, doesn't require any user choice. The way the new window is inserted is determined by the value of the automatic scheme and the initial polarity settings.
+
+#### Longest side
+
+When the value of the automatic scheme is `longest_side`, the window will be attached as if the insertion point was in manual mode and the split direction was choosen based on the dimensions of the tiling rectangle and the initial polarity.
+
+Let's consider the following scenario, where the initial polarity is set to `second_child`:
+
+```
+ 1 a a
+ ^ / \ / \
+ ---> 1 2 ---> 1 b
+ ^ / \
+ 2 3
+ ^
+
+ +-----------------------+ +-----------------------+ +-----------------------+
+ | | | | | | | |
+ | | | | | | | 2 |
+ | | | | | | | |
+ | 1 | | 1 | 2 | | 1 |-----------|
+ | ^ | | | ^ | | | |
+ | | | | | | | 3 |
+ | | | | | | | ^ |
+ +-----------------------+ +-----------------------+ +-----------------------+
+
+ X Y Z
+```
+
+In state *X*, a new window is added.
+
+Since *1* is wide, it gets split vertically and *2* is added as *a*'s second child given the initial polarity.
+
+This leads to *Y* where we insert window *3*. *2* is tall and is therefore split horizontally. *3* is once again added as *b*'s second child.
+
+#### Spiral
+
+When the value of the automatic scheme is `spiral`, the window will *take the space* of the insertion point.
+
+Let's dive into the details with the following scenario:
+
+```
+ a a a
+ / \ / \ / \
+ 1 b ---> 1 c ---> 1 d
+ / \ / \ / \
+ 2 3 4 b 5 c
+ ^ ^ / \ ^ / \
+ 3 2 b 4
+ / \
+ 3 2
+
+ +-----------------------+ +-----------------------+ +-----------------------+
+ | | | | | | | | |
+ | | 2 | | | 4 | | | 5 |
+ | | ^ | | | ^ | | | ^ |
+ | 1 |-----------| | 1 |-----------| | 1 |-----------|
+ | | | | | | | | | 3 | |
+ | | 3 | | | 3 | 2 | | |-----| 4 |
+ | | | | | | | | | 2 | |
+ +-----------------------+ +-----------------------+ +-----------------------+
+
+ X Y Z
+```
+
+In state *X*, the insertion point, *2* is in automatic mode.
+
+When we add a new window, *4*, the whole tree rooted at *b* is reattached, as the second child of a new internal node, *c*.
+
+The splitting parameters of *b* (type: *horizontal*, ratio: *½*) are copied to *c* and *b* is rotated by 90° clockwise.
+
+The tiling rectangle of *4* in state *Y* is equal to the tiling rectangle of *2* in state *X*.
+
+Then the insertion of *5*, with *4* as insertion point, leads to *Z*.
+
+The *spiral* automatic scheme generates window spirals that rotate clockwise (resp. anti-clockwise) if the insertion point is the first (resp. second) child of its parent.
+
+
## Supported protocols and standards
- The RandR and Xinerama protocols.
_bspc() {
local commands='node desktop monitor query rule wm subscribe config quit'
- local settings='external_rules_command status_prefix normal_border_color active_border_color focused_border_color presel_feedback_color border_width window_gap top_padding right_padding bottom_padding left_padding split_ratio initial_polarity directional_focus_tightness borderless_monocle gapless_monocle single_monocle pointer_motion_interval pointer_modifier pointer_action1 pointer_action2 pointer_action3 click_to_focus swallow_first_click focus_follows_pointer pointer_follows_focus pointer_follows_monitor mapping_events_count ignore_ewmh_focus ignore_ewmh_fullscreen center_pseudo_tiled honor_size_hints remove_disabled_monitors remove_unplugged_monitors merge_overlapping_monitors'
+ local settings='external_rules_command status_prefix normal_border_color active_border_color focused_border_color presel_feedback_color border_width window_gap top_padding right_padding bottom_padding left_padding split_ratio automatic_scheme initial_polarity directional_focus_tightness borderless_monocle gapless_monocle single_monocle pointer_motion_interval pointer_modifier pointer_action1 pointer_action2 pointer_action3 click_to_focus swallow_first_click focus_follows_pointer pointer_follows_focus pointer_follows_monitor mapping_events_count ignore_ewmh_focus ignore_ewmh_fullscreen center_pseudo_tiled honor_size_hints remove_disabled_monitors remove_unplugged_monitors merge_overlapping_monitors'
COMPREPLY=()
end
complete -f -c bspc -n '__fish_bspc_needs_command' -a 'node desktop monitor query rule wm subscribe config quit'
-complete -f -c bspc -n '__fish_bspc_using_command config' -a 'external_rules_command status_prefix normal_border_color active_border_color focused_border_color presel_feedback_color border_width window_gap top_padding right_padding bottom_padding left_padding split_ratio initial_polarity directional_focus_tightness borderless_monocle gapless_monocle single_monocle pointer_motion_interval pointer_modifier pointer_action1 pointer_action2 pointer_action3 click_to_focus swallow_first_click focus_follows_pointer pointer_follows_focus pointer_follows_monitor mapping_events_count ignore_ewmh_focus ignore_ewmh_fullscreen center_pseudo_tiled honor_size_hints remove_disabled_monitors remove_unplugged_monitors merge_overlapping_monitors'
+complete -f -c bspc -n '__fish_bspc_using_command config' -a 'external_rules_command status_prefix normal_border_color active_border_color focused_border_color presel_feedback_color border_width window_gap top_padding right_padding bottom_padding left_padding split_ratio automatic_scheme initial_polarity directional_focus_tightness borderless_monocle gapless_monocle single_monocle pointer_motion_interval pointer_modifier pointer_action1 pointer_action2 pointer_action3 click_to_focus swallow_first_click focus_follows_pointer pointer_follows_focus pointer_follows_monitor mapping_events_count ignore_ewmh_focus ignore_ewmh_fullscreen center_pseudo_tiled honor_size_hints remove_disabled_monitors remove_unplugged_monitors merge_overlapping_monitors'
look_bool=(borderless_monocle gapless_monocle)
look=({normal,active,focused}_border_color {top,right,bottom,left}_padding presel_feedback_color border_width window_gap)
behaviour_bool=(single_monocle ignore_ewmh_focus center_pseudo_tiled honor_size_hints remove_disabled_monitors remove_unplugged_monitors merge_overlapping_monitors)
- behaviour=(mapping_events_count ignore_ewmh_fullscreen external_rules_command split_ratio initial_polarity directional_focus_tightness status_prefix)
+ behaviour=(mapping_events_count ignore_ewmh_fullscreen external_rules_command split_ratio automatic_scheme initial_polarity directional_focus_tightness status_prefix)
input_bool=(swallow_first_click focus_follows_pointer pointer_follows_{focus,monitor})
input=(click_to_focus pointer_motion_interval pointer_modifier pointer_action{1,2,3})
if [[ "$CURRENT" == (2|3) ]];then
.\" Title: bspwm
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
-.\" Date: 08/28/2018
+.\" Date: 08/31/2018
.\" Manual: Bspwm Manual
-.\" Source: Bspwm 0.9.5-10-g336bc86
+.\" Source: Bspwm 0.9.5-14-g56ad57c
.\" Language: English
.\"
-.TH "BSPWM" "1" "08/28/2018" "Bspwm 0\&.9\&.5\-10\-g336bc86" "Bspwm Manual"
+.TH "BSPWM" "1" "08/31/2018" "Bspwm 0\&.9\&.5\-14\-g56ad57c" "Bspwm Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
command)\&.
.RE
.PP
+\fIautomatic_scheme\fR
+.RS 4
+The insertion scheme used when the insertion point is in automatic mode\&. Accept the following values:
+\fBlongest_side\fR,
+\fBspiral\fR\&.
+.RE
+.PP
\fIinitial_polarity\fR
.RS 4
On which child should a new window be attached when adding a window on a single window tree in automatic mode\&. Accept the following values:
'external_rules_command'::
External command used to retrieve rule consequences. The command will receive the following arguments: window ID, class name, instance name, and intermediate consequences. The output of that command must have the following format: *key1=value1 key2=value2 ...* (the valid key/value pairs are given in the description of the 'rule' command).
+'automatic_scheme'::
+ The insertion scheme used when the insertion point is in automatic mode. Accept the following values: *longest_side*, *spiral*.
+
'initial_polarity'::
On which child should a new window be attached when adding a window on a single window tree in automatic mode. Accept the following values: *first_child*, *second_child*.
+++ /dev/null
-`wattr` belongs to [wmutils](https://github.com/wmutils/core).
+++ /dev/null
-#! /bin/sh
-
-fwid=$(bspc query -N -n focused.automatic)
-
-if [ -n "$fwid" ] ; then
- wattr wh $fwid | {
- read width height
- if [ $width -gt $height ] ; then
- echo "split_dir=west"
- else
- echo "split_dir=south"
- fi
- echo "split_ratio=0.5"
- }
-fi
#define LAYOUT_STR(A) ((A) == LAYOUT_TILED ? "tiled" : "monocle")
#define LAYOUT_CHR(A) ((A) == LAYOUT_TILED ? 'T' : 'M')
#define CHILD_POL_STR(A) ((A) == FIRST_CHILD ? "first_child" : "second_child")
+#define AUTO_SCM_STR(A) ((A) == SCHEME_LONGEST_SIDE ? "longest_side" : "spiral")
#define TIGHTNESS_STR(A) ((A) == TIGHTNESS_HIGH ? "high" : "low")
#define SPLIT_TYPE_STR(A) ((A) == TYPE_HORIZONTAL ? "horizontal" : "vertical")
#define SPLIT_MODE_STR(A) ((A) == MODE_AUTOMATIC ? "automatic" : "manual")
fail(rsp, "config: %s: Invalid value: '%s'.\n", name, value);
return;
}
+ } else if (streq("automatic_scheme", name)) {
+ automatic_scheme_t a;
+ if (parse_automatic_scheme(value, &a)) {
+ automatic_scheme = a;
+ } else {
+ fail(rsp, "config: %s: Invalid value: '%s'.\n", name, value);
+ return;
+ }
} else if (streq("mapping_events_count", name)) {
if (sscanf(value, "%" SCNi8, &mapping_events_count) != 1) {
fail(rsp, "config: %s: Invalid value: '%s'.\n", name, value);
fprintf(rsp, "%s", status_prefix);
} else if (streq("initial_polarity", name)) {
fprintf(rsp, "%s", CHILD_POL_STR(initial_polarity));
+ } else if (streq("automatic_scheme", name)) {
+ fprintf(rsp, "%s", AUTO_SCM_STR(automatic_scheme));
} else if (streq("mapping_events_count", name)) {
fprintf(rsp, "%" PRIi8, mapping_events_count);
} else if (streq("directional_focus_tightness", name)) {
return false;
}
+bool parse_automatic_scheme(char *s, automatic_scheme_t *a)
+{
+ if (streq("longest_side", s)) {
+ *a = SCHEME_LONGEST_SIDE;
+ return true;
+ } else if (streq("spiral", s)) {
+ *a = SCHEME_SPIRAL;
+ return true;
+ }
+ return false;
+}
+
bool parse_state_transition(char *s, state_transition_t *m)
{
if (streq("none", s)) {
bool parse_button_index(char *s, int8_t *b);
bool parse_pointer_action(char *s, pointer_action_t *a);
bool parse_child_polarity(char *s, child_polarity_t *p);
+bool parse_automatic_scheme(char *s, automatic_scheme_t *a);
bool parse_state_transition(char *s, state_transition_t *m);
bool parse_tightness(char *s, tightness_t *t);
bool parse_degree(char *s, int *d);
window_gap = WINDOW_GAP;
border_width = BORDER_WIDTH;
split_ratio = SPLIT_RATIO;
- initial_polarity = FIRST_CHILD;
+ initial_polarity = SECOND_CHILD;
+ automatic_scheme = SCHEME_LONGEST_SIDE;
directional_focus_tightness = TIGHTNESS_HIGH;
+
pointer_modifier = POINTER_MODIFIER;
pointer_motion_interval = POINTER_MOTION_INTERVAL;
- mapping_events_count = MAPPING_EVENTS_COUNT;
-
pointer_actions[0] = ACTION_MOVE;
pointer_actions[1] = ACTION_RESIZE_SIDE;
pointer_actions[2] = ACTION_RESIZE_CORNER;
+ mapping_events_count = MAPPING_EVENTS_COUNT;
borderless_monocle = BORDERLESS_MONOCLE;
gapless_monocle = GAPLESS_MONOCLE;
#define WINDOW_GAP 6
#define BORDER_WIDTH 1
#define SPLIT_RATIO 0.5
+#define AUTOMATIC_SCHEME SCHEME_LONGEST_SIDE
#define BORDERLESS_MONOCLE false
#define GAPLESS_MONOCLE false
int window_gap;
unsigned int border_width;
double split_ratio;
-
child_polarity_t initial_polarity;
+automatic_scheme_t automatic_scheme;
tightness_t directional_focus_tightness;
+
uint16_t pointer_modifier;
uint32_t pointer_motion_interval;
pointer_action_t pointer_actions[3];
}
n->parent = c;
if (f->presel == NULL) {
- if (p == NULL || (f->client != NULL && IS_TILED(f->client) && tiled_count(d->root, true) == 1)) {
+ if (p == NULL || automatic_scheme == SCHEME_LONGEST_SIDE || (f->client != NULL && IS_TILED(f->client) && tiled_count(d->root, true) == 1)) {
if (p != NULL) {
if (is_first_child(f)) {
p->first_child = c;
c->first_child = f;
c->second_child = n;
}
- if (m->rectangle.width > m->rectangle.height) {
+ if (f->rectangle.width > f->rectangle.height) {
c->split_type = TYPE_VERTICAL;
} else {
c->split_type = TYPE_HORIZONTAL;
MODE_MANUAL
} split_mode_t;
+typedef enum {
+ SCHEME_LONGEST_SIDE,
+ SCHEME_SPIRAL
+} automatic_scheme_t;
+
typedef enum {
STATE_TILED,
STATE_PSEUDO_TILED,
focus_follows_pointer=$(bspc config focus_follows_pointer)
initial_polarity=$(bspc config initial_polarity)
+automatic_scheme=$(bspc config automatic_scheme)
+bspc config automatic_scheme spiral
bspc config initial_polarity first_child
bspc config focus_follows_pointer false
cleanup () {
+ bspc config automatic_scheme "$automatic_scheme"
bspc config initial_polarity "$initial_polarity"
bspc config focus_follows_pointer "$focus_follows_pointer"
}