📄 qbackingstore.cpp
字号:
#endif QRect newRect = rect.translated(dx,dy); QRect destRect = rect.intersected(clipR); if (destRect.isValid()) destRect = destRect.translated(dx,dy).intersected(clipR); QRect sourceRect = destRect.translated(-dx, -dy); bool accelerateMove = accelEnv && isOpaque() && !isOverlapped(sourceRect) && !isOverlapped(destRect); if (!accelerateMove) { QRegion parentR(rect & clipR); if (q->mask().isEmpty()) { parentR -= newRect; } else { // invalidateBuffer() excludes anything outside the mask parentR += newRect & clipR; } pd->invalidateBuffer(parentR); invalidateBuffer((newRect & clipR).translated(-data.crect.topLeft())); } else { QRegion childExpose = newRect & clipR; QWidgetBackingStore *wbs = x->backingStore; if (sourceRect.isValid()) { if (wbs->bltRect(sourceRect, dx, dy, pw)) childExpose -= destRect; }#ifdef Q_WS_QWS QRegion dirty = sourceRect.translated(toplevelOffset); if (surface) dirty &= surface->dirtyRegion(); const QRect newDirty = dirty.boundingRect().translated(QPoint(dx,dy) - toplevelOffset);#else QRect newDirty = (wbs->dirty & sourceRect.translated(toplevelOffset)).boundingRect().translated(QPoint(dx,dy) - toplevelOffset);#endif childExpose += newDirty; childExpose.translate(-data.crect.topLeft()); invalidateBuffer(childExpose); QRegion parentExpose = rect & clipR; parentExpose -= newRect; if (!q->mask().isEmpty()) { parentExpose += QRegion(newRect) - q->mask().translated(data.crect.topLeft()); } pd->invalidateBuffer(parentExpose);#ifdef Q_WS_QWS //QWS does not have native child widgets: copy everything to screen, just like scrollRect()// pd->dirtyWidget_sys(QRegion(sourceRect)+destRect); wbs->dirtyOnScreen += sourceRect.translated(toplevelOffset); wbs->dirtyOnScreen += destRect.translated(toplevelOffset);#endif }}//widget's coordinates; scroll within rect; only update widgetvoid QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy){ Q_Q(QWidget); QWidget *tlw = q->window(); QTLWExtra* x = tlw->d_func()->topData(); QWidgetBackingStore *wbs = x->backingStore; static int accelEnv = -1; if (accelEnv == -1) { accelEnv = qgetenv("QT_NO_FAST_SCROLL").toInt() == 0; } bool accelerateScroll = accelEnv && isOpaque() && !isOverlapped(data.crect);#if defined(Q_WS_QWS) QWSWindowSurface *surface; surface = static_cast<QWSWindowSurface*>(wbs->windowSurface); if (accelerateScroll && !surface->isBuffered()) { const QRegion surfaceClip = surface->clipRegion(); const QRegion outsideClip = QRegion(rect) - surfaceClip; if (!outsideClip.isEmpty()) { const QVector<QRect> clipped = (surfaceClip & rect).rects(); if (clipped.size() < 8) { for (int i = 0; i < clipped.size(); ++i) scrollRect(clipped.at(i), dx, dy); return; } else { accelerateScroll = false; } } }#endif // Q_WS_QWS if (!accelerateScroll) { invalidateBuffer(rect); } else { const QPoint toplevelOffset = q->mapTo(tlw, QPoint());#ifdef Q_WS_QWS QWSWindowSurface *surface = static_cast<QWSWindowSurface*>(wbs->windowSurface); const QRegion clip = surface->clipRegion().translated(-toplevelOffset) & clipRect(); const QRect scrollRect = rect & clip.boundingRect(); const QRect destRect = scrollRect.translated(dx, dy) & scrollRect & clip.boundingRect();#else QRect scrollRect = rect & clipRect(); QRect destRect = scrollRect.isValid() ? scrollRect.translated(dx,dy).intersected(scrollRect) : QRect();#endif QRect sourceRect = destRect.translated(-dx, -dy); QRegion childExpose = scrollRect; if (sourceRect.isValid()) { if (wbs->bltRect(sourceRect, dx, dy, q)) childExpose -= destRect; }// childExpose += (wbs->dirty & sourceRect.translated(toplevelOffset)).boundingRect().translated(QPoint(dx,dy) - toplevelOffset);#ifdef Q_WS_QWS QRegion dirty = sourceRect.translated(toplevelOffset); if (surface) dirty &= surface->dirtyRegion(); const QRect newDirty = dirty.boundingRect().translated(QPoint(dx,dy) - toplevelOffset);#else QRect newDirty = (wbs->dirty & sourceRect.translated(toplevelOffset)).boundingRect().translated(QPoint(dx,dy) - toplevelOffset);#endif// qDebug() << "scrollRect" << q << rect << dx << dy << "dirty" << wbs->dirty << "newDirty" << newDirty; childExpose += newDirty; invalidateBuffer(childExpose); // Instead of using native scroll-on-screen, we copy from // backingstore, giving only one screen update for each // scroll, and a solid appearance#ifdef Q_WS_QWS wbs->dirtyOnScreen += destRect.translated(toplevelOffset);#else dirtyWidget_sys(rect);#endif }}void QWidgetBackingStore::dirtyRegion(const QRegion &rgn, QWidget *widget){ QRegion wrgn(rgn); Q_ASSERT(widget->window() == tlw); if(!widget->isVisible() || !widget->updatesEnabled()) return; wrgn &= widget->d_func()->clipRect(); if (!widget->mask().isEmpty()) wrgn &= widget->mask();#ifndef Q_WS_QWS#ifdef Q_RATE_LIMIT_PAINTING if (refreshInterval > 0) { QWidget *timerWidget = widget;#ifdef Q_FLATTEN_EXPOSE if (timerWidget != tlw) { timerWidget = tlw; wrgn.translate(widget->mapTo(tlw, QPoint(0, 0))); }#endif timerWidget->d_func()->dirty += wrgn; if (timerWidget->d_func()->timerId == -1) timerWidget->d_func()->timerId = timerWidget->startTimer(refreshInterval); } else { widget->d_func()->dirtyWidget_sys(wrgn); }#else widget->d_func()->dirtyWidget_sys(wrgn);#endif // Q_RATE_LIMIT_PAINTING#endif#if defined(Q_RATE_LIMIT_PAINTING) && defined(Q_FLATTEN_EXPOSE) // wrgn is already translated otherwise if (refreshInterval <= 0)#endif wrgn.translate(widget->mapTo(tlw, QPoint(0, 0)));#ifndef Q_WS_QWS dirty += wrgn;#endif#ifdef Q_WS_QWS tlw->d_func()->dirtyWidget_sys(wrgn); //optimization: don't translate twice#endif}#ifdef Q_RATE_LIMIT_PAINTINGint QWidgetBackingStore::refreshInterval = 30;Q_GUI_EXPORT void qt_setMinimumRefreshInterval(int ms){ QWidgetBackingStore::refreshInterval = ms >= 0 ? ms : 0;}void QWidgetBackingStore::updateDirtyRegion(QWidget *widget){ if (!widget || widget->d_func()->dirty.isEmpty()) return; if (widget->isVisible() && widget->updatesEnabled()) widget->d_func()->dirtyWidget_sys(widget->d_func()->dirty); widget->d_func()->dirty = QRegion();}#endif // Q_RATE_LIMIT_PAINTINGvoid QWidgetBackingStore::copyToScreen(QWidget *widget, const QRegion &rgn){ QWidget *tlw = widget->window(); QTLWExtra *topextra = tlw->d_func()->extra->topextra; QPoint offset = widget->mapTo(tlw, QPoint()); topextra->backingStore->copyToScreen(rgn, widget, offset, false);}/** * Copies the contents of the backingstore into the screen area of \a widget. * \a offset is the position of \a widget relative to the top level widget. * \a rgn is the region to be updated in \a widget coordinates. * \a recursive indicates that the widget should recursivly call copyToScreen * for all child widgets. */void QWidgetBackingStore::copyToScreen(const QRegion &rgn, QWidget *widget, const QPoint &offset, bool recursive){ if (rgn.isEmpty()) return; Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));#ifdef Q_WS_QWS Q_UNUSED(recursive); // XXX: hw: this addition should probably be moved to cleanRegion() const QRegion toFlush = rgn + dirtyOnScreen; windowSurface->flush(widget, toFlush, offset); dirtyOnScreen = QRegion();#else if (!QWidgetBackingStore::paintOnScreen(widget)) { widget->d_func()->cleanWidget_sys(rgn);#if defined(Q_WS_WIN) && defined(Q_WIN_USE_QT_UPDATE_EVENT) HDC oldHandle = HDC(widget->d_func()->hd); if (oldHandle) { // New clip is the widget's visible region intersected with the flush region. widget->d_func()->hd = Qt::HANDLE(GetDCEx(widget->internalWinId(), rgn.handle(), DCX_INTERSECTRGN)); }#endif#ifndef QT_NO_PAINT_DEBUG qt_flushUpdate(widget, rgn);#endif QPoint wOffset = widget->data->wrect.topLeft(); windowSurface->flush(widget, rgn, offset);#if defined(Q_WS_WIN) && defined(Q_WIN_USE_QT_UPDATE_EVENT) // Reset device context. if (oldHandle) { ReleaseDC(widget->internalWinId(), HDC(widget->d_func()->hd)); widget->d_func()->hd = Qt::HANDLE(oldHandle); }#endif }#ifdef Q_FLATTEN_EXPOSE Q_ASSERT(!recursive); // Q_ASSERT(widget->isWindow());#endif if(recursive) { const QObjectList children = widget->children(); for(int i = 0; i < children.size(); ++i) { if(QWidget *child = qobject_cast<QWidget*>(children.at(i))) { if(!child->isWindow() && child->isVisible()) { if (qRectIntersects(rgn.boundingRect().translated(-child->pos()), child->rect())) { QRegion childRegion(rgn); childRegion.translate(-child->pos()); childRegion &= child->d_func()->clipRect(); if(!childRegion.isEmpty()) copyToScreen(childRegion, child, offset+child->pos(), recursive); } } } } }#endif}#ifdef Q_BACKINGSTORE_SUBSURFACESvoid QWidgetBackingStore::cleanRegion(const QRegion &rgn, QWidget *widget, bool recursiveCopyToScreen){ if (!widget->isVisible() || !widget->updatesEnabled() || !tlw->testAttribute(Qt::WA_Mapped)) return; if(QWidgetBackingStore::paintOnScreen(widget)) return; QRegion toClean;#if defined(Q_WS_QWS) QRect tlwRect = tlw->frameGeometry();#else QRect tlwRect = tlw->geometry();#endif#ifdef Q_WS_QWS QList<QWindowSurface*> surfaces = subSurfaces; surfaces.prepend(windowSurface); for (int i = 0; i < surfaces.size(); ++i) { QWindowSurface *windowSurface = surfaces.at(i); QWidget *currWidget = windowSurface->window(); QRect tlwRect; if (currWidget->isWindow()) { QWSWindowSurface *s = static_cast<QWSWindowSurface*>(windowSurface); tlwRect = QRect(currWidget->mapToGlobal(-s->painterOffset()), currWidget->frameGeometry().size()); } else { // XXX: hw: currently subsurfaces are resized in setGeometry_sys tlwRect = windowSurface->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); }#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); } else {#ifdef Q_WS_QWS toClean = static_cast<QWSWindowSurface*>(windowSurface)->dirtyRegion();#else toClean = dirty;#endif }#ifdef Q_WS_QWS const QPoint painterOffset = static_cast<QWSWindowSurface*>(windowSurface)->painterOffset(); if (currWidget->isWindow()) tlwOffset = painterOffset;#else const QPoint painterOffset(0, 0);#endif // ### move into prerender step QRegion toFlush = toClean;#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()) { // Pre render config windowSurface->paintDevice()->paintEngine()->setSystemClip(toClean); // hw: XXX the toClean region is not correct if !dirtyWidgets.isEmpty()// 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 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(w->windowSurface()->paintDevice(), dirty, painterOffset + offset, 0); toFlush += dirty.translated(offset); w->d_func()->dirty = QRegion(); } dirtyWidgets.clear();#endif // Q_WIDGET_USE_DIRTYLIST if (!toClean.isEmpty()) { currWidget->d_func()->drawWidget(windowSurface->paintDevice(), toClean, painterOffset); } // Drawing the overlay... windowSurface->paintDevice()->paintEngine()->setSystemClip(toClean); if (!flushing) windowSurface->endPaint(toClean); windowSurface->paintDevice()->paintEngine()->setSystemClip(QRegion()); } }#ifdef Q_WS_QWS if (toFlush.isEmpty()) continue; // XXX: hack to make copyToScreen work on the correct windowsurface QWindowSurface *oldSurface = this->windowSurface; this->windowSurface = windowSurface;#endif#if 0 if (recursiveCopyToScreen) { toFlush.translate(widget->mapTo(tlw, QPoint()));#ifdef Q_WS_QWS toFlush.translate(currWidget->mapFrom(tlw, QPoint())); copyToScreen(toFlush, currWidget, tlwOffset, recursiveCopyToScreen);#else copyToScreen(toFlush, tlw, tlwOffset, recursiveCopyToScreen);#endif } else {#ifdef Q_WS_X11 toFlush += widget->d_func()->dirtyOnScreen;#endif#ifdef Q_WS_QWS copyToScreen(toFlush, currWidget, currWidget->mapFrom(tlw, widget->mapTo(tlw, QPoint())), false);#else copyToScreen(toFlush, widget, widget->mapTo(tlw, QPoint()), false);#endif }#else // XXX copyToScreen(toFlush & static_cast<QWSWindowSurface*>(windowSurface)->clipRegion(), currWidget, tlwOffset, recursiveCopyToScreen);#endif#ifdef Q_WS_QWS this->windowSurface = oldSurface;#endif }}#else // Q_BACKINGSTORE_SUBSURFACESvoid QWidgetBackingStore::cleanRegion(const QRegion &rgn, QWidget *widget, bool recursiveCopyToScreen){ if (!widget->isVisible() || !widget->updatesEnabled() || !tlw->testAttribute(Qt::WA_Mapped)) return; if(QWidgetBackingStore::paintOnScreen(widget)) return; QRegion toClean;#if defined(Q_WS_QWS) QRect tlwRect = tlw->frameGeometry();#else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -