Created
April 2, 2026 20:52
-
-
Save mariushelf/f5b5028b0e78298c0064c7cf657340ae to your computer and use it in GitHub Desktop.
Cycle window through KDE tiles
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # Cycle the active window through available KWin Meta+T tiling spots | |
| # | |
| # KDE allows to tile windows to the left/right/top bottom with Meta+Left, Right, Top, Bottom. | |
| # With the Meta+T shortcut you can define custom tiles, e.g. a 3-column layout. However it is not | |
| # possible to move a window to a certain tile with a shortcut. | |
| # This is what this script helps with: it moves the active window to the "next" tile. | |
| # | |
| # Usage: cycle-window-tile [index] | |
| # index — move directly to this tile (0-based); logs error if out of range. If omitted, | |
| # cycle through tiles. | |
| # | |
| # Assigning a shortcut: | |
| # 1. place this script into `~/.local/bin/cycle-window-tile` | |
| # 2. in KDE System Settings -> Keyboard -> Shortcuts -> Add New -> Command or script | |
| # 3. set Command to `cycle-window-tile` | |
| # 4. assign a shortcut to the command, e.g. `Meta+Shift+K` | |
| TARGET_INDEX=-1 | |
| if [[ $# -ge 1 ]]; then | |
| if [[ ! "$1" =~ ^[0-9]+$ ]]; then | |
| echo "cycle-window-tile: invalid argument '$1': must be a non-negative integer" >&2 | |
| exit 1 | |
| fi | |
| TARGET_INDEX="$1" | |
| fi | |
| SCRIPT_JS=$(mktemp /tmp/kwin_tile_XXXXXX.js) | |
| cat > "$SCRIPT_JS" << JSEOF | |
| var screen = workspace.activeScreen; | |
| var tm = workspace.tilingForScreen(screen); | |
| var win = workspace.activeWindow; | |
| var targetIndex = ${TARGET_INDEX}; | |
| if (!win) { | |
| print("kwin-tile-cycle: no active window"); | |
| } else if (!tm || !tm.rootTile || !tm.rootTile.tiles || tm.rootTile.tiles.length < 1) { | |
| print("kwin-tile-cycle: no tiling layout found"); | |
| } else { | |
| var tiles = tm.rootTile.tiles; | |
| var nextIndex; | |
| if (targetIndex >= 0) { | |
| if (targetIndex >= tiles.length) { | |
| print("kwin-tile-cycle: index " + targetIndex + " out of range (0-" + (tiles.length - 1) + ")"); | |
| } else { | |
| nextIndex = targetIndex; | |
| } | |
| } else { | |
| var currentIndex = -1; | |
| for (var i = 0; i < tiles.length; i++) { | |
| if (win.tile === tiles[i]) { currentIndex = i; break; } | |
| } | |
| nextIndex = (currentIndex + 1) % tiles.length; | |
| } | |
| if (nextIndex !== undefined) { | |
| win.tile = tiles[nextIndex]; | |
| print("kwin-tile-cycle: moved '" + win.caption + "' to tile " + nextIndex); | |
| } | |
| } | |
| JSEOF | |
| PLUGIN_NAME="kwin_tile_middle_$$" | |
| SCRIPT_ID=$(qdbus6 org.kde.KWin /Scripting org.kde.kwin.Scripting.loadScript "$SCRIPT_JS" "$PLUGIN_NAME" 2>&1) | |
| qdbus6 org.kde.KWin "/Scripting/Script${SCRIPT_ID}" org.kde.kwin.Script.run 2>/dev/null | |
| qdbus6 org.kde.KWin /Scripting org.kde.kwin.Scripting.unloadScript "$PLUGIN_NAME" 2>/dev/null | |
| rm -f "$SCRIPT_JS" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment