示例#1
0
      void ResultBitSet::updateChanged( uint32_t const* visibility )
      {
        dp::util::ProfileEntry p("ResultBitSet::updateChanged");

        if ( m_objectIncarnation != m_groupParent->getObjectIncarnation() )
        {
          m_objectIncarnation = m_groupParent->getObjectIncarnation();
          m_groupParent->getObjectCount();

          size_t numberOfResultChunks = ( m_groupParent->getObjectCount() + 31 ) / 32;
          size_t oldSize = m_results.getSize();
          m_results.resize( m_groupParent->getObjectCount() );

          // objects are visible by default, TODO required?
          for ( size_t index = oldSize; index < m_results.getSize(); ++index )
          {
            m_results.enableBit( index );
          }
        }
        /** \brief Visitor which adds changed objects to the changed group **/
        struct Visitor
        {
          inline Visitor( GroupBitSetSharedPtr const & group, std::vector<ObjectSharedPtr> & changed )
            : m_group( group )
            , m_changed( changed )
          {
            m_changed.clear();
          }

          inline void operator()( size_t index )
          {
            const ObjectBitSetSharedPtr& objectImpl = m_group->getObject( index );
            m_changed.push_back( objectImpl );
          }
        private:
          GroupBitSetSharedPtr const & m_group;
          std::vector<ObjectSharedPtr> & m_changed;
        };

        dp::util::BitArray newVisible( m_groupParent->getObjectCount() );
        newVisible.setBits( visibility, m_groupParent->getObjectCount() );

        dp::util::BitArray changed = newVisible ^ m_results;

        Visitor visitorBase( m_groupParent, m_changedObjects );
        changed.traverseBits(visitorBase);
        m_results = newVisible;
      }
示例#2
0
/*!
    Synchronizes the backing store, i.e. dirty areas are repainted and flushed.
*/
void QWidgetBackingStore::sync()
{
    QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData();
    if (discardSyncRequest(tlw, tlwExtra)) {
        // If the top-level is minimized, it's not visible on the screen so we can delay the
        // update until it's shown again. In order to do that we must keep the dirty states.
        // These will be cleared when we receive the first expose after showNormal().
        // However, if the widget is not visible (isVisible() returns false), everything will
        // be invalidated once the widget is shown again, so clear all dirty states.
        if (!tlw->isVisible()) {
            dirty = QRegion();
            for (int i = 0; i < dirtyWidgets.size(); ++i)
                resetWidget(dirtyWidgets.at(i));
            dirtyWidgets.clear();
            fullUpdatePending = false;
        }
        return;
    }

    const bool updatesDisabled = !tlw->updatesEnabled();
    bool repaintAllWidgets = false;

    const bool inTopLevelResize = tlwExtra->inTopLevelResize;
    const QRect tlwRect(tlw->data->crect);
    const QRect surfaceGeometry(windowSurface->geometry());
    if ((fullUpdatePending || inTopLevelResize || surfaceGeometry.size() != tlwRect.size()) && !updatesDisabled) {
        if (hasStaticContents()) {
            // Repaint existing dirty area and newly visible area.
            const QRect clipRect(0, 0, surfaceGeometry.width(), surfaceGeometry.height());
            const QRegion staticRegion(staticContents(0, clipRect));
            QRegion newVisible(0, 0, tlwRect.width(), tlwRect.height());
            newVisible -= staticRegion;
            dirty += newVisible;
            windowSurface->setStaticContents(staticRegion);
        } else {
            // Repaint everything.
            dirty = QRegion(0, 0, tlwRect.width(), tlwRect.height());
            for (int i = 0; i < dirtyWidgets.size(); ++i)
                resetWidget(dirtyWidgets.at(i));
            dirtyWidgets.clear();
            repaintAllWidgets = true;
        }
    }

    if (inTopLevelResize || surfaceGeometry != tlwRect)
        windowSurface->setGeometry(tlwRect);

    if (updatesDisabled)
        return;

    if (hasDirtyFromPreviousSync)
        dirty += dirtyFromPreviousSync;

    // Contains everything that needs repaint.
    QRegion toClean(dirty);

    // Loop through all update() widgets and remove them from the list before they are
    // painted (in case someone calls update() in paintEvent). If the widget is opaque
    // and does not have transparent overlapping siblings, append it to the
    // opaqueNonOverlappedWidgets list and paint it directly without composition.
    QVarLengthArray<QWidget *, 32> opaqueNonOverlappedWidgets;
    for (int i = 0; i < dirtyWidgets.size(); ++i) {
        QWidget *w = dirtyWidgets.at(i);
        QWidgetPrivate *wd = w->d_func();
        if (wd->data.in_destructor)
            continue;

        // Clip with mask() and clipRect().
        wd->dirty &= wd->clipRect();
        wd->clipToEffectiveMask(wd->dirty);

        // Subtract opaque siblings and children.
        bool hasDirtySiblingsAbove = false;
        // We know for sure that the widget isn't overlapped if 'isMoved' is true.
        if (!wd->isMoved)
            wd->subtractOpaqueSiblings(wd->dirty, &hasDirtySiblingsAbove);
        // Scrolled and moved widgets must draw all children.
        if (!wd->isScrolled && !wd->isMoved)
            wd->subtractOpaqueChildren(wd->dirty, w->rect());

        if (wd->dirty.isEmpty()) {
            resetWidget(w);
            continue;
        }

        const QRegion widgetDirty(w != tlw ? wd->dirty.translated(w->mapTo(tlw, QPoint()))
                                           : wd->dirty);
        toClean += widgetDirty;

#ifndef QT_NO_GRAPHICSVIEW
        if (tlw->d_func()->extra->proxyWidget) {
            resetWidget(w);
            continue;
        }
#endif

        if (!hasDirtySiblingsAbove && wd->isOpaque && !dirty.intersects(widgetDirty.boundingRect())) {
            opaqueNonOverlappedWidgets.append(w);
        } else {
            resetWidget(w);
            dirty += widgetDirty;
        }
    }
    dirtyWidgets.clear();

    fullUpdatePending = false;

    if (toClean.isEmpty()) {
        // Nothing to repaint. However, we might have newly exposed areas on the
        // screen if this function was called from sync(QWidget *, QRegion)), so
        // we have to make sure those are flushed.
        flush();
        return;
    }

#ifndef QT_NO_GRAPHICSVIEW
    if (tlw->d_func()->extra->proxyWidget) {
        updateStaticContentsSize();
        dirty = QRegion();
        const QVector<QRect> rects(toClean.rects());
        for (int i = 0; i < rects.size(); ++i)
            tlw->d_func()->extra->proxyWidget->update(rects.at(i));
        return;
    }
#endif

#ifndef Q_BACKINGSTORE_SUBSURFACES
    BeginPaintInfo beginPaintInfo;
    beginPaint(toClean, tlw, windowSurface, &beginPaintInfo);
    if (beginPaintInfo.nothingToPaint) {
        for (int i = 0; i < opaqueNonOverlappedWidgets.size(); ++i)
            resetWidget(opaqueNonOverlappedWidgets[i]);
        dirty = QRegion();
        return;
    }
#endif

    // Must do this before sending any paint events because
    // the size may change in the paint event.
    updateStaticContentsSize();
    const QRegion dirtyCopy(dirty);
    dirty = QRegion();

    // Paint opaque non overlapped widgets.
    for (int i = 0; i < opaqueNonOverlappedWidgets.size(); ++i) {
        QWidget *w = opaqueNonOverlappedWidgets[i];
        QWidgetPrivate *wd = w->d_func();

        int flags = QWidgetPrivate::DrawRecursive;
        // Scrolled and moved widgets must draw all children.
        if (!wd->isScrolled && !wd->isMoved)
            flags |= QWidgetPrivate::DontDrawOpaqueChildren;
        if (w == tlw)
            flags |= QWidgetPrivate::DrawAsRoot;

        QRegion toBePainted(wd->dirty);
        resetWidget(w);

#ifdef Q_BACKINGSTORE_SUBSURFACES
        QWindowSurface *subSurface = w->windowSurface();
        BeginPaintInfo beginPaintInfo;

        QPoint off = w->mapTo(tlw, QPoint());
        toBePainted.translate(off);
        beginPaint(toBePainted, w, subSurface, &beginPaintInfo, true);
        toBePainted.translate(-off);

        if (beginPaintInfo.nothingToPaint)
            continue;

        if (beginPaintInfo.windowSurfaceRecreated) {
            // Eep the window surface has changed. The old one may have been
            // deleted, in which case we will segfault on the call to
            // painterOffset() below. Use the new window surface instead.
            subSurface = w->windowSurface();
        }

        QPoint offset(tlwOffset);
        if (subSurface == windowSurface)
            offset += w->mapTo(tlw, QPoint());
        else
            offset = static_cast<QWSWindowSurface*>(subSurface)->painterOffset();
        wd->drawWidget(subSurface->paintDevice(), toBePainted, offset, flags, 0, this);

        endPaint(toBePainted, subSurface, &beginPaintInfo);
#else
        QPoint offset(tlwOffset);
        if (w != tlw)
            offset += w->mapTo(tlw, QPoint());
        wd->drawWidget(windowSurface->paintDevice(), toBePainted, offset, flags, 0, this);
#endif
    }

    // Paint the rest with composition.
#ifndef Q_BACKINGSTORE_SUBSURFACES
    if (repaintAllWidgets || !dirtyCopy.isEmpty()) {
        const int flags = QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawRecursive;
        tlw->d_func()->drawWidget(windowSurface->paintDevice(), dirtyCopy, tlwOffset, flags, 0, this);
    }

    endPaint(toClean, windowSurface, &beginPaintInfo);
#else
    if (!repaintAllWidgets && dirtyCopy.isEmpty())
        return; // Nothing more to paint.

    QList<QWindowSurface *> surfaceList(subSurfaces);
    surfaceList.prepend(windowSurface);
    const QRect dirtyBoundingRect(dirtyCopy.boundingRect());

    // Loop through all window surfaces (incl. the top-level surface) and
    // repaint those intersecting with the bounding rect of the dirty region.
    for (int i = 0; i < surfaceList.size(); ++i) {
        QWindowSurface *subSurface = surfaceList.at(i);
        QWidget *w = subSurface->window();
        QWidgetPrivate *wd = w->d_func();

        const QRect clipRect = wd->clipRect().translated(w->mapTo(tlw, QPoint()));
        if (!qRectIntersects(dirtyBoundingRect, clipRect))
            continue;

        toClean = dirtyCopy;
        BeginPaintInfo beginPaintInfo;
        beginPaint(toClean, w, subSurface, &beginPaintInfo);
        if (beginPaintInfo.nothingToPaint)
            continue;

        if (beginPaintInfo.windowSurfaceRecreated) {
            // Eep the window surface has changed. The old one may have been
            // deleted, in which case we will segfault on the call to
            // painterOffset() below. Use the new window surface instead.
            subSurface = w->windowSurface();
        }

        int flags = QWidgetPrivate::DrawRecursive;
        if (w == tlw)
            flags |= QWidgetPrivate::DrawAsRoot;
        const QPoint painterOffset = static_cast<QWSWindowSurface*>(subSurface)->painterOffset();
        wd->drawWidget(subSurface->paintDevice(), toClean, painterOffset, flags, 0, this);

        endPaint(toClean, subSurface, &beginPaintInfo);
    }
#endif
}
示例#3
0
/*!
    Invalidates the buffer when the widget is resized.
    Static areas are never invalidated unless absolutely needed.
*/
void QWidgetPrivate::invalidateBuffer_resizeHelper(const QPoint &oldPos, const QSize &oldSize)
{
    Q_Q(QWidget);
    Q_ASSERT(!q->isWindow());
    Q_ASSERT(q->parentWidget());

    const bool staticContents = q->testAttribute(Qt::WA_StaticContents);
    const bool sizeDecreased = (data.crect.width() < oldSize.width())
                               || (data.crect.height() < oldSize.height());

    const QPoint offset(data.crect.x() - oldPos.x(), data.crect.y() - oldPos.y());
    const bool parentAreaExposed = !offset.isNull() || sizeDecreased;
    const QRect newWidgetRect(q->rect());
    const QRect oldWidgetRect(0, 0, oldSize.width(), oldSize.height());

    if (!staticContents || graphicsEffect) {
        QRegion staticChildren;
        QWidgetBackingStore *bs = 0;
        if (offset.isNull() && (bs = maybeBackingStore()))
            staticChildren = bs->staticContents(q, oldWidgetRect);
        const bool hasStaticChildren = !staticChildren.isEmpty();

        if (hasStaticChildren) {
            QRegion dirty(newWidgetRect);
            dirty -= staticChildren;
            invalidateBuffer(dirty);
        } else {
            // Entire widget needs repaint.
            invalidateBuffer(newWidgetRect);
        }

        if (!parentAreaExposed)
            return;

        // Invalidate newly exposed area of the parent.
        if (!graphicsEffect && extra && extra->hasMask) {
            QRegion parentExpose(extra->mask.translated(oldPos));
            parentExpose &= QRect(oldPos, oldSize);
            if (hasStaticChildren)
                parentExpose -= data.crect; // Offset is unchanged, safe to do this.
            q->parentWidget()->d_func()->invalidateBuffer(parentExpose);
        } else {
            if (hasStaticChildren && !graphicsEffect) {
                QRegion parentExpose(QRect(oldPos, oldSize));
                parentExpose -= data.crect; // Offset is unchanged, safe to do this.
                q->parentWidget()->d_func()->invalidateBuffer(parentExpose);
            } else {
                q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(QRect(oldPos, oldSize)));
            }
        }
        return;
    }

    // Move static content to its new position.
    if (!offset.isNull()) {
        if (sizeDecreased) {
            const QSize minSize(qMin(oldSize.width(), data.crect.width()),
                                qMin(oldSize.height(), data.crect.height()));
            moveRect(QRect(oldPos, minSize), offset.x(), offset.y());
        } else {
            moveRect(QRect(oldPos, oldSize), offset.x(), offset.y());
        }
    }

    // Invalidate newly visible area of the widget.
    if (!sizeDecreased || !oldWidgetRect.contains(newWidgetRect)) {
        QRegion newVisible(newWidgetRect);
        newVisible -= oldWidgetRect;
        invalidateBuffer(newVisible);
    }

    if (!parentAreaExposed)
        return;

    // Invalidate newly exposed area of the parent.
    const QRect oldRect(oldPos, oldSize);
    if (extra && extra->hasMask) {
        QRegion parentExpose(oldRect);
        parentExpose &= extra->mask.translated(oldPos);
        parentExpose -= (extra->mask.translated(data.crect.topLeft()) & data.crect);
        q->parentWidget()->d_func()->invalidateBuffer(parentExpose);
    } else {
        QRegion parentExpose(oldRect);
        parentExpose -= data.crect;
        q->parentWidget()->d_func()->invalidateBuffer(parentExpose);
    }
}