Fix handling of virtual/native pixels in QAndroidPlatformWindow

f92e195369 made sure a new
QAndroidPlatformWindow always has a geometry. However, it did not
take into account HiDPI handling. This patch fixes it and introduces
proper HiDPI handling.

Pick-to: 5.15 6.0 6.1
Fixes: QTBUG-91161
Change-Id: Iddf31b7abfd0a1bada3b051ed4de3bf6c2897d8e
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
Andreas Buhr 2021-02-17 20:15:04 +01:00
parent 4f24e1e9b1
commit dec429e077
2 changed files with 35 additions and 21 deletions

View File

@ -678,16 +678,16 @@ void QPlatformWindow::invalidateSurface()
{
}
static QSize fixInitialSize(QSize size, const QWindow *w,
int defaultWidth, int defaultHeight)
static QSize fixInitialSize(QSize size, const QWindow *w, int deviceIndependentDefaultWidth,
int deviceIndependentDefaultHeight)
{
if (size.width() == 0) {
const int minWidth = w->minimumWidth();
size.setWidth(minWidth > 0 ? minWidth : defaultWidth);
size.setWidth(minWidth > 0 ? minWidth : deviceIndependentDefaultWidth);
}
if (size.height() == 0) {
const int minHeight = w->minimumHeight();
size.setHeight(minHeight > 0 ? minHeight : defaultHeight);
size.setHeight(minHeight > 0 ? minHeight : deviceIndependentDefaultHeight);
}
return size;
}
@ -700,6 +700,10 @@ static QSize fixInitialSize(QSize size, const QWindow *w,
layout new windows to optimize usage of the available desktop space.
However if the given window already has geometry which the application has
initialized, it takes priority.
\a initialGeometry has to be provided in native pixels.
\a defaultWidth has to be provided in device independent pixels
\a defaultHeight has to be provided in device independent pixels
*/
QRect QPlatformWindow::initialGeometry(const QWindow *w, const QRect &initialGeometry,
int defaultWidth, int defaultHeight,
@ -709,9 +713,10 @@ QRect QPlatformWindow::initialGeometry(const QWindow *w, const QRect &initialGeo
*resultingScreenReturn = w->screen();
if (!w->isTopLevel()) {
const qreal factor = QHighDpiScaling::factor(w);
const QSize size = fixInitialSize(QHighDpi::fromNative(initialGeometry.size(), factor),
w, defaultWidth, defaultHeight);
return QRect(initialGeometry.topLeft(), QHighDpi::toNative(size, factor));
const QSize deviceIndependentSize =
fixInitialSize(QHighDpi::fromNative(initialGeometry.size(), factor), w,
defaultWidth, defaultHeight);
return QRect(initialGeometry.topLeft(), QHighDpi::toNative(deviceIndependentSize, factor));
}
const auto *wp = qt_window_private(const_cast<QWindow*>(w));
const bool position = wp->positionAutomatic && w->type() != Qt::Popup;
@ -725,26 +730,28 @@ QRect QPlatformWindow::initialGeometry(const QWindow *w, const QRect &initialGeo
if (resultingScreenReturn)
*resultingScreenReturn = screen;
// initialGeometry refers to window's screen
QRect rect(QHighDpi::fromNativePixels(initialGeometry, w));
QRect deviceIndependentRect(QHighDpi::fromNativePixels(initialGeometry, w));
if (wp->resizeAutomatic)
rect.setSize(fixInitialSize(rect.size(), w, defaultWidth, defaultHeight));
deviceIndependentRect.setSize(
fixInitialSize(deviceIndependentRect.size(), w, defaultWidth, defaultHeight));
if (position) {
const QRect availableGeometry = screen->availableGeometry();
const QRect availableDeviceIndependentGeometry = screen->availableGeometry();
// Center unless the geometry ( + unknown window frame) is too large for the screen).
if (rect.height() < (availableGeometry.height() * 8) / 9
&& rect.width() < (availableGeometry.width() * 8) / 9) {
if (deviceIndependentRect.height() < (availableDeviceIndependentGeometry.height() * 8) / 9
&& deviceIndependentRect.width()
< (availableDeviceIndependentGeometry.width() * 8) / 9) {
const QWindow *tp = w->transientParent();
if (tp) {
// A transient window should be centered w.r.t. its transient parent.
rect.moveCenter(tp->geometry().center());
deviceIndependentRect.moveCenter(tp->geometry().center());
} else {
// Center the window on the screen. (Only applicable on platforms
// which do not provide a better way.)
rect.moveCenter(availableGeometry.center());
deviceIndependentRect.moveCenter(availableDeviceIndependentGeometry.center());
}
}
}
return QHighDpi::toNativePixels(rect, screen);
return QHighDpi::toNativePixels(deviceIndependentRect, screen);
}
/*!

View File

@ -60,14 +60,21 @@ QAndroidPlatformWindow::QAndroidPlatformWindow(QWindow *window)
m_windowId = winIdGenerator.fetchAndAddRelaxed(1) + 1;
setWindowState(window->windowStates());
// the following is in relation to the virtual geometry
const bool forceMaximize = m_windowState & (Qt::WindowMaximized | Qt::WindowFullScreen);
const QRect requestedGeometry = forceMaximize ? QRect() : window->geometry();
const QRect availableGeometry = (window->parent()) ? window->parent()->geometry() : platformScreen()->availableGeometry();
const QRect finalGeometry = QPlatformWindow::initialGeometry(window, requestedGeometry,
availableGeometry.width(), availableGeometry.height());
const QRect requestedNativeGeometry =
forceMaximize ? QRect() : QHighDpi::toNativePixels(window->geometry(), window);
const QRect availableDeviceIndependentGeometry = (window->parent())
? window->parent()->geometry()
: QHighDpi::fromNativePixels(platformScreen()->availableGeometry(), window);
if (requestedGeometry != finalGeometry)
setGeometry(QHighDpi::toNativePixels(finalGeometry, window));
// initialGeometry returns in native pixels
const QRect finalNativeGeometry = QPlatformWindow::initialGeometry(
window, requestedNativeGeometry, availableDeviceIndependentGeometry.width(),
availableDeviceIndependentGeometry.height());
if (requestedNativeGeometry != finalNativeGeometry)
setGeometry(finalNativeGeometry);
}
void QAndroidPlatformWindow::lower()