From: Michael Stapelberg Date: Sun, 14 Jan 2018 17:22:44 +0000 (+0100) Subject: Merge pull request #2998 from orestisf1993/issue-2990 X-Git-Tag: 4.15~17 X-Git-Url: https://git.sur5r.net/?p=i3%2Fi3;a=commitdiff_plain;h=fe95ac56bbc4de66b3b1a7120af587d72b033262;hp=0c2fbeedc2d8c11e210961c8c0ca9d43d4a044ce Merge pull request #2998 from orestisf1993/issue-2990 Don't raise floating windows when focused because of focus_follows_mouse --- diff --git a/docs/userguide b/docs/userguide index 98242a9b..974135ac 100644 --- a/docs/userguide +++ b/docs/userguide @@ -2320,8 +2320,11 @@ space from all the other containers. The optional pixel argument specifies by how many pixels a *floating container* should be grown or shrunk (the default is 10 pixels). The ppt argument means percentage points and specifies by how many percentage points a *tiling container* should be grown or shrunk (the -default is 10 percentage points). Note that +resize set+ will only work for -floating containers. +default is 10 percentage points). + +Notes about +resize set+: a value of 0 for or means "do +not resize in this direction", and resizing a tiling container by +px+ is not +implemented. It is recommended to define bindings for resizing in a dedicated binding mode. See <> and the example in the i3 diff --git a/etc/config b/etc/config index 5b751d00..3be9831d 100644 --- a/etc/config +++ b/etc/config @@ -104,29 +104,43 @@ bindsym Mod1+Shift+minus move scratchpad # If there are multiple scratchpad windows, this command cycles through them. bindsym Mod1+minus scratchpad show +# Define names for default workspaces for which we configure key bindings later on. +# We use variables to avoid repeating the names in multiple places. +set $ws1 "1" +set $ws2 "2" +set $ws3 "3" +set $ws4 "4" +set $ws5 "5" +set $ws6 "6" +set $ws7 "7" +set $ws8 "8" +set $ws9 "9" +set $ws10 "10" + + # switch to workspace -bindsym Mod1+1 workspace 1 -bindsym Mod1+2 workspace 2 -bindsym Mod1+3 workspace 3 -bindsym Mod1+4 workspace 4 -bindsym Mod1+5 workspace 5 -bindsym Mod1+6 workspace 6 -bindsym Mod1+7 workspace 7 -bindsym Mod1+8 workspace 8 -bindsym Mod1+9 workspace 9 -bindsym Mod1+0 workspace 10 +bindsym Mod1+1 workspace $ws1 +bindsym Mod1+2 workspace $ws2 +bindsym Mod1+3 workspace $ws3 +bindsym Mod1+4 workspace $ws4 +bindsym Mod1+5 workspace $ws5 +bindsym Mod1+6 workspace $ws6 +bindsym Mod1+7 workspace $ws7 +bindsym Mod1+8 workspace $ws8 +bindsym Mod1+9 workspace $ws9 +bindsym Mod1+0 workspace $ws10 # move focused container to workspace -bindsym Mod1+Shift+1 move container to workspace 1 -bindsym Mod1+Shift+2 move container to workspace 2 -bindsym Mod1+Shift+3 move container to workspace 3 -bindsym Mod1+Shift+4 move container to workspace 4 -bindsym Mod1+Shift+5 move container to workspace 5 -bindsym Mod1+Shift+6 move container to workspace 6 -bindsym Mod1+Shift+7 move container to workspace 7 -bindsym Mod1+Shift+8 move container to workspace 8 -bindsym Mod1+Shift+9 move container to workspace 9 -bindsym Mod1+Shift+0 move container to workspace 10 +bindsym Mod1+Shift+1 move container to workspace $ws1 +bindsym Mod1+Shift+2 move container to workspace $ws2 +bindsym Mod1+Shift+3 move container to workspace $ws3 +bindsym Mod1+Shift+4 move container to workspace $ws4 +bindsym Mod1+Shift+5 move container to workspace $ws5 +bindsym Mod1+Shift+6 move container to workspace $ws6 +bindsym Mod1+Shift+7 move container to workspace $ws7 +bindsym Mod1+Shift+8 move container to workspace $ws8 +bindsym Mod1+Shift+9 move container to workspace $ws9 +bindsym Mod1+Shift+0 move container to workspace $ws10 # reload the configuration file bindsym Mod1+Shift+c reload @@ -154,7 +168,7 @@ mode "resize" { bindsym Up resize shrink height 10 px or 10 ppt bindsym Right resize grow width 10 px or 10 ppt - # back to normal: Enter or Escape + # back to normal: Enter or Escape or Mod1+r bindsym Return mode "default" bindsym Escape mode "default" bindsym Mod1+r mode "default" diff --git a/etc/config.keycodes b/etc/config.keycodes index c07462b4..2d56876c 100644 --- a/etc/config.keycodes +++ b/etc/config.keycodes @@ -91,29 +91,42 @@ bindcode $mod+38 focus parent # focus the child container #bindsym $mod+d focus child +# Define names for default workspaces for which we configure key bindings later on. +# We use variables to avoid repeating the names in multiple places. +set $ws1 "1" +set $ws2 "2" +set $ws3 "3" +set $ws4 "4" +set $ws5 "5" +set $ws6 "6" +set $ws7 "7" +set $ws8 "8" +set $ws9 "9" +set $ws10 "10" + # switch to workspace -bindcode $mod+10 workspace 1 -bindcode $mod+11 workspace 2 -bindcode $mod+12 workspace 3 -bindcode $mod+13 workspace 4 -bindcode $mod+14 workspace 5 -bindcode $mod+15 workspace 6 -bindcode $mod+16 workspace 7 -bindcode $mod+17 workspace 8 -bindcode $mod+18 workspace 9 -bindcode $mod+19 workspace 10 +bindcode $mod+10 workspace $ws1 +bindcode $mod+11 workspace $ws2 +bindcode $mod+12 workspace $ws3 +bindcode $mod+13 workspace $ws4 +bindcode $mod+14 workspace $ws5 +bindcode $mod+15 workspace $ws6 +bindcode $mod+16 workspace $ws7 +bindcode $mod+17 workspace $ws8 +bindcode $mod+18 workspace $ws9 +bindcode $mod+19 workspace $ws10 # move focused container to workspace -bindcode $mod+Shift+10 move container to workspace 1 -bindcode $mod+Shift+11 move container to workspace 2 -bindcode $mod+Shift+12 move container to workspace 3 -bindcode $mod+Shift+13 move container to workspace 4 -bindcode $mod+Shift+14 move container to workspace 5 -bindcode $mod+Shift+15 move container to workspace 6 -bindcode $mod+Shift+16 move container to workspace 7 -bindcode $mod+Shift+17 move container to workspace 8 -bindcode $mod+Shift+18 move container to workspace 9 -bindcode $mod+Shift+19 move container to workspace 10 +bindcode $mod+Shift+10 move container to workspace $ws1 +bindcode $mod+Shift+11 move container to workspace $ws2 +bindcode $mod+Shift+12 move container to workspace $ws3 +bindcode $mod+Shift+13 move container to workspace $ws4 +bindcode $mod+Shift+14 move container to workspace $ws5 +bindcode $mod+Shift+15 move container to workspace $ws6 +bindcode $mod+Shift+16 move container to workspace $ws7 +bindcode $mod+Shift+17 move container to workspace $ws8 +bindcode $mod+Shift+18 move container to workspace $ws9 +bindcode $mod+Shift+19 move container to workspace $ws10 # reload the configuration file bindcode $mod+Shift+54 reload @@ -141,7 +154,7 @@ mode "resize" { bindcode 111 resize shrink height 10 px or 10 ppt bindcode 114 resize grow width 10 px or 10 ppt - # back to normal: Enter or Escape + # back to normal: Enter or Escape or $mod+r bindcode 36 mode "default" bindcode 9 mode "default" bindcode $mod+27 mode "default" diff --git a/include/commands.h b/include/commands.h index 85d5fe78..1057f021 100644 --- a/include/commands.h +++ b/include/commands.h @@ -63,7 +63,7 @@ void cmd_move_con_to_workspace_name(I3_CMD, const char *name, const char *no_aut void cmd_move_con_to_workspace_number(I3_CMD, const char *which, const char *no_auto_back_and_forth); /** - * Implementation of 'resize set [px] [px]'. + * Implementation of 'resize set [px | ppt] [px | ppt]'. * */ void cmd_resize_set(I3_CMD, long cwidth, const char *mode_width, long cheight, const char *mode_height); diff --git a/include/resize.h b/include/resize.h index 7b33de90..38634156 100644 --- a/include/resize.h +++ b/include/resize.h @@ -11,6 +11,6 @@ #include -bool resize_find_tiling_participants(Con **current, Con **other, direction_t direction); +bool resize_find_tiling_participants(Con **current, Con **other, direction_t direction, bool both_sides); int resize_graphical_handler(Con *first, Con *second, orientation_t orientation, const xcb_button_press_event_t *event); diff --git a/src/click.c b/src/click.c index 5b529a38..b036c5f8 100644 --- a/src/click.c +++ b/src/click.c @@ -49,7 +49,7 @@ static bool tiling_resize_for_border(Con *con, border_t border, xcb_button_press break; } - bool res = resize_find_tiling_participants(&first, &second, search_direction); + bool res = resize_find_tiling_participants(&first, &second, search_direction, false); if (!res) { LOG("No second container in this direction found.\n"); return false; diff --git a/src/commands.c b/src/commands.c index df2b236b..afb624be 100644 --- a/src/commands.c +++ b/src/commands.c @@ -511,7 +511,7 @@ static bool cmd_resize_tiling_direction(I3_CMD, Con *current, const char *way, c else search_direction = D_DOWN; - bool res = resize_find_tiling_participants(&first, &second, search_direction); + bool res = resize_find_tiling_participants(&first, &second, search_direction, false); if (!res) { LOG("No second container in this direction found.\n"); ysuccess(false); @@ -552,19 +552,15 @@ static bool cmd_resize_tiling_direction(I3_CMD, Con *current, const char *way, c static bool cmd_resize_tiling_width_height(I3_CMD, Con *current, const char *way, const char *direction, int ppt) { LOG("width/height resize\n"); - /* get the appropriate current container (skip stacked/tabbed cons) */ - while (current->parent->layout == L_STACKED || - current->parent->layout == L_TABBED) - current = current->parent; - - /* Then further go up until we find one with the matching orientation. */ - orientation_t search_orientation = - (strcmp(direction, "width") == 0 ? HORIZ : VERT); - while (current->type != CT_WORKSPACE && - current->type != CT_FLOATING_CON && - (con_orientation(current->parent) != search_orientation || con_num_children(current->parent) == 1)) - current = current->parent; + /* get the appropriate current container (skip stacked/tabbed cons) */ + Con *dummy = NULL; + direction_t search_direction = (strcmp(direction, "width") == 0 ? D_LEFT : D_DOWN); + bool search_result = resize_find_tiling_participants(¤t, &dummy, search_direction, true); + if (search_result == false) { + ysuccess(false); + return false; + } /* get the default percentage */ int children = con_num_children(current->parent); @@ -572,24 +568,6 @@ static bool cmd_resize_tiling_width_height(I3_CMD, Con *current, const char *way double percentage = 1.0 / children; LOG("default percentage = %f\n", percentage); - orientation_t orientation = con_orientation(current->parent); - - if ((orientation == HORIZ && - strcmp(direction, "height") == 0) || - (orientation == VERT && - strcmp(direction, "width") == 0)) { - LOG("You cannot resize in that direction. Your focus is in a %s split container currently.\n", - (orientation == HORIZ ? "horizontal" : "vertical")); - ysuccess(false); - return false; - } - - if (children == 1) { - LOG("This is the only container, cannot resize.\n"); - ysuccess(false); - return false; - } - /* Ensure all the other children have a percentage set. */ Con *child; TAILQ_FOREACH(child, &(current->parent->nodes_head), nodes) { @@ -681,7 +659,7 @@ void cmd_resize(I3_CMD, const char *way, const char *direction, long resize_px, */ void cmd_resize_set(I3_CMD, long cwidth, const char *mode_width, long cheight, const char *mode_height) { DLOG("resizing to %ld %s x %ld %s\n", cwidth, mode_width, cheight, mode_height); - if (cwidth <= 0 || cheight <= 0) { + if (cwidth < 0 || cheight < 0) { ELOG("Resize failed: dimensions cannot be negative (was %ld %s x %ld %s)\n", cwidth, mode_width, cheight, mode_height); return; } @@ -689,25 +667,84 @@ void cmd_resize_set(I3_CMD, long cwidth, const char *mode_width, long cheight, c HANDLE_EMPTY_MATCH; owindow *current; + bool success = true; TAILQ_FOREACH(current, &owindows, owindows) { Con *floating_con; if ((floating_con = con_inside_floating(current->con))) { Con *output = con_get_output(floating_con); - if (mode_width && strcmp(mode_width, "ppt") == 0) { + if (cwidth == 0) { + cwidth = output->rect.width; + } else if (mode_width && strcmp(mode_width, "ppt") == 0) { cwidth = output->rect.width * ((double)cwidth / 100.0); } - if (mode_height && strcmp(mode_height, "ppt") == 0) { + if (cheight == 0) { + cheight = output->rect.height; + } else if (mode_height && strcmp(mode_height, "ppt") == 0) { cheight = output->rect.height * ((double)cheight / 100.0); } floating_resize(floating_con, cwidth, cheight); } else { - ELOG("Resize failed: %p not a floating container\n", current->con); + if (current->con->window && current->con->window->dock) { + DLOG("This is a dock window. Not resizing (con = %p)\n)", current->con); + continue; + } + + if (cwidth > 0 && mode_width && strcmp(mode_width, "ppt") == 0) { + /* get the appropriate current container (skip stacked/tabbed cons) */ + Con *target = current->con; + Con *dummy; + resize_find_tiling_participants(&target, &dummy, D_LEFT, true); + + /* Calculate new size for the target container */ + double current_percent = target->percent; + char *action_string; + long adjustment; + + if (current_percent > cwidth) { + action_string = "shrink"; + adjustment = (int)(current_percent * 100) - cwidth; + } else { + action_string = "grow"; + adjustment = cwidth - (int)(current_percent * 100); + } + + /* perform resizing and report failure if not possible */ + if (!cmd_resize_tiling_width_height(current_match, cmd_output, + target, action_string, "width", adjustment)) { + success = false; + } + } + + if (cheight > 0 && mode_width && strcmp(mode_width, "ppt") == 0) { + /* get the appropriate current container (skip stacked/tabbed cons) */ + Con *target = current->con; + Con *dummy; + resize_find_tiling_participants(&target, &dummy, D_DOWN, true); + + /* Calculate new size for the target container */ + double current_percent = target->percent; + char *action_string; + long adjustment; + + if (current_percent > cheight) { + action_string = "shrink"; + adjustment = (int)(current_percent * 100) - cheight; + } else { + action_string = "grow"; + adjustment = cheight - (int)(current_percent * 100); + } + + /* perform resizing and report failure if not possible */ + if (!cmd_resize_tiling_width_height(current_match, cmd_output, + target, action_string, "height", adjustment)) { + success = false; + } + } } } cmd_output->needs_tree_render = true; - // XXX: default reply for now, make this a better reply - ysuccess(true); + ysuccess(success); } /* @@ -767,6 +804,7 @@ void cmd_nop(I3_CMD, const char *comment) { LOG("-------------------------------------------------\n"); LOG(" NOP: %s\n", comment); LOG("-------------------------------------------------\n"); + ysuccess(true); } /* diff --git a/src/resize.c b/src/resize.c index f07fcec6..ee50bfbc 100644 --- a/src/resize.c +++ b/src/resize.c @@ -47,7 +47,7 @@ DRAGGING_CB(resize_callback) { xcb_flush(conn); } -bool resize_find_tiling_participants(Con **current, Con **other, direction_t direction) { +bool resize_find_tiling_participants(Con **current, Con **other, direction_t direction, bool both_sides) { DLOG("Find two participants for resizing container=%p in direction=%i\n", other, direction); Con *first = *current; Con *second = NULL; @@ -74,8 +74,14 @@ bool resize_find_tiling_participants(Con **current, Con **other, direction_t dir /* get the counterpart for this resizement */ if (dir_backwards) { second = TAILQ_PREV(first, nodes_head, nodes); + if (second == NULL && both_sides == true) { + second = TAILQ_NEXT(first, nodes); + } } else { second = TAILQ_NEXT(first, nodes); + if (second == NULL && both_sides == true) { + second = TAILQ_PREV(first, nodes_head, nodes); + } } if (second == NULL) { diff --git a/testcases/t/541-resize-set-tiling.t b/testcases/t/541-resize-set-tiling.t new file mode 100644 index 00000000..82267baf --- /dev/null +++ b/testcases/t/541-resize-set-tiling.t @@ -0,0 +1,147 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Please read the following documents before working on tests: +# • https://build.i3wm.org/docs/testsuite.html +# (or docs/testsuite) +# +# • https://build.i3wm.org/docs/lib-i3test.html +# (alternatively: perldoc ./testcases/lib/i3test.pm) +# +# • https://build.i3wm.org/docs/ipc.html +# (or docs/ipc) +# +# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf +# (unless you are already familiar with Perl) +# +# Tests resizing tiling containers +use i3test; + +############################################################ +# resize horizontally +############################################################ + +my $tmp = fresh_workspace; + +cmd 'split h'; + +my $left = open_window; +my $right = open_window; + +diag("left = " . $left->id . ", right = " . $right->id); + +is($x->input_focus, $right->id, 'Right window focused'); + +cmd 'resize set 75 ppt 0 ppt'; + +my ($nodes, $focus) = get_ws_content($tmp); + +cmp_float($nodes->[0]->{percent}, 0.25, 'left window got only 25%'); +cmp_float($nodes->[1]->{percent}, 0.75, 'right window got 75%'); + +############################################################ +# resize vertically +############################################################ + +my $tmp = fresh_workspace; + +cmd 'split v'; + +my $top = open_window; +my $bottom = open_window; + +diag("top = " . $top->id . ", bottom = " . $bottom->id); + +is($x->input_focus, $bottom->id, 'Bottom window focused'); + +cmd 'resize set 0 ppt 75 ppt'; + +my ($nodes, $focus) = get_ws_content($tmp); + +cmp_float($nodes->[0]->{percent}, 0.25, 'top window got only 25%'); +cmp_float($nodes->[1]->{percent}, 0.75, 'bottom window got 75%'); + + +############################################################ +# resize horizontally and vertically +############################################################ + +my $tmp = fresh_workspace; + +cmd 'split h'; +my $left = open_window; +my $top_right = open_window; +cmd 'split v'; +my $bottom_right = open_window; + +diag("left = " . $left->id . ", top-right = " . $top_right->id . ", bottom-right = " . $bottom_right->id); + +is($x->input_focus, $bottom_right->id, 'Bottom-right window focused'); + +cmd 'resize set 75 ppt 75 ppt'; + +my ($nodes, $focus) = get_ws_content($tmp); + +cmp_float($nodes->[0]->{percent}, 0.25, 'left container got 25%'); +cmp_float($nodes->[1]->{percent}, 0.75, 'right container got 75%'); +cmp_float($nodes->[1]->{nodes}->[0]->{percent}, 0.25, 'top-right window got 25%'); +cmp_float($nodes->[1]->{nodes}->[1]->{percent}, 0.75, 'bottom-right window got 75%'); + + +############################################################ +# resize from inside a tabbed container +############################################################ + +my $tmp = fresh_workspace; + +cmd 'split h'; + +my $left = open_window; +my $right1 = open_window; + +cmd 'split h'; +cmd 'layout tabbed'; + +my $right2 = open_window; + +diag("left = " . $left->id . ", right1 = " . $right1->id . ", right2 = " . $right2->id); + +is($x->input_focus, $right2->id, '2nd right window focused'); + +cmd 'resize set 75 ppt 0 ppt'; + +my ($nodes, $focus) = get_ws_content($tmp); + +cmp_float($nodes->[0]->{percent}, 0.25, 'left container got 25%'); +cmp_float($nodes->[1]->{percent}, 0.75, 'right container got 75%'); + + +############################################################ +# resize from inside a stacked container +############################################################ + +my $tmp = fresh_workspace; + +cmd 'split h'; + +my $left = open_window; +my $right1 = open_window; + +cmd 'split h'; +cmd 'layout stacked'; + +my $right2 = open_window; + +diag("left = " . $left->id . ", right1 = " . $right1->id . ", right2 = " . $right2->id); + +is($x->input_focus, $right2->id, '2nd right window focused'); + +cmd 'resize set 75 ppt 0 ppt'; + +my ($nodes, $focus) = get_ws_content($tmp); + +cmp_float($nodes->[0]->{percent}, 0.25, 'left container got 25%'); +cmp_float($nodes->[1]->{percent}, 0.75, 'right container got 75%'); + + +done_testing;