330 lines
14 KiB
Diff
330 lines
14 KiB
Diff
Patch-Source: https://github.com/qt/qtbase/commit/ab449c205cb656b32e8d1b8e036783f18704ff8e
|
|
https://codereview.qt-project.org/c/qt/qtbase/+/447074
|
|
https://bugreports.qt.io/browse/QTBUG-93380
|
|
--
|
|
From ab449c205cb656b32e8d1b8e036783f18704ff8e Mon Sep 17 00:00:00 2001
|
|
From: David Edmundson <davidedmundson@kde.org>
|
|
Date: Mon, 5 Dec 2022 22:15:01 +0000
|
|
Subject: [PATCH] Introduce events for Window device pixel ratio changes
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
There is a mix between screen device pixel ratio. Currently we store the
|
|
property on a per-window basis, but the change notifications are still
|
|
on a per screen basis which can fall apart on edge cases.
|
|
|
|
On wayland we are getting per window DPR changes without as useful
|
|
screen change events so it's important to fix. It also has potential to
|
|
clean up the Windows backend in the future where the backend is
|
|
currently papering over the two concepts.
|
|
|
|
This patch introduces two new events:
|
|
|
|
A QWindowSystemInterface to trigger a window DPR change
|
|
independently of a screen change.
|
|
|
|
An event to notify windows the new DPR rather than needing to track
|
|
signals on the screen. This happens either when the window dpr changes
|
|
or implicitly through a screen change. This can deprecate an existing
|
|
event ScreenChangeInternal so the value is reused and renamed for
|
|
clarity.
|
|
|
|
Change-Id: I637a07fd4520ba3184ccc2c987c29d8d23a65ad3
|
|
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
|
|
---
|
|
src/corelib/kernel/qcoreevent.cpp | 1 +
|
|
src/corelib/kernel/qcoreevent.h | 2 ++
|
|
src/gui/kernel/qguiapplication.cpp | 21 +++++++++++++++++++++
|
|
src/gui/kernel/qguiapplication_p.h | 1 +
|
|
src/gui/kernel/qwindow.cpp | 7 +++++++
|
|
src/gui/kernel/qwindowsysteminterface.cpp | 6 ++++++
|
|
src/gui/kernel/qwindowsysteminterface.h | 3 +++
|
|
src/gui/kernel/qwindowsysteminterface_p.h | 12 +++++++++++-
|
|
src/openglwidgets/qopenglwidget.cpp | 2 +-
|
|
src/widgets/kernel/qwidget.cpp | 2 ++
|
|
src/widgets/kernel/qwidgetwindow.cpp | 22 ++++++++++++++++++----
|
|
src/widgets/kernel/qwidgetwindow_p.h | 3 ++-
|
|
src/widgets/widgets/qdockwidget.cpp | 2 +-
|
|
13 files changed, 76 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp
|
|
index 0f4af06363d..b01f1c2a699 100644
|
|
--- a/src/corelib/kernel/qcoreevent.cpp
|
|
+++ b/src/corelib/kernel/qcoreevent.cpp
|
|
@@ -85,6 +85,7 @@ Q_TRACE_POINT(qtcore, QEvent_dtor, QEvent *event, QEvent::Type type);
|
|
\value ContextMenu Context popup menu (QContextMenuEvent).
|
|
\value CursorChange The widget's cursor has changed.
|
|
\value DeferredDelete The object will be deleted after it has cleaned up (QDeferredDeleteEvent)
|
|
+ \value DevicePixelRatioChange The devicePixelRatio has changed for this widget's or window's underlying backing store
|
|
\value DragEnter The cursor enters a widget during a drag and drop operation (QDragEnterEvent).
|
|
\value DragLeave The cursor leaves a widget during a drag and drop operation (QDragLeaveEvent).
|
|
\value DragMove A drag and drop operation is in progress (QDragMoveEvent).
|
|
diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h
|
|
index 536c5ab5582..0c83919bc50 100644
|
|
--- a/src/corelib/kernel/qcoreevent.h
|
|
+++ b/src/corelib/kernel/qcoreevent.h
|
|
@@ -284,6 +284,8 @@ class Q_CORE_EXPORT QEvent // event base class
|
|
// GraphicsSceneLeave = 220,
|
|
WindowAboutToChangeInternal = 221, // internal for QQuickWidget and texture-based widgets
|
|
|
|
+ DevicePixelRatioChange = 222,
|
|
+
|
|
// 512 reserved for Qt Jambi's MetaCall event
|
|
// 513 reserved for Qt Jambi's DeleteOnMainThread event
|
|
|
|
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
|
|
index f37095053e4..ca2d2155415 100644
|
|
--- a/src/gui/kernel/qguiapplication.cpp
|
|
+++ b/src/gui/kernel/qguiapplication.cpp
|
|
@@ -2052,6 +2052,9 @@ void Q_TRACE_INSTRUMENT(qtgui) QGuiApplicationPrivate::processWindowSystemEvent(
|
|
case QWindowSystemInterfacePrivate::WindowScreenChanged:
|
|
QGuiApplicationPrivate::processWindowScreenChangedEvent(static_cast<QWindowSystemInterfacePrivate::WindowScreenChangedEvent *>(e));
|
|
break;
|
|
+ case QWindowSystemInterfacePrivate::WindowDevicePixelRatioChanged:
|
|
+ QGuiApplicationPrivate::processWindowDevicePixelRatioChangedEvent(static_cast<QWindowSystemInterfacePrivate::WindowDevicePixelRatioChangedEvent *>(e));
|
|
+ break;
|
|
case QWindowSystemInterfacePrivate::SafeAreaMarginsChanged:
|
|
QGuiApplicationPrivate::processSafeAreaMarginsChangedEvent(static_cast<QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent *>(e));
|
|
break;
|
|
@@ -2555,6 +2558,9 @@ void QGuiApplicationPrivate::processWindowScreenChangedEvent(QWindowSystemInterf
|
|
if (QWindow *window = wse->window.data()) {
|
|
if (window->screen() == wse->screen.data())
|
|
return;
|
|
+
|
|
+ const qreal oldDevicePixelRatio = window->screen() ? window->screen()->devicePixelRatio() : 1.0;
|
|
+
|
|
if (QWindow *topLevelWindow = window->d_func()->topLevelWindow(QWindow::ExcludeTransients)) {
|
|
if (QScreen *screen = wse->screen.data())
|
|
topLevelWindow->d_func()->setTopLevelScreen(screen, false /* recreate */);
|
|
@@ -2571,9 +2577,24 @@ void QGuiApplicationPrivate::processWindowScreenChangedEvent(QWindowSystemInterf
|
|
processGeometryChangeEvent(&gce);
|
|
}
|
|
#endif
|
|
+
|
|
+ const qreal newDevicePixelRatio = window->screen() ? window->screen()->devicePixelRatio() : 1.0;
|
|
+ if (!qFuzzyCompare(oldDevicePixelRatio, newDevicePixelRatio)) {
|
|
+ QEvent dprChangeEvent(QEvent::DevicePixelRatioChange);
|
|
+ QGuiApplication::sendSpontaneousEvent(window, &dprChangeEvent);
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+void QGuiApplicationPrivate::processWindowDevicePixelRatioChangedEvent(QWindowSystemInterfacePrivate::WindowDevicePixelRatioChangedEvent *wde)
|
|
+{
|
|
+ if (wde->window.isNull())
|
|
+ return;
|
|
+
|
|
+ QEvent dprChangeEvent(QEvent::DevicePixelRatioChange);
|
|
+ QGuiApplication::sendSpontaneousEvent(wde->window, &dprChangeEvent);
|
|
+}
|
|
+
|
|
void QGuiApplicationPrivate::processSafeAreaMarginsChangedEvent(QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent *wse)
|
|
{
|
|
if (wse->window.isNull())
|
|
diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h
|
|
index 47228a0738b..433cf1a0886 100644
|
|
--- a/src/gui/kernel/qguiapplication_p.h
|
|
+++ b/src/gui/kernel/qguiapplication_p.h
|
|
@@ -116,6 +116,7 @@ class Q_GUI_EXPORT QGuiApplicationPrivate : public QCoreApplicationPrivate
|
|
static void processActivatedEvent(QWindowSystemInterfacePrivate::ActivatedWindowEvent *e);
|
|
static void processWindowStateChangedEvent(QWindowSystemInterfacePrivate::WindowStateChangedEvent *e);
|
|
static void processWindowScreenChangedEvent(QWindowSystemInterfacePrivate::WindowScreenChangedEvent *e);
|
|
+ static void processWindowDevicePixelRatioChangedEvent(QWindowSystemInterfacePrivate::WindowDevicePixelRatioChangedEvent *e);
|
|
|
|
static void processSafeAreaMarginsChangedEvent(QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent *e);
|
|
|
|
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
|
|
index 1e368914f36..5a0fc79f30a 100644
|
|
--- a/src/gui/kernel/qwindow.cpp
|
|
+++ b/src/gui/kernel/qwindow.cpp
|
|
@@ -505,6 +505,8 @@ void QWindowPrivate::create(bool recursive, WId nativeHandle)
|
|
// the platformWindow, if there was one, is now gone, so make this flag reflect reality now
|
|
updateRequestPending = false;
|
|
|
|
+ const qreal currentDevicePixelRatio = q->devicePixelRatio();
|
|
+
|
|
if (q->parent())
|
|
q->parent()->create();
|
|
|
|
@@ -550,6 +552,11 @@ void QWindowPrivate::create(bool recursive, WId nativeHandle)
|
|
QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceCreated);
|
|
QGuiApplication::sendEvent(q, &e);
|
|
|
|
+ if (!qFuzzyCompare(currentDevicePixelRatio, q->devicePixelRatio())) {
|
|
+ QEvent dprChangeEvent(QEvent::DevicePixelRatioChange);
|
|
+ QGuiApplication::sendEvent(q, &dprChangeEvent);
|
|
+ }
|
|
+
|
|
if (needsUpdate)
|
|
q->requestUpdate();
|
|
}
|
|
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
|
|
index ab07002191a..00343fef665 100644
|
|
--- a/src/gui/kernel/qwindowsysteminterface.cpp
|
|
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
|
|
@@ -259,6 +259,12 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowScreenChanged, QWindow *window, QS
|
|
handleWindowSystemEvent<QWindowSystemInterfacePrivate::WindowScreenChangedEvent, Delivery>(window, screen);
|
|
}
|
|
|
|
+QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowDevicePixelRatioChanged, QWindow *window)
|
|
+{
|
|
+ handleWindowSystemEvent<QWindowSystemInterfacePrivate::WindowDevicePixelRatioChangedEvent, Delivery>(window);
|
|
+}
|
|
+
|
|
+
|
|
QT_DEFINE_QPA_EVENT_HANDLER(void, handleSafeAreaMarginsChanged, QWindow *window)
|
|
{
|
|
handleWindowSystemEvent<QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent, Delivery>(window);
|
|
diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h
|
|
index 004019ae2de..37b06b0b040 100644
|
|
--- a/src/gui/kernel/qwindowsysteminterface.h
|
|
+++ b/src/gui/kernel/qwindowsysteminterface.h
|
|
@@ -190,6 +190,9 @@ class Q_GUI_EXPORT QWindowSystemInterface
|
|
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
|
|
static void handleWindowScreenChanged(QWindow *window, QScreen *newScreen);
|
|
|
|
+ template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
|
|
+ static void handleWindowDevicePixelRatioChanged(QWindow *window);
|
|
+
|
|
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
|
|
static void handleSafeAreaMarginsChanged(QWindow *window);
|
|
|
|
diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h
|
|
index 27aa7dbc570..3569667325e 100644
|
|
--- a/src/gui/kernel/qwindowsysteminterface_p.h
|
|
+++ b/src/gui/kernel/qwindowsysteminterface_p.h
|
|
@@ -68,7 +68,8 @@ class Q_GUI_EXPORT QWindowSystemInterfacePrivate {
|
|
WindowScreenChanged = 0x21,
|
|
SafeAreaMarginsChanged = 0x22,
|
|
ApplicationTermination = 0x23,
|
|
- Paint = 0x24
|
|
+ Paint = 0x24,
|
|
+ WindowDevicePixelRatioChanged = 0x25,
|
|
};
|
|
|
|
class WindowSystemEvent {
|
|
@@ -154,6 +155,15 @@ class Q_GUI_EXPORT QWindowSystemInterfacePrivate {
|
|
QPointer<QScreen> screen;
|
|
};
|
|
|
|
+ class WindowDevicePixelRatioChangedEvent : public WindowSystemEvent {
|
|
+ public:
|
|
+ WindowDevicePixelRatioChangedEvent(QWindow *w)
|
|
+ : WindowSystemEvent(WindowDevicePixelRatioChanged), window(w)
|
|
+ { }
|
|
+
|
|
+ QPointer<QWindow> window;
|
|
+ };
|
|
+
|
|
class SafeAreaMarginsChangedEvent : public WindowSystemEvent {
|
|
public:
|
|
SafeAreaMarginsChangedEvent(QWindow *w)
|
|
diff --git a/src/openglwidgets/qopenglwidget.cpp b/src/openglwidgets/qopenglwidget.cpp
|
|
index 4d8c181c226..68fabc7f14c 100644
|
|
--- a/src/openglwidgets/qopenglwidget.cpp
|
|
+++ b/src/openglwidgets/qopenglwidget.cpp
|
|
@@ -1690,7 +1690,7 @@ bool QOpenGLWidget::event(QEvent *e)
|
|
}
|
|
}
|
|
break;
|
|
- case QEvent::ScreenChangeInternal:
|
|
+ case QEvent::DevicePixelRatioChange:
|
|
if (d->initialized && d->paintDevice->devicePixelRatio() != devicePixelRatio())
|
|
d->recreateFbos();
|
|
break;
|
|
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
|
|
index 4da80073a82..3ca70d56e5a 100644
|
|
--- a/src/widgets/kernel/qwidget.cpp
|
|
+++ b/src/widgets/kernel/qwidget.cpp
|
|
@@ -9318,6 +9318,8 @@ bool QWidget::event(QEvent *event)
|
|
const QWindow *win = te->window;
|
|
d->setWinId((win && win->handle()) ? win->handle()->winId() : 0);
|
|
}
|
|
+ break;
|
|
+ case QEvent::DevicePixelRatioChange:
|
|
if (d->data.fnt.d->dpi != logicalDpiY())
|
|
d->updateFont(d->data.fnt);
|
|
d->renderToTextureReallyDirty = 1;
|
|
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
|
|
index 7a3c38bb8d1..b6a6acfc927 100644
|
|
--- a/src/widgets/kernel/qwidgetwindow.cpp
|
|
+++ b/src/widgets/kernel/qwidgetwindow.cpp
|
|
@@ -329,6 +329,10 @@ bool QWidgetWindow::event(QEvent *event)
|
|
m_widget->repaint();
|
|
return true;
|
|
|
|
+ case QEvent::DevicePixelRatioChange:
|
|
+ handleDevicePixelRatioChange();
|
|
+ break;
|
|
+
|
|
default:
|
|
break;
|
|
}
|
|
@@ -695,22 +699,32 @@ void QWidgetWindow::updateMargins()
|
|
m_widget->data->fstrut_dirty = false;
|
|
}
|
|
|
|
-static void sendScreenChangeRecursively(QWidget *widget)
|
|
+static void sendChangeRecursively(QWidget *widget, QEvent::Type type)
|
|
{
|
|
- QEvent e(QEvent::ScreenChangeInternal);
|
|
+ QEvent e(type);
|
|
QCoreApplication::sendEvent(widget, &e);
|
|
QWidgetPrivate *d = QWidgetPrivate::get(widget);
|
|
for (int i = 0; i < d->children.size(); ++i) {
|
|
QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
|
|
if (w)
|
|
- sendScreenChangeRecursively(w);
|
|
+ sendChangeRecursively(w, type);
|
|
}
|
|
}
|
|
|
|
void QWidgetWindow::handleScreenChange()
|
|
{
|
|
// Send an event recursively to the widget and its children.
|
|
- sendScreenChangeRecursively(m_widget);
|
|
+ sendChangeRecursively(m_widget, QEvent::ScreenChangeInternal);
|
|
+
|
|
+ // Invalidate the backing store buffer and repaint immediately.
|
|
+ if (screen())
|
|
+ repaintWindow();
|
|
+}
|
|
+
|
|
+void QWidgetWindow::handleDevicePixelRatioChange()
|
|
+{
|
|
+ // Send an event recursively to the widget and its children.
|
|
+ sendChangeRecursively(m_widget, QEvent::DevicePixelRatioChange);
|
|
|
|
// Invalidate the backing store buffer and repaint immediately.
|
|
if (screen())
|
|
diff --git a/src/widgets/kernel/qwidgetwindow_p.h b/src/widgets/kernel/qwidgetwindow_p.h
|
|
index 92f1a8b6d47..0eee3cd900e 100644
|
|
--- a/src/widgets/kernel/qwidgetwindow_p.h
|
|
+++ b/src/widgets/kernel/qwidgetwindow_p.h
|
|
@@ -81,9 +81,10 @@ class QWidgetWindow : public QWindow
|
|
|
|
private slots:
|
|
void updateObjectName();
|
|
- void handleScreenChange();
|
|
|
|
private:
|
|
+ void handleScreenChange();
|
|
+ void handleDevicePixelRatioChange();
|
|
void repaintWindow();
|
|
bool updateSize();
|
|
void updateMargins();
|
|
diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp
|
|
index 67bb0994464..375bd3daaee 100644
|
|
--- a/src/widgets/widgets/qdockwidget.cpp
|
|
+++ b/src/widgets/widgets/qdockwidget.cpp
|
|
@@ -119,7 +119,7 @@ bool QDockWidgetTitleButton::event(QEvent *event)
|
|
{
|
|
switch (event->type()) {
|
|
case QEvent::StyleChange:
|
|
- case QEvent::ScreenChangeInternal:
|
|
+ case QEvent::DevicePixelRatioChange:
|
|
m_iconSize = -1;
|
|
break;
|
|
default:
|