hluk / CopyQ

Clipboard manager with advanced features
GNU General Public License v3.0
8.7k stars 441 forks source link

window placement issue in multi-mon environment #1595

Open laur89 opened 3 years ago

laur89 commented 3 years ago

Describe the bug Copyq window placement is erratic. In my setup it's okay on the leftmost screen (screen 2), okay-ish on screen 0 (laptop internal screen, right-most display) with the caveat that the window is always placed on top-left corner on screen 0. However, opening copyq when screen 1 is active, the behavior is as if it were opened on screen 0, as in cursor is moved to screen 0 and window is positioned there in the top-left corner.

a) when screen 1 is active and copyq is toggled, it opens on screen 0 as described above. b) while the window is opened, the user drags it left onto screen 1 c) copyq window is closed d) copyq is toggled (still being on screen 1) e) window opens correctly in the position it was previously closed on, ie on screen 1 f) window is closed g) copyq is toggled again -> we're back to start, ie window gets opened on screen 0 again

xrandr --listactivemonitors 
Monitors: 3
 0: +*eDP 1920/309x1080/174+4000+1480  eDP
 1: +DisplayPort-3 1440/597x2560/336+2560+0  DisplayPort-3
 2: +DisplayPort-4 2560/597x1440/336+0+136  DisplayPort-4

Displays are positioned, from left-to-right, as 2,1,0. Also note screen 1 is in portrait. screenshot from arandr showing the screen placement.

copyq_geometry.ini:

[Options]
MainWindow_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\x11\x5\0\0\x6\xbd\0\0\x14\xf6\0\0\b\xe1\0\0\x11\a\0\0\x6\xbd\0\0\x14\xf4\0\0\b\xdf\0\0\0\0\0\0\0\0\a\x80\0\0\x11\a\0\0\x6\xbd\0\0\x14\xf4\0\0\b\xdf)
MainWindow_geometry_1920x1080=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\x11\x5\0\0\x6\xbd\0\0\x14\xf6\0\0\b\xe1\0\0\x11\a\0\0\x6\xbd\0\0\x14\xf4\0\0\b\xdf\0\0\0\0\0\0\0\0\a\x80\0\0\x11\a\0\0\x6\xbd\0\0\x14\xf4\0\0\b\xdf)
MainWindow_geometry_screen_2=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\n\xba\0\0\x5/\0\0\xe\xab\0\0\aS\0\0\n\xbc\0\0\x5/\0\0\xe\xa9\0\0\aQ\0\0\0\x2\0\0\0\0\x5\xa0\0\0\n\xbc\0\0\x5/\0\0\xe\xa9\0\0\aQ)
MainWindow_geometry_screen_2_1440x2560=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\n\xba\0\0\x5/\0\0\xe\xab\0\0\aS\0\0\n\xbc\0\0\x5/\0\0\xe\xa9\0\0\aQ\0\0\0\x2\0\0\0\0\x5\xa0\0\0\n\xbc\0\0\x5/\0\0\xe\xa9\0\0\aQ)

copyq.conf

CopyQ Clipboard Manager v3.13.0
Qt: 5.14.2
Compiler: GCC
Arch: x86_64-little_endian-lp64
OS: Debian GNU/Linux bullseye/sid

Using i3 window manager.

hluk commented 3 years ago

Restoring window geometry in X11 is very hard, maybe even impossible in some cases. :(

I can add option to disable the geometry restoring on application side and leave it to the window manager.

laur89 commented 3 years ago

If it's not crazy amount of effort, might make sense to make it a togglable option.

hluk commented 3 years ago

If it's not crazy amount of effort, might make sense to make it a togglable option.

The problem is that it may work even worse when it's disabled.

BTW, you can check the debug logs for window geometry (store/restore operations); in bash it's something like:

copyq exit
COPYQ_LOG_LEVEL=DEBUG copyq |& grep -i geometry

Moving and resizing window should print "Save geometry ..." message; reopening window should print "Restore geometry ...".

laur89 commented 3 years ago

Weirdest thing, after restarting the server it's working fine now. My guess is that geometry had not been saved for one of the screens. First when I copied the geometry file it had these contents:

[Options]
MainWindow_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\x13\x30\0\0\a\xdd\0\0\x17!\0\0\n\x1\0\0\x13\x32\0\0\a\xdd\0\0\x17\x1f\0\0\t\xff\0\0\0\0\0\0\0\0\a\x80\0\0\x13\x32\0\0\a\xdd\0\0\x17\x1f\0\0\t\xff)
MainWindow_geometry_1920x1080=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\x13\x30\0\0\a\xdd\0\0\x17!\0\0\n\x1\0\0\x13\x32\0\0\a\xdd\0\0\x17\x1f\0\0\t\xff\0\0\0\0\0\0\0\0\a\x80\0\0\x13\x32\0\0\a\xdd\0\0\x17\x1f\0\0\t\xff)

Then after opening copyq on screen 1 and then manually dragging it from screen 0 to 1, the geometry file had contents in the initial post.

Edit, also, can see that the geometry file now looks like this:

[Options]
MainWindow_geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\x10\xc4\0\0\x6\xc1\0\0\x14\xb5\0\0\b\xe5\0\0\x10\xc6\0\0\x6\xc1\0\0\x14\xb3\0\0\b\xe3\0\0\0\0\0\0\0\0\a\x80\0\0\x10\xc6\0\0\x6\xc1\0\0\x14\xb3\0\0\b\xe3)
MainWindow_geometry_1920x1080=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\x10\xc4\0\0\x6\xc1\0\0\x14\xb5\0\0\b\xe5\0\0\x10\xc6\0\0\x6\xc1\0\0\x14\xb3\0\0\b\xe3\0\0\0\0\0\0\0\0\a\x80\0\0\x10\xc6\0\0\x6\xc1\0\0\x14\xb3\0\0\b\xe3)
MainWindow_geometry_screen_1=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\x2\xce\0\0\x2[\0\0\x6\xbf\0\0\x4\x7f\0\0\x2\xd0\0\0\x2[\0\0\x6\xbd\0\0\x4}\0\0\0\x1\0\0\0\0\n\0\0\0\x2\xd0\0\0\x2[\0\0\x6\xbd\0\0\x4})
MainWindow_geometry_screen_1_2560x1440=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\x2\xce\0\0\x2[\0\0\x6\xbf\0\0\x4\x7f\0\0\x2\xd0\0\0\x2[\0\0\x6\xbd\0\0\x4}\0\0\0\x1\0\0\0\0\n\0\0\0\x2\xd0\0\0\x2[\0\0\x6\xbd\0\0\x4})
MainWindow_geometry_screen_2=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\n\xcf\0\0\x5.\0\0\xe\xc0\0\0\aR\0\0\n\xd1\0\0\x5.\0\0\xe\xbe\0\0\aP\0\0\0\x2\0\0\0\0\x5\xa0\0\0\n\xd1\0\0\x5.\0\0\xe\xbe\0\0\aP)
MainWindow_geometry_screen_2_1440x2560=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\n\xcf\0\0\x5.\0\0\xe\xc0\0\0\aR\0\0\n\xd1\0\0\x5.\0\0\xe\xbe\0\0\aP\0\0\0\x2\0\0\0\0\x5\xa0\0\0\n\xd1\0\0\x5.\0\0\xe\xbe\0\0\aP)
MainWindow_state=@ByteArray(\0\0\0\xff\0\0\0\0\xfd\0\0\0\x1\0\0\0\x3\0\0\0\0\0\0\0\0\xfc\x1\0\0\0\x1\xfb\0\0\0*\0\x64\0o\0\x63\0k\0W\0i\0\x64\0g\0\x65\0t\0I\0t\0\x65\0m\0P\0r\0\x65\0v\0i\0\x65\0w\0\0\0\0\0\xff\xff\xff\xff\0\0\0:\0\xff\xff\xff\0\0\x3\xc6\0\0\x2\xf\0\0\0\x4\0\0\0\x4\0\0\0\b\0\0\0\b\xfc\0\0\0\x3\0\0\0\0\0\0\0\x1\0\0\0\x1c\0t\0o\0o\0l\0\x42\0\x61\0r\0T\0\x61\0\x62\0T\0r\0\x65\0\x65\x2\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x1\0\0\0\x1\0\0\0\xe\0t\0o\0o\0l\0\x42\0\x61\0r\x3\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x2\0\0\0\x1\0\0\0\x1a\0t\0o\0o\0l\0\x42\0\x61\0r\0T\0\x61\0\x62\0\x42\0\x61\0r\0\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0)

So there might be an issue with storing the geometry, but once it's there it's all good.

Quite confident that manual window moving was the fix, as the current OS install has been live for ~couple of weeks now, and this is the first time the window placement works as expected.

hluk commented 3 years ago

Hmm, let me try to review the source code. There is probably some inconsistency in the option names when geometry is stored and restored.

laur89 commented 3 years ago

There's something more at play here. After restarting X the issue came about again. As previously, restarting copyq fixed it.

Could there be a race condition between xrandr and copyq? As in xserver is started, copyq starts, xrandr configures external monitors. Which likely would also have implications on (re-)docking a computer.

I'll try to gather some debug output for geometry.

hluk commented 3 years ago

I found out that, at least on Wayland, restoring window geometry on a screen with a higher DPI did not work properly (https://github.com/hluk/CopyQ/commit/a7d1609dc266720a6520117f0edf88d74566cb86). Not sure if it's a Qt/Wayland bug.

NOTE: This problem would show up in debug logs (COPYQ_LOG_LEVEL=DEBUG) as "Resize window: ..." or "Move window: ..." message when opening the main window.

blueyed commented 3 years ago

FWIW: there have been changes in that regard in CopyQ 4 - in case you want to try / verify it there. (I've come here due to a regression in that regard/area, which apparently is fixed in development builds already though: https://github.com/hluk/CopyQ/issues/1624)

blueyed commented 3 years ago

I have the problem that it is not showing up properly when run from the laptop's screen (eDP1), which is right of the external screen:

Monitors: 2
 0: +*eDP1 1920/280x1080/160+1920+120  eDP1
 1: +HDMI1 1920/520x1200/330+0+0  HDMI1

I have "Open windows on current screen" checked, using X.org with awesomeWM.

First I've opened it on the external screen four times (given the shortcut); the first two lines include the message from startup. Note that it is "bumpy" already: it alternates between being in the top left and the middle of the screen..! (edit: this changed when I've moved it to the lower right explicitly later)

% COPYQ_LOG_LEVEL=DEBUG copyq |& grep -i '[g]eometry'
DEBUG: Geometry: Window "MainWindow": Restore geometry "Options/MainWindow_geometry_screen_1": 645x421,157,89 -> 645x421,157,89
DEBUG: Geometry: Window "MainWindow": Restore geometry "Options/MainWindow_geometry_screen_1": 645x421,157,89 -> 645x421,157,89

DEBUG: Geometry: Window "MainWindow": Restore geometry "Options/MainWindow_geometry_screen_1": 645x421,159,91 -> 645x421,159,91

DEBUG: Geometry: Window "MainWindow": Restore geometry "Options/MainWindow_geometry_screen_1": 645x421,159,91 -> 645x421,159,91

DEBUG: Geometry: Window "MainWindow": Restore geometry "Options/MainWindow_geometry_screen_1": 645x421,159,91 -> 645x421,159,91

When opening it on the internal screen it does not show up at all (I've minimized/maximized it here):

DEBUG: Geometry: Window "MainWindow": Restore geometry "Options/MainWindow_geometry_screen_1": 645x421,157,89 -> 645x421,157,89
DEBUG: Geometry: Window "MainWindow": Move window: 3840, 240
DEBUG: Geometry: Window "MainWindow": Restore geometry "Options/MainWindow_geometry_960x540": 645x421,2077,179 -> 476x520,3840,240
DEBUG: Geometry: Window "MainWindow": Move window: 3840, 240
DEBUG: Geometry: Window "MainWindow": Restore geometry "Options/MainWindow_geometry_960x540": 476x520,2164,132 -> 476x520,3842,242

And then resized it using awesomeWM (using a keyboard shortcut for the focused, but invisible window):

DEBUG: Geometry: Window "MainWindow": Save geometry "Options/MainWindow_geometry_960x540": 476x258,2402,401

Opening it again made it not show up again then:

DEBUG: Geometry: Window "MainWindow": Move window: 3840, 399
DEBUG: Geometry: Window "MainWindow": Restore geometry "Options/MainWindow_geometry_960x540": 476x258,2164,263 -> 476x258,3842,401

Note the property name for the internal screen: "Options/MainWindow_geometry_960x540", in contrast to the external one ("Options/MainWindow_geometry_screen_1"). I can see that it should maybe have some ID in there, and while the size might be useful therein also, it certainly is not the correct one.

CopyQ Clipboard Manager v4.1.0
Qt: 5.15.2
KNotifications: 5.81.0
Compiler: GCC
Arch: x86_64-little_endian-lp64
OS: Arch Linux
laur89 commented 3 years ago

@blueyed does restarting copyq process help in any way after all the screens have been attached?

blueyed commented 3 years ago

@laur89 It works now better on another Xorg server/display. On the other one I've restarted it of course, to being able to run it with debug output.

% xrandr --listactivemonitors
Monitors: 2
 0: +*eDP1 1920/280x1080/160+1920+120  eDP1
 1: +HDMI1 1920/520x1200/330+0+0  HDMI1

On this (X.org) display it looks like this, opening it a few times on the internal screen:

DEBUG: Geometry: Window "MainWindow": Move window: 3840, 240
DEBUG: Geometry: Window "MainWindow": Restore geometry "Options/MainWindow_geometry": 645x421,2077,179 -> 645x421,3840,240
DEBUG: Geometry: Window "MainWindow": Geometry blocked until hidden: 1
DEBUG: Geometry: Window "MainWindow": Move window: 3840, 320
DEBUG: Geometry: Window "MainWindow": Geometry blocked until hidden: 0
DEBUG: Geometry: Window "MainWindow": Geometry blocked until hidden: 1
DEBUG: Geometry: Window "MainWindow": Move window: 3840, 320
DEBUG: Geometry: Window "MainWindow": Geometry blocked until hidden: 0

On the external display:

DEBUG: Geometry: Window "MainWindow": Geometry blocked until hidden: 1
DEBUG: Geometry: Window "MainWindow": Move window: 211, 198
DEBUG: Geometry: Window "MainWindow": Geometry blocked until hidden: 0
DEBUG: Geometry: Window "MainWindow": Geometry blocked until hidden: 1
DEBUG: Geometry: Window "MainWindow": Move window: 211, 198
DEBUG: Geometry: Window "MainWindow": Geometry blocked until hidden: 0
DEBUG: Geometry: Window "MainWindow": Geometry blocked until hidden: 1
DEBUG: Geometry: Window "MainWindow": Move window: 211, 198
DEBUG: Geometry: Window "MainWindow": Geometry blocked until hidden: 0

Resized/moved the window, which did not save the position, but the width/height only:

DEBUG: Geometry: Window "MainWindow": Geometry blocked until hidden: 1
DEBUG: Geometry: Window "MainWindow": Move window: 211, 198
DEBUG: Geometry: Window "MainWindow": Geometry blocked until hidden: 0
DEBUG: Geometry: Window "MainWindow": Geometry blocked until hidden: 1
DEBUG: Geometry: Window "MainWindow": Move window: 211, 198
DEBUG: Geometry: Window "MainWindow": Geometry blocked until hidden: 0
blueyed commented 2 years ago

@hluk

Restoring window geometry in X11 is very hard, maybe even impossible in some cases. :(

I can add option to disable the geometry restoring on application side and leave it to the window manager.

Any input here? I would prefer an option to not change window placement at all also (i.e. neither restore it to the old position nor put it on the current screen). I've tried having rules for / with awesomeWM to handle it, but apparently CopyQ's own handling happens afterwards still. (I am using v5.0.0 currently)

But it might actually also be fixable like you've imagined:

Hmm, let me try to review the source code. There is probably some inconsistency in the option names when geometry is stored and restored.

(Just to clarify: it was working before, and I've kept using an older version for a while due to this.)

hluk commented 2 years ago

I would prefer an option to not change window placement at all also (i.e. neither restore it to the old position nor put it on the current screen).

Sure. Quick fix here: https://github.com/hluk/CopyQ/pull/1802

laur89 commented 2 years ago

FYI I recently upgraded from v3.x to 6.0.1, and now the restore was completely broken - copyq was always launched on my central screen; suspect that's what @blueyed mentioned. After disabling geometry restoration (as per #1802) at least window is displayed on a correct screen.

hluk commented 2 years ago

I'm trying to improve the window-geometry-restore behavior in fc307126c9cfd165222f0d598abae53332162e81.