From d7a8b0e7eeac3575b05d1ae5bea4473177de30a1 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Wed, 16 Sep 2026 17:43:45 +0200 Subject: fix(appearance): stage a cursor theme, apply on confirm Clicking a cursor card called applyCursor straight away, so the pointer, gsettings, environment.lua and both GTK settings files all changed on a single click with nothing to confirm. The wallpaper tab already stages a pick and commits it from an Apply button; the cursor grid now does the same, with a Reset beside it. The hover preview is unchanged: it still switches the real cursor and reverts on unhover, which is what makes staging readable, you see the theme before committing to it. That preview is also why Apply clears liveCursorCursor before calling applyCursor. Moving the mouse off the card to reach the button fires the unhover revert, which would otherwise set the old theme back over the one just applied. A staged card takes the solid accent border and the current one drops to a half-alpha border, so both stay visible at once. Icon themes and cursor size still apply on click. Neither has a hover preview to confirm against. Co-Authored-By: Claude Opus 5 --- appearance/IconsTab.qml | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/appearance/IconsTab.qml b/appearance/IconsTab.qml index b2c7ee4..908a003 100644 --- a/appearance/IconsTab.qml +++ b/appearance/IconsTab.qml @@ -18,6 +18,10 @@ Flickable { clip: true property string liveCursorCursor: "" + // Clicking a cursor card stages it; Apply commits. The hover preview above + // switches the real cursor and reverts, so staging must not be confused + // with it: pendingCursor survives unhover, liveCursorCursor does not. + property string pendingCursor: "" Column { id: col @@ -131,10 +135,13 @@ Flickable { id: cursorCard required property string modelData readonly property bool current: Icons.currentCursor === modelData + readonly property bool staged: pendingCursor === modelData width: 230; height: 150; radius: 10 - color: current ? Qt.alpha(Theme.accent, 0.2) : Qt.alpha(Theme.surface, 0.35) - border.width: current ? 2 : 1 - border.color: current ? Theme.accent : "transparent" + color: current || staged ? Qt.alpha(Theme.accent, 0.2) : Qt.alpha(Theme.surface, 0.35) + border.width: current || staged ? 2 : 1 + border.color: staged ? Theme.accent + : current ? Qt.alpha(Theme.accent, 0.5) + : "transparent" HoverHandler { onHoveredChanged: { @@ -154,7 +161,7 @@ Flickable { MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor - onClicked: Icons.applyCursor(modelData) + onClicked: pendingCursor = modelData } Column { @@ -181,7 +188,9 @@ Flickable { Text { width: parent.width horizontalAlignment: Text.AlignHCenter - text: cursorCard.current ? modelData + " current" : modelData + text: cursorCard.staged ? modelData + " staged" + : cursorCard.current ? modelData + " current" + : modelData color: Theme.text font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 3 } wrapMode: Text.WrapAnywhere @@ -193,6 +202,33 @@ Flickable { } } + Row { + spacing: 8 + Text { + anchors.verticalCenter: parent.verticalCenter + text: pendingCursor !== "" ? "click Apply to set" : "click a cursor theme to stage it" + color: Theme.overlay + font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 4 } + } + Tab { + text: "Apply" + selected: pendingCursor !== "" + enabled: pendingCursor !== "" + onClicked: { + // The hover revert would otherwise fire on the way out and + // set the old theme back over the one just applied. + liveCursorCursor = ""; + Icons.applyCursor(pendingCursor); + pendingCursor = ""; + } + } + Tab { + text: "Reset" + enabled: pendingCursor !== "" + onClicked: pendingCursor = "" + } + } + Text { width: parent.width wrapMode: Text.Wrap -- cgit v1.2.3