QWindowSurface *QGLGraphicsSystem::createWindowSurface(QWidget *widget) const { #ifdef Q_WS_WIN // On Windows the QGLWindowSurface class can't handle // drop shadows and native effects, e.g. fading a menu in/out using // top level window opacity. if (widget->windowType() == Qt::Popup) return new QRasterWindowSurface(widget); #endif #if defined(Q_WS_X11) && !defined(QT_NO_EGL) if (m_useX11GL && QX11GLPixmapData::hasX11GLPixmaps()) { // If the widget is a QGraphicsView which will be re-drawing the entire // scene each frame anyway, we should use QGLWindowSurface as this may // provide proper buffer flipping, which should be faster than QX11GL's // blitting approach: QGraphicsView* qgv = qobject_cast<QGraphicsView*>(widget); if (qgv && qgv->viewportUpdateMode() == QGraphicsView::FullViewportUpdate) return new QGLWindowSurface(widget); else return new QX11GLWindowSurface(widget); } #endif #if defined(Q_OS_SYMBIAN) if (!QApplicationPrivate::instance()->useTranslucentEGLSurfaces) { QWidgetPrivate *d = qt_widget_private(widget); if (!d->isOpaque && widget->testAttribute(Qt::WA_TranslucentBackground)) return d->createDefaultWindowSurface_sys(); } #endif return new QGLWindowSurface(widget); }
void QAbstractScrollAreaPrivate::setSingleFingerPanEnabled(bool on) { singleFingerPanEnabled = on; QWidgetPrivate *dd = static_cast<QWidgetPrivate *>(QObjectPrivate::get(viewport)); if (dd) dd->winSetupGestures(); }
QPlatformScreen * QPlatformScreen::platformScreenForWidget(const QWidget *widget) { QWidget *window = widget->window(); QWidgetPrivate *windowPrivate = qt_widget_private(window); QTLWExtra * topData = windowPrivate->topData(); QPlatformIntegration *integration = QApplicationPrivate::platformIntegration(); return integration->screens()[topData->screenIndex]; }
void markParentChain() { Q_Q(QWindowContainer); QWidget *p = q; while (p) { QWidgetPrivate *d = static_cast<QWidgetPrivate *>(QWidgetPrivate::get(p)); d->createExtra(); d->extra->hasWindowContainer = true; p = p->parentWidget(); } }
QWindowSurface *QVGGraphicsSystem::createWindowSurface(QWidget *widget) const { #if defined(Q_OS_SYMBIAN) if (!QApplicationPrivate::instance()->useTranslucentEGLSurfaces) { QWidgetPrivate *d = qt_widget_private(widget); if (!d->isOpaque && widget->testAttribute(Qt::WA_TranslucentBackground)) return d->createDefaultWindowSurface_sys(); } #endif return new QVGWindowSurface(widget); }
QGesture *QWinNativePanGestureRecognizer::create(QObject *target) { if (!target) return new QPanGesture; // a special case if (!target->isWidgetType()) return 0; if (qobject_cast<QGraphicsObject *>(target)) return 0; QWidget *q = static_cast<QWidget *>(target); QWidgetPrivate *d = q->d_func(); d->nativeGesturePanEnabled = true; d->winSetupGestures(); return new QPanGesture; }
/*! Returns the static content inside the \a parent if non-zero; otherwise the static content for the entire backing store is returned. The content will be clipped to \a withinClipRect if non-empty. */ QRegion QWidgetBackingStore::staticContents(QWidget *parent, const QRect &withinClipRect) const { if (!parent && tlw->testAttribute(Qt::WA_StaticContents)) { const QRect surfaceGeometry(windowSurface->geometry()); QRect surfaceRect(0, 0, surfaceGeometry.width(), surfaceGeometry.height()); if (!withinClipRect.isEmpty()) surfaceRect &= withinClipRect; return QRegion(surfaceRect); } QRegion region; if (parent && parent->d_func()->children.isEmpty()) return region; const bool clipToRect = !withinClipRect.isEmpty(); const int count = staticWidgets.count(); for (int i = 0; i < count; ++i) { QWidget *w = staticWidgets.at(i); QWidgetPrivate *wd = w->d_func(); if (!wd->isOpaque || !wd->extra || wd->extra->staticContentsSize.isEmpty() || !w->isVisible() || (parent && !parent->isAncestorOf(w))) { continue; } QRect rect(0, 0, wd->extra->staticContentsSize.width(), wd->extra->staticContentsSize.height()); const QPoint offset = w->mapTo(parent ? parent : tlw, QPoint()); if (clipToRect) rect &= withinClipRect.translated(-offset); if (rect.isEmpty()) continue; rect &= wd->clipRect(); if (rect.isEmpty()) continue; QRegion visible(rect); wd->clipToEffectiveMask(visible); if (visible.isEmpty()) continue; wd->subtractOpaqueSiblings(visible, 0, /*alsoNonOpaque=*/true); visible.translate(offset); region += visible; } return region; }
void QWindowContainer::parentWasChanged(QWidget *parent) { if (QWindowContainerPrivate *d = QWindowContainerPrivate::get(parent)) { if (d->window->parent()) { d->updateUsesNativeWidgets(); d->markParentChain(); QWidget *toplevel = d->usesNativeWidgets ? parent : parent->window(); if (!toplevel->windowHandle()) { QWidgetPrivate *tld = static_cast<QWidgetPrivate *>(QWidgetPrivate::get(toplevel)); tld->createTLExtra(); tld->createTLSysExtra(); Q_ASSERT(toplevel->windowHandle()); } d->window->setParent(toplevel->windowHandle()); d->updateGeometry(); } } qwindowcontainer_traverse(parent, parentWasChanged); }
/*! 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 }
//parent's coordinates; move whole rect; update parent and widget //assume the screen blt has already been done, so we don't need to refresh that part void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy) { Q_Q(QWidget); if (!q->isVisible() || (dx == 0 && dy == 0)) return; QWidget *tlw = q->window(); QTLWExtra* x = tlw->d_func()->topData(); if (x->inTopLevelResize) return; static int accelEnv = -1; if (accelEnv == -1) { accelEnv = qgetenv("QT_NO_FAST_MOVE").toInt() == 0; } QWidget *pw = q->parentWidget(); QPoint toplevelOffset = pw->mapTo(tlw, QPoint()); QWidgetPrivate *pd = pw->d_func(); QRect clipR(pd->clipRect()); const QRect newRect(rect.translated(dx, dy)); QRect destRect = rect.intersected(clipR); if (destRect.isValid()) destRect = destRect.translated(dx, dy).intersected(clipR); const QRect sourceRect(destRect.translated(-dx, -dy)); const QRect parentRect(rect & clipR); bool accelerateMove = accelEnv && isOpaque #ifndef QT_NO_GRAPHICSVIEW // No accelerate move for proxy widgets. && !tlw->d_func()->extra->proxyWidget #endif && !isOverlapped(sourceRect) && !isOverlapped(destRect); if (!accelerateMove) { QRegion parentR(effectiveRectFor(parentRect)); if (!extra || !extra->hasMask) { parentR -= newRect; } else { // invalidateBuffer() excludes anything outside the mask parentR += newRect & clipR; } pd->invalidateBuffer(parentR); invalidateBuffer((newRect & clipR).translated(-data.crect.topLeft())); } else { QWidgetBackingStore *wbs = x->backingStore.data(); QRegion childExpose(newRect & clipR); if (sourceRect.isValid() && wbs->bltRect(sourceRect, dx, dy, pw)) childExpose -= destRect; if (!pw->updatesEnabled()) return; const bool childUpdatesEnabled = q->updatesEnabled(); if (childUpdatesEnabled && !childExpose.isEmpty()) { childExpose.translate(-data.crect.topLeft()); wbs->markDirty(childExpose, q); isMoved = true; } QRegion parentExpose(parentRect); parentExpose -= newRect; if (extra && extra->hasMask) parentExpose += QRegion(newRect) - extra->mask.translated(data.crect.topLeft()); if (!parentExpose.isEmpty()) { wbs->markDirty(parentExpose, pw); pd->isMoved = true; } if (childUpdatesEnabled) { QRegion needsFlush(sourceRect); needsFlush += destRect; wbs->markDirtyOnScreen(needsFlush, pw, toplevelOffset); } } }