macOS: Transition to new QPA dag-and-drop API

The new API allows us to pass the mouse buttons and
keyboard modifiers along with the QWSI event.

Task-number: QTBUG-57168
Change-Id: Ic54c012d1593d922e7dcd31facab2f2c630c7996
Reviewed-by: Gatis Paeglis <gatis.paeglis@qt.io>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
bb10
Mikhail Svetkin 2018-04-27 12:05:06 +02:00
parent 60457e6cd0
commit c427ba53aa
4 changed files with 105 additions and 25 deletions

View File

@ -98,6 +98,12 @@ QPointF qt_mac_flip(const QPointF &pos, const QRectF &reference);
QRectF qt_mac_flip(const QRectF &rect, const QRectF &reference);
Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum);
Qt::MouseButton cocoaButton2QtButton(NSEvent *event);
QEvent::Type cocoaEvent2QtMouseEvent(NSEvent *event);
Qt::MouseButtons cocoaMouseButtons2QtMouseButtons(NSInteger pressedMouseButtons);
Qt::MouseButtons currentlyPressedMouseButtons();
// strip out '&' characters, and convert "&&" to a single '&', in menu
// text - since menu text is sometimes decorated with these for Windows

View File

@ -278,6 +278,77 @@ Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum)
return Qt::NoButton;
}
/*!
\fn Qt::MouseButton cocoaButton2QtButton(NSEvent *event)
Returns the Qt::Button that corresponds to an NSEvent.buttonNumber.
\note AppKit will use buttonNumber 0 to indicate both "left button"
and "no button". Only NSEvents that describes mouse press/release/dragging
events (e.g NSEventTypeOtherMouseDown) will contain a valid
button number.
*/
Qt::MouseButton cocoaButton2QtButton(NSEvent *event)
{
if (event.type == NSMouseMoved)
return Qt::NoButton;
return cocoaButton2QtButton(event.buttonNumber);
}
/*!
\fn QEvent::Type cocoaEvent2QtMouseEvent(NSEvent *event)
Returns the QEvent::Type that corresponds to an NSEvent.type.
*/
QEvent::Type cocoaEvent2QtMouseEvent(NSEvent *event)
{
switch (event.type) {
case NSLeftMouseDown:
case NSRightMouseDown:
case NSOtherMouseDown:
return QEvent::MouseButtonPress;
case NSLeftMouseUp:
case NSRightMouseUp:
case NSOtherMouseUp:
return QEvent::MouseButtonRelease;
case NSLeftMouseDragged:
case NSRightMouseDragged:
case NSOtherMouseDragged:
return QEvent::MouseMove;
case NSMouseMoved:
return QEvent::MouseMove;
default:
break;
}
return QEvent::None;
}
/*!
\fn Qt::MouseButtons cocoaMouseButtons2QtMouseButtons(NSInteger pressedMouseButtons)
Returns the Qt::MouseButtons that corresponds to an NSEvent.pressedMouseButtons.
*/
Qt::MouseButtons cocoaMouseButtons2QtMouseButtons(NSInteger pressedMouseButtons)
{
return static_cast<Qt::MouseButton>(pressedMouseButtons & Qt::MouseButtonMask);
}
/*!
\fn Qt::MouseButtons currentlyPressedMouseButtons()
Returns the Qt::MouseButtons that corresponds to an NSEvent.pressedMouseButtons.
*/
Qt::MouseButtons currentlyPressedMouseButtons()
{
return cocoaMouseButtons2QtMouseButtons(NSEvent.pressedMouseButtons);
}
QString qt_mac_removeAmpersandEscapes(QString s)
{
return QPlatformTheme::removeMnemonics(s).trimmed();

View File

@ -207,18 +207,21 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin
if (!target)
return NSDragOperationNone;
// update these so selecting move/copy/link works
QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers: [[NSApp currentEvent] modifierFlags]];
const auto modifiers = [QNSView convertKeyModifiers:NSApp.currentEvent.modifierFlags];
const auto buttons = currentlyPressedMouseButtons();
const auto point = mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint);
QPlatformDragQtResponse response(false, Qt::IgnoreAction, QRect());
QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag();
if (nativeDrag->currentDrag()) {
// The drag was started from within the application
response = QWindowSystemInterface::handleDrag(target, nativeDrag->dragMimeData(), mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint), qtAllowed);
response = QWindowSystemInterface::handleDrag(target, nativeDrag->dragMimeData(),
point, qtAllowed, buttons, modifiers);
[self updateCursorFromDragResponse:response drag:nativeDrag];
} else {
QCocoaDropData mimeData([sender draggingPasteboard]);
response = QWindowSystemInterface::handleDrag(target, &mimeData, mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint), qtAllowed);
response = QWindowSystemInterface::handleDrag(target, &mimeData,
point, qtAllowed, buttons, modifiers);
}
return qt_mac_mapDropAction(response.acceptedAction());
@ -237,7 +240,9 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin
QPoint qt_windowPoint(windowPoint.x, windowPoint.y);
// Send 0 mime data to indicate drag exit
QWindowSystemInterface::handleDrag(target, 0, mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint), Qt::IgnoreAction);
QWindowSystemInterface::handleDrag(target, nullptr,
mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint),
Qt::IgnoreAction, Qt::NoButton, Qt::NoModifier);
}
// called on drop, send the drop to Qt and return if it was accepted.
@ -256,12 +261,18 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin
QPlatformDropQtResponse response(false, Qt::IgnoreAction);
QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag();
const auto modifiers = [QNSView convertKeyModifiers:NSApp.currentEvent.modifierFlags];
const auto buttons = currentlyPressedMouseButtons();
const auto point = mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint);
if (nativeDrag->currentDrag()) {
// The drag was started from within the application
response = QWindowSystemInterface::handleDrop(target, nativeDrag->dragMimeData(), mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint), qtAllowed);
response = QWindowSystemInterface::handleDrop(target, nativeDrag->dragMimeData(),
point, qtAllowed, buttons, modifiers);
} else {
QCocoaDropData mimeData([sender draggingPasteboard]);
response = QWindowSystemInterface::handleDrop(target, &mimeData, mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint), qtAllowed);
response = QWindowSystemInterface::handleDrop(target, &mimeData,
point, qtAllowed, buttons, modifiers);
}
return response.isAccepted();
}
@ -271,7 +282,7 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin
operation:(NSDragOperation)operation
{
Q_UNUSED(session);
Q_UNUSED(operation);
Q_UNUSED(screenPoint);
if (!m_platformWindow)
return;
@ -283,20 +294,7 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin
QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag();
nativeDrag->setAcceptedAction(qt_mac_mapNSDragOperation(operation));
// keep our state, and QGuiApplication state (buttons member) in-sync,
// or future mouse events will be processed incorrectly
NSUInteger pmb = [NSEvent pressedMouseButtons];
for (int buttonNumber = 0; buttonNumber < 32; buttonNumber++) { // see cocoaButton2QtButton() for the 32 value
if (!(pmb & (1 << buttonNumber)))
m_buttons &= ~cocoaButton2QtButton(buttonNumber);
}
NSPoint windowPoint = [self.window convertRectFromScreen:NSMakeRect(screenPoint.x, screenPoint.y, 1, 1)].origin;
NSPoint nsViewPoint = [self convertPoint: windowPoint fromView: nil]; // NSView/QWindow coordinates
QPoint qtWindowPoint(nsViewPoint.x, nsViewPoint.y);
QPoint qtScreenPoint = QCocoaScreen::mapFromNative(screenPoint).toPoint();
QWindowSystemInterface::handleMouseEvent(target, mapWindowCoordinates(m_platformWindow->window(), target, qtWindowPoint), qtScreenPoint, m_buttons);
m_buttons = currentlyPressedMouseButtons();
}
@end

View File

@ -201,9 +201,14 @@
QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag();
nativeDrag->setLastMouseEvent(theEvent, self);
Qt::KeyboardModifiers keyboardModifiers = [QNSView convertKeyModifiers:[theEvent modifierFlags]];
QWindowSystemInterface::handleMouseEvent(targetView->m_platformWindow->window(), timestamp, qtWindowPoint, qtScreenPoint,
m_buttons, keyboardModifiers, Qt::MouseEventNotSynthesized);
const auto modifiers = [QNSView convertKeyModifiers:theEvent.modifierFlags];
const auto buttons = currentlyPressedMouseButtons();
const auto button = cocoaButton2QtButton(theEvent);
const auto eventType = cocoaEvent2QtMouseEvent(theEvent);
QWindowSystemInterface::handleMouseEvent(targetView->m_platformWindow->window(),
timestamp, qtWindowPoint, qtScreenPoint,
buttons, button, eventType, modifiers);
}
- (bool)handleMouseDownEvent:(NSEvent *)theEvent withButton:(int)buttonNumber