interactive starts false at atYBeginning so HomeScreenState can
own the swipe-up gesture that opens the drawer on phones. No such
gesture exists in convergence mode, leaving the grid permanently
non-interactive. Short-circuit the condition when convergence
mode is active.
Remove hardcoded Complementary override and white color literals
from AppDrawerHeader. In mobile mode the Plasma containment
framework already provides Complementary context; in convergence
mode the drawerOverlay Window starts a fresh Window context.
Both cases now propagate correctly without an explicit override.
Also set Kirigami.Theme.Window on the convergence dock
FavouritesBar so icon labels and hover highlights follow the
active system palette instead of the wallpaper context.
A mapped LayerShell surface prevents KWin from using DRM direct
scanout for fullscreen windows. Setting showing=false fades out
the HUD then sets visible=false, unmapping the Wayland surface
and allowing KWin to bypass the compositor render loop entirely
for the game frame.
The HUD reappears when the game exits or is minimised. Error
toasts still work because a failed launch never produces a
fullscreen window, so showingWindow remains false.
Connect to gameLaunched and gameLaunchFailed signals. Launch
toasts dismiss after 3 s; error toasts after 5 s with a red
background. The window grows downward from the HUD pill to
accommodate the toast pill.
When recentGamesChanged fires, the most recently played game
is stored in quickResumeGame. While set, the HUD pill widens
leftward to show the game name and a play button that calls
launchByStorageId directly — no need to open Game Center.
Star badge on pinned tiles (passive Kirigami.Icon, no event
handlers to avoid pointer-feedback loops). Pin/Unpin action
and per-game FPS cap + overlay rows added to the details dialog.
Per-game FPS and overlay rows use ButtonGroup with a Global
option that deletes the per-game key and falls back to the
global quick-settings value.
Remove isCurrent from info button visibility; add Menu and I
key handlers on the grid for keyboard/gamepad access to details.
Inject MangoHud when launching desktop and command-line games.
MANGOHUD_CONFIG is built per-launch via a QProcess instance so
env vars are isolated to each child process — qputenv is not used.
Global overlay toggle and FPS cap (Off/30/40/60) are stored as
properties on GameLauncherProvider and reflected in the quick
settings panel. Per-game overrides stored in plasmamobilerc under
[GamingPerGame/<storageId>] take precedence over the globals at
launch time.
Games can be pinned to the top of the grid. The pinned set is
persisted in plasmamobilerc [GamingPinned] and restored on start.
applyFilter() uses stable_sort so pinned games float to the top
while alphabetical order is preserved within each group.
Read the Waydroid allowlist from plasmamobilerc and treat matching
Waydroid launchers as their own source in the gaming shell.
Surface that source in Game Center so Android titles get their own tab,
source chip, and empty-state guidance.
Record recent launches only after the launcher reports success instead of
optimistically on every attempt. For desktop entries, wait for the
ApplicationLauncherJob result; for detached commands, use startDetached's
return value and show an inline error when startup fails.
Parse Steam libraryfolders and app manifests as KeyValues instead of
matching individual lines. This makes Steam discovery less brittle when
the files contain comments, nested blocks, or different formatting.
Keep Continue Playing visible alongside Running and show a temporary
launching state so the overlay does not pretend a task already exists.
Rename the GameMode status text to say what the shell actually knows.
Use SDL button labels so shell prompts match the connected
controller instead of always using Xbox-style wording. Expose
trigger rumble, touchpad count, gyro, and accelerometer support
through the gamepad wrapper and surface the relevant capability
labels in the overlay.
Enable background gamepad events and add short rumble feedback
for major shell actions such as opening quick settings, opening
the exit prompt, and launching a game.
Expose missing gaming controls directly in the panel so they
remain reachable in convergence mode. Add toggles for DND,
Launch Hint, Night Color, and Perf Overlay with gamepad focus
order updates.
Restyle brightness and volume sliders with rounded Plasma-themed
tracks and handles to remove harsh bar visuals while keeping
existing behavior unchanged.
Add PowerProfileControl and GameModeControl singletons and wire
them into gaming mode lifecycle handling. When gaming mode turns
on, keep DND on, switch to the performance profile when available,
and request GameMode. Restore previous state when gaming mode
turns off.
Add an overlayEnabled property in GameLauncherProvider so the
launcher can toggle MangoHud environment variables from QML.
Slide-out panel with brightness, volume, Wi-Fi, Bluetooth,
and airplane mode. Fully gamepad-navigable; D-pad and stick
input routed to the panel while open. System status bar
(clock, battery, connectivity) added to game center header.
Lutris games discovered from ~/.local/share/lutris/pga.db,
Heroic from ~/.config/heroic/store_cache/ JSON files.
Deduplication extended to cover all launcher sources.
Desktop entries launched via KIO::ApplicationLauncherJob to
expand Exec field codes. Generic commands parsed with
KShell::splitArgs. SQLite uses RAII cleanup guard.
Clamped SDL axis, rumble, and LED values. Renamed rumble
params from frequency to intensity. GamepadManager uses
singleton factory. setPlayerIndex checks SDL return.
FavouritesBar popup uses screen virtualX/Y for multi-monitor.
Show a PlaceholderMessage in the grid when no games are found,
with context-aware text for empty library vs no search results.
Map gamepad A to activate and X to close in RunningGamesView.
Update the legend bar to show X: Close when running tasks are
visible.
LB/RB cycle through source filter tabs (All/Steam/Desktop).
Start toggles focus between the search field and the grid.
Right stick Y-axis smoothly scrolls the grid at 60 Hz with
speed proportional to deflection. Update the gamepad legend
to show the new bindings.
Expose SDL_GamepadAxis as an Axis enum in GamepadManager so
QML can identify axis events by name.
Convert left-stick deflection into repeated grid navigation
events with a 150ms interval and 0.4 deadzone. First movement
fires immediately when the stick crosses the threshold.
Wrap game launches in a brief fade-to-black curtain (250ms)
before dismissing the overlay, giving visual feedback that the
launch is in progress.
The cover art tile used layer.effect with a plain Item instead
of a ShaderEffect, which broke the overlay rendering. Replace
with a clipped Rectangle wrapper.
Remove Behavior on color from the grid delegate background —
GridView currentIndex changes on hover caused the highlight
color to flash visibly between cells.
Fix dangling taskList reference in the gamepad ButtonA and
DPadDown handlers (taskList lives inside RunningGamesView).
Auto-reopen Game Center when the last window closes in gaming
mode so the user is never stranded on a bare wallpaper.
Grid tiles now show Steam library artwork when available,
falling back to icon+label for games without cover art.
Cell proportions adjusted to 2:3 for portrait covers.
Search bar filters the library by name. Source tabs filter
by All/Steam/Desktop. Both properties live in C++ so QML
just binds filterString and sourceFilter.
"Continue Playing" row shows the last 5 launched games
with artwork, persisted across sessions via plasmamobilerc.
Remove orphaned GameTile.qml (replaced by inline delegate).
SDL3-backed gamepad manager polls at 60Hz, handles hotplug,
exposes battery/rumble/LED per device. Game launcher aggregates
XDG desktop entries, Steam appmanifests, and Flatpak into a
single sorted model.
Game Center uses the new model instead of folio's search model.
D-pad/A/B/Y navigate and launch. Guide button toggles the
overlay. Battery and controller status shown in the HUD.
Strut windows committed zero height to layer-shell during
early init, causing a protocol error and session exit. Wrap
height and exclusionZone in Math.max(1, ...) for top bar
and dock.
Persisted gamingModeEnabled=true with hardcoded
gameCenterOpen=false hid panels with no overlay visible.
Initialize gameCenterOpen from the stored setting.
Fix HUD visibility regression from an emergency visible:true
override. Various null-guard and positioning fixes from
static analysis across the gaming shell QML.
LayerShell windows with non-spanning anchors (AnchorTop|AnchorRight)
crash the compositor when made invisible because Qt briefly resizes
the surface to 0 before unmapping it. Wrap GamingHUD in a Loader so
the window is destroyed rather than hidden.
Replace the generic 'Yes / Cancel' exit dialog with 'Keep Playing /
Leave' in both the Game Center header and the QS tile, matching the
mental model of a couch user.
The 'Launch Hint' QS tile is now hidden (available: false) when
gaming mode is off so it does not clutter the regular action drawer.
Full-screen layer-shell overlay containing a game library grid
(XDG Game category, filtered via ApplicationListSearchModel) and
a panel of running tasks built on TaskManager.TasksModel.
Keyboard-navigable with directional focus between the running
tasks row and the game grid. A persistent HUD button lets the
user return after launching a game. Exiting gaming mode requires
an explicit confirmation dialog.
The overlay is a Window with LayerShell.LayerTop so it sits above
running application windows without covering system notifications.
Hide the navigation panel, status bar, and app drawer while
gamingModeEnabled is active. The KWin convergent-windows script
skips its window policy so game windows are not forcibly tiled
or maximized.
The Home button in gaming mode re-opens the Game Center overlay
rather than the app drawer. A configurable hint nudges the user
toward the HUD button after launching a game.
Make the convergence dock fully usable from the keyboard.
Tab now reaches Home, favorites, running tasks, and Overview.
Left and right move across section boundaries, and Enter/Space
triggers the same actions as mouse clicks.
Also add accessible role/name/press actions for these controls
so screen readers expose meaningful button semantics.
The popup snapped to visible/hidden instantly while every other
surface in the shell uses animated transitions. Add an opacity
fade over shortDuration so it matches the rest of the motion
language. State cleanup waits for the fade-out to finish.
The dock background was a hardcoded dark fill because upstream
icon labels are white (for floating over wallpaper). Switching
to Theme.backgroundColor alone just made labels vanish on light
themes, so it kept getting reverted.
Fix the whole stack at once: background uses the Window color
set, hover highlights derive from Theme.textColor instead of
white, and delegate labels switch to Theme.textColor in
convergence mode (still white over wallpaper on mobile).
Use QByteArray::data() instead of constData() for the
udev_device_set_sysattr_value call — Alpine libudev declares the
value parameter as char*, not const char*. Fix the SPDX license
identifier in CategoryPanel.qml from "EUPL 1.2" to "EUPL-1.2".
Clamp FavouritesBar window indicator dots to at least 1 so a
running task with an empty WinIdList still shows a dot. Add
Accessible.onPressAction to CategoryPanel tiles. Remove dead
convergence-mode property bindings from NavigationPanelComponent
since it is hidden in that mode. Use HTML video tags for .webm
files in README so they render as playable video.
Remove duplicate KService include in favouritesmodel.cpp. Add
keyboard navigation and accessibility role to CategoryPanel
tiles. Clamp the FavouritesBar thumbnail popup position to
screen bounds so it does not overflow offscreen on edge items.
ApplicationListSearchModel: beginFilterChange() was called after
mutating m_categoryFilter, inverting the documented before/after
contract. Also add null checks for sourceModel() and
favouritesModel() in filterAcceptsRow.
CategoryPanel: add onModelReset to repopulate the category list
when the underlying model is fully reloaded, not just on individual
row insertions and removals.
Qt.rgba expects 0.0–1.0 floats. Passing 255 for R/G/B saturates
every channel to 1.0, producing opaque white instead of the
intended semi-transparent tint. Fix all call sites across
FavouritesBar, StatusBar, and AbstractDelegate.
A panel between the drawer and the power panel lists the XDG
categories installed on the device as icon-and-label tiles.
Tapping one filters the app list; text search still applies
on top. The filter resets each time the drawer opens. Audio,
Video and Settings fold into their parent groups to match
Kickoff.
The dismiss button in the drawer header was isolated from the
other controls. Moving it to the top of the power panel groups
everything in one place and lets the power icons sit centered
between it and the user avatar.
Labels are gone; each action shows only an icon with a tooltip
on hover, keeping the panel narrow. A user avatar at the bottom
opens User Accounts on click. The shadow is on a backing
Rectangle rather than via layer.enabled, which would rasterize
the panel and blur icons at non-integer scale.
The hidden dock's window still covered full height, blocking
toolbar buttons in maximized apps. Reduce the input region to
a thin strip at the screen edge while off-screen and restore
it on reveal. A debounce timer prevents an accidental edge
graze from reopening the dock.
The dock's LayerShell window is transparent; icon labels are
hardcoded white (designed to float over wallpaper on mobile).
A dark semi-transparent fill keeps labels legible on any
wallpaper without coupling to the Plasma theme color.
Shows a narrow card to the right of the app drawer popup with
Lock Screen, Restart, and Shut Down buttons. Uses SessionManagement
from org.kde.plasma.private.sessions directly, the same QML type
Logout.qml already uses. No C++ changes needed. Shares the drawer
open/close animation and dismisses with it.
Drawer is inside the homescreen, which sits behind windows.
Home button minimized everything to reach it. Render it in
a LayerTop window instead and skip the blanket minimizeAll
in the D-Bus handler.
Dock and space reserver hid unconditionally on maximize.
Gate both on autoHidePanelsEnabled. Make the exclusive zone
constant — dynamic changes on a contentless surface never
get committed to the compositor.
Running task icons in the convergence dock can now be dragged into the favourites section to pin the app at the drop position.
Add indexed insertion to FavouritesModel so pinning can place the new favourite at a specific slot instead of always appending.
Show a placeholder while dragging and reuse the existing addApplication path for the final pin action.
Click-and-drag reordering of favourites bar items in convergence
mode. The existing touch-based press-and-hold drag is kept for
mobile; in convergence mode, press-and-hold opens the context
menu only.
DelegateTouchArea owns the exclusive mouse grab at the C++ level,
so drag detection (threshold crossing + delta signals) is added
there rather than using a QML DragHandler. Displaced items
animate into their new positions while the dragged item follows
the cursor.
Expose FavouritesModel::moveEntry as Q_INVOKABLE so QML can
persist the reorder.
The visible binding on the Pin to Dock menu item called the
imperative containsApplication() without any reactive dependency,
so QML never re-evaluated it after model changes. Add repeater.count
to the binding to force re-evaluation when favourites change.
Switch TasksModel from GroupDisabled to GroupApplications so
multiple windows of the same app share a single dock icon.
Replace the per-task windowCountForTask() helper with the
built-in WinIdList role.
The thumbnail popup now shows a horizontal row of per-window
previews. Clicking a grouped icon toggles the popup instead
of activating a single window. "Close All" replaces the
close action for multi-window groups.
Slide the dock off-screen when WindowMaximizedTracker reports a
maximized window, and bring it back on mouse proximity via a
HoverHandler. The dockSpaceReserver exclusion zone drops to 0 so
KWin gives the full screen to the maximized window.
Animation follows the StatusBarWrapper pattern: offset property,
Translate transform, Behavior with InExpo/OutExpo easing.
The transparent dock overlay at LayerTop let maximized app content
bleed through, visible as a colored band (e.g. VLC's orange toolbar)
behind the favourites bar.
Add a Rectangle with Kirigami.Theme.backgroundColor using the Window
colorset, matching the pattern used by NavigationPanelComponent.
Right-click a running task icon to pin the app to the dock
favourites bar. Pinned apps show a "Remove from Dock" action.
The dock overlay renders as a LayerTop window so context menus
and the dock itself stay above application windows. Menus use
popupType Window to avoid clipping inside the narrow dock
surface.
When multiple windows of the same application are open, each
dock icon displays a row of dots matching the sibling window
count. The active window's dots are bright; inactive siblings
are dimmed. Single-window apps show one dot as before.
Uses the TasksModel AppId role to count windows sharing the
same application identity.
The click-to-dismiss overlay for the app drawer popup
covered the dock, intercepting taps on dock icons. Add a
bottom margin equal to the dock height in convergence mode
so dock icons remain interactive.
filterHidden: true removed minimized windows from the
TasksModel because on Wayland IsHidden maps to IsMinimized.
Set filterHidden to false so minimized apps remain in the
dock and can be restored by tapping their icon.
Hovering a running-app icon in the dock shows a live PipeWire
thumbnail of the window via zkde_screencast. Falls back to the
app icon when the stream isn't available. Clicking the thumbnail
activates the window.
Uses a tooltip-type Window so the popup renders above app windows
instead of being clipped to the panel surface.
In convergence mode the app drawer appears as a sized popup
anchored above the dock near the Overview button, instead of
taking over the full screen.
- Popup has rounded background, shadow, and clipped content
- Desktop stays visible behind the popup (no scale/fade/blur)
- Click outside the popup dismisses it
- Wallpaper scrim suppressed in convergence mode
- Mobile behavior is unchanged
Right-click on a pinned favourite in the dock now shows:
- Launch: opens the app (using its own icon)
- Remove from Dock: existing unpin action, renamed for clarity
The task panel window reserved bottom-edge screen space even
with zero thickness and invisible content. Set its visibility
mode to auto-hide in convergence and force the dock bottom
margin to zero so the favourites bar sits flush at the screen
edge.
Dock buttons, running-app icons, and favourite delegates had no
mouse-over feedback. Add 3-state highlight backgrounds (hover
and press), Kirigami.Icon active state, and tooltips following
existing Plasma patterns. Favourite delegate hover is gated on
convergence mode to avoid overlap with touch press events.
On desktop there is no swipe-down gesture to dismiss the drawer.
Add an X button at the right end of the header row, visible only
in convergence mode, so mouse users have an obvious way to close
the app drawer.
In convergence mode the separate navigation panel is redundant
with window title-bar controls. Remove it by setting its
thickness to zero and visibility to false, then embed Home and
Overview buttons at the left and right ends of the favourites
bar. Running application icons with context menus are shown
between the favourites and the Overview button.
Add HomeScreen::triggerOverview() to invoke the KWin Overview
shortcut over D-Bus so the homescreen containment can open it
without access to the task-panel Plasmoid.
Halve the favourites bar from gridUnit*6 to gridUnit*3 to avoid
oversized dock on desktop screens. Hide the arrow-up icon and
disable the page-indicator tap handler since the app drawer is
now opened via the dedicated Overview button.
In convergence mode the app drawer stays open after launching an
application. Connect to WindowUtil.onWindowCreated and close the
drawer automatically so the user lands on the new window.
Accept Qt.RightButton on the HomeScreenPages and FavouritesBar
MouseAreas and open the settings view (wallpaper/widgets) on
right-click, mirroring the existing long-press behavior for mouse
users.
The home button was a no-op in convergence mode when windows were
visible. Call WindowUtil.minimizeAll() so the home button acts as
show-desktop, preserving the mobile path that also resets homescreen
state before minimizing.
This is exacerbated now that we have device-specific view margins (to
deal with notches and the like), which caused the drag and drop
positions to be wildly inaccurate.
This refactors the homescreen state object to isolate drag & drop from
swipe states, allowing for using proper system-level drag & drop for delegate
movement. This then ports the new applet list to use it.
This switching Folio and Halcyon to define their settings as a
containment config so that it fits in with the other containment
options.
This removes the convoluted maze of nested settings windows due to
wrapping the containment settings with a custom settings window around
it.
This converts many of the animation durations to Kirigami units so that
they can be controlled system wide. It also speeds up several of the
animation durations (ex. in folio) from 800ms to 400ms to improve the
feel and responsiveness of the shell.
Fixes typos in various source comments.
Found via `codespell -S "*.po,*.svg,*.pgm,*.xml,./po,*.desktop,*.json,*.actions" -L aline,aparent,childs,distroname,indexin,indx,logicaly,lokal,nd,splitted,te`
Apparently i18n doesn't support string literals with single quotes as
parameters. Fix occurrences of this and add a CI check to ensure this
won't happen in the future.
Currently Folio's settings are being written to the main KConfigGroup of the
containment, when can interfere with other generic containment settings.
ShellCorona in plasma-workspace also expects the settings to be in
sub-config group when it preserves them when changing containments.
This commit moves all of the settings to its own config group, and also
consolidates config read/write for favourites and pages into
FolioSettings.
This MR ensures that delegates created with make_shared do not also get
initialized with a QObject parent. Some of the classes used the same
constructor parameter for HomeScreen and used it as a parent simultaneously. This was refactored
so that they are separated.
This commit drops halcyon's search widget in favour of using the same
widget as folio to share code. This also brings over its keyboard
navigation features.
search
This commit is a subset of
https://invent.kde.org/plasma/plasma-mobile/-/merge_requests/694 to add
keyboard navigation to the app drawer.
Pressing the arrow keys while in the app drawer will allow you to
navigate between the apps and the search bar, and going up will exit the
app drawer. Escape/Back is also supported for unfocusing the search bar
and exiting the view.
This also fixes an issue in the keyboard navigation on the search screen
where it wouldn't close when there are no search results.
This ensures extraneous signals from being emitted when values don't
change in y animations. This fixes the vkbd in the search widget getting
in a weird stuck state due to multiple focuses on the search widget.