summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel/qt_cocoa_helpers_mac.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/kernel/qt_cocoa_helpers_mac.mm')
-rw-r--r--src/gui/kernel/qt_cocoa_helpers_mac.mm459
1 files changed, 333 insertions, 126 deletions
diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm
index b2d9ca6..ddbf53f 100644
--- a/src/gui/kernel/qt_cocoa_helpers_mac.mm
+++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm
@@ -89,9 +89,16 @@
#include <private/qcocoaview_mac_p.h>
#include <private/qkeymapper_p.h>
#include <private/qwidget_p.h>
+#include <private/qcocoawindow_mac_p.h>
QT_BEGIN_NAMESPACE
+#ifdef QT_MAC_USE_COCOA
+// Cmd + left mousebutton should produce a right button
+// press (mainly for mac users with one-button mice):
+static bool qt_leftButtonIsRightButton = false;
+#endif
+
Q_GLOBAL_STATIC(QMacWindowFader, macwindowFader);
QMacWindowFader::QMacWindowFader()
@@ -141,6 +148,9 @@ void QMacWindowFader::performFade()
extern bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); // qapplication.cpp;
extern QWidget * mac_mouse_grabber;
extern QWidget *qt_button_down; //qapplication_mac.cpp
+extern QPointer<QWidget> qt_last_mouse_receiver;
+extern OSViewRef qt_mac_effectiveview_for(const QWidget *w);
+extern void qt_mac_updateCursorWithWidgetUnderMouse(QWidget *widgetUnderMouse); // qcursor_mac.mm
void macWindowFade(void * /*OSWindowRef*/ window, float durationSeconds)
{
@@ -167,6 +177,70 @@ void macWindowFade(void * /*OSWindowRef*/ window, float durationSeconds)
}
}
}
+struct dndenum_mapper
+{
+ NSDragOperation mac_code;
+ Qt::DropAction qt_code;
+ bool Qt2Mac;
+};
+
+#ifdef QT_MAC_USE_COCOA && __OBJC__
+
+static dndenum_mapper dnd_enums[] = {
+ { NSDragOperationLink, Qt::LinkAction, true },
+ { NSDragOperationMove, Qt::MoveAction, true },
+ { NSDragOperationCopy, Qt::CopyAction, true },
+ { NSDragOperationGeneric, Qt::CopyAction, false },
+ { NSDragOperationEvery, Qt::ActionMask, false },
+ { NSDragOperationNone, Qt::IgnoreAction, false }
+};
+
+NSDragOperation qt_mac_mapDropAction(Qt::DropAction action)
+{
+ for (int i=0; dnd_enums[i].qt_code; i++) {
+ if (dnd_enums[i].Qt2Mac && (action & dnd_enums[i].qt_code)) {
+ return dnd_enums[i].mac_code;
+ }
+ }
+ return NSDragOperationNone;
+}
+
+NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions)
+{
+ NSDragOperation nsActions = NSDragOperationNone;
+ for (int i=0; dnd_enums[i].qt_code; i++) {
+ if (dnd_enums[i].Qt2Mac && (actions & dnd_enums[i].qt_code))
+ nsActions |= dnd_enums[i].mac_code;
+ }
+ return nsActions;
+}
+
+Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions)
+{
+ Qt::DropAction action = Qt::IgnoreAction;
+ for (int i=0; dnd_enums[i].mac_code; i++) {
+ if (nsActions & dnd_enums[i].mac_code)
+ return dnd_enums[i].qt_code;
+ }
+ return action;
+}
+
+Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions)
+{
+ Qt::DropActions actions = Qt::IgnoreAction;
+ for (int i=0; dnd_enums[i].mac_code; i++) {
+ if (nsActions & dnd_enums[i].mac_code)
+ actions |= dnd_enums[i].qt_code;
+ }
+ return actions;
+}
+
+Q_GLOBAL_STATIC(DnDParams, currentDnDParameters);
+DnDParams *macCurrentDnDParameters()
+{
+ return currentDnDParameters();
+}
+#endif
bool macWindowIsTextured( void * /*OSWindowRef*/ window )
{
@@ -301,7 +375,7 @@ bool qt_mac_checkForNativeSizeGrip(const QWidget *widget)
HIViewFindByID(HIViewGetRoot(HIViewGetWindow(HIViewRef(widget->winId()))), kHIViewWindowGrowBoxID, &nativeSizeGrip);
return (nativeSizeGrip != 0);
#else
- return [[reinterpret_cast<NSView *>(widget->winId()) window] showsResizeIndicator];
+ return [[reinterpret_cast<NSView *>(widget->effectiveWinId()) window] showsResizeIndicator];
#endif
}
struct qt_mac_enum_mapper
@@ -517,8 +591,12 @@ static const KeyPair entries[NumEntries] = {
{ NSNewlineCharacter, Qt::Key_Return },
{ NSCarriageReturnCharacter, Qt::Key_Return },
{ NSBackTabCharacter, Qt::Key_Backtab },
- { NSDeleteCharacter, Qt::Key_Delete },
{ kEscapeCharCode, Qt::Key_Escape },
+ // Cocoa sends us delete when pressing backspace!
+ // (NB when we reverse this list in qtKey2CocoaKey, there
+ // will be two indices of Qt::Key_Backspace. But is seems to work
+ // ok for menu shortcuts (which uses that function):
+ { NSDeleteCharacter, Qt::Key_Backspace },
{ NSUpArrowFunctionKey, Qt::Key_Up },
{ NSDownArrowFunctionKey, Qt::Key_Down },
{ NSLeftArrowFunctionKey, Qt::Key_Left },
@@ -731,7 +809,6 @@ Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum)
return Qt::NoButton;
}
-// Helper to share code between QCocoaWindow and QCocoaView
bool qt_dispatchKeyEvent(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEvent)
{
#ifndef QT_MAC_USE_COCOA
@@ -743,6 +820,7 @@ bool qt_dispatchKeyEvent(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEve
EventRef key_event = static_cast<EventRef>(const_cast<void *>([event eventRef]));
Q_ASSERT(key_event);
unsigned int info = 0;
+
if ([event type] == NSKeyDown) {
NSString *characters = [event characters];
if ([characters length]) {
@@ -752,19 +830,12 @@ bool qt_dispatchKeyEvent(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEve
}
}
- // Redirect keys to alien widgets.
- if (widgetToGetEvent->testAttribute(Qt::WA_NativeWindow) == false) {
- widgetToGetEvent = qApp->focusWidget();
- }
-
- if (widgetToGetEvent == 0)
- return false;
-
if (qt_mac_sendMacEventToWidget(widgetToGetEvent, key_event))
return true;
if (mustUseCocoaKeyEvent())
return qt_dispatchKeyEventWithCocoa(keyEvent, widgetToGetEvent);
+
bool consumed = qt_keymapper_private()->translateKeyEvent(widgetToGetEvent, 0, key_event, &info, true);
return consumed && (info != 0);
#endif
@@ -788,7 +859,6 @@ void qt_dispatchModifiersChanged(void * /*NSEvent * */flagsChangedEvent, QWidget
#endif
}
-
QPointF flipPoint(const NSPoint &p)
{
return QPointF(p.x, flipYCoordinate(p.y));
@@ -804,21 +874,15 @@ NSPoint flipPoint(const QPointF &p)
return NSMakePoint(p.x(), flipYCoordinate(p.y()));
}
-void qt_mac_dispatchNCMouseMessage(void * /* NSWindow* */eventWindow, void * /* NSEvent* */mouseEvent,
- QWidget *widgetToGetEvent, bool &leftButtonIsRightButton)
+#if QT_MAC_USE_COCOA && __OBJC__
+
+void qt_mac_handleNonClientAreaMouseEvent(NSWindow *window, NSEvent *event)
{
-#ifndef QT_MAC_USE_COCOA
- Q_UNUSED(eventWindow);
- Q_UNUSED(mouseEvent);
- Q_UNUSED(widgetToGetEvent);
- Q_UNUSED(leftButtonIsRightButton);
-#else
+ QWidget *widgetToGetEvent = [window QT_MANGLE_NAMESPACE(qt_qwidget)];
if (widgetToGetEvent == 0)
return;
- NSWindow *window = static_cast<NSWindow *>(eventWindow);
- NSEvent *event = static_cast<NSEvent *>(mouseEvent);
- NSEventType evtType = [event type];
+ NSEventType evtType = [event type];
QPoint qlocalPoint;
QPoint qglobalPoint;
bool processThisEvent = false;
@@ -936,12 +1000,12 @@ void qt_mac_dispatchNCMouseMessage(void * /* NSWindow* */eventWindow, void * /*
: QEvent::MouseButtonDblClick;
if (button == Qt::LeftButton && (keyMods & Qt::MetaModifier)) {
button = Qt::RightButton;
- leftButtonIsRightButton = true;
+ qt_leftButtonIsRightButton = true;
}
} else if (eventType == QEvent::NonClientAreaMouseButtonRelease || eventType == QEvent::MouseButtonRelease) {
- if (button == Qt::LeftButton && leftButtonIsRightButton) {
+ if (button == Qt::LeftButton && qt_leftButtonIsRightButton) {
button = Qt::RightButton;
- leftButtonIsRightButton = false;
+ qt_leftButtonIsRightButton = false;
}
}
@@ -961,155 +1025,268 @@ void qt_mac_dispatchNCMouseMessage(void * /* NSWindow* */eventWindow, void * /*
// However we might need to unset it if the event is Release.
if (eventType == QEvent::MouseButtonRelease)
qt_button_down = 0;
-#endif
}
-bool qt_mac_handleMouseEvent(void * /* NSView * */view, void * /* NSEvent * */event, QEvent::Type eventType, Qt::MouseButton button)
+QWidget *qt_mac_getTargetForKeyEvent(QWidget *widgetThatReceivedEvent)
+{
+ if (QWidget *popup = QApplication::activePopupWidget()) {
+ QWidget *focusInPopup = popup->focusWidget();
+ return focusInPopup ? focusInPopup : popup;
+ }
+
+ QWidget *widgetToGetKey = qApp->focusWidget();
+ if (!widgetToGetKey)
+ widgetToGetKey = widgetThatReceivedEvent;
+
+ return widgetToGetKey;
+}
+
+// This function will find the widget that should receive the
+// mouse event. Because of explicit/implicit mouse grabs, popups,
+// etc, this might not end up being the same as the widget under
+// the mouse (which is more interresting when handling enter/leave
+// events
+QWidget *qt_mac_getTargetForMouseEvent(
+ // You can call this function without providing an event.
+ // If so, set returnGlobalPoint before the call.
+ NSEvent *event,
+ QEvent::Type eventType,
+ QPoint &returnLocalPoint,
+ QPoint &returnGlobalPoint,
+ QWidget *nativeWidget,
+ QWidget **returnWidgetUnderMouse)
{
-#ifndef QT_MAC_USE_COCOA
- Q_UNUSED(view);
Q_UNUSED(event);
- Q_UNUSED(eventType);
- Q_UNUSED(button);
- return false;
-#else
- QT_MANGLE_NAMESPACE(QCocoaView) *theView = static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(view);
- NSEvent *theEvent = static_cast<NSEvent *>(event);
+ returnGlobalPoint = flipPoint([NSEvent mouseLocation]).toPoint();
+ QWidget *mouseGrabber = QWidget::mouseGrabber();
+ bool buttonDownNotBlockedByModal = qt_button_down && !QApplicationPrivate::isBlockedByModal(qt_button_down);
+
+ // Resolve the widget under the mouse:
+ QWidget *widgetUnderMouse = 0;
+ if (nativeWidget) {
+ QPoint p = nativeWidget->mapFromGlobal(returnGlobalPoint);
+ widgetUnderMouse = nativeWidget->childAt(p);
+ if (!widgetUnderMouse){
+ // Cocoa will redirct mouse event to the current
+ // mouse down widget, which is not what we want for our
+ // widgetUnderMouse assignment. So we need to check
+ // if we are actually inside nativeView:
+ if (nativeWidget->rect().contains(p)) {
+ widgetUnderMouse = nativeWidget;
+ } else {
+ // Ok, fallback to find the widget under mouse ourselves.
+ widgetUnderMouse = QApplication::widgetAt(returnGlobalPoint);
+ }
+ }
+ } else {
+ // Calling QApplication::widgetAt is potentially slow, hence the
+ // reason we avoid it if we can. So supplying a nativeWidget to
+ // this function is mostly an optimization. But at the same time,
+ // calling QApplication::widgetAt fails for QMacNativeWidget...
+ widgetUnderMouse = QApplication::widgetAt(returnGlobalPoint);
+ }
- // Give the Input Manager a chance to process the mouse events.
- NSInputManager *currentIManager = [NSInputManager currentInputManager];
- if (currentIManager && [currentIManager wantsToHandleMouseEvents]) {
- [currentIManager handleMouseEvent:theEvent];
- }
+ if (widgetUnderMouse) {
+ // Check if widgetUnderMouse is blocked by a modal
+ // window, or the mouse if over the frame strut:
+ if (widgetUnderMouse == qt_button_down) {
+ // Small optimization to avoid an extra call to isBlockedByModal:
+ if (buttonDownNotBlockedByModal == false)
+ widgetUnderMouse = 0;
+ } else if (QApplicationPrivate::isBlockedByModal(widgetUnderMouse)) {
+ widgetUnderMouse = 0;
+ }
- // Handle tablet events (if any) first.
- if (qt_mac_handleTabletEvent(theView, theEvent)) {
- // Tablet event was handled. In Qt we aren't supposed to send the mouse event.
- return true;
+ if (widgetUnderMouse && widgetUnderMouse->isWindow()) {
+ // Exclude the titlebar (and frame strut) when finding widget under mouse:
+ QPoint p = widgetUnderMouse->mapFromGlobal(returnGlobalPoint);
+ if (!widgetUnderMouse->rect().contains(p))
+ widgetUnderMouse = 0;
+ }
+ }
+ if (returnWidgetUnderMouse)
+ *returnWidgetUnderMouse = widgetUnderMouse;
+
+ // Resolve the target for the mouse event. Default will be widgetUnderMouse, except
+ // if there is a popup-"grab", mousegrab, or button-down-"grab":
+ QWidget *popup = QApplication::activePopupWidget();
+ if (popup && !mouseGrabber) {
+ if (!popup->isAncestorOf(widgetUnderMouse)) {
+ // The popup will always grab the mouse unless the
+ // mouse is over a child, or the user scrolls:
+ if (eventType == QEvent::Wheel)
+ return 0;
+ returnLocalPoint = popup->mapFromGlobal(returnGlobalPoint);
+ return popup;
+ } else if (popup == widgetUnderMouse) {
+ returnLocalPoint = popup->mapFromGlobal(returnGlobalPoint);
+ return popup;
+ } else {
+ returnLocalPoint = widgetUnderMouse->mapFromGlobal(returnGlobalPoint);
+ return widgetUnderMouse;
+ }
}
- NSPoint windowPoint = [theEvent locationInWindow];
- NSPoint globalPoint = [[theEvent window] convertBaseToScreen:windowPoint];
+ QWidget *target = mouseGrabber;
+ if (!target && buttonDownNotBlockedByModal)
+ target = qt_button_down;
+ if (!target)
+ target = widgetUnderMouse;
+ if (!target)
+ return 0;
- // Find the widget that *should* get the event (e.g., maybe it was a pop-up,
- // they always get the mouse event).
- QWidget *qwidget = [theView qt_qwidget];
- QWidget *widgetToGetMouse = 0;
- NSView *tmpView = 0;
- QWidget *popup = qAppInstance()->activePopupWidget();
- QPoint qglobalPoint(flipPoint(globalPoint).toPoint());
+ returnLocalPoint = target->mapFromGlobal(returnGlobalPoint);
+ return target;
+}
- if (popup) {
- widgetToGetMouse = popup;
- tmpView = qt_mac_nativeview_for(popup);
- windowPoint = [[tmpView window] convertScreenToBase:globalPoint];
-
- QPoint qWindowPoint(windowPoint.x, windowPoint.y);
- if (widgetToGetMouse->rect().contains(qWindowPoint)) {
- // Keeping the mouse pressed on a combobox button will make
- // the popup pop in front of the mouse. But all mouse events
- // will be sendt to the button. Since we want mouse events
- // to be sendt to widgets inside the popup, we search for the
- // widget in front of the mouse:
- tmpView = [tmpView hitTest:windowPoint];
- if (!tmpView)
- return false;
- widgetToGetMouse =
- [static_cast<QT_MANGLE_NAMESPACE(QCocoaView) *>(tmpView) qt_qwidget];
- }
+static inline void qt_mac_checkEnterLeaveForNativeWidgets(QWidget *maybeEnterWidget)
+{
+ // Dispatch enter/leave for the cases where QApplicationPrivate::sendMouseEvent do
+ // not. This will in general be the cases when alien widgets are not involved:
+ // 1. from a native widget to another native widget or
+ // 2. from a native widget to no widget
+ // 3. from no widget to a native or alien widget
+
+ if (qt_button_down || QWidget::mouseGrabber())
+ return;
+ if ((maybeEnterWidget == qt_last_mouse_receiver) && qt_last_mouse_receiver)
+ return;
+
+ if (maybeEnterWidget) {
+ if (!qt_last_mouse_receiver) {
+ // case 3
+ QApplicationPrivate::dispatchEnterLeave(maybeEnterWidget, 0);
+ qt_last_mouse_receiver = maybeEnterWidget;
+ } else if (qt_last_mouse_receiver->internalWinId() && maybeEnterWidget->internalWinId()) {
+ // case 1
+ if (qt_last_mouse_receiver->isVisible()) {
+ QApplicationPrivate::dispatchEnterLeave(maybeEnterWidget, qt_last_mouse_receiver);
+ qt_last_mouse_receiver = maybeEnterWidget;
+ }
+ } // else at lest one of the widgets are alien, so enter/leave will be handled in QApplicationPrivate
} else {
- extern QWidget * qt_button_down; //qapplication_mac.cpp
- QPoint pos;
- widgetToGetMouse = QApplicationPrivate::pickMouseReceiver(qwidget, qglobalPoint,
- pos, eventType,
- button, qt_button_down, 0);
- if (widgetToGetMouse)
- tmpView = qt_mac_nativeview_for(widgetToGetMouse);
+ if (qt_last_mouse_receiver && qt_last_mouse_receiver->internalWinId()) {
+ // case 2
+ QApplicationPrivate::dispatchEnterLeave(0, qt_last_mouse_receiver);
+ // This seems to be the only case where we need to update qt_last_mouse_receiver
+ // from the mac specific code. Otherwise, QApplicationPrivate::sendMouseEvent
+ // will handle it:
+ qt_last_mouse_receiver = 0;
+ }
}
+}
+
+bool qt_mac_handleMouseEvent(NSEvent *event, QEvent::Type eventType, Qt::MouseButton button, QWidget *nativeWidget)
+{
+ // Give the Input Manager a chance to process the mouse events.
+ NSInputManager *currentIManager = [NSInputManager currentInputManager];
+ if (currentIManager && [currentIManager wantsToHandleMouseEvents]) {
+ [currentIManager handleMouseEvent:event];
+ }
+
+ // Find the widget that should receive the event, and the widget under the mouse. Those
+ // can differ if an implicit or explicit mouse grab is active:
+ QWidget *widgetUnderMouse = 0;
+ QPoint localPoint, globalPoint;
+ QWidget *widgetToGetMouse = qt_mac_getTargetForMouseEvent(event, eventType, localPoint, globalPoint, nativeWidget, &widgetUnderMouse);
if (!widgetToGetMouse)
return false;
- NSPoint localPoint = [tmpView convertPoint:windowPoint fromView:nil];
- QPoint qlocalPoint = QPoint(localPoint.x, localPoint.y);
+ if (!nativeWidget) {
+ // Path typically taken for mouse moves (send
+ // directly from [QCocoaWindow sendEvent]
+ if (!widgetUnderMouse)
+ return false;
+ nativeWidget = widgetUnderMouse->internalWinId() ?
+ widgetUnderMouse : widgetUnderMouse->nativeParentWidget();
+ if (!nativeWidget)
+ return false;
+ }
+ NSView *view = qt_mac_effectiveview_for(nativeWidget);
- // Search for alien child widgets (either on this qwidget or on the popup)
- if (widgetToGetMouse->testAttribute(Qt::WA_NativeWindow) == false || qt_widget_private(widgetToGetMouse)->hasAlienChildren) {
- QPoint qScreenPoint = flipPoint(globalPoint).toPoint();
-#ifdef ALIEN_DEBUG
- qDebug() << "alien mouse event" << qScreenPoint << possibleAlien;
-#endif
- QWidget *possibleAlien = widgetToGetMouse->childAt(qlocalPoint);
- if (possibleAlien) {
- qlocalPoint = possibleAlien->mapFromGlobal(widgetToGetMouse->mapToGlobal(qlocalPoint));
- widgetToGetMouse = possibleAlien;
- }
+ // Handle tablet events (if any) first.
+ if (qt_mac_handleTabletEvent(view, event)) {
+ // Tablet event was handled. In Qt we aren't supposed to send the mouse event.
+ return true;
}
- EventRef carbonEvent = static_cast<EventRef>(const_cast<void *>([theEvent eventRef]));
+ EventRef carbonEvent = static_cast<EventRef>(const_cast<void *>([event eventRef]));
if (qt_mac_sendMacEventToWidget(widgetToGetMouse, carbonEvent))
return true;
- // Yay! All the special cases are handled, it really is just a normal mouse event.
- Qt::KeyboardModifiers keyMods = qt_cocoaModifiers2QtModifiers([theEvent modifierFlags]);
- NSInteger clickCount = [theEvent clickCount];
- Qt::MouseButtons buttons = 0;
+ // Keep previousButton to make sure we don't send double click
+ // events when the user double clicks using two different buttons:
static Qt::MouseButton previousButton = Qt::NoButton;
+
+ Qt::KeyboardModifiers keyMods = qt_cocoaModifiers2QtModifiers([event modifierFlags]);
+ NSInteger clickCount = [event clickCount];
+ Qt::MouseButtons buttons = 0;
{
UInt32 mac_buttons;
if (GetEventParameter(carbonEvent, kEventParamMouseChord, typeUInt32, 0,
sizeof(mac_buttons), 0, &mac_buttons) == noErr)
buttons = qt_mac_get_buttons(mac_buttons);
}
+
+ // Send enter/leave events for the cases when QApplicationPrivate::sendMouseEvent do not:
+ qt_mac_checkEnterLeaveForNativeWidgets(widgetUnderMouse);
+
switch (eventType) {
default:
qWarning("not handled! %d", eventType);
break;
case QEvent::MouseMove:
+ if (button == Qt::LeftButton && qt_leftButtonIsRightButton)
+ button = Qt::RightButton;
break;
case QEvent::MouseButtonPress:
- [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]->view = theView;
- [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]->theEvent = theEvent;
-#ifndef QT_NAMESPACE
- Q_ASSERT(clickCount > 0);
-#endif
+ qt_button_down = widgetUnderMouse;
if (clickCount % 2 == 0 && (previousButton == Qt::NoButton || previousButton == button))
eventType = QEvent::MouseButtonDblClick;
if (button == Qt::LeftButton && (keyMods & Qt::MetaModifier)) {
button = Qt::RightButton;
- [theView qt_setLeftButtonIsRightButton: true];
+ qt_leftButtonIsRightButton = true;
}
break;
case QEvent::MouseButtonRelease:
- if (button == Qt::LeftButton && [theView qt_leftButtonIsRightButton]) {
+ if (button == Qt::LeftButton && qt_leftButtonIsRightButton) {
button = Qt::RightButton;
- [theView qt_setLeftButtonIsRightButton: false];
+ qt_leftButtonIsRightButton = false;
}
qt_button_down = 0;
break;
}
- [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]->localPoint = localPoint;
- QMouseEvent qme(eventType, qlocalPoint, qglobalPoint, button, buttons, keyMods);
-#ifdef ALIEN_DEBUG
- qDebug() << "sending mouse event to" << widgetToGetMouse;
-#endif
- extern QWidget *qt_button_down;
- extern QPointer<QWidget> qt_last_mouse_receiver;
+ qt_mac_updateCursorWithWidgetUnderMouse(widgetUnderMouse);
- if (qwidget->testAttribute(Qt::WA_NativeWindow) && qt_widget_private(qwidget)->hasAlienChildren == false)
- qt_sendSpontaneousEvent(widgetToGetMouse, &qme);
- else
- QApplicationPrivate::sendMouseEvent(widgetToGetMouse, &qme, widgetToGetMouse, qwidget, &qt_button_down,
- qt_last_mouse_receiver);
+ DnDParams *dndParams = currentDnDParameters();
+ dndParams->view = view;
+ dndParams->theEvent = event;
+ dndParams->globalPoint = globalPoint;
+
+ // Send the mouse event:
+ QMouseEvent qme(eventType, localPoint, globalPoint, button, buttons, keyMods);
+ QApplicationPrivate::sendMouseEvent(
+ widgetToGetMouse, &qme, widgetUnderMouse, nativeWidget,
+ &qt_button_down, qt_last_mouse_receiver, true);
if (eventType == QEvent::MouseButtonPress && button == Qt::RightButton) {
- QContextMenuEvent qcme(QContextMenuEvent::Mouse, qlocalPoint, qglobalPoint, keyMods);
+ QContextMenuEvent qcme(QContextMenuEvent::Mouse, localPoint, globalPoint, keyMods);
qt_sendSpontaneousEvent(widgetToGetMouse, &qcme);
}
+
+ if (eventType == QEvent::MouseButtonRelease) {
+ // A mouse button was released, which means that the implicit grab was
+ // released. We therefore need to re-check if should send (delayed) enter leave events:
+ // qt_button_down has now become NULL since the call at the top of the function.
+ widgetToGetMouse = qt_mac_getTargetForMouseEvent(0, QEvent::None, localPoint, globalPoint, nativeWidget, &widgetUnderMouse);
+ qt_mac_checkEnterLeaveForNativeWidgets(widgetUnderMouse);
+ }
+
previousButton = button;
return true;
-#endif
}
+#endif
bool qt_mac_handleTabletEvent(void * /*QCocoaView * */view, void * /*NSEvent * */tabletEvent)
{
@@ -1293,17 +1470,17 @@ void qt_mac_replaceDrawRectOriginal(void * /*OSWindowRef */window, QWidgetPrivat
}
#endif // QT_MAC_USE_COCOA
+#if QT_MAC_USE_COCOA
void qt_mac_showBaseLineSeparator(void * /*OSWindowRef */window, bool show)
{
if(!window)
return;
-#if QT_MAC_USE_COCOA
QMacCocoaAutoReleasePool pool;
OSWindowRef theWindow = static_cast<OSWindowRef>(window);
NSToolbar *macToolbar = [theWindow toolbar];
[macToolbar setShowsBaselineSeparator:show];
-#endif // QT_MAC_USE_COCOA
}
+#endif // QT_MAC_USE_COCOA
QStringList qt_mac_NSArrayToQStringList(void *nsarray)
{
@@ -1323,6 +1500,7 @@ void *qt_mac_QStringListToNSMutableArrayVoid(const QStringList &list)
return result;
}
+#if QT_MAC_USE_COCOA
void qt_syncCocoaTitleBarButtons(OSWindowRef window, QWidget *widgetForWindow)
{
if (!widgetForWindow)
@@ -1347,6 +1525,7 @@ void qt_syncCocoaTitleBarButtons(OSWindowRef window, QWidget *widgetForWindow)
[window setShowsToolbarButton:uint(flags & Qt::MacWindowToolBarButtonHint) != 0];
}
+#endif // QT_MAC_USE_COCOA
// Carbon: Make sure you call QDEndContext on the context when done with it.
CGContextRef qt_mac_graphicsContextFor(QWidget *widget)
@@ -1448,6 +1627,7 @@ void qt_mac_constructQIconFromIconRef(const IconRef icon, const IconRef overlayI
}
}
+#ifdef QT_MAC_USE_COCOA
void qt_mac_menu_collapseSeparators(void */*NSMenu **/ theMenu, bool collapse)
{
OSMenuRef menu = static_cast<OSMenuRef>(theMenu);
@@ -1481,12 +1661,24 @@ void qt_mac_menu_collapseSeparators(void */*NSMenu **/ theMenu, bool collapse)
}
}
-#ifdef QT_MAC_USE_COCOA
-void qt_cocoaChangeOverrideCursor(const QCursor &cursor)
+class CocoaPostMessageAfterEventLoopExitHelp : public QObject
{
- QMacCocoaAutoReleasePool pool;
- [static_cast<NSCursor *>(qt_mac_nsCursorForQCursor(cursor)) set];
-}
+ id target;
+ SEL selector;
+ int argCount;
+ id arg1;
+ id arg2;
+public:
+ CocoaPostMessageAfterEventLoopExitHelp(id target, SEL selector, int argCount, id arg1, id arg2)
+ : target(target), selector(selector), argCount(argCount), arg1(arg1), arg2(arg2){
+ deleteLater();
+ }
+
+ ~CocoaPostMessageAfterEventLoopExitHelp()
+ {
+ qt_cocoaPostMessage(target, selector, argCount, arg1, arg2);
+ }
+};
void qt_cocoaPostMessage(id target, SEL selector, int argCount, id arg1, id arg2)
{
@@ -1500,6 +1692,15 @@ void qt_cocoaPostMessage(id target, SEL selector, int argCount, id arg1, id arg2
context:nil subtype:QtCocoaEventSubTypePostMessage data1:lower data2:upper];
[NSApp postEvent:e atStart:NO];
}
+
+void qt_cocoaPostMessageAfterEventLoopExit(id target, SEL selector, int argCount, id arg1, id arg2)
+{
+ if (QApplicationPrivate::instance()->threadData->eventLoops.size() <= 1)
+ qt_cocoaPostMessage(target, selector, argCount, arg1, arg2);
+ else
+ new CocoaPostMessageAfterEventLoopExitHelp(target, selector, argCount, arg1, arg2);
+}
+
#endif
QMacCocoaAutoReleasePool::QMacCocoaAutoReleasePool()
@@ -1523,6 +1724,12 @@ void qt_mac_post_retranslateAppMenu()
#endif
}
+QWidgetPrivate *QMacScrollOptimization::_target = 0;
+bool QMacScrollOptimization::_inWheelEvent = false;
+int QMacScrollOptimization::_dx = 0;
+int QMacScrollOptimization::_dy = 0;
+QRect QMacScrollOptimization::_scrollRect = QRect(0, 0, -1, -1);
+
#ifdef QT_MAC_USE_COCOA
// This method implements the magic for the drawRectSpecial method.
// We draw a line at the upper edge of the content view in order to