]> git.sur5r.net Git - i3/i3/commitdiff
Make swap work with fullscreen windows 2902/head
authorOrestis Floros <orestisf1993@gmail.com>
Wed, 6 Sep 2017 01:10:22 +0000 (04:10 +0300)
committerOrestis Floros <orestisf1993@gmail.com>
Sat, 16 Sep 2017 10:49:20 +0000 (13:49 +0300)
Swap works like normal with fullscreen windows but swaps the fullscreen
mode of the 2 containers after it's done.

Fixes #2811

src/con.c
testcases/t/291-swap.t

index 04aacd32578ed554869acbf2b85aed52976b2f99..a663db31bcc278ed14f5b804126d0279220fe0c2 100644 (file)
--- a/src/con.c
+++ b/src/con.c
@@ -2276,15 +2276,14 @@ bool con_swap(Con *first, Con *second) {
     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_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)) {
-        DLOG("Cannot swap because target workspace \"%s\" is obscured.\n", first_ws->name);
-        return false;
+    if (first_fullscreen_mode != CF_NONE) {
+        con_disable_fullscreen(first);
     }
-
-    if (!con_fullscreen_permits_focusing(second_ws)) {
-        DLOG("Cannot swap because target workspace \"%s\" is obscured.\n", second_ws->name);
-        return false;
+    if (second_fullscreen_mode != CF_NONE) {
+        con_disable_fullscreen(second);
     }
 
     double first_percent = first->percent;
@@ -2385,7 +2384,17 @@ bool con_swap(Con *first, Con *second) {
     second->percent = first_percent;
     fake->percent = 0.0;
 
+    SWAP(first_fullscreen_mode, second_fullscreen_mode, fullscreen_mode_t);
+
 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
      * anything, but we'll better be safe than sorry and just make sure as we'd
      * otherwise crash i3. */
index 539325976f13c28f682894898f42d44ef3fee5a4..f9ac3b6ac3ab97a9915bb8d20addaba2fd03a509 100644 (file)
@@ -25,10 +25,17 @@ for_window[class="mark_B"] mark B
 EOT
 
 my ($ws, $ws1, $ws2, $ws3);
-my ($nodes, $expected_focus, $A, $B, $F);
+my ($node, $nodes, $expected_focus, $A, $B, $F);
 my ($result);
+my @fullscreen_permutations = ([], ["A"], ["B"], ["A", "B"]);
 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
 # See issue #2895.
@@ -162,26 +169,114 @@ kill_all_windows;
 # | Y | B |    Focus Stacks:
 # +---+---+        H2: B, Y
 ###############################################################################
+for my $fullscreen (@fullscreen_permutations){
+    $ws1 = fresh_workspace;
+    $A = open_window(wm_class => 'mark_A');
+    $expected_focus = get_focused($ws1);
+    open_window;
+    cmd 'focus left';
+
+    $ws2 = fresh_workspace;
+    open_window;
+    $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);
-open_window;
-cmd 'focus left';
 
 $ws2 = fresh_workspace;
-open_window;
 $B = open_window(wm_class => 'mark_B');
+$B->fullscreen(1);
 
 cmd '[con_mark=B] swap container with mark A';
 
 $nodes = get_ws_content($ws1);
 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);
-is($nodes->[1]->{window}, $A->{id}, 'A is on ws2:right');
-is(get_focused($ws2), $expected_focus, 'A is focused');
+is($nodes->[0]->{window}, $A->{id}, 'A is on ws1');
 
-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.
@@ -232,27 +327,41 @@ kill_all_windows;
 # | F |
 # +---+
 ###############################################################################
-$ws1 = fresh_workspace;
-$A = open_window(wm_class => 'mark_A');
+for my $fullscreen (@fullscreen_permutations){
+    $ws1 = fresh_workspace;
+    $A = open_window(wm_class => 'mark_A');
 
-$ws2 = fresh_workspace;
-$B = open_window(wm_class => 'mark_B');
+    $ws2 = fresh_workspace;
+    $B = open_window(wm_class => 'mark_B');
 
-$ws3 = fresh_workspace;
-open_window;
-$expected_focus = get_focused($ws3);
+    $ws3 = fresh_workspace;
+    open_window;
+    $expected_focus = get_focused($ws3);
 
-cmd '[con_mark=B] swap container with mark A';
+    my $A_fullscreen = "A" ~~ @$fullscreen || 0;
+    my $B_fullscreen = "B" ~~ @$fullscreen || 0;
+    $A->fullscreen($A_fullscreen);
+    $B->fullscreen($B_fullscreen);
+    sync_with_i3;
 
-$nodes = get_ws_content($ws1);
-is($nodes->[0]->{window}, $B->{id}, 'B is on the first workspace');
+    cmd '[con_mark=B] swap container with mark A';
 
-$nodes = get_ws_content($ws2);
-is($nodes->[0]->{window}, $A->{id}, 'A is on the second workspace');
+    $nodes = get_ws_content($ws1);
+    $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');
 
-is(get_focused($ws3), $expected_focus, 'F is still focused');
+    $nodes = get_ws_content($ws2);
+    $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');
 
-kill_all_windows;
+    is(get_focused($ws3), $expected_focus, 'F is still focused');
+
+    kill_all_windows;
+}
 
 ###############################################################################
 # Swap two non-focused containers with one being on a different workspace.