Open cafetestrest opened 1 week ago
Behaviour is the same no matter what variable QT_QPA_PLATFORM is set to.
@cafetestrest, I have exactly the same issue, also on hyprland, are you using nixos?
@cafetestrest ahh, I just saw your first screenshot and it looks like you are also on nixos, pretty sure it has to do with that we are on nixos ...
@gowallasnewpony @hluk , I got it working by using the following workaround:
function fish_greeting
if not pidof copyq > /dev/null
env QT_QPA_PLATFORM=wayland copyq --start-server &
end
end
Does anyone happen to know why would it work like this? My suspicion is that hyprland with exec-once starts copyq differently than terminal (perhaps by user rather than root/service...). Any feedback is appreciated.
So this does not seem like a bug in CopyQ, but a problem with how ydotool is set up.
Can you update to the latest Wayland Support command? It should print more details if a command fails.
Hi @hluk ,
My ydotool config looks like following (I've tried to remove as much hardening as possible): https://github.com/cafetestrest/nixos/blob/72b1b7ee096a6e5b43bd7173cacda5ca54cdbf29/nixos/ydotool.nix
I think I'm using the latest Wayland Support command, the one that I have right now has the following content (I was unable to locate newer one from this):
[Command]
Command="
/*
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.exit_code !== 0) {
throw 'Failed command ' + arguments[0] + ': ' + str(p.stderr)
}
return p.stdout
}
function swayGetTree() {
var tree = run('swaymsg', '--raw', '--type', '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'
}"
Icon=
IsScript=true
Name=Wayland Support
Oh, sorry, that seems up-to-date - specifically this line: throw 'Failed command ' + arguments[0] + ': ' + str(p.stderr)
But I wonder why ydotool
does not print any error. Maybe it prints an error message to stdout
? Or showing the p.exit_code
might help if these are well-defined in ydotool
.
Hi @hluk I have the issue with CopyQ with Wayland on Hyprland still after importing Wayland script.![1](https://github.com/hluk/CopyQ/assets/111571367/eefa33b9-1e6c-41df-85d9-8aa0e8bb2428)
This only happens if I start it with either some startup script or use hyprland's own exec-once to start copyq server. You can see on this screenshot that I have all environments and ydotool service running, also ydotool when run from terminal, it works as expected.
It does resolve itself once I stop the copyq and start it again myself manually from terminal. That way it does work perfectly fine, are you familiar with said issue and do you happen to know a fix for it?
This screenshot is after I've exited copyq and started it again from terminal using:
You can see that on 15:24 it failed, while at 15:40 it works as expected.