Merge pull request #2902 from orestisf1993/swap-for-fullscreen
Make swap work with fullscreen windows
This commit is contained in:
commit
9a9ade88ef
|
@ -57,6 +57,13 @@
|
||||||
|
|
||||||
#define CALL(obj, member, ...) obj->member(obj, ##__VA_ARGS__)
|
#define CALL(obj, member, ...) obj->member(obj, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#define SWAP(first, second, type) \
|
||||||
|
do { \
|
||||||
|
type tmp_SWAP = first; \
|
||||||
|
first = second; \
|
||||||
|
second = tmp_SWAP; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
int min(int a, int b);
|
int min(int a, int b);
|
||||||
int max(int a, int b);
|
int max(int a, int b);
|
||||||
bool rect_contains(Rect rect, uint32_t x, uint32_t y);
|
bool rect_contains(Rect rect, uint32_t x, uint32_t y);
|
||||||
|
|
23
src/con.c
23
src/con.c
|
@ -2276,15 +2276,14 @@ bool con_swap(Con *first, Con *second) {
|
||||||
Con *current_ws = con_get_workspace(old_focus);
|
Con *current_ws = con_get_workspace(old_focus);
|
||||||
const bool focused_within_first = (first == old_focus || con_has_parent(old_focus, first));
|
const bool focused_within_first = (first == old_focus || con_has_parent(old_focus, first));
|
||||||
const bool focused_within_second = (second == old_focus || con_has_parent(old_focus, second));
|
const bool focused_within_second = (second == old_focus || con_has_parent(old_focus, second));
|
||||||
|
fullscreen_mode_t first_fullscreen_mode = first->fullscreen_mode;
|
||||||
|
fullscreen_mode_t second_fullscreen_mode = second->fullscreen_mode;
|
||||||
|
|
||||||
if (!con_fullscreen_permits_focusing(first_ws)) {
|
if (first_fullscreen_mode != CF_NONE) {
|
||||||
DLOG("Cannot swap because target workspace \"%s\" is obscured.\n", first_ws->name);
|
con_disable_fullscreen(first);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
if (second_fullscreen_mode != CF_NONE) {
|
||||||
if (!con_fullscreen_permits_focusing(second_ws)) {
|
con_disable_fullscreen(second);
|
||||||
DLOG("Cannot swap because target workspace \"%s\" is obscured.\n", second_ws->name);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double first_percent = first->percent;
|
double first_percent = first->percent;
|
||||||
|
@ -2385,7 +2384,17 @@ bool con_swap(Con *first, Con *second) {
|
||||||
second->percent = first_percent;
|
second->percent = first_percent;
|
||||||
fake->percent = 0.0;
|
fake->percent = 0.0;
|
||||||
|
|
||||||
|
SWAP(first_fullscreen_mode, second_fullscreen_mode, fullscreen_mode_t);
|
||||||
|
|
||||||
swap_end:
|
swap_end:
|
||||||
|
/* The two windows exchange their original fullscreen status */
|
||||||
|
if (first_fullscreen_mode != CF_NONE) {
|
||||||
|
con_enable_fullscreen(first, first_fullscreen_mode);
|
||||||
|
}
|
||||||
|
if (second_fullscreen_mode != CF_NONE) {
|
||||||
|
con_enable_fullscreen(second, second_fullscreen_mode);
|
||||||
|
}
|
||||||
|
|
||||||
/* We don't actually need this since percentages-wise we haven't changed
|
/* We don't actually need this since percentages-wise we haven't changed
|
||||||
* anything, but we'll better be safe than sorry and just make sure as we'd
|
* anything, but we'll better be safe than sorry and just make sure as we'd
|
||||||
* otherwise crash i3. */
|
* otherwise crash i3. */
|
||||||
|
|
|
@ -25,10 +25,17 @@ for_window[class="mark_B"] mark B
|
||||||
EOT
|
EOT
|
||||||
|
|
||||||
my ($ws, $ws1, $ws2, $ws3);
|
my ($ws, $ws1, $ws2, $ws3);
|
||||||
my ($nodes, $expected_focus, $A, $B, $F);
|
my ($node, $nodes, $expected_focus, $A, $B, $F);
|
||||||
my ($result);
|
my ($result);
|
||||||
|
my @fullscreen_permutations = ([], ["A"], ["B"], ["A", "B"]);
|
||||||
my @urgent;
|
my @urgent;
|
||||||
|
|
||||||
|
sub fullscreen_windows {
|
||||||
|
my $ws = shift if @_;
|
||||||
|
|
||||||
|
scalar grep { $_->{fullscreen_mode} != 0 } @{get_ws_content($ws)}
|
||||||
|
}
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Invalid con_id should not crash i3
|
# Invalid con_id should not crash i3
|
||||||
# See issue #2895.
|
# See issue #2895.
|
||||||
|
@ -162,6 +169,7 @@ kill_all_windows;
|
||||||
# | Y | B | Focus Stacks:
|
# | Y | B | Focus Stacks:
|
||||||
# +---+---+ H2: B, Y
|
# +---+---+ H2: B, Y
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
for my $fullscreen (@fullscreen_permutations){
|
||||||
$ws1 = fresh_workspace;
|
$ws1 = fresh_workspace;
|
||||||
$A = open_window(wm_class => 'mark_A');
|
$A = open_window(wm_class => 'mark_A');
|
||||||
$expected_focus = get_focused($ws1);
|
$expected_focus = get_focused($ws1);
|
||||||
|
@ -172,16 +180,103 @@ $ws2 = fresh_workspace;
|
||||||
open_window;
|
open_window;
|
||||||
$B = open_window(wm_class => 'mark_B');
|
$B = open_window(wm_class => 'mark_B');
|
||||||
|
|
||||||
|
my $A_fullscreen = "A" ~~ @$fullscreen || 0;
|
||||||
|
my $B_fullscreen = "B" ~~ @$fullscreen || 0;
|
||||||
|
$A->fullscreen($A_fullscreen);
|
||||||
|
$B->fullscreen($B_fullscreen);
|
||||||
|
sync_with_i3;
|
||||||
|
|
||||||
|
cmd '[con_mark=B] swap container with mark A';
|
||||||
|
|
||||||
|
$nodes = get_ws_content($ws1);
|
||||||
|
$node = $nodes->[0];
|
||||||
|
is($node->{window}, $B->{id}, 'B is on ws1:left');
|
||||||
|
is(fullscreen_windows($ws1), $A_fullscreen, 'amount of fullscreen windows in ws1');
|
||||||
|
is($node->{fullscreen_mode}, $A_fullscreen, 'B got A\'s fullscreen mode');
|
||||||
|
|
||||||
|
$nodes = get_ws_content($ws2);
|
||||||
|
$node = $nodes->[1];
|
||||||
|
is($node->{window}, $A->{id}, 'A is on ws2:right');
|
||||||
|
is(get_focused($ws2), $expected_focus, 'A is focused');
|
||||||
|
is(fullscreen_windows($ws2), $B_fullscreen, 'amount of fullscreen windows in ws2');
|
||||||
|
is($node->{fullscreen_mode}, $B_fullscreen, 'A got B\'s fullscreen mode');
|
||||||
|
|
||||||
|
kill_all_windows;
|
||||||
|
}
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Swap a non-fullscreen window with a fullscreen one in different workspaces.
|
||||||
|
# Layout: O1[ W1[ H1 ] W2[ B ] ]
|
||||||
|
#
|
||||||
|
# +---+---+ Layout: H1[ A F ]
|
||||||
|
# | A | F | Focus Stacks:
|
||||||
|
# +---+---+ H1: F, A
|
||||||
|
#
|
||||||
|
# +---+---+
|
||||||
|
# | B |
|
||||||
|
# +---+---+
|
||||||
|
###############################################################################
|
||||||
|
$ws1 = fresh_workspace;
|
||||||
|
|
||||||
|
$A = open_window(wm_class => 'mark_A');
|
||||||
|
$F = open_window();
|
||||||
|
$F->fullscreen(1);
|
||||||
|
$expected_focus = get_focused($ws1);
|
||||||
|
|
||||||
|
$ws2 = fresh_workspace;
|
||||||
|
$B = open_window(wm_class => 'mark_B');
|
||||||
|
$B->fullscreen(1);
|
||||||
|
|
||||||
cmd '[con_mark=B] swap container with mark A';
|
cmd '[con_mark=B] swap container with mark A';
|
||||||
|
|
||||||
$nodes = get_ws_content($ws1);
|
$nodes = get_ws_content($ws1);
|
||||||
is($nodes->[0]->{window}, $B->{id}, 'B is on ws1:left');
|
is($nodes->[0]->{window}, $B->{id}, 'B is on ws1:left');
|
||||||
|
is(fullscreen_windows($ws1), 1, 'F still fullscreen in ws1');
|
||||||
|
is(get_focused($ws1), $expected_focus, 'F is still focused');
|
||||||
|
|
||||||
$nodes = get_ws_content($ws2);
|
$nodes = get_ws_content($ws2);
|
||||||
is($nodes->[1]->{window}, $A->{id}, 'A is on ws2:right');
|
is($nodes->[0]->{window}, $A->{id}, 'A is on ws1');
|
||||||
is(get_focused($ws2), $expected_focus, 'A is focused');
|
|
||||||
|
|
||||||
kill_all_windows;
|
###############################################################################
|
||||||
|
# Try a more exotic layout with fullscreen containers.
|
||||||
|
# A and F are fullscreened as a stack of two vertical containers before the
|
||||||
|
# swap is performed.
|
||||||
|
# A is swapped with fullscreened window B which is in another workspace.
|
||||||
|
#
|
||||||
|
# +---+---+ Layout: H1[ X V1[ A F ] ]
|
||||||
|
# | | A | Focus Stacks:
|
||||||
|
# | X +---+ H1: V1, X
|
||||||
|
# | | F | V1: F, A
|
||||||
|
# +---+---+
|
||||||
|
###############################################################################
|
||||||
|
$ws1 = fresh_workspace;
|
||||||
|
|
||||||
|
open_window;
|
||||||
|
$A = open_window(wm_class => 'mark_A');
|
||||||
|
cmd "split v";
|
||||||
|
open_window;
|
||||||
|
cmd "focus parent";
|
||||||
|
cmd "fullscreen enable";
|
||||||
|
$F = fullscreen_windows($ws1);
|
||||||
|
$expected_focus = get_focused($ws1);
|
||||||
|
|
||||||
|
$ws2 = fresh_workspace;
|
||||||
|
$B = open_window(wm_class => 'mark_B');
|
||||||
|
$B->fullscreen(1);
|
||||||
|
|
||||||
|
cmd '[con_mark=B] swap container with mark A';
|
||||||
|
|
||||||
|
sync_with_i3;
|
||||||
|
does_i3_live;
|
||||||
|
|
||||||
|
$nodes = get_ws_content($ws1);
|
||||||
|
is($nodes->[1]->{nodes}->[0]->{window}, $B->{id}, 'B is on top right in ws1');
|
||||||
|
is(get_focused($ws1), $expected_focus, 'The container of the stacked windows remains focused in ws1');
|
||||||
|
is(fullscreen_windows($ws1), $F, 'Same amount of fullscreen windows in ws1');
|
||||||
|
|
||||||
|
$nodes = get_ws_content($ws2);
|
||||||
|
is($nodes->[0]->{window}, $A->{id}, 'A is on ws2');
|
||||||
|
is(fullscreen_windows($ws2), 1, 'A is in fullscreen mode');
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Swap two non-focused containers within the same workspace.
|
# Swap two non-focused containers within the same workspace.
|
||||||
|
@ -232,6 +327,7 @@ kill_all_windows;
|
||||||
# | F |
|
# | F |
|
||||||
# +---+
|
# +---+
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
for my $fullscreen (@fullscreen_permutations){
|
||||||
$ws1 = fresh_workspace;
|
$ws1 = fresh_workspace;
|
||||||
$A = open_window(wm_class => 'mark_A');
|
$A = open_window(wm_class => 'mark_A');
|
||||||
|
|
||||||
|
@ -242,17 +338,30 @@ $ws3 = fresh_workspace;
|
||||||
open_window;
|
open_window;
|
||||||
$expected_focus = get_focused($ws3);
|
$expected_focus = get_focused($ws3);
|
||||||
|
|
||||||
|
my $A_fullscreen = "A" ~~ @$fullscreen || 0;
|
||||||
|
my $B_fullscreen = "B" ~~ @$fullscreen || 0;
|
||||||
|
$A->fullscreen($A_fullscreen);
|
||||||
|
$B->fullscreen($B_fullscreen);
|
||||||
|
sync_with_i3;
|
||||||
|
|
||||||
cmd '[con_mark=B] swap container with mark A';
|
cmd '[con_mark=B] swap container with mark A';
|
||||||
|
|
||||||
$nodes = get_ws_content($ws1);
|
$nodes = get_ws_content($ws1);
|
||||||
is($nodes->[0]->{window}, $B->{id}, 'B is on the first workspace');
|
$node = $nodes->[0];
|
||||||
|
is($node->{window}, $B->{id}, 'B is on the first workspace');
|
||||||
|
is(fullscreen_windows($ws1), $A_fullscreen, 'amount of fullscreen windows in ws1');
|
||||||
|
is($node->{fullscreen_mode}, $A_fullscreen, 'B got A\'s fullscreen mode');
|
||||||
|
|
||||||
$nodes = get_ws_content($ws2);
|
$nodes = get_ws_content($ws2);
|
||||||
is($nodes->[0]->{window}, $A->{id}, 'A is on the second workspace');
|
$node = $nodes->[0];
|
||||||
|
is($node->{window}, $A->{id}, 'A is on the second workspace');
|
||||||
|
is(fullscreen_windows($ws2), $B_fullscreen, 'amount of fullscreen windows in ws2');
|
||||||
|
is($node->{fullscreen_mode}, $B_fullscreen, 'A got B\'s fullscreen mode');
|
||||||
|
|
||||||
is(get_focused($ws3), $expected_focus, 'F is still focused');
|
is(get_focused($ws3), $expected_focus, 'F is still focused');
|
||||||
|
|
||||||
kill_all_windows;
|
kill_all_windows;
|
||||||
|
}
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Swap two non-focused containers with one being on a different workspace.
|
# Swap two non-focused containers with one being on a different workspace.
|
||||||
|
|
Loading…
Reference in New Issue