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
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
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.
(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
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?
Created attachment 187457 [details] wrongfractionalqwindowdpr I've made a small C++ project that can demonstrate the issue if you are using a fractional scale.
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.