void QUnifiedToolbarSurface::renderToolbar(QWidget *widget, bool forceFlush) { QWidget *toolbar = widget->d_func()->toolbar_ancestor; updateToolbarOffset(toolbar); QRect beginPaintRect(toolbar->d_func()->toolbar_offset.x(), toolbar->d_func()->toolbar_offset.y(), toolbar->geometry().width(), toolbar->geometry().height()); QRegion beginPaintRegion(beginPaintRect); beginPaint(beginPaintRegion); toolbar->render(paintDevice(), toolbar->d_func()->toolbar_offset, QRegion(toolbar->geometry()), QWidget::DrawChildren); toolbar->d_func()->flushRequested = true; if (forceFlush) flush(toolbar); }
void QWSWindowSurface::invalidateBuffer() { QWidget *win = window(); if (win) { win->d_func()->invalidateBuffer(win->rect()); #ifndef QT_NO_QWS_MANAGER QTLWExtra *topextra = win->d_func()->extra->topextra; QWSManager *manager = topextra->qwsManager; if (manager) manager->d_func()->dirtyRegion(QDecoration::All, QDecoration::Normal); #endif } }
/*! Returns the region (in top-level coordinates) that needs repaint and/or flush. If the widget is non-zero, only the dirty region for the widget is returned and the region will be in widget coordinates. */ QRegion QWidgetBackingStore::dirtyRegion(QWidget *widget) const { const bool widgetDirty = widget && widget != tlw; const QRect tlwRect(tlw->data->crect); const QRect surfaceGeometry(windowSurface->geometry()); if (fullUpdatePending || (surfaceGeometry != tlwRect && surfaceGeometry.size() != tlwRect.size())) { if (widgetDirty) { const QRect dirtyTlwRect = QRect(QPoint(), tlwRect.size()); const QPoint offset(widget->mapTo(tlw, QPoint())); const QRect dirtyWidgetRect(dirtyTlwRect & widget->rect().translated(offset)); return dirtyWidgetRect.translated(-offset); } return QRect(QPoint(), tlwRect.size()); } // Calculate the region that needs repaint. QRegion r(dirty); for (int i = 0; i < dirtyWidgets.size(); ++i) { QWidget *w = dirtyWidgets.at(i); if (widgetDirty && w != widget && !widget->isAncestorOf(w)) continue; r += w->d_func()->dirty.translated(w->mapTo(tlw, QPoint())); } // Append the region that needs flush. r += dirtyOnScreen; if (dirtyOnScreenWidgets) { // Only in use with native child widgets. for (int i = 0; i < dirtyOnScreenWidgets->size(); ++i) { QWidget *w = dirtyOnScreenWidgets->at(i); if (widgetDirty && w != widget && !widget->isAncestorOf(w)) continue; QWidgetPrivate *wd = w->d_func(); Q_ASSERT(wd->needsFlush); r += wd->needsFlush->translated(w->mapTo(tlw, QPoint())); } } if (widgetDirty) { // Intersect with the widget geometry and translate to its coordinates. const QPoint offset(widget->mapTo(tlw, QPoint())); r &= widget->rect().translated(offset); r.translate(-offset); } return r; }
// We basically undo what we set in recursiveRedirect(). void QUnifiedToolbarSurface::recursiveRemoval(QObject *object) { if (object != 0) { if (object->isWidgetType()) { QWidget *widget = qobject_cast<QWidget *>(object); // If it's a pop-up or something similar, we don't redirect it. if (widget->windowType() & Qt::Window) return; widget->d_func()->unifiedSurface = 0; widget->d_func()->isInUnifiedToolbar = false; widget->d_func()->toolbar_offset = QPoint(); widget->d_func()->toolbar_ancestor = 0; } for (int i = 0; i < object->children().size(); ++i) { recursiveRemoval(object->children().at(i)); } } }
void QUnifiedToolbarSurface::recursiveRedirect(QObject *object, QWidget *parent_toolbar, const QPoint &offset) { if (object != 0) { if (object->isWidgetType()) { QWidget *widget = qobject_cast<QWidget *>(object); // We redirect the painting only if the widget is in the same window // and is not a window in itself. if (!(widget->windowType() & Qt::Window)) { widget->d_func()->unifiedSurface = this; widget->d_func()->isInUnifiedToolbar = true; widget->d_func()->toolbar_offset = offset; widget->d_func()->toolbar_ancestor = parent_toolbar; for (int i = 0; i < object->children().size(); ++i) { recursiveRedirect(object->children().at(i), parent_toolbar, offset); } } } } }
/*! Sets the region currently visible on the screen to be the given \a clip region. \sa clipRegion() */ void QWSWindowSurface::setClipRegion(const QRegion &clip) { if (clip == d_ptr->clip) return; QRegion expose = (clip - d_ptr->clip); d_ptr->clip = clip; if (expose.isEmpty() || clip.isEmpty()) return; // No repaint or flush required. QWidget *win = window(); if (!win) return; if (isBuffered()) { // No repaint required. Flush exposed area via the backing store. win->d_func()->syncBackingStore(expose); return; } #ifndef QT_NO_QWS_MANAGER // Invalidate exposed decoration area. if (win && win->isWindow()) { QTLWExtra *topextra = win->d_func()->extra->topextra; if (QWSManager *manager = topextra->qwsManager) { QRegion decorationExpose(manager->region()); decorationExpose.translate(-win->geometry().topLeft()); decorationExpose &= expose; if (!decorationExpose.isEmpty()) { expose -= decorationExpose; manager->d_func()->dirtyRegion(QDecoration::All, QDecoration::Normal, decorationExpose); } } } #endif // Invalidate exposed widget area. win->d_func()->invalidateBuffer(expose); }
void QWidgetBackingStore::unflushPaint(QWidget *widget, const QRegion &rgn) { if (widget->d_func()->paintOnScreen() || rgn.isEmpty()) return; QWidget *tlw = widget->window(); QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData(); if (!tlwExtra) return; const QPoint offset = widget->mapTo(tlw, QPoint()); qt_flush(widget, rgn, tlwExtra->backingStore->windowSurface, tlw, offset); }
void QRasterWindowSurface::setGeometry(const QRect &rect) { QWindowSurface::setGeometry(rect); Q_D(QRasterWindowSurface); d->inSetGeometry = true; if (d->image == 0 || d->image->width() < rect.width() || d->image->height() < rect.height()) { #if (defined(Q_WS_X11) && !defined(QT_NO_XRENDER)) || (defined(Q_WS_WIN)) #ifndef Q_WS_WIN if (d_ptr->translucentBackground) #else if (!qt_widget_private(window())->isOpaque) #endif prepareBuffer(QImage::Format_ARGB32_Premultiplied, window()); else #endif prepareBuffer(QNativeImage::systemFormat(), window()); } d->inSetGeometry = false; #if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA) QMainWindow* mWindow = qobject_cast<QMainWindow*>(window()); if (mWindow) { QMainWindowLayout *mLayout = qobject_cast<QMainWindowLayout*>(mWindow->layout()); QList<QToolBar *> toolbarList = mLayout->qtoolbarsInUnifiedToolbarList; for (int i = 0; i < toolbarList.size(); ++i) { QToolBar* toolbar = toolbarList.at(i); if (mLayout->toolBarArea(toolbar) == Qt::TopToolBarArea) { QWidget* tbWidget = (QWidget*) toolbar; if (tbWidget->d_func()->unifiedSurface) { tbWidget->d_func()->unifiedSurface->setGeometry(rect); } } } } #endif // Q_WS_MAC && QT_MAC_USE_COCOA }
void QApplicationPrivate::reportGeometryChange(QWindowSystemInterfacePrivate::ScreenGeometryEvent *e) { // This operation only makes sense after the QApplication constructor runs if (QCoreApplication::startingUp()) return; QApplication::desktop()->d_func()->updateScreenList(); // signal anything listening for screen geometry changes QDesktopWidget *desktop = QApplication::desktop(); emit desktop->resized(e->index); // make sure maximized and fullscreen windows are updated QWidgetList list = QApplication::topLevelWidgets(); for (int i = list.size() - 1; i >= 0; --i) { QWidget *w = list.at(i); if (w->isFullScreen()) w->d_func()->setFullScreenSize_helper(); else if (w->isMaximized()) w->d_func()->setMaxWindowState_helper(); } }
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 QWidgetPrivate::dirtyWidget_sys(const QRegion &rgn, bool updateImmediately) { Q_Q(QWidget); QWidget *tlw = q->window(); QTLWExtra *tlwExtra = tlw->d_func()->topData(); QWidgetBackingStore *wbs = tlwExtra->backingStore; QRegion wrgn(rgn); if (tlw != q) { QPoint offs(q->mapTo(tlw, QPoint())); wrgn.translate(offs); } QWSWindowSurface *surface = static_cast<QWSWindowSurface*>(wbs->windowSurface); if (surface) { surface->d_ptr->updateImmediately = updateImmediately; if (tlwExtra->proxyWidget) { // Add the existing dirty region to the current update region before // we reset QWSWindowSurface::dirty. We do this in order to always // send an update event on sub-sequent updates/repaints. wrgn += surface->d_ptr->dirty; surface->d_ptr->dirty = QRegion(); // XXX: hw: Make sure we post/send update requests. surface->d_ptr->clip = wrgn; } surface->setDirty(wrgn); // re-get, since setDirty may recreate the surface surface = static_cast<QWSWindowSurface*>(wbs->windowSurface); surface->d_ptr->updateImmediately = false; #ifdef Q_BACKINGSTORE_SUBSURFACES // dirty on all subsurfaces... QList<QWindowSurface*> subSurfaces = wbs->subSurfaces; // XXX: hw: only if region intersects any of the subsurfaces for (int i = 0; i < subSurfaces.size(); ++i) { QWSWindowSurface *s = static_cast<QWSWindowSurface*>(subSurfaces.at(i)); QPoint p = s->window()->mapTo(tlw, QPoint()); // must use widget? s->d_ptr->updateImmediately = updateImmediately; s->setDirty(wrgn.translated(-p)); s->d_ptr->updateImmediately = false; } #endif // Q_BACKINGSTORE_SUBSURFACES } }
void QWidgetPrivate::cleanWidget_sys(const QRegion& rgn) { Q_Q(QWidget); QWidget *tlw = q->window(); QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData(); if (!tlwExtra || !tlwExtra->proxyWidget || tlwExtra->backingStore) return; QRegion wrgn(rgn); if (tlw != q) { QPoint offs(q->mapTo(tlw, QPoint())); wrgn.translate(offs); } if (QWSWindowSurface *surface = static_cast<QWSWindowSurface*>(tlwExtra->backingStore->windowSurface)) surface->d_ptr->dirty -= wrgn; }
void QS60WindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &) { QWidget *window = widget->window(); Q_ASSERT(window); QTLWExtra *topExtra = window->d_func()->maybeTopData(); Q_ASSERT(topExtra); QRect qr = region.boundingRect(); if (!topExtra->inExpose) { topExtra->inExpose = true; // Prevent DrawNow() from calling syncBackingStore() again TRect tr = qt_QRect2TRect(qr); widget->winId()->DrawNow(tr); topExtra->inExpose = false; } else { // This handles the case when syncBackingStore updates content outside of the // original drawing rectangle. This might happen if there are pending update() // events at the same time as we get a Draw() from Symbian. QRect drawRect = qt_TRect2QRect(widget->winId()->DrawableWindow()->GetDrawRect()); if (!drawRect.contains(qr)) widget->winId()->DrawDeferred(); } }
/*! Flushes the contents of the backing store into the top-level widget. If the \a widget is non-zero, the content is flushed to the \a widget. If the \a surface is non-zero, the content of the \a surface is flushed. */ void QWidgetBackingStore::flush(QWidget *widget, QWindowSurface *surface) { if (!dirtyOnScreen.isEmpty()) { QWidget *target = widget ? widget : tlw; QWindowSurface *source = surface ? surface : windowSurface; qt_flush(target, dirtyOnScreen, source, tlw, tlwOffset); dirtyOnScreen = QRegion(); } if (!dirtyOnScreenWidgets || dirtyOnScreenWidgets->isEmpty()) return; for (int i = 0; i < dirtyOnScreenWidgets->size(); ++i) { QWidget *w = dirtyOnScreenWidgets->at(i); QWidgetPrivate *wd = w->d_func(); Q_ASSERT(wd->needsFlush); qt_flush(w, *wd->needsFlush, windowSurface, tlw, tlwOffset); *wd->needsFlush = QRegion(); } dirtyOnScreenWidgets->clear(); }
/*! Marks the \a region of the \a widget as dirty on screen. The \a region will be copied from the backing store to the \a widget's native parent next time flush() is called. Paint on screen widgets are ignored. */ void QWidgetBackingStore::markDirtyOnScreen(const QRegion ®ion, QWidget *widget, const QPoint &topLevelOffset) { if (!widget || widget->d_func()->paintOnScreen() || region.isEmpty()) return; // Top-level. if (widget == tlw) { if (!widget->testAttribute(Qt::WA_WState_InPaintEvent)) dirtyOnScreen += region; return; } // Alien widgets. if (!widget->internalWinId() && !widget->isWindow()) { QWidget *nativeParent = widget->nativeParentWidget(); // Alien widgets with the top-level as the native parent (common case). if (nativeParent == tlw) { if (!widget->testAttribute(Qt::WA_WState_InPaintEvent)) dirtyOnScreen += region.translated(topLevelOffset); return; } // Alien widgets with native parent != tlw. QWidgetPrivate *nativeParentPrivate = nativeParent->d_func(); if (!nativeParentPrivate->needsFlush) nativeParentPrivate->needsFlush = new QRegion; const QPoint nativeParentOffset = widget->mapTo(nativeParent, QPoint()); *nativeParentPrivate->needsFlush += region.translated(nativeParentOffset); appendDirtyOnScreenWidget(nativeParent); return; } // Native child widgets. QWidgetPrivate *widgetPrivate = widget->d_func(); if (!widgetPrivate->needsFlush) widgetPrivate->needsFlush = new QRegion; *widgetPrivate->needsFlush += region; appendDirtyOnScreenWidget(widget); }
/*! 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 }
void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool /*destroyOldWindow*/) { Q_Q(QWidget); Qt::WindowType type = q->windowType(); // Make sure the WindowTitleHint is on if any of the title bar hints are set // Note: This might be moved to cross-platform QWidgetPrivate::adjustFlags() if ( !(data.window_flags & Qt::CustomizeWindowHint) && ( (data.window_flags & Qt::WindowSystemMenuHint) || (data.window_flags & Qt::WindowContextHelpButtonHint) || (data.window_flags & Qt::WindowMinimizeButtonHint) || (data.window_flags & Qt::WindowMaximizeButtonHint) || (data.window_flags & Qt::WindowCloseButtonHint) ) ) { data.window_flags |= Qt::WindowTitleHint; } // Decoration plugins on QWS don't support switching on the close button on its own if (data.window_flags & Qt::WindowCloseButtonHint) data.window_flags |= Qt::WindowSystemMenuHint; Qt::WindowFlags flags = data.window_flags; data.alloc_region_index = -1; // we don't have a "Drawer" window type if (type == Qt::Drawer) { type = Qt::Widget; flags &= ~Qt::WindowType_Mask; } bool topLevel = (flags & Qt::Window); bool popup = (type == Qt::Popup); bool dialog = (type == Qt::Dialog || type == Qt::Sheet || (flags & Qt::MSWindowsFixedSizeDialogHint)); bool desktop = (type == Qt::Desktop); bool tool = (type == Qt::Tool || type == Qt::SplashScreen || type == Qt::ToolTip); #ifndef QT_NO_WARNING_OUTPUT static bool toolWarningShown = false; if (!toolWarningShown && type == Qt::Tool && !(flags & Qt::FramelessWindowHint)) { qWarning("Qt for Embedded Linux " QT_VERSION_STR " does not support tool windows with frames.\n" "This behavior will change in a later release. To ensure compatibility with\n" "future versions, use (Qt::Tool | Qt::FramelessWindowHint)."); toolWarningShown = true; } #endif WId id; QWSDisplay* dpy = QWidget::qwsDisplay(); if (!window) // always initialize initializeWindow = true; // use the size of the primary screen to determine the default window size QList<QScreen *> screens = qt_screen->subScreens(); if (screens.isEmpty()) screens.append(qt_screen); int sw = screens[0]->width(); int sh = screens[0]->height(); if (desktop) { // desktop widget dialog = popup = false; // force these flags off data.crect.setRect(0, 0, sw, sh); } else if (topLevel && !q->testAttribute(Qt::WA_Resized)) { int width = sw / 2; int height = 4 * sh / 10; if (extra) { width = qMax(qMin(width, extra->maxw), extra->minw); height = qMax(qMin(height, extra->maxh), extra->minh); } data.crect.setSize(QSize(width, height)); } if (window) { // override the old window id = window; setWinId(window); } else if (desktop) { // desktop widget id = (WId)-2; // id = root window #if 0 QWidget *otherDesktop = q->find(id); // is there another desktop? if (otherDesktop && otherDesktop->testWFlags(Qt::WPaintDesktop)) { otherDesktop->d_func()->setWinId(0); // remove id from widget mapper setWinId(id); // make sure otherDesktop is otherDesktop->d_func()->setWinId(id); // found first } else #endif { setWinId(id); } } else { id = topLevel ? dpy->takeId() : takeLocalId(); setWinId(id); // set widget id/handle + hd } bool hasFrame = true; if (topLevel) { if (desktop || popup || tool || q->testAttribute(Qt::WA_DontShowOnScreen)) hasFrame = false; else hasFrame = !(flags & Qt::FramelessWindowHint); } if (desktop) { q->setAttribute(Qt::WA_WState_Visible); } else if (topLevel) { // set X cursor //QCursor *oc = QApplication::overrideCursor(); if (initializeWindow) { //XXX XDefineCursor(dpy, winid, oc ? oc->handle() : cursor().handle()); } QWidget::qwsDisplay()->nameRegion(q->internalWinId(), q->objectName(), q->windowTitle()); } if (topLevel) { createTLExtra(); QTLWExtra *topextra = extra->topextra; #ifndef QT_NO_QWS_MANAGER if (hasFrame) { // get size of wm decoration and make the old crect the new frect QRect cr = data.crect; QRegion r = QApplication::qwsDecoration().region(q, cr) | cr; QRect br(r.boundingRect()); topextra->frameStrut.setCoords(cr.x() - br.x(), cr.y() - br.y(), br.right() - cr.right(), br.bottom() - cr.bottom()); if (!q->testAttribute(Qt::WA_Moved) || topextra->posFromMove) data.crect.translate(topextra->frameStrut.left(), topextra->frameStrut.top()); if (!topData()->qwsManager) { topData()->qwsManager = new QWSManager(q); if((q->data->window_state & ~Qt::WindowActive) == Qt::WindowMaximized) topData()->qwsManager->maximize(); } } else if (topData()->qwsManager) { delete topData()->qwsManager; topData()->qwsManager = 0; data.crect.translate(-topextra->frameStrut.left(), -topextra->frameStrut.top()); topextra->frameStrut.setCoords(0, 0, 0, 0); } #endif if (!topextra->caption.isEmpty()) setWindowTitle_helper(topextra->caption); //XXX If we are session managed, inform the window manager about it } else { if (extra && extra->topextra) { // already allocated due to reparent? extra->topextra->frameStrut.setCoords(0, 0, 0, 0); } //updateRequestedRegion(mapToGlobal(QPoint(0,0))); } }
//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); } } }
//widget's coordinates; scroll within rect; only update widget void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy) { Q_Q(QWidget); QWidget *tlw = q->window(); QTLWExtra* x = tlw->d_func()->topData(); if (x->inTopLevelResize) return; QWidgetBackingStore *wbs = x->backingStore.data(); if (!wbs) return; static int accelEnv = -1; if (accelEnv == -1) { accelEnv = qgetenv("QT_NO_FAST_SCROLL").toInt() == 0; } QRect scrollRect = rect & clipRect(); bool overlapped = false; bool accelerateScroll = accelEnv && isOpaque && !(overlapped = isOverlapped(scrollRect.translated(data.crect.topLeft()))); if (!accelerateScroll) { if (overlapped) { QRegion region(scrollRect); subtractOpaqueSiblings(region); invalidateBuffer(region); }else { invalidateBuffer(scrollRect); } } else { const QPoint toplevelOffset = q->mapTo(tlw, QPoint()); const QRect destRect = scrollRect.translated(dx, dy) & scrollRect; const QRect sourceRect = destRect.translated(-dx, -dy); QRegion childExpose(scrollRect); if (sourceRect.isValid()) { if (wbs->bltRect(sourceRect, dx, dy, q)) childExpose -= destRect; } if (inDirtyList) { if (rect == q->rect()) { dirty.translate(dx, dy); } else { QRegion dirtyScrollRegion = dirty.intersected(scrollRect); if (!dirtyScrollRegion.isEmpty()) { dirty -= dirtyScrollRegion; dirtyScrollRegion.translate(dx, dy); dirty += dirtyScrollRegion; } } } if (!q->updatesEnabled()) return; if (!childExpose.isEmpty()) { wbs->markDirty(childExpose, q); isScrolled = true; } // Instead of using native scroll-on-screen, we copy from // backingstore, giving only one screen update for each // scroll, and a solid appearance wbs->markDirtyOnScreen(destRect, q, toplevelOffset); } }
void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &) { // Note: based on x11 implementation static const int XCOORD_MAX = 16383; static const int WRECT_MAX = 16383; Q_Q(QWidget); Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); /* There are up to four different coordinate systems here: Qt coordinate system for this widget. Symbian coordinate system for this widget (relative to wrect). Qt coordinate system for parent Symbian coordinate system for parent (relative to parent's wrect). */ QRect validRange(-XCOORD_MAX,-XCOORD_MAX, 2*XCOORD_MAX, 2*XCOORD_MAX); QRect wrectRange(-WRECT_MAX,-WRECT_MAX, 2*WRECT_MAX, 2*WRECT_MAX); QRect wrect; //xrect is the Symbian geometry of my widget. (starts out in parent's Qt coord sys, and ends up in parent's Symbian coord sys) QRect xrect = data.crect; const QWidget *const parent = q->parentWidget(); QRect parentWRect = parent->data->wrect; if (parentWRect.isValid()) { // parent is clipped, and we have to clip to the same limit as parent if (!parentWRect.contains(xrect)) { xrect &= parentWRect; wrect = xrect; //translate from parent's to my Qt coord sys wrect.translate(-data.crect.topLeft()); } //translate from parent's Qt coords to parent's X coords xrect.translate(-parentWRect.topLeft()); } else { // parent is not clipped, we may or may not have to clip if (data.wrect.isValid() && QRect(QPoint(),data.crect.size()).contains(data.wrect)) { // This is where the main optimization is: we are already // clipped, and if our clip is still valid, we can just // move our window, and do not need to move or clip // children QRect vrect = xrect & parent->rect(); vrect.translate(-data.crect.topLeft()); //the part of me that's visible through parent, in my Qt coords if (data.wrect.contains(vrect)) { xrect = data.wrect; xrect.translate(data.crect.topLeft()); if (data.winid) data.winid->SetExtent(TPoint(xrect.x(), xrect.y()), TSize(xrect.width(), xrect.height())); return; } } if (!validRange.contains(xrect)) { // we are too big, and must clip xrect &=wrectRange; wrect = xrect; wrect.translate(-data.crect.topLeft()); //parent's X coord system is equal to parent's Qt coord //sys, so we don't need to map xrect. } } // unmap if we are outside the valid window system coord system bool outsideRange = !xrect.isValid(); bool mapWindow = false; if (q->testAttribute(Qt::WA_OutsideWSRange) != outsideRange) { q->setAttribute(Qt::WA_OutsideWSRange, outsideRange); if (outsideRange) { if (data.winid) data.winid->DrawableWindow()->SetVisible(EFalse); q->setAttribute(Qt::WA_Mapped, false); } else if (!q->isHidden()) { mapWindow = true; } } if (outsideRange) return; bool jump = (data.wrect != wrect); data.wrect = wrect; // and now recursively for all children... for (int i = 0; i < children.size(); ++i) { QObject *object = children.at(i); if (object->isWidgetType()) { QWidget *w = static_cast<QWidget *>(object); if (!w->isWindow() && w->testAttribute(Qt::WA_WState_Created)) w->d_func()->setWSGeometry(jump); } } if (data.winid) { // move ourselves to the new position and map (if necessary) after // the movement. Rationale: moving unmapped windows is much faster // than moving mapped windows if (!parent->internalWinId()) xrect.translate(parent->mapTo(q->nativeParentWidget(), QPoint(0, 0))); data.winid->SetExtent(TPoint(xrect.x(), xrect.y()), TSize(xrect.width(), xrect.height())); } if (mapWindow and !dontShow) { q->setAttribute(Qt::WA_Mapped); if (q->internalWinId()) q->internalWinId()->DrawableWindow()->SetVisible(ETrue); } if (jump && data.winid) { RWindow *const window = static_cast<RWindow *>(data.winid->DrawableWindow()); window->Invalidate(TRect(0, 0, wrect.width(), wrect.height())); } }