qwidgetbackingstore.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/widgets/kernel/qwidgetbackingstore.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
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 QtWidgets 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-
41#include "qplatformdefs.h"-
42-
43#include "qwidgetbackingstore_p.h"-
44-
45#include <QtCore/qglobal.h>-
46#include <QtCore/qdebug.h>-
47#include <QtCore/qvarlengtharray.h>-
48#include <QtGui/qevent.h>-
49#include <QtWidgets/qapplication.h>-
50#include <QtGui/qpaintengine.h>-
51#include <QtWidgets/qgraphicsproxywidget.h>-
52-
53#include <private/qwidget_p.h>-
54#include <private/qapplication_p.h>-
55#include <private/qpaintengine_raster_p.h>-
56#include <private/qgraphicseffect_p.h>-
57#include <QtGui/private/qwindow_p.h>-
58-
59#include <qpa/qplatformbackingstore.h>-
60-
61#if defined(Q_OS_WIN) && !defined(QT_NO_PAINT_DEBUG)-
62# include <QtCore/qt_windows.h>-
63# include <qpa/qplatformnativeinterface.h>-
64#endif-
65-
66QT_BEGIN_NAMESPACE-
67-
68extern QRegion qt_dirtyRegion(QWidget *);-
69-
70#ifndef QT_NO_OPENGL-
71Q_GLOBAL_STATIC(QPlatformTextureList, qt_dummy_platformTextureList)-
72#endif-
73-
74/**-
75 * Flushes the contents of the \a backingStore into the screen area of \a widget.-
76 * \a tlwOffset is the position of the top level widget relative to the window surface.-
77 * \a region is the region to be updated in \a widget coordinates.-
78 */-
79void QWidgetBackingStore::qt_flush(QWidget *widget, const QRegion &region, QBackingStore *backingStore,-
80 QWidget *tlw, const QPoint &tlwOffset, QPlatformTextureList *widgetTextures,-
81 QWidgetBackingStore *widgetBackingStore)-
82{-
83#ifdef QT_NO_OPENGL-
84 Q_UNUSED(widgetTextures);-
85 Q_ASSERT(!region.isEmpty());-
86#else-
87 Q_ASSERT(!region.isEmpty() || widgetTextures);-
88#endif-
89 Q_ASSERT(widget);-
90 Q_ASSERT(backingStore);-
91 Q_ASSERT(tlw);-
92#if !defined(QT_NO_PAINT_DEBUG)-
93 static int flushUpdate = qEnvironmentVariableIntValue("QT_FLUSH_UPDATE");-
94 if (flushUpdate > 0)-
95 QWidgetBackingStore::showYellowThing(widget, region, flushUpdate * 10, false);-
96#endif-
97-
98 if (tlw->testAttribute(Qt::WA_DontShowOnScreen) || widget->testAttribute(Qt::WA_DontShowOnScreen))-
99 return;-
100 static bool fpsDebug = qEnvironmentVariableIntValue("QT_DEBUG_FPS");-
101 if (fpsDebug) {-
102 if (!widgetBackingStore->perfFrames++)-
103 widgetBackingStore->perfTime.start();-
104 if (widgetBackingStore->perfTime.elapsed() > 5000) {-
105 double fps = double(widgetBackingStore->perfFrames * 1000) / widgetBackingStore->perfTime.restart();-
106 qDebug("FPS: %.1f\n", fps);-
107 widgetBackingStore->perfFrames = 0;-
108 }-
109 }-
110-
111 QPoint offset = tlwOffset;-
112 if (widget != tlw)-
113 offset += widget->mapTo(tlw, QPoint());-
114-
115 QRegion effectiveRegion = region;-
116#ifndef QT_NO_OPENGL-
117 const bool compositionWasActive = widget->d_func()->renderToTextureComposeActive;-
118 if (!widgetTextures) {-
119 widget->d_func()->renderToTextureComposeActive = false;-
120 // Detect the case of falling back to the normal flush path when no-
121 // render-to-texture widgets are visible anymore. We will force one-
122 // last flush to go through the OpenGL-based composition to prevent-
123 // artifacts. The next flush after this one will use the normal path.-
124 if (compositionWasActive)-
125 widgetTextures = qt_dummy_platformTextureList;-
126 } else {-
127 widget->d_func()->renderToTextureComposeActive = true;-
128 }-
129 // When changing the composition status, make sure the dirty region covers-
130 // the entire widget. Just having e.g. the shown/hidden render-to-texture-
131 // widget's area marked as dirty is incorrect when changing flush paths.-
132 if (compositionWasActive != widget->d_func()->renderToTextureComposeActive)-
133 effectiveRegion = widget->rect();-
134-
135 // re-test since we may have been forced to this path via the dummy texture list above-
136 if (widgetTextures) {-
137 qt_window_private(tlw->windowHandle())->compositing = true;-
138 widget->window()->d_func()->sendComposeStatus(widget->window(), false);-
139 // A window may have alpha even when the app did not request-
140 // WA_TranslucentBackground. Therefore the compositor needs to know whether the app intends-
141 // to rely on translucency, in order to decide if it should clear to transparent or opaque.-
142 const bool translucentBackground = widget->testAttribute(Qt::WA_TranslucentBackground);-
143 // Use the tlw's context, not widget's. The difference is important with native child-
144 // widgets where tlw != widget.-
145 backingStore->handle()->composeAndFlush(widget->windowHandle(), effectiveRegion, offset, widgetTextures,-
146 tlw->d_func()->shareContext(), translucentBackground);-
147 widget->window()->d_func()->sendComposeStatus(widget->window(), true);-
148 } else-
149#endif-
150 backingStore->flush(effectiveRegion, widget->windowHandle(), offset);-
151}-
152-
153#ifndef QT_NO_PAINT_DEBUG-
154#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)-
155-
156static void showYellowThing_win(QWidget *widget, const QRegion &region, int msec)-
157{-
158 // We expect to be passed a native parent.-
159 QWindow *nativeWindow = widget->windowHandle();-
160 if (!nativeWindow)-
161 return;-
162 void *hdcV = QGuiApplication::platformNativeInterface()->nativeResourceForWindow(QByteArrayLiteral("getDC"), nativeWindow);-
163 if (!hdcV)-
164 return;-
165 const HDC hdc = reinterpret_cast<HDC>(hdcV);-
166-
167 HBRUSH brush;-
168 static int i = 0;-
169 switch (i) {-
170 case 0:-
171 brush = CreateSolidBrush(RGB(255, 255, 0));-
172 break;-
173 case 1:-
174 brush = CreateSolidBrush(RGB(255, 200, 55));-
175 break;-
176 case 2:-
177 brush = CreateSolidBrush(RGB(200, 255, 55));-
178 break;-
179 case 3:-
180 brush = CreateSolidBrush(RGB(200, 200, 0));-
181 break;-
182 }-
183 i = (i + 1) & 3;-
184-
185 foreach (const QRect &rect, region.rects()) {-
186 RECT winRect;-
187 SetRect(&winRect, rect.left(), rect.top(), rect.right(), rect.bottom());-
188 FillRect(hdc, &winRect, brush);-
189 }-
190 DeleteObject(brush);-
191 QGuiApplication::platformNativeInterface()->nativeResourceForWindow(QByteArrayLiteral("releaseDC"), nativeWindow);-
192 ::Sleep(msec);-
193}-
194#endif // defined(Q_OS_WIN) && !defined(Q_OS_WINRT)-
195-
196void QWidgetBackingStore::showYellowThing(QWidget *widget, const QRegion &toBePainted, int msec, bool unclipped)-
197{-
198#ifdef Q_OS_WINRT-
199 Q_UNUSED(msec)-
200#endif-
201 QRegion paintRegion = toBePainted;-
202 QRect widgetRect = widget->rect();-
203-
204 if (!widget->internalWinId()) {-
205 QWidget *nativeParent = widget->nativeParentWidget();-
206 const QPoint offset = widget->mapTo(nativeParent, QPoint(0, 0));-
207 paintRegion.translate(offset);-
208 widgetRect.translate(offset);-
209 widget = nativeParent;-
210 }-
211-
212#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)-
213 Q_UNUSED(unclipped);-
214 showYellowThing_win(widget, paintRegion, msec);-
215#else-
216 //flags to fool painter-
217 bool paintUnclipped = widget->testAttribute(Qt::WA_PaintUnclipped);-
218 if (unclipped && !widget->d_func()->paintOnScreen())-
219 widget->setAttribute(Qt::WA_PaintUnclipped);-
220-
221 const bool setFlag = !widget->testAttribute(Qt::WA_WState_InPaintEvent);-
222 if (setFlag)-
223 widget->setAttribute(Qt::WA_WState_InPaintEvent);-
224-
225 //setup the engine-
226 QPaintEngine *pe = widget->paintEngine();-
227 if (pe) {-
228 pe->setSystemClip(paintRegion);-
229 {-
230 QPainter p(widget);-
231 p.setClipRegion(paintRegion);-
232 static int i = 0;-
233 switch (i) {-
234 case 0:-
235 p.fillRect(widgetRect, QColor(255,255,0));-
236 break;-
237 case 1:-
238 p.fillRect(widgetRect, QColor(255,200,55));-
239 break;-
240 case 2:-
241 p.fillRect(widgetRect, QColor(200,255,55));-
242 break;-
243 case 3:-
244 p.fillRect(widgetRect, QColor(200,200,0));-
245 break;-
246 }-
247 i = (i+1) & 3;-
248 p.end();-
249 }-
250 }-
251-
252 if (setFlag)-
253 widget->setAttribute(Qt::WA_WState_InPaintEvent, false);-
254-
255 //restore-
256 widget->setAttribute(Qt::WA_PaintUnclipped, paintUnclipped);-
257-
258 if (pe)-
259 pe->setSystemClip(QRegion());-
260-
261#if defined(Q_OS_UNIX)-
262 ::usleep(1000 * msec);-
263#endif-
264#endif // !Q_OS_WIN-
265}-
266-
267bool QWidgetBackingStore::flushPaint(QWidget *widget, const QRegion &rgn)-
268{-
269 if (!widget)-
270 return false;-
271-
272 int delay = 0;-
273 if (widget->testAttribute(Qt::WA_WState_InPaintEvent)) {-
274 static int flushPaintEvent = qEnvironmentVariableIntValue("QT_FLUSH_PAINT_EVENT");-
275 if (!flushPaintEvent)-
276 return false;-
277 delay = flushPaintEvent;-
278 } else {-
279 static int flushPaint = qEnvironmentVariableIntValue("QT_FLUSH_PAINT");-
280 if (!flushPaint)-
281 return false;-
282 delay = flushPaint;-
283 }-
284-
285 QWidgetBackingStore::showYellowThing(widget, rgn, delay * 10, true);-
286 return true;-
287}-
288-
289void QWidgetBackingStore::unflushPaint(QWidget *widget, const QRegion &rgn)-
290{-
291 if (widget->d_func()->paintOnScreen() || rgn.isEmpty())-
292 return;-
293-
294 QWidget *tlw = widget->window();-
295 QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData();-
296 if (!tlwExtra)-
297 return;-
298-
299 const QPoint offset = widget->mapTo(tlw, QPoint());-
300 qt_flush(widget, rgn, tlwExtra->backingStoreTracker->store, tlw, offset, 0, tlw->d_func()->maybeBackingStore());-
301}-
302#endif // QT_NO_PAINT_DEBUG-
303-
304/*-
305 Moves the whole rect by (dx, dy) in widget's coordinate system.-
306 Doesn't generate any updates.-
307*/-
308bool QWidgetBackingStore::bltRect(const QRect &rect, int dx, int dy, QWidget *widget)-
309{-
310 const QPoint pos(tlwOffset + widget->mapTo(tlw, rect.topLeft()));-
311 const QRect tlwRect(QRect(pos, rect.size()));-
312 if (fullUpdatePending || dirty.intersects(tlwRect))-
313 return false; // We don't want to scroll junk.-
314 return store->scroll(tlwRect, dx, dy);-
315}-
316-
317void QWidgetBackingStore::releaseBuffer()-
318{-
319 if (store)-
320 store->resize(QSize());-
321}-
322-
323/*!-
324 Prepares the window surface to paint a\ toClean region of the \a widget and-
325 updates the BeginPaintInfo struct accordingly.-
326-
327 The \a toClean region might be clipped by the window surface.-
328*/-
329void QWidgetBackingStore::beginPaint(QRegion &toClean, QWidget *widget, QBackingStore *backingStore,-
330 BeginPaintInfo *returnInfo, bool toCleanIsInTopLevelCoordinates)-
331{-
332 Q_UNUSED(widget);-
333 Q_UNUSED(toCleanIsInTopLevelCoordinates);-
334-
335 // Always flush repainted areas.-
336 dirtyOnScreen += toClean;-
337-
338#ifdef QT_NO_PAINT_DEBUG-
339 backingStore->beginPaint(toClean);-
340#else-
341 returnInfo->wasFlushed = QWidgetBackingStore::flushPaint(tlw, toClean);-
342 // Avoid deadlock with QT_FLUSH_PAINT: the server will wait for-
343 // the BackingStore lock, so if we hold that, the server will-
344 // never release the Communication lock that we are waiting for in-
345 // sendSynchronousCommand-
346 if (!returnInfo->wasFlushed)-
347 backingStore->beginPaint(toClean);-
348#endif-
349-
350 Q_UNUSED(returnInfo);-
351}-
352-
353void QWidgetBackingStore::endPaint(const QRegion &cleaned, QBackingStore *backingStore,-
354 BeginPaintInfo *beginPaintInfo)-
355{-
356#ifndef QT_NO_PAINT_DEBUG-
357 if (!beginPaintInfo->wasFlushed)-
358 backingStore->endPaint();-
359 else-
360 QWidgetBackingStore::unflushPaint(tlw, cleaned);-
361#else-
362 Q_UNUSED(beginPaintInfo);-
363 Q_UNUSED(cleaned);-
364 backingStore->endPaint();-
365#endif-
366-
367 flush();-
368}-
369-
370/*!-
371 Returns the region (in top-level coordinates) that needs repaint and/or flush.-
372-
373 If the widget is non-zero, only the dirty region for the widget is returned-
374 and the region will be in widget coordinates.-
375*/-
376QRegion QWidgetBackingStore::dirtyRegion(QWidget *widget) const-
377{-
378 const bool widgetDirty = widget && widget != tlw;-
379 const QRect tlwRect(topLevelRect());-
380 const QRect surfaceGeometry(tlwRect.topLeft(), store->size());-
381 if (fullUpdatePending || (surfaceGeometry != tlwRect && surfaceGeometry.size() != tlwRect.size())) {-
382 if (widgetDirty) {-
383 const QRect dirtyTlwRect = QRect(QPoint(), tlwRect.size());-
384 const QPoint offset(widget->mapTo(tlw, QPoint()));-
385 const QRect dirtyWidgetRect(dirtyTlwRect & widget->rect().translated(offset));-
386 return dirtyWidgetRect.translated(-offset);-
387 }-
388 return QRect(QPoint(), tlwRect.size());-
389 }-
390-
391 // Calculate the region that needs repaint.-
392 QRegion r(dirty);-
393 for (int i = 0; i < dirtyWidgets.size(); ++i) {-
394 QWidget *w = dirtyWidgets.at(i);-
395 if (widgetDirty && w != widget && !widget->isAncestorOf(w))-
396 continue;-
397 r += w->d_func()->dirty.translated(w->mapTo(tlw, QPoint()));-
398 }-
399-
400 // Append the region that needs flush.-
401 r += dirtyOnScreen;-
402-
403 if (dirtyOnScreenWidgets) { // Only in use with native child widgets.-
404 for (int i = 0; i < dirtyOnScreenWidgets->size(); ++i) {-
405 QWidget *w = dirtyOnScreenWidgets->at(i);-
406 if (widgetDirty && w != widget && !widget->isAncestorOf(w))-
407 continue;-
408 QWidgetPrivate *wd = w->d_func();-
409 Q_ASSERT(wd->needsFlush);-
410 r += wd->needsFlush->translated(w->mapTo(tlw, QPoint()));-
411 }-
412 }-
413-
414 if (widgetDirty) {-
415 // Intersect with the widget geometry and translate to its coordinates.-
416 const QPoint offset(widget->mapTo(tlw, QPoint()));-
417 r &= widget->rect().translated(offset);-
418 r.translate(-offset);-
419 }-
420 return r;-
421}-
422-
423/*!-
424 Returns the static content inside the \a parent if non-zero; otherwise the static content-
425 for the entire backing store is returned. The content will be clipped to \a withinClipRect-
426 if non-empty.-
427*/-
428QRegion QWidgetBackingStore::staticContents(QWidget *parent, const QRect &withinClipRect) const-
429{-
430 if (!parent && tlw->testAttribute(Qt::WA_StaticContents)) {-
431 const QSize surfaceGeometry(store->size());-
432 QRect surfaceRect(0, 0, surfaceGeometry.width(), surfaceGeometry.height());-
433 if (!withinClipRect.isEmpty())-
434 surfaceRect &= withinClipRect;-
435 return QRegion(surfaceRect);-
436 }-
437-
438 QRegion region;-
439 if (parent && parent->d_func()->children.isEmpty())-
440 return region;-
441-
442 const bool clipToRect = !withinClipRect.isEmpty();-
443 const int count = staticWidgets.count();-
444 for (int i = 0; i < count; ++i) {-
445 QWidget *w = staticWidgets.at(i);-
446 QWidgetPrivate *wd = w->d_func();-
447 if (!wd->isOpaque || !wd->extra || wd->extra->staticContentsSize.isEmpty()-
448 || !w->isVisible() || (parent && !parent->isAncestorOf(w))) {-
449 continue;-
450 }-
451-
452 QRect rect(0, 0, wd->extra->staticContentsSize.width(), wd->extra->staticContentsSize.height());-
453 const QPoint offset = w->mapTo(parent ? parent : tlw, QPoint());-
454 if (clipToRect)-
455 rect &= withinClipRect.translated(-offset);-
456 if (rect.isEmpty())-
457 continue;-
458-
459 rect &= wd->clipRect();-
460 if (rect.isEmpty())-
461 continue;-
462-
463 QRegion visible(rect);-
464 wd->clipToEffectiveMask(visible);-
465 if (visible.isEmpty())-
466 continue;-
467 wd->subtractOpaqueSiblings(visible, 0, /*alsoNonOpaque=*/true);-
468-
469 visible.translate(offset);-
470 region += visible;-
471 }-
472-
473 return region;-
474}-
475-
476void QWidgetBackingStore::sendUpdateRequest(QWidget *widget, UpdateTime updateTime)-
477{-
478 if (!widget)-
479 return;-
480-
481#ifndef QT_NO_OPENGL-
482 // Having every repaint() leading to a sync/flush is bad as it causes-
483 // compositing and waiting for vsync each and every time. Change to-
484 // UpdateLater, except for approx. once per frame to prevent starvation in-
485 // case the control does not get back to the event loop.-
486 QWidget *w = widget->window();-
487 if (updateTime == UpdateNow && w && w->windowHandle() && QWindowPrivate::get(w->windowHandle())->compositing) {-
488 int refresh = 60;-
489 QScreen *ws = w->windowHandle()->screen();-
490 if (ws)-
491 refresh = ws->refreshRate();-
492 QWindowPrivate *wd = QWindowPrivate::get(w->windowHandle());-
493 if (wd->lastComposeTime.isValid()) {-
494 const qint64 elapsed = wd->lastComposeTime.elapsed();-
495 if (elapsed <= qint64(1000.0f / refresh))-
496 updateTime = UpdateLater;-
497 }-
498 }-
499#endif-
500-
501 switch (updateTime) {-
502 case UpdateLater:-
503 updateRequestSent = true;-
504 QApplication::postEvent(widget, new QEvent(QEvent::UpdateRequest), Qt::LowEventPriority);-
505 break;-
506 case UpdateNow: {-
507 QEvent event(QEvent::UpdateRequest);-
508 QApplication::sendEvent(widget, &event);-
509 break;-
510 }-
511 }-
512}-
513-
514/*!-
515 Marks the region of the widget as dirty (if not already marked as dirty) and-
516 posts an UpdateRequest event to the top-level widget (if not already posted).-
517-
518 If updateTime is UpdateNow, the event is sent immediately instead of posted.-
519-
520 If bufferState is BufferInvalid, all widgets intersecting with the region will be dirty.-
521-
522 If the widget paints directly on screen, the event is sent to the widget-
523 instead of the top-level widget, and bufferState is completely ignored.-
524-
525 ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).-
526*/-
527void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget,-
528 UpdateTime updateTime, BufferState bufferState)-
529{-
530 Q_ASSERT(tlw->d_func()->extra);-
531 Q_ASSERT(tlw->d_func()->extra->topextra);-
532 Q_ASSERT(!tlw->d_func()->extra->topextra->inTopLevelResize);-
533 Q_ASSERT(widget->isVisible() && widget->updatesEnabled());-
534 Q_ASSERT(widget->window() == tlw);-
535 Q_ASSERT(!rgn.isEmpty());-
536-
537#ifndef QT_NO_GRAPHICSEFFECT-
538 widget->d_func()->invalidateGraphicsEffectsRecursively();-
539#endif //QT_NO_GRAPHICSEFFECT-
540-
541 if (widget->d_func()->paintOnScreen()) {-
542 if (widget->d_func()->dirty.isEmpty()) {-
543 widget->d_func()->dirty = rgn;-
544 sendUpdateRequest(widget, updateTime);-
545 return;-
546 } else if (qt_region_strictContains(widget->d_func()->dirty, widget->rect())) {-
547 if (updateTime == UpdateNow)-
548 sendUpdateRequest(widget, updateTime);-
549 return; // Already dirty.-
550 }-
551-
552 const bool eventAlreadyPosted = !widget->d_func()->dirty.isEmpty();-
553 widget->d_func()->dirty += rgn;-
554 if (!eventAlreadyPosted || updateTime == UpdateNow)-
555 sendUpdateRequest(widget, updateTime);-
556 return;-
557 }-
558-
559 //### FIXME fullUpdatePending seems to be always false????-
560 if (fullUpdatePending) {-
561 if (updateTime == UpdateNow)-
562 sendUpdateRequest(tlw, updateTime);-
563 return;-
564 }-
565-
566 const QPoint offset = widget->mapTo(tlw, QPoint());-
567-
568 if (QWidgetPrivate::get(widget)->renderToTexture) {-
569 if (!widget->d_func()->inDirtyList)-
570 addDirtyRenderToTextureWidget(widget);-
571 if (!updateRequestSent || updateTime == UpdateNow)-
572 sendUpdateRequest(tlw, updateTime);-
573 return;-
574 }-
575-
576 const QRect widgetRect = widget->d_func()->effectiveRectFor(widget->rect());-
577 if (qt_region_strictContains(dirty, widgetRect.translated(offset))) {-
578 if (updateTime == UpdateNow)-
579 sendUpdateRequest(tlw, updateTime);-
580 return; // Already dirty.-
581 }-
582-
583 if (bufferState == BufferInvalid) {-
584 const bool eventAlreadyPosted = !dirty.isEmpty() || updateRequestSent;-
585#ifndef QT_NO_GRAPHICSEFFECT-
586 if (widget->d_func()->graphicsEffect)-
587 dirty += widget->d_func()->effectiveRectFor(rgn.boundingRect()).translated(offset);-
588 else-
589#endif //QT_NO_GRAPHICSEFFECT-
590 dirty += rgn.translated(offset);-
591 if (!eventAlreadyPosted || updateTime == UpdateNow)-
592 sendUpdateRequest(tlw, updateTime);-
593 return;-
594 }-
595-
596 if (dirtyWidgets.isEmpty()) {-
597 addDirtyWidget(widget, rgn);-
598 sendUpdateRequest(tlw, updateTime);-
599 return;-
600 }-
601-
602 if (widget->d_func()->inDirtyList) {-
603 if (!qt_region_strictContains(widget->d_func()->dirty, widgetRect)) {-
604#ifndef QT_NO_GRAPHICSEFFECT-
605 if (widget->d_func()->graphicsEffect)-
606 widget->d_func()->dirty += widget->d_func()->effectiveRectFor(rgn.boundingRect());-
607 else-
608#endif //QT_NO_GRAPHICSEFFECT-
609 widget->d_func()->dirty += rgn;-
610 }-
611 } else {-
612 addDirtyWidget(widget, rgn);-
613 }-
614-
615 if (updateTime == UpdateNow)-
616 sendUpdateRequest(tlw, updateTime);-
617}-
618-
619/*!-
620 This function is equivalent to calling markDirty(QRegion(rect), ...), but-
621 is more efficient as it eliminates QRegion operations/allocations and can-
622 use the rect more precisely for additional cut-offs.-
623-
624 ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).-
625*/-
626void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget,-
627 UpdateTime updateTime, BufferState bufferState)-
628{-
629 Q_ASSERT(tlw->d_func()->extra);-
630 Q_ASSERT(tlw->d_func()->extra->topextra);-
631 Q_ASSERT(!tlw->d_func()->extra->topextra->inTopLevelResize);-
632 Q_ASSERT(widget->isVisible() && widget->updatesEnabled());-
633 Q_ASSERT(widget->window() == tlw);-
634 Q_ASSERT(!rect.isEmpty());-
635-
636#ifndef QT_NO_GRAPHICSEFFECT-
637 widget->d_func()->invalidateGraphicsEffectsRecursively();-
638#endif //QT_NO_GRAPHICSEFFECT-
639-
640 if (widget->d_func()->paintOnScreen()) {-
641 if (widget->d_func()->dirty.isEmpty()) {-
642 widget->d_func()->dirty = QRegion(rect);-
643 sendUpdateRequest(widget, updateTime);-
644 return;-
645 } else if (qt_region_strictContains(widget->d_func()->dirty, rect)) {-
646 if (updateTime == UpdateNow)-
647 sendUpdateRequest(widget, updateTime);-
648 return; // Already dirty.-
649 }-
650-
651 const bool eventAlreadyPosted = !widget->d_func()->dirty.isEmpty();-
652 widget->d_func()->dirty += rect;-
653 if (!eventAlreadyPosted || updateTime == UpdateNow)-
654 sendUpdateRequest(widget, updateTime);-
655 return;-
656 }-
657-
658 if (fullUpdatePending) {-
659 if (updateTime == UpdateNow)-
660 sendUpdateRequest(tlw, updateTime);-
661 return;-
662 }-
663-
664 if (QWidgetPrivate::get(widget)->renderToTexture) {-
665 if (!widget->d_func()->inDirtyList)-
666 addDirtyRenderToTextureWidget(widget);-
667 if (!updateRequestSent || updateTime == UpdateNow)-
668 sendUpdateRequest(tlw, updateTime);-
669 return;-
670 }-
671-
672-
673 const QRect widgetRect = widget->d_func()->effectiveRectFor(rect);-
674 QRect translatedRect = widgetRect;-
675 if (widget != tlw)-
676 translatedRect.translate(widget->mapTo(tlw, QPoint()));-
677 // Graphics effects may exceed window size, clamp.-
678 translatedRect = translatedRect.intersected(QRect(QPoint(), tlw->size()));-
679 if (qt_region_strictContains(dirty, translatedRect)) {-
680 if (updateTime == UpdateNow)-
681 sendUpdateRequest(tlw, updateTime);-
682 return; // Already dirty-
683 }-
684-
685 if (bufferState == BufferInvalid) {-
686 const bool eventAlreadyPosted = !dirty.isEmpty();-
687 dirty += translatedRect;-
688 if (!eventAlreadyPosted || updateTime == UpdateNow)-
689 sendUpdateRequest(tlw, updateTime);-
690 return;-
691 }-
692-
693 if (dirtyWidgets.isEmpty()) {-
694 addDirtyWidget(widget, rect);-
695 sendUpdateRequest(tlw, updateTime);-
696 return;-
697 }-
698-
699 if (widget->d_func()->inDirtyList) {-
700 if (!qt_region_strictContains(widget->d_func()->dirty, widgetRect))-
701 widget->d_func()->dirty += widgetRect;-
702 } else {-
703 addDirtyWidget(widget, rect);-
704 }-
705-
706 if (updateTime == UpdateNow)-
707 sendUpdateRequest(tlw, updateTime);-
708}-
709-
710/*!-
711 Marks the \a region of the \a widget as dirty on screen. The \a region will be copied from-
712 the backing store to the \a widget's native parent next time flush() is called.-
713-
714 Paint on screen widgets are ignored.-
715*/-
716void QWidgetBackingStore::markDirtyOnScreen(const QRegion &region, QWidget *widget, const QPoint &topLevelOffset)-
717{-
718 if (!widget || widget->d_func()->paintOnScreen() || region.isEmpty())-
719 return;-
720-
721#if defined(Q_DEAD_CODE_FROM_QT4_MAC)-
722 if (!widget->testAttribute(Qt::WA_WState_InPaintEvent))-
723 dirtyOnScreen += region.translated(topLevelOffset);-
724 return;-
725#endif-
726-
727 // Top-level.-
728 if (widget == tlw) {-
729 if (!widget->testAttribute(Qt::WA_WState_InPaintEvent))-
730 dirtyOnScreen += region;-
731 return;-
732 }-
733-
734 // Alien widgets.-
735 if (!widget->internalWinId() && !widget->isWindow()) {-
736 QWidget *nativeParent = widget->nativeParentWidget(); // Alien widgets with the top-level as the native parent (common case).-
737 if (nativeParent == tlw) {-
738 if (!widget->testAttribute(Qt::WA_WState_InPaintEvent))-
739 dirtyOnScreen += region.translated(topLevelOffset);-
740 return;-
741 }-
742-
743 // Alien widgets with native parent != tlw.-
744 QWidgetPrivate *nativeParentPrivate = nativeParent->d_func();-
745 if (!nativeParentPrivate->needsFlush)-
746 nativeParentPrivate->needsFlush = new QRegion;-
747 const QPoint nativeParentOffset = widget->mapTo(nativeParent, QPoint());-
748 *nativeParentPrivate->needsFlush += region.translated(nativeParentOffset);-
749 appendDirtyOnScreenWidget(nativeParent);-
750 return;-
751 }-
752-
753 // Native child widgets.-
754 QWidgetPrivate *widgetPrivate = widget->d_func();-
755 if (!widgetPrivate->needsFlush)-
756 widgetPrivate->needsFlush = new QRegion;-
757 *widgetPrivate->needsFlush += region;-
758 appendDirtyOnScreenWidget(widget);-
759}-
760-
761void QWidgetBackingStore::removeDirtyWidget(QWidget *w)-
762{-
763 if (!w)-
764 return;-
765-
766 dirtyWidgetsRemoveAll(w);-
767 dirtyOnScreenWidgetsRemoveAll(w);-
768 dirtyRenderToTextureWidgets.removeAll(w);-
769 resetWidget(w);-
770-
771 QWidgetPrivate *wd = w->d_func();-
772 const int n = wd->children.count();-
773 for (int i = 0; i < n; ++i) {-
774 if (QWidget *child = qobject_cast<QWidget*>(wd->children.at(i)))-
775 removeDirtyWidget(child);-
776 }-
777}-
778-
779void QWidgetBackingStore::updateLists(QWidget *cur)-
780{-
781 if (!cur)-
782 return;-
783-
784 QList<QObject*> children = cur->children();-
785 for (int i = 0; i < children.size(); ++i) {-
786 QWidget *child = qobject_cast<QWidget*>(children.at(i));-
787 if (!child)-
788 continue;-
789-
790 updateLists(child);-
791 }-
792-
793 if (cur->testAttribute(Qt::WA_StaticContents))-
794 addStaticWidget(cur);-
795}-
796-
797QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel)-
798 : tlw(topLevel),-
799 dirtyOnScreenWidgets(0),-
800 fullUpdatePending(0),-
801 updateRequestSent(0),-
802 textureListWatcher(0),-
803 perfFrames(0)-
804{-
805 store = tlw->backingStore();-
806 Q_ASSERT(store);-
807-
808 // Ensure all existing subsurfaces and static widgets are added to their respective lists.-
809 updateLists(topLevel);-
810}-
811-
812QWidgetBackingStore::~QWidgetBackingStore()-
813{-
814 for (int c = 0; c < dirtyWidgets.size(); ++c)-
815 resetWidget(dirtyWidgets.at(c));-
816 for (int c = 0; c < dirtyRenderToTextureWidgets.size(); ++c)-
817 resetWidget(dirtyRenderToTextureWidgets.at(c));-
818-
819 delete dirtyOnScreenWidgets;-
820}-
821-
822//parent's coordinates; move whole rect; update parent and widget-
823//assume the screen blt has already been done, so we don't need to refresh that part-
824void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy)-
825{-
826 Q_Q(QWidget);-
827 if (!q->isVisible() || (dx == 0 && dy == 0))-
828 return;-
829-
830 QWidget *tlw = q->window();-
831 QTLWExtra* x = tlw->d_func()->topData();-
832 if (x->inTopLevelResize)-
833 return;-
834-
835 static const bool accelEnv = qEnvironmentVariableIntValue("QT_NO_FAST_MOVE") == 0;-
836-
837 QWidget *pw = q->parentWidget();-
838 QPoint toplevelOffset = pw->mapTo(tlw, QPoint());-
839 QWidgetPrivate *pd = pw->d_func();-
840 QRect clipR(pd->clipRect());-
841 const QRect newRect(rect.translated(dx, dy));-
842 QRect destRect = rect.intersected(clipR);-
843 if (destRect.isValid())-
844 destRect = destRect.translated(dx, dy).intersected(clipR);-
845 const QRect sourceRect(destRect.translated(-dx, -dy));-
846 const QRect parentRect(rect & clipR);-
847 const bool nativeWithTextureChild = textureChildSeen && q->internalWinId();-
848-
849 bool accelerateMove = accelEnv && isOpaque && !nativeWithTextureChild-
850#ifndef QT_NO_GRAPHICSVIEW-
851 // No accelerate move for proxy widgets.-
852 && !tlw->d_func()->extra->proxyWidget-
853#endif-
854 && !isOverlapped(sourceRect) && !isOverlapped(destRect);-
855-
856 if (!accelerateMove) {-
857 QRegion parentR(effectiveRectFor(parentRect));-
858 if (!extra || !extra->hasMask) {-
859 parentR -= newRect;-
860 } else {-
861 // invalidateBuffer() excludes anything outside the mask-
862 parentR += newRect & clipR;-
863 }-
864 pd->invalidateBuffer(parentR);-
865 invalidateBuffer((newRect & clipR).translated(-data.crect.topLeft()));-
866 } else {-
867-
868 QWidgetBackingStore *wbs = x->backingStoreTracker.data();-
869 QRegion childExpose(newRect & clipR);-
870-
871 if (sourceRect.isValid() && wbs->bltRect(sourceRect, dx, dy, pw))-
872 childExpose -= destRect;-
873-
874 if (!pw->updatesEnabled())-
875 return;-
876-
877 const bool childUpdatesEnabled = q->updatesEnabled();-
878 if (childUpdatesEnabled && !childExpose.isEmpty()) {-
879 childExpose.translate(-data.crect.topLeft());-
880 wbs->markDirty(childExpose, q);-
881 isMoved = true;-
882 }-
883-
884 QRegion parentExpose(parentRect);-
885 parentExpose -= newRect;-
886 if (extra && extra->hasMask)-
887 parentExpose += QRegion(newRect) - extra->mask.translated(data.crect.topLeft());-
888-
889 if (!parentExpose.isEmpty()) {-
890 wbs->markDirty(parentExpose, pw);-
891 pd->isMoved = true;-
892 }-
893-
894 if (childUpdatesEnabled) {-
895 QRegion needsFlush(sourceRect);-
896 needsFlush += destRect;-
897 wbs->markDirtyOnScreen(needsFlush, pw, toplevelOffset);-
898 }-
899 }-
900}-
901-
902//widget's coordinates; scroll within rect; only update widget-
903void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy)-
904{-
905 Q_Q(QWidget);-
906 QWidget *tlw = q->window();-
907 QTLWExtra* x = tlw->d_func()->topData();-
908 if (x->inTopLevelResize)-
909 return;-
910-
911 QWidgetBackingStore *wbs = x->backingStoreTracker.data();-
912 if (!wbs)-
913 return;-
914-
915 static const bool accelEnv = qEnvironmentVariableIntValue("QT_NO_FAST_SCROLL") == 0;-
916-
917 QRect scrollRect = rect & clipRect();-
918 bool overlapped = false;-
919 bool accelerateScroll = accelEnv && isOpaque && !q_func()->testAttribute(Qt::WA_WState_InPaintEvent)-
920 && !(overlapped = isOverlapped(scrollRect.translated(data.crect.topLeft())));-
921-
922 if (!accelerateScroll) {-
923 if (overlapped) {-
924 QRegion region(scrollRect);-
925 subtractOpaqueSiblings(region);-
926 invalidateBuffer(region);-
927 }else {-
928 invalidateBuffer(scrollRect);-
929 }-
930 } else {-
931 const QPoint toplevelOffset = q->mapTo(tlw, QPoint());-
932 const QRect destRect = scrollRect.translated(dx, dy) & scrollRect;-
933 const QRect sourceRect = destRect.translated(-dx, -dy);-
934-
935 QRegion childExpose(scrollRect);-
936 if (sourceRect.isValid()) {-
937 if (wbs->bltRect(sourceRect, dx, dy, q))-
938 childExpose -= destRect;-
939 }-
940-
941 if (inDirtyList) {-
942 if (rect == q->rect()) {-
943 dirty.translate(dx, dy);-
944 } else {-
945 QRegion dirtyScrollRegion = dirty.intersected(scrollRect);-
946 if (!dirtyScrollRegion.isEmpty()) {-
947 dirty -= dirtyScrollRegion;-
948 dirtyScrollRegion.translate(dx, dy);-
949 dirty += dirtyScrollRegion;-
950 }-
951 }-
952 }-
953-
954 if (!q->updatesEnabled())-
955 return;-
956-
957 if (!childExpose.isEmpty()) {-
958 wbs->markDirty(childExpose, q);-
959 isScrolled = true;-
960 }-
961-
962 // Instead of using native scroll-on-screen, we copy from-
963 // backingstore, giving only one screen update for each-
964 // scroll, and a solid appearance-
965 wbs->markDirtyOnScreen(destRect, q, toplevelOffset);-
966 }-
967}-
968-
969#ifndef QT_NO_OPENGL-
970static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatformTextureList *widgetTextures, QVector<QWidget *> *nativeChildren)-
971{-
972 QWidgetPrivate *wd = QWidgetPrivate::get(widget);-
973 if (wd->renderToTexture) {-
974 QPlatformTextureList::Flags flags = 0;-
975 if (widget->testAttribute(Qt::WA_AlwaysStackOnTop))-
976 flags |= QPlatformTextureList::StacksOnTop;-
977 const QRect rect(widget->mapTo(tlw, QPoint()), widget->size());-
978 widgetTextures->appendTexture(widget, wd->textureId(), rect, wd->clipRect(), flags);-
979 }-
980-
981 for (int i = 0; i < wd->children.size(); ++i) {-
982 QWidget *w = qobject_cast<QWidget *>(wd->children.at(i));-
983 // Stop at native widgets but store them. Stop at hidden widgets too.-
984 if (w && !w->isWindow() && w->internalWinId())-
985 nativeChildren->append(w);-
986 if (w && !w->isWindow() && !w->internalWinId() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen)-
987 findTextureWidgetsRecursively(tlw, w, widgetTextures, nativeChildren);-
988 }-
989}-
990-
991static void findAllTextureWidgetsRecursively(QWidget *tlw, QWidget *widget)-
992{-
993 // textureChildSeen does not take native child widgets into account and that's good.-
994 if (QWidgetPrivate::get(widget)->textureChildSeen) {-
995 QVector<QWidget *> nativeChildren;-
996 QScopedPointer<QPlatformTextureList> tl(new QPlatformTextureList);-
997 // Look for texture widgets (incl. widget itself) from 'widget' down,-
998 // but skip subtrees with a parent of a native child widget.-
999 findTextureWidgetsRecursively(tlw, widget, tl.data(), &nativeChildren);-
1000 // tl may be empty regardless of textureChildSeen if we have native or hidden children.-
1001 if (!tl->isEmpty())-
1002 QWidgetPrivate::get(tlw)->topData()->widgetTextures.append(tl.take());-
1003 // Native child widgets, if there was any, get their own separate QPlatformTextureList.-
1004 foreach (QWidget *ncw, nativeChildren) {-
1005 if (QWidgetPrivate::get(ncw)->textureChildSeen)-
1006 findAllTextureWidgetsRecursively(tlw, ncw);-
1007 }-
1008 }-
1009}-
1010-
1011static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget)-
1012{-
1013 foreach (QPlatformTextureList *tl, QWidgetPrivate::get(tlw)->topData()->widgetTextures) {-
1014 Q_ASSERT(!tl->isEmpty());-
1015 for (int i = 0; i < tl->count(); ++i) {-
1016 QWidget *w = static_cast<QWidget *>(tl->source(i));-
1017 if ((w->internalWinId() && w == widget) || (!w->internalWinId() && w->nativeParentWidget() == widget))-
1018 return tl;-
1019 }-
1020 }-
1021-
1022 if (QWidgetPrivate::get(tlw)->textureChildSeen) {-
1023 // No render-to-texture widgets in the (sub-)tree due to hidden or native-
1024 // children. Returning null results in using the normal backingstore flush path-
1025 // without OpenGL-based compositing. This is very desirable normally. However,-
1026 // some platforms cannot handle switching between the non-GL and GL paths for-
1027 // their windows so it has to be opt-in.-
1028 static bool switchableWidgetComposition =-
1029 QGuiApplicationPrivate::instance()->platformIntegration()-
1030 ->hasCapability(QPlatformIntegration::SwitchableWidgetComposition);-
1031 if (!switchableWidgetComposition-
1032// The Windows compositor handles fullscreen OpenGL window specially. Besides-
1033// having trouble with popups, it also has issues with flip-flopping between-
1034// OpenGL-based and normal flushing. Therefore, stick with GL for fullscreen-
1035// windows (QTBUG-53515). Similary, translucent windows should not switch to-
1036// layered native windows (QTBUG-54734).-
1037#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) && !defined(Q_OS_WINCE)-
1038 || tlw->windowState().testFlag(Qt::WindowFullScreen)-
1039 || tlw->testAttribute(Qt::WA_TranslucentBackground)-
1040#endif-
1041 )-
1042 {-
1043 return qt_dummy_platformTextureList();-
1044 }-
1045 }-
1046-
1047 return 0;-
1048}-
1049-
1050// Watches one or more QPlatformTextureLists for changes in the lock state and-
1051// triggers a backingstore sync when all the registered lists turn into-
1052// unlocked state. This is essential when a custom composeAndFlush()-
1053// implementation in a platform plugin is not synchronous and keeps-
1054// holding on to the textures for some time even after returning from there.-
1055QPlatformTextureListWatcher::QPlatformTextureListWatcher(QWidgetBackingStore *backingStore)-
1056 : m_backingStore(backingStore)-
1057{-
1058}-
1059-
1060void QPlatformTextureListWatcher::watch(QPlatformTextureList *textureList)-
1061{-
1062 connect(textureList, SIGNAL(locked(bool)), SLOT(onLockStatusChanged(bool)));-
1063 m_locked[textureList] = textureList->isLocked();-
1064}-
1065-
1066bool QPlatformTextureListWatcher::isLocked() const-
1067{-
1068 foreach (bool v, m_locked) {-
1069 if (v)-
1070 return true;-
1071 }-
1072 return false;-
1073}-
1074-
1075void QPlatformTextureListWatcher::onLockStatusChanged(bool locked)-
1076{-
1077 QPlatformTextureList *tl = static_cast<QPlatformTextureList *>(sender());-
1078 m_locked[tl] = locked;-
1079 if (!isLocked())-
1080 m_backingStore->sync();-
1081}-
1082-
1083#else-
1084-
1085static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget)-
1086{-
1087 Q_UNUSED(tlw);-
1088 Q_UNUSED(widget);-
1089 return Q_NULLPTR;-
1090}-
1091-
1092#endif // QT_NO_OPENGL-
1093-
1094static inline bool discardSyncRequest(QWidget *tlw, QTLWExtra *tlwExtra)-
1095{-
1096 if (!tlw || !tlwExtra || !tlw->testAttribute(Qt::WA_Mapped) || !tlw->isVisible())-
1097 return true;-
1098-
1099 return false;-
1100}-
1101-
1102bool QWidgetBackingStore::syncAllowed()-
1103{-
1104#ifndef QT_NO_OPENGL-
1105 QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData();-
1106 if (textureListWatcher && !textureListWatcher->isLocked()) {-
1107 textureListWatcher->deleteLater();-
1108 textureListWatcher = 0;-
1109 } else if (!tlwExtra->widgetTextures.isEmpty()) {-
1110 bool skipSync = false;-
1111 foreach (QPlatformTextureList *tl, tlwExtra->widgetTextures) {-
1112 if (tl->isLocked()) {-
1113 if (!textureListWatcher)-
1114 textureListWatcher = new QPlatformTextureListWatcher(this);-
1115 if (!textureListWatcher->isLocked())-
1116 textureListWatcher->watch(tl);-
1117 skipSync = true;-
1118 }-
1119 }-
1120 if (skipSync) // cannot compose due to widget textures being in use-
1121 return false;-
1122 }-
1123#endif-
1124 return true;-
1125}-
1126-
1127/*!-
1128 Synchronizes the \a exposedRegion of the \a exposedWidget with the backing store.-
1129-
1130 If there's nothing to repaint, the area is flushed and painting does not occur;-
1131 otherwise the area is marked as dirty on screen and will be flushed right after-
1132 we are done with all painting.-
1133*/-
1134void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedRegion)-
1135{-
1136 QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData();-
1137 if (!tlw->isVisible() || !tlwExtra || tlwExtra->inTopLevelResize)-
1138 return;-
1139-
1140 if (!exposedWidget || !exposedWidget->internalWinId() || !exposedWidget->isVisible() || !exposedWidget->testAttribute(Qt::WA_Mapped)-
1141 || !exposedWidget->updatesEnabled() || exposedRegion.isEmpty()) {-
1142 return;-
1143 }-
1144-
1145 // Nothing to repaint.-
1146 if (!isDirty() && store->size().isValid()) {-
1147 QPlatformTextureList *tl = widgetTexturesFor(tlw, exposedWidget);-
1148 qt_flush(exposedWidget, tl ? QRegion() : exposedRegion, store, tlw, tlwOffset, tl, this);-
1149 return;-
1150 }-
1151-
1152 if (exposedWidget != tlw)-
1153 markDirtyOnScreen(exposedRegion, exposedWidget, exposedWidget->mapTo(tlw, QPoint()));-
1154 else-
1155 markDirtyOnScreen(exposedRegion, exposedWidget, QPoint());-
1156-
1157 if (syncAllowed())-
1158 doSync();-
1159}-
1160-
1161/*!-
1162 Synchronizes the backing store, i.e. dirty areas are repainted and flushed.-
1163*/-
1164void QWidgetBackingStore::sync()-
1165{-
1166 updateRequestSent = false;-
1167 QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData();-
1168 if (discardSyncRequest(tlw, tlwExtra)) {-
1169 // If the top-level is minimized, it's not visible on the screen so we can delay the-
1170 // update until it's shown again. In order to do that we must keep the dirty states.-
1171 // These will be cleared when we receive the first expose after showNormal().-
1172 // However, if the widget is not visible (isVisible() returns false), everything will-
1173 // be invalidated once the widget is shown again, so clear all dirty states.-
1174 if (!tlw->isVisible()) {-
1175 dirty = QRegion();-
1176 for (int i = 0; i < dirtyWidgets.size(); ++i)-
1177 resetWidget(dirtyWidgets.at(i));-
1178 dirtyWidgets.clear();-
1179 fullUpdatePending = false;-
1180 }-
1181 return;-
1182 }-
1183-
1184 if (syncAllowed())-
1185 doSync();-
1186}-
1187-
1188void QWidgetBackingStore::doSync()-
1189{-
1190 const bool updatesDisabled = !tlw->updatesEnabled();-
1191 bool repaintAllWidgets = false;-
1192-
1193 const bool inTopLevelResize = tlw->d_func()->maybeTopData()->inTopLevelResize;-
1194 const QRect tlwRect(topLevelRect());-
1195 const QRect surfaceGeometry(tlwRect.topLeft(), store->size());-
1196 if ((fullUpdatePending || inTopLevelResize || surfaceGeometry.size() != tlwRect.size()) && !updatesDisabled) {-
1197 if (hasStaticContents() && !store->size().isEmpty() ) {-
1198 // Repaint existing dirty area and newly visible area.-
1199 const QRect clipRect(0, 0, surfaceGeometry.width(), surfaceGeometry.height());-
1200 const QRegion staticRegion(staticContents(0, clipRect));-
1201 QRegion newVisible(0, 0, tlwRect.width(), tlwRect.height());-
1202 newVisible -= staticRegion;-
1203 dirty += newVisible;-
1204 store->setStaticContents(staticRegion);-
1205 } else {-
1206 // Repaint everything.-
1207 dirty = QRegion(0, 0, tlwRect.width(), tlwRect.height());-
1208 for (int i = 0; i < dirtyWidgets.size(); ++i)-
1209 resetWidget(dirtyWidgets.at(i));-
1210 dirtyWidgets.clear();-
1211 repaintAllWidgets = true;-
1212 }-
1213 }-
1214-
1215 if (inTopLevelResize || surfaceGeometry.size() != tlwRect.size())-
1216 store->resize(tlwRect.size());-
1217-
1218 if (updatesDisabled)-
1219 return;-
1220-
1221 // Contains everything that needs repaint.-
1222 QRegion toClean(dirty);-
1223-
1224 // Loop through all update() widgets and remove them from the list before they are-
1225 // painted (in case someone calls update() in paintEvent). If the widget is opaque-
1226 // and does not have transparent overlapping siblings, append it to the-
1227 // opaqueNonOverlappedWidgets list and paint it directly without composition.-
1228 QVarLengthArray<QWidget *, 32> opaqueNonOverlappedWidgets;-
1229 for (int i = 0; i < dirtyWidgets.size(); ++i) {-
1230 QWidget *w = dirtyWidgets.at(i);-
1231 QWidgetPrivate *wd = w->d_func();-
1232 if (wd->data.in_destructor)-
1233 continue;-
1234-
1235 // Clip with mask() and clipRect().-
1236 wd->dirty &= wd->clipRect();-
1237 wd->clipToEffectiveMask(wd->dirty);-
1238-
1239 // Subtract opaque siblings and children.-
1240 bool hasDirtySiblingsAbove = false;-
1241 // We know for sure that the widget isn't overlapped if 'isMoved' is true.-
1242 if (!wd->isMoved)-
1243 wd->subtractOpaqueSiblings(wd->dirty, &hasDirtySiblingsAbove);-
1244-
1245 // Make a copy of the widget's dirty region, to restore it in case there is an opaque-
1246 // render-to-texture child that completely covers the widget, because otherwise the-
1247 // render-to-texture child won't be visible, due to its parent widget not being redrawn-
1248 // with a proper blending mask.-
1249 const QRegion dirtyBeforeSubtractedOpaqueChildren = wd->dirty;-
1250-
1251 // Scrolled and moved widgets must draw all children.-
1252 if (!wd->isScrolled && !wd->isMoved)-
1253 wd->subtractOpaqueChildren(wd->dirty, w->rect());-
1254-
1255 if (wd->dirty.isEmpty() && wd->textureChildSeen)-
1256 wd->dirty = dirtyBeforeSubtractedOpaqueChildren;-
1257-
1258 if (wd->dirty.isEmpty()) {-
1259 resetWidget(w);-
1260 continue;-
1261 }-
1262-
1263 const QRegion widgetDirty(w != tlw ? wd->dirty.translated(w->mapTo(tlw, QPoint()))-
1264 : wd->dirty);-
1265 toClean += widgetDirty;-
1266-
1267#ifndef QT_NO_GRAPHICSVIEW-
1268 if (tlw->d_func()->extra->proxyWidget) {-
1269 resetWidget(w);-
1270 continue;-
1271 }-
1272#endif-
1273-
1274 if (!hasDirtySiblingsAbove && wd->isOpaque && !dirty.intersects(widgetDirty.boundingRect())) {-
1275 opaqueNonOverlappedWidgets.append(w);-
1276 } else {-
1277 resetWidget(w);-
1278 dirty += widgetDirty;-
1279 }-
1280 }-
1281 dirtyWidgets.clear();-
1282-
1283#ifndef QT_NO_OPENGL-
1284 // Find all render-to-texture child widgets (including self).-
1285 // The search is cut at native widget boundaries, meaning that each native child widget-
1286 // has its own list for the subtree below it.-
1287 QTLWExtra *tlwExtra = tlw->d_func()->topData();-
1288 qDeleteAll(tlwExtra->widgetTextures);-
1289 tlwExtra->widgetTextures.clear();-
1290 findAllTextureWidgetsRecursively(tlw, tlw);-
1291 qt_window_private(tlw->windowHandle())->compositing = false; // will get updated in qt_flush()-
1292 fullUpdatePending = false;-
1293#endif-
1294-
1295 if (toClean.isEmpty()) {-
1296 // Nothing to repaint. However renderToTexture widgets are handled-
1297 // specially, they are not in the regular dirty list, in order to-
1298 // prevent triggering unnecessary backingstore painting when only the-
1299 // OpenGL content changes. Check if we have such widgets in the special-
1300 // dirty list.-
1301 QVarLengthArray<QWidget *, 16> paintPending;-
1302 const int numPaintPending = dirtyRenderToTextureWidgets.count();-
1303 paintPending.reserve(numPaintPending);-
1304 for (int i = 0; i < numPaintPending; ++i) {-
1305 QWidget *w = dirtyRenderToTextureWidgets.at(i);-
1306 paintPending << w;-
1307 resetWidget(w);-
1308 }-
1309 dirtyRenderToTextureWidgets.clear();-
1310 for (int i = 0; i < numPaintPending; ++i) {-
1311 QWidget *w = paintPending[i];-
1312 w->d_func()->sendPaintEvent(w->rect());-
1313 if (w != tlw) {-
1314 QWidget *npw = w->nativeParentWidget();-
1315 if (w->internalWinId() || (npw && npw != tlw)) {-
1316 if (!w->internalWinId())-
1317 w = npw;-
1318 QWidgetPrivate *wPrivate = w->d_func();-
1319 if (!wPrivate->needsFlush)-
1320 wPrivate->needsFlush = new QRegion;-
1321 appendDirtyOnScreenWidget(w);-
1322 }-
1323 }-
1324 }-
1325-
1326 // We might have newly exposed areas on the screen if this function was-
1327 // called from sync(QWidget *, QRegion)), so we have to make sure those-
1328 // are flushed. We also need to composite the renderToTexture widgets.-
1329 flush();-
1330-
1331 return;-
1332 }-
1333-
1334#ifndef QT_NO_OPENGL-
1335 foreach (QPlatformTextureList *tl, tlwExtra->widgetTextures) {-
1336 for (int i = 0; i < tl->count(); ++i) {-
1337 QWidget *w = static_cast<QWidget *>(tl->source(i));-
1338 if (dirtyRenderToTextureWidgets.contains(w)) {-
1339 const QRect rect = tl->geometry(i); // mapped to the tlw already-
1340 // Set a flag to indicate that the paint event for this-
1341 // render-to-texture widget must not to be optimized away.-
1342 w->d_func()->renderToTextureReallyDirty = 1;-
1343 dirty += rect;-
1344 toClean += rect;-
1345 }-
1346 }-
1347 }-
1348 for (int i = 0; i < dirtyRenderToTextureWidgets.count(); ++i)-
1349 resetWidget(dirtyRenderToTextureWidgets.at(i));-
1350 dirtyRenderToTextureWidgets.clear();-
1351#endif-
1352-
1353#ifndef QT_NO_GRAPHICSVIEW-
1354 if (tlw->d_func()->extra->proxyWidget) {-
1355 updateStaticContentsSize();-
1356 dirty = QRegion();-
1357 updateRequestSent = false;-
1358 const QVector<QRect> rects(toClean.rects());-
1359 for (int i = 0; i < rects.size(); ++i)-
1360 tlw->d_func()->extra->proxyWidget->update(rects.at(i));-
1361 return;-
1362 }-
1363#endif-
1364-
1365 BeginPaintInfo beginPaintInfo;-
1366 beginPaint(toClean, tlw, store, &beginPaintInfo);-
1367 if (beginPaintInfo.nothingToPaint) {-
1368 for (int i = 0; i < opaqueNonOverlappedWidgets.size(); ++i)-
1369 resetWidget(opaqueNonOverlappedWidgets[i]);-
1370 dirty = QRegion();-
1371 updateRequestSent = false;-
1372 return;-
1373 }-
1374-
1375 // Must do this before sending any paint events because-
1376 // the size may change in the paint event.-
1377 updateStaticContentsSize();-
1378 const QRegion dirtyCopy(dirty);-
1379 dirty = QRegion();-
1380 updateRequestSent = false;-
1381-
1382 // Paint opaque non overlapped widgets.-
1383 for (int i = 0; i < opaqueNonOverlappedWidgets.size(); ++i) {-
1384 QWidget *w = opaqueNonOverlappedWidgets[i];-
1385 QWidgetPrivate *wd = w->d_func();-
1386-
1387 int flags = QWidgetPrivate::DrawRecursive;-
1388 // Scrolled and moved widgets must draw all children.-
1389 if (!wd->isScrolled && !wd->isMoved)-
1390 flags |= QWidgetPrivate::DontDrawOpaqueChildren;-
1391 if (w == tlw)-
1392 flags |= QWidgetPrivate::DrawAsRoot;-
1393-
1394 QRegion toBePainted(wd->dirty);-
1395 resetWidget(w);-
1396-
1397 QPoint offset(tlwOffset);-
1398 if (w != tlw)-
1399 offset += w->mapTo(tlw, QPoint());-
1400 wd->drawWidget(store->paintDevice(), toBePainted, offset, flags, 0, this);-
1401 }-
1402-
1403 // Paint the rest with composition.-
1404 if (repaintAllWidgets || !dirtyCopy.isEmpty()) {-
1405 const int flags = QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawRecursive;-
1406 tlw->d_func()->drawWidget(store->paintDevice(), dirtyCopy, tlwOffset, flags, 0, this);-
1407 }-
1408-
1409 endPaint(toClean, store, &beginPaintInfo);-
1410}-
1411-
1412/*!-
1413 Flushes the contents of the backing store into the top-level widget.-
1414 If the \a widget is non-zero, the content is flushed to the \a widget.-
1415 If the \a surface is non-zero, the content of the \a surface is flushed.-
1416*/-
1417void QWidgetBackingStore::flush(QWidget *widget)-
1418{-
1419 const bool hasDirtyOnScreenWidgets = dirtyOnScreenWidgets && !dirtyOnScreenWidgets->isEmpty();-
1420 bool flushed = false;-
1421-
1422 // Flush the region in dirtyOnScreen.-
1423 if (!dirtyOnScreen.isEmpty()) {-
1424 QWidget *target = widget ? widget : tlw;-
1425 qt_flush(target, dirtyOnScreen, store, tlw, tlwOffset, widgetTexturesFor(tlw, tlw), this);-
1426 dirtyOnScreen = QRegion();-
1427 flushed = true;-
1428 }-
1429-
1430 // Render-to-texture widgets are not in dirtyOnScreen so flush if we have not done it above.-
1431 if (!flushed && !hasDirtyOnScreenWidgets) {-
1432#ifndef QT_NO_OPENGL-
1433 if (!tlw->d_func()->topData()->widgetTextures.isEmpty()) {-
1434 QPlatformTextureList *tl = widgetTexturesFor(tlw, tlw);-
1435 if (tl) {-
1436 QWidget *target = widget ? widget : tlw;-
1437 qt_flush(target, QRegion(), store, tlw, tlwOffset, tl, this);-
1438 }-
1439 }-
1440#endif-
1441 }-
1442-
1443 if (!hasDirtyOnScreenWidgets)-
1444 return;-
1445-
1446 for (int i = 0; i < dirtyOnScreenWidgets->size(); ++i) {-
1447 QWidget *w = dirtyOnScreenWidgets->at(i);-
1448 QWidgetPrivate *wd = w->d_func();-
1449 Q_ASSERT(wd->needsFlush);-
1450 QPlatformTextureList *widgetTexturesForNative = wd->textureChildSeen ? widgetTexturesFor(tlw, w) : 0;-
1451 qt_flush(w, *wd->needsFlush, store, tlw, tlwOffset, widgetTexturesForNative, this);-
1452 *wd->needsFlush = QRegion();-
1453 }-
1454 dirtyOnScreenWidgets->clear();-
1455}-
1456-
1457static inline bool discardInvalidateBufferRequest(QWidget *widget, QTLWExtra *tlwExtra)-
1458{-
1459 Q_ASSERT(widget);-
1460 if (QApplication::closingDown())-
1461 return true;-
1462-
1463 if (!tlwExtra || tlwExtra->inTopLevelResize || !tlwExtra->backingStore)-
1464 return true;-
1465-
1466 if (!widget->isVisible() || !widget->updatesEnabled())-
1467 return true;-
1468-
1469 return false;-
1470}-
1471-
1472/*!-
1473 Invalidates the buffer when the widget is resized.-
1474 Static areas are never invalidated unless absolutely needed.-
1475*/-
1476void QWidgetPrivate::invalidateBuffer_resizeHelper(const QPoint &oldPos, const QSize &oldSize)-
1477{-
1478 Q_Q(QWidget);-
1479 Q_ASSERT(!q->isWindow());-
1480 Q_ASSERT(q->parentWidget());-
1481-
1482 const bool staticContents = q->testAttribute(Qt::WA_StaticContents);-
1483 const bool sizeDecreased = (data.crect.width() < oldSize.width())-
1484 || (data.crect.height() < oldSize.height());-
1485-
1486 const QPoint offset(data.crect.x() - oldPos.x(), data.crect.y() - oldPos.y());-
1487 const bool parentAreaExposed = !offset.isNull() || sizeDecreased;-
1488 const QRect newWidgetRect(q->rect());-
1489 const QRect oldWidgetRect(0, 0, oldSize.width(), oldSize.height());-
1490-
1491 if (!staticContents || graphicsEffect) {-
1492 QRegion staticChildren;-
1493 QWidgetBackingStore *bs = 0;-
1494 if (offset.isNull() && (bs = maybeBackingStore()))-
1495 staticChildren = bs->staticContents(q, oldWidgetRect);-
1496 const bool hasStaticChildren = !staticChildren.isEmpty();-
1497-
1498 if (hasStaticChildren) {-
1499 QRegion dirty(newWidgetRect);-
1500 dirty -= staticChildren;-
1501 invalidateBuffer(dirty);-
1502 } else {-
1503 // Entire widget needs repaint.-
1504 invalidateBuffer(newWidgetRect);-
1505 }-
1506-
1507 if (!parentAreaExposed)-
1508 return;-
1509-
1510 // Invalidate newly exposed area of the parent.-
1511 if (!graphicsEffect && extra && extra->hasMask) {-
1512 QRegion parentExpose(extra->mask.translated(oldPos));-
1513 parentExpose &= QRect(oldPos, oldSize);-
1514 if (hasStaticChildren)-
1515 parentExpose -= data.crect; // Offset is unchanged, safe to do this.-
1516 q->parentWidget()->d_func()->invalidateBuffer(parentExpose);-
1517 } else {-
1518 if (hasStaticChildren && !graphicsEffect) {-
1519 QRegion parentExpose(QRect(oldPos, oldSize));-
1520 parentExpose -= data.crect; // Offset is unchanged, safe to do this.-
1521 q->parentWidget()->d_func()->invalidateBuffer(parentExpose);-
1522 } else {-
1523 q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(QRect(oldPos, oldSize)));-
1524 }-
1525 }-
1526 return;-
1527 }-
1528-
1529 // Move static content to its new position.-
1530 if (!offset.isNull()) {-
1531 if (sizeDecreased) {-
1532 const QSize minSize(qMin(oldSize.width(), data.crect.width()),-
1533 qMin(oldSize.height(), data.crect.height()));-
1534 moveRect(QRect(oldPos, minSize), offset.x(), offset.y());-
1535 } else {-
1536 moveRect(QRect(oldPos, oldSize), offset.x(), offset.y());-
1537 }-
1538 }-
1539-
1540 // Invalidate newly visible area of the widget.-
1541 if (!sizeDecreased || !oldWidgetRect.contains(newWidgetRect)) {-
1542 QRegion newVisible(newWidgetRect);-
1543 newVisible -= oldWidgetRect;-
1544 invalidateBuffer(newVisible);-
1545 }-
1546-
1547 if (!parentAreaExposed)-
1548 return;-
1549-
1550 // Invalidate newly exposed area of the parent.-
1551 const QRect oldRect(oldPos, oldSize);-
1552 if (extra && extra->hasMask) {-
1553 QRegion parentExpose(oldRect);-
1554 parentExpose &= extra->mask.translated(oldPos);-
1555 parentExpose -= (extra->mask.translated(data.crect.topLeft()) & data.crect);-
1556 q->parentWidget()->d_func()->invalidateBuffer(parentExpose);-
1557 } else {-
1558 QRegion parentExpose(oldRect);-
1559 parentExpose -= data.crect;-
1560 q->parentWidget()->d_func()->invalidateBuffer(parentExpose);-
1561 }-
1562}-
1563-
1564/*!-
1565 Invalidates the \a rgn (in widget's coordinates) of the backing store, i.e.-
1566 all widgets intersecting with the region will be repainted when the backing store-
1567 is synced.-
1568-
1569 ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).-
1570*/-
1571void QWidgetPrivate::invalidateBuffer(const QRegion &rgn)-
1572{-
1573 Q_Q(QWidget);-
1574-
1575 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();-
1576 if (discardInvalidateBufferRequest(q, tlwExtra) || rgn.isEmpty())-
1577 return;-
1578-
1579 QRegion wrgn(rgn);-
1580 wrgn &= clipRect();-
1581 if (!graphicsEffect && extra && extra->hasMask)-
1582 wrgn &= extra->mask;-
1583 if (wrgn.isEmpty())-
1584 return;-
1585-
1586 tlwExtra->backingStoreTracker->markDirty(wrgn, q,-
1587 QWidgetBackingStore::UpdateLater, QWidgetBackingStore::BufferInvalid);-
1588}-
1589-
1590/*!-
1591 This function is equivalent to calling invalidateBuffer(QRegion(rect), ...), but-
1592 is more efficient as it eliminates QRegion operations/allocations and can-
1593 use the rect more precisely for additional cut-offs.-
1594-
1595 ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).-
1596*/-
1597void QWidgetPrivate::invalidateBuffer(const QRect &rect)-
1598{-
1599 Q_Q(QWidget);-
1600-
1601 QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();-
1602 if (discardInvalidateBufferRequest(q, tlwExtra) || rect.isEmpty())-
1603 return;-
1604-
1605 QRect wRect(rect);-
1606 wRect &= clipRect();-
1607 if (wRect.isEmpty())-
1608 return;-
1609-
1610 if (graphicsEffect || !extra || !extra->hasMask) {-
1611 tlwExtra->backingStoreTracker->markDirty(wRect, q,-
1612 QWidgetBackingStore::UpdateLater, QWidgetBackingStore::BufferInvalid);-
1613 return;-
1614 }-
1615-
1616 QRegion wRgn(extra->mask);-
1617 wRgn &= wRect;-
1618 if (wRgn.isEmpty())-
1619 return;-
1620-
1621 tlwExtra->backingStoreTracker->markDirty(wRgn, q,-
1622 QWidgetBackingStore::UpdateLater, QWidgetBackingStore::BufferInvalid);-
1623}-
1624-
1625void QWidgetPrivate::repaint_sys(const QRegion &rgn)-
1626{-
1627 if (data.in_destructor)
data.in_destructorDescription
TRUEnever evaluated
FALSEnever evaluated
0
1628 return;
never executed: return;
0
1629-
1630 Q_Q(QWidget);-
1631 if (discardSyncRequest(q, maybeTopData()))
discardSyncReq...aybeTopData())Description
TRUEnever evaluated
FALSEnever evaluated
0
1632 return;
never executed: return;
0
1633-
1634 if (q->testAttribute(Qt::WA_StaticContents)) {
q->testAttribu...taticContents)Description
TRUEnever evaluated
FALSEnever evaluated
0
1635 if (!extra)
!extraDescription
TRUEnever evaluated
FALSEnever evaluated
0
1636 createExtra();
never executed: createExtra();
0
1637 extra->staticContentsSize = data.crect.size();-
1638 }
never executed: end of block
0
1639-
1640 QPaintEngine *engine = q->paintEngine();-
1641-
1642 // QGLWidget does not support partial updates if:-
1643 // 1) The context is double buffered-
1644 // 2) The context is single buffered and auto-fill background is enabled.-
1645 const bool noPartialUpdateSupport = (engine && (engine->type() == QPaintEngine::OpenGL
engineDescription
TRUEnever evaluated
FALSEnever evaluated
engine->type()...Engine::OpenGLDescription
TRUEnever evaluated
FALSEnever evaluated
0
1646 || engine->type() == QPaintEngine::OpenGL2))
engine->type()...ngine::OpenGL2Description
TRUEnever evaluated
FALSEnever evaluated
0
1647 && (usesDoubleBufferedGLContext || q->autoFillBackground());
usesDoubleBufferedGLContextDescription
TRUEnever evaluated
FALSEnever evaluated
q->autoFillBackground()Description
TRUEnever evaluated
FALSEnever evaluated
0
1648 QRegion toBePainted(noPartialUpdateSupport ? q->rect() : rgn);-
1649-
1650#ifdef Q_DEAD_CODE_FROM_QT4_MAC-
1651 // No difference between update() and repaint() on the Mac.-
1652 update_sys(toBePainted);-
1653 return;-
1654#endif-
1655-
1656 toBePainted &= clipRect();-
1657 clipToEffectiveMask(toBePainted);-
1658 if (toBePainted.isEmpty())
toBePainted.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1659 return; // Nothing to repaint.
never executed: return;
0
1660-
1661#ifndef QT_NO_PAINT_DEBUG-
1662 bool flushed = QWidgetBackingStore::flushPaint(q, toBePainted);-
1663#endif-
1664-
1665 drawWidget(q, toBePainted, QPoint(), QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawPaintOnScreen, 0);-
1666-
1667#ifndef QT_NO_PAINT_DEBUG-
1668 if (flushed)
flushedDescription
TRUEnever evaluated
FALSEnever evaluated
0
1669 QWidgetBackingStore::unflushPaint(q, toBePainted);
never executed: QWidgetBackingStore::unflushPaint(q, toBePainted);
0
1670#endif-
1671-
1672 if (Q_UNLIKELY(q->paintingActive())()))
__builtin_expe...ive()), false)Description
TRUEnever evaluated
FALSEnever evaluated
0
1673 qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
never executed: QMessageLogger(__FILE__, 1673, __PRETTY_FUNCTION__).warning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
0
1674}
never executed: end of block
0
1675-
1676-
1677QT_END_NAMESPACE-
1678-
1679#include "moc_qwidgetbackingstore_p.cpp"-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9