- QML 51.4%
- JavaScript 35.2%
- Shell 7.8%
- Python 4.6%
- Makefile 1%
The picker fix in |
||
|---|---|---|
| docs | ||
| experiments | ||
| LICENSES | ||
| src | ||
| .gitignore | ||
| LICENSE | ||
| Makefile | ||
| README.md | ||
| REUSE.toml | ||
tactile-kde
A keyboard-driven window tiler for KDE Plasma 6 on Wayland — a port of the GNOME Shell extension Tactile to KWin.
Press
Alt+Rto show a grid over the current screen, then type two tile keys (or the same key twice) to move and resize the focused window into the rectangle spanned by those two tiles.
Status: working, tested in a nested compositor; not yet run in a real session. See docs/DESIGN.md for the port design and the evidence behind it.
make install # package + install via kpackagetool6
make enable # or: System Settings -> Desktop Effects -> Tactile
./experiments/run-tests.sh # drive it in a nested compositor; never touches your session
OUTPUTS=2 ./experiments/run-tests.sh # same, with two virtual monitors
./experiments/run-probe.sh # the original API probe (docs/DESIGN.md section 13)
Why this exists
Tactile's interaction model is "show a grid, type two corners". Nothing on Plasma offers exactly that:
- KWin's built-in custom tiling (
Meta+Ttile editor) snaps with the mouse, or withMeta+arrow keys through a fixed quarter/half layout. - MouseTiler is the closest existing KWin
script, but it is pointer-driven by design: its overlay is created with
Qt.WindowTransparentForInputand it tracksWorkspace.cursorPos, so the keyboard is never grabbed.
Reproducing Tactile means holding a modal keyboard grab while an overlay is on screen. On Plasma that is something only a KWin effect can do, which drives the whole design.
Planned behaviour
| Key | Action |
|---|---|
Alt+R |
Show / hide the grid |
Meta+Shift+T |
Open the layout editor (from anywhere) |
, |
Open the layout editor (while the grid is showing) |
Esc |
Cancel, or close the editor |
tile key (Q W E R / A S D F / Z X C V by default) |
Pick a corner; two picks commit |
Space / Shift+Space |
Move the grid to the next / previous monitor |
1–4 |
Switch the current monitor to layout 1–4 |
Multiple monitors
Space and Shift+Space walk the grid to the next and previous monitor, wrapping, in the
order your outputs are arranged. The grid moves, not the window — the window follows when
you pick two tiles, landing on whichever monitor the grid is on. Each monitor remembers which
layout it was last using, so one screen can be on a 2×1 split while another is on 4×3.
Each of the four layouts is a table of up to 7 columns × 5 rows, with one key per cell — a
letter, or a combination such as Shift+A or Ctrl+Period when the letters run out. Rows
and columns carry an integer weight, so tiles can be uneven; a weight of 0 hides that row
or column without shifting the keys either side of it. Each monitor remembers which layout it
last used. Gap size, border size, text size and colours are configurable, with an option to
follow the system accent colour.
Try it without touching your session
./experiments/run-nested.sh
Opens a second compositor in a window on your desktop, with Tactile installed into a
throwaway HOME and its own D-Bus session, so Alt+R there never collides with your real
shortcuts. Click into the window and press Alt+R. Close the window to end it.
This is the recommended first run: it is the only way to exercise real keystrokes through the keyboard grab without risking your live compositor.
Install for real
make install
make enable
To update an installed copy after pulling or editing, disable it first:
make disable && make install && make enable
make install on an already-installed package replaces its files in place, and doing that
under a loaded scene effect is the same risk make uninstall goes out of its way to avoid.
It also would not take effect: KWin keeps running the QML it already loaded until the effect
is unloaded and loaded again, and make enable alone reloads nothing when the effect was
already enabled.
Then find Tactile under System Settings → Window Management → Desktop Effects. It is an effect, not a script, so it does not appear under KWin Scripts — that is deliberate: only an effect can hold the keyboard grab that bare letter keys need.
To remove it:
make uninstall
That disables the effect and waits for KWin to unload it before deleting the files —
removing a loaded scene effect out from under a running compositor is a good way to crash
kwin_wayland, so don't just rm -rf the package directory.
Changing the shortcut
Alt+R is only the default. Once the effect has been enabled at least once, it registers
itself with KWin's global shortcut system, so rebind it in
System Settings → Shortcuts → KWin → "Tactile: show tiling grid". Your binding is stored
in kglobalshortcutsrc and takes precedence from then on.
There is intentionally no shortcut setting in kwinrc: KGlobalAccel already owns this, and a
config entry would silently lose to whatever you set in System Settings.
Note that Alt+R is grabbed globally, so it will shadow any application that uses Alt+R
as a menu accelerator. Rebind if that bites.
Settings
The layout editor
Press , while the grid is showing, or Meta+Shift+T from anywhere.
The editor draws over the grid, and the grid redraws as you type, so you are looking at the result while you make it:
┌ Tactile grid layouts ────────────────── 1 │ 2 │ 3 │ 4 ┐
│ Columns: 4 Rows: 2 │
│ │
│ 1 1 1 1 │
│ 1 │ Q ││ W ││ E ││ R │ │
│ 1 │Shift+A││ S ││ D ││ F │ │
│ │
│ Gap between tiles: 0 Reset this layout Done │
└────────────────────────────────────────────────────────┘
Set Columns and Rows, and the table resizes to match — that size is the layout's
size, stored on its own, not inferred from anything you type. Then put one key in each cell:
that is the key which picks that tile. A cell takes a letter, a named key (Space, F5,
Period, …), or a combination — Shift+A, Ctrl+Period, Meta+Q — so a table can reach
past the letters you have. The tile is labelled with its modifiers set small above the key.
The numbers down the left and across the top are each row's and column's share of the
screen; 0 hides that row or column. A cell is outlined in red if its key is used twice
(only the first such cell can be picked) or if what you typed is not a key at all.
1–4 at the top right pick which layout you are editing, and switch the grid behind the
editor to that layout too, so the preview is always the table you are editing. The grid stays
on the last layout you edited after you close the editor, just as if you had pressed that
number key. Tab moves from cell to cell. Every field applies immediately and is saved when
you close the editor.
Done (or Escape) closes the editor. If you opened it over a grid you were already
using, you are put back on that grid; if you opened it with Meta+Shift+T, the overlay
closes with it.
This lives in the grid rather than in System Settings because the System Settings page is a fixed Qt Designer form with no code behind it, and a table that resizes with a spin box cannot be expressed there.
Everything else
System Settings → Window Management → Desktop Effects → Tactile → ⚙ — colours, sizes, dimming, the in-overlay control keys, and the behaviour options.
The two trigger shortcuts are deliberately not there: they are global shortcuts owned by KGlobalAccel, so they live in System Settings → Shortcuts → KWin (see Changing the shortcut above). Everything else is a key read while the effect holds the keyboard grab, which is why it is an effect setting instead.
Cycling between monitors
Keys tab → Next monitor / Previous monitor. Defaults are Space and Shift+Space.
Editing by hand
Settings are written to kwinrc under [Effect-tactile], so you can equally set them
directly — after which qdbus org.kde.KWin /KWin reconfigure applies them without a
restart. Each layout is a size plus four lists, and KConfig splits the lists on commas:
[Effect-tactile]
L1Cols=4
L1Rows=2
L1ColWeights=1,1,1,1
L1RowWeights=1,1
L1KeyRow0=q,w,e,r
L1KeyRow1=a,s,d,f
So a Dvorak or Colemak layout is a few lines per layout. A row list may be shorter than the table is wide; cells with no key are simply unreachable. Note that KConfig omits any entry that still matches its default, so a freshly reset layout writes nothing at all.
Every key in this file — the tile keys above and the control keys below — takes an optional
Shift+ / Ctrl+ / Alt+ / Meta+ modifier plus a named key (Space, Escape, Tab,
Return, Backspace, F1–F12, arrows, Comma, Period, Slash, Plus, …) or any
single character. (+ itself has to be spelled Plus, since it is the separator.) A tile
row may therefore read L1KeyRow0=Shift+q,Ctrl+w,e,r. The control keys may each list
several alternatives:
KeyCancel=Escape Backspace
KeyNextMonitor=Space Tab
KeyPrevMonitor=Shift+Space
KeySettings=Comma
KeyLayout1=1
KeyLayout4=4
Control keys match modifiers exactly, which is what keeps Space and Shift+Space
distinct. Tile keys are matched in two passes — the cells that name modifiers first, then
the ones that do not — so Shift+A and a can sit in the same table and each pick its own
tile, wherever they are in it. A cell that names no modifiers still ignores Shift, so Caps
Lock will not stop a tile being picked, but it no longer answers to Ctrl, Alt or Meta.
The full list of settings and defaults is in docs/DESIGN.md § 8.
Development
Never load, unload or test this package in your live Plasma session — unloading a
scene effect while it is active has segfaulted kwin_wayland. Use the nested-compositor
recipe in docs/DESIGN.md § Testing.
Credits
- Tactile by lundal — the original extension and the source of the interaction model, grid maths and default key map. GPL-3.0-or-later.
- MouseTiler by rxappdev — reference for KWin QML packaging, overlay rendering and window geometry handling. GPL-3.0.
License
GPL-3.0-or-later — see LICENSE.
This is a port of Tactile, which is
GPL-3.0-or-later, so this project inherits that licence. The port reimplements
Tactile's interaction model and grid arithmetic in QML/JavaScript; docs/DESIGN.md
additionally quotes KWin, which is GPL-2.0-or-later.