Support "resize set W H"

This commit is contained in:
rr- 2015-09-05 08:31:45 +02:00
parent ee2983c791
commit 23d16e1332
8 changed files with 178 additions and 1 deletions

View File

@ -2007,6 +2007,7 @@ If you want to resize containers/windows using your keyboard, you can use the
*Syntax*:
-------------------------------------------------------
resize grow|shrink <direction> [<px> px [or <ppt> ppt]]
resize set <width> [px] <height> [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

View File

@ -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] <px> [px]'.
*
*/
void cmd_size(I3_CMD, char *cwidth, char *cheight);
/**
* Implementation of 'resize grow|shrink <direction> [<px> px] [or <ppt> ppt]'.
*

View File

@ -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 outputs rect changes).

View File

@ -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 <name> to <name>
# rename workspace to <name>
state RENAME:

View File

@ -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] <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 [<n>]', 'border none|1pixel|toggle'.
*

View File

@ -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 outputs rect changes).

View File

@ -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 = <<EOT;
# i3 config file (v4)
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
# Test with different dimensions than the i3 default.
floating_minimum_size 80 x 70
floating_maximum_size 100 x 90
EOT
$pid = launch_with_config($config);
my $window = open_floating_window(rect => [ 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;

View File

@ -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 <width> <height>" 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;