1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qpaintdevicewindow_p.h"
41
42#include <QtGui/QGuiApplication>
43#include <QtGui/QScreen>
44
45QT_BEGIN_NAMESPACE
46
47/*!
48 \class QPaintDeviceWindow
49 \inmodule QtGui
50 \since 5.4
51 \brief Convenience subclass of QWindow that is also a QPaintDevice.
52
53 QPaintDeviceWindow is like a regular QWindow, with the added functionality
54 of being a paint device too. Whenever the content needs to be updated,
55 the virtual paintEvent() function is called. Subclasses, that reimplement
56 this function, can then simply open a QPainter on the window.
57
58 \note This class cannot directly be used in applications. It rather serves
59 as a base for subclasses like QOpenGLWindow.
60
61 \sa QOpenGLWindow
62*/
63
64/*!
65 Marks the entire window as dirty and schedules a repaint.
66
67 \note Subsequent calls to this function before the next paint
68 event will get ignored.
69
70 \note For non-exposed windows the update is deferred until the
71 window becomes exposed again.
72*/
73void QPaintDeviceWindow::update()
74{
75 update(QRect(QPoint(0,0), size()));
76}
77
78/*!
79 Marks the \a rect of the window as dirty and schedules a repaint.
80
81 \note Subsequent calls to this function before the next paint
82 event will get ignored, but \a rect is added to the region to update.
83
84 \note For non-exposed windows the update is deferred until the
85 window becomes exposed again.
86*/
87void QPaintDeviceWindow::update(const QRect &rect)
88{
89 Q_D(QPaintDeviceWindow);
90 d->dirtyRegion += rect;
91 if (isExposed())
92 requestUpdate();
93}
94
95/*!
96 Marks the \a region of the window as dirty and schedules a repaint.
97
98 \note Subsequent calls to this function before the next paint
99 event will get ignored, but \a region is added to the region to update.
100
101 \note For non-exposed windows the update is deferred until the
102 window becomes exposed again.
103*/
104void QPaintDeviceWindow::update(const QRegion &region)
105{
106 Q_D(QPaintDeviceWindow);
107 d->dirtyRegion += region;
108 if (isExposed())
109 requestUpdate();
110}
111
112/*!
113 Handles paint events passed in the \a event parameter.
114
115 The default implementation does nothing. Reimplement this function to
116 perform painting. If necessary, the dirty area is retrievable from
117 the \a event.
118*/
119void QPaintDeviceWindow::paintEvent(QPaintEvent *event)
120{
121 Q_UNUSED(event);
122 // Do nothing
123}
124
125/*!
126 \internal
127 */
128int QPaintDeviceWindow::metric(PaintDeviceMetric metric) const
129{
130 QScreen *screen = this->screen();
131 if (!screen && QGuiApplication::primaryScreen())
132 screen = QGuiApplication::primaryScreen();
133
134 switch (metric) {
135 case PdmWidth:
136 return width();
137 case PdmWidthMM:
138 if (screen)
139 return width() * screen->physicalSize().width() / screen->geometry().width();
140 break;
141 case PdmHeight:
142 return height();
143 case PdmHeightMM:
144 if (screen)
145 return height() * screen->physicalSize().height() / screen->geometry().height();
146 break;
147 case PdmDpiX:
148 if (screen)
149 return qRound(screen->logicalDotsPerInchX());
150 break;
151 case PdmDpiY:
152 if (screen)
153 return qRound(screen->logicalDotsPerInchY());
154 break;
155 case PdmPhysicalDpiX:
156 if (screen)
157 return qRound(screen->physicalDotsPerInchX());
158 break;
159 case PdmPhysicalDpiY:
160 if (screen)
161 return qRound(screen->physicalDotsPerInchY());
162 break;
163 case PdmDevicePixelRatio:
164 return int(QWindow::devicePixelRatio());
165 break;
166 case PdmDevicePixelRatioScaled:
167 return int(QWindow::devicePixelRatio() * devicePixelRatioFScale());
168 break;
169 default:
170 break;
171 }
172
173 return QPaintDevice::metric(metric);
174}
175
176/*!
177 \internal
178 */
179void QPaintDeviceWindow::exposeEvent(QExposeEvent *exposeEvent)
180{
181 QWindow::exposeEvent(exposeEvent);
182}
183
184/*!
185 \internal
186 */
187bool QPaintDeviceWindow::event(QEvent *event)
188{
189 Q_D(QPaintDeviceWindow);
190
191 if (event->type() == QEvent::UpdateRequest) {
192 if (handle()) // platform window may be gone when the window is closed during app exit
193 d->handleUpdateEvent();
194 return true;
195 } else if (event->type() == QEvent::Paint) {
196 d->markWindowAsDirty();
197 // Do not rely on exposeEvent->region() as it has some issues for the
198 // time being, namely that it is sometimes in local coordinates,
199 // sometimes relative to the parent, depending on the platform plugin.
200 // We require local coords here.
201 auto region = QRect(QPoint(0, 0), size());
202 d->doFlush(region); // Will end up calling paintEvent
203 return true;
204 }
205
206 return QWindow::event(event);
207}
208
209/*!
210 \internal
211 */
212QPaintDeviceWindow::QPaintDeviceWindow(QPaintDeviceWindowPrivate &dd, QWindow *parent)
213 : QWindow(dd, parent)
214{
215}
216
217/*!
218 \internal
219 */
220QPaintEngine *QPaintDeviceWindow::paintEngine() const
221{
222 return nullptr;
223}
224
225QT_END_NAMESPACE
226