📄 qbackingstore.cpp
字号:
QRect tlwRect = tlw->geometry();#endif#ifdef Q_WS_QWS if (!static_cast<QWSWindowSurface*>(windowSurface)->isValid()) { // this looks strange but it really just releases the surface windowSurface->setGeometry(QRect()); // the old window surface is deleted in setWindowSurface, which is // called from QWindowSurface constructor windowSurface = qt_default_window_surface(tlw); } toClean = static_cast<QWSWindowSurface*>(windowSurface)->dirtyRegion();#else toClean = dirty;#endif if (windowSurface->geometry() != tlwRect) { if (windowSurface->geometry().size() != tlwRect.size()) { toClean = QRect(QPoint(0, 0), tlwRect.size()); recursiveCopyToScreen = true;#ifdef Q_WIDGET_USE_DIRTYLIST for (int i = 0; i < dirtyWidgets.size(); ++i) dirtyWidgets.at(i)->d_func()->dirty = QRegion(); dirtyWidgets.clear();#endif } windowSurface->setGeometry(tlwRect); }#ifdef Q_WS_QWS tlwOffset = static_cast<QWSWindowSurface*>(windowSurface)->painterOffset();#endif // ### move into prerender step QRegion toFlush = rgn;#ifdef Q_WIDGET_USE_DIRTYLIST if (!toClean.isEmpty() || !dirtyWidgets.isEmpty()) {#else if (!toClean.isEmpty()) {#endif#ifndef Q_WS_QWS dirty -= toClean;#endif if (tlw->updatesEnabled()) { // hw: XXX the toClean region is not correct if !dirtyWidgets.isEmpty() // Pre render config windowSurface->paintDevice()->paintEngine()->setSystemClip(toClean);// Avoid deadlock with QT_FLUSH_PAINT: the server will wait for// the BackingStore lock, so if we hold that, the server will// never release the Communication lock that we are waiting for in// sendSynchronousCommand#ifndef QT_NO_PAINT_DEBUG const bool flushing = (test_qt_flushPaint() > 0);#else const bool flushing = false;#endif if (!flushing) windowSurface->beginPaint(toClean); windowSurface->paintDevice()->paintEngine()->setSystemClip(QRegion());#ifdef Q_WIDGET_USE_DIRTYLIST#ifdef Q_WS_QWS const QPoint poffset = static_cast<QWSWindowSurface*>(windowSurface)->painterOffset();#else const QPoint poffset(0,0);#endif for (int i = 0; i < dirtyWidgets.size(); ++i) { QWidget *w = dirtyWidgets.at(i); const QPoint offset = w->mapTo(tlw, QPoint()); const QRegion dirty = w->d_func()->dirty; w->d_func()->drawWidget(windowSurface->paintDevice(), dirty, poffset + offset, 0); toFlush += dirty.translated(offset); w->d_func()->dirty = QRegion(); } dirtyWidgets.clear();#endif // Q_WIDGET_USE_DIRTYLIST if (!toClean.isEmpty()) tlw->d_func()->drawWidget(windowSurface->paintDevice(), toClean, tlwOffset); // Drawing the overlay... windowSurface->paintDevice()->paintEngine()->setSystemClip(toClean); if (!flushing) windowSurface->endPaint(toClean); windowSurface->paintDevice()->paintEngine()->setSystemClip(QRegion()); } }#ifdef Q_FLATTEN_EXPOSE // Q_ASSERT(widget->isWindow()); recursiveCopyToScreen = false;#endif if (recursiveCopyToScreen) { toFlush.translate(widget->mapTo(tlw, QPoint())); copyToScreen(toFlush, tlw, tlwOffset, recursiveCopyToScreen); } else {#if defined(Q_WS_X11) || (defined(Q_WS_WIN) && defined(Q_WIN_USE_QT_UPDATE_EVENT)) toFlush += widget->d_func()->dirtyOnScreen;#endif copyToScreen(toFlush, widget, widget->mapTo(tlw, QPoint()), false); }}#endif // Q_BACKINGSTORE_SUBSURFACES#ifdef Q_WS_QWSvoid QWidgetBackingStore::releaseBuffer(){ if (windowSurface) windowSurface->setGeometry(QRect());#ifdef Q_BACKINGSTORE_SUBSURFACES for (int i = 0; i < subSurfaces.size(); ++i) subSurfaces.at(i)->setGeometry(QRect());#endif}#elif defined(Q_WS_WIN)void QWidgetBackingStore::releaseBuffer(){ windowSurface->setGeometry(QRect());}#endifbool QWidgetBackingStore::isOpaque(const QWidget *widget){ return widget->d_func()->isOpaque();}void QWidgetBackingStore::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& siblings, int index, const QRegion &rgn, const QPoint &offset, int flags#ifdef Q_BACKINGSTORE_SUBSURFACES , const QWindowSurface *currentSurface#endif ){ QWidget *w = 0; do { QWidget *x = qobject_cast<QWidget*>(siblings.at(index)); if (x && !x->isWindow() && !x->isHidden() && qRectIntersects(rgn.boundingRect(), x->geometry())) {#ifdef Q_BACKINGSTORE_SUBSURFACES if (x->windowSurface() == currentSurface)#endif { w = x; break; } } --index; } while (index >= 0); if (!w) return; QWExtra *extra = w->d_func()->extraData(); if (index > 0) { QRegion wr = rgn; if (isOpaque(w)) { if(!extra || extra->mask.isEmpty()) { wr -= w->geometry(); } else { wr -= extra->mask.translated(w->pos()); } } paintSiblingsRecursive(pdev, siblings, index - 1, wr, offset, flags#ifdef Q_BACKINGSTORE_SUBSURFACES , currentSurface#endif ); } if(w->updatesEnabled()) { QRegion wRegion(rgn & w->geometry()); wRegion.translate(-w->pos()); if(extra && !extra->mask.isEmpty()) wRegion &= extra->mask; if(!wRegion.isEmpty()) w->d_func()->drawWidget(pdev, wRegion, offset+w->pos(), flags); }}#ifdef Q_WIDGET_USE_DIRTYLISTvoid QWidgetBackingStore::removeDirtyWidget(QWidget *w){ if (!w->d_func()->dirty.isEmpty()) { dirtyWidgets.removeAll(w); w->d_func()->dirty = QRegion(); } const int n = w->children().count(); for (int i = 0; i < n; ++i) { if (QWidget *child = qobject_cast<QWidget*>(w->children().at(i))) removeDirtyWidget(child); }}#endif // Q_WIDGET_USE_DIRTYLISTvoid QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, int flags){ Q_Q(QWidget); if (rgn.isEmpty()) return; const bool asRoot = flags & DrawAsRoot; const bool alsoOnScreen = flags & DrawPaintOnScreen; const bool recursive = flags & DrawRecursive; const bool alsoInvisible = flags & DrawInvisible; QRegion toBePainted = rgn; if (asRoot && !alsoInvisible) toBePainted &= clipRect(); //(rgn & visibleRegion());#ifndef Q_FLATTEN_EXPOSE if (!(flags & DontSubtractOpaqueChildren)) subtractOpaqueChildren(toBePainted, q->rect(), QPoint());#endif if (!toBePainted.isEmpty()) { bool onScreen = QWidgetBackingStore::paintOnScreen(q); if (!onScreen || alsoOnScreen) { //update the "in paint event" flag if (q->testAttribute(Qt::WA_WState_InPaintEvent)) qWarning("QWidget::repaint: Recursive repaint detected"); q->setAttribute(Qt::WA_WState_InPaintEvent); //clip away the new area#ifndef QT_NO_PAINT_DEBUG bool flushed = qt_flushPaint(q, toBePainted);#endif QPaintEngine *paintEngine = pdev->paintEngine(); if (paintEngine) { QPainter::setRedirected(q, pdev, -offset); QRegion wrgn = toBePainted; wrgn.translate(offset); paintEngine->setSystemRect(q->data->crect); paintEngine->setSystemClip(wrgn); //paint the background if ((asRoot || q->autoFillBackground() || onScreen || q->testAttribute(Qt::WA_StyledBackground)) && !q->testAttribute(Qt::WA_OpaquePaintEvent) && !q->testAttribute(Qt::WA_NoSystemBackground)) { QPainter p(q); QRect backgroundRect = toBePainted.boundingRect();#ifndef QT_NO_SCROLLAREA if (QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(q->parent())) { if (scrollArea->viewport() == q) { QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(static_cast<QWidget *>(scrollArea)->d_ptr); const QPoint offset = priv->contentsOffset(); p.translate(-offset); backgroundRect.translate(offset); } }#endif // QT_NO_SCROLLAREA paintBackground(&p, backgroundRect, asRoot || onScreen); } if (q->testAttribute(Qt::WA_TintedBackground) && !onScreen && !asRoot && !isOpaque() ) { QPainter p(q); QColor tint = q->palette().window().color(); tint.setAlphaF(.6); p.fillRect(toBePainted.boundingRect(), tint); } }#if 0 qDebug() << "painting" << q << "opaque ==" << isOpaque(); qDebug() << "clipping to" << toBePainted << "location == " << offset << "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size());#endif //actually send the paint event QPaintEvent e(toBePainted); qt_sendSpontaneousEvent(q, &e); //restore if (paintEngine) { paintEngine->setSystemRect(QRect()); pdev->paintEngine()->setSystemClip(QRegion()); QPainter::restoreRedirected(q); } q->setAttribute(Qt::WA_WState_InPaintEvent, false); if(!q->testAttribute(Qt::WA_PaintOutsidePaintEvent) && q->paintingActive()) qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent");#ifndef QT_NO_PAINT_DEBUG if (flushed) qt_unflushPaint(q, toBePainted);#endif } else if(q->isWindow()) { if (pdev->paintEngine()) { QPainter p(pdev); p.setClipRegion(toBePainted); const QBrush bg = q->palette().brush(QPalette::Window); if (bg.style() == Qt::TexturePattern) p.drawTiledPixmap(q->rect(), bg.texture()); else p.fillRect(q->rect(), bg); } } } if (recursive) { const QObjectList children = q->children(); if (!children.isEmpty()) { QWidgetBackingStore::paintSiblingsRecursive(pdev, children, children.size()-1, rgn, offset, flags & ~DrawAsRoot#ifdef Q_BACKINGSTORE_SUBSURFACES , q->windowSurface()#endif ); } }}/* cross-platform QWidget code */void QWidgetPrivate::invalidateBuffer(const QRegion &rgn){ if(qApp && qApp->closingDown()) return; Q_Q(QWidget); if (QWidgetBackingStore *bs = maybeBackingStore()) bs->dirtyRegion(rgn, q);}void QWidget::repaint(const QRegion& rgn){ if (testAttribute(Qt::WA_WState_ConfigPending)) { update(rgn); return; } if (!isVisible() || !updatesEnabled() || rgn.isEmpty()) return; Q_D(QWidget); Q_ASSERT(testAttribute(Qt::WA_WState_Created));// qDebug() << "repaint" << this << rgn; if (!QWidgetBackingStore::paintOnScreen(this)) { if (QWidgetBackingStore *bs = d->maybeBackingStore()) { QRegion wrgn(rgn); d->subtractOpaqueSiblings(wrgn, QPoint()); d->subtractOpaqueChildren(wrgn, rect(), QPoint()); bs->dirtyRegion(wrgn, this); bs->cleanRegion(wrgn, this); } }#ifndef Q_WS_QWS// QWS does paint-on-screen in qscreen_qws.cpp else { d->cleanWidget_sys(rgn); // qDebug() << "QWidget::repaint paintOnScreen" << this << "region" << rgn;#ifndef QT_NO_PAINT_DEBUG qt_flushPaint(this, rgn);#endif QPaintEngine *engine = paintEngine(); QRegion systemClipRgn(rgn); if (engine) { if (!data->wrect.topLeft().isNull()) { QPainter::setRedirected(this, this, data->wrect.topLeft()); systemClipRgn.translate(-data->wrect.topLeft()); } engine->setSystemClip(systemClipRgn); engine->setSystemRect(data->crect); } d->drawWidget(this, rgn, QPoint(), QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawPaintOnScreen);#ifdef Q_WS_WIN if (engine && engine->type() == QPaintEngine::Raster) { bool tmp_dc = !d->hd; if (tmp_dc) d->hd = GetDC(winId()); static_cast<QRasterPaintEngine *>(engine)->flush(this, QPoint(0, 0)); if (tmp_dc) { ReleaseDC(winId(), (HDC)d->hd); d->hd = 0; } }#endif if (engine) { if (!data->wrect.topLeft().isNull()) QPainter::restoreRedirected(this); engine->setSystemClip(QRegion()); engine->setSystemRect(QRect()); } if(!testAttribute(Qt::WA_PaintOutsidePaintEvent) && paintingActive()) qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent"); }#endif //Q_WS_QWS}void QWidget::update(){ if(!isVisible() || !updatesEnabled()) return; QWidgetBackingStore::updateWidget(this, rect());}void QWidget::update(const QRect &r){ if(!isVisible() || !updatesEnabled() || r.isEmpty()) return; QWidgetBackingStore::updateWidget(this, r);}void QWidget::update(const QRegion& rgn){ if(!isVisible() || !updatesEnabled() || rgn.isEmpty()) return; QWidgetBackingStore::updateWidget(this, rgn);}void QWidgetBackingStore::updateWidget(QWidget *that, const QRegion &rgn){ QWidgetPrivate * const d = that->d_func(); if (that->testAttribute(Qt::WA_WState_InPaintEvent)) { QApplication::postEvent(that, new QUpdateLaterEvent(rgn)); return; } QWidgetBackingStore *bs = d->maybeBackingStore(); if (!bs) return; QRegion wrgn = rgn & d->clipRect();#ifndef Q_FLATTEN_EXPOSE d->subtractOpaqueSiblings(wrgn, QPoint()); d->subtractOpaqueChildren(wrgn, that->rect(), QPoint());#endif if (wrgn.isEmpty()) return;#ifdef Q_WIDGET_USE_DIRTYLIST if (qt_region_strictContains(d->dirty, wrgn.boundingRect())) return; // already dirty if (d->isOpaque()) { // TODO: overlapping non-opaque siblings if (bs->dirtyWidgets.isEmpty()) QApplication::postEvent(that->window(), new QEvent(QEvent::UpdateRequest), Qt::LowEventPriority); if (d->dirty.isEmpty()) bs->dirtyWidgets.append(that); d->dirty += wrgn; return; }#endif bs->dirtyRegion(wrgn, that);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -