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);
}
Esempio n. 2
0
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
    }
}
Esempio n. 3
0
/*!
    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);
                }
            }
        }
    }
}
Esempio n. 6
0
/*!
    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);
}
Esempio n. 7
0
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;
}
Esempio n. 11
0
/*!
    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;
}
Esempio n. 12
0
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
    }
}
Esempio n. 13
0
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;
}
Esempio n. 14
0
void QS60WindowSurface::flush(QWidget *widget, const QRegion &region, 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();
    }
}
Esempio n. 15
0
/*!
    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();
}
Esempio n. 16
0
/*!
    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 &region, 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);
}
Esempio n. 17
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
}
Esempio n. 18
0
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)));
    }
}
Esempio n. 19
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);
        }
    }
}
Esempio n. 20
0
//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);
    }
}
Esempio n. 21
0
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()));
    }
}