summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMorten Johan Sørvig <morten.sorvig@digia.com>2013-10-09 08:43:34 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-11-01 09:38:12 +0100
commitd1114669e301e35cc4e9b2e4c8c4b9476180fb56 (patch)
treed96efc96e6f119a2433b9baaccec15871c11b25b /src
parentd0f8ba748e4ee93b4b2a205421a0340b2d146ce5 (diff)
Cocoa: Improve cursor setting.
Implement cursor setting in terms of [NSCursor set] and [NSView cursorUpdate] using the window tracking area. Refactor cursor conversion into QCocoaCursor:: convertCursor. Rename QCoocaWindow::m_underMouseWindow to m_enterLeaveTargetWindow since it's set according to spesific enter/leave logic. Add m_windowUnderMouse which tracks mouseEntered/mouseExited state. Task-number: QTBUG-33961 Change-Id: Id5e12594f5db365e09c9926a4c08d748a9afb935 Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/platforms/cocoa/qcocoacursor.h5
-rw-r--r--src/plugins/platforms/cocoa/qcocoacursor.mm75
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm19
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm27
5 files changed, 88 insertions, 44 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoacursor.h b/src/plugins/platforms/cocoa/qcocoacursor.h
index dfa1fcff81..f332240724 100644
--- a/src/plugins/platforms/cocoa/qcocoacursor.h
+++ b/src/plugins/platforms/cocoa/qcocoacursor.h
@@ -55,12 +55,13 @@ public:
QCocoaCursor();
~QCocoaCursor();
- virtual void changeCursor(QCursor * widgetCursor, QWindow * widget);
+ virtual void changeCursor(QCursor *cursor, QWindow *window);
virtual QPoint pos() const;
virtual void setPos(const QPoint &position);
private:
QHash<Qt::CursorShape, NSCursor *> m_cursors;
- NSCursor *createCursorData(QCursor *);
+ NSCursor *convertCursor(QCursor *cursor);
+ NSCursor *createCursorData(QCursor * cursor);
NSCursor *createCursorFromBitmap(const QBitmap *bitmap, const QBitmap *mask, const QPoint hotspot = QPoint());
NSCursor *createCursorFromPixmap(const QPixmap pixmap, const QPoint hotspot = QPoint());
};
diff --git a/src/plugins/platforms/cocoa/qcocoacursor.mm b/src/plugins/platforms/cocoa/qcocoacursor.mm
index d734c36d6f..13f6423701 100644
--- a/src/plugins/platforms/cocoa/qcocoacursor.mm
+++ b/src/plugins/platforms/cocoa/qcocoacursor.mm
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qcocoacursor.h"
+#include "qcocoawindow.h"
#include "qcocoahelpers.h"
#include "qcocoaautoreleasepool.h"
@@ -63,82 +64,90 @@ QCocoaCursor::~QCocoaCursor()
void QCocoaCursor::changeCursor(QCursor *cursor, QWindow *window)
{
- Q_UNUSED(window);
+ NSCursor * cocoaCursor = convertCursor(cursor);
+ if (QPlatformWindow * platformWindow = window->handle())
+ static_cast<QCocoaWindow *>(platformWindow)->setWindowCursor(cocoaCursor);
+}
+
+QPoint QCocoaCursor::pos() const
+{
+ return qt_mac_flipPoint([NSEvent mouseLocation]).toPoint();
+}
+
+void QCocoaCursor::setPos(const QPoint &position)
+{
+ CGPoint pos;
+ pos.x = position.x();
+ pos.y = position.y();
+
+ CGEventRef e = CGEventCreateMouseEvent(0, kCGEventMouseMoved, pos, 0);
+ CGEventPost(kCGHIDEventTap, e);
+ CFRelease(e);
+}
+
+NSCursor *QCocoaCursor::convertCursor(QCursor * cursor)
+{
const Qt::CursorShape newShape = cursor ? cursor->shape() : Qt::ArrowCursor;
+ NSCursor *cocoaCursor;
+
// Check for a suitable built-in NSCursor first:
switch (newShape) {
case Qt::ArrowCursor:
- [[NSCursor arrowCursor] set];
+ cocoaCursor= [NSCursor arrowCursor];
break;
case Qt::CrossCursor:
- [[NSCursor crosshairCursor] set];
+ cocoaCursor = [NSCursor crosshairCursor];
break;
case Qt::IBeamCursor:
- [[NSCursor IBeamCursor] set];
+ cocoaCursor = [NSCursor IBeamCursor];
break;
case Qt::WhatsThisCursor: //for now just use the pointing hand
case Qt::PointingHandCursor:
- [[NSCursor pointingHandCursor] set];
+ cocoaCursor = [NSCursor pointingHandCursor];
break;
case Qt::SplitVCursor:
- [[NSCursor resizeUpDownCursor] set];
+ cocoaCursor = [NSCursor resizeUpDownCursor];
break;
case Qt::SplitHCursor:
- [[NSCursor resizeLeftRightCursor] set];
+ cocoaCursor = [NSCursor resizeLeftRightCursor];
break;
case Qt::OpenHandCursor:
- [[NSCursor openHandCursor] set];
+ cocoaCursor = [NSCursor openHandCursor];
break;
case Qt::ClosedHandCursor:
- [[NSCursor closedHandCursor] set];
+ cocoaCursor = [NSCursor closedHandCursor];
break;
case Qt::DragMoveCursor:
- [[NSCursor crosshairCursor] set];
+ cocoaCursor = [NSCursor crosshairCursor];
break;
case Qt::DragCopyCursor:
- [[NSCursor crosshairCursor] set];
+ cocoaCursor = [NSCursor crosshairCursor];
break;
case Qt::DragLinkCursor:
- [[NSCursor dragLinkCursor] set];
+ cocoaCursor = [NSCursor dragLinkCursor];
break;
default : {
// No suitable OS cursor exist, use cursors provided
// by Qt for the rest. Check for a cached cursor:
- NSCursor *cocoaCursor = m_cursors.value(newShape);
+ cocoaCursor = m_cursors.value(newShape);
if (cocoaCursor && cursor->shape() == Qt::BitmapCursor) {
[cocoaCursor release];
cocoaCursor = 0;
}
if (cocoaCursor == 0) {
cocoaCursor = createCursorData(cursor);
- if (cocoaCursor == 0) {
- [[NSCursor arrowCursor] set];
- return;
- }
+ if (cocoaCursor == 0)
+ return [NSCursor arrowCursor];
+
m_cursors.insert(newShape, cocoaCursor);
}
- [cocoaCursor set];
break; }
}
+ return cocoaCursor;
}
-QPoint QCocoaCursor::pos() const
-{
- return qt_mac_flipPoint([NSEvent mouseLocation]).toPoint();
-}
-
-void QCocoaCursor::setPos(const QPoint &position)
-{
- CGPoint pos;
- pos.x = position.x();
- pos.y = position.y();
-
- CGEventRef e = CGEventCreateMouseEvent(0, kCGEventMouseMoved, pos, 0);
- CGEventPost(kCGHIDEventTap, e);
- CFRelease(e);
-}
// Creates an NSCursor for the given QCursor.
NSCursor *QCocoaCursor::createCursorData(QCursor *cursor)
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index 7f0f07e912..4f5a208f43 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -154,6 +154,8 @@ public:
void setMenubar(QCocoaMenuBar *mb);
QCocoaMenuBar *menubar() const;
+ void setWindowCursor(NSCursor *cursor);
+
void registerTouch(bool enable);
qreal devicePixelRatio() const;
@@ -190,11 +192,13 @@ public: // for QNSView
Qt::WindowState m_synchedWindowState;
Qt::WindowModality m_windowModality;
QPointer<QWindow> m_activePopupWindow;
- QPointer<QWindow> m_underMouseWindow;
+ QPointer<QWindow> m_enterLeaveTargetWindow;
+ bool m_windowUnderMouse;
bool m_inConstructor;
QCocoaGLContext *m_glContext;
QCocoaMenuBar *m_menubar;
+ NSCursor *m_windowCursor;
bool m_hasModalSession;
bool m_frameStrutEventsEnabled;
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 845cc1202f..565594a98a 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -206,9 +206,11 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
, m_nsWindowDelegate(0)
, m_synchedWindowState(Qt::WindowActive)
, m_windowModality(Qt::NonModal)
+ , m_windowUnderMouse(false)
, m_inConstructor(true)
, m_glContext(0)
, m_menubar(0)
+ , m_windowCursor(0)
, m_hasModalSession(false)
, m_frameStrutEventsEnabled(false)
, m_isExposed(false)
@@ -1030,6 +1032,23 @@ QCocoaMenuBar *QCocoaWindow::menubar() const
return m_menubar;
}
+void QCocoaWindow::setWindowCursor(NSCursor *cursor)
+{
+ // 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.
+
+ // Cocoa has different abstractions. We can set the cursor *now*:
+ if (m_windowUnderMouse)
+ [cursor set];
+ // or we can set the cursor on mouse enter/leave using tracking
+ // areas. This is done in QNSView, save the cursor:
+ m_windowCursor = cursor;
+}
+
void QCocoaWindow::registerTouch(bool enable)
{
m_registerTouchCount += enable ? 1 : -1;
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 8f839384df..71c4de3b69 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -671,7 +671,7 @@ static QTouchDevice *touchDevice = 0;
// mouse moves delivered to it (Apple recommends keeping it OFF because there
// is a performance hit). So it goes.
NSUInteger trackingOptions = NSTrackingMouseEnteredAndExited | NSTrackingActiveInActiveApp
- | NSTrackingInVisibleRect | NSTrackingMouseMoved;
+ | NSTrackingInVisibleRect | NSTrackingMouseMoved | NSTrackingCursorUpdate;
NSTrackingArea *ta = [[[NSTrackingArea alloc] initWithRect:[self frame]
options:trackingOptions
owner:self
@@ -680,6 +680,13 @@ static QTouchDevice *touchDevice = 0;
[self addTrackingArea:ta];
}
+-(void)cursorUpdate:(NSEvent *)theEvent
+{
+ Q_UNUSED(theEvent)
+ if (m_platformWindow->m_windowCursor)
+ [m_platformWindow->m_windowCursor set];
+}
+
- (void)mouseMoved:(NSEvent *)theEvent
{
if (m_window->flags() & Qt::WindowTransparentForInput)
@@ -696,9 +703,9 @@ static QTouchDevice *touchDevice = 0;
// handling mouseEnter and mouseLeave envents, since they are sent
// individually to different views.
if (m_platformWindow->m_nsWindow && childWindow) {
- if (childWindow != m_platformWindow->m_underMouseWindow) {
- QWindowSystemInterface::handleEnterLeaveEvent(childWindow, m_platformWindow->m_underMouseWindow, windowPoint, screenPoint);
- m_platformWindow->m_underMouseWindow = childWindow;
+ if (childWindow != m_platformWindow->m_enterLeaveTargetWindow) {
+ QWindowSystemInterface::handleEnterLeaveEvent(childWindow, m_platformWindow->m_enterLeaveTargetWindow, windowPoint, screenPoint);
+ m_platformWindow->m_enterLeaveTargetWindow = childWindow;
}
}
@@ -712,6 +719,8 @@ static QTouchDevice *touchDevice = 0;
- (void)mouseEntered:(NSEvent *)theEvent
{
+ m_platformWindow->m_windowUnderMouse = true;
+
if (m_window->flags() & Qt::WindowTransparentForInput)
return [super mouseEntered:theEvent];
@@ -722,12 +731,14 @@ static QTouchDevice *touchDevice = 0;
QPointF windowPoint;
QPointF screenPoint;
[self convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&windowPoint andScreenPoint:&screenPoint];
- m_platformWindow->m_underMouseWindow = m_platformWindow->childWindowAt(windowPoint.toPoint());
- QWindowSystemInterface::handleEnterEvent(m_platformWindow->m_underMouseWindow, windowPoint, screenPoint);
+ m_platformWindow->m_enterLeaveTargetWindow = m_platformWindow->childWindowAt(windowPoint.toPoint());
+ QWindowSystemInterface::handleEnterEvent(m_platformWindow->m_enterLeaveTargetWindow, windowPoint, screenPoint);
}
- (void)mouseExited:(NSEvent *)theEvent
{
+ m_platformWindow->m_windowUnderMouse = false;
+
if (m_window->flags() & Qt::WindowTransparentForInput)
return [super mouseExited:theEvent];
Q_UNUSED(theEvent);
@@ -736,8 +747,8 @@ static QTouchDevice *touchDevice = 0;
if (!m_platformWindow->m_nsWindow)
return;
- QWindowSystemInterface::handleLeaveEvent(m_platformWindow->m_underMouseWindow);
- m_platformWindow->m_underMouseWindow = 0;
+ QWindowSystemInterface::handleLeaveEvent(m_platformWindow->m_enterLeaveTargetWindow);
+ m_platformWindow->m_enterLeaveTargetWindow = 0;
}
- (void)rightMouseDown:(NSEvent *)theEvent