 
             let (pane, paneIndex) = paneArrangement.coordinates(at: windowIndex)
 
-            let (windowHeight, windowWidth): (CGFloat, CGFloat) = paneArrangement.windowDimensions(for: pane)
-            let column: Column = paneArrangement.column(for: pane)
+            let (windowHeight, windowWidth): (CGFloat, CGFloat) = paneArrangement.windowDimensions(inPane: pane)
+            let column: Column = paneArrangement.column(ofPane: pane)
 
             let (leftPaneWidth, middlePaneWidth, _): (CGFloat, CGFloat, CGFloat) = paneArrangement.widthsLeftToRight()
 
-            let xorigin: CGFloat = {
+            let xorigin: CGFloat = screenFrame.origin.x + {
                 switch column {
-                case .left: return screenFrame.origin.x
-                case .middle: return screenFrame.origin.x + leftPaneWidth
-                case .right: return screenFrame.origin.x + leftPaneWidth + middlePaneWidth
+                case .left: return 0.0
+                case .middle: return leftPaneWidth
+                case .right: return leftPaneWidth + middlePaneWidth
                 }
             }()
 
-            let scaleFactor: CGFloat = (screenFrame.width / windowWidth)
+            let scaleFactor: CGFloat = screenFrame.width / {
+                if pane == .main {
+                    return paneArrangement.width(.main)
+                }
+                return paneArrangement.width(.secondary) + paneArrangement.width(.tertiary)
+            }()
 
             windowFrame.origin.x = xorigin
             windowFrame.origin.y = screenFrame.origin.y + (windowHeight * CGFloat(paneIndex))
             windowFrame.size.width = windowWidth
             windowFrame.size.height = windowHeight
 
-            let isTertiaryMain = (paneArrangement.tertiaryPaneCount > 0 ? pane == Pane.main : pane != Pane.main)
-
-            let resizeRules = ResizeRules(isMain: isTertiaryMain, unconstrainedDimension: .horizontal, scaleFactor: scaleFactor)
+            let isMain = windowIndex < paneArrangement.firstIndex(.secondary)
+
+            let resizeRules = ResizeRules(isMain: isMain, unconstrainedDimension: .horizontal, scaleFactor: scaleFactor)
             let frameAssignment = FrameAssignment(frame: windowFrame, window: window, focused: window.isEqual(to: focusedWindow), screenFrame: screenFrame, resizeRules: resizeRules)
 
             assignments.append(frameAssignment)

        }

        let screenFrame = screen.adjustedFrame()
        let paneArrangement = PaneArrangement(mainPane: mainIs,
                                              numWindows: UInt(windows.count),
                                              numMainPane: UInt(layout.mainPaneCount),
                                              screenHeight: screenFrame.height,
                                              screenWidth: screenFrame.width,
                                              mainPaneRatio: layout.mainPaneRatio)

        let focusedWindow = SIWindow.focused()


import Silica

// we'd like to hide these structures and enums behind fileprivate, but
// https://bugs.swift.org/browse/SR-47

internal enum Column {
    case left
    case middle
    case right
}

internal enum Pane {
    case main
    case secondary
    case tertiary
}

internal struct TriplePaneArrangement {

    let paneCount: [Pane: UInt]            // number of windows in pane
    let paneWindowHeight: [Pane: CGFloat]  // height of windows in pane
    let paneWindowWidth: [Pane: CGFloat]   // width of windows in pane
    let panePosition: [Pane: Column]       // how panes relate to columns
    let columnDesignation: [Column: Pane]  // how columns relate to panes

    init(mainPane: Column,    // which Column is the main Pane
         numWindows: UInt,    // how many windows total
         numMainPane: UInt,   // how many windows in the main Pane
         screenSize: CGSize,  // total size of the screen
         mainPaneRatio: CGFloat
    ) {
        // forward and reverse mapping of columns to their designations
        self.panePosition = {
            switch mainPane {
            case .left:   return [.main: .left, .secondary: .middle, .tertiary: .right]
            case .middle: return [.main: .middle, .secondary: .left, .tertiary: .right]
            case .right:  return [.main: .right, .secondary: .left, .tertiary: .middle]
            }
        }()
        // swap keys and values for reverse lookup
        self.columnDesignation = Dictionary(uniqueKeysWithValues: panePosition.map({ ($1, $0) }))

        // calculate how many are in each type
        let mainPaneCount = min(numWindows, numMainPane)
        let nonMainCount: UInt = numWindows - mainPaneCount
        let tertiaryPaneCount = nonMainCount >> 1   // divide by 2. we do tertiary first so that a single window results in a zero here
        let secondaryPaneCount = nonMainCount - tertiaryPaneCount
        self.paneCount = [.main: mainPaneCount, .secondary: secondaryPaneCount, .tertiary: tertiaryPaneCount]

        // calculate heights
        let screenHeight = screenSize.height
        self.paneWindowHeight = [
            .main: round(screenHeight / CGFloat(mainPaneCount)),
            .secondary: secondaryPaneCount == 0 ? 0.0 : round(screenHeight / CGFloat(secondaryPaneCount)),
            .tertiary: tertiaryPaneCount == 0 ? 0.0 : round(screenHeight / CGFloat(tertiaryPaneCount))
        ]

        // calculate widths
        let screenWidth = screenSize.width
        let mainWindowWidth = secondaryPaneCount == 0 ? screenWidth : round(screenWidth * mainPaneRatio)
        let nonMainWindowWidth = round((screenWidth - mainWindowWidth) / 2)
        self.paneWindowWidth = [
            .main: mainWindowWidth,
            .secondary: nonMainWindowWidth,
            .tertiary: nonMainWindowWidth
        ]
   }

    func count(_ pane: Pane) -> UInt {
        return paneCount[pane]!
    }

    func height(_ pane: Pane) -> CGFloat {
        return paneWindowHeight[pane]!
    }

    func width(_ pane: Pane) -> CGFloat {
        return paneWindowWidth[pane]!
    }

    func firstIndex(_ pane: Pane) -> UInt {
        switch pane {
        case .main: return 0
        case .secondary: return count(.main)
        case .tertiary: return count(.main) + count(.secondary)
        }
    }

    func pane(ofIndex windowIndex: UInt) -> Pane {
        if windowIndex >= firstIndex(.tertiary) {
            return .tertiary
        }
        if windowIndex >= firstIndex(.secondary) {
            return .secondary
        }
        return .main
    }

    // Given a window index, which Pane does it belong to, and which index within that Pane
    func coordinates(at windowIndex: UInt) -> (Pane, UInt) {
        let pane = self.pane(ofIndex: windowIndex)
        return (pane, windowIndex - firstIndex(pane))
    }

    // Get the (height, width) dimensions for a window in the given Pane
    func windowDimensions(inPane pane: Pane) -> (CGFloat, CGFloat) {
        return (height(pane), width(pane))
    }

    // Get the Column assignment for the given Pane
    func column(ofPane pane: Pane) -> Column {
        return panePosition[pane]!
    }

    func pane(ofColumn column: Column) -> Pane {
        return columnDesignation[column]!
    }

    // Get the column widths in the order (left, middle, right)
    func widthsLeftToRight() -> (CGFloat, CGFloat, CGFloat) {
        return (width(pane(ofColumn: .left)), width(pane(ofColumn: .middle)), width(pane(ofColumn: .right)))
    }
}

final class ThreeColumnReflowOperation: ReflowOperation {
    private let layout: ThreeColumnLayout & MainColumnSpecifier

    fileprivate init(screen: NSScreen, windows: [SIWindow], layout: ThreeColumnLayout & MainColumnSpecifier & FrameAssigner) {
        self.layout = layout
        super.init(screen: screen, windows: windows, frameAssigner: layout)
    }

    func frameAssignments() -> [FrameAssignment] {
