From f0c44734bc5e7376fcac8ba2e85b3a417bead082 Mon Sep 17 00:00:00 2001 From: DuckySoLucky Date: Fri, 10 Oct 2025 20:07:28 +0200 Subject: [PATCH 1/3] feat(Application Launcher): add option to ignore initial mouse position --- Assets/Translations/en.json | 4 +++ Assets/settings-default.json | 5 +-- Commons/Settings.qml | 3 +- Modules/Launcher/Launcher.qml | 52 +++++++++++++++++++++++++-- Modules/Settings/Tabs/LauncherTab.qml | 7 ++++ 5 files changed, 66 insertions(+), 5 deletions(-) diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index c4ff50ae..d3a3b630 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -354,6 +354,10 @@ "label": "Use App2Unit to launch applications", "description": "Uses an alternative launch method to better manage app processes and prevent issues." }, + "ignore-initial-mouse": { + "label": "Ignore initial mouse position", + "description": "When enabled, the launcher always defaults to the first item, ignoring where your mouse cursor is positioned. Selection only changes when you move the mouse." + }, "terminal-command": { "label": "Terminal command", "description": "Command to launch a terminal. E.g., 'kitty -e' or 'gnome-terminal --'." diff --git a/Assets/settings-default.json b/Assets/settings-default.json index 9b63d3ae..1df70c5a 100644 --- a/Assets/settings-default.json +++ b/Assets/settings-default.json @@ -1,5 +1,5 @@ { - "settingsVersion": 15, + "settingsVersion": 16, "bar": { "position": "top", "backgroundOpacity": 1, @@ -104,7 +104,8 @@ "pinnedExecs": [], "useApp2Unit": false, "sortByMostUsed": true, - "terminalCommand": "xterm -e" + "terminalCommand": "xterm -e", + "ignoreInitialMousePosition": false }, "controlCenter": { "position": "close_to_bar_button", diff --git a/Commons/Settings.qml b/Commons/Settings.qml index d8e8f4bf..355c42e3 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -125,7 +125,7 @@ Singleton { JsonAdapter { id: adapter - property int settingsVersion: 15 + property int settingsVersion: 16 // bar property JsonObject bar: JsonObject { @@ -233,6 +233,7 @@ Singleton { property bool useApp2Unit: false property bool sortByMostUsed: true property string terminalCommand: "xterm -e" + property bool ignoreInitialMousePosition: true } // control center diff --git a/Modules/Launcher/Launcher.qml b/Modules/Launcher/Launcher.qml index 25bafe37..d31762ea 100644 --- a/Modules/Launcher/Launcher.qml +++ b/Modules/Launcher/Launcher.qml @@ -35,6 +35,7 @@ NPanel { property var plugins: [] property var activePlugin: null property bool resultsReady: false + property bool ignoreMouseHover: false readonly property int badgeSize: Math.round(Style.baseWidgetSize * 1.6 * scaling) readonly property int entryHeight: Math.round(badgeSize + Style.marginM * 2 * scaling) @@ -94,6 +95,7 @@ NPanel { // Lifecycle onOpened: { resultsReady = false + ignoreMouseHover = Settings.data.appLauncher.ignoreInitialMousePosition // Use setting value // Notify plugins for (let plugin of plugins) { @@ -110,6 +112,7 @@ NPanel { onClosed: { // Reset search text searchText = "" + ignoreMouseHover = Settings.data.appLauncher.ignoreInitialMousePosition // Use setting value // Notify plugins for (let plugin of plugins) { @@ -154,6 +157,49 @@ NPanel { color: Color.transparent opacity: resultsReady ? 1.0 : 0.0 + // Global MouseArea to detect mouse movement + MouseArea { + id: mouseMovementDetector + anchors.fill: parent + z: -999 + hoverEnabled: true + propagateComposedEvents: true + acceptedButtons: Qt.NoButton + + property real lastX: 0 + property real lastY: 0 + property bool initialized: false + + onPositionChanged: mouse => { + // Store initial position + if (!initialized) { + lastX = mouse.x + lastY = mouse.y + initialized = true + return + } + + // Check if mouse actually moved + const deltaX = Math.abs(mouse.x - lastX) + const deltaY = Math.abs(mouse.y - lastY) + if (deltaX > 1 || deltaY > 1) { + root.ignoreMouseHover = false + lastX = mouse.x + lastY = mouse.y + } + } + + // Reset when launcher opens + Connections { + target: root + function onOpenedChanged() { + if (root.opened) { + mouseMovementDetector.initialized = false + } + } + } + } + Behavior on opacity { NumberAnimation { duration: Style.animationFast @@ -321,7 +367,7 @@ NPanel { delegate: Rectangle { id: entry - property bool isSelected: mouseArea.containsMouse || (index === selectedIndex) + property bool isSelected: (!root.ignoreMouseHover && mouseArea.containsMouse) || (index === selectedIndex) // Accessor for app id property string appId: (modelData && modelData.appId) ? String(modelData.appId) : "" @@ -523,7 +569,9 @@ NPanel { hoverEnabled: true cursorShape: Qt.PointingHandCursor onEntered: { - selectedIndex = index + if (!root.ignoreMouseHover) { + selectedIndex = index + } } onClicked: mouse => { if (mouse.button === Qt.LeftButton) { diff --git a/Modules/Settings/Tabs/LauncherTab.qml b/Modules/Settings/Tabs/LauncherTab.qml index a01c13fb..1149c811 100644 --- a/Modules/Settings/Tabs/LauncherTab.qml +++ b/Modules/Settings/Tabs/LauncherTab.qml @@ -99,6 +99,13 @@ ColumnLayout { onToggled: checked => Settings.data.appLauncher.useApp2Unit = checked } + NToggle { + label: I18n.tr("settings.launcher.settings.ignore-initial-mouse.label") + description: I18n.tr("settings.launcher.settings.ignore-initial-mouse.description") + checked: Settings.data.appLauncher.ignoreInitialMousePosition + onToggled: checked => Settings.data.appLauncher.ignoreInitialMousePosition = checked + } + NTextInput { label: I18n.tr("settings.launcher.settings.terminal-command.label") description: I18n.tr("settings.launcher.settings.terminal-command.description") From b22c2e7d4ddd951c55a353e873e51e1e4128483c Mon Sep 17 00:00:00 2001 From: DuckySoLucky Date: Fri, 10 Oct 2025 21:34:37 +0200 Subject: [PATCH 2/3] refactor: remove setting --- Assets/Translations/en.json | 4 ---- Assets/settings-default.json | 3 +-- Commons/Settings.qml | 1 - Modules/Launcher/Launcher.qml | 4 ++-- Modules/Settings/Tabs/LauncherTab.qml | 7 ------- 5 files changed, 3 insertions(+), 16 deletions(-) diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index d3a3b630..c4ff50ae 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -354,10 +354,6 @@ "label": "Use App2Unit to launch applications", "description": "Uses an alternative launch method to better manage app processes and prevent issues." }, - "ignore-initial-mouse": { - "label": "Ignore initial mouse position", - "description": "When enabled, the launcher always defaults to the first item, ignoring where your mouse cursor is positioned. Selection only changes when you move the mouse." - }, "terminal-command": { "label": "Terminal command", "description": "Command to launch a terminal. E.g., 'kitty -e' or 'gnome-terminal --'." diff --git a/Assets/settings-default.json b/Assets/settings-default.json index 1df70c5a..29ebba85 100644 --- a/Assets/settings-default.json +++ b/Assets/settings-default.json @@ -104,8 +104,7 @@ "pinnedExecs": [], "useApp2Unit": false, "sortByMostUsed": true, - "terminalCommand": "xterm -e", - "ignoreInitialMousePosition": false + "terminalCommand": "xterm -e" }, "controlCenter": { "position": "close_to_bar_button", diff --git a/Commons/Settings.qml b/Commons/Settings.qml index 355c42e3..7e62b2cf 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -233,7 +233,6 @@ Singleton { property bool useApp2Unit: false property bool sortByMostUsed: true property string terminalCommand: "xterm -e" - property bool ignoreInitialMousePosition: true } // control center diff --git a/Modules/Launcher/Launcher.qml b/Modules/Launcher/Launcher.qml index d31762ea..f4a7fd4d 100644 --- a/Modules/Launcher/Launcher.qml +++ b/Modules/Launcher/Launcher.qml @@ -95,7 +95,7 @@ NPanel { // Lifecycle onOpened: { resultsReady = false - ignoreMouseHover = Settings.data.appLauncher.ignoreInitialMousePosition // Use setting value + ignoreMouseHover = true // Notify plugins for (let plugin of plugins) { @@ -112,7 +112,7 @@ NPanel { onClosed: { // Reset search text searchText = "" - ignoreMouseHover = Settings.data.appLauncher.ignoreInitialMousePosition // Use setting value + ignoreMouseHover = true // Notify plugins for (let plugin of plugins) { diff --git a/Modules/Settings/Tabs/LauncherTab.qml b/Modules/Settings/Tabs/LauncherTab.qml index 1149c811..a01c13fb 100644 --- a/Modules/Settings/Tabs/LauncherTab.qml +++ b/Modules/Settings/Tabs/LauncherTab.qml @@ -99,13 +99,6 @@ ColumnLayout { onToggled: checked => Settings.data.appLauncher.useApp2Unit = checked } - NToggle { - label: I18n.tr("settings.launcher.settings.ignore-initial-mouse.label") - description: I18n.tr("settings.launcher.settings.ignore-initial-mouse.description") - checked: Settings.data.appLauncher.ignoreInitialMousePosition - onToggled: checked => Settings.data.appLauncher.ignoreInitialMousePosition = checked - } - NTextInput { label: I18n.tr("settings.launcher.settings.terminal-command.label") description: I18n.tr("settings.launcher.settings.terminal-command.description") From f0d14f3c61e87815bdaa7454951c1ffe105f9b33 Mon Sep 17 00:00:00 2001 From: DuckySoLucky Date: Fri, 10 Oct 2025 21:38:36 +0200 Subject: [PATCH 3/3] fix: forgot to revert settings change --- Assets/settings-default.json | 2 +- Commons/Settings.qml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Assets/settings-default.json b/Assets/settings-default.json index 29ebba85..9b63d3ae 100644 --- a/Assets/settings-default.json +++ b/Assets/settings-default.json @@ -1,5 +1,5 @@ { - "settingsVersion": 16, + "settingsVersion": 15, "bar": { "position": "top", "backgroundOpacity": 1, diff --git a/Commons/Settings.qml b/Commons/Settings.qml index 7e62b2cf..d8e8f4bf 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -125,7 +125,7 @@ Singleton { JsonAdapter { id: adapter - property int settingsVersion: 16 + property int settingsVersion: 15 // bar property JsonObject bar: JsonObject {