shift-shell/tests/check-dynamic-tiles-motion.sh
Marco Allegretti 75b9049a8c Page dynamic tiles by workspace
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.
2026-05-20 09:38:37 +02:00

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'