From 1966b88611bb45d18d586847eeb3597d6e022eb7 Mon Sep 17 00:00:00 2001 From: Fabien Freling Date: Fri, 8 Oct 2010 18:37:25 +0200 Subject: Experimental support of the unified toolbar with the raster engine on Mac OS X. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-12615 Reviewed-by: Samuel Rødal --- src/gui/graphicsview/qgraphicsview_p.h | 2 +- src/gui/image/qnativeimage.cpp | 13 +- src/gui/kernel/qcocoaview_mac.mm | 11 +- src/gui/kernel/qt_cocoa_helpers_mac.mm | 7 + src/gui/kernel/qt_cocoa_helpers_mac_p.h | 2 + src/gui/kernel/qwidget.cpp | 14 +- src/gui/kernel/qwidget.h | 4 + src/gui/kernel/qwidget_p.h | 7 + src/gui/painting/painting.pri | 6 + src/gui/painting/qunifiedtoolbarsurface_mac.cpp | 233 ++++++++++++++++++++++++ src/gui/painting/qunifiedtoolbarsurface_mac_p.h | 95 ++++++++++ src/gui/painting/qwindowsurface.cpp | 4 +- src/gui/painting/qwindowsurface_p.h | 2 +- src/gui/painting/qwindowsurface_raster.cpp | 41 ++++- src/gui/painting/qwindowsurface_raster_p.h | 2 +- src/gui/widgets/qmainwindow.cpp | 11 +- src/gui/widgets/qmainwindowlayout_mac.mm | 12 ++ src/gui/widgets/qmainwindowlayout_p.h | 10 +- 18 files changed, 461 insertions(+), 15 deletions(-) create mode 100644 src/gui/painting/qunifiedtoolbarsurface_mac.cpp create mode 100644 src/gui/painting/qunifiedtoolbarsurface_mac_p.h diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h index 62be800..38c3bca 100644 --- a/src/gui/graphicsview/qgraphicsview_p.h +++ b/src/gui/graphicsview/qgraphicsview_p.h @@ -184,7 +184,7 @@ public: #ifdef Q_WS_MAC // QWidget::update() works slightly different on the Mac without the raster engine; // it's not part of our backing store so it needs special threatment. - if (QApplicationPrivate::graphics_system_name != "raster") { + if (QApplicationPrivate::graphics_system_name != QLatin1String("raster")) { // At this point either HIViewSetNeedsDisplay (Carbon) or setNeedsDisplay: YES (Cocoa) // is called, which means there's a pending update request. We want to dispatch it // now because otherwise graphics view updates would require two diff --git a/src/gui/image/qnativeimage.cpp b/src/gui/image/qnativeimage.cpp index 8446387..5978a1b 100644 --- a/src/gui/image/qnativeimage.cpp +++ b/src/gui/image/qnativeimage.cpp @@ -241,8 +241,19 @@ QNativeImage::QNativeImage(int width, int height, QImage::Format format, bool /* : image(width, height, format) { - uint cgflags = kCGImageAlphaNoneSkipFirst; + switch (format) { + case QImage::Format_ARGB32: + cgflags = kCGImageAlphaFirst; + break; + case QImage::Format_ARGB32_Premultiplied: + case QImage::Format_ARGB8565_Premultiplied: + case QImage::Format_ARGB6666_Premultiplied: + case QImage::Format_ARGB8555_Premultiplied: + case QImage::Format_ARGB4444_Premultiplied: + cgflags = kCGImageAlphaPremultipliedFirst; + break; + } #ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version cgflags |= kCGBitmapByteOrder32Host; diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index 8576f52..2016d40 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -534,7 +534,7 @@ static int qCocoaViewCount = 0; return; // We use a different graphics system. - if (QApplicationPrivate::graphicsSystem() != 0) { + if (QApplicationPrivate::graphicsSystem() != 0 && !qwidgetprivate->isInUnifiedToolbar) { // Qt handles the painting occuring inside the window. // Cocoa also keeps track of all widgets as NSView and therefore might @@ -558,6 +558,15 @@ static int qCocoaViewCount = 0; CGContextRef cg = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; qwidgetprivate->hd = cg; + + // We steal the CGContext for flushing in the unified toolbar with the raster engine. + if (QApplicationPrivate::graphicsSystem() != 0 && qwidgetprivate->isInUnifiedToolbar) { + qwidgetprivate->cgContext = cg; + qwidgetprivate->hasOwnContext = true; + qwidgetprivate->unifiedSurface->flush(qwidget, qwidgetprivate->ut_rg, qwidgetprivate->ut_pt); + return; + } + CGContextSaveGState(cg); if (qwidget->isVisible() && qwidget->updatesEnabled()) { //process the actual paint event. diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index 2dd3791..cce9daa 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -1561,6 +1561,13 @@ void qt_cocoaStackChildWindowOnTopOfOtherChildren(QWidget *childWidget) } } +void qt_mac_display(QWidget *widget) +{ + NSView *theNSView = qt_mac_nativeview_for(widget); + [theNSView display]; + return; +} + #endif // QT_MAC_USE_COCOA QT_END_NAMESPACE diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h index 5c23392..04c2d06 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h +++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h @@ -227,6 +227,8 @@ void qt_cocoaPostMessage(id target, SEL selector, int argCount=0, id arg1=0, id void qt_mac_post_retranslateAppMenu(); +void qt_mac_display(QWidget *widget); + QT_END_NAMESPACE #endif // QT_COCOA_HELPERS_MAC_P_H diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index cffad1d..2c31fd0 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -301,6 +301,9 @@ QWidgetPrivate::QWidgetPrivate(int version) drawRectOriginalAdded = false; originalDrawMethod = true; changeMethods = false; + hasOwnContext = false; + isInUnifiedToolbar = false; + unifiedSurface = 0; #endif // QT_MAC_USE_COCOA #ifdef QWIDGET_EXTRA_DEBUG static int count = 0; @@ -5316,6 +5319,14 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP if (rgn.isEmpty()) return; +#ifdef Q_WS_MAC + // We disable the rendering of QToolBar in the backingStore if + // it's supposed to be in the unified toolbar on Mac OS X. + if (backingStore && isInUnifiedToolbar) + return; +#endif // Q_WS_MAC + + Q_Q(QWidget); #ifndef QT_NO_GRAPHICSEFFECT if (graphicsEffect && graphicsEffect->isEnabled()) { @@ -5378,6 +5389,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP QPaintEngine *paintEngine = pdev->paintEngine(); if (paintEngine) { setRedirected(pdev, -offset); + #ifdef Q_WS_MAC // (Alien support) Special case for Mac when redirecting: If the paint device // is of the Widget type we need to set WA_WState_InPaintEvent since painting @@ -5420,7 +5432,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP //actually send the paint event QPaintEvent e(toBePainted); QCoreApplication::sendSpontaneousEvent(q, &e); -#if !defined(Q_WS_MAC) && !defined(Q_WS_QWS) +#if !defined(Q_WS_QWS) if (backingStore && !onScreen && !asRoot && (q->internalWinId() || !q->nativeParentWidget()->isWindow())) backingStore->markDirtyOnScreen(toBePainted, q, offset); #endif diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h index 980f40f..81b3618 100644 --- a/src/gui/kernel/qwidget.h +++ b/src/gui/kernel/qwidget.h @@ -97,6 +97,8 @@ class QWindowSurface; class QLocale; class QGraphicsProxyWidget; class QGraphicsEffect; +class QRasterWindowSurface; +class QUnifiedToolbarSurface; #if defined(Q_WS_X11) class QX11Info; #endif @@ -758,6 +760,8 @@ private: friend OSViewRef qt_mac_nativeview_for(const QWidget *w); friend void qt_event_request_window_change(QWidget *widget); friend bool qt_mac_sendMacEventToWidget(QWidget *widget, EventRef ref); + friend class QRasterWindowSurface; + friend class QUnifiedToolbarSurface; #endif #ifdef Q_WS_QWS friend class QWSBackingStore; diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index c943bd8..1433ce3 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -840,6 +840,13 @@ public: bool originalDrawMethod; // Do we need to change the methods? bool changeMethods; + bool hasOwnContext; + CGContextRef cgContext; + QRegion ut_rg; + QPoint ut_pt; + bool isInUnifiedToolbar; + QWindowSurface *unifiedSurface; + QPoint toolbar_offset; #endif void determineWindowClass(); void transferChildren(); diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 793d380..10c6f40 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -247,6 +247,12 @@ symbian { QMAKE_CXXFLAGS.ARMCC *= -O3 } +mac { + HEADERS += painting/qunifiedtoolbarsurface_mac_p.h + SOURCES += painting/qunifiedtoolbarsurface_mac.cpp +} + + NEON_SOURCES += painting/qdrawhelper_neon.cpp NEON_HEADERS += painting/qdrawhelper_neon_p.h NEON_ASM += ../3rdparty/pixman/pixman-arm-neon-asm.S painting/qdrawhelper_neon_asm.S diff --git a/src/gui/painting/qunifiedtoolbarsurface_mac.cpp b/src/gui/painting/qunifiedtoolbarsurface_mac.cpp new file mode 100644 index 0000000..722355e --- /dev/null +++ b/src/gui/painting/qunifiedtoolbarsurface_mac.cpp @@ -0,0 +1,233 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qunifiedtoolbarsurface_mac_p.h" +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +QUnifiedToolbarSurface::QUnifiedToolbarSurface(QWidget *widget) + : QRasterWindowSurface(widget, false), d_ptr(new QUnifiedToolbarSurfacePrivate) +{ + d_ptr->image = 0; + d_ptr->inSetGeometry = false; + setStaticContentsSupport(true); + + setGeometry(QRect(QPoint(0, 0), QSize(widget->width(), 100))); // FIXME: Fix height. +} + +QUnifiedToolbarSurface::~QUnifiedToolbarSurface() +{ + if (d_ptr->image) + delete d_ptr->image; +} + +QPaintDevice *QUnifiedToolbarSurface::paintDevice() +{ + return &d_ptr->image->image; +} + +void QUnifiedToolbarSurface::recursiveRedirect(QObject *object, const QPoint &offset) +{ + if (object != 0) { + if (object->isWidgetType()) { + QWidget *widget = qobject_cast(object); + widget->d_func()->unifiedSurface = this; + widget->d_func()->isInUnifiedToolbar = true; + widget->d_func()->toolbar_offset = offset; + } + + for (int i = 0; i < object->children().size(); ++i) { + recursiveRedirect(object->children().at(i), offset); + } + } +} + +void QUnifiedToolbarSurface::insertToolbar(QWidget *toolbar, const QPoint &offset) +{ + setGeometry(QRect(QPoint(0, 0), QSize(offset.x() + toolbar->width(), 100))); // FIXME + recursiveRedirect(toolbar, offset); +// toolbar->d_func()->toolbar_offset = offset; +} + +void QUnifiedToolbarSurface::setGeometry(const QRect &rect) +{ + QWindowSurface::setGeometry(rect); + Q_D(QUnifiedToolbarSurface); + d->inSetGeometry = true; + if (d->image == 0 || d->image->width() < rect.width() || d->image->height() < rect.height()) + prepareBuffer(QImage::Format_ARGB32_Premultiplied, window()); + d->inSetGeometry = false; +} + +void QUnifiedToolbarSurface::beginPaint(const QRegion &rgn) +{ + QPainter p(&d_ptr->image->image); + p.setCompositionMode(QPainter::CompositionMode_Source); + const QVector rects = rgn.rects(); + const QColor blank = Qt::transparent; + for (QVector::const_iterator it = rects.begin(); it != rects.end(); ++it) { + p.fillRect(*it, blank); + } +} + +void QUnifiedToolbarSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset) +{ + Q_D(QUnifiedToolbarSurface); + + if (!d->image || rgn.rectCount() == 0) { + return; + } + + Q_UNUSED(offset); + + // Get a context for the widget. + CGContextRef context; + if (!(widget->d_func()->hasOwnContext)) { + widget->d_func()->ut_rg = rgn; + widget->d_func()->ut_pt = offset; + qt_mac_display(widget); + return; + } else { + context = widget->d_func()->cgContext; + widget->render(widget->d_func()->unifiedSurface->paintDevice(), widget->d_func()->toolbar_offset, QRegion(), QWidget::DrawChildren); + } + + CGContextSaveGState(context); + + int areaX = widget->geometry().x() + widget->d_func()->toolbar_offset.x(); + int areaY = widget->geometry().y() + widget->d_func()->toolbar_offset.y(); + int areaWidth = widget->geometry().width(); + int areaHeight = widget->geometry().height(); + const CGRect area = CGRectMake(areaX, areaY, areaWidth, areaHeight); + + // Clip to region. + const QVector &rects = rgn.rects(); + for (int i = 0; i < rects.size(); ++i) { + const QRect &rect = rects.at(i); + // CGContextAddRect(context, CGRectMake(rect.x(), rect.y(), rect.width(), rect.height())); + CGContextAddRect(context, CGRectMake(0, 0, 1000, 1000)); //FIXME: Set correct size. + } + CGContextAddRect(context, area); + CGContextClip(context); + + + CGImageRef image = CGBitmapContextCreateImage(d->image->cg); + CGImageRef subImage = CGImageCreateWithImageInRect(image, area); + + const CGRect drawingArea = CGRectMake(0, 0, areaWidth, areaHeight); + qt_mac_drawCGImage(context, &drawingArea, subImage); + + CGImageRelease(subImage); + CGImageRelease(image); + + CGContextFlush(context); + + // Restore context. + CGContextRestoreGState(context); + widget->d_func()->hasOwnContext = false; +} + +void QUnifiedToolbarSurface::prepareBuffer(QImage::Format format, QWidget *widget) +{ + Q_D(QUnifiedToolbarSurface); + + int width = geometry().width(); + int height = geometry().height(); + if (d->image) { + width = qMax(d->image->width(), width); + height = qMax(d->image->height(), height); + } + + if (width == 0 || height == 0) { + delete d->image; + d->image = 0; + return; + } + + QNativeImage *oldImage = d->image; + + d->image = new QNativeImage(width, height, format, false, widget); + + if (oldImage && d->inSetGeometry && hasStaticContents()) { + // Make sure we use the const version of bits() (no detach). + const uchar *src = const_cast(oldImage->image).bits(); + uchar *dst = d->image->image.bits(); + + const int srcBytesPerLine = oldImage->image.bytesPerLine(); + const int dstBytesPerLine = d->image->image.bytesPerLine(); + const int bytesPerPixel = oldImage->image.depth() >> 3; + + QRegion staticRegion(staticContents()); + // Make sure we're inside the boundaries of the old image. + staticRegion &= QRect(0, 0, oldImage->image.width(), oldImage->image.height()); + const QVector &rects = staticRegion.rects(); + const QRect *srcRect = rects.constData(); + + // Copy the static content of the old image into the new one. + int numRectsLeft = rects.size(); + do { + const int bytesOffset = srcRect->x() * bytesPerPixel; + const int dy = srcRect->y(); + + // Adjust src and dst to point to the right offset. + const uchar *s = src + dy * srcBytesPerLine + bytesOffset; + uchar *d = dst + dy * dstBytesPerLine + bytesOffset; + const int numBytes = srcRect->width() * bytesPerPixel; + + int numScanLinesLeft = srcRect->height(); + do { + ::memcpy(d, s, numBytes); + d += dstBytesPerLine; + s += srcBytesPerLine; + } while (--numScanLinesLeft); + + ++srcRect; + } while (--numRectsLeft); + } + + delete oldImage; +} + +QT_END_NAMESPACE diff --git a/src/gui/painting/qunifiedtoolbarsurface_mac_p.h b/src/gui/painting/qunifiedtoolbarsurface_mac_p.h new file mode 100644 index 0000000..d7805e8 --- /dev/null +++ b/src/gui/painting/qunifiedtoolbarsurface_mac_p.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QUNIFIEDTOOLBARSURFACE_MAC_P_H +#define QUNIFIEDTOOLBARSURFACE_MAC_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QNativeImage; + + +class QUnifiedToolbarSurfacePrivate +{ +public: + QNativeImage *image; + uint inSetGeometry : 1; +}; + +class Q_GUI_EXPORT QUnifiedToolbarSurface : public QRasterWindowSurface +{ +public: + QUnifiedToolbarSurface(QWidget *widget); + ~QUnifiedToolbarSurface(); + + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void setGeometry(const QRect &rect); + void beginPaint(const QRegion &rgn); + void insertToolbar(QWidget *toolbar, const QPoint &offset); + +private: + QPaintDevice *paintDevice(); + void prepareBuffer(QImage::Format format, QWidget *widget); + void recursiveRedirect(QObject *widget, const QPoint &offset); + + Q_DECLARE_PRIVATE(QUnifiedToolbarSurface) + QScopedPointer d_ptr; +}; + +QT_END_NAMESPACE + +#endif // QUNIFIEDTOOLBARSURFACE_MAC_P_H diff --git a/src/gui/painting/qwindowsurface.cpp b/src/gui/painting/qwindowsurface.cpp index 02a8b80..8cf3977 100644 --- a/src/gui/painting/qwindowsurface.cpp +++ b/src/gui/painting/qwindowsurface.cpp @@ -114,11 +114,11 @@ public: /*! Constructs an empty surface for the given top-level \a window. */ -QWindowSurface::QWindowSurface(QWidget *window) +QWindowSurface::QWindowSurface(QWidget *window, bool setDefaultSurface) : d_ptr(new QWindowSurfacePrivate(window)) { if (!QApplicationPrivate::runtime_graphics_system) { - if(window) + if(setDefaultSurface && window) window->setWindowSurface(this); } } diff --git a/src/gui/painting/qwindowsurface_p.h b/src/gui/painting/qwindowsurface_p.h index 6171ae8..ab84527 100644 --- a/src/gui/painting/qwindowsurface_p.h +++ b/src/gui/painting/qwindowsurface_p.h @@ -67,7 +67,7 @@ class QWindowSurfacePrivate; class Q_GUI_EXPORT QWindowSurface { public: - QWindowSurface(QWidget *window); + QWindowSurface(QWidget *window, bool setDefaultSurface = true); virtual ~QWindowSurface(); QWidget *window() const; diff --git a/src/gui/painting/qwindowsurface_raster.cpp b/src/gui/painting/qwindowsurface_raster.cpp index 6a2cb1e..99f8597 100644 --- a/src/gui/painting/qwindowsurface_raster.cpp +++ b/src/gui/painting/qwindowsurface_raster.cpp @@ -64,6 +64,9 @@ #ifdef Q_WS_MAC #include +#include +#include +#include #endif QT_BEGIN_NAMESPACE @@ -82,8 +85,8 @@ public: uint inSetGeometry : 1; }; -QRasterWindowSurface::QRasterWindowSurface(QWidget *window) - : QWindowSurface(window), d_ptr(new QRasterWindowSurfacePrivate) +QRasterWindowSurface::QRasterWindowSurface(QWidget *window, bool setDefaultSurface) + : QWindowSurface(window, setDefaultSurface), d_ptr(new QRasterWindowSurfacePrivate) { #ifdef Q_WS_X11 d_ptr->gc = XCreateGC(X11->display, window->handle(), 0, 0); @@ -248,6 +251,23 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi #ifdef Q_WS_MAC + // Unified toolbar hack. + QMainWindow* mWindow = qobject_cast(widget->window()); + if (mWindow) { + QMainWindowLayout *mLayout = qobject_cast(mWindow->layout()); + QList 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->flush(tbWidget, rgn, offset); + } + } + } + } + Q_UNUSED(offset); // Get a context for the widget. #ifndef QT_MAC_USE_COCOA @@ -318,6 +338,23 @@ void QRasterWindowSurface::setGeometry(const QRect &rect) prepareBuffer(QNativeImage::systemFormat(), window()); } d->inSetGeometry = false; +#ifdef Q_WS_MAC + QMainWindow* mWindow = qobject_cast(window()); + if (mWindow) { + QMainWindowLayout *mLayout = qobject_cast(mWindow->layout()); + QList 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 } // from qwindowsurface.cpp diff --git a/src/gui/painting/qwindowsurface_raster_p.h b/src/gui/painting/qwindowsurface_raster_p.h index 2b932a9..a7c3b9f 100644 --- a/src/gui/painting/qwindowsurface_raster_p.h +++ b/src/gui/painting/qwindowsurface_raster_p.h @@ -97,7 +97,7 @@ class QNativeImage; class Q_GUI_EXPORT QRasterWindowSurface : public QWindowSurface { public: - QRasterWindowSurface(QWidget *widget); + QRasterWindowSurface(QWidget *widget, bool setDefaultSurface = true); ~QRasterWindowSurface(); QPaintDevice *paintDevice(); diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp index 4ca11b0..861cfaa 100644 --- a/src/gui/widgets/qmainwindow.cpp +++ b/src/gui/widgets/qmainwindow.cpp @@ -1516,14 +1516,19 @@ void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool set) if (!isWindow() || d->useHIToolBar == set || QSysInfo::MacintoshVersion < QSysInfo::MV_10_3) return; - // ### Disable the unified toolbar when using anything but the native graphics system. - // ### Disable when using alien widgets as well - if (windowSurface() || testAttribute(Qt::WA_NativeWindow) == false) + // ### Disable when using alien widgets + if (testAttribute(Qt::WA_NativeWindow) == false) { return; + } d->useHIToolBar = set; createWinId(); // We need the hiview for down below. + // Activate the unified toolbar with the raster engine. + if (windowSurface()) { + d->layout->unifiedSurface = new QUnifiedToolbarSurface(this); + } + d->layout->updateHIToolBarStatus(); // Enabling the unified toolbar clears the opaque size grip setting, update it. d->macUpdateOpaqueSizeGrip(); diff --git a/src/gui/widgets/qmainwindowlayout_mac.mm b/src/gui/widgets/qmainwindowlayout_mac.mm index 1bfc746..b2c4cea 100644 --- a/src/gui/widgets/qmainwindowlayout_mac.mm +++ b/src/gui/widgets/qmainwindowlayout_mac.mm @@ -49,6 +49,7 @@ #else #include #import +#include #endif QT_BEGIN_NAMESPACE @@ -408,6 +409,7 @@ void QMainWindowLayout::insertIntoMacToolbar(QToolBar *before, QToolBar *toolbar beforeIndex = qtoolbarsInUnifiedToolbarList.size(); int toolbarIndex = qtoolbarsInUnifiedToolbarList.indexOf(toolbar); + #ifndef QT_MAC_USE_COCOA HIToolbarRef macToolbar = NULL; if ((GetWindowToolbar(window, &macToolbar) == noErr) && !macToolbar) { @@ -444,6 +446,16 @@ void QMainWindowLayout::insertIntoMacToolbar(QToolBar *before, QToolBar *toolbar #endif } qtoolbarsInUnifiedToolbarList.insert(beforeIndex, toolbar); + + // Adding to the unified toolbar surface for the raster engine. + if (layoutState.mainWindow->windowSurface()) { + QPoint offset(0, 0); + for (int i = 0; i < beforeIndex; ++i) { + offset.setX(offset.x() + qtoolbarsInUnifiedToolbarList.at(i)->size().width()); + } + unifiedSurface->insertToolbar(toolbar, offset); + } + #ifndef QT_MAC_USE_COCOA QCFType outItem; const QObject *stupidArray[] = { toolbar, this }; diff --git a/src/gui/widgets/qmainwindowlayout_p.h b/src/gui/widgets/qmainwindowlayout_p.h index e1b981c..3eb2545 100644 --- a/src/gui/widgets/qmainwindowlayout_p.h +++ b/src/gui/widgets/qmainwindowlayout_p.h @@ -85,7 +85,11 @@ typedef HIObjectRef HIToolbarItemRef; typedef const void * CFTypeRef; typedef const struct __CFString * CFStringRef; -#endif +# ifdef QT_MAC_USE_COCOA +#include +# endif // QT_MAC_USE_COCOA + +#endif // Q_WS_MAC QT_BEGIN_NAMESPACE @@ -337,7 +341,9 @@ public: bool useHIToolBar; void syncUnifiedToolbarVisibility(); bool blockVisiblityCheck; -#endif + + QUnifiedToolbarSurface *unifiedSurface; +#endif // Q_WS_MAC }; QT_END_NAMESPACE -- cgit v0.12