mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-06-11 16:57:43 +00:00
Keep one layout per output and virtual desktop. Move new windows to another existing desktop when the current page is full. When a user moves a window onto a full page, replace the last focused window on that page and send it back to the source desktop. Use stable slot swaps instead of insert splits so the layout shape does not change during moves.
118 lines
No EOL
6.3 KiB
Bash
118 lines
No EOL
6.3 KiB
Bash
#!/usr/bin/env bash
|
|
# SPDX-FileCopyrightText: 2026 Marco Allegretti <mightymarco4@gmail.com>
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
set -euo pipefail
|
|
|
|
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
|
|
effect_qml="$repo_root/kwin/effects/shift-tile-preview/contents/ui/main.qml"
|
|
effect_metadata="$repo_root/kwin/effects/shift-tile-preview/metadata.json"
|
|
effects_cmake="$repo_root/kwin/effects/CMakeLists.txt"
|
|
tiling_script="$repo_root/kwin/scripts/shift-tiling/contents/ui/main.qml"
|
|
env_config="$repo_root/envmanager/config.h"
|
|
|
|
require_line() {
|
|
local file="$1"
|
|
local needle="$2"
|
|
|
|
if ! grep -Fq -- "$needle" "$file"; then
|
|
echo "Missing dynamic tile motion invariant in ${file#$repo_root/}: $needle" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
reject_line() {
|
|
local file="$1"
|
|
local needle="$2"
|
|
|
|
if grep -Fq -- "$needle" "$file"; then
|
|
echo "Rejected dynamic tile motion pattern in ${file#$repo_root/}: $needle" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
require_line "$effects_cmake" "add_kwin_effect(shift-tile-preview shift-tile-preview)"
|
|
require_line "$effect_metadata" '"Id": "shift-tile-preview"'
|
|
require_line "$effect_metadata" '"X-Plasma-API": "declarativescript"'
|
|
|
|
require_line "$env_config" '{"shift-tilingEnabled", convergenceModeEnabled}'
|
|
require_line "$env_config" '{"shift-tile-previewEnabled", convergenceModeEnabled}'
|
|
require_line "$env_config" '"shift-tile-preview"'
|
|
require_line "$env_config" '"shift-tiling"'
|
|
|
|
require_line "$effect_qml" "KWinComponents.SceneEffect"
|
|
require_line "$effect_qml" "visible: false"
|
|
require_line "$effect_qml" "ShellSettings.Settings.dynamicTilingEnabled"
|
|
require_line "$effect_qml" "interactiveMoveResizeStarted.connect"
|
|
require_line "$effect_qml" "interactiveMoveResizeStepped.connect"
|
|
require_line "$effect_qml" "interactiveMoveResizeFinished.connect"
|
|
require_line "$effect_qml" "Behavior on x"
|
|
require_line "$effect_qml" "Behavior on y"
|
|
require_line "$effect_qml" "Behavior on width"
|
|
require_line "$effect_qml" "Behavior on height"
|
|
require_line "$effect_qml" "showPreview(\"swap\""
|
|
require_line "$effect_qml" "showPreview(\"float\""
|
|
require_line "$effect_qml" "showPreview(\"restore\""
|
|
|
|
require_line "$tiling_script" "readonly property int maxWindowsPerPage: 4"
|
|
require_line "$tiling_script" "readonly property real stablePrimaryRatio: 0.58"
|
|
require_line "$tiling_script" "readonly property var layoutModes: [\"master\", \"columns\", \"rows\"]"
|
|
require_line "$tiling_script" "function desktopKey(desktop)"
|
|
require_line "$tiling_script" "function desktopForWindow(win)"
|
|
require_line "$tiling_script" "function layoutKeyFor(outputName, desktop)"
|
|
require_line "$tiling_script" "function desktopForLayoutKey(outputName)"
|
|
require_line "$tiling_script" "function layoutKeyForWindow(win)"
|
|
require_line "$tiling_script" "function assignWindowToDesktop(win, desktop)"
|
|
require_line "$tiling_script" "function targetLayoutForNewWindow(win)"
|
|
require_line "$tiling_script" "function leafIndexForWindow(outputName, win)"
|
|
require_line "$tiling_script" "function leafForSlot(outputName, preferredIndex)"
|
|
require_line "$tiling_script" "property var lastFocusedWindowKeys: ({})"
|
|
require_line "$tiling_script" "function rememberFocusedWindow(win)"
|
|
require_line "$tiling_script" "function replacementLeafForLayout(outputName, fallbackIndex)"
|
|
require_line "$tiling_script" "function swapWindowBetweenLayouts(win, sourceName, targetName)"
|
|
require_line "$tiling_script" "windowCountForLayout(currentKey) < maxWindowsPerPage"
|
|
require_line "$tiling_script" "windowCountForLayout(targetName) >= maxWindowsPerPage && swapWindowBetweenLayouts(win, currentName, targetName)"
|
|
require_line "$tiling_script" "KWinComponents.Workspace.currentDesktop = target.desktop"
|
|
require_line "$tiling_script" "assignWindowToDesktop(displacedWindow, sourceDesktop)"
|
|
require_line "$tiling_script" "const targetLeaf = replacementLeafForLayout(targetName, sourceIndex)"
|
|
require_line "$tiling_script" "function onActiveWindowChanged()"
|
|
require_line "$tiling_script" "root.rememberFocusedWindow(KWinComponents.Workspace.activeWindow)"
|
|
require_line "$tiling_script" "win.desktops = [desktop]"
|
|
require_line "$tiling_script" "win.desktopsChanged.connect"
|
|
require_line "$tiling_script" "function orderedWindowsForScreen(outputName)"
|
|
require_line "$tiling_script" "function buildStableStack(windows, startIndex)"
|
|
require_line "$tiling_script" "function buildLinearLayout(windows, startIndex, orientation)"
|
|
require_line "$tiling_script" "function layoutModeForScreen(outputName)"
|
|
require_line "$tiling_script" "function buildStableLayout(windows, mode)"
|
|
require_line "$tiling_script" "function setStableLayout(outputName, windows)"
|
|
require_line "$tiling_script" "function cycleLayoutMode(outputName)"
|
|
require_line "$tiling_script" "function swapDraggedWindow(target)"
|
|
require_line "$tiling_script" "showDragOutline(\"swap\", target.rect)"
|
|
require_line "$tiling_script" "swapDraggedWindow(dragSwapTarget)"
|
|
require_line "$tiling_script" "setStableLayout(outputName, windows)"
|
|
require_line "$tiling_script" "setStableLayout(outputName, remaining)"
|
|
require_line "$tiling_script" "retileScreen(name)"
|
|
require_line "$tiling_script" "retileScreen(targetName)"
|
|
require_line "$tiling_script" "function promoteWindow(win)"
|
|
require_line "$tiling_script" "setStableLayout(outputName, reordered)"
|
|
require_line "$tiling_script" "name: \"SHIFT Tiling Promote Primary\""
|
|
require_line "$tiling_script" "sequence: \"Meta+Shift+Return\""
|
|
require_line "$tiling_script" "name: \"SHIFT Tiling Cycle Layout\""
|
|
require_line "$tiling_script" "sequence: \"Meta+Shift+T\""
|
|
|
|
reject_line "$tiling_script" "targetKey = lastLeafKey(rootNode)"
|
|
reject_line "$tiling_script" "function lastLeafKey(node)"
|
|
reject_line "$tiling_script" "win.output.name !== outputName"
|
|
reject_line "$tiling_script" "const targetName = output.name"
|
|
reject_line "$tiling_script" "const desktop = win.desktops[0]"
|
|
reject_line "$tiling_script" "setScreenLayout(outputName, splitLeaf(rootNode, targetKey"
|
|
reject_line "$tiling_script" "function moveWindowToSplit(target)"
|
|
reject_line "$tiling_script" "function splitLeaf(node, targetKey"
|
|
reject_line "$tiling_script" "function tileInsertDirection(cursor, rect)"
|
|
reject_line "$tiling_script" "showDragOutline(\"insert\""
|
|
reject_line "$tiling_script" "KWinComponents.Workspace.showOutline(dragOutlineRect)"
|
|
reject_line "$tiling_script" "KWinComponents.Workspace.hideOutline()"
|
|
reject_line "$effect_qml" "effect.visible = true"
|
|
|
|
printf '%s\n' 'dynamic-tiles-motion-ok' |