From 3aa724ee1a2344d2357b3163aa09113236c54f05 Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Sat, 9 Aug 2025 00:44:00 +0200 Subject: [PATCH] Fix Applauncher copy once and for all --- Bar/Modules/Applauncher.qml | 117 +++++++++++++++++++++++++++++++++--- 1 file changed, 110 insertions(+), 7 deletions(-) diff --git a/Bar/Modules/Applauncher.qml b/Bar/Modules/Applauncher.qml index e3f15c9..3672200 100644 --- a/Bar/Modules/Applauncher.qml +++ b/Bar/Modules/Applauncher.qml @@ -15,7 +15,7 @@ PanelWithOverlay { id: clipboardTimer interval: 1000 repeat: true - running: appLauncherPanel.visible && searchField.text.startsWith(">clip") + running: appLauncherPanel.visible onTriggered: { updateClipboardHistory(); } @@ -95,7 +95,9 @@ PanelWithOverlay { onExited: (exitCode, exitStatus) => { if (exitCode === 0) { const content = String(stdout.text).trim(); - if (content && !content.startsWith("vscode-file://")) { + // Only filter out self path to avoid capturing this file + const isSelfPath = content.indexOf("/home/lysec/.config/quickshell/Bar/Modules/Applauncher.qml") !== -1; + if (content && !isSelfPath) { const entry = { type: 'text', content: content, @@ -139,6 +141,101 @@ PanelWithOverlay { stdout: StdioCollector {} } + Process { + id: clipboardImageCopyProcess + property string mimeType: "" + property string pendingBase64: "" + // Simple FIFO queue for repeated copy requests + property var queue: [] + stdinEnabled: true + + command: [ + "sh", + "-c", + "base64 -d | wl-copy -t '" + mimeType + "'" + ] + function copyBase64(mime, base64) { + // If a copy is in progress or pending, queue the next request + if (running || (pendingBase64 && pendingBase64.length > 0)) { + var q = queue.slice(); + q.push({ mime: mime, base64: base64 }); + queue = q; + return; + } + mimeType = mime; + pendingBase64 = base64; + running = true; + } + onStarted: { + // ensure stdin is open for each new run + stdinEnabled = true; + if (pendingBase64 && pendingBase64.length > 0) { + write(pendingBase64); + } + // Close stdin to signal EOF so base64 exits + stdinEnabled = false; + } + onExited: (exitCode, exitStatus) => { + pendingBase64 = ""; + // re-open stdin for the next run so we can copy repeatedly + stdinEnabled = true; + if (queue.length > 0) { + var next = queue[0]; + // pop front + var q2 = queue.slice(1); + queue = q2; + mimeType = next.mime; + pendingBase64 = next.base64; + running = true; + } + } + stdout: StdioCollector {} + } + + // Process to copy arbitrary text via stdin to avoid quoting/ARG_MAX issues + Process { + id: clipboardTextCopyProcess + property string pendingText: "" + property var queue: [] + stdinEnabled: true + + command: [ + "sh", + "-c", + "cat | wl-copy -t text/plain;charset=utf-8" + ] + + function copyText(text) { + if (running || (pendingText && pendingText.length > 0)) { + var q = queue.slice(); + q.push(text); + queue = q; + return; + } + pendingText = text; + running = true; + } + + onStarted: { + stdinEnabled = true; + if (pendingText && pendingText.length > 0) { + write(pendingText); + } + stdinEnabled = false; + } + onExited: (exitCode, exitStatus) => { + pendingText = ""; + stdinEnabled = true; + if (queue.length > 0) { + var next = queue[0]; + queue = queue.slice(1); + pendingText = next; + running = true; + } + } + stdout: StdioCollector {} + } + function updateClipboardHistory() { @@ -202,6 +299,8 @@ PanelWithOverlay { root.selectedIndex = 0; root.appModel = DesktopEntries.applications.values; root.updateFilter(); + // Start clipboard refresh immediately on open so >clip is ready + updateClipboardHistory(); } function hidePanel() { @@ -316,10 +415,10 @@ PanelWithOverlay { type: 'image', data: clip.data, execute: function() { - // Convert base64 image data back to binary and copy to clipboard + // Restore image via stdin to avoid command-length limits const base64Data = clip.data.split(',')[1]; - clipboardTypeProcess.command = ["sh", "-c", `echo '${base64Data}' | base64 -d | wl-copy -t '${clip.mimeType}'`]; - clipboardTypeProcess.running = true; + clipboardImageCopyProcess.copyBase64(clip.mimeType, base64Data); + Quickshell.execDetached(["notify-send", "Clipboard", "Image copied: " + clip.mimeType]); } }; } else { @@ -343,7 +442,11 @@ PanelWithOverlay { content: previewContent || textContent, icon: "content_paste", execute: function() { - Quickshell.execDetached(["sh", "-c", "echo -n '" + textContent.replace(/'/g, "'\\''") + "' | wl-copy"]); + // Set Quickshell clipboard as primary path; also stream to wl-copy for system clipboard + Quickshell.clipboardText = String(textContent); + clipboardTextCopyProcess.copyText(String(textContent)); + var preview = (textContent.length > 50) ? textContent.slice(0,50) + "…" : textContent; + Quickshell.execDetached(["notify-send", "Clipboard", "Text copied: " + preview]); } }; } @@ -787,7 +890,7 @@ PanelWithOverlay { anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom - height: 1 + height: Math.max(1, 1 * Theme.scale(screen)) color: Theme.outline opacity: index === appList.count - 1 ? 0 : 0.10 }