diff --git a/src/config/bismuth_config.kcfg b/src/config/bismuth_config.kcfg
index f4e57ede..67799221 100644
--- a/src/config/bismuth_config.kcfg
+++ b/src/config/bismuth_config.kcfg
@@ -43,6 +43,11 @@
false
+
+
+ true
+
+
false
diff --git a/src/core/ts-proxy.cpp b/src/core/ts-proxy.cpp
index 0fa25a9f..fdfd9278 100644
--- a/src/core/ts-proxy.cpp
+++ b/src/core/ts-proxy.cpp
@@ -54,6 +54,7 @@ QJSValue TSProxy::jsConfig()
addLayout("enableQuarterLayout", "QuarterLayout");
addLayout("enableFloatingLayout", "FloatingLayout");
addLayout("enableCascadeLayout", "CascadeLayout");
+ addLayout("enableSlabsLayout", "SlabsLayout");
setProp("monocleMaximize", m_config.monocleMaximize());
setProp("maximizeSoleTile", m_config.maximizeSoleTile());
diff --git a/src/kcm/package/contents/ui/views/Layouts.qml b/src/kcm/package/contents/ui/views/Layouts.qml
index cd59dc1d..442a272e 100644
--- a/src/kcm/package/contents/ui/views/Layouts.qml
+++ b/src/kcm/package/contents/ui/views/Layouts.qml
@@ -52,6 +52,11 @@ Kirigami.Page {
settingName: "enableQuarterLayout"
}
+ ListElement {
+ name: "Slabs"
+ settingName: "enableSlabsLayout"
+ }
+
ListElement {
name: "Floating"
settingName: "enableFloatingLayout"
diff --git a/src/kwinscript/controller/action.ts b/src/kwinscript/controller/action.ts
index c83da63f..5143c9ff 100644
--- a/src/kwinscript/controller/action.ts
+++ b/src/kwinscript/controller/action.ts
@@ -570,6 +570,19 @@ export class ToggleSpiralLayout extends ToggleCurrentLayout {
}
}
+export class ToggleSlabsLayout extends ToggleCurrentLayout {
+ constructor(protected engine: Engine, protected log: Log) {
+ super(
+ engine,
+ "SlabsLayout",
+ "toggle_slabs_layout",
+ "Toggle Slabs Layout",
+ "",
+ log
+ );
+ }
+}
+
export class Rotate extends ActionImpl implements Action {
constructor(protected engine: Engine, protected log: Log) {
super(engine, "rotate", "Rotate", "Meta+R", log);
diff --git a/src/kwinscript/controller/index.ts b/src/kwinscript/controller/index.ts
index aae1af0d..e6c1393c 100644
--- a/src/kwinscript/controller/index.ts
+++ b/src/kwinscript/controller/index.ts
@@ -424,6 +424,7 @@ export class ControllerImpl implements Controller {
new Action.ToggleFloatingLayout(this.engine, this.log),
new Action.ToggleQuarterLayout(this.engine, this.log),
new Action.ToggleSpiralLayout(this.engine, this.log),
+ new Action.ToggleSlabsLayout(this.engine, this.log),
new Action.Rotate(this.engine, this.log),
new Action.RotateReverse(this.engine, this.log),
diff --git a/src/kwinscript/engine/layout/slabs_layout.ts b/src/kwinscript/engine/layout/slabs_layout.ts
new file mode 100644
index 00000000..874f0061
--- /dev/null
+++ b/src/kwinscript/engine/layout/slabs_layout.ts
@@ -0,0 +1,83 @@
+// SPDX-FileCopyrightText: 2022 Joe Dean
+//
+// SPDX-License-Identifier: MIT
+
+import { WindowsLayout } from ".";
+
+import { WindowState, EngineWindow } from "../window";
+
+import { Rect } from "../../util/rect";
+import { Config } from "../../config";
+import { Controller } from "../../controller";
+
+/* "Slabs" stacks up to 5 windows bottom-to-top (ideal for vertically-rotated
+monitors). It shares the available space equally between windows; if there are
+more than 2 windows, the "first" window will be given 50% more than the others*/
+export default class SlabsLayout implements WindowsLayout {
+ public static readonly id = "SlabsLayout";
+ public readonly classID = SlabsLayout.id;
+ public readonly name = "Slabs Layout";
+ public readonly icon = "bismuth-slabs";
+ public readonly capacity = 3;
+
+ private config: Config;
+
+ public constructor(config: Config) {
+ this.config = config;
+ }
+
+ public clone(): WindowsLayout {
+ return new SlabsLayout(this.config);
+ }
+
+ public apply(
+ _controller: Controller,
+ tileables: EngineWindow[],
+ area: Rect
+ ): void {
+ if (tileables.length <= 0) {
+ return;
+ }
+
+ const tileCount = Math.min(this.capacity, tileables.length);
+ let tileSize =
+ (area.height - Math.max(0, tileCount - 1) * this.config.tileLayoutGap) /
+ tileCount;
+ let firstTileSize = tileSize;
+ if (tileCount > 2) {
+ firstTileSize *= 1.5;
+ tileSize =
+ (area.height - firstTileSize - tileCount * this.config.tileLayoutGap) /
+ (tileCount - 1);
+ }
+
+ let xPos = 0;
+ for (let i = 0; i < tileCount; i++) {
+ const currentTileSize = i == 0 ? firstTileSize : tileSize;
+ tileables[i].geometry = new Rect(
+ area.x,
+ area.height - (xPos + currentTileSize),
+ area.width,
+ currentTileSize
+ );
+ xPos += this.config.tileLayoutGap + currentTileSize;
+ }
+ for (let i = 0; i < tileables.length; i++) {
+ if (i < tileCount) {
+ tileables[i].state = WindowState.Tiled;
+ } else {
+ tileables[i].state = WindowState.TiledAfloat;
+ tileables[i].geometry = new Rect(
+ area.x,
+ area.y,
+ area.width,
+ area.height
+ );
+ }
+ }
+ }
+
+ public toString(): string {
+ return "SlabsLayout()";
+ }
+}
diff --git a/src/kwinscript/engine/layout_store.ts b/src/kwinscript/engine/layout_store.ts
index 8d1e8a68..4d765931 100644
--- a/src/kwinscript/engine/layout_store.ts
+++ b/src/kwinscript/engine/layout_store.ts
@@ -19,6 +19,7 @@ import SpiralLayout from "./layout/spiral_layout";
import SpreadLayout from "./layout/spread_layout";
import StairLayout from "./layout/stair_layout";
import ThreeColumnLayout from "./layout/three_column_layout";
+import SlabsLayout from "./layout/slabs_layout";
export class LayoutStoreEntry {
public get currentLayout(): WindowsLayout {
@@ -96,6 +97,8 @@ export class LayoutStoreEntry {
return new ThreeColumnLayout(this.config);
} else if (id == TileLayout.id) {
return new TileLayout(this.config);
+ } else if (id == SlabsLayout.id) {
+ return new SlabsLayout(this.config);
} else {
return new FloatingLayout();
}
diff --git a/src/kwinscript/icons/16-status-bismuth-slabs.svg b/src/kwinscript/icons/16-status-bismuth-slabs.svg
new file mode 100644
index 00000000..59fc9017
--- /dev/null
+++ b/src/kwinscript/icons/16-status-bismuth-slabs.svg
@@ -0,0 +1,13 @@
+
+
diff --git a/src/kwinscript/icons/32-status-bismuth-slabs.svg b/src/kwinscript/icons/32-status-bismuth-slabs.svg
new file mode 100644
index 00000000..16167003
--- /dev/null
+++ b/src/kwinscript/icons/32-status-bismuth-slabs.svg
@@ -0,0 +1,13 @@
+
+
diff --git a/src/kwinscript/icons/CMakeLists.txt b/src/kwinscript/icons/CMakeLists.txt
index 0c73ca01..12253e98 100644
--- a/src/kwinscript/icons/CMakeLists.txt
+++ b/src/kwinscript/icons/CMakeLists.txt
@@ -7,6 +7,7 @@ ecm_install_icons(
16-status-bismuth-floating.svg
16-status-bismuth-monocle.svg
16-status-bismuth-quarter.svg
+ 16-status-bismuth-slabs.svg
16-status-bismuth-spiral.svg
16-status-bismuth-spread.svg
16-status-bismuth-stair.svg
@@ -15,6 +16,7 @@ ecm_install_icons(
32-status-bismuth-floating.svg
32-status-bismuth-monocle.svg
32-status-bismuth-quarter.svg
+ 32-status-bismuth-slabs.svg
32-status-bismuth-spiral.svg
32-status-bismuth-spread.svg
32-status-bismuth-stair.svg