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 
45 QT_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 */
update()73 void 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 */
update(const QRect & rect)87 void 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 */
update(const QRegion & region)104 void 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 */
paintEvent(QPaintEvent * event)119 void QPaintDeviceWindow::paintEvent(QPaintEvent *event)
120 {
121     Q_UNUSED(event);
122     // Do nothing
123 }
124 
125 /*!
126   \internal
127  */
metric(PaintDeviceMetric metric) const128 int 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  */
exposeEvent(QExposeEvent * exposeEvent)179 void QPaintDeviceWindow::exposeEvent(QExposeEvent *exposeEvent)
180 {
181     Q_UNUSED(exposeEvent);
182     Q_D(QPaintDeviceWindow);
183     if (isExposed()) {
184         d->markWindowAsDirty();
185         // Do not rely on exposeEvent->region() as it has some issues for the
186         // time being, namely that it is sometimes in local coordinates,
187         // sometimes relative to the parent, depending on the platform plugin.
188         // We require local coords here.
189         d->doFlush(QRect(QPoint(0, 0), size()));
190     }
191 }
192 
193 /*!
194   \internal
195  */
event(QEvent * event)196 bool QPaintDeviceWindow::event(QEvent *event)
197 {
198     Q_D(QPaintDeviceWindow);
199 
200     if (event->type() == QEvent::UpdateRequest) {
201         if (handle()) // platform window may be gone when the window is closed during app exit
202             d->handleUpdateEvent();
203         return true;
204     }
205 
206     return QWindow::event(event);
207 }
208 
209 /*!
210   \internal
211  */
QPaintDeviceWindow(QPaintDeviceWindowPrivate & dd,QWindow * parent)212 QPaintDeviceWindow::QPaintDeviceWindow(QPaintDeviceWindowPrivate &dd, QWindow *parent)
213     : QWindow(dd, parent)
214 {
215 }
216 
217 /*!
218   \internal
219  */
paintEngine() const220 QPaintEngine *QPaintDeviceWindow::paintEngine() const
221 {
222     return nullptr;
223 }
224 
225 QT_END_NAMESPACE
226