From: Ingo Bürk Date: Mon, 13 Nov 2017 21:01:06 +0000 (+0100) Subject: Merge pull request #3040 from jchook/next X-Git-Tag: 4.15~42 X-Git-Url: https://git.sur5r.net/?p=i3%2Fi3;a=commitdiff_plain;h=a78c9ab82f6eb3a62cf863fa14a6d652ef08ecfc;hp=0afe714e2b43e95db8b377c62966916ebf242217 Merge pull request #3040 from jchook/next $mod+r toggles resize mode --- diff --git a/docs/userguide b/docs/userguide index 54ac9c8d..4fec6cda 100644 --- a/docs/userguide +++ b/docs/userguide @@ -2302,7 +2302,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] +resize set [px | ppt] [px | ppt] ------------------------------------------------------- Direction can either be one of +up+, +down+, +left+ or +right+. Or you can be diff --git a/etc/config b/etc/config index f6fd5e7b..5b751d00 100644 --- a/etc/config +++ b/etc/config @@ -22,7 +22,7 @@ font pango:monospace 8 # The font above is very space-efficient, that is, it looks good, sharp and # clear in small sizes. However, its unicode glyph coverage is limited, the old # X core fonts rendering does not support right-to-left and this being a bitmap -# font, it doesn’t scale on retina/hidpi displays. +# font, it doesn't scale on retina/hidpi displays. # use these keys for focus, movement, and resize directions when reaching for # the arrows is not convenient diff --git a/i3-sensible-terminal b/i3-sensible-terminal index f92ff224..23cb5688 100755 --- a/i3-sensible-terminal +++ b/i3-sensible-terminal @@ -8,7 +8,7 @@ # We welcome patches that add distribution-specific mechanisms to find the # preferred terminal emulator. On Debian, there is the x-terminal-emulator # symlink for example. -for terminal in "$TERMINAL" x-terminal-emulator urxvt rxvt termit terminator Eterm aterm uxterm xterm gnome-terminal roxterm xfce4-terminal termite lxterminal mate-terminal terminology st qterminal lilyterm tilix terminix konsole; do +for terminal in "$TERMINAL" x-terminal-emulator urxvt rxvt termit terminator Eterm aterm uxterm xterm gnome-terminal roxterm xfce4-terminal termite lxterminal mate-terminal terminology st qterminal lilyterm tilix terminix konsole kitty; do if command -v "$terminal" > /dev/null 2>&1; then exec "$terminal" "$@" fi diff --git a/include/commands.h b/include/commands.h index 9780f788..85d5fe78 100644 --- a/include/commands.h +++ b/include/commands.h @@ -66,7 +66,7 @@ void cmd_move_con_to_workspace_number(I3_CMD, const char *which, const char *no_ * Implementation of 'resize set [px] [px]'. * */ -void cmd_resize_set(I3_CMD, long cwidth, long cheight); +void cmd_resize_set(I3_CMD, long cwidth, const char *mode_width, long cheight, const char *mode_height); /** * Implementation of 'resize grow|shrink [ px] [or ppt]'. diff --git a/libi3/ipc_recv_message.c b/libi3/ipc_recv_message.c index 16dda90d..84da5aa3 100644 --- a/libi3/ipc_recv_message.c +++ b/libi3/ipc_recv_message.c @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -41,14 +42,21 @@ int ipc_recv_message(int sockfd, uint32_t *message_type, if (n == -1) return -1; if (n == 0) { - return -2; + if (read_bytes == 0) { + return -2; + } else { + ELOG("IPC: unexpected EOF while reading header, got %" PRIu32 " bytes, want %" PRIu32 " bytes\n", + read_bytes, to_read); + return -3; + } } read_bytes += n; } if (memcmp(walk, I3_IPC_MAGIC, strlen(I3_IPC_MAGIC)) != 0) { - ELOG("IPC: invalid magic in reply\n"); + ELOG("IPC: invalid magic in header, got \"%.*s\", want \"%s\"\n", + (int)strlen(I3_IPC_MAGIC), walk, I3_IPC_MAGIC); return -3; } @@ -61,13 +69,18 @@ int ipc_recv_message(int sockfd, uint32_t *message_type, *reply = smalloc(*reply_length); read_bytes = 0; - int n; while (read_bytes < *reply_length) { - if ((n = read(sockfd, *reply + read_bytes, *reply_length - read_bytes)) == -1) { + const int n = read(sockfd, *reply + read_bytes, *reply_length - read_bytes); + if (n == -1) { if (errno == EINTR || errno == EAGAIN) continue; return -1; } + if (n == 0) { + ELOG("IPC: unexpected EOF while reading payload, got %" PRIu32 " bytes, want %" PRIu32 " bytes\n", + read_bytes, *reply_length); + return -3; + } read_bytes += n; } diff --git a/man/i3-sensible-terminal.man b/man/i3-sensible-terminal.man index 20a6810c..bccc824a 100644 --- a/man/i3-sensible-terminal.man +++ b/man/i3-sensible-terminal.man @@ -44,6 +44,7 @@ It tries to start one of the following (in that order): * tilix * terminix * konsole +* kitty Please don’t complain about the order: If the user has any preference, they will have $TERMINAL set or modified their i3 configuration file. diff --git a/parser-specs/commands.spec b/parser-specs/commands.spec index a5873328..0289fa1a 100644 --- a/parser-specs/commands.spec +++ b/parser-specs/commands.spec @@ -258,14 +258,16 @@ state RESIZE_SET: -> RESIZE_WIDTH state RESIZE_WIDTH: - 'px' + mode_width = 'px', 'ppt' -> height = number -> RESIZE_HEIGHT state RESIZE_HEIGHT: - 'px', end - -> call cmd_resize_set(&width, &height) + mode_height = 'px', 'ppt' + -> + end + -> call cmd_resize_set(&width, $mode_width, &height, $mode_height) # rename workspace to # rename workspace to diff --git a/src/commands.c b/src/commands.c index d7cdf219..e68fcd80 100644 --- a/src/commands.c +++ b/src/commands.c @@ -676,13 +676,13 @@ void cmd_resize(I3_CMD, const char *way, const char *direction, long resize_px, } /* - * Implementation of 'resize set [px] [px]'. + * Implementation of 'resize set [px | ppt] [px | ppt]'. * */ -void cmd_resize_set(I3_CMD, long cwidth, long cheight) { - DLOG("resizing to %ldx%ld px\n", cwidth, cheight); +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) { - ELOG("Resize failed: dimensions cannot be negative (was %ldx%ld)\n", cwidth, cheight); + ELOG("Resize failed: dimensions cannot be negative (was %ld %s x %ld %s)\n", cwidth, mode_width, cheight, mode_height); return; } @@ -692,6 +692,13 @@ void cmd_resize_set(I3_CMD, long cwidth, long cheight) { 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) { + cwidth = output->rect.width * ((double)cwidth / 100.0); + } + 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); diff --git a/src/tree.c b/src/tree.c index a6cc59fb..710bb655 100644 --- a/src/tree.c +++ b/src/tree.c @@ -560,21 +560,10 @@ static bool _tree_next(Con *con, char way, orientation_t orientation, bool wrap) if (!workspace) return false; - workspace_show(workspace); - - /* If a workspace has an active fullscreen container, one of its - * children should always be focused. The above workspace_show() - * should be adequate for that, so return. */ - if (con_get_fullscreen_con(workspace, CF_OUTPUT)) - return true; - - Con *focus = con_descend_direction(workspace, direction); - - /* special case: if there was no tiling con to focus and the workspace - * has a floating con in the focus stack, focus the top of the focus - * stack (which may be floating) */ - if (focus == workspace) + Con *focus = con_descend_tiling_focused(workspace); + if (focus == workspace) { focus = con_descend_focused(workspace); + } if (focus) { con_focus(focus); diff --git a/testcases/t/252-floating-size.t b/testcases/t/252-floating-size.t index 8d8d4120..ac0c48d0 100644 --- a/testcases/t/252-floating-size.t +++ b/testcases/t/252-floating-size.t @@ -17,7 +17,13 @@ # Test behavior of "resize " command. # Ticket: #1727 # Bug still in: 4.10.2-1-gc0dbc5d -use i3test; +use i3test i3_config => <{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'); +################################################################################ +# Same but with ppt instead of px +################################################################################ + +kill_all_windows; +$tmp = 'ws'; +cmd "workspace $tmp"; +open_floating_window; + +@content = @{get_ws($tmp)->{floating_nodes}}; +is(@content, 1, 'one floating node on this ws'); + +$oldrect = $content[0]->{rect}; + +cmd 'resize set 33 ppt 20 ppt'; +my $expected_width = int(0.33 * 1333); +my $expected_height = int(0.2 * 999); + +@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}, '==', $expected_width, "width changed to $expected_width px"); +cmp_ok($content[0]->{rect}->{height}, '==', $expected_height, "height changed to $expected_height px"); + +################################################################################ +# Mix ppt and px in a single resize set command +################################################################################ + +cmd 'resize set 44 ppt 111 px'; +my $expected_width = int(0.44 * 1333); +my $expected_height = 111; + +@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}, '==', $expected_width, "width changed to $expected_width px"); +cmp_ok($content[0]->{rect}->{height}, '==', $expected_height, "height changed to $expected_height px"); + +cmd 'resize set 222 px 100 ppt'; +my $expected_width = 222; +my $expected_height = 999; + +@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}, '==', $expected_width, "width changed to $expected_width px"); +cmp_ok($content[0]->{rect}->{height}, '==', $expected_height, "height changed to $expected_height px"); + done_testing; diff --git a/testcases/t/510-focus-across-outputs.t b/testcases/t/510-focus-across-outputs.t index 21169adb..07a2115c 100644 --- a/testcases/t/510-focus-across-outputs.t +++ b/testcases/t/510-focus-across-outputs.t @@ -92,7 +92,7 @@ reset_focus $s3_ws; cmd "workspace $s2_ws"; cmd 'focus right'; -is($x->input_focus, $sixth->id, 'sixth window focused'); +is($x->input_focus, $seventh->id, 'seventh window focused'); reset_focus $s3_ws; cmd "workspace $s2_ws"; @@ -110,6 +110,8 @@ is($x->input_focus, $third->id, 'third window focused'); cmd 'focus parent'; cmd 'focus parent'; cmd 'split v'; +# Focus second or else $first gets to the top of the focus stack. +cmd '[id=' . $second->id . '] focus'; reset_focus $s0_ws; cmd "workspace $s3_ws"; @@ -137,4 +139,96 @@ cmd "workspace $s2_ws"; cmd 'focus up'; is($x->input_focus, $second->id, 'second window focused'); +################################################################### +# Test that focus (left|down|right|up), when focusing across +# outputs, doesn't focus the next window in the given direction but +# the most focused window of the container in the given direction. +# In the following layout: +# [ WS1*[ ] WS2[ H[ A B* ] ] ] +# (where the asterisk denotes the focused container within its +# parent) moving right from WS1 should focus B which is focused +# inside WS2, not A which is the next window on the right of WS1. +# See issue #1160. +################################################################### + +kill_all_windows; + +sync_with_i3; +$x->root->warp_pointer(1025, 0); # Second screen. +sync_with_i3; +$s1_ws = fresh_workspace; +$first = open_window; +$second = open_window; + +sync_with_i3; +$x->root->warp_pointer(0, 0); # First screen. +sync_with_i3; +$s0_ws = fresh_workspace; +open_window; +$third = open_window; + +cmd 'focus right'; +is($x->input_focus, $second->id, 'second window (rightmost) focused'); +cmd 'focus left'; +is($x->input_focus, $first->id, 'first window focused'); +cmd 'focus left'; +is($x->input_focus, $third->id, 'third window focused'); + + +################################################################### +# Similar but with a tabbed layout. +################################################################### + +cmd 'layout tabbed'; +$fourth = open_window; +cmd 'focus left'; +is($x->input_focus, $third->id, 'third window (tabbed) focused'); +cmd "workspace $s1_ws"; +cmd 'focus left'; +is($x->input_focus, $third->id, 'third window (tabbed) focused'); + + +################################################################### +# Similar but with a stacked layout on the bottom screen. +################################################################### + +sync_with_i3; +$x->root->warp_pointer(0, 769); # Third screen. +sync_with_i3; +$s2_ws = fresh_workspace; +cmd 'layout stacked'; +$fifth = open_window; +$sixth = open_window; + +cmd "workspace $s0_ws"; +cmd 'focus down'; +is($x->input_focus, $sixth->id, 'sixth window (stacked) focused'); + +################################################################### +# Similar but with a more complex layout. +################################################################### + +sync_with_i3; +$x->root->warp_pointer(1025, 769); # Fourth screen. +sync_with_i3; +$s3_ws = fresh_workspace; +open_window; +open_window; +cmd 'split v'; +open_window; +open_window; +cmd 'split h'; +my $nested = open_window; +open_window; +cmd 'focus left'; +is($x->input_focus, $nested->id, 'nested window focused'); + +cmd "workspace $s1_ws"; +cmd 'focus down'; +is($x->input_focus, $nested->id, 'nested window focused from workspace above'); + +cmd "workspace $s2_ws"; +cmd 'focus right'; +is($x->input_focus, $nested->id, 'nested window focused from workspace on the left'); + done_testing;