diff --git a/Modules/Panels/Launcher/Launcher.qml b/Modules/Panels/Launcher/Launcher.qml index 6c23857f1..a73fd27a1 100644 --- a/Modules/Panels/Launcher/Launcher.qml +++ b/Modules/Panels/Launcher/Launcher.qml @@ -376,21 +376,21 @@ SmartPanel { // Search handling function updateResults() { results = []; - activeProvider = null; + var newActiveProvider = null; // Check for command mode if (searchText.startsWith(">")) { // Find provider that handles this command for (let provider of providers) { if (provider.handleCommand && provider.handleCommand(searchText)) { - activeProvider = provider; + newActiveProvider = provider; results = provider.getResults(searchText); break; } } // Show available commands if just ">" or filter commands if partial match - if (!activeProvider) { + if (!newActiveProvider) { // Collect all commands from all providers let allCommands = []; for (let provider of providers) { @@ -436,6 +436,8 @@ SmartPanel { } } + // Update activeProvider only after computing new state to avoid UI flicker + activeProvider = newActiveProvider; selectedIndex = 0; } @@ -587,6 +589,21 @@ SmartPanel { function activate() { if (results.length > 0 && results[selectedIndex]) { const item = results[selectedIndex]; + const provider = item.provider || currentProvider; + + // Check if auto-paste is enabled and provider/item supports it + if (Settings.data.appLauncher.autoPasteClipboard && provider && provider.supportsAutoPaste && item.autoPasteText) { + // Call optional pre-paste callback (e.g., to record usage) + if (item.onAutoPaste) { + item.onAutoPaste(); + } + root.closeImmediately(); + Qt.callLater(() => { + ClipboardService.pasteText(item.autoPasteText); + }); + return; + } + if (item.onActivate) { item.onActivate(); } diff --git a/Modules/Panels/Launcher/Providers/EmojiProvider.qml b/Modules/Panels/Launcher/Providers/EmojiProvider.qml index ce6c7555a..246ea0be4 100644 --- a/Modules/Panels/Launcher/Providers/EmojiProvider.qml +++ b/Modules/Panels/Launcher/Providers/EmojiProvider.qml @@ -14,6 +14,7 @@ Item { property string supportedLayouts: "grid" // Only grid layout for emoji property int preferredGridColumns: 7 // More columns for compact emoji display property real preferredGridCellRatio: 1.0 // Square cells like apps + property bool supportsAutoPaste: true // Emoji can be auto-pasted property string selectedCategory: "recent" property bool showsCategories: true // Default to showing categories @@ -149,7 +150,11 @@ Item { "icon": null, "isImage": false, "displayString": emojiChar, + "autoPasteText": emojiChar, "provider": root, + "onAutoPaste": function () { + EmojiService.recordUsage(emojiChar); + }, "onActivate": function () { EmojiService.copy(emojiChar); launcher.close(); diff --git a/Services/Keyboard/ClipboardService.qml b/Services/Keyboard/ClipboardService.qml index e2cb271db..664c19c9b 100644 --- a/Services/Keyboard/ClipboardService.qml +++ b/Services/Keyboard/ClipboardService.qml @@ -339,6 +339,17 @@ Singleton { pasteProc.running = true; } + // Paste plain text: copy to clipboard and simulate Ctrl+Shift+V + function pasteText(text) { + if (!text) + return; + // Escape single quotes for shell + const escaped = text.replace(/'/g, "'\\''"); + const cmd = `printf '%s' '${escaped}' | wl-copy && wtype -M ctrl -M shift v`; + pasteProc.command = ["sh", "-lc", cmd]; + pasteProc.running = true; + } + function deleteById(id) { if (!root.cliphistAvailable) { return;