“Fixing” spectacle’s offset bug on Hi-DPI screens

Spectacle is KDE‘s screenshot utility. Since the beginning of time (but only reported years ago), it has a bug that annoys people using multiple high or mixed PPI monitors. For example, consider my desktop. It looks like this:

~11.5k x 2160 — it was resized to something more in-line for an online blog.

5120×2160 at 34″ gives us a PPI (pixels per inch) of about 160. This has its benefits, but also some drawbacks — especially on Linux. Wayland solves some of the issues in that regard as it allows you to set scaling factor on per-display basis. Unfortunately, there are show-stoppers that prevent me from going that way.

This leaves us with Xorg. Xorg doesn’t do mixed PPI setups at all, but there’s workarounds. You can tell Xorg to pretend your low PPI monitors run at a higher resolution than they actually are. This has downsides (blurred image), but it beats the alternative. So you set your scaling factor to your highest PPI monitor and “supersample” other monitors appropriately.

The ‘scaling factor’ is set by your desktop environment — in my case, KDE (which uses Qt). If you set this scaling factor above 1, you will sometimes into a bug (in Qt). It pops up in a few different places, most annoying of which is when you want to take a screenshot of a rectangular region.

Compare to the first screenshot. Notice the extra offset.

The unwelcome offset and duplication of the screenshot area renders some parts of the screen impossible to screenshot using rectangular selection. This is annoying. Let’s fix it.

Oh why, what a jolly good idea.

Window-herding

KDE’s window manager, kwin, is pretty nice thing. Among other things, it allows us to tell windows and programs how to behave. We can force windows to stay always on top, we can force windows to open on a specific monitor, we can prevent windows from being closed. We can make windows transparent and tons of other things, but most importantly: we can make windows appear at exact location we want them.

Lots and lots and lots of options.

The still frame of our screen on which we select is technically a full screen window covering all three screens. We only need to tell kwin how to recognize that window and move it to where we want. In order to that, we need to know two things: window class and window title.

… both of which are helpfully marked with question marks.

We don’t know them yet, but the ‘Detect Window Properties’ button looks inviting — except it doesn’t work when we try to detect properties of our “draw rectangle for screenshot here” window.

Okay then, we’ll run xprop in the terminal while the window for drawing rectangular selection is active and click it.

… get ready for a whole lot of this.

Fine, clicking the window is not the only way to coax data we want out of xprop. We can give it the window id, like so:

xprop -id $(xdotool search --pid `pidof spectacle`)

This works. We set this command to run while rectangular selection for spectacle is active, we get what we want:

To be honest — seeing the ‘user specified location: -864px’ bit is what gave me the idea of trying to only move the window. My original idea was much more contrived (trying to convince spectacle to start on the leftmost screen, which would also solve the issue)

Window class: spectacle. Window title: Spectacle (as opposed to filename — Spectacle of the regular window). This is enough for us to only move the rectangular selection window, while keeping the spectacle window that appears after we’ve taken a screenshot where it is.

Kwin rule is thus written. Another screenshot is taken. The issue persists.

How to waste an hour.

Where there’s a whip, there’s a way

But we’re not giving up quite yet. The good thing about Linux is that you can do a lot of things via terminal — such as, move windows around. xdotool can do that. The command looks like this:

xdotool windowmove <window id> <x> <y>

And we already know how to get window id. We put what we know together and paste our command to the terminal:

sleep 5; xdotool windowmove $(xdotool search --pid `pidof spectacle` | tail -n 1) 0 0

During the five seconds of grace, we try to screenshot a rectangular selection of the screen. We get the first real success of the evening — after the five seconds are up, the rectangular selection window moves to where it should be.

Now, let’s try to launch spectacle’s rectangular selection and the code that corrects its position at the same time:

spectacle --region & sleep 1; xdotool windowmove $(xdotool search --pid `pidof spectacle` | tail -n 1) 0 0

… and now, it suddenly doesn’t work anymore. Spectacle launches, but the rectangular selection window remains offset. Of course, we can swap positions of spectacle and commands that correct the offset of rectangular selection window, like this:

$(sleep 5; xdotool windowmove $(xdotool search --pid `pidof spectacle` | tail -n 1) 0 0) & spectacle --region

This works, but:

Wouldn’t be nice if this would happen when I pressed ‘print screen’?

Yes, actually, yes it would. So we open the custom shortcuts settings, provide a key shortcut, paste our command into the command box.

Visual representation.

We click okay. We try to take a screenshot. Nothing happens.

Fuck.

But let’s not give up. Files with bash scripts also counts as a command. We thus take this command and paste it into a file (and take care to not forget to put the #!/bin/bash in the topmost line), save, make it executable and jot down the path to the file in our custom keyboard shortcut.

And it finally works — after about two hours of experimenting.

The end.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.