2026-04-13 06:37:19 +00:00
|
|
|
|
# Hacking on Shift
|
|
|
|
|
|
|
|
|
|
|
|
Shift is a convergent Plasma Mobile shell. This guide covers
|
|
|
|
|
|
building and testing it locally without polluting your host system.
|
|
|
|
|
|
|
|
|
|
|
|
The approach: keep every build dependency inside a **distrobox** container
|
|
|
|
|
|
(openSUSE Tumbleweed), and preview the shell in a **nested KWin** window
|
|
|
|
|
|
that runs on your host.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 1. Host prerequisites
|
|
|
|
|
|
|
|
|
|
|
|
You need three things installed on your host (outside the container):
|
|
|
|
|
|
|
|
|
|
|
|
| Tool | Why |
|
|
|
|
|
|
| ------------------ | ------------------------------------------ |
|
|
|
|
|
|
| `podman` | Container runtime used by distrobox. |
|
|
|
|
|
|
| `distrobox` | Manages the build container. |
|
|
|
|
|
|
| `kwin_wayland` | Launches a nested Wayland compositor for preview. |
|
|
|
|
|
|
| `dbus-run-session` | Provides a private D-Bus session to kwin. |
|
|
|
|
|
|
|
|
|
|
|
|
On Plasma desktops, `kwin_wayland` and `dbus-run-session` are already
|
|
|
|
|
|
present. For distrobox and podman, install them through your host
|
|
|
|
|
|
package manager.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 2. Create the build container
|
|
|
|
|
|
|
|
|
|
|
|
Shift builds against the latest KDE Frameworks 6, Plasma 6, and Qt 6.
|
|
|
|
|
|
openSUSE Tumbleweed tracks them closely and makes a good base.
|
|
|
|
|
|
|
|
|
|
|
|
### 2a. Work around missing `/etc/zypp/zypp.conf`
|
|
|
|
|
|
|
|
|
|
|
|
As of April 2026, the Tumbleweed container image ships without
|
|
|
|
|
|
`/etc/zypp/zypp.conf`, which causes `distrobox create` to fail during
|
|
|
|
|
|
init (zypper refuses to run without it). Create a patched image first:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
podman run --name tw-fix registry.opensuse.org/opensuse/tumbleweed:latest \
|
|
|
|
|
|
bash -c 'mkdir -p /etc/zypp && echo "## zypp.conf" > /etc/zypp/zypp.conf'
|
|
|
|
|
|
podman commit tw-fix localhost/tw-fixed:latest
|
|
|
|
|
|
podman rm tw-fix
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
> **Note:** If a future Tumbleweed image ships with the file already
|
|
|
|
|
|
> present, you can skip this step and use the upstream image directly.
|
|
|
|
|
|
|
|
|
|
|
|
### 2b. Create and initialise the distrobox
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
distrobox create --name shift-tw --image localhost/tw-fixed:latest
|
|
|
|
|
|
distrobox enter shift-tw -- echo "init ok"
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Wait for the `Container Setup Complete!` message. The container's home
|
|
|
|
|
|
directory is transparently mapped to your real `$HOME`, so the source
|
|
|
|
|
|
tree is shared between host and container.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 3. Install build dependencies
|
|
|
|
|
|
|
|
|
|
|
|
All `zypper` commands run inside the container. Either prefix them with
|
|
|
|
|
|
`distrobox enter shift-tw --` or open an interactive shell first with
|
|
|
|
|
|
`distrobox enter shift-tw`.
|
|
|
|
|
|
|
|
|
|
|
|
### Build tools and libraries
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
sudo zypper install --no-confirm \
|
|
|
|
|
|
cmake gcc-c++ ninja kf6-extra-cmake-modules \
|
|
|
|
|
|
qt6-core-devel qt6-gui-devel qt6-qml-devel qt6-quick-devel \
|
|
|
|
|
|
qt6-sensors-devel qt6-waylandclient-devel \
|
|
|
|
|
|
qt6-waylandclient-private-devel qt6-wayland-private-devel \
|
|
|
|
|
|
kf6-ki18n-devel kf6-kglobalaccel-devel kf6-kio-devel \
|
|
|
|
|
|
kf6-kconfig-devel kf6-kdbusaddons-devel kf6-kitemmodels-devel \
|
|
|
|
|
|
kf6-kservice-devel kf6-knotifications-devel kf6-kcmutils-devel \
|
|
|
|
|
|
kf6-kpackage-devel kf6-kjobwidgets-devel kf6-kwindowsystem-devel \
|
|
|
|
|
|
kf6-kauth-devel kf6-kirigami-devel kf6-ksvg-devel \
|
|
|
|
|
|
kf6-modemmanager-qt-devel kf6-networkmanager-qt-devel \
|
|
|
|
|
|
kirigami-addons6-devel libplasma6-devel plasma6-activities-devel \
|
|
|
|
|
|
libkscreen6-devel kwayland6-devel kpipewire6-devel \
|
|
|
|
|
|
kwin6-devel layer-shell-qt6-devel plasma6-workspace-devel \
|
|
|
|
|
|
plasma-wayland-protocols qcoro-qt6-devel \
|
|
|
|
|
|
libepoxy-devel libxcb-devel wayland-devel systemd-devel
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Runtime dependencies (needed for preview, not for compilation)
|
|
|
|
|
|
|
|
|
|
|
|
The nested preview runs the system `plasmashell` binary. It needs a
|
|
|
|
|
|
complete Plasma Mobile runtime so all QML imports resolve:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
sudo zypper install --no-confirm \
|
|
|
|
|
|
plasma6-mobile plasma6-workspace plasma6-nano plasma6-nm plasma6-pa \
|
|
|
|
|
|
layer-shell-qt6-imports kf6-bluez-qt-imports \
|
|
|
|
|
|
kf6-networkmanager-qt-imports \
|
|
|
|
|
|
breeze6-wallpapers plasma6-workspace-wallpapers
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 4. Configure and build
|
|
|
|
|
|
|
|
|
|
|
|
All build commands run inside the container. The source tree lives on
|
|
|
|
|
|
the host filesystem (e.g. `~/Projects/Shift`); distrobox maps it
|
|
|
|
|
|
automatically.
|
|
|
|
|
|
|
|
|
|
|
|
### Configure (first time or after CMakeLists.txt changes)
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
distrobox enter shift-tw -- bash -c '
|
|
|
|
|
|
cd ~/Projects/Shift
|
|
|
|
|
|
cmake -S . -B build-clean -G Ninja \
|
|
|
|
|
|
-DCMAKE_INSTALL_PREFIX=$PWD/.prefix \
|
2026-04-13 07:39:27 +00:00
|
|
|
|
-DCMAKE_BUILD_TYPE=Debug \
|
|
|
|
|
|
-DPLASMA_MOBILE_LOCAL_KAUTH_INSTALL=ON
|
2026-04-13 06:37:19 +00:00
|
|
|
|
'
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
`-DCMAKE_INSTALL_PREFIX=$PWD/.prefix` tells cmake to install into a
|
2026-04-13 07:39:27 +00:00
|
|
|
|
local directory instead of `/usr`.
|
|
|
|
|
|
`-DPLASMA_MOBILE_LOCAL_KAUTH_INSTALL=ON` redirects KAuth helper
|
|
|
|
|
|
executables and polkit policy files into the local prefix so that
|
|
|
|
|
|
`cmake --install` works without root. During configure, ECM auto-generates
|
2026-04-13 06:37:19 +00:00
|
|
|
|
`build-clean/prefix.sh` — a shell snippet that prepends `.prefix` paths
|
|
|
|
|
|
to `QT_PLUGIN_PATH`, `QML2_IMPORT_PATH`, `XDG_DATA_DIRS`, etc. The
|
|
|
|
|
|
preview script sources this file so the system `plasmashell` finds our
|
|
|
|
|
|
custom-built plugins first and falls back to system ones for everything
|
|
|
|
|
|
else.
|
|
|
|
|
|
|
|
|
|
|
|
### Build everything
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
distrobox enter shift-tw -- cmake --build ~/Projects/Shift/build-clean
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Or build only the homescreen applet for a faster cycle:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
distrobox enter shift-tw -- cmake --build ~/Projects/Shift/build-clean \
|
|
|
|
|
|
--target org.kde.plasma.mobile.homescreen.folio
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Install
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
distrobox enter shift-tw -- cmake --install ~/Projects/Shift/build-clean
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
This populates `.prefix/`. There is no need to install to `~/.local`
|
|
|
|
|
|
unless you also want to use the shell outside the preview window (e.g.
|
|
|
|
|
|
in a full mobile session).
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 5. Preview in a nested KWin window
|
|
|
|
|
|
|
|
|
|
|
|
The preview launches a **host** `kwin_wayland` compositor with its own
|
|
|
|
|
|
Wayland socket, then starts `plasmashell` **inside the container**
|
|
|
|
|
|
connected to that socket. The end result is a self-contained window
|
|
|
|
|
|
showing the mobile shell — no need to log out or switch sessions.
|
|
|
|
|
|
|
|
|
|
|
|
### The preview script
|
|
|
|
|
|
|
|
|
|
|
|
Create `preview.sh` in the project root:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
|
# Launch Shift in a nested KWin window for testing.
|
|
|
|
|
|
#
|
2026-04-14 05:17:51 +00:00
|
|
|
|
# kwin_wayland runs on the host (needs direct GPU access) with the project
|
|
|
|
|
|
# prefix paths so it can load the convergentwindows KWin script and resolve
|
|
|
|
|
|
# its QML imports. plasmashell runs inside the distrobox container.
|
2026-04-13 06:37:19 +00:00
|
|
|
|
#
|
|
|
|
|
|
# Usage: ./preview.sh [WIDTHxHEIGHT]
|
|
|
|
|
|
# e.g. ./preview.sh # 1280x720
|
|
|
|
|
|
# ./preview.sh 1920x1080
|
|
|
|
|
|
|
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
|
|
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
|
|
|
|
SIZE="${1:-1280x720}"
|
|
|
|
|
|
WIDTH="${SIZE%%x*}"
|
|
|
|
|
|
HEIGHT="${SIZE##*x}"
|
|
|
|
|
|
|
2026-04-14 05:17:51 +00:00
|
|
|
|
PREFIX="$SCRIPT_DIR/.prefix"
|
|
|
|
|
|
|
2026-04-13 06:37:19 +00:00
|
|
|
|
# Write an ephemeral inner launcher (kwin needs a single executable path)
|
|
|
|
|
|
INNER=$(mktemp /tmp/shift-inner.XXXXXX.sh)
|
|
|
|
|
|
chmod +x "$INNER"
|
|
|
|
|
|
trap 'rm -f "$INNER"' EXIT
|
|
|
|
|
|
|
|
|
|
|
|
cat > "$INNER" << ENDSCRIPT
|
|
|
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
|
exec distrobox enter shift-tw -- bash -c '
|
|
|
|
|
|
cd "$SCRIPT_DIR"
|
|
|
|
|
|
. ./build-clean/prefix.sh
|
|
|
|
|
|
export WAYLAND_DISPLAY=shift-kwin
|
|
|
|
|
|
export QT_QPA_PLATFORM=wayland
|
|
|
|
|
|
export QT_QPA_PLATFORMTHEME=KDE
|
|
|
|
|
|
export EGL_PLATFORM=wayland
|
|
|
|
|
|
export QT_QUICK_CONTROLS_STYLE=org.kde.breeze
|
|
|
|
|
|
export QT_QUICK_CONTROLS_MOBILE=true
|
|
|
|
|
|
export PLASMA_PLATFORM=phone:handset
|
|
|
|
|
|
export PLASMA_DEFAULT_SHELL=org.kde.plasma.mobileshell
|
|
|
|
|
|
export QT_FORCE_STDERR_LOGGING=1
|
|
|
|
|
|
exec plasmashell --replace -p org.kde.plasma.mobileshell
|
|
|
|
|
|
'
|
|
|
|
|
|
ENDSCRIPT
|
|
|
|
|
|
|
2026-04-14 05:17:51 +00:00
|
|
|
|
# Expose the project prefix to the host kwin_wayland so it can find
|
|
|
|
|
|
# KWin scripts (convergentwindows) and their QML dependencies.
|
|
|
|
|
|
# Also overlay ~/.config/plasma-mobile so KWin reads the mobile kwinrc
|
|
|
|
|
|
# (envmanager writes convergentwindowsEnabled, Placement, etc. there).
|
|
|
|
|
|
export XDG_DATA_DIRS="$PREFIX/share:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"
|
|
|
|
|
|
export XDG_CONFIG_DIRS="$HOME/.config/plasma-mobile:${XDG_CONFIG_DIRS:-/etc/xdg}"
|
|
|
|
|
|
export QT_PLUGIN_PATH="$PREFIX/lib64/plugins:${QT_PLUGIN_PATH:-}"
|
|
|
|
|
|
export QML2_IMPORT_PATH="$PREFIX/lib64/qml:${QML2_IMPORT_PATH:-}"
|
|
|
|
|
|
|
2026-04-13 06:37:19 +00:00
|
|
|
|
exec dbus-run-session \
|
|
|
|
|
|
kwin_wayland --xwayland \
|
|
|
|
|
|
--socket shift-kwin \
|
|
|
|
|
|
--width "$WIDTH" \
|
|
|
|
|
|
--height "$HEIGHT" \
|
|
|
|
|
|
--exit-with-session "$INNER"
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Make it executable: `chmod +x preview.sh`.
|
|
|
|
|
|
|
|
|
|
|
|
### How it works
|
|
|
|
|
|
|
|
|
|
|
|
1. `dbus-run-session` spins up an isolated D-Bus session so the nested
|
|
|
|
|
|
compositor doesn't clash with your running desktop.
|
2026-04-14 05:17:51 +00:00
|
|
|
|
2. Four environment exports give the **host** `kwin_wayland` access to
|
|
|
|
|
|
the project's `.prefix` (KWin scripts, QML plugins) and to
|
|
|
|
|
|
`~/.config/plasma-mobile` (where envmanager writes convergence
|
|
|
|
|
|
settings like `convergentwindowsEnabled`, `Placement`, etc.).
|
|
|
|
|
|
3. `kwin_wayland` opens a window on your current desktop and creates a
|
|
|
|
|
|
Wayland socket named `shift-kwin`. Because of the exports it can
|
|
|
|
|
|
load the `convergentwindows` script, which handles maximising
|
|
|
|
|
|
windows on undock and restoring decorations on dock.
|
|
|
|
|
|
4. The inner script enters the distrobox, sources `prefix.sh` to put
|
2026-04-13 06:37:19 +00:00
|
|
|
|
the custom build first in all search paths, then starts
|
|
|
|
|
|
`plasmashell` from the container's `/usr/bin/plasmashell` — but with
|
|
|
|
|
|
our plugins loaded from `.prefix`.
|
2026-04-14 05:17:51 +00:00
|
|
|
|
5. `--exit-with-session` makes kwin close when plasmashell exits, and
|
2026-04-13 06:37:19 +00:00
|
|
|
|
vice versa.
|
|
|
|
|
|
|
|
|
|
|
|
### Running it
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
./preview.sh # 1280×720 (default)
|
|
|
|
|
|
./preview.sh 1920x1080 # Full-HD
|
|
|
|
|
|
./preview.sh 360x720 # Narrow phone
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Close the KWin window to stop the preview.
|
|
|
|
|
|
|
|
|
|
|
|
### Convergence mode
|
|
|
|
|
|
|
|
|
|
|
|
Shift's convergence mode (desktop-style dock, auto-hide, etc.) requires
|
|
|
|
|
|
this in `~/.config/plasmamobilerc`:
|
|
|
|
|
|
|
|
|
|
|
|
```ini
|
|
|
|
|
|
[General]
|
|
|
|
|
|
convergenceModeEnabled=true
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
This file lives on the host (shared home), so just create or edit it
|
|
|
|
|
|
before running the preview.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 6. Edit – build – preview cycle
|
|
|
|
|
|
|
|
|
|
|
|
The fast loop:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 1. Edit source files on the host with your editor.
|
|
|
|
|
|
# 2. Build the changed target (runs inside the container):
|
|
|
|
|
|
distrobox enter shift-tw -- cmake --build ~/Projects/Shift/build-clean \
|
|
|
|
|
|
--target org.kde.plasma.mobile.homescreen.folio
|
|
|
|
|
|
|
|
|
|
|
|
# 3. Install:
|
|
|
|
|
|
distrobox enter shift-tw -- cmake --install ~/Projects/Shift/build-clean
|
|
|
|
|
|
|
|
|
|
|
|
# 4. Preview:
|
|
|
|
|
|
./preview.sh
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
> **Tip:** QML files installed to `.prefix/share/` or
|
|
|
|
|
|
> `.prefix/lib64/qml/` are read at runtime. For pure-QML changes you
|
|
|
|
|
|
> can skip the build step and just re-run `cmake --install` then
|
|
|
|
|
|
> restart the preview. For C++ changes you need the full build.
|
|
|
|
|
|
|
|
|
|
|
|
### Key build targets
|
|
|
|
|
|
|
|
|
|
|
|
| Target | What it builds |
|
|
|
|
|
|
| ------ | -------------- |
|
|
|
|
|
|
| *(none — full build)* | Everything: all applets, QML plugins, KCMs, quicksettings, initial-start modules. |
|
|
|
|
|
|
| `org.kde.plasma.mobile.homescreen.folio` | Folio homescreen applet (app grid, dock, folders). |
|
|
|
|
|
|
| `org.kde.plasma.mobile.panel` | Top status bar (clock, indicators). |
|
|
|
|
|
|
| `org.kde.plasma.mobile.taskpanel` | Bottom navigation / gesture panel. |
|
|
|
|
|
|
| `org.kde.plasma.mobile.homescreen.halcyon` | Halcyon homescreen (alternative to Folio). |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 7. Troubleshooting
|
|
|
|
|
|
|
|
|
|
|
|
### `plasmashell: not found`
|
|
|
|
|
|
|
|
|
|
|
|
The container needs the full `plasma6-workspace` package (which provides
|
|
|
|
|
|
`/usr/bin/plasmashell`), not just `plasma6-workspace-devel`. Install it
|
|
|
|
|
|
with `sudo zypper install plasma6-workspace`.
|
|
|
|
|
|
|
|
|
|
|
|
### `module "org.kde.foo" is not installed`
|
|
|
|
|
|
|
|
|
|
|
|
A QML import is missing. The error names the module; find the package
|
|
|
|
|
|
that provides it:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# Inside the container:
|
|
|
|
|
|
zypper se -x $(echo org.kde.foo | tr . /) # crude guess
|
|
|
|
|
|
# Or search file contents:
|
|
|
|
|
|
zypper wp /usr/lib64/qt6/qml/org/kde/foo/qmldir
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Common culprits:
|
|
|
|
|
|
|
|
|
|
|
|
| Module | Package |
|
|
|
|
|
|
| ------ | ------- |
|
|
|
|
|
|
| `org.kde.bluezqt` | `kf6-bluez-qt-imports` |
|
|
|
|
|
|
| `org.kde.plasma.networkmanagement` | `plasma6-nm` |
|
|
|
|
|
|
| `org.kde.plasma.private.volume` | `plasma6-pa` |
|
|
|
|
|
|
| `org.kde.plasma.private.nanoshell` | `plasma6-nano` |
|
|
|
|
|
|
| `org.kde.layershell` | `layer-shell-qt6-imports` |
|
|
|
|
|
|
|
|
|
|
|
|
### `Could not set containment property on rootObject`
|
|
|
|
|
|
|
|
|
|
|
|
This means the Desktop.qml failed to load, almost always due to a
|
|
|
|
|
|
missing QML module — look for the preceding `module "…" is not
|
|
|
|
|
|
installed` line.
|
|
|
|
|
|
|
|
|
|
|
|
### `FATAL ERROR: could not add wayland socket shift-kwin`
|
|
|
|
|
|
|
|
|
|
|
|
A previous preview didn't exit cleanly. Remove the stale lock:
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
rm -f /run/user/$UID/shift-kwin.lock
|
|
|
|
|
|
pkill -f 'kwin_wayland.*shift-kwin'
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### `distrobox create` hangs or zypper crashes during init
|
|
|
|
|
|
|
|
|
|
|
|
Likely the missing `/etc/zypp/zypp.conf` bug. See
|
|
|
|
|
|
[2a. Work around missing zypp.conf](#2a-work-around-missing-etczyppzyppconf).
|
|
|
|
|
|
|
|
|
|
|
|
### Harmless warnings you can ignore
|
|
|
|
|
|
|
|
|
|
|
|
These appear in the preview output and are not errors:
|
|
|
|
|
|
|
|
|
|
|
|
- `fusermount3: failed to access mountpoint` — FUSE is restricted
|
|
|
|
|
|
inside the nested session.
|
|
|
|
|
|
- `qt.qpa.services: Failed to register with host portal` — Portal
|
|
|
|
|
|
registration unsupported in nested compositors.
|
|
|
|
|
|
- `kf.solid.backends.udisks2: Failed to fetch all devices` — No
|
|
|
|
|
|
udisks2 in the isolated D-Bus session.
|
|
|
|
|
|
- `TypeError: Cannot read property 'volume' of null` — PulseAudio /
|
|
|
|
|
|
PipeWire is not running in the sandbox.
|
|
|
|
|
|
- `Could not load a session backend` — systemd --user is not running in
|
|
|
|
|
|
the nested D-Bus session.
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 8. Project layout (quick reference)
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
Shift/
|
|
|
|
|
|
├── CMakeLists.txt # Top-level build file
|
|
|
|
|
|
├── build-clean/ # Out-of-source build directory
|
|
|
|
|
|
│ └── prefix.sh # Auto-generated by ECM; sources .prefix paths
|
|
|
|
|
|
├── .prefix/ # Local install tree (not committed)
|
|
|
|
|
|
├── preview.sh # Nested KWin launcher (see §5)
|
|
|
|
|
|
├── shell/ # Shell package (Desktop.qml, Panel.qml, applet overrides)
|
|
|
|
|
|
├── components/
|
|
|
|
|
|
│ └── mobileshell/ # QML & C++ for the mobile shell runtime plugin
|
|
|
|
|
|
├── containments/
|
|
|
|
|
|
│ ├── homescreens/folio/ # Folio homescreen applet
|
|
|
|
|
|
│ ├── panel/ # Status bar
|
|
|
|
|
|
│ └── taskpanel/ # Navigation bar / gesture panel
|
2026-04-14 05:17:51 +00:00
|
|
|
|
├── envmanager/ # Applies KWin/KDE config on convergence mode changes
|
2026-04-13 06:37:19 +00:00
|
|
|
|
├── quicksettings/ # Action drawer quick-setting tiles
|
|
|
|
|
|
├── kcms/ # System Settings modules
|
2026-04-14 05:17:51 +00:00
|
|
|
|
└── kwin/
|
|
|
|
|
|
├── mobiletaskswitcher/ # KWin task-switcher plugin
|
|
|
|
|
|
└── scripts/convergentwindows/ # KWin script: maximize on undock, restore borders on dock
|
2026-04-13 06:37:19 +00:00
|
|
|
|
```
|