diff options
-rw-r--r-- | src/gui/kernel/qcocoasharedwindowmethods_mac_p.h | 16 | ||||
-rw-r--r-- | src/gui/kernel/qcocoaview_mac.mm | 111 | ||||
-rw-r--r-- | src/gui/kernel/qcocoawindowdelegate_mac.mm | 21 | ||||
-rw-r--r-- | src/gui/kernel/qt_cocoa_helpers_mac.mm | 24 | ||||
-rw-r--r-- | src/gui/kernel/qt_cocoa_helpers_mac_p.h | 32 | ||||
-rw-r--r-- | src/gui/kernel/qwidget.cpp | 42 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_p.h | 14 | ||||
-rw-r--r-- | src/gui/painting/qgraphicssystemfactory.cpp | 2 | ||||
-rw-r--r-- | src/gui/painting/qunifiedtoolbarsurface_mac.cpp | 120 | ||||
-rw-r--r-- | src/gui/painting/qunifiedtoolbarsurface_mac_p.h | 14 | ||||
-rw-r--r-- | src/gui/painting/qwindowsurface_raster.cpp | 50 | ||||
-rw-r--r-- | src/gui/painting/qwindowsurface_raster_p.h | 11 | ||||
-rw-r--r-- | src/gui/widgets/qmainwindow.cpp | 13 | ||||
-rw-r--r-- | src/gui/widgets/qmainwindowlayout_mac.mm | 6 |
14 files changed, 330 insertions, 146 deletions
diff --git a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h index c4b74c6..7d41f3d 100644 --- a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h +++ b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h @@ -533,22 +533,6 @@ QT_END_NAMESPACE return de.isAccepted(); } -- (void)displayIfNeeded -{ - - QWidget *qwidget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self]; - if (qwidget == 0) { - [super displayIfNeeded]; - return; - } - - if (QApplicationPrivate::graphicsSystem() != 0) { - if (QWidgetBackingStore *bs = qt_widget_private(qwidget)->maybeBackingStore()) - bs->sync(qwidget, qwidget->rect()); - } - [super displayIfNeeded]; -} - // This is a hack and it should be removed once we find the real cause for // the painting problems. // We have a static variable that signals if we have been called before or not. diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index 5e8b37e..43eb072 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -51,6 +51,8 @@ #include <private/qmacinputcontext_p.h> #include <private/qevent_p.h> #include <private/qbackingstore_p.h> +#include <private/qwindowsurface_raster_p.h> +#include <private/qunifiedtoolbarsurface_mac_p.h> #include <qscrollarea.h> #include <qhash.h> @@ -246,8 +248,79 @@ static int qCocoaViewCount = 0; { if (!qwidget) return; - if (QApplicationPrivate::graphicsSystem() != 0 && !qwidgetprivate->isInUnifiedToolbar) { - // INVARIANT: We use a different graphics system. + + // Getting context. + CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; + qt_mac_retain_graphics_context(context); + + // We use a different graphics system. + if (QApplicationPrivate::graphicsSystem() != 0) { + + // Raster engine. + if (QApplicationPrivate::graphics_system_name == QLatin1String("raster")) { + + if (!qwidgetprivate->isInUnifiedToolbar) { + + // Qt handles the painting occuring inside the window. + // Cocoa also keeps track of all widgets as NSView and therefore might + // ask for a repainting of a widget even if Qt is already taking care of it. + // + // The only valid reason for Cocoa to call drawRect: is for window manipulation + // (ie. resize, ...). + // + // Qt will then forward the update to the children. + if (!qwidget->isWindow()) { + qt_mac_release_graphics_context(context); + return; + } + + QRasterWindowSurface *winSurface = dynamic_cast<QRasterWindowSurface *>(qwidget->windowSurface()); + if (!winSurface || !winSurface->needsFlush) { + qt_mac_release_graphics_context(context); + return; + } + + // Clip to region. + const QVector<QRect> &rects = winSurface->regionToFlush.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())); + } + CGContextClip(context); + + QRect r = winSurface->regionToFlush.boundingRect(); + const CGRect area = CGRectMake(r.x(), r.y(), r.width(), r.height()); + + qt_mac_draw_image(context, winSurface->imageContext(), area, area); + + winSurface->needsFlush = false; + winSurface->regionToFlush = QRegion(); + + } else { + + QUnifiedToolbarSurface *unifiedSurface = qwidgetprivate->unifiedSurface; + if (!unifiedSurface || !qwidgetprivate->flushRequested) { + qt_mac_release_graphics_context(context); + return; + } + + int areaX = qwidgetprivate->toolbar_offset.x(); + int areaY = qwidgetprivate->toolbar_offset.y(); + int areaWidth = qwidget->geometry().width(); + int areaHeight = qwidget->geometry().height(); + const CGRect area = CGRectMake(areaX, areaY, areaWidth, areaHeight); + const CGRect drawingArea = CGRectMake(0, 0, areaWidth, areaHeight); + + qt_mac_draw_image(context, unifiedSurface->imageContext(), area, drawingArea); + + qwidgetprivate->flushRequested = false; + + } + + CGContextFlush(context); + qt_mac_release_graphics_context(context); + return; + } // Qt handles the painting occuring inside the window. // Cocoa also keeps track of all widgets as NSView and therefore might @@ -263,25 +336,14 @@ static int qCocoaViewCount = 0; } // Since we don't want to use the native engine, we must exit, however - // widgets that are set to paint on screen, spesifically QGLWidget, + // widgets that are set to paint on screen, specifically QGLWidget, // requires the following code to execute in order to be drawn. if (!qwidget->testAttribute(Qt::WA_PaintOnScreen)) return; } - CGContextRef cg = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; - CGContextRetain(cg); - qwidgetprivate->hd = cg; - - // We steal the CGContext for flushing in the unified toolbar with the raster engine. - if (QApplicationPrivate::graphicsSystem() != 0 && qwidgetprivate->isInUnifiedToolbar && qwidgetprivate->unifiedSurface) { - qwidgetprivate->cgContext = cg; - qwidgetprivate->hasOwnContext = true; - qwidgetprivate->unifiedSurface->flush(qwidget, qwidgetprivate->ut_rg, qwidgetprivate->ut_pt); - return; - } - - CGContextSaveGState(cg); + // Native engine. + qwidgetprivate->hd = context; if (qwidget->isVisible() && qwidget->updatesEnabled()) { //process the actual paint event. if (qwidget->testAttribute(Qt::WA_WState_InPaintEvent)) @@ -316,18 +378,18 @@ static int qCocoaViewCount = 0; engine->setSystemClip(qrgn); if (qwidgetprivate->extra && qwidgetprivate->extra->hasMask) { CGRect widgetRect = CGRectMake(0, 0, qwidget->width(), qwidget->height()); - CGContextTranslateCTM (cg, 0, widgetRect.size.height); - CGContextScaleCTM(cg, 1, -1); + CGContextTranslateCTM (context, 0, widgetRect.size.height); + CGContextScaleCTM(context, 1, -1); if (qwidget->isWindow()) - CGContextClearRect(cg, widgetRect); - CGContextClipToMask(cg, widgetRect, qwidgetprivate->extra->imageMask); - CGContextScaleCTM(cg, 1, -1); - CGContextTranslateCTM (cg, 0, -widgetRect.size.height); + CGContextClearRect(context, widgetRect); + CGContextClipToMask(context, widgetRect, qwidgetprivate->extra->imageMask); + CGContextScaleCTM(context, 1, -1); + CGContextTranslateCTM (context, 0, -widgetRect.size.height); } if (qwidget->isWindow() && !qwidgetprivate->isOpaque && !qwidget->testAttribute(Qt::WA_MacBrushedMetal)) { - CGContextClearRect(cg, NSRectToCGRect(aRect)); + CGContextClearRect(context, NSRectToCGRect(aRect)); } qwidget->setAttribute(Qt::WA_WState_InPaintEvent, false); @@ -358,8 +420,7 @@ static int qCocoaViewCount = 0; " widget outside of the PaintEvent"); } qwidgetprivate->hd = 0; - CGContextRestoreGState(cg); - CGContextRelease(cg); + qt_mac_release_graphics_context(context); } - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent diff --git a/src/gui/kernel/qcocoawindowdelegate_mac.mm b/src/gui/kernel/qcocoawindowdelegate_mac.mm index b8be627..1faf068 100644 --- a/src/gui/kernel/qcocoawindowdelegate_mac.mm +++ b/src/gui/kernel/qcocoawindowdelegate_mac.mm @@ -48,6 +48,9 @@ #include <qlayout.h> #include <qcoreapplication.h> #include <qmenubar.h> +#include <QMainWindow> +#include <QToolBar> +#include <private/qmainwindowlayout_p.h> QT_BEGIN_NAMESPACE extern QWidgetData *qt_qwidget_data(QWidget *); // qwidget.cpp @@ -215,6 +218,24 @@ static void cleanupCocoaWindowDelegate() QWidgetPrivate::qt_mac_update_sizer(qwidget); [self syncSizeForWidget:qwidget toSize:newSize fromSize:oldSize]; } + + // We force the repaint to be synchronized with the resize of the window. + // Otherwise, the resize looks sluggish because we paint one event loop later. + if ([[window contentView] inLiveResize]) { + qwidget->repaint(); + + // We need to repaint the toolbar as well. + QMainWindow* mWindow = qobject_cast<QMainWindow*>(qwidget->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); + toolbar->repaint(); + } + } + } } - (void)windowDidMove:(NSNotification *)notification diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index f4a1ea5..32123ee 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -1794,7 +1794,29 @@ void qt_mac_display(QWidget *widget) { NSView *theNSView = qt_mac_nativeview_for(widget); [theNSView display]; - return; +} + +void qt_mac_setNeedsDisplay(QWidget *widget) +{ + NSView *theNSView = qt_mac_nativeview_for(widget); + [theNSView setNeedsDisplay:YES]; +} + +void qt_mac_setNeedsDisplayInRect(QWidget *widget, QRegion region) +{ + NSView *theNSView = qt_mac_nativeview_for(widget); + if (region.isEmpty()) { + [theNSView setNeedsDisplay:YES]; + return; + } + + QVector<QRect> rects = region.rects(); + for (int i = 0; i < rects.count(); ++i) { + const QRect &rect = rects.at(i); + NSRect nsrect = NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height()); + [theNSView setNeedsDisplayInRect:nsrect]; + } + } #endif // QT_MAC_USE_COCOA diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h index 334d9e8..a49753a 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h +++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h @@ -301,7 +301,39 @@ public: void qt_mac_post_retranslateAppMenu(); +#ifdef QT_MAC_USE_COCOA void qt_mac_display(QWidget *widget); +void qt_mac_setNeedsDisplay(QWidget *widget); +void qt_mac_setNeedsDisplayInRect(QWidget *widget, QRegion region); +#endif // QT_MAC_USE_COCOA + + +// Utility functions to ease the use of Core Graphics contexts. + +inline void qt_mac_retain_graphics_context(CGContextRef context) +{ + CGContextRetain(context); + CGContextSaveGState(context); +} + +inline void qt_mac_release_graphics_context(CGContextRef context) +{ + CGContextRestoreGState(context); + CGContextRelease(context); +} + +inline void qt_mac_draw_image(CGContextRef context, CGContextRef imageContext, CGRect area, CGRect drawingArea) +{ + CGImageRef image = CGBitmapContextCreateImage(imageContext); + CGImageRef subImage = CGImageCreateWithImageInRect(image, area); + + CGContextTranslateCTM (context, 0, drawingArea.origin.y + CGRectGetMaxY(drawingArea)); + CGContextScaleCTM(context, 1, -1); + CGContextDrawImage(context, drawingArea, subImage); + + CGImageRelease(subImage); + CGImageRelease(image); +} QT_END_NAMESPACE diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 37d7147..4e18940 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -328,9 +328,10 @@ QWidgetPrivate::QWidgetPrivate(int version) drawRectOriginalAdded = false; originalDrawMethod = true; changeMethods = false; - hasOwnContext = false; isInUnifiedToolbar = false; unifiedSurface = 0; + toolbar_ancestor = 0; + flushRequested = false; touchEventsEnabled = false; #endif // QT_MAC_USE_COCOA #ifdef QWIDGET_EXTRA_DEBUG @@ -1385,6 +1386,16 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) QApplication::postEvent(q, new QEvent(QEvent::PolishRequest)); extraPaintEngine = 0; + +#ifdef QT_MAC_USE_COCOA + // If we add a child to the unified toolbar, we have to redirect the painting. + if (parentWidget && parentWidget->d_func() && parentWidget->d_func()->isInUnifiedToolbar) { + if (parentWidget->d_func()->unifiedSurface) { + QWidget *toolbar = parentWidget->d_func()->toolbar_ancestor; + parentWidget->d_func()->unifiedSurface->recursiveRedirect(toolbar, toolbar, toolbar->d_func()->toolbar_offset); + } + } +#endif // QT_MAC_USE_COCOA } @@ -2099,6 +2110,11 @@ void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirt if (disableSubtractOpaqueSiblings || q->isWindow()) return; +#ifdef QT_MAC_USE_COCOA + if (q->d_func()->isInUnifiedToolbar) + return; +#endif // QT_MAC_USE_COCOA + QRect clipBoundingRect; bool dirtyClipBoundingRect = true; @@ -10391,6 +10407,12 @@ void QWidget::repaint(const QRect &rect) return; if (hasBackingStoreSupport()) { +#ifdef QT_MAC_USE_COCOA + if (qt_widget_private(this)->isInUnifiedToolbar) { + qt_widget_private(this)->unifiedSurface->renderToolbar(this, true); + return; + } +#endif // QT_MAC_USE_COCOA QTLWExtra *tlwExtra = window()->d_func()->maybeTopData(); if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) { tlwExtra->inRepaint = true; @@ -10420,6 +10442,12 @@ void QWidget::repaint(const QRegion &rgn) return; if (hasBackingStoreSupport()) { +#ifdef QT_MAC_USE_COCOA + if (qt_widget_private(this)->isInUnifiedToolbar) { + qt_widget_private(this)->unifiedSurface->renderToolbar(this, true); + return; + } +#endif // QT_MAC_USE_COCOA QTLWExtra *tlwExtra = window()->d_func()->maybeTopData(); if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) { tlwExtra->inRepaint = true; @@ -10477,6 +10505,12 @@ void QWidget::update(const QRect &rect) } if (hasBackingStoreSupport()) { +#ifdef QT_MAC_USE_COCOA + if (qt_widget_private(this)->isInUnifiedToolbar) { + qt_widget_private(this)->unifiedSurface->renderToolbar(this, true); + return; + } +#endif // QT_MAC_USE_COCOA QTLWExtra *tlwExtra = window()->d_func()->maybeTopData(); if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) tlwExtra->backingStore->markDirty(rect, this); @@ -10501,6 +10535,12 @@ void QWidget::update(const QRegion &rgn) } if (hasBackingStoreSupport()) { +#ifdef QT_MAC_USE_COCOA + if (qt_widget_private(this)->isInUnifiedToolbar) { + qt_widget_private(this)->unifiedSurface->renderToolbar(this, true); + return; + } +#endif // QT_MAC_USE_COCOA QTLWExtra *tlwExtra = window()->d_func()->maybeTopData(); if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) tlwExtra->backingStore->markDirty(rgn, this); diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index dd9bb49..ea55acd 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -113,6 +113,8 @@ class QWidgetItemV2; class QStyle; +class QUnifiedToolbarSurface; + class Q_AUTOTEST_EXPORT QWidgetBackingStoreTracker { @@ -856,15 +858,15 @@ public: bool originalDrawMethod; // Do we need to change the methods? bool changeMethods; - bool hasOwnContext; - CGContextRef cgContext; - QRegion ut_rg; - QPoint ut_pt; + + // Unified toolbar variables bool isInUnifiedToolbar; - QWindowSurface *unifiedSurface; + QUnifiedToolbarSurface *unifiedSurface; QPoint toolbar_offset; + QWidget *toolbar_ancestor; + bool flushRequested; bool touchEventsEnabled; -#endif +#endif // QT_MAC_USE_COCOA void determineWindowClass(); void transferChildren(); bool qt_mac_dnd_event(uint, DragRef); diff --git a/src/gui/painting/qgraphicssystemfactory.cpp b/src/gui/painting/qgraphicssystemfactory.cpp index 5605fc1..62a60d7 100644 --- a/src/gui/painting/qgraphicssystemfactory.cpp +++ b/src/gui/painting/qgraphicssystemfactory.cpp @@ -45,6 +45,7 @@ #include "qmutex.h" #include "qapplication.h" +#include <private/qapplication_p.h> #include "qgraphicssystem_raster_p.h" #include "qgraphicssystem_runtime_p.h" #include "qdebug.h" @@ -79,6 +80,7 @@ QGraphicsSystem *QGraphicsSystemFactory::create(const QString& key) } #endif + QApplicationPrivate::graphics_system_name = system; if (system == QLatin1String("raster")) return new QRasterGraphicsSystem; else if (system == QLatin1String("runtime")) diff --git a/src/gui/painting/qunifiedtoolbarsurface_mac.cpp b/src/gui/painting/qunifiedtoolbarsurface_mac.cpp index e7434c7..63364f3 100644 --- a/src/gui/painting/qunifiedtoolbarsurface_mac.cpp +++ b/src/gui/painting/qunifiedtoolbarsurface_mac.cpp @@ -71,7 +71,7 @@ QPaintDevice *QUnifiedToolbarSurface::paintDevice() return &d_ptr->image->image; } -void QUnifiedToolbarSurface::recursiveRedirect(QObject *object, const QPoint &offset) +void QUnifiedToolbarSurface::recursiveRedirect(QObject *object, QWidget *parent_toolbar, const QPoint &offset) { if (object != 0) { if (object->isWidgetType()) { @@ -83,9 +83,10 @@ void QUnifiedToolbarSurface::recursiveRedirect(QObject *object, const QPoint &of 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), offset); + recursiveRedirect(object->children().at(i), parent_toolbar, offset); } } } @@ -95,7 +96,35 @@ void QUnifiedToolbarSurface::recursiveRedirect(QObject *object, const QPoint &of void QUnifiedToolbarSurface::insertToolbar(QWidget *toolbar, const QPoint &offset) { setGeometry(QRect(QPoint(0, 0), QSize(offset.x() + toolbar->width(), 100))); // FIXME - recursiveRedirect(toolbar, offset); + recursiveRedirect(toolbar, toolbar, offset); +} + +// 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::removeToolbar(QToolBar *toolbar) +{ + recursiveRemoval(toolbar); } void QUnifiedToolbarSurface::setGeometry(const QRect &rect) @@ -127,70 +156,17 @@ void QUnifiedToolbarSurface::updateToolbarOffset(QWidget *widget) mlayout->updateUnifiedToolbarOffset(); } -void QUnifiedToolbarSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset) +void QUnifiedToolbarSurface::flush(QWidget *widget) { Q_D(QUnifiedToolbarSurface); - QRegion flushingRegion(widget->rect()); - - if (!d->image || rgn.rectCount() == 0) { + if (!d->image) 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; + if (widget->d_func()->flushRequested) { + // We call display: directly to avoid flickering in the toolbar. qt_mac_display(widget); - return; - } else { - // We render the content of the toolbar in the surface. - updateToolbarOffset(widget); - QRect beginPaintRect(widget->d_func()->toolbar_offset.x(), widget->d_func()->toolbar_offset.y(), widget->geometry().width(), widget->geometry().height()); - QRegion beginPaintRegion(beginPaintRect); - - context = widget->d_func()->cgContext; - beginPaint(beginPaintRegion); - widget->render(widget->d_func()->unifiedSurface->paintDevice(), widget->d_func()->toolbar_offset, QRegion(), QWidget::DrawChildren); } - - CGContextSaveGState(context); - - int areaX = widget->d_func()->toolbar_offset.x(); - int areaY = 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<QRect> &rects = flushingRegion.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, 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); - CGContextRelease(context); - widget->d_func()->cgContext = 0; - widget->d_func()->hasOwnContext = false; } void QUnifiedToolbarSurface::prepareBuffer(QImage::Format format, QWidget *widget) @@ -198,7 +174,7 @@ void QUnifiedToolbarSurface::prepareBuffer(QImage::Format format, QWidget *widge Q_D(QUnifiedToolbarSurface); int width = geometry().width(); - int height = geometry().height(); + int height = 100; // FIXME if (d->image) { width = qMax(d->image->width(), width); height = qMax(d->image->height(), height); @@ -254,6 +230,28 @@ void QUnifiedToolbarSurface::prepareBuffer(QImage::Format format, QWidget *widge delete oldImage; } +CGContextRef QUnifiedToolbarSurface::imageContext() +{ + Q_D(QUnifiedToolbarSurface); + return d->image->cg; +} + +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); +} + QT_END_NAMESPACE #endif // QT_MAC_USE_COCOA diff --git a/src/gui/painting/qunifiedtoolbarsurface_mac_p.h b/src/gui/painting/qunifiedtoolbarsurface_mac_p.h index e1157d7..b0075b6 100644 --- a/src/gui/painting/qunifiedtoolbarsurface_mac_p.h +++ b/src/gui/painting/qunifiedtoolbarsurface_mac_p.h @@ -55,6 +55,7 @@ #include <private/qwindowsurface_raster_p.h> #include <QWidget> +#include <QToolBar> #include <private/qwidget_p.h> #include <private/qnativeimage_p.h> @@ -78,16 +79,21 @@ public: QUnifiedToolbarSurface(QWidget *widget); ~QUnifiedToolbarSurface(); - void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void flush(QWidget *widget); void setGeometry(const QRect &rect); void beginPaint(const QRegion &rgn); void insertToolbar(QWidget *toolbar, const QPoint &offset); + void removeToolbar(QToolBar *toolbar); + void updateToolbarOffset(QWidget *widget); + void renderToolbar(QWidget *widget, bool forceFlush = false); + void recursiveRedirect(QObject *widget, QWidget *parent_toolbar, const QPoint &offset); -private: QPaintDevice *paintDevice(); - void updateToolbarOffset(QWidget *widget); + CGContextRef imageContext(); + +private: void prepareBuffer(QImage::Format format, QWidget *widget); - void recursiveRedirect(QObject *widget, const QPoint &offset); + void recursiveRemoval(QObject *object); Q_DECLARE_PRIVATE(QUnifiedToolbarSurface) QScopedPointer<QUnifiedToolbarSurfacePrivate> d_ptr; diff --git a/src/gui/painting/qwindowsurface_raster.cpp b/src/gui/painting/qwindowsurface_raster.cpp index 419518ac..8170b7a 100644 --- a/src/gui/painting/qwindowsurface_raster.cpp +++ b/src/gui/painting/qwindowsurface_raster.cpp @@ -104,6 +104,11 @@ QRasterWindowSurface::QRasterWindowSurface(QWidget *window, bool setDefaultSurfa d_ptr->image = 0; d_ptr->inSetGeometry = false; setStaticContentsSupport(true); + +#ifdef QT_MAC_USE_COCOA + needsFlush = false; + regionToFlush = QRegion(); +#endif // QT_MAC_USE_COCOA } @@ -272,41 +277,26 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi #ifdef Q_WS_MAC + Q_UNUSED(offset); + // This is mainly done for native components like native "open file" dialog. if (widget->testAttribute(Qt::WA_DontShowOnScreen)) { return; } #ifdef QT_MAC_USE_COCOA - // Unified toolbar hack. - QMainWindow* mWindow = qobject_cast<QMainWindow*>(widget->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->flush(tbWidget, rgn, offset); - } - } - } - } -#endif // QT_MAC_USE_COCOA + this->needsFlush = true; + this->regionToFlush += rgn; - Q_UNUSED(offset); + // The actual flushing will be processed in [view drawRect:rect] + qt_mac_setNeedsDisplay(widget); + +#else // Get a context for the widget. -#ifndef QT_MAC_USE_COCOA CGContextRef context; CGrafPtr port = GetWindowPort(qt_mac_window_for(widget)); QDBeginCGContext(port, &context); -#else - QMacCocoaAutoReleasePool pool; - extern CGContextRef qt_mac_graphicsContextFor(QWidget *); - CGContextRef context = qt_mac_graphicsContextFor(widget); -#endif CGContextRetain(context); CGContextSaveGState(context); @@ -332,16 +322,12 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi CGImageRelease(subImage); CGImageRelease(image); -#ifndef QT_MAC_USE_COCOA QDEndCGContext(port, &context); -#else - CGContextFlush(context); -#endif // Restore context. CGContextRestoreGState(context); CGContextRelease(context); - +#endif // QT_MAC_USE_COCOA #endif // Q_WS_MAC @@ -487,4 +473,12 @@ void QRasterWindowSurface::prepareBuffer(QImage::Format format, QWidget *widget) delete oldImage; } +#ifdef QT_MAC_USE_COCOA +CGContextRef QRasterWindowSurface::imageContext() +{ + Q_D(QRasterWindowSurface); + return d->image->cg; +} +#endif // QT_MAC_USE_COCOA + QT_END_NAMESPACE diff --git a/src/gui/painting/qwindowsurface_raster_p.h b/src/gui/painting/qwindowsurface_raster_p.h index 903810b..7e46161 100644 --- a/src/gui/painting/qwindowsurface_raster_p.h +++ b/src/gui/painting/qwindowsurface_raster_p.h @@ -56,6 +56,10 @@ #include <qglobal.h> #include "private/qwindowsurface_p.h" +#ifdef QT_MAC_USE_COCOA +# include <private/qt_cocoa_helpers_mac_p.h> +#endif // QT_MAC_USE_COCOA + QT_BEGIN_NAMESPACE #ifdef Q_WS_WIN @@ -106,6 +110,13 @@ public: void setGeometry(const QRect &rect); bool scroll(const QRegion &area, int dx, int dy); +#ifdef QT_MAC_USE_COCOA + CGContextRef imageContext(); + + bool needsFlush; + QRegion regionToFlush; +#endif // QT_MAC_USE_COCOA + private: #if defined(Q_WS_X11) && !defined(QT_NO_MITSHM) void syncX(); diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp index fd61783..43d6796 100644 --- a/src/gui/widgets/qmainwindow.cpp +++ b/src/gui/widgets/qmainwindow.cpp @@ -1521,12 +1521,23 @@ void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool set) #ifdef QT_MAC_USE_COCOA // Activate the unified toolbar with the raster engine. - if (windowSurface()) { + if (windowSurface() && set) { d->layout->unifiedSurface = new QUnifiedToolbarSurface(this); } #endif // QT_MAC_USE_COCOA d->layout->updateHIToolBarStatus(); + +#ifdef QT_MAC_USE_COCOA + // Deactivate the unified toolbar with the raster engine. + if (windowSurface() && !set) { + if (d->layout->unifiedSurface) { + delete d->layout->unifiedSurface; + d->layout->unifiedSurface = 0; + } + } +#endif // QT_MAC_USE_COCOA + // Enabling the unified toolbar clears the opaque size grip setting, update it. d->macUpdateOpaqueSizeGrip(); #else diff --git a/src/gui/widgets/qmainwindowlayout_mac.mm b/src/gui/widgets/qmainwindowlayout_mac.mm index e428ffc..761a433 100644 --- a/src/gui/widgets/qmainwindowlayout_mac.mm +++ b/src/gui/widgets/qmainwindowlayout_mac.mm @@ -356,10 +356,10 @@ void QMainWindowLayout::updateHIToolBarStatus() while (!qtoolbarsInUnifiedToolbarList.isEmpty()) { // Should shrink the list by one every time. QToolBar *toolbar = qtoolbarsInUnifiedToolbarList.first(); - layoutState.mainWindow->addToolBar(Qt::TopToolBarArea, toolbar); #if defined(QT_MAC_USE_COCOA) - toolbar->d_func()->isInUnifiedToolbar = false; + unifiedSurface->removeToolbar(toolbar); #endif + layoutState.mainWindow->addToolBar(Qt::TopToolBarArea, toolbar); } macWindowToolbarSet(qt_mac_window_for(layoutState.mainWindow), 0); } else { @@ -393,7 +393,7 @@ void QMainWindowLayout::insertIntoMacToolbar(QToolBar *before, QToolBar *toolbar return; #if defined(QT_MAC_USE_COCOA) - // toolbar will now become native (if not allready) since we need + // toolbar will now become native (if not already) since we need // an nsview for it inside the corresponding NSToolbarItem. // Setting isInUnifiedToolbar will (among other things) stop alien // siblings from becoming native when this happends since the toolbar |