Skip to content

Commit

Permalink
Fix move out with normalization
Browse files Browse the repository at this point in the history
  • Loading branch information
nikitabobko committed Nov 25, 2023
1 parent 7e21b77 commit 86d37a2
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 21 deletions.
3 changes: 2 additions & 1 deletion src/command/WorkspaceCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ struct WorkspaceCommand : Command {
func _run(_ subject: inout CommandSubject, _ index: Int, _ commands: [any Command]) {
check(Thread.current.isMainThread)
let workspace = Workspace.get(byName: workspaceName)
if let window = workspace.mostRecentWindow { // switch to not empty workspace
// todo drop anyLeafWindowRecursive. It must not be necessary
if let window = workspace.mostRecentWindow ?? workspace.anyLeafWindowRecursive { // switch to not empty workspace
subject = .window(window)
} else { // switch to empty workspace
check(workspace.isEffectivelyEmpty)
Expand Down
2 changes: 1 addition & 1 deletion src/focused.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func getNativeFocusedWindow(startup: Bool) -> Window? {

var focusedWindow: Window? {
//check(focusSourceOfTruth == .ownModel)
Workspace.focused.mostRecentWindow
return Workspace.focused.mostRecentWindow ?? Workspace.focused.anyLeafWindowRecursive
//focusSourceOfTruth == .ownModel
// ? (Workspace.focused.mostRecentWindow ?? Workspace.focused.anyLeafWindowRecursive)
// : nativeFocusedWindow
Expand Down
3 changes: 2 additions & 1 deletion src/tree/TreeNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,15 @@ class TreeNode: Equatable {
}
newParent._children.insert(self, at: index != INDEX_BIND_LAST ? index : newParent._children.count)
_parent = newParent
markAsMostRecentChild()
return result
}

private func unbindIfPossible() -> BindingData? {
guard let _parent else { return nil }

let index = _parent._children.remove(element: self) ?? errorT("Can't find child in its parent")
_parent._mruChildren.remove(self)
check(_parent._mruChildren.remove(self))
self._parent = nil

return BindingData(parent: _parent, adaptiveWeight: adaptiveWeight, index: index)
Expand Down
6 changes: 6 additions & 0 deletions src/tree/normalizeContainers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,15 @@ private extension TilingContainer {
func unbindEmptyAndAutoFlatten() {
if let child = children.singleOrNil(), config.enableNormalizationFlattenContainers && (child is TilingContainer || !isRootContainer) {
child.unbindFromParent()
let mru = parent.mostRecentChild
let previousBinding = unbindFromParent()
child.bind(to: previousBinding.parent, adaptiveWeight: previousBinding.adaptiveWeight, index: previousBinding.index)
(child as? TilingContainer)?.unbindEmptyAndAutoFlatten()
if mru != self {
mru?.markAsMostRecentChild()
} else {
child.markAsMostRecentChild()
}
} else {
for child in children {
(child as? TilingContainer)?.unbindEmptyAndAutoFlatten()
Expand Down
32 changes: 24 additions & 8 deletions test/command/FocusCommandTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,35 @@ final class FocusCommandTest: XCTestCase {

func testFocus() {
XCTAssertEqual(focusedWindow, nil)
var start: Window!
Workspace.get(byName: name).rootTilingContainer.apply {
TestWindow(id: 1, parent: $0)
TestWindow(id: 2, parent: $0).focus()
start = TestWindow(id: 2, parent: $0)
TestWindow(id: 3, parent: $0)
}
start.focus()
XCTAssertEqual(focusedWindow?.windowId, 2)
}

func testFocusAlongTheContainerOrientation() {
var start: Window!
Workspace.get(byName: name).rootTilingContainer.apply {
TestWindow(id: 1, parent: $0).focus()
start = TestWindow(id: 1, parent: $0)
TestWindow(id: 2, parent: $0)
}
start.focus()

FocusCommand(direction: .right).testRun()
XCTAssertEqual(focusedWindow?.windowId, 2)
}

func testFocusAcrossTheContainerOrientation() {
var start: Window!
Workspace.get(byName: name).rootTilingContainer.apply {
TestWindow(id: 1, parent: $0).focus()
start = TestWindow(id: 1, parent: $0)
TestWindow(id: 2, parent: $0)
}
start.focus()

FocusCommand(direction: .up).testRun()
XCTAssertEqual(focusedWindow?.windowId, 1)
Expand All @@ -57,10 +63,12 @@ final class FocusCommandTest: XCTestCase {
}

func testFocusNoWrapping() {
var start: Window!
Workspace.get(byName: name).rootTilingContainer.apply {
TestWindow(id: 1, parent: $0).focus()
start = TestWindow(id: 1, parent: $0)
TestWindow(id: 2, parent: $0)
}
start.focus()

FocusCommand(direction: .left).testRun()
XCTAssertEqual(focusedWindow?.windowId, 1)
Expand All @@ -73,7 +81,7 @@ final class FocusCommandTest: XCTestCase {
var window3: Window!
var unrelatedWindow: Window!
workspace.rootTilingContainer.apply {
startWindow = TestWindow(id: 1, parent: $0).apply { $0.focus() }
startWindow = TestWindow(id: 1, parent: $0)
TilingContainer.newVTiles(parent: $0, adaptiveWeight: 1).apply {
TilingContainer.newHTiles(parent: $0, adaptiveWeight: 1).apply {
window2 = TestWindow(id: 2, parent: $0)
Expand All @@ -83,6 +91,11 @@ final class FocusCommandTest: XCTestCase {
}
}

XCTAssertEqual(workspace.mostRecentWindow?.windowId, 3) // The latest bound
startWindow.focus()
FocusCommand(direction: .right).testRun()
XCTAssertEqual(focusedWindow?.windowId, 3)

window2.markAsMostRecentChild()
startWindow.focus()
FocusCommand(direction: .right).testRun()
Expand All @@ -96,24 +109,28 @@ final class FocusCommandTest: XCTestCase {
}

func testFocusOutsideOfTheContainer() {
var start: Window!
Workspace.get(byName: name).rootTilingContainer.apply {
TestWindow(id: 1, parent: $0)
TilingContainer.newVTiles(parent: $0, adaptiveWeight: 1).apply {
TestWindow(id: 2, parent: $0).focus()
start = TestWindow(id: 2, parent: $0)
}
}
start.focus()

FocusCommand(direction: .left).testRun()
XCTAssertEqual(focusedWindow?.windowId, 1)
}

func testFocusOutsideOfTheContainer2() {
var start: Window!
Workspace.get(byName: name).rootTilingContainer.apply {
TestWindow(id: 1, parent: $0)
TilingContainer.newHTiles(parent: $0, adaptiveWeight: 1).apply {
TestWindow(id: 2, parent: $0).focus()
start = TestWindow(id: 2, parent: $0)
}
}
start.focus()

FocusCommand(direction: .left).testRun()
XCTAssertEqual(focusedWindow?.windowId, 1)
Expand All @@ -130,6 +147,5 @@ extension Command {
state = .emptyWorkspace(focusedWorkspaceName)
}
run(&state)
state.windowOrNil?.focus()
}
}
6 changes: 4 additions & 2 deletions test/command/JoinWithCommandTest.swift
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import XCTest
@testable import AeroSpace_Debug

final class MoveInCommandTest: XCTestCase {
final class JoinWithCommandTest: XCTestCase {
override func setUpWithError() throws { setUpWorkspacesForTests() }

func testMoveIn() {
var start: Window!
let root = Workspace.get(byName: name).rootTilingContainer.apply {
TestWindow(id: 0, parent: $0)
TestWindow(id: 1, parent: $0).focus()
start = TestWindow(id: 1, parent: $0)
TestWindow(id: 2, parent: $0)
}
start.focus()

JoinWithCommand(direction: .right).testRun()
XCTAssertEqual(root.layoutDescription, .h_tiles([
Expand Down
58 changes: 54 additions & 4 deletions test/command/MoveThroughCommandTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,29 @@ final class MoveThroughCommandTest: XCTestCase {
override func setUpWithError() throws { setUpWorkspacesForTests() }

func testMove_swapWindows() {
var start: Window!
let root = Workspace.get(byName: name).rootTilingContainer.apply {
TestWindow(id: 1, parent: $0).focus()
start = TestWindow(id: 1, parent: $0)
TestWindow(id: 2, parent: $0)
}
start.focus()

MoveThroughCommand(direction: .right).testRun()
XCTAssertEqual(root.layoutDescription, .h_tiles([.window(2), .window(1)]))
}

func testMoveInto_findTopMostContainerWithRightOrientation() {
var start: Window!
let root = Workspace.get(byName: name).rootTilingContainer.apply {
TestWindow(id: 0, parent: $0)
TestWindow(id: 1, parent: $0).focus()
start = TestWindow(id: 1, parent: $0)
TilingContainer.newHTiles(parent: $0, adaptiveWeight: 1).apply {
TilingContainer.newHTiles(parent: $0, adaptiveWeight: 1).apply {
TestWindow(id: 2, parent: $0)
}
}
}
start.focus()

MoveThroughCommand(direction: .right).testRun()
XCTAssertEqual(
Expand Down Expand Up @@ -106,11 +110,13 @@ final class MoveThroughCommandTest: XCTestCase {

func testCreateImplicitContainer() {
let workspace = Workspace.get(byName: name)
var start: Window!
workspace.rootTilingContainer.apply {
TestWindow(id: 1, parent: $0)
TestWindow(id: 2, parent: $0).focus()
start = TestWindow(id: 2, parent: $0)
TestWindow(id: 3, parent: $0)
}
start.focus()

MoveThroughCommand(direction: .up).testRun()
XCTAssertEqual(
Expand All @@ -125,14 +131,16 @@ final class MoveThroughCommandTest: XCTestCase {
}

func testMoveOut() {
var start: Window!
let root = Workspace.get(byName: name).rootTilingContainer.apply {
TestWindow(id: 1, parent: $0)
TilingContainer.newVTiles(parent: $0, adaptiveWeight: 1).apply {
TestWindow(id: 2, parent: $0).focus()
start = TestWindow(id: 2, parent: $0)
TestWindow(id: 3, parent: $0)
TestWindow(id: 4, parent: $0)
}
}
start.focus()

MoveThroughCommand(direction: .left).testRun()
XCTAssertEqual(
Expand All @@ -147,6 +155,48 @@ final class MoveThroughCommandTest: XCTestCase {
])
)
}

func testMoveOutWithNormalization_right() {
config.enableNormalizationFlattenContainers = true

var start: Window!
let workspace = Workspace.get(byName: name).apply {
TestWindow(id: 1, parent: $0.rootTilingContainer)
start = TestWindow(id: 2, parent: $0.rootTilingContainer)
}
start.focus()

MoveThroughCommand(direction: .right).testRun()
XCTAssertEqual(
workspace.rootTilingContainer.layoutDescription,
.h_tiles([
.window(1),
.window(2),
])
)
XCTAssertEqual(focusedWindow?.windowId, 2)
}

func testMoveOutWithNormalization_left() {
config.enableNormalizationFlattenContainers = true

var start: Window!
let workspace = Workspace.get(byName: name).apply {
start = TestWindow(id: 1, parent: $0.rootTilingContainer)
TestWindow(id: 2, parent: $0.rootTilingContainer)
}
start.focus()

MoveThroughCommand(direction: .left).testRun()
XCTAssertEqual(
workspace.rootTilingContainer.layoutDescription,
.h_tiles([
.window(1),
.window(2),
])
)
XCTAssertEqual(focusedWindow?.windowId, 1)
}
}

extension TreeNode {
Expand Down
16 changes: 12 additions & 4 deletions test/command/SplitCommandTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ final class SplitCommandTest: XCTestCase {
override func setUpWithError() throws { setUpWorkspacesForTests() }

func testSplit() {
var start: Window!
let root = Workspace.get(byName: name).rootTilingContainer.apply {
TestWindow(id: 1, parent: $0).focus()
start = TestWindow(id: 1, parent: $0)
TestWindow(id: 2, parent: $0)
}
start.focus()

SplitCommand(splitArg: .vertical).testRun()
XCTAssertEqual(root.layoutDescription, .h_tiles([
Expand All @@ -20,10 +22,12 @@ final class SplitCommandTest: XCTestCase {
}

func testSplitOppositeOrientation() {
var start: Window!
let root = Workspace.get(byName: name).rootTilingContainer.apply {
TestWindow(id: 1, parent: $0).focus()
start = TestWindow(id: 1, parent: $0)
TestWindow(id: 2, parent: $0)
}
start.focus()

SplitCommand(splitArg: .opposite).testRun()
XCTAssertEqual(root.layoutDescription, .h_tiles([
Expand All @@ -35,12 +39,14 @@ final class SplitCommandTest: XCTestCase {
}

func testChangeOrientation() {
var start: Window!
let root = Workspace.get(byName: name).rootTilingContainer.apply {
TilingContainer.newVTiles(parent: $0, adaptiveWeight: 1).apply {
TestWindow(id: 1, parent: $0).focus()
start = TestWindow(id: 1, parent: $0)
}
TestWindow(id: 2, parent: $0)
}
start.focus()

SplitCommand(splitArg: .horizontal).testRun()
XCTAssertEqual(root.layoutDescription, .h_tiles([
Expand All @@ -52,12 +58,14 @@ final class SplitCommandTest: XCTestCase {
}

func testToggleOrientation() {
var start: Window!
let root = Workspace.get(byName: name).rootTilingContainer.apply {
TilingContainer.newVTiles(parent: $0, adaptiveWeight: 1).apply {
TestWindow(id: 1, parent: $0).focus()
start = TestWindow(id: 1, parent: $0)
}
TestWindow(id: 2, parent: $0)
}
start.focus()

SplitCommand(splitArg: .opposite).testRun()
XCTAssertEqual(root.layoutDescription, .h_tiles([
Expand Down

0 comments on commit 86d37a2

Please sign in to comment.