From 194f774519e084d1eb792ba94c4a84a8daa92bba Mon Sep 17 00:00:00 2001 From: Peter Fajdiga Date: Sat, 12 Oct 2024 16:38:20 +0200 Subject: [PATCH] Actions: columns-squeeze-*: squeeze all visible columns --- src/lib/keyBindings/Actions.ts | 94 ++++++++++++++++------------- src/lib/keyBindings/definition.ts | 26 ++++---- src/tests/flows/columnShrinkSide.ts | 15 +++-- 3 files changed, 76 insertions(+), 59 deletions(-) diff --git a/src/lib/keyBindings/Actions.ts b/src/lib/keyBindings/Actions.ts index ccfcf1a..6a721e1 100644 --- a/src/lib/keyBindings/Actions.ts +++ b/src/lib/keyBindings/Actions.ts @@ -184,48 +184,70 @@ class Actions { this.config.columnResizer.decreaseWidth(column, this.config.manualResizeStep); } - public readonly columnShrinkLeft = (cm: ClientManager, dm: DesktopManager, window: Window, focusedColumn: Column, grid: Grid) => { - const visibleRange = grid.desktop.getCurrentVisibleRange(); - if (!focusedColumn.isVisible(visibleRange, true)) { + public readonly cyclePresetWidths = (cm: ClientManager, dm: DesktopManager, window: Window, column: Column, grid: Grid) => { + if (this.config.presetWidths === null) { return; } - - const visibleColumns: Column[] = []; - for (const visibleColumn of grid.getVisibleColumns(visibleRange, true)) { - visibleColumns.push(visibleColumn); - if (visibleColumn === focusedColumn) { - break; - } - } - console.assert(visibleColumns.length > 0, "should at least contain the focused column"); - - const targetColumn = grid.getLeftColumn(visibleColumns[0]); - if (targetColumn === null) { - return; - } - - this.squeezeColumns([targetColumn, ...visibleColumns]); + const nextWidth = this.config.presetWidths.next(column.getWidth(), column.getMinWidth(), column.getMaxWidth()); + column.setWidth(nextWidth, true); } - public readonly columnShrinkRight = (cm: ClientManager, dm: DesktopManager, window: Window, focusedColumn: Column, grid: Grid) => { + public readonly columnsWidthEqualize = (cm: ClientManager, dm: DesktopManager) => { + dm.getCurrentDesktop().equalizeVisibleColumnsWidths(); + } + + public readonly columnsSqueezeLeft = (cm: ClientManager, dm: DesktopManager, window: Window, focusedColumn: Column, grid: Grid) => { const visibleRange = grid.desktop.getCurrentVisibleRange(); if (!focusedColumn.isVisible(visibleRange, true)) { return; } - const visibleColumns: Column[] = [focusedColumn]; - for (const visibleColumn of grid.getVisibleColumns(visibleRange, true)) { - if (visibleColumn.isToTheRightOf(focusedColumn)) { - visibleColumns.push(visibleColumn); - } - } + const currentVisibleColumns = Array.from(grid.getVisibleColumns(visibleRange, true)); + console.assert(currentVisibleColumns.includes(focusedColumn), "should at least contain the focused column"); - const targetColumn = grid.getRightColumn(visibleColumns[visibleColumns.length-1]); + const targetColumn = grid.getLeftColumn(currentVisibleColumns[0]); if (targetColumn === null) { return; } - this.squeezeColumns([...visibleColumns, targetColumn]); + const wantedVisibleColumns = [targetColumn, ...currentVisibleColumns]; + while (true) { + const success = this.squeezeColumns(wantedVisibleColumns); + if (success) { + break; + } + const removedColumn = wantedVisibleColumns.pop(); + if (removedColumn === focusedColumn) { + break; // don't scroll past the currently focused column + } + } + } + + public readonly columnsSqueezeRight = (cm: ClientManager, dm: DesktopManager, window: Window, focusedColumn: Column, grid: Grid) => { + const visibleRange = grid.desktop.getCurrentVisibleRange(); + if (!focusedColumn.isVisible(visibleRange, true)) { + return; + } + + const currentVisibleColumns = Array.from(grid.getVisibleColumns(visibleRange, true)); + console.assert(currentVisibleColumns.includes(focusedColumn), "should at least contain the focused column"); + + const targetColumn = grid.getRightColumn(currentVisibleColumns[currentVisibleColumns.length-1]); + if (targetColumn === null) { + return; + } + + const wantedVisibleColumns = [...currentVisibleColumns, targetColumn]; + while (true) { + const success = this.squeezeColumns(wantedVisibleColumns); + if (success) { + break; + } + const removedColumn = wantedVisibleColumns.shift(); + if (removedColumn === focusedColumn) { + break; // don't scroll past the currently focused column + } + } } private readonly squeezeColumns = (columns: Column[]) => { @@ -239,14 +261,14 @@ class Actions { if (missingSpace <= 0) { // just scroll desktop.scrollCenterRange(Desktop.RangeImpl.fromRanges(firstColumn, lastColumn)); - return; + return true; } const gainableSpacePerColumn = columns.map(column => column.getWidth() - column.getMinWidth()); const gainableSpaceTotal = sum(...gainableSpacePerColumn); if (gainableSpaceTotal < missingSpace) { // there's nothing we can do - return; + return false; } const shrinkRatio = missingSpace / gainableSpaceTotal; @@ -257,18 +279,8 @@ class Actions { } lastColumn.adjustWidth(-missingSpace, true); desktop.scrollCenterRange(Desktop.RangeImpl.fromRanges(firstColumn, lastColumn)); - } - public readonly cyclePresetWidths = (cm: ClientManager, dm: DesktopManager, window: Window, column: Column, grid: Grid) => { - if (this.config.presetWidths === null) { - return; - } - const nextWidth = this.config.presetWidths.next(column.getWidth(), column.getMinWidth(), column.getMaxWidth()); - column.setWidth(nextWidth, true); - } - - public readonly columnsWidthEqualize = (cm: ClientManager, dm: DesktopManager) => { - dm.getCurrentDesktop().equalizeVisibleColumnsWidths(); + return true; } public readonly gridScrollLeft = (cm: ClientManager, dm: DesktopManager) => { diff --git a/src/lib/keyBindings/definition.ts b/src/lib/keyBindings/definition.ts index 2dcbe5d..fb22b0e 100644 --- a/src/lib/keyBindings/definition.ts +++ b/src/lib/keyBindings/definition.ts @@ -146,19 +146,6 @@ function getKeyBindings(world: World, actions: Actions): KeyBinding[] { defaultKeySequence: "Meta+Ctrl+-", action: () => world.doIfTiledFocused(actions.columnWidthDecrease), }, - { - name: "column-shrink-left", - description: "Give room left", - comment: "Clashes with default KDE shortcuts, may require manual remapping", - defaultKeySequence: "Meta+Ctrl+A", - action: () => world.doIfTiledFocused(actions.columnShrinkLeft), - }, - { - name: "column-shrink-right", - description: "Give room right", - defaultKeySequence: "Meta+Ctrl+D", - action: () => world.doIfTiledFocused(actions.columnShrinkRight), - }, { name: "cycle-preset-widths", description: "Cycle through preset column widths", @@ -171,6 +158,19 @@ function getKeyBindings(world: World, actions: Actions): KeyBinding[] { defaultKeySequence: "Meta+Ctrl+X", action: () => world.do(actions.columnsWidthEqualize), }, + { + name: "columns-squeeze-left", + description: "Squeeze left column onto the screen", + comment: "Clashes with default KDE shortcuts, may require manual remapping", + defaultKeySequence: "Meta+Ctrl+A", + action: () => world.doIfTiledFocused(actions.columnsSqueezeLeft), + }, + { + name: "columns-squeeze-right", + description: "Squeeze right column onto the screen", + defaultKeySequence: "Meta+Ctrl+D", + action: () => world.doIfTiledFocused(actions.columnsSqueezeRight), + }, { name: "grid-scroll-focused", description: "Center focused window", diff --git a/src/tests/flows/columnShrinkSide.ts b/src/tests/flows/columnShrinkSide.ts index 74ecbbb..9a02019 100644 --- a/src/tests/flows/columnShrinkSide.ts +++ b/src/tests/flows/columnShrinkSide.ts @@ -1,4 +1,4 @@ -tests.register("column shrink left", 1, () => { +tests.register("columns squeeze side", 1, () => { const baseTestCases = [ { widths: [500, 500], blocked: [false, false], possible: true }, { widths: [500, 768], blocked: [false, false], possible: true }, @@ -12,7 +12,7 @@ tests.register("column shrink left", 1, () => { const testCasesLeft = baseTestCases.map((baseTestCase, i) => ({ ...baseTestCase, name: "left " + i, - action: "karousel-column-shrink-left", + action: "karousel-columns-squeeze-left", focus: baseTestCase.widths.length-1, })); @@ -21,7 +21,7 @@ tests.register("column shrink left", 1, () => { widths: baseTestCase.widths.slice().reverse(), blocked: baseTestCase.blocked.slice().reverse(), name: "right " + i, - action: "karousel-column-shrink-right", + action: "karousel-columns-squeeze-right", focus: 0, })); @@ -60,17 +60,22 @@ tests.register("column shrink left", 1, () => { } }); -tests.register("column shrink left (just scroll)", 1, () => { +tests.register("columns squeeze left (just scroll)", 1, () => { const config = getDefaultConfig(); const { qtMock, workspaceMock, world } = init(config); const [ clientLeft, clientMiddle, clientRight ] = workspaceMock.createClientsWithWidths(300, 300, 300); + const minSize = new MockQmlSize(300, 100); + clientLeft.minSize = minSize; + clientMiddle.minSize = minSize; + clientRight.minSize = minSize; + workspaceMock.activeWindow = clientMiddle; Assert.notFullyVisible(clientLeft.frameGeometry); Assert.fullyVisible(clientMiddle.frameGeometry); Assert.fullyVisible(clientRight.frameGeometry); - qtMock.fireShortcut("karousel-column-shrink-left"); + qtMock.fireShortcut("karousel-columns-squeeze-left"); Assert.fullyVisible(clientLeft.frameGeometry); Assert.fullyVisible(clientMiddle.frameGeometry); Assert.notFullyVisible(clientRight.frameGeometry);