diff options
author | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2015-03-18 15:23:56 +0000 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2015-03-18 22:27:24 +0000 |
commit | dcf0ececbf167502ac9943c6435bb9ddeeb29d5e (patch) | |
tree | 19416d427b84f0a90e0d3028588404a544003734 /src/plugins/platforms/cocoa | |
parent | 7aad6b9fd426e05fdfb3892d60432a45e4079887 (diff) | |
parent | 198606f6dbca95ba3a170fff387327d8271018cd (diff) |
Merge "Merge remote-tracking branch 'origin/5.5' into dev" into refs/staging/dev
Diffstat (limited to 'src/plugins/platforms/cocoa')
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoabackingstore.h | 1 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoabackingstore.mm | 12 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm | 15 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaintegration.h | 6 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaintegration.mm | 24 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoamenu.h | 1 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoamenu.mm | 5 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.h | 1 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.mm | 26 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qnsview.mm | 45 |
10 files changed, 105 insertions, 31 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h index d012ede5f9..3737584c4c 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.h +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h @@ -54,6 +54,7 @@ public: QImage toImage() const; void resize (const QSize &size, const QRegion &); bool scroll(const QRegion &area, int dx, int dy); + void beginPaint(const QRegion ®ion); qreal getBackingStoreDevicePixelRatio(); private: diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index cddb960197..6a4f7ed8ee 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -96,6 +96,18 @@ bool QCocoaBackingStore::scroll(const QRegion &area, int dx, int dy) return true; } +void QCocoaBackingStore::beginPaint(const QRegion ®ion) +{ + if (m_qImage.hasAlphaChannel()) { + QPainter p(&m_qImage); + p.setCompositionMode(QPainter::CompositionMode_Source); + const QVector<QRect> rects = region.rects(); + const QColor blank = Qt::transparent; + for (QVector<QRect>::const_iterator it = rects.begin(), end = rects.end(); it != end; ++it) + p.fillRect(*it, blank); + } +} + qreal QCocoaBackingStore::getBackingStoreDevicePixelRatio() { return m_qImage.devicePixelRatio(); diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm index 933034bb6f..d1802fe4f9 100644 --- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm @@ -84,20 +84,13 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont) QFont newFont; if (cocoaFont) { int pSize = qRound([cocoaFont pointSize]); - QString family(QCFString::toQString([cocoaFont familyName])); - QString typeface(QCFString::toQString([cocoaFont fontName])); - - int hyphenPos = typeface.indexOf(QLatin1Char('-')); - if (hyphenPos != -1) { - typeface.remove(0, hyphenPos + 1); - } else { - typeface = QLatin1String("Normal"); - } + QCFType<CTFontDescriptorRef> font(CTFontCopyFontDescriptor((CTFontRef)cocoaFont)); + QString family(QCFString((CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontFamilyNameAttribute))); + QString style(QCFString(((CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontStyleNameAttribute)))); - newFont = QFontDatabase().font(family, typeface, pSize); + newFont = QFontDatabase().font(family, style, pSize); newFont.setUnderline(resolveFont.underline()); newFont.setStrikeOut(resolveFont.strikeOut()); - } return newFont; } diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index 3b79717472..dc9140d990 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -133,6 +133,11 @@ public: void setToolbar(QWindow *window, NSToolbar *toolbar); NSToolbar *toolbar(QWindow *window) const; void clearToolbars(); + + void pushPopupWindow(QCocoaWindow *window); + QCocoaWindow *popPopupWindow(); + QCocoaWindow *activePopupWindow() const; + QList<QCocoaWindow *> *popupWindowStack(); private: static QCocoaIntegration *mInstance; @@ -151,6 +156,7 @@ private: QScopedPointer<QCocoaKeyMapper> mKeyboardMapper; QHash<QWindow *, NSToolbar *> mToolbars; + QList<QCocoaWindow *> m_popupWindowStack; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 881b23cd6f..aa33cfd8bc 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -545,4 +545,28 @@ void QCocoaIntegration::clearToolbars() mToolbars.clear(); } +void QCocoaIntegration::pushPopupWindow(QCocoaWindow *window) +{ + m_popupWindowStack.append(window); +} + +QCocoaWindow *QCocoaIntegration::popPopupWindow() +{ + if (m_popupWindowStack.isEmpty()) + return 0; + return m_popupWindowStack.takeLast(); +} + +QCocoaWindow *QCocoaIntegration::activePopupWindow() const +{ + if (m_popupWindowStack.isEmpty()) + return 0; + return m_popupWindowStack.front(); +} + +QList<QCocoaWindow *> *QCocoaIntegration::popupWindowStack() +{ + return &m_popupWindowStack; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoamenu.h b/src/plugins/platforms/cocoa/qcocoamenu.h index ad8821ca97..59807deb5a 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.h +++ b/src/plugins/platforms/cocoa/qcocoamenu.h @@ -58,6 +58,7 @@ public: void removeMenuItem(QPlatformMenuItem *menuItem); void syncMenuItem(QPlatformMenuItem *menuItem); void setEnabled(bool enabled); + bool isEnabled() const; void setVisible(bool visible); void showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item); void dismiss(); diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index fb11efb689..4fadc2f60a 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -426,6 +426,11 @@ void QCocoaMenu::setEnabled(bool enabled) syncModalState(!m_enabled); } +bool QCocoaMenu::isEnabled() const +{ + return [m_nativeItem isEnabled]; +} + void QCocoaMenu::setVisible(bool visible) { [m_nativeItem setSubmenu:(visible ? m_nativeMenu : nil)]; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index e4794f8674..c87a871ad0 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -262,7 +262,6 @@ public: // for QNSView bool m_effectivelyMaximized; Qt::WindowState m_synchedWindowState; Qt::WindowModality m_windowModality; - QPointer<QWindow> m_activePopupWindow; QPointer<QWindow> m_enterLeaveTargetWindow; bool m_windowUnderMouse; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index b9a09d03b5..8aed9da9c5 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -455,6 +455,10 @@ QCocoaWindow::~QCocoaWindow() [m_qtView clearQWindowPointers]; } + // While it is unlikely that this window will be in the popup stack + // during deletetion we clear any pointers here to make sure. + QCocoaIntegration::instance()->popupWindowStack()->removeAll(this); + foreach (QCocoaWindow *child, m_childWindows) { [m_nsWindow removeChildWindow:child->m_nsWindow]; child->m_parentCocoaWindow = 0; @@ -647,17 +651,17 @@ void QCocoaWindow::setVisible(bool visible) // We need to recreate if the modality has changed as the style mask will need updating if (m_windowModality != window()->modality()) recreateWindow(parent()); + + // Register popup windows. The Cocoa platform plugin will forward mouse events + // to them and close them when needed. + if (window()->type() == Qt::Popup || window()->type() == Qt::ToolTip) + QCocoaIntegration::instance()->pushPopupWindow(this); + if (parentCocoaWindow) { // The parent window might have moved while this window was hidden, // update the window geometry if there is a parent. setGeometry(window()->geometry()); - // Register popup windows so that the parent window can close them when needed. - if (window()->type() == Qt::Popup || window()->type() == Qt::ToolTip) { - // qDebug() << "transientParent and popup" << window()->type() << Qt::Popup << (window()->type() & Qt::Popup); - parentCocoaWindow->m_activePopupWindow = window(); - } - if (window()->type() == Qt::Popup) { // QTBUG-30266: a window should not be resizable while a transient popup is open // Since this isn't a native popup, the window manager doesn't close the popup when you click outside @@ -759,8 +763,11 @@ void QCocoaWindow::setVisible(bool visible) [NSEvent removeMonitor:monitor]; monitor = nil; } + + if (window()->type() == Qt::Popup) + QCocoaIntegration::instance()->popupWindowStack()->removeAll(this); + if (parentCocoaWindow && window()->type() == Qt::Popup) { - parentCocoaWindow->m_activePopupWindow = 0; if (m_resizableTransientParent && !([parentCocoaWindow->m_nsWindow styleMask] & NSFullScreenWindowMask)) // QTBUG-30266: a window should not be resizable while a transient popup is open @@ -1177,10 +1184,9 @@ void QCocoaWindow::setEmbeddedInForeignView(bool embedded) void QCocoaWindow::windowWillMove() { // Close any open popups on window move - if (m_activePopupWindow) { - QWindowSystemInterface::handleCloseEvent(m_activePopupWindow); + while (QCocoaWindow *popup = QCocoaIntegration::instance()->popPopupWindow()) { + QWindowSystemInterface::handleCloseEvent(popup->window()); QWindowSystemInterface::flushWindowSystemEvents(); - m_activePopupWindow = 0; } } diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 39bd5d486c..1c87b90450 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -699,6 +699,10 @@ QT_WARNING_POP m_platformWindow->m_forwardWindow = 0; } + // Popups implicitly grap mouse events; forward to the active popup if there is one + if (QCocoaWindow *popup = QCocoaIntegration::instance()->activePopupWindow()) + targetView = popup->contentView(); + [targetView convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint]; ulong timestamp = [theEvent timestamp] * 1000; @@ -766,16 +770,39 @@ QT_WARNING_POP if (m_window->flags() & Qt::WindowTransparentForInput) return [super mouseDown:theEvent]; m_sendUpAsRightButton = false; - if (m_platformWindow->m_activePopupWindow) { - Qt::WindowType type = m_platformWindow->m_activePopupWindow->type(); - QWindowSystemInterface::handleCloseEvent(m_platformWindow->m_activePopupWindow); - QWindowSystemInterface::flushWindowSystemEvents(); - m_platformWindow->m_activePopupWindow = 0; - // Consume the mouse event when closing the popup, except for tool tips - // were it's expected that the event is processed normally. - if (type != Qt::ToolTip) - return; + + // Handle any active poup windows; clicking outisde them should close them + // all. Don't do anything or clicks inside one of the menus, let Cocoa + // handle that case. Note that in practice many windows of the Qt::Popup type + // will actually close themselves in this case using logic implemented in + // that particular poup type (for example context menus). However, Qt expects + // that plain popup QWindows will also be closed, so we implement the logic + // here as well. + QList<QCocoaWindow *> *popups = QCocoaIntegration::instance()->popupWindowStack(); + if (!popups->isEmpty()) { + // Check if the click is outside all popups. + bool inside = false; + QPointF qtScreenPoint = qt_mac_flipPoint([self screenMousePoint:theEvent]); + for (QList<QCocoaWindow *>::const_iterator it = popups->begin(); it != popups->end(); ++it) { + if ((*it)->geometry().contains(qtScreenPoint.toPoint())) { + inside = true; + break; + } + } + // Close the popups if the click was outside. + if (!inside) { + Qt::WindowType type = QCocoaIntegration::instance()->activePopupWindow()->window()->type(); + while (QCocoaWindow *popup = QCocoaIntegration::instance()->popPopupWindow()) { + QWindowSystemInterface::handleCloseEvent(popup->window()); + QWindowSystemInterface::flushWindowSystemEvents(); + } + // Consume the mouse event when closing the popup, except for tool tips + // were it's expected that the event is processed normally. + if (type != Qt::ToolTip) + return; + } } + if ([self hasMarkedText]) { NSInputManager* inputManager = [NSInputManager currentInputManager]; if ([inputManager wantsToHandleMouseEvents]) { |