00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <qglobal.h>
00024 #include <qapplication.h>
00025 #ifdef Q_WS_WIN
00026 # include "qt_windows.h"
00027 # include <private/qpaintengine_raster_p.h>
00028 #endif
00029 #include "qbackingstore_p.h"
00030 #include "private/qwidget_p.h"
00031 #include <qdebug.h>
00032 #include <qstack.h>
00033 #include <qevent.h>
00034 #include <qabstractscrollarea.h>
00035 #include "private/qabstractscrollarea_p.h"
00036 #ifdef Q_WS_X11
00037 # include "private/qt_x11_p.h"
00038 #endif
00039
00040 #ifdef Q_WS_QWS
00041 #include <qscreen_qws.h>
00042 #include <qwsdisplay_qws.h>
00043 #include <qapplication.h>
00044 #include <qwsmanager_qws.h>
00045 #include <private/qwsmanager_p.h>
00046 #include <unistd.h>
00047 #endif
00048
00049 #include "qwindowsurface_raster_p.h"
00050 #ifdef Q_WS_X11
00051 #include "qwindowsurface_x11_p.h"
00052 #elif defined(Q_WS_QWS)
00053 #include "qwindowsurface_qws_p.h"
00054 #endif
00055
00056
00057
00058
00059
00060 extern bool qt_sendSpontaneousEvent(QObject*, QEvent*);
00061
00062 #ifndef Q_WS_QWS
00063 static bool qt_enable_backingstore = true;
00064 #endif
00065 #ifdef Q_WS_X11
00066
00067 Q_GUI_EXPORT void qt_x11_set_global_double_buffer(bool enable)
00068 {
00069 qt_enable_backingstore = enable;
00070 }
00071 #endif
00072
00073 bool QWidgetBackingStore::paintOnScreen(QWidget *w)
00074 {
00075 #if defined(Q_WS_QWS) || defined(Q_WS_MAC)
00076 Q_UNUSED(w);
00077 return false;
00078 #elif defined(QT_NO_BACKINGSTORE)
00079 Q_UNUSED(w);
00080 return true;
00081 #else
00082 if (w && (w->testAttribute(Qt::WA_PaintOnScreen) || !w->isWindow() && w->window()->testAttribute(Qt::WA_PaintOnScreen)))
00083 return true;
00084
00085
00086 if (w && w->isWindow() && (w->width() > 4096 || w->height() > 4096))
00087 return true;
00088
00089 static signed char checked_env = -1;
00090 if(checked_env == -1)
00091 checked_env = (qgetenv("QT_ONSCREEN_PAINT") == "1") ? 1 : 0;
00092
00093 return checked_env == 1 || !qt_enable_backingstore;
00094 #endif
00095 }
00096
00097 #ifdef Q_WS_QWS
00098 static void qt_showYellowThing(QWidget *widget, const QRegion &rgn, int msec, bool)
00099 {
00100 Q_UNUSED(widget);
00101
00102 static QWSYellowSurface surface(true);
00103 surface.setDelay(msec);
00104 surface.flush(widget, rgn, QPoint());
00105 }
00106
00107 #else
00108 static void qt_showYellowThing(QWidget *widget, const QRegion &toBePainted, int msec, bool unclipped)
00109 {
00110
00111 bool paintUnclipped = widget->testAttribute(Qt::WA_PaintUnclipped);
00112 if (unclipped && !QWidgetBackingStore::paintOnScreen(widget))
00113 widget->setAttribute(Qt::WA_PaintUnclipped);
00114
00115 bool setFlag = !widget->testAttribute(Qt::WA_WState_InPaintEvent);
00116 if(setFlag)
00117 widget->setAttribute(Qt::WA_WState_InPaintEvent);
00118
00119
00120 static int i = 0;
00121
00122
00123 QPaintEngine *pe = widget->paintEngine();
00124 if (pe) {
00125 pe->setSystemClip(toBePainted);
00126 {
00127 QPainter p(widget);
00128 p.setClipRegion(toBePainted);
00129
00130 switch (i) {
00131 case 0:
00132 p.fillRect(widget->rect(), QColor(255,255,0));
00133 break;
00134 case 1:
00135 p.fillRect(widget->rect(), QColor(255,200,55));
00136 break;
00137 case 2:
00138 p.fillRect(widget->rect(), QColor(200,255,55));
00139 break;
00140 case 3:
00141 p.fillRect(widget->rect(), QColor(200,200,0));
00142 break;
00143 }
00144 i = (i+1) & 3;
00145 p.end();
00146 }
00147 }
00148
00149 if(setFlag)
00150 widget->setAttribute(Qt::WA_WState_InPaintEvent, false);
00151
00152
00153 widget->setAttribute(Qt::WA_PaintUnclipped, paintUnclipped);
00154
00155 if (pe) {
00156 pe->setSystemClip(QRegion());
00157
00158 if (pe->type() == QPaintEngine::Raster) {
00159 QRasterPaintEngine *rpe = static_cast<QRasterPaintEngine *>(pe);
00160 rpe->flush(widget, QPoint());
00161 }
00162 }
00163
00164 QApplication::syncX();
00165
00166 #if defined(Q_OS_UNIX)
00167 ::usleep(1000*msec);
00168 #elif defined(Q_OS_WIN)
00169 ::Sleep(msec);
00170 #endif
00171
00172 }
00173 #endif
00174
00175 static bool qt_flushPaint(QWidget *widget, const QRegion &toBePainted)
00176 {
00177 static int checked_env = -1;
00178 if(checked_env == -1)
00179 checked_env = qgetenv("QT_FLUSH_PAINT").toInt();
00180
00181 if (checked_env == 0)
00182 return false;
00183
00184 qt_showYellowThing(widget, toBePainted, checked_env*10, true);
00185
00186 return true;
00187 }
00188
00189 static void qt_unflushPaint(QWidget *widget, const QRegion &rgn)
00190 {
00191 if (!QWidgetBackingStore::paintOnScreen(widget))
00192 QWidgetBackingStore::copyToScreen(widget, rgn);
00193 }
00194
00195 #if !defined(Q_WS_QWS)
00196 static bool qt_flushUpdate(QWidget *widget, const QRegion &rgn)
00197 {
00198 static int checked_env = -1;
00199 if(checked_env == -1) {
00200 checked_env = qgetenv("QT_FLUSH_UPDATE").toInt();
00201 }
00202
00203 if (checked_env == 0)
00204 return false;
00205
00206 qt_showYellowThing(widget, rgn, checked_env*10, false);
00207
00208 return true;
00209 }
00210 #endif
00211
00212 void qt_syncBackingStore(QRegion rgn, QWidget *widget, bool recursive)
00213 {
00214 if (!QWidgetBackingStore::paintOnScreen(widget)) {
00215 if (QWidgetBackingStore *bs = widget->d_func()->maybeBackingStore())
00216 bs->cleanRegion(rgn, widget, recursive);
00217 } else {
00218 widget->repaint(rgn);
00219 }
00220 }
00221 void qt_syncBackingStore(QRegion rgn, QWidget *widget)
00222 {
00223 qt_syncBackingStore(rgn, widget, false);
00224 }
00225
00226 QWindowSurface *qt_default_window_surface(QWidget *widget)
00227 {
00228 #ifdef Q_WS_WIN
00229 return new QRasterWindowSurface(widget);
00230 #elif defined(Q_WS_X11)
00231 return new QX11WindowSurface(widget);
00232 #elif defined(Q_WS_QWS)
00233 if (widget->windowType() == Qt::Desktop)
00234 return 0;
00235 return qt_screen->createSurface(widget);
00236 #else
00237 Q_UNUSED(widget);
00238 return 0;
00239 #endif
00240 }
00241
00242 #ifdef Q_WS_WIN
00243
00244
00245
00246
00247
00248
00249 void QWidgetBackingStore::blitToScreen(const QRegion &rgn, QWidget *widget)
00250 {
00251 QWidget *tlw = widget->window();
00252 if (!widget->isVisible() || !tlw->testAttribute(Qt::WA_Mapped) || rgn.isEmpty())
00253 return;
00254
00255 if (!QWidgetBackingStore::paintOnScreen(widget)) {
00256 QWidgetBackingStore *bs = tlw->d_func()->topData()->backingStore;
00257
00258 bs->windowSurface->flush(widget, rgn, widget->mapTo(tlw, QPoint(0, 0)));
00259 }
00260 }
00261 #endif
00262
00263 #if defined(Q_WS_X11)
00264 void qt_syncBackingStore(QWidget *widget)
00265 {
00266
00267 widget->d_func()->dirtyOnScreen &= widget->d_func()->clipRect();
00268
00269 const QRegion dirty = widget->d_func()->dirtyOnScreen;
00270 QWidget *tlw = widget->window();
00271 if (!QWidgetBackingStore::paintOnScreen(widget)) {
00272 QWidgetBackingStore *bs = tlw->d_func()->topData()->backingStore;
00273 bs->cleanRegion(dirty, widget);
00274 } else {
00275 widget->repaint(dirty);
00276 }
00277 }
00278 #elif defined(Q_WS_QWS)
00279 void qt_syncBackingStore(QWidget *widget)
00280 {
00281 QWidget *tlw = widget->window();
00282 QTLWExtra *topData = tlw->d_func()->topData();
00283
00284 QWidgetBackingStore *bs = topData->backingStore;
00285 QWSWindowSurface *surface = 0;
00286 if(bs)
00287 surface = static_cast<QWSWindowSurface*>(bs->windowSurface);
00288 else
00289 qWarning("request to sync backing store of widget %p, "
00290 "which does not have its backing store defined yet",
00291 (void*)widget);
00292
00293 QRegion toClean;
00294
00295 if (surface)
00296 toClean = surface->dirtyRegion();
00297 if (!toClean.isEmpty())
00298 topData->backingStore->cleanRegion(toClean, tlw);
00299 }
00300 #endif
00301
00302
00303
00304
00305 static inline bool qRectIntersects(const QRect &r1, const QRect &r2)
00306 {
00307 return (qMax(r1.left(), r2.left()) <= qMin(r1.right(), r2.right()) &&
00308 qMax(r1.top(), r2.top()) <= qMin(r1.bottom(), r2.bottom()));
00309 }
00310
00311 QWidgetBackingStore::QWidgetBackingStore(QWidget *t) : tlw(t)
00312 {
00313 windowSurface = tlw->windowSurface();
00314 if (!windowSurface)
00315 windowSurface = qt_default_window_surface(t);
00316 }
00317
00318 QWidgetBackingStore::~QWidgetBackingStore()
00319 {
00320 if (!tlw->windowSurface())
00321 delete windowSurface;
00322 }
00323
00324
00325
00326
00327
00328
00329
00330 void QWidgetBackingStore::bltRect(const QRect &rect, int dx, int dy, QWidget *widget)
00331 {
00332 QPoint pos(widget->mapTo(tlw, rect.topLeft()));
00333
00334 #ifdef Q_WS_QWS
00335 QWSWindowSurface *surface = static_cast<QWSWindowSurface*>(windowSurface);
00336 if (!surface)
00337 return;
00338
00339
00340 const QRegion clip = surface->clipRegion();
00341 QRegion r = QRect(pos, rect.size());
00342 r = (r & clip).translated(dx, dy) & clip;
00343 r.translate(-dx, -dy);
00344
00345 windowSurface->scroll(r.translated(topLevelOffset()), dx, dy);
00346 #else
00347 windowSurface->scroll(QRect(pos, rect.size()), dx, dy);
00348 #endif
00349 }
00350
00351
00352
00353
00354 void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy)
00355 {
00356 Q_Q(QWidget);
00357 if (!q->isVisible())
00358 return;
00359
00360 QWidget *tlw = q->window();
00361 QTLWExtra* x = tlw->d_func()->topData();
00362
00363
00364 static int accelEnv = -1;
00365 if (accelEnv == -1) {
00366 accelEnv = qgetenv("QT_NO_FAST_MOVE").toInt() == 0;
00367 }
00368
00369 QWidget *pw = q->parentWidget();
00370 QWidgetPrivate *pd = pw->d_func();
00371 QRect clipR = pd->clipRect();
00372 QRect newRect = rect.translated(dx,dy);
00373
00374 QRect destRect = rect.intersected(clipR);
00375 if (destRect.isValid())
00376 destRect = destRect.translated(dx,dy).intersected(clipR);
00377 QRect sourceRect = destRect.translated(-dx, -dy);
00378
00379 bool accelerateMove = accelEnv && isOpaque() && !isOverlapped(sourceRect)
00380 && !isOverlapped(destRect);
00381
00382 if (!accelerateMove) {
00383 QRegion parentR(rect & clipR);
00384 if (q->mask().isEmpty()) {
00385 parentR -= newRect;
00386 } else {
00387
00388 parentR += newRect & clipR;
00389 }
00390 pd->invalidateBuffer(parentR);
00391 invalidateBuffer((newRect & clipR).translated(-data.crect.topLeft()));
00392 } else {
00393 QWidgetBackingStore *wbs = x->backingStore;
00394 if (sourceRect.isValid())
00395 wbs->bltRect(sourceRect, dx, dy, pw);
00396
00397
00398 QRegion childExpose = newRect & clipR;
00399 childExpose -= destRect;
00400
00401 QPoint toplevelOffset = pw->mapTo(tlw, QPoint());
00402 QRect newDirty = (wbs->dirty & sourceRect.translated(toplevelOffset)).boundingRect().translated(QPoint(dx,dy) - toplevelOffset);
00403 childExpose += newDirty;
00404
00405 childExpose.translate(-data.crect.topLeft());
00406 invalidateBuffer(childExpose);
00407
00408 QRegion parentExpose = rect & clipR;
00409 parentExpose -= newRect;
00410 if (!q->mask().isEmpty()) {
00411 parentExpose += QRegion(newRect) - q->mask().translated(data.crect.topLeft());
00412 }
00413 pd->invalidateBuffer(parentExpose);
00414 #ifdef Q_WS_QWS
00415
00416 pd->dirtyWidget_sys(QRegion(sourceRect)+destRect);
00417 #endif
00418 }
00419 }
00420
00421
00422 void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy)
00423 {
00424 Q_Q(QWidget);
00425 QWidget *tlw = q->window();
00426 QTLWExtra* x = tlw->d_func()->topData();
00427 QWidgetBackingStore *wbs = x->backingStore;
00428
00429 static int accelEnv = -1;
00430 if (accelEnv == -1) {
00431 accelEnv = qgetenv("QT_NO_FAST_SCROLL").toInt() == 0;
00432 }
00433
00434 bool accelerateScroll = accelEnv && isOpaque() && !isOverlapped(data.crect);
00435
00436 #if defined(Q_WS_QWS)
00437 QWSWindowSurface *surface;
00438 surface = static_cast<QWSWindowSurface*>(wbs->windowSurface);
00439
00440 if (accelerateScroll && !surface->isBuffered()) {
00441 const QRegion surfaceClip = surface->clipRegion();
00442 const QRegion outsideClip = QRegion(rect) - surfaceClip;
00443 if (!outsideClip.isEmpty()) {
00444 const QVector<QRect> clipped = (surfaceClip & rect).rects();
00445 if (clipped.size() < 8) {
00446 for (int i = 0; i < clipped.size(); ++i)
00447 scrollRect(clipped.at(i), dx, dy);
00448 return;
00449 } else {
00450 accelerateScroll = false;
00451 }
00452 }
00453 }
00454 #endif // Q_WS_QWS
00455
00456 if (!accelerateScroll) {
00457 invalidateBuffer(rect);
00458 } else {
00459 QRect scrollRect = rect & clipRect();
00460
00461 QRect destRect = scrollRect.isValid() ? scrollRect.translated(dx,dy).intersected(scrollRect) : QRect();
00462 QRect sourceRect = destRect.translated(-dx, -dy);
00463
00464 QPoint toplevelOffset = q->mapTo(tlw, QPoint());
00465
00466
00467 if (sourceRect.isValid())
00468 wbs->bltRect(sourceRect, dx, dy, q);
00469
00470 QRegion childExpose = scrollRect;
00471 childExpose -= destRect;
00472
00473 QRect newDirty = (wbs->dirty & sourceRect.translated(toplevelOffset)).boundingRect().translated(QPoint(dx,dy) - toplevelOffset);
00474
00475 childExpose += newDirty;
00476 invalidateBuffer(childExpose);
00477
00478
00479
00480
00481 dirtyWidget_sys(rect);
00482 }
00483 }
00484
00485 void QWidgetBackingStore::dirtyRegion(const QRegion &rgn, QWidget *widget)
00486 {
00487 QRegion wrgn(rgn);
00488 Q_ASSERT(widget->window() == tlw);
00489 if(!widget->isVisible() || !widget->updatesEnabled())
00490 return;
00491 wrgn &= widget->d_func()->clipRect();
00492 if (!widget->mask().isEmpty())
00493 wrgn &= widget->mask();
00494 #ifndef Q_WS_QWS
00495 widget->d_func()->dirtyWidget_sys(wrgn);
00496 #endif
00497 wrgn.translate(widget->mapTo(tlw, QPoint(0, 0)));
00498 dirty += wrgn;
00499 #ifdef Q_WS_QWS
00500 tlw->d_func()->dirtyWidget_sys(wrgn);
00501 #endif
00502 }
00503
00504
00505 void QWidgetBackingStore::copyToScreen(QWidget *widget, const QRegion &rgn)
00506 {
00507 QWidget *tlw = widget->window();
00508 QTLWExtra *topextra = tlw->d_func()->extra->topextra;
00509 QPoint offset = widget->mapTo(tlw, QPoint());
00510 topextra->backingStore->copyToScreen(rgn, widget, offset, false);
00511 }
00512
00520 void QWidgetBackingStore::copyToScreen(const QRegion &rgn, QWidget *widget, const QPoint &offset, bool recursive)
00521 {
00522 if (rgn.isEmpty())
00523 return;
00524 Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
00525 #ifdef Q_WS_QWS
00526 Q_UNUSED(recursive);
00527 windowSurface->flush(widget, rgn, offset);
00528 #else
00529 if (!QWidgetBackingStore::paintOnScreen(widget)) {
00530 widget->d_func()->cleanWidget_sys(rgn);
00531
00532 qt_flushUpdate(widget, rgn);
00533
00534 QPoint wOffset = widget->data->wrect.topLeft();
00535 windowSurface->flush(widget, rgn, offset);
00536 }
00537
00538 if(recursive) {
00539 const QObjectList children = widget->children();
00540 for(int i = 0; i < children.size(); ++i) {
00541 if(QWidget *child = qobject_cast<QWidget*>(children.at(i))) {
00542 if(!child->isWindow() && child->isVisible()) {
00543 if (qRectIntersects(rgn.boundingRect().translated(-child->pos()), child->rect())) {
00544 QRegion childRegion(rgn);
00545 childRegion.translate(-child->pos());
00546 childRegion &= child->d_func()->clipRect();
00547 if(!childRegion.isEmpty())
00548 copyToScreen(childRegion, child, offset+child->pos(), recursive);
00549 }
00550 }
00551 }
00552 }
00553 }
00554 #endif
00555 }
00556
00557 void QWidgetBackingStore::cleanRegion(const QRegion &rgn, QWidget *widget, bool recursiveCopyToScreen)
00558 {
00559 if (!widget->isVisible() || !widget->updatesEnabled() || !tlw->testAttribute(Qt::WA_Mapped) || rgn.isEmpty())
00560 return;
00561
00562 if(!QWidgetBackingStore::paintOnScreen(widget)) {
00563 QRegion toClean;
00564 #if defined(Q_WS_QWS)
00565 QRect tlwRect = tlw->frameGeometry();
00566 #else
00567 QRect tlwRect = tlw->geometry();
00568 #endif
00569
00570 #ifdef Q_WS_QWS
00571 if (!static_cast<QWSWindowSurface*>(windowSurface)->isValidFor(tlw)) {
00572 delete windowSurface;
00573 windowSurface = qt_default_window_surface(tlw);
00574 }
00575 #endif
00576 if (windowSurface->geometry() != tlwRect) {
00577 windowSurface->setGeometry(tlwRect);
00578 toClean = QRect(QPoint(0, 0), tlwRect.size());
00579 recursiveCopyToScreen = true;
00580 } else {
00581 toClean = dirty;
00582 }
00583 #ifdef Q_WS_QWS
00584 tlwOffset = static_cast<QWSWindowSurface*>(windowSurface)->painterOffset();
00585 #endif
00586
00587
00588 #if defined(Q_WS_QWS)
00589 const QRegion clip = static_cast<QWSWindowSurface*>(windowSurface)->clipRegion();
00590 if (!clip.isEmpty())
00591 toClean &= clip;
00592 #endif
00593
00594 if(!toClean.isEmpty()) {
00595 dirty -= toClean;
00596 if (tlw->updatesEnabled()) {
00597
00598 windowSurface->paintDevice()->paintEngine()->setSystemClip(toClean);
00599 windowSurface->beginPaint(toClean);
00600 windowSurface->paintDevice()->paintEngine()->setSystemClip(QRegion());
00601
00602 tlw->d_func()->drawWidget(windowSurface->paintDevice(), toClean, tlwOffset);
00603
00604
00605 windowSurface->paintDevice()->paintEngine()->setSystemClip(toClean);
00606 windowSurface->endPaint(toClean);
00607 windowSurface->paintDevice()->paintEngine()->setSystemClip(QRegion());
00608 }
00609 }
00610
00611 QRegion toFlush = rgn;
00612 if (recursiveCopyToScreen) {
00613 toFlush.translate(widget->mapTo(tlw, QPoint()));
00614 copyToScreen(toFlush, tlw, tlwOffset, recursiveCopyToScreen);
00615 } else {
00616 #ifdef Q_WS_X11
00617 toFlush += widget->d_func()->dirtyOnScreen;
00618 #endif
00619 copyToScreen(toFlush, widget, widget->mapTo(tlw, QPoint()), false);
00620 }
00621 }
00622 }
00623
00624 #ifdef Q_WS_QWS
00625 void QWidgetBackingStore::releaseBuffer()
00626 {
00627 if (windowSurface)
00628 windowSurface->release();
00629 }
00630 #elif defined(Q_WS_WIN)
00631 void QWidgetBackingStore::releaseBuffer()
00632 {
00633 windowSurface->release();
00634 }
00635 #endif
00636
00637 bool QWidgetBackingStore::isOpaque(const QWidget *widget)
00638 {
00639 return widget->d_func()->isOpaque();
00640 }
00641
00642
00643 void QWidgetBackingStore::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& siblings, int index, const QRegion &rgn,
00644 const QPoint &offset, int flags)
00645 {
00646 QWidget *w = 0;
00647
00648 do {
00649 QWidget *x = qobject_cast<QWidget*>(siblings.at(index));
00650 if (x && !x->isWindow() && !x->isHidden() && qRectIntersects(rgn.boundingRect(), x->geometry())) {
00651 w = x;
00652 break;
00653 }
00654 --index;
00655 } while (index >= 0);
00656
00657
00658 if (!w)
00659 return;
00660
00661 QWExtra *extra = w->d_func()->extraData();
00662
00663 if (index > 0) {
00664 QRegion wr = rgn;
00665 if (isOpaque(w)) {
00666 if(!extra || extra->mask.isEmpty()) {
00667 wr -= w->geometry();
00668 } else {
00669 wr -= extra->mask.translated(w->pos());
00670 }
00671 }
00672 paintSiblingsRecursive(pdev, siblings, index - 1, wr, offset, flags);
00673 }
00674 if(w->updatesEnabled()) {
00675 QRegion wRegion(rgn & w->geometry());
00676 wRegion.translate(-w->pos());
00677
00678 if(extra && !extra->mask.isEmpty())
00679 wRegion &= extra->mask;
00680 if(!wRegion.isEmpty())
00681 w->d_func()->drawWidget(pdev, wRegion, offset+w->pos(), flags);
00682 }
00683 }
00684
00685 void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, int flags)
00686 {
00687 Q_Q(QWidget);
00688 if (rgn.isEmpty())
00689 return;
00690
00691 const bool asRoot = flags & DrawAsRoot;
00692 const bool alsoOnScreen = flags & DrawPaintOnScreen;
00693 const bool recursive = flags & DrawRecursive;
00694 const bool alsoInvisible = flags & DrawInvisible;
00695
00696 QRegion toBePainted = rgn;
00697 if (asRoot && !alsoInvisible)
00698 toBePainted &= clipRect();
00699 subtractOpaqueChildren(toBePainted, q->rect(), QPoint());
00700
00701 if (!toBePainted.isEmpty()) {
00702 bool onScreen = QWidgetBackingStore::paintOnScreen(q);
00703 if (!onScreen || alsoOnScreen) {
00704
00705 if (q->testAttribute(Qt::WA_WState_InPaintEvent))
00706 qWarning("QWidget::repaint: Recursive repaint detected");
00707 q->setAttribute(Qt::WA_WState_InPaintEvent);
00708
00709
00710 bool flushed = qt_flushPaint(q, toBePainted);
00711
00712 QPaintEngine *paintEngine = pdev->paintEngine();
00713 if (paintEngine) {
00714 QPainter::setRedirected(q, pdev, -offset);
00715
00716 QRegion wrgn = toBePainted;
00717 wrgn.translate(offset);
00718 paintEngine->setSystemRect(q->data->crect);
00719 paintEngine->setSystemClip(wrgn);
00720
00721
00722 if ((asRoot || q->autoFillBackground() || onScreen)
00723 && !q->testAttribute(Qt::WA_OpaquePaintEvent)
00724 && !q->testAttribute(Qt::WA_NoSystemBackground)) {
00725
00726 QPainter p(q);
00727 QRect backgroundRect = toBePainted.boundingRect();
00728
00729 #ifndef QT_NO_SCROLLAREA
00730 if (QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(q->parent())) {
00731 if (scrollArea->viewport() == q) {
00732 QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(static_cast<QWidget *>(scrollArea)->d_ptr);
00733 const QPoint offset = priv->contentsOffset();
00734 p.translate(-offset);
00735 backgroundRect.translate(offset);
00736 }
00737 }
00738 #endif // QT_NO_SCROLLAREA
00739 paintBackground(&p, backgroundRect, asRoot || onScreen);
00740 }
00741 if (q->testAttribute(Qt::WA_TintedBackground)
00742 && !onScreen && !asRoot && !isOpaque() ) {
00743 QPainter p(q);
00744 QColor tint = q->palette().window().color();
00745 tint.setAlphaF(.6);
00746 p.fillRect(toBePainted.boundingRect(), tint);
00747 }
00748 }
00749
00750 #if 0
00751 qDebug() << "painting" << q << "opaque ==" << isOpaque();
00752 qDebug() << "clipping to" << toBePainted << "location == " << offset
00753 << "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size());
00754 #endif
00755
00756
00757 QPaintEvent e(toBePainted);
00758 qt_sendSpontaneousEvent(q, &e);
00759
00760
00761 if (paintEngine) {
00762 paintEngine->setSystemRect(QRect());
00763 pdev->paintEngine()->setSystemClip(QRegion());
00764 QPainter::restoreRedirected(q);
00765 }
00766 q->setAttribute(Qt::WA_WState_InPaintEvent, false);
00767 if(!q->testAttribute(Qt::WA_PaintOutsidePaintEvent) && q->paintingActive())
00768 qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
00769
00770 if (flushed)
00771 qt_unflushPaint(q, toBePainted);
00772 } else if(q->isWindow()) {
00773 if (pdev->paintEngine()) {
00774 QPainter p(pdev);
00775 p.setClipRegion(toBePainted);
00776 const QBrush bg = q->palette().brush(QPalette::Window);
00777 if (bg.style() == Qt::TexturePattern)
00778 p.drawTiledPixmap(q->rect(), bg.texture());
00779 else
00780 p.fillRect(q->rect(), bg);
00781 }
00782 }
00783 }
00784
00785 if (recursive) {
00786 const QObjectList children = q->children();
00787 if (!children.isEmpty())
00788 QWidgetBackingStore::paintSiblingsRecursive(pdev, children, children.size()-1, rgn, offset, flags & ~DrawAsRoot);
00789 }
00790 }
00791
00792
00793
00794 void QWidgetPrivate::invalidateBuffer(const QRegion &rgn)
00795 {
00796 if(qApp && qApp->closingDown())
00797 return;
00798 Q_Q(QWidget);
00799 if (QWidgetBackingStore *bs = maybeBackingStore())
00800 bs->dirtyRegion(rgn, q);
00801 }
00802
00803 void QWidget::repaint(const QRegion& rgn)
00804 {
00805 if (testAttribute(Qt::WA_WState_ConfigPending)) {
00806 update(rgn);
00807 return;
00808 }
00809
00810 if (!isVisible() || !updatesEnabled() || rgn.isEmpty())
00811 return;
00812 Q_D(QWidget);
00813 Q_ASSERT(testAttribute(Qt::WA_WState_Created));
00814
00815 if (!QWidgetBackingStore::paintOnScreen(this)) {
00816 if (QWidgetBackingStore *bs = d->maybeBackingStore()) {
00817 QRegion wrgn(rgn);
00818 d->subtractOpaqueSiblings(wrgn, QPoint());
00819 d->subtractOpaqueChildren(wrgn, rect(), QPoint());
00820 bs->dirtyRegion(wrgn, this);
00821 bs->cleanRegion(wrgn, this);
00822 }
00823 }
00824 #ifndef Q_WS_QWS
00825
00826 else {
00827 d->cleanWidget_sys(rgn);
00828
00829 qt_flushPaint(this, rgn);
00830
00831 QPaintEngine *engine = paintEngine();
00832
00833 QRegion systemClipRgn(rgn);
00834
00835 if (engine) {
00836 if (!data->wrect.topLeft().isNull()) {
00837 QPainter::setRedirected(this, this, data->wrect.topLeft());
00838 systemClipRgn.translate(-data->wrect.topLeft());
00839 }
00840 engine->setSystemClip(systemClipRgn);
00841 engine->setSystemRect(data->crect);
00842 }
00843
00844 d->drawWidget(this, rgn, QPoint(), QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawPaintOnScreen);
00845
00846 #ifdef Q_WS_WIN
00847 if (engine && engine->type() == QPaintEngine::Raster) {
00848 bool tmp_dc = !d->hd;
00849 if (tmp_dc)
00850 d->hd = GetDC(winId());
00851 static_cast<QRasterPaintEngine *>(engine)->flush(this, QPoint(0, 0));
00852 if (tmp_dc) {
00853 ReleaseDC(winId(), (HDC)d->hd);
00854 d->hd = 0;
00855 }
00856 }
00857 #endif
00858 if (engine) {
00859 if (!data->wrect.topLeft().isNull())
00860 QPainter::restoreRedirected(this);
00861 engine->setSystemClip(QRegion());
00862 engine->setSystemRect(QRect());
00863 }
00864
00865 if(!testAttribute(Qt::WA_PaintOutsidePaintEvent) && paintingActive())
00866 qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");
00867 }
00868 #endif //Q_WS_QWS
00869 }
00870
00871 void QWidget::update()
00872 {
00873 update(rect());
00874 }
00875
00876 void QWidget::update(const QRect &r)
00877 {
00878 update(QRegion(r));
00879 }
00880
00881 void QWidget::update(const QRegion& rgn)
00882 {
00883 if(!isVisible() || !updatesEnabled() || rgn.isEmpty())
00884 return;
00885
00886 Q_D(QWidget);
00887 if (testAttribute(Qt::WA_WState_InPaintEvent)) {
00888 QApplication::postEvent(this, new QUpdateLaterEvent(rgn));
00889 } else {
00890 if (QWidgetBackingStore *bs = d->maybeBackingStore()) {
00891 QRegion wrgn(rgn);
00892 d->subtractOpaqueSiblings(wrgn, QPoint());
00893 d->subtractOpaqueChildren(wrgn, rect(), QPoint());
00894 bs->dirtyRegion(wrgn, this);
00895 }
00896 }
00897 }
00898