1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qpaintdevicewindow_p.h"
5
6#include <QtGui/QGuiApplication>
7#include <QtGui/QScreen>
8
9QT_BEGIN_NAMESPACE
10
11QPaintDeviceWindowPrivate::QPaintDeviceWindowPrivate()
12 = default;
13
14QPaintDeviceWindowPrivate::~QPaintDeviceWindowPrivate()
15 = default;
16
17/*!
18 \class QPaintDeviceWindow
19 \inmodule QtGui
20 \since 5.4
21 \brief Convenience subclass of QWindow that is also a QPaintDevice.
22
23 QPaintDeviceWindow is like a regular QWindow, with the added functionality
24 of being a paint device too. Whenever the content needs to be updated,
25 the virtual paintEvent() function is called. Subclasses, that reimplement
26 this function, can then simply open a QPainter on the window.
27
28 \note This class cannot directly be used in applications. It rather serves
29 as a base for subclasses like QOpenGLWindow.
30
31 \sa QOpenGLWindow
32*/
33
34/*!
35 Marks the entire window as dirty and schedules a repaint.
36
37 \note Subsequent calls to this function before the next paint
38 event will get ignored.
39
40 \note For non-exposed windows the update is deferred until the
41 window becomes exposed again.
42*/
43void QPaintDeviceWindow::update()
44{
45 update(rect: QRect(QPoint(0,0), size()));
46}
47
48/*!
49 Marks the \a rect of the window as dirty and schedules a repaint.
50
51 \note Subsequent calls to this function before the next paint
52 event will get ignored, but \a rect is added to the region to update.
53
54 \note For non-exposed windows the update is deferred until the
55 window becomes exposed again.
56*/
57void QPaintDeviceWindow::update(const QRect &rect)
58{
59 Q_D(QPaintDeviceWindow);
60 d->dirtyRegion += rect;
61 if (isExposed())
62 requestUpdate();
63}
64
65/*!
66 Marks the \a region of the window as dirty and schedules a repaint.
67
68 \note Subsequent calls to this function before the next paint
69 event will get ignored, but \a region is added to the region to update.
70
71 \note For non-exposed windows the update is deferred until the
72 window becomes exposed again.
73*/
74void QPaintDeviceWindow::update(const QRegion &region)
75{
76 Q_D(QPaintDeviceWindow);
77 d->dirtyRegion += region;
78 if (isExposed())
79 requestUpdate();
80}
81
82/*!
83 Handles paint events passed in the \a event parameter.
84
85 The default implementation does nothing. Reimplement this function to
86 perform painting. If necessary, the dirty area is retrievable from
87 the \a event.
88*/
89void QPaintDeviceWindow::paintEvent(QPaintEvent *event)
90{
91 Q_UNUSED(event);
92 // Do nothing
93}
94
95/*!
96 \internal
97 */
98int QPaintDeviceWindow::metric(PaintDeviceMetric metric) const
99{
100 QScreen *screen = this->screen();
101 if (!screen && QGuiApplication::primaryScreen())
102 screen = QGuiApplication::primaryScreen();
103
104 switch (metric) {
105 case PdmWidth:
106 return width();
107 case PdmWidthMM:
108 if (screen)
109 return width() * screen->physicalSize().width() / screen->geometry().width();
110 break;
111 case PdmHeight:
112 return height();
113 case PdmHeightMM:
114 if (screen)
115 return height() * screen->physicalSize().height() / screen->geometry().height();
116 break;
117 case PdmDpiX:
118 if (screen)
119 return qRound(d: screen->logicalDotsPerInchX());
120 break;
121 case PdmDpiY:
122 if (screen)
123 return qRound(d: screen->logicalDotsPerInchY());
124 break;
125 case PdmPhysicalDpiX:
126 if (screen)
127 return qRound(d: screen->physicalDotsPerInchX());
128 break;
129 case PdmPhysicalDpiY:
130 if (screen)
131 return qRound(d: screen->physicalDotsPerInchY());
132 break;
133 case PdmDevicePixelRatio:
134 return int(QWindow::devicePixelRatio());
135 break;
136 case PdmDevicePixelRatioScaled:
137 return int(QWindow::devicePixelRatio() * devicePixelRatioFScale());
138 break;
139 default:
140 break;
141 }
142
143 return QPaintDevice::metric(metric);
144}
145
146/*!
147 \internal
148 */
149void QPaintDeviceWindow::exposeEvent(QExposeEvent *exposeEvent)
150{
151 QWindow::exposeEvent(exposeEvent);
152}
153
154/*!
155 \internal
156 */
157bool QPaintDeviceWindow::event(QEvent *event)
158{
159 Q_D(QPaintDeviceWindow);
160
161 if (event->type() == QEvent::UpdateRequest) {
162 if (handle()) // platform window may be gone when the window is closed during app exit
163 d->handleUpdateEvent();
164 return true;
165 } else if (event->type() == QEvent::Paint) {
166 d->markWindowAsDirty();
167 // Do not rely on exposeEvent->region() as it has some issues for the
168 // time being, namely that it is sometimes in local coordinates,
169 // sometimes relative to the parent, depending on the platform plugin.
170 // We require local coords here.
171 auto region = QRect(QPoint(0, 0), size());
172 d->doFlush(region); // Will end up calling paintEvent
173 return true;
174 }
175
176 return QWindow::event(event);
177}
178
179/*!
180 \internal
181 */
182QPaintDeviceWindow::QPaintDeviceWindow(QPaintDeviceWindowPrivate &dd, QWindow *parent)
183 : QWindow(dd, parent)
184{
185}
186
187/*!
188 \internal
189 */
190QPaintEngine *QPaintDeviceWindow::paintEngine() const
191{
192 return nullptr;
193}
194
195QT_END_NAMESPACE
196
197#include "moc_qpaintdevicewindow.cpp"
198

source code of qtbase/src/gui/kernel/qpaintdevicewindow.cpp