diff --git a/docs/userguide b/docs/userguide index 62010587..5e148ff5 100644 --- a/docs/userguide +++ b/docs/userguide @@ -2007,6 +2007,7 @@ If you want to resize containers/windows using your keyboard, you can use the *Syntax*: ------------------------------------------------------- resize grow|shrink [ px [or ppt]] +resize set [px] [px] ------------------------------------------------------- Direction can either be one of +up+, +down+, +left+ or +right+. Or you can be @@ -2015,7 +2016,8 @@ 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). +default is 10 percentage points). Note that +resize set+ will only work for +floating containers. I recommend using the resize command inside a so called +mode+: @@ -2048,6 +2050,11 @@ mode "resize" { bindsym $mod+r mode "resize" ---------------------------------------------------------------------- +*Example 2 - setting urxvt size to 640x480:* +------------------------------------------------ +for_window [class="urxvt"] resize set 640 480 +------------------------------------------------ + === Jumping to specific windows Often when in a multi-monitor environment, you want to quickly jump to a diff --git a/include/commands.h b/include/commands.h index 6d1046d4..b243b9e0 100644 --- a/include/commands.h +++ b/include/commands.h @@ -60,6 +60,12 @@ void cmd_move_con_to_workspace_name(I3_CMD, char *name); */ void cmd_move_con_to_workspace_number(I3_CMD, char *which); +/** + * Implementation of 'resize set [px] [px]'. + * + */ +void cmd_size(I3_CMD, char *cwidth, char *cheight); + /** * Implementation of 'resize grow|shrink [ px] [or ppt]'. * diff --git a/include/floating.h b/include/floating.h index 78e75be8..466c0e79 100644 --- a/include/floating.h +++ b/include/floating.h @@ -188,6 +188,15 @@ drag_result_t drag_pointer(Con *con, const xcb_button_press_event_t *event, */ void floating_reposition(Con *con, Rect newrect); +/** + * Sets size of the CT_FLOATING_CON to specified dimensions. Might limit the + * actual size with regard to size constraints taken from user settings. + * Additionally, the dimensions may be upscaled until they're divisible by the + * window's size hints. + * + */ +void floating_resize(Con *floating_con, int x, int y); + /** * Fixes the coordinates of the floating window whenever the window gets * reassigned to a different output (or when the output’s rect changes). diff --git a/parser-specs/commands.spec b/parser-specs/commands.spec index 94dc630a..f5fb9884 100644 --- a/parser-specs/commands.spec +++ b/parser-specs/commands.spec @@ -211,6 +211,8 @@ state UNMARK: state RESIZE: way = 'grow', 'shrink' -> RESIZE_DIRECTION + set = 'set' + -> RESIZE_SET state RESIZE_DIRECTION: direction = 'up', 'down', 'left', 'right', 'width', 'height' @@ -238,6 +240,20 @@ state RESIZE_TILING_FINAL: 'ppt', end -> call cmd_resize($way, $direction, $resize_px, $resize_ppt) +state RESIZE_SET: + width = word + -> RESIZE_WIDTH + +state RESIZE_WIDTH: + 'px' + -> + height = word + -> RESIZE_HEIGHT + +state RESIZE_HEIGHT: + 'px', end + -> call cmd_size($width, $height) + # rename workspace to # rename workspace to state RENAME: diff --git a/src/commands.c b/src/commands.c index d0888c0f..443edf4a 100644 --- a/src/commands.c +++ b/src/commands.c @@ -823,6 +823,37 @@ void cmd_resize(I3_CMD, char *way, char *direction, char *resize_px, char *resiz ysuccess(true); } +/* + * Implementation of 'resize set [px] [px]'. + * + */ +void cmd_size(I3_CMD, char *cwidth, char *cheight) { + DLOG("resizing to %sx%s px\n", cwidth, cheight); + // TODO: We could either handle this in the parser itself as a separate token (and make the stack typed) or we need a better way to convert a string to a number with error checking + int x = atoi(cwidth); + int y = atoi(cheight); + if (x <= 0 || y <= 0) { + ELOG("Resize failed: dimensions cannot be negative (was %sx%s)\n", cwidth, cheight); + return; + } + + HANDLE_EMPTY_MATCH; + + owindow *current; + TAILQ_FOREACH(current, &owindows, owindows) { + Con *floating_con; + if ((floating_con = con_inside_floating(current->con))) { + floating_resize(floating_con, x, y); + } else { + ELOG("Resize failed: %p not a floating container\n", current->con); + } + } + + cmd_output->needs_tree_render = true; + // XXX: default reply for now, make this a better reply + ysuccess(true); +} + /* * Implementation of 'border normal|pixel []', 'border none|1pixel|toggle'. * diff --git a/src/floating.c b/src/floating.c index eef02ac6..0a510f67 100644 --- a/src/floating.c +++ b/src/floating.c @@ -825,6 +825,37 @@ void floating_reposition(Con *con, Rect newrect) { tree_render(); } +/* + * Sets size of the CT_FLOATING_CON to specified dimensions. Might limit the + * actual size with regard to size constraints taken from user settings. + * Additionally, the dimensions may be upscaled until they're divisible by the + * window's size hints. + * + */ +void floating_resize(Con *floating_con, int x, int y) { + DLOG("floating resize to %dx%d px\n", x, y); + Rect *rect = &floating_con->rect; + Con *focused_con = con_descend_focused(floating_con); + if (focused_con->window == NULL) { + DLOG("No window is focused. Not resizing.\n"); + return; + } + int wi = focused_con->window->width_increment; + int hi = focused_con->window->height_increment; + rect->width = x; + rect->height = y; + if (wi) + rect->width += (wi - 1 - rect->width) % wi; + if (hi) + rect->height += (hi - 1 - rect->height) % hi; + + floating_check_size(floating_con); + + /* If this is a scratchpad window, don't auto center it from now on. */ + if (floating_con->scratchpad_state == SCRATCHPAD_FRESH) + floating_con->scratchpad_state = SCRATCHPAD_CHANGED; +} + /* * Fixes the coordinates of the floating window whenever the window gets * reassigned to a different output (or when the output’s rect changes). diff --git a/testcases/t/189-floating-constraints.t b/testcases/t/189-floating-constraints.t index debbb0a2..ad356f42 100644 --- a/testcases/t/189-floating-constraints.t +++ b/testcases/t/189-floating-constraints.t @@ -186,4 +186,36 @@ is($rect->{y}, $old_y, 'window did not move when trying to resize'); exit_gracefully($pid); +################################################################################ +# 7: check floating_maximum_size with cmd_size +################################################################################ + +my $config = < [ 0, 0, 90, 80 ]); +cmd 'border none'; + +cmd 'resize set 101 91'; +sync_with_i3; +my $rect = $window->rect; +is($rect->{width}, 100, 'width did not exceed maximum width'); +is($rect->{height}, 90, 'height did not exceed maximum height'); + +cmd 'resize set 79 69'; +sync_with_i3; +$rect = $window->rect; +is($rect->{width}, 80, 'width did not exceed minimum width'); +is($rect->{height}, 70, 'height did not exceed minimum height'); + +exit_gracefully($pid); + done_testing; diff --git a/testcases/t/252-floating-size.t b/testcases/t/252-floating-size.t new file mode 100644 index 00000000..ef4861a6 --- /dev/null +++ b/testcases/t/252-floating-size.t @@ -0,0 +1,45 @@ +#!perl +# vim:ts=4:sw=4:expandtab +# +# Please read the following documents before working on tests: +# • http://build.i3wm.org/docs/testsuite.html +# (or docs/testsuite) +# +# • http://build.i3wm.org/docs/lib-i3test.html +# (alternatively: perldoc ./testcases/lib/i3test.pm) +# +# • http://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) +# +# Test behavior of "resize " command. +# Ticket: #1727 +# Bug still in: 4.10.2-1-gc0dbc5d +use i3test; + +################################################################################ +# Check that setting floating windows size works +################################################################################ + +my $tmp = fresh_workspace; + +open_floating_window; + +my @content = @{get_ws($tmp)->{floating_nodes}}; +is(@content, 1, 'one floating node on this ws'); + +my $oldrect = $content[0]->{rect}; + +cmd 'resize set 100 px 250 px'; + +@content = @{get_ws($tmp)->{floating_nodes}}; +cmp_ok($content[0]->{rect}->{x}, '==', $oldrect->{x}, 'x untouched'); +cmp_ok($content[0]->{rect}->{y}, '==', $oldrect->{y}, 'y untouched'); +cmp_ok($content[0]->{rect}->{width}, '!=', $oldrect->{width}, 'width changed'); +cmp_ok($content[0]->{rect}->{height}, '!=', $oldrect->{width}, 'height changed'); +cmp_ok($content[0]->{rect}->{width}, '==', 100, 'width changed to 100 px'); +cmp_ok($content[0]->{rect}->{height}, '==', 250, 'height changed to 250 px'); + +done_testing;