By default, the paste action doesn’t work when you press enter. Basically you have to press ctrl+v after choosing something from the clipboard history. This script will basically press ctrl+v for you after you choose an item to paste.
First, make sure you’ve ydotool installed, it’s in your package manager.
In your Sway config, add
#start ydotool daemon needed to paste in sway
exec export YDOTOOL_SOCKET=/tmp/.ydotool_socket
exec ydotoold
#start copyq server
exec copyq --start-server
#set clipboard manager to copyq
set $clipboard copyq toggle
In CopyQ, go to File > Commands and make sure that the “Advanced” checkbox on the right bottom is checked.
Create a new command of type Script and paste in the following code to use ydotool to paste so you don’t have to manually ctrl+v after selecting a snippet from history.
Source of the code below: https://github.com/hluk/copyq-commands/blob/master/Scripts/wayland-support.ini Thank you hluk!!!
/*
This adds support for KDE, Gnome, Sway and Hyprland Wayland sessions.
For Sway and Hyprland, this requires:
- `ydotool` utility to send copy/paste shortcuts to applications
- `grim` for taking screenshot
- `slurp` for selecting screenshot area
For KDE, this requires Spectacle for taking screenshots.
Getting current window title is not supported in KDE.
Global shortcut commands can be triggered with:
copyq triggerGlobalShortcut {COMMAND_NAME}
On Gnome, clipboard monitor is executed as X11 app using XWayland.
Links:
- https://github.com/ReimuNotMoe/ydotool
- https://github.com/emersion/grim
- https://github.com/emersion/slurp
*/
function isSway() {
return env('SWAYSOCK').length != 0
}
function isHyprland() {
return env('HYPRLAND_CMD').length != 0
}
function isGnome() {
return str(env('XAUTHORITY')).includes('mutter-Xwayland')
}
function run() {
var p = execute.apply(this, arguments)
if (!p) {
throw 'Failed to start ' + arguments[0]
}
if (p.exitCode && p.stderr.length) {
throw 'Failed command ' + arguments[0] + ': ' + str(p.stderr)
}
return p.stdout
}
function swayGetTree() {
var tree = run('swaymsg', '-t', 'get_tree')
return JSON.parse(str(tree))
}
function swayFindFocused(tree) {
var nodes = tree['nodes'].concat(tree['floating_nodes'])
for (var i in nodes) {
var node = nodes[i]
if (node['focused'])
return node
var focusedNode = swayFindFocused(node)
if (focusedNode)
return focusedNode
}
return undefined
}
function hyprlandFindFocused() {
var window = run('hyprctl', '-j', 'activewindow')
return JSON.parse(str(window))
}
function sendShortcut(...shortcut) {
sleep(100)
run('ydotool', 'key', ...shortcut)
}
global.currentWindowTitle = function() {
if (isSway()) {
var tree = swayGetTree()
var focusedNode = swayFindFocused(tree)
return focusedNode ? focusedNode['name'] : ''
} else if (isHyprland()) {
var focusedWindow = hyprlandFindFocused()
return focusedWindow ? focusedWindow['title'] : ''
}
return ''
}
global.paste = function() {
sendShortcut('42:1', '110:1', '110:0', '42:0')
}
var copy_ = global.copy
global.copy = function() {
if (arguments.length == 0) {
sendShortcut('29:1', '46:1', '46:0', '29:0')
} else {
copy_.apply(this, arguments)
}
}
global.focusPrevious = function() {
hide()
}
var monitorClipboard_ = monitorClipboard
monitorClipboard = function() {
if (isGnome() && env('QT_QPA_PLATFORM') != 'xcb') {
serverLog('Starting X11 clipboard monitor')
setEnv('QT_QPA_PLATFORM', 'xcb')
execute('copyq', '--clipboard-access', 'monitorClipboard')
serverLog('Stopping X11 clipboard monitor')
return
}
return monitorClipboard_()
}
var onClipboardChanged_ = onClipboardChanged
onClipboardChanged = function() {
var title = currentWindowTitle()
if (title)
setData(mimeWindowTitle, title)
onClipboardChanged_()
}
screenshot = function(format, screenName) {
if (isSway() || isHyprland())
return run('grim', '-t', format || 'png', '-')
return run(
'spectacle',
'--background',
'--nonotify',
'--pointer',
'--output',
'/dev/stdout',
)
}
screenshotSelect = function(format, screenName) {
if (isSway() || isHyprland()) {
var geometry = run('slurp')
geometry = str(geometry).trim()
return run('grim', '-c', '-g', geometry, '-t', format || 'png', '-')
}
return run(
'spectacle',
'--background',
'--nonotify',
'--pointer',
'--region',
'--output',
'/dev/stdout',
)
}
global.triggerGlobalShortcut = function(commandName) {
var cmds = commands()
for (var i in cmds) {
var cmd = cmds[i]
if (cmd.isGlobalShortcut && cmd.enable && cmd.name == commandName)
return action(cmd.cmd)
}
throw 'Failed to find enabled global command with given name'
}