diff --git a/Makefile b/Makefile index 9cbedc22..d228a0f7 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ VERCMD ?= git describe --tags 2> /dev/null VERSION := $(shell $(VERCMD) || cat VERSION) CPPFLAGS += -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" -CFLAGS += -std=c99 -pedantic -Wall -Wextra -DJSMN_STRICT +CFLAGS += -std=c99 -pedantic -Wall -Wextra -DJSMN_STRICT -fcommon LDFLAGS ?= LDLIBS = $(LDFLAGS) -lm -lxcb -lxcb-util -lxcb-keysyms -lxcb-icccm -lxcb-ewmh -lxcb-randr -lxcb-xinerama -lxcb-shape diff --git a/README.md b/README.md index 035e8876..c2a70ddc 100644 --- a/README.md +++ b/README.md @@ -131,6 +131,10 @@ Since *1* is wide, it gets split vertically and *2* is added as *a*'s second chi 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. +#### Hvsplit scheme + +This is a generalized longest side scheme. It takes into account parameter hvsplit_ratio which indicates maximum ratio of width to hight after which the split is vertical. With hvsplit_ratio it behaves like longest side scheme. + #### Alternate scheme When the value of the automatic scheme is `alternate`, the window will be attached as if the insertion point was in manual mode and the split direction was chosen based on the split type of the insertion point's parent and the initial polarity. If the parent is split horizontally, the insertion point will be split vertically and vice versa. diff --git a/contrib/bash_completion b/contrib/bash_completion index 059612c5..674b5c87 100644 --- a/contrib/bash_completion +++ b/contrib/bash_completion @@ -1,7 +1,7 @@ _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 top_monocle_padding right_monocle_padding bottom_monocle_padding left_monocle_padding split_ratio automatic_scheme removal_adjustment initial_polarity directional_focus_tightness presel_feedback 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 ignore_ewmh_struts 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 top_monocle_padding right_monocle_padding bottom_monocle_padding left_monocle_padding split_ratio hvsplit_ratio automatic_scheme removal_adjustment initial_polarity directional_focus_tightness presel_feedback borderless_monocle gapless_monocle single_monocle pointer_motion_interval pointer_modifier pointer_action1 pointer_action2 pointer_action3 pointer_action8 pointer_action9 click_to_focus swallow_first_click focus_follows_pointer pointer_follows_focus pointer_follows_monitor mapping_events_count ignore_ewmh_focus ignore_ewmh_fullscreen ignore_ewmh_struts center_pseudo_tiled honor_size_hints remove_disabled_monitors remove_unplugged_monitors merge_overlapping_monitors' COMPREPLY=() diff --git a/contrib/fish_completion b/contrib/fish_completion index c76cde5b..404aad66 100644 --- a/contrib/fish_completion +++ b/contrib/fish_completion @@ -11,4 +11,4 @@ function __fish_bspc_using_command 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 top_monocle_padding right_monocle_padding bottom_monocle_padding left_monocle_padding split_ratio automatic_scheme removal_adjustment initial_polarity directional_focus_tightness presel_feedback 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 ignore_ewmh_struts 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 top_monocle_padding right_monocle_padding bottom_monocle_padding left_monocle_padding split_ratio hvsplit_ratio automatic_scheme removal_adjustment initial_polarity directional_focus_tightness presel_feedback borderless_monocle gapless_monocle single_monocle pointer_motion_interval pointer_modifier pointer_action1 pointer_action2 pointer_action3 pointer_action8 pointer_action9 click_to_focus swallow_first_click focus_follows_pointer pointer_follows_focus pointer_follows_monitor mapping_events_count ignore_ewmh_focus ignore_ewmh_fullscreen ignore_ewmh_struts center_pseudo_tiled honor_size_hints remove_disabled_monitors remove_unplugged_monitors merge_overlapping_monitors' diff --git a/contrib/zsh_completion b/contrib/zsh_completion index 417dde59..2e2ee9a0 100644 --- a/contrib/zsh_completion +++ b/contrib/zsh_completion @@ -321,7 +321,7 @@ _bspc() { behaviour_bool=(single_monocle removal_adjustment ignore_ewmh_focus ignore_ewmh_struts 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 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}) + input=(click_to_focus pointer_motion_interval pointer_modifier pointer_action{1,2,3,8,9}) if [[ "$CURRENT" == (2|3) ]];then _arguments \ '-d[Set settings for the selected desktop]: :_bspc_selector -- desktop'\ @@ -347,7 +347,7 @@ _bspc() { (initial_polarity) _values "set $setting" first_child second_child ;; - (pointer_action(1|2|3)) + (pointer_action(1|2|3|8|9)) _values "set $setting" move resize_side resize_corner focus none ;; (pointer_modifier) diff --git a/doc/bspwm.1 b/doc/bspwm.1 index 732f1190..46d1b284 100644 --- a/doc/bspwm.1 +++ b/doc/bspwm.1 @@ -1243,7 +1243,7 @@ Keyboard modifier used for moving or resizing windows\&. Accept the following va \fBmod5\fR\&. .RE .PP -\fIpointer_action1\fR, \fIpointer_action2\fR, \fIpointer_action3\fR +\fIpointer_action1\fR, \fIpointer_action2\fR, \fIpointer_action3\fR, \fIpointer_action8\fR, \fIpointer_action9\fR .RS 4 Action performed when pressing \fIpointer_modifier\fR diff --git a/doc/bspwm.1.asciidoc b/doc/bspwm.1.asciidoc index 6fc237ed..4ea6951e 100644 --- a/doc/bspwm.1.asciidoc +++ b/doc/bspwm.1.asciidoc @@ -724,6 +724,8 @@ Global Settings 'pointer_action1':: 'pointer_action2':: 'pointer_action3':: +'pointer_action8':: +'pointer_action9':: Action performed when pressing 'pointer_modifier' + 'button'. Accept the following values: *move*, *resize_side*, *resize_corner*, *focus*, *none*. 'click_to_focus':: diff --git a/src/events.h b/src/events.h index d450965e..52bf8f2e 100644 --- a/src/events.h +++ b/src/events.h @@ -31,7 +31,7 @@ #define ERROR_CODE_BAD_WINDOW 3 uint8_t randr_base; -static const xcb_button_index_t BUTTONS[] = {XCB_BUTTON_INDEX_1, XCB_BUTTON_INDEX_2, XCB_BUTTON_INDEX_3}; +static const xcb_button_index_t BUTTONS[] = {XCB_BUTTON_INDEX_1, XCB_BUTTON_INDEX_2, XCB_BUTTON_INDEX_3, 8, 9 }; void handle_event(xcb_generic_event_t *evt); void map_request(xcb_generic_event_t *evt); diff --git a/src/helpers.h b/src/helpers.h index e51e5d06..eb4a4779 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -46,7 +46,7 @@ #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" : ((A) == SCHEME_ALTERNATE ? "alternate" : "spiral")) +#define AUTO_SCM_STR(A) ((A) == SCHEME_LONGEST_SIDE ? "longest_side" : ((A) == SCHEME_HVSPLIT ? "hvsplit" : ((A) == SCHEME_ALTERNATE ? "alternate" : "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") diff --git a/src/messages.c b/src/messages.c index a8198922..54134fa8 100644 --- a/src/messages.c +++ b/src/messages.c @@ -1554,6 +1554,15 @@ void set_setting(coordinates_t loc, char *name, char *value, FILE *rsp) return; } return; + } else if (streq("hvsplit_ratio", name)) { + double r; + if (sscanf(value, "%lf", &r) == 1 && r > 0) { + hvsplit_ratio = r; + } else { + fail(rsp, "config: %s: Invalid value: '%s'.\n", name, value); \ + return; + } + return; #define SET_COLOR(s) \ } else if (streq(#s, name)) { \ if (!is_hex_color(value)) { \ @@ -1620,8 +1629,13 @@ void set_setting(coordinates_t loc, char *name, char *value, FILE *rsp) } } else if (streq("pointer_action1", name) || streq("pointer_action2", name) || - streq("pointer_action3", name)) { + streq("pointer_action3", name) || + streq("pointer_action8", name) || + streq("pointer_action9", name)) { int index = name[14] - '1'; + if (index > 2) { + index -= 4; + } if (parse_pointer_action(value, &pointer_actions[index])) { ungrab_buttons(); grab_buttons(); @@ -1693,7 +1707,6 @@ void set_setting(coordinates_t loc, char *name, char *value, FILE *rsp) SET_BOOL(borderless_monocle) SET_BOOL(gapless_monocle) SET_BOOL(swallow_first_click) - SET_BOOL(pointer_follows_focus) SET_BOOL(pointer_follows_monitor) SET_BOOL(ignore_ewmh_focus) SET_BOOL(ignore_ewmh_struts) @@ -1701,6 +1714,15 @@ void set_setting(coordinates_t loc, char *name, char *value, FILE *rsp) SET_BOOL(honor_size_hints) SET_BOOL(removal_adjustment) #undef SET_BOOL + } else if (streq("pointer_follows_focus", name)) { + bool pff = pointer_follows_focus; + if (!parse_bool(value, &pointer_follows_focus)) { + fail(rsp, "config: %s: Invalid value: '%s'.\n", name, value); + return; + } + if (pff == pointer_follows_focus) { + return; + } #define SET_MON_BOOL(s) \ } else if (streq(#s, name)) { \ if (!parse_bool(value, &s)) { \ @@ -1733,6 +1755,8 @@ void get_setting(coordinates_t loc, char *name, FILE* rsp) { if (streq("split_ratio", name)) { fprintf(rsp, "%lf", split_ratio); + } else if (streq("hvsplit_ratio", name)) { + fprintf(rsp, "%lf", hvsplit_ratio); } else if (streq("border_width", name)) { if (loc.node != NULL) { for (node_t *n = first_extrema(loc.node); n != NULL; n = next_leaf(n, loc.node)) { @@ -1803,8 +1827,13 @@ void get_setting(coordinates_t loc, char *name, FILE* rsp) fprintf(rsp, "%u", pointer_motion_interval); } else if (streq("pointer_action1", name) || streq("pointer_action2", name) || - streq("pointer_action3", name)) { + streq("pointer_action3", name) || + streq("pointer_action8", name) || + streq("pointer_action9", name)) { int index = name[14] - '1'; + if (index > 2) { + index -= 4; + } print_pointer_action(pointer_actions[index], rsp); #define GET_COLOR(s) \ } else if (streq(#s, name)) { \ diff --git a/src/parse.c b/src/parse.c index 8035d108..2cf485d6 100644 --- a/src/parse.c +++ b/src/parse.c @@ -227,6 +227,12 @@ bool parse_button_index(char *s, int8_t *b) } else if (strcmp(s, "button3") == 0) { *b = XCB_BUTTON_INDEX_3; return true; + } else if (strcmp(s, "button8") == 0) { + *b = 8; + return true; + } else if (strcmp(s, "button9") == 0) { + *b = 9; + return true; } else if (strcmp(s, "none") == 0) { *b = -1; return true; @@ -272,6 +278,9 @@ bool parse_automatic_scheme(char *s, automatic_scheme_t *a) if (streq("longest_side", s)) { *a = SCHEME_LONGEST_SIDE; return true; + } else if (streq("hvsplit", s)) { + *a = SCHEME_HVSPLIT; + return true; } else if (streq("alternate", s)) { *a = SCHEME_ALTERNATE; return true; diff --git a/src/pointer.c b/src/pointer.c index 1bc6a6bb..d35c1aed 100644 --- a/src/pointer.c +++ b/src/pointer.c @@ -55,7 +55,11 @@ void window_grab_buttons(xcb_window_t win) window_grab_button(win, BUTTONS[i], XCB_NONE); } if (pointer_actions[i] != ACTION_NONE) { - window_grab_button(win, BUTTONS[i], pointer_modifier); + if (BUTTONS[i] == 8 || BUTTONS[i] == 9) { + window_grab_button(win, BUTTONS[i], 0); + } else { + window_grab_button(win, BUTTONS[i], pointer_modifier); + } } } } diff --git a/src/query.c b/src/query.c index 9084e4c4..57f21f07 100644 --- a/src/query.c +++ b/src/query.c @@ -393,6 +393,12 @@ void print_button_index(int8_t b, FILE *rsp) case XCB_BUTTON_INDEX_3: fprintf(rsp, "button3"); break; + case 8: + fprintf(rsp, "button8"); + break; + case 9: + fprintf(rsp, "button9"); + break; case -1: fprintf(rsp, "none"); break; diff --git a/src/settings.c b/src/settings.c index 7997c371..b6ff5955 100644 --- a/src/settings.c +++ b/src/settings.c @@ -57,6 +57,7 @@ void load_settings(void) window_gap = WINDOW_GAP; border_width = BORDER_WIDTH; split_ratio = SPLIT_RATIO; + hvsplit_ratio = HVSPLIT_RATIO; initial_polarity = SECOND_CHILD; automatic_scheme = AUTOMATIC_SCHEME; removal_adjustment = REMOVAL_ADJUSTMENT; @@ -67,6 +68,8 @@ void load_settings(void) pointer_actions[0] = ACTION_MOVE; pointer_actions[1] = ACTION_RESIZE_SIDE; pointer_actions[2] = ACTION_RESIZE_CORNER; + pointer_actions[3] = ACTION_NONE; + pointer_actions[4] = ACTION_NONE; mapping_events_count = MAPPING_EVENTS_COUNT; presel_feedback = PRESEL_FEEDBACK; diff --git a/src/settings.h b/src/settings.h index c205e50b..a716a78d 100644 --- a/src/settings.h +++ b/src/settings.h @@ -42,6 +42,7 @@ #define WINDOW_GAP 6 #define BORDER_WIDTH 1 #define SPLIT_RATIO 0.5 +#define HVSPLIT_RATIO 1 #define AUTOMATIC_SCHEME SCHEME_LONGEST_SIDE #define REMOVAL_ADJUSTMENT true @@ -80,6 +81,7 @@ padding_t monocle_padding; int window_gap; unsigned int border_width; double split_ratio; +double hvsplit_ratio; child_polarity_t initial_polarity; automatic_scheme_t automatic_scheme; bool removal_adjustment; @@ -87,7 +89,7 @@ tightness_t directional_focus_tightness; uint16_t pointer_modifier; uint32_t pointer_motion_interval; -pointer_action_t pointer_actions[3]; +pointer_action_t pointer_actions[5]; int8_t mapping_events_count; bool presel_feedback; diff --git a/src/tree.c b/src/tree.c index 2aa42ebe..7d621dd6 100644 --- a/src/tree.c +++ b/src/tree.c @@ -341,8 +341,14 @@ node_t *insert_node(monitor_t *m, desktop_t *d, node_t *n, node_t *f) c->first_child = f; c->second_child = n; } - if (p == NULL || automatic_scheme == SCHEME_LONGEST_SIDE || single_tiled) { - if (f->rectangle.width > f->rectangle.height) { + if (p == NULL || automatic_scheme == SCHEME_LONGEST_SIDE || automatic_scheme == SCHEME_HVSPLIT || single_tiled) { + // TODO + double ratio = 1; + if (automatic_scheme == SCHEME_HVSPLIT) { + ratio = hvsplit_ratio; + } + + if (f->rectangle.width > f->rectangle.height * ratio) { c->split_type = TYPE_VERTICAL; } else { c->split_type = TYPE_HORIZONTAL; @@ -1260,9 +1266,16 @@ void unlink_node(monitor_t *m, desktop_t *d, node_t *n) } else { rotate_tree(b, 90); } - } else if (automatic_scheme == SCHEME_LONGEST_SIDE || g == NULL) { + } else if (automatic_scheme == SCHEME_LONGEST_SIDE || + automatic_scheme == SCHEME_HVSPLIT || + g == NULL) { + double ratio = 1; + if (automatic_scheme == SCHEME_HVSPLIT) { + ratio = hvsplit_ratio; + } + if (p != NULL) { - if (p->rectangle.width > p->rectangle.height) { + if (p->rectangle.width > p->rectangle.height * ratio) { b->split_type = TYPE_VERTICAL; } else { b->split_type = TYPE_HORIZONTAL; diff --git a/src/types.h b/src/types.h index 2c15a264..ad53225b 100644 --- a/src/types.h +++ b/src/types.h @@ -46,6 +46,7 @@ typedef enum { typedef enum { SCHEME_LONGEST_SIDE, + SCHEME_HVSPLIT, SCHEME_ALTERNATE, SCHEME_SPIRAL } automatic_scheme_t; @@ -240,6 +241,7 @@ struct node_t { uint32_t id; split_type_t split_type; double split_ratio; + double hvsplit_ratio; presel_t *presel; xcb_rectangle_t rectangle; constraints_t constraints; @@ -353,6 +355,7 @@ typedef struct { char node_desc[MAXLEN]; char split_dir[SMALEN]; double split_ratio; + double hvsplit_ratio; stack_layer_t *layer; client_state_t *state; bool hidden;