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.
Use Kirigami.Theme.textColor for the status bar hover overlay
so it works on both light and dark themes instead of hardcoded
white. Remove convergence-mode branches from the navigation
panel left action since it is hidden in convergence mode and
the code paths were unreachable.
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.
navigationPanelThickness is explicitly 0 in convergence mode, so using
it as the layer-shell surface height triggered a Wayland protocol error
and crashed the shell. Use gridUnit * 3 directly, matching the dock bar
height set on FavouritesBar.
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.
NavigationPanel: the taskStrip ListView checked contentWidth > width
to decide whether scrolling is enabled, which is wrong when the
panel is vertical. Check contentHeight > height in that case.
taskpanel: dockSpaceReserver used a hardcoded gridUnit * 3 for both
height and exclusionZone. Use navigationPanelHeight so the reserved
strip tracks the actual panel thickness.
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.
open() alone does not set intendedToBeVisible, so the drawer
immediately closes itself. Call the proper toggle path instead.
Also hide the drag handle since convergence users click.
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.
The status bar was hidden whenever a window was showing because
the fullscreen property evaluated autoHidePanelsEnabled without
checking convergence mode. Return false from fullscreen when
convergence is active so the bar stays on screen.
Use WindowsGoBelow visibility mode in convergence so PanelView
does not manage the exclusive zone (it would fight with the
LayerOverlay layer set by QML). Add a separate layer-shell
surface at LayerBottom with an exclusive zone matching the bar
height, following the same pattern as the dock space reserver.
Re-run setWindowProperties on convergence mode changes.
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.
Add an invisible layer-shell surface with an exclusive zone matching
the dock height. KWin uses this to shrink MaximizeArea so maximized
and tiled windows no longer overlap the dock.
The previous approach of tweaking the nav-panel PanelView was a dead
end: PanelView resets its own surface properties on reconfiguration
and Wayland offers no way to set struts from a KWin script. A
separate surface at LayerBottom with exclusionZone is the intended
protocol mechanism.
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