summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/cocoa
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2023-03-16 17:22:57 +0100
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2023-03-20 17:39:18 +0100
commit3bedeb837ef68e0062668406e7662ed9ffc5268a (patch)
treec695616952c5dc3667e20d657fd54086cbbbc45b /src/plugins/platforms/cocoa
parent391491c8b355fd06d0b86ef81614323a3666eb15 (diff)
macOS: Bail out if handling cut/copy/paste action from non-Qt NSMenuItem
The typical way to set up menus on macOS, which we follow, is to create NSMenuItems with an action selector set (copy:), but without a target. This will result in AppKit finding a target dynamically, starting with the first responder, walking the responder chain, and then moving on to other NSWindows, before ending up in the NSApplication and its delegate. Unfortunately, we don't have a mechanism in Qt to forward generic actions, such as the cut/copy/paste, or selectAll, so we rely on mapping the actions back to QCocoaNSMenuItem that we can trace back to a QPlatformMenuItem that we in turn emit activated() for. Normally this works fine, but in the case where the Qt app is embedded in a native UI, which has its own menu items with cut/copy/paste, we'll get callbacks into QNSView for actions triggered by a generic NSMenuItem. In that case, we need to bail out, but we must do so without calling [super forwardInvocation:invocation], as that will just try to invoke the action on ourselves again. It's unfortunately too late to try to redirect the action to another responder, that might have handled the action, and it's questionable whether that would be the behavior we'd want, as that would possibly result in e.g. pasting text into another window than the Qt one that currently has an active cursor in a text entry. Fixes: QTBUG-111916 Pick-to: 6.5 Change-Id: I56318e4f7efd779cd20bf577aec8c2de04a6a142 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src/plugins/platforms/cocoa')
-rw-r--r--src/plugins/platforms/cocoa/qnsview_menus.mm18
1 files changed, 15 insertions, 3 deletions
diff --git a/src/plugins/platforms/cocoa/qnsview_menus.mm b/src/plugins/platforms/cocoa/qnsview_menus.mm
index 7a541c599c..644f2139de 100644
--- a/src/plugins/platforms/cocoa/qnsview_menus.mm
+++ b/src/plugins/platforms/cocoa/qnsview_menus.mm
@@ -91,10 +91,22 @@ static bool selectorIsCutCopyPaste(SEL selector)
NSObject *sender;
[invocation getArgument:&sender atIndex:2];
qCDebug(lcQpaMenus) << "Forwarding" << invocation.selector << "from" << sender;
- if (auto *nativeItem = qt_objc_cast<QCocoaNSMenuItem *>(sender)) {
+
+ // We claim to respond to standard edit actions such as cut/copy/paste,
+ // but these might not be exclusively coming from menu items that we
+ // control. For example, when embedded into a native UI (as a plugin),
+ // the menu items might be part of the host application, and if we're
+ // the first responder, we'll be the target of these actions. As we
+ // don't have a mechanism in Qt to trigger generic actions, we have
+ // to bail out if we don't have a QCocoaNSMenuItem we can activate().
+ // Note that we skip the call to super as well, as that would just
+ // try to invoke the current action on ourselves again.
+ if (auto *nativeItem = qt_objc_cast<QCocoaNSMenuItem *>(sender))
[self qt_itemFired:nativeItem];
- return;
- }
+ else
+ qCDebug(lcQpaMenus) << "Ignoring action for menu item we didn't create";
+
+ return;
}
[super forwardInvocation:invocation];