1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). |
4 | ** Contact: http://www.qt-project.org/legal |
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 Digia. For licensing terms and |
14 | ** conditions see http://qt.digia.com/licensing. For further information |
15 | ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 2.1 requirements |
23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
24 | ** |
25 | ** In addition, as a special exception, Digia gives you certain additional |
26 | ** rights. These rights are described in the Digia Qt LGPL Exception |
27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
28 | ** |
29 | ** GNU General Public License Usage |
30 | ** Alternatively, this file may be used under the terms of the GNU |
31 | ** General Public License version 3.0 as published by the Free Software |
32 | ** Foundation and appearing in the file LICENSE.GPL included in the |
33 | ** packaging of this file. Please review the following information to |
34 | ** ensure the GNU General Public License version 3.0 requirements will be |
35 | ** met: http://www.gnu.org/copyleft/gpl.html. |
36 | ** |
37 | ** |
38 | ** $QT_END_LICENSE$ |
39 | ** |
40 | ****************************************************************************/ |
41 | |
42 | #ifndef QBACKINGSTORE_P_H |
43 | #define QBACKINGSTORE_P_H |
44 | |
45 | // |
46 | // W A R N I N G |
47 | // ------------- |
48 | // |
49 | // This file is not part of the Qt API. It exists purely as an |
50 | // implementation detail. This header file may change from version to |
51 | // version without notice, or even be removed. |
52 | // |
53 | // We mean it. |
54 | // |
55 | |
56 | #include <QDebug> |
57 | #include <QtGui/qwidget.h> |
58 | #include <private/qwidget_p.h> |
59 | #include <private/qwindowsurface_p.h> |
60 | #ifdef Q_WS_QWS |
61 | #include <private/qwindowsurface_qws_p.h> |
62 | #endif |
63 | |
64 | QT_BEGIN_NAMESPACE |
65 | |
66 | class QWindowSurface; |
67 | |
68 | struct BeginPaintInfo { |
69 | inline BeginPaintInfo() : wasFlushed(0), nothingToPaint(0), windowSurfaceRecreated(0) {} |
70 | uint wasFlushed : 1; |
71 | uint nothingToPaint : 1; |
72 | uint windowSurfaceRecreated : 1; |
73 | }; |
74 | |
75 | class Q_AUTOTEST_EXPORT QWidgetBackingStore |
76 | { |
77 | public: |
78 | QWidgetBackingStore(QWidget *t); |
79 | ~QWidgetBackingStore(); |
80 | |
81 | static void showYellowThing(QWidget *widget, const QRegion &rgn, int msec, bool); |
82 | |
83 | void sync(QWidget *exposedWidget, const QRegion &exposedRegion); |
84 | void sync(); |
85 | void flush(QWidget *widget = 0, QWindowSurface *surface = 0); |
86 | |
87 | inline QPoint topLevelOffset() const { return tlwOffset; } |
88 | |
89 | QWindowSurface *surface() const { return windowSurface; } |
90 | |
91 | inline bool isDirty() const |
92 | { |
93 | return !(dirtyWidgets.isEmpty() && dirty.isEmpty() && !hasDirtyFromPreviousSync |
94 | && !fullUpdatePending |
95 | #if defined(Q_WS_QWS) && !defined(QT_NO_QWS_MANAGER) |
96 | && !hasDirtyWindowDecoration() |
97 | #endif |
98 | ); |
99 | } |
100 | |
101 | // ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore). |
102 | void markDirty(const QRegion &rgn, QWidget *widget, bool updateImmediately = false, |
103 | bool invalidateBuffer = false); |
104 | void markDirty(const QRect &rect, QWidget *widget, bool updateImmediately = false, |
105 | bool invalidateBuffer = false); |
106 | |
107 | private: |
108 | QWidget *tlw; |
109 | QRegion dirtyOnScreen; // needsFlush |
110 | QRegion dirty; // needsRepaint |
111 | QRegion dirtyFromPreviousSync; |
112 | QVector<QWidget *> dirtyWidgets; |
113 | QVector<QWidget *> *dirtyOnScreenWidgets; |
114 | QList<QWidget *> staticWidgets; |
115 | QWindowSurface *windowSurface; |
116 | #ifdef Q_BACKINGSTORE_SUBSURFACES |
117 | QList<QWindowSurface*> subSurfaces; |
118 | #endif |
119 | uint hasDirtyFromPreviousSync : 1; |
120 | uint fullUpdatePending : 1; |
121 | |
122 | QPoint tlwOffset; |
123 | |
124 | static bool flushPaint(QWidget *widget, const QRegion &rgn); |
125 | static void unflushPaint(QWidget *widget, const QRegion &rgn); |
126 | |
127 | bool bltRect(const QRect &rect, int dx, int dy, QWidget *widget); |
128 | void releaseBuffer(); |
129 | |
130 | void beginPaint(QRegion &toClean, QWidget *widget, QWindowSurface *windowSurface, |
131 | BeginPaintInfo *returnInfo, bool toCleanIsInTopLevelCoordinates = true); |
132 | void endPaint(const QRegion &cleaned, QWindowSurface *windowSurface, BeginPaintInfo *beginPaintInfo); |
133 | |
134 | QRegion dirtyRegion(QWidget *widget = 0) const; |
135 | QRegion staticContents(QWidget *widget = 0, const QRect &withinClipRect = QRect()) const; |
136 | |
137 | void markDirtyOnScreen(const QRegion &dirtyOnScreen, QWidget *widget, const QPoint &topLevelOffset); |
138 | |
139 | void removeDirtyWidget(QWidget *w); |
140 | |
141 | #if defined(Q_WS_QWS) && !defined(QT_NO_QWS_MANAGER) |
142 | bool hasDirtyWindowDecoration() const; |
143 | void paintWindowDecoration(); |
144 | #endif |
145 | void updateLists(QWidget *widget); |
146 | |
147 | inline void addDirtyWidget(QWidget *widget, const QRegion &rgn) |
148 | { |
149 | if (widget && !widget->d_func()->inDirtyList && !widget->data->in_destructor) { |
150 | QWidgetPrivate *widgetPrivate = widget->d_func(); |
151 | #ifndef QT_NO_GRAPHICSEFFECT |
152 | if (widgetPrivate->graphicsEffect) |
153 | widgetPrivate->dirty = widgetPrivate->effectiveRectFor(rgn.boundingRect()); |
154 | else |
155 | #endif //QT_NO_GRAPHICSEFFECT |
156 | widgetPrivate->dirty = rgn; |
157 | dirtyWidgets.append(widget); |
158 | widgetPrivate->inDirtyList = true; |
159 | } |
160 | } |
161 | |
162 | inline void dirtyWidgetsRemoveAll(QWidget *widget) |
163 | { |
164 | int i = 0; |
165 | while (i < dirtyWidgets.size()) { |
166 | if (dirtyWidgets.at(i) == widget) |
167 | dirtyWidgets.remove(i); |
168 | else |
169 | ++i; |
170 | } |
171 | } |
172 | |
173 | inline void addStaticWidget(QWidget *widget) |
174 | { |
175 | if (!widget) |
176 | return; |
177 | |
178 | Q_ASSERT(widget->testAttribute(Qt::WA_StaticContents)); |
179 | if (!staticWidgets.contains(widget)) |
180 | staticWidgets.append(widget); |
181 | } |
182 | |
183 | inline void removeStaticWidget(QWidget *widget) |
184 | { staticWidgets.removeAll(widget); } |
185 | |
186 | // Move the reparented widget and all its static children from this backing store |
187 | // to the new backing store if reparented into another top-level / backing store. |
188 | inline void moveStaticWidgets(QWidget *reparented) |
189 | { |
190 | Q_ASSERT(reparented); |
191 | QWidgetBackingStore *newBs = reparented->d_func()->maybeBackingStore(); |
192 | if (newBs == this) |
193 | return; |
194 | |
195 | int i = 0; |
196 | while (i < staticWidgets.size()) { |
197 | QWidget *w = staticWidgets.at(i); |
198 | if (reparented == w || reparented->isAncestorOf(w)) { |
199 | staticWidgets.removeAt(i); |
200 | if (newBs) |
201 | newBs->addStaticWidget(w); |
202 | } else { |
203 | ++i; |
204 | } |
205 | } |
206 | } |
207 | |
208 | inline QRect topLevelRect() const |
209 | { |
210 | #ifdef Q_WS_QWS |
211 | return tlw->frameGeometry(); |
212 | #else |
213 | return tlw->data->crect; |
214 | #endif |
215 | } |
216 | |
217 | inline void appendDirtyOnScreenWidget(QWidget *widget) |
218 | { |
219 | if (!widget) |
220 | return; |
221 | |
222 | if (!dirtyOnScreenWidgets) { |
223 | dirtyOnScreenWidgets = new QVector<QWidget *>; |
224 | dirtyOnScreenWidgets->append(widget); |
225 | } else if (!dirtyOnScreenWidgets->contains(widget)) { |
226 | dirtyOnScreenWidgets->append(widget); |
227 | } |
228 | } |
229 | |
230 | inline void dirtyOnScreenWidgetsRemoveAll(QWidget *widget) |
231 | { |
232 | if (!widget || !dirtyOnScreenWidgets) |
233 | return; |
234 | |
235 | int i = 0; |
236 | while (i < dirtyOnScreenWidgets->size()) { |
237 | if (dirtyOnScreenWidgets->at(i) == widget) |
238 | dirtyOnScreenWidgets->remove(i); |
239 | else |
240 | ++i; |
241 | } |
242 | } |
243 | |
244 | inline void resetWidget(QWidget *widget) |
245 | { |
246 | if (widget) { |
247 | widget->d_func()->inDirtyList = false; |
248 | widget->d_func()->isScrolled = false; |
249 | widget->d_func()->isMoved = false; |
250 | widget->d_func()->dirty = QRegion(); |
251 | } |
252 | } |
253 | |
254 | inline void updateStaticContentsSize() |
255 | { |
256 | for (int i = 0; i < staticWidgets.size(); ++i) { |
257 | QWidgetPrivate *wd = staticWidgets.at(i)->d_func(); |
258 | if (!wd->extra) |
259 | wd->createExtra(); |
260 | wd->extra->staticContentsSize = wd->data.crect.size(); |
261 | } |
262 | } |
263 | |
264 | inline bool hasStaticContents() const |
265 | { return !staticWidgets.isEmpty() && windowSurface->hasFeature(QWindowSurface::StaticContents); } |
266 | |
267 | friend QRegion qt_dirtyRegion(QWidget *); |
268 | friend class QWidgetPrivate; |
269 | friend class QWidget; |
270 | friend class QWSManagerPrivate; |
271 | friend class QETWidget; |
272 | friend class QWindowSurface; |
273 | friend class QWSWindowSurface; |
274 | }; |
275 | |
276 | QT_END_NAMESPACE |
277 | |
278 | #endif // QBACKINGSTORE_P_H |
279 | |