summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/cocoa
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@theqtcompany.com>2015-03-18 15:23:56 +0000
committerThe Qt Project <gerrit-noreply@qt-project.org>2015-03-18 22:27:24 +0000
commitdcf0ececbf167502ac9943c6435bb9ddeeb29d5e (patch)
tree19416d427b84f0a90e0d3028588404a544003734 /src/plugins/platforms/cocoa
parent7aad6b9fd426e05fdfb3892d60432a45e4079887 (diff)
parent198606f6dbca95ba3a170fff387327d8271018cd (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.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm12
-rw-r--r--src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm15
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm24
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.mm5
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm26
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm45
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 &region);
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 &region)
+{
+ 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]) {