diff options
author | Liang Qi <liang.qi@qt.io> | 2016-11-16 12:26:36 +0000 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2016-11-16 13:54:01 +0000 |
commit | b39adf8945616dfc02df7177dccef6b051a1903b (patch) | |
tree | 21a91178abc484b8cf191eec461f80678a107b33 /src/plugins/platforms/cocoa | |
parent | 38e935701c0faeb19b9b1493dc2d6d60c6bc3ca3 (diff) | |
parent | 90c425642dfeae4564b43dacf15f80479962e910 (diff) |
Merge "Merge remote-tracking branch 'origin/5.7' into 5.8" into refs/staging/5.8
Diffstat (limited to 'src/plugins/platforms/cocoa')
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm | 5 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoacursor.mm | 9 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaeventdispatcher.h | 2 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm | 13 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm | 5 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm | 5 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoanativeinterface.h | 2 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoanativeinterface.mm | 6 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.h | 2 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.mm | 60 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qnsview.h | 1 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qnsview.mm | 23 |
12 files changed, 92 insertions, 41 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm index 60c4c1a8ca..e53c085e41 100644 --- a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm @@ -45,6 +45,7 @@ #include "qcocoacolordialoghelper.h" #include "qcocoahelpers.h" +#include "qcocoaeventdispatcher.h" #import <AppKit/AppKit.h> @@ -231,6 +232,10 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate); // cleanup of modal sessions. Do this before showing the native dialog, otherwise it will // close down during the cleanup. qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers); + + // Make sure we don't interrupt the runModalForWindow call. + QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag(); + [NSApp runModalForWindow:mColorPanel]; mDialogIsExecuting = false; return (mResultCode == NSOKButton); diff --git a/src/plugins/platforms/cocoa/qcocoacursor.mm b/src/plugins/platforms/cocoa/qcocoacursor.mm index 8e523dfbbf..3df2a7c962 100644 --- a/src/plugins/platforms/cocoa/qcocoacursor.mm +++ b/src/plugins/platforms/cocoa/qcocoacursor.mm @@ -62,7 +62,7 @@ QCocoaCursor::~QCocoaCursor() void QCocoaCursor::changeCursor(QCursor *cursor, QWindow *window) { - NSCursor * cocoaCursor = convertCursor(cursor); + NSCursor *cocoaCursor = convertCursor(cursor); if (QPlatformWindow * platformWindow = window->handle()) static_cast<QCocoaWindow *>(platformWindow)->setWindowCursor(cocoaCursor); @@ -84,9 +84,12 @@ void QCocoaCursor::setPos(const QPoint &position) CFRelease(e); } -NSCursor *QCocoaCursor::convertCursor(QCursor * cursor) +NSCursor *QCocoaCursor::convertCursor(QCursor *cursor) { - const Qt::CursorShape newShape = cursor ? cursor->shape() : Qt::ArrowCursor; + if (cursor == Q_NULLPTR) + return 0; + + const Qt::CursorShape newShape = cursor->shape(); NSCursor *cocoaCursor; // Check for a suitable built-in NSCursor first: diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h index 84880d51c5..70887c41c9 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h @@ -131,6 +131,8 @@ public: void interrupt(); void flush(); + static void clearCurrentThreadCocoaEventDispatcherInterruptFlag(); + friend void qt_mac_maybeCancelWaitForMoreEventsForwarder(QAbstractEventDispatcher *eventDispatcher); }; diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index b2b9fe2c1e..72c7856c2d 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -965,6 +965,19 @@ void QCocoaEventDispatcher::interrupt() void QCocoaEventDispatcher::flush() { } +// QTBUG-56746: The behavior of processEvents() has been changed to not clear +// the interrupt flag. Use this function to clear it. + void QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag() +{ + QCocoaEventDispatcher *cocoaEventDispatcher = + qobject_cast<QCocoaEventDispatcher *>(QThread::currentThread()->eventDispatcher()); + if (!cocoaEventDispatcher) + return; + QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = + static_cast<QCocoaEventDispatcherPrivate *>(QObjectPrivate::get(cocoaEventDispatcher)); + cocoaEventDispatcherPrivate->interrupt = false; +} + QCocoaEventDispatcher::~QCocoaEventDispatcher() { Q_D(QCocoaEventDispatcher); diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index ef102990b4..234da57f59 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -53,6 +53,7 @@ #include "qt_mac_p.h" #include "qcocoahelpers.h" #include "qcocoamenubar.h" +#include "qcocoaeventdispatcher.h" #include <qregexp.h> #include <qbuffer.h> #include <qdebug.h> @@ -250,6 +251,10 @@ static QString strippedText(QString s) // cleanup of modal sessions. Do this before showing the native dialog, otherwise it will // close down during the cleanup. qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers); + + // Make sure we don't interrupt the runModal call below. + QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag(); + QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder(); mReturnCode = [mSavePanel runModal]; QCocoaMenuBar::resetKnownMenuItemsToQt(); diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm index e565f3b5b1..33dd4260a5 100644 --- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm @@ -49,6 +49,7 @@ #include "qcocoafontdialoghelper.h" #include "qcocoahelpers.h" +#include "qcocoaeventdispatcher.h" #import <AppKit/AppKit.h> @@ -217,6 +218,10 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate); // cleanup of modal sessions. Do this before showing the native dialog, otherwise it will // close down during the cleanup. qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers); + + // Make sure we don't interrupt the runModalForWindow call. + QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag(); + [NSApp runModalForWindow:mFontPanel]; mDialogIsExecuting = false; return (mResultCode == NSOKButton); diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.h b/src/plugins/platforms/cocoa/qcocoanativeinterface.h index 477165607c..26fbe3e4bc 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h @@ -100,6 +100,8 @@ private: */ Q_INVOKABLE QPixmap defaultBackgroundPixmapForQWizard(); + Q_INVOKABLE void clearCurrentThreadCocoaEventDispatcherInterruptFlag(); + // QMacPastebardMime support. The mac pasteboard void pointers are // QMacPastebardMime instances from the cocoa plugin or qtmacextras // These two classes are kept in sync and can be casted between. diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index 10435d0b1d..972230349b 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -44,6 +44,7 @@ #include "qcocoahelpers.h" #include "qcocoaapplication.h" #include "qcocoaintegration.h" +#include "qcocoaeventdispatcher.h" #include <qbytearray.h> #include <qwindow.h> @@ -194,6 +195,11 @@ QPixmap QCocoaNativeInterface::defaultBackgroundPixmapForQWizard() return QPixmap(); } +void QCocoaNativeInterface::clearCurrentThreadCocoaEventDispatcherInterruptFlag() +{ + QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag(); +} + void QCocoaNativeInterface::onAppFocusWindowChanged(QWindow *window) { Q_UNUSED(window); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 2e9de03dfc..16639fd8b1 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -216,6 +216,8 @@ public: void setMenubar(QCocoaMenuBar *mb); QCocoaMenuBar *menubar() const; + NSCursor *effectiveWindowCursor() const; + void applyEffectiveWindowCursor(); void setWindowCursor(NSCursor *cursor); void registerTouch(bool enable); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index e377d8f83d..602da0a175 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1638,31 +1638,53 @@ QCocoaMenuBar *QCocoaWindow::menubar() const return m_menubar; } -void QCocoaWindow::setWindowCursor(NSCursor *cursor) +// Finds the effective cursor for this window by walking up the +// ancestor chain (including this window) until a set cursor is +// found. Returns nil if there is not set cursor. +NSCursor *QCocoaWindow::effectiveWindowCursor() const { - // This function is called (via QCocoaCursor) by Qt to set - // the cursor for this window. It can be called for a window - // that is not currenly under the mouse pointer (for example - // for a popup window.) Qt expects the set cursor to "stick": - // it should be accociated with the window until a different - // cursor is set. - if (m_windowCursor != cursor) { - [m_windowCursor release]; - m_windowCursor = [cursor retain]; - } - // Use the built in cursor rect API if the QCocoaWindow has a NSWindow. - // Othervise, set the cursor if this window is under the mouse. In - // this case QNSView::cursorUpdate will set the cursor as the pointer - // moves. - if (m_nsWindow && window()->type() != Qt::ForeignWindow) { - [m_nsWindow invalidateCursorRectsForView:m_view]; + if (m_windowCursor) + return m_windowCursor; + if (!QPlatformWindow::parent()) + return nil; + return static_cast<QCocoaWindow *>(QPlatformWindow::parent())->effectiveWindowCursor(); +} + +// Applies the cursor as returned by effectiveWindowCursor(), handles +// the special no-cursor-set case by setting the arrow cursor. +void QCocoaWindow::applyEffectiveWindowCursor() +{ + NSCursor *effectiveCursor = effectiveWindowCursor(); + if (effectiveCursor) { + [effectiveCursor set]; } else { - if (m_windowUnderMouse) - [cursor set]; + // We wold like to _unset_ the cursor here; but there is no such + // API. Fall back to setting the default arrow cursor. + [[NSCursor arrowCursor] set]; } } +void QCocoaWindow::setWindowCursor(NSCursor *cursor) +{ + if (m_windowCursor == cursor) + return; + + // Setting a cursor in a foregin view is not supported. + if (window()->type() == Qt::ForeignWindow) + return; + + [m_windowCursor release]; + m_windowCursor = cursor; + [m_windowCursor retain]; + + // The installed view tracking area (see QNSView updateTrackingAreas) will + // handle cursor updates on mouse enter/leave. Handle the case where the + // mouse is on the this window by changing the cursor immediately. + if (m_windowUnderMouse) + applyEffectiveWindowCursor(); +} + void QCocoaWindow::registerTouch(bool enable) { m_registerTouchCount += enable ? 1 : -1; diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index abaff39e81..f226547b90 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -129,7 +129,6 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper)); - (void)mouseMovedImpl:(NSEvent *)theEvent; - (void)mouseEnteredImpl:(NSEvent *)theEvent; - (void)mouseExitedImpl:(NSEvent *)theEvent; -- (void)cursorUpdateImpl:(NSEvent *)theEvent; - (void)rightMouseDown:(NSEvent *)theEvent; - (void)rightMouseDragged:(NSEvent *)theEvent; - (void)rightMouseUp:(NSEvent *)theEvent; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 6181997923..a63bc4d570 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -121,7 +121,7 @@ static bool _q_dontOverrideCtrlLMB = false; - (void)cursorUpdate:(NSEvent *)theEvent { - [view cursorUpdateImpl:theEvent]; + [self cursorUpdate:theEvent]; } @end @@ -1053,21 +1053,10 @@ static bool _q_dontOverrideCtrlLMB = false; [self addTrackingArea:m_trackingArea]; } --(void)cursorUpdateImpl:(NSEvent *)theEvent -{ - Q_UNUSED(theEvent) - // Set the cursor manually if there is no NSWindow. - if (!m_platformWindow->m_nsWindow && m_platformWindow->m_windowCursor) - [m_platformWindow->m_windowCursor set]; - else - [super cursorUpdate:theEvent]; -} - --(void)resetCursorRects +- (void)cursorUpdate:(NSEvent *)theEvent { - // Use the cursor rect API if there is a NSWindow - if (m_platformWindow->m_nsWindow && m_platformWindow->m_windowCursor) - [self addCursorRect:[self visibleRect] cursor:m_platformWindow->m_windowCursor]; + Q_UNUSED(theEvent); + m_platformWindow->applyEffectiveWindowCursor(); } - (void)mouseMovedImpl:(NSEvent *)theEvent @@ -1891,9 +1880,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) - (NSRange) selectedRange { - NSRange selectedRange = {NSNotFound, 0}; - selectedRange.location = NSNotFound; - selectedRange.length = 0; + NSRange selectedRange = {0, 0}; QObject *fo = QGuiApplication::focusObject(); if (!fo) |