@@ -33,9 +33,7 @@ enum NiriWindowMoveResult {
3333 struct RemovalContext {
3434 var existingHandleIds : Set < WindowToken >
3535 var wasEmptyBeforeSync : Bool
36- var columnRemovalResult : NiriLayoutEngine . ColumnRemovalResult ?
37- var precomputedFallback : NodeId ?
38- var originalColumnIndex : Int ?
36+ var removalResult : NiriLayoutEngine . NiriRemovalResult
3937 }
4038
4139 var scrollAnimationByDisplay : [ CGDirectDisplayID : WorkspaceDescriptor . ID ] = [ : ]
@@ -407,55 +405,24 @@ enum NiriWindowMoveResult {
407405 removedNodeIds: [ NodeId ]
408406 ) -> RemovalContext {
409407 let existingHandleIds = pass. engine. root ( for: pass. wsId) ? . windowIdSet ?? [ ]
410- let currentHandleIds = Set ( windowTokens)
411- let removedHandleIds = existingHandleIds. subtracting ( currentHandleIds)
412- let removedNodeIdSet = Set ( removedNodeIds)
413-
414- var precomputedFallback : NodeId ?
415- var originalColumnIndex : Int ?
416- var columnRemovalResult : NiriLayoutEngine . ColumnRemovalResult ?
417-
408+ let removedHandleIds = existingHandleIds. subtracting ( Set ( windowTokens) )
418409 let wasEmptyBeforeSync = pass. engine. columns ( in: pass. wsId) . isEmpty
419410
420- for removedHandleId in removedHandleIds {
421- guard let window = pass. engine. findNode ( for: removedHandleId) ,
422- let col = pass. engine. column ( of: window) ,
423- let colIdx = pass. engine. columnIndex ( of: col, in: pass. wsId) else { continue }
424-
425- let allWindowsInColumnRemoved = col. windowNodes. allSatisfy { w in
426- !currentHandleIds. contains ( w. token)
427- }
428-
429- if allWindowsInColumnRemoved && columnRemovalResult == nil {
430- originalColumnIndex = colIdx
431- columnRemovalResult = pass. engine. animateColumnsForRemoval (
432- columnIndex: colIdx,
433- in: pass. wsId,
434- motion: motion,
435- state: & state,
436- gaps: pass. gap
437- )
438- }
439-
440- let shouldPrecomputeFallback = if removedNodeIdSet. isEmpty {
441- window. id == currentSelection
442- } else {
443- removedNodeIdSet. contains ( window. id)
444- }
445- if shouldPrecomputeFallback {
446- precomputedFallback = pass. engine. fallbackSelectionOnRemoval (
447- removing: window. id,
448- in: pass. wsId
449- )
450- }
451- }
411+ let removalResult = pass. engine. removeWindows (
412+ removedHandleIds,
413+ in: pass. wsId,
414+ state: & state,
415+ motion: motion,
416+ workingFrame: pass. insetFrame,
417+ gaps: pass. gap,
418+ selectedNodeId: currentSelection,
419+ removedNodeIds: removedNodeIds
420+ )
452421
453422 return RemovalContext (
454423 existingHandleIds: existingHandleIds,
455424 wasEmptyBeforeSync: wasEmptyBeforeSync,
456- columnRemovalResult: columnRemovalResult,
457- precomputedFallback: precomputedFallback,
458- originalColumnIndex: originalColumnIndex
425+ removalResult: removalResult
459426 )
460427 }
461428
@@ -497,7 +464,7 @@ enum NiriWindowMoveResult {
497464
498465 let originalActiveIdx = state. activeColumnIndex
499466 let insertedBeforeActive = newColumnData. filter { $0. colIdx <= originalActiveIdx }
500- if !insertedBeforeActive. isEmpty, removal. columnRemovalResult == nil {
467+ if !insertedBeforeActive. isEmpty, removal. removalResult . removedColumnIndicesBefore . isEmpty {
501468 let totalInsertedWidth = insertedBeforeActive. reduce ( CGFloat ( 0 ) ) { total, data in
502469 total + data. col. cachedWidth + pass. gap
503470 }
@@ -531,25 +498,11 @@ enum NiriWindowMoveResult {
531498 ) -> ( viewportNeedsRecalc: Bool , rememberedFocusToken: WindowToken ? ) {
532499 state. displayRefreshRate = snapshot. displayRefreshRate
533500
534- if let result = removal. columnRemovalResult {
535- if let prevOffset = state. activatePrevColumnOnRemoval {
536- state. viewOffsetPixels = . static( prevOffset)
537- state. activatePrevColumnOnRemoval = nil
538- }
539-
540- if let fallback = result. fallbackSelectionId {
541- state. selectedNodeId = fallback
542- } else if let selectedId = state. selectedNodeId, pass. engine. findNode ( by: selectedId) == nil {
543- state. selectedNodeId = removal. precomputedFallback
544- ?? pass. engine. validateSelection ( selectedId, in: pass. wsId)
545- }
546- } else {
547- if let selectedId = state. selectedNodeId {
548- if pass. engine. findNode ( by: selectedId) == nil {
549- state. selectedNodeId = removal. precomputedFallback
550- ?? pass. engine. validateSelection ( selectedId, in: pass. wsId)
551- }
552- }
501+ if let finalSelectionId = removal. removalResult. finalSelectionId {
502+ state. selectedNodeId = finalSelectionId
503+ } else if let selectedId = state. selectedNodeId,
504+ pass. engine. findNode ( by: selectedId) == nil {
505+ state. selectedNodeId = pass. engine. validateSelection ( selectedId, in: pass. wsId)
553506 }
554507
555508 if state. selectedNodeId == nil {
@@ -566,7 +519,7 @@ enum NiriWindowMoveResult {
566519 }
567520
568521 let offsetBefore = state. viewOffsetPixels. current ( )
569- var viewportNeedsRecalc = false
522+ var viewportNeedsRecalc = removal . removalResult . viewportNeedsRecalc
570523
571524 let isGestureOrAnimation = state. viewOffsetPixels. isGesture || state. viewOffsetPixels. isAnimating
572525
@@ -580,21 +533,19 @@ enum NiriWindowMoveResult {
580533 !isGestureOrAnimation,
581534 snapshot. isActiveWorkspace,
582535 let selectedId = state. selectedNodeId,
583- let selectedNode = pass. engine. findNode ( by: selectedId)
536+ let selectedNode = pass. engine. findNode ( by: selectedId) ,
537+ !removal. removalResult. visibilityWasCorrected,
538+ removal. removalResult. removedTokens. isEmpty || removal. removalResult. fromIndexForVisibility != nil
584539 {
585- if let restoreOffset = removal. columnRemovalResult? . restorePreviousViewOffset {
586- state. viewOffsetPixels = . static( restoreOffset)
587- } else {
588- pass. engine. ensureSelectionVisible (
589- node: selectedNode,
590- in: pass. wsId,
591- motion: motion,
592- state: & state,
593- workingFrame: pass. insetFrame,
594- gaps: pass. gap,
595- fromContainerIndex: removal. originalColumnIndex
596- )
597- }
540+ pass. engine. ensureSelectionVisible (
541+ node: selectedNode,
542+ in: pass. wsId,
543+ motion: motion,
544+ state: & state,
545+ workingFrame: pass. insetFrame,
546+ gaps: pass. gap,
547+ fromContainerIndex: removal. removalResult. fromIndexForVisibility
548+ )
598549 if abs ( state. viewOffsetPixels. current ( ) - offsetBefore) > 1 {
599550 viewportNeedsRecalc = true
600551 }
0 commit comments