Bug 510569 - QWindow gives wrong devicePixelRatio with fractional scales
Summary: QWindow gives wrong devicePixelRatio with fractional scales
Status: CONFIRMED
Alias: None
Product: kwin
Classification: Plasma
Component: wayland-generic (other bugs)
Version First Reported In: 6.4.5
Platform: Arch Linux Linux
: NOR normal
Target Milestone: ---
Assignee: KWin default assignee
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2025-10-13 17:39 UTC by vincentv42
Modified: 2025-12-22 17:30 UTC (History)
6 users (show)

See Also:
Latest Commit:
Version Fixed/Implemented In:
Sentry Crash Report:


Attachments
wrongfractionalqwindowdpr (857 bytes, application/zip)
2025-12-09 17:47 UTC, Noah Davis
Details

Note You need to log in before you can comment on or make changes to this bug.
Description vincentv42 2025-10-13 17:39:43 UTC
SUMMARY
Size label displays incorrect pixel dimensions when using fractional scaling (125%, 150%, etc.)

STEPS TO REPRODUCE
1. Enable fractional scaling in System Settings (e.g., set scaling to 125%)
2. Open Spectacle
3. Make a screen selection or observe the full screen size in the toolbar
4. Check the pixel dimensions shown in the size label

OBSERVED RESULT
The size label shows incorrect dimensions that don't match the actual pixel size. With 125% scaling, the dimensions appear to be multiplied by 2.0 instead of 1.25.

EXPECTED RESULT
The label should display the correct physical pixel dimensions of the selection.

SOFTWARE/OS VERSIONS
Operating System: Arch Linux 
KDE Plasma Version: 6.4.5
KDE Frameworks Version: 6.19.0
Qt Version: 6.10.0
Kernel Version: 6.17.1-arch1-1 (64-bit)
Graphics Platform: Wayland
Processors: 16 × AMD Ryzen 7 PRO 6850U with Radeon Graphics
Memory: 16 Gio of RAM (13.4 Gio usable)
Graphics Processor: AMD Radeon Graphics

The bug is present with spectacle 6.4.5-2 and with spectacle compiled from git master

in CaptureOverlay.qml the value of 
`return Geometry.rawSize(sz, SelectionEditor.devicePixelRatio)`
is wrong

sz is 1536x960 in my case and SelectionEditor.devicePixelRatio 2
Comment 1 Nate Graham 2025-10-13 19:04:49 UTC
Can confirm. I have a 2880x1800 screen I run at 175% scale. Spectacle says the dimensions are 3291x2057, which is exactly what you would get if you multiplied the native resolution by 2, and then divided by 1.75
Comment 2 Nate Graham 2025-12-09 05:59:25 UTC
The problem is in SelectionEditor::reset(), which sets the devicePixelRatio to qGuiApp->devicePixelRatio(), which in our cases returns a ceil()'ed version of the actual DPR (i.e. 2 instead of 1.25 or 1.75). It should be using QWindow::devicePixelRatio() instead so it can get a more accurate value.
Comment 3 Noah Davis 2025-12-09 14:56:09 UTC
(In reply to Nate Graham from comment #2)
> The problem is in SelectionEditor::reset(), which sets the devicePixelRatio
> to qGuiApp->devicePixelRatio(), which in our cases returns a ceil()'ed
> version of the actual DPR (i.e. 2 instead of 1.25 or 1.75). It should be
> using QWindow::devicePixelRatio() instead so it can get a more accurate
> value.

It's actually not supposed to return a ceiled value. It seems that the fundamental issue is that QScreen and QWindow/QQuickWindow/CaptureWindow return the wrong values for the DPR when there are two screens with one set to 1.25x DPR and the other set to 1.75x. It seems that the issue is not fixable from Spectacle's side.

Using windows instead of QScreen after ensuring that the windows are created first, which should provide correct DPRs:

> const auto windows = CaptureWindow::instances();
> Q_ASSERT(!windows.empty());
> const auto dpr = std::accumulate(windows.cbegin(), windows.cend(), 0.0, [](qreal dpr, CaptureWindow *w) {
>     qDebug() << w->devicePixelRatio();
>     return std::max(dpr, w->devicePixelRatio());
> });
> qDebug() << "max dpr" << dpr;

Output with 1.25 and 1.75 DPR screens:

> ❯ spectacle -i
> 2
> 2
> max dpr 2
Comment 4 Noah Davis 2025-12-09 17:23:28 UTC
It seems that the source of the DPR is KWin since KWin sends a fractional scale to QWaylandWindow (QPlatformWindow subclass, which gives the DPR to QWindow). Perhaps the bug is from there?
Comment 5 Noah Davis 2025-12-09 17:47:20 UTC
Created attachment 187457 [details]
wrongfractionalqwindowdpr

I've made a small C++ project that can demonstrate the issue if you are using a fractional scale.
Comment 6 Zamundaaa 2025-12-15 12:42:04 UTC
KWin does send the correct fractional scale events, the test app just queries the value at a time where the event hasn't arrived yet.