Bug 421634 - Presentation mode misrendering with two monitors and screen scaling
Summary: Presentation mode misrendering with two monitors and screen scaling
Status: RESOLVED WORKSFORME
Alias: None
Product: okular
Classification: Applications
Component: general (show other bugs)
Version: unspecified
Platform: Other Linux
: NOR normal
Target Milestone: ---
Assignee: Okular developers
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-05-16 19:13 UTC by Oliver Sander
Modified: 2020-05-28 12:15 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments
Screenshot showing the misrendering (319.14 KB, image/png)
2020-05-16 19:13 UTC, Oliver Sander
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Oliver Sander 2020-05-16 19:13:25 UTC
Created attachment 128524 [details]
Screenshot showing the misrendering

I have a setup with a built-in laptop monitor and one external monitor. Both are set to 1920x1080 resolution.  They are combined to a single virtual desktop, the external one (set to be the primary display) is stacked on top of the laptop monitor.

I use a screen scaling factor of 1.5 for both monitors:

~> echo $QT_SCREEN_SCALE_FACTORS 
eDP-1=1.5;DP-1=1.5;HDMI-1=1.5;HDMI-2=1.5;

Presentation mode on the laptop screen works as expected.  On the external screen, however, I see garbage on 2/3 of the screen (see attachment).

I started debugging and noticed that the size of m_lastRenderedPixmap in the PresentationWidget::paintEvent method depends on what screen the presentation mode is activated on.  That size is set in PresentationWidget::generatePage to 1.5 times the widget size.  On the laptop screen, the widget size is reported as being 1280x720 which, multiplied by 1.5, yields the correct 1920x1080.  On the external monitor, however, the same code reports a widget size of 1920x1080 right away.  Multiply that by 1.5, and m_lastRenderedPixmap ends up with a size of 2880x1620.  That seems odd to me.

Now at this point I am stuck.  Can somebody explain to me why I get two different widget sizes depending on what monitor my widget is on?  And which one of the two is correct anyway?

In the documentation of QWidget I read: "Do not use [the height function] to find the height of a screen on a multiple screen desktop."  But the explanation given there claims that the height method would give me the height of the complete virtual desktop, which is not the case.  Can somebody who knows Qt please enlighten me?
Comment 1 David Hurka 2020-05-17 21:01:39 UTC
QWidget, being a QPaintDevice, returns its size in Device Independent Pixels. That is the actual size / scaling factor. The intention is to let QPainter operations operate with the same Device Independent Pixels on any QPaintDevice, and QWidget will render painting operations in the correct display resolution.

Considering that, returning 1280x720 as the widget size is correct.

Sorry, this is for sure not the information you are looking for, and you probably already know that. Specifically, I can’t tell why the widget returns different sizes, and don’t know the painting code of the presentation widget.
Comment 2 Tobias Deiminger 2020-05-19 22:00:53 UTC
I can reproduce exactly what you described in a dual monitor virtual machine.

> But the explanation given there claims that the height method would give me the height of the complete virtual desktop
If you refer to "Read [https://doc.qt.io/qt-5/qdesktopwidget.html#screen-geometry] for details...", there they say: "for desktops with multiple screens, the size of the desktop is the union of all the screen sizes". That's not too explicit, but my guess is that "union" means not the same as "complete virtual desktop". It's probably more like with variables in a C-union, i.e. not laid side-by-side, but each put at the same starting location and then measure the bounding rect. But again, that's no real explanation.
Comment 3 Oliver Sander 2020-05-20 10:58:17 UTC
But even if the word 'union' was meant in a C way I'd expect to get a 1280x720 resolution for both screens...

@David, thanks for confirming that 1280x720 is correct rather than 1920x1080. I wasn't 100% sure.
Comment 4 Tobias Deiminger 2020-05-21 22:35:20 UTC
While I did some digging on how size is calculated, I noted my usage of QT_SCREEN_SCALE_FACTORS was wrong. Now I can't reproduce your issue any longer if I use the global QT_SCALE_FACTOR instead of QT_SCREEN_SCALE_FACTORS.
$ QT_SCALE_FACTOR=1.5 okular
Oliver, could you try this? As you set the same 1.5 for each screen, you could use the global parameter as well.

PS: Just saw QDesktopWidget doc [1] says "This class is obsolete". Does this mean we'll have to replace QDesktopWidget in presentationwidget.cpp anyway?

PPS: QDesktopWidgetPrivate::_q_updateScreens [2] gives insight on how size is calculated, basically it's the bounding rect of the QRegion union [3] of all screen geometries from QGuiApplication::screens().

[1] https://doc.qt.io/qt-5/qdesktopwidget.html
[2] https://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/kernel/qdesktopwidget.cpp#n110
[3] https://doc.qt.io/qt-5/qregion.html#united
Comment 5 Oliver Sander 2020-05-22 07:11:01 UTC
I confirm that the problem goes away when I set QT_SCALE_FACTOR instead of QT_SCREEN_SCALE_FACTORS.  However, I don't usually set these variables per hand.  Rather, I use the slider in the control center, and that set QT_SCREEN_SCALE_FACTORS for me, not the other one.

> Does this mean we'll have to replace QDesktopWidget in presentationwidget.cpp anyway?

I guess, maybe for the transition to Qt6.  Doesn't look very difficult, though.
Comment 6 Oliver Sander 2020-05-22 07:26:39 UTC
I just noticed something interesting:  When scaling my display with the control center GUI, it sets

~> echo $QT_SCREEN_SCALE_FACTORS 
eDP-1=1.5;DP-1=1.5;HDMI-1=1.5;HDMI-2=1.5;

(and QT_SCALE_FACTOR is unset).  No idea why it sets HDMI-1 and HDMI-2, I only have two physical monitors.

However, when I ask xrandr about the available screens I get

~> xrandr
Screen 0: minimum 320 x 200, current 1921 x 2160, maximum 16384 x 16384
eDP-1 connected 1920x1080+1+1080 (normal left inverted right x axis y axis) 276mm x 155mm
   1920x1080     60.00 +  59.97*   59.96    59.93  
[snip]
DP-1 disconnected (normal left inverted right x axis y axis)
HDMI-1 disconnected (normal left inverted right x axis y axis)
HDMI-2 disconnected (normal left inverted right x axis y axis)
DP-1-1 disconnected (normal left inverted right x axis y axis)
DP-1-2 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 527mm x 296mm
   1920x1080     60.00 +  50.00    50.00    59.94* 
[snip]
DP-1-3 disconnected (normal left inverted right x axis y axis)

Observe how QT_SCREEN_SCALE_FACTORS contains a scaling for display DP-1, but xrandr says that the display name is actually DP-1-2.  And indeed, when updating QT_SCREEN_SCALE_FACTORS accordingly

~> echo $QT_SCREEN_SCALE_FACTORS 
eDP-1=1.5;DP-1-2=1.5

the problem goes away.

So is this a bug in kscreen / the control center?
Comment 7 Oliver Sander 2020-05-28 12:15:23 UTC
Surprisingly, this issue basically fixed itself.  Setting the scale mode in the system-settings UI to 1.0 and back to 1.5 resulted in

~> echo $QT_SCREEN_SCALE_FACTORS 
eDP-1=1.5;DP-1=1.5;HDMI-1=1.5;HDMI-2=1.5;DP-1-1=1.5;DP-1-2=1.5;DP-1-3=1.5;

and now the resolution mismatches are gone.  (And, yes, I think I had tried that before.)  I see trouble coming on the day KDE supports per-screen scaling, but for the time being I'll close this report.

Thanks to Tobias Deiminger helping me debug this.