summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/cocoa/qcocoamenubar.mm
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@digia.com>2014-03-31 14:17:29 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-04-07 08:30:24 +0200
commitb5eb850e0deb61ff71e26a5a2d0e070b91306aa2 (patch)
tree957dcbb14ee657afd74348cd4fd0179650401e5b /src/plugins/platforms/cocoa/qcocoamenubar.mm
parenta7f98a7ac01a9faa08d1119cf4d5550c50e00005 (diff)
OSX: add several menuitem roles to support menu shortcuts in dialogs
Now menu items and key shortcuts for Cut, Copy, Paste and Select All work in the standard ways in dialogs such as the file dialog, provided that the corresponding QActions have been created and added to the menu. This depends on new roles to identify each menu item which is so broadly applicable that it should work even when a native widget has focus; but the role will be auto-detected, just as we were already doing for application menu items such as Quit, About and Preferences. When the QFileDialog is opened, it will call redirectKnownMenuItemsToFirstResponder() which will make only those "special" menu items have the standard actions and nil targets. When the dialog is dismissed, those NSMenuItems must be reverted by calling resetKnownMenuItemsToQt(), because to invoke a QAction, the NSMenuItem's action should be itemFired and the target should be the QCocoaMenuDelegate. Task-number: QTBUG-17291 Change-Id: I501375ca6fa13fac75d4b4fdcede993ec2329cc7 Reviewed-by: Morten Johan Sørvig <morten.sorvig@digia.com>
Diffstat (limited to 'src/plugins/platforms/cocoa/qcocoamenubar.mm')
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenubar.mm63
1 files changed, 63 insertions, 0 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm
index 7335deb800..ffc0fabdce 100644
--- a/src/plugins/platforms/cocoa/qcocoamenubar.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm
@@ -205,6 +205,59 @@ QCocoaMenuBar *QCocoaMenuBar::findGlobalMenubar()
return NULL;
}
+void QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder()
+{
+ // QTBUG-17291: http://forums.macrumors.com/showthread.php?t=1249452
+ // When a dialog is opened, shortcuts for actions inside the dialog (cut, paste, ...)
+ // continue to go through the same menu items which claimed those shortcuts.
+ // They are not keystrokes which we can intercept in any other way; the OS intercepts them.
+ // The menu items had to be created by the application. That's why we need roles
+ // to identify those "special" menu items which can be useful even when non-Qt
+ // native widgets are in focus. When the native widget is focused it will be the
+ // first responder, so the menu item needs to have its target be the first responder;
+ // this is done by setting it to nil.
+
+ // This function will find all menu items on all menus which have
+ // "special" roles, set the target and also set the standard actions which
+ // apply to those roles. But afterwards it is necessary to call
+ // resetKnownMenuItemsToQt() to put back the target and action so that
+ // those menu items will go back to invoking their associated QActions.
+ foreach (QCocoaMenuBar *mb, static_menubars)
+ foreach (QCocoaMenu *m, mb->m_menus)
+ foreach (QCocoaMenuItem *i, m->items()) {
+ bool known = true;
+ switch (i->effectiveRole()) {
+ case QPlatformMenuItem::CutRole:
+ [i->nsItem() setAction:@selector(cut:)];
+ break;
+ case QPlatformMenuItem::CopyRole:
+ [i->nsItem() setAction:@selector(copy:)];
+ break;
+ case QPlatformMenuItem::PasteRole:
+ [i->nsItem() setAction:@selector(paste:)];
+ break;
+ case QPlatformMenuItem::SelectAllRole:
+ [i->nsItem() setAction:@selector(selectAll:)];
+ break;
+ // We may discover later that there are other roles/actions which
+ // are meaningful to standard native widgets; they can be added.
+ default:
+ known = false;
+ break;
+ }
+ if (known)
+ [i->nsItem() setTarget:nil];
+ }
+}
+
+void QCocoaMenuBar::resetKnownMenuItemsToQt()
+{
+ // Undo the effect of redirectKnownMenuItemsToFirstResponder():
+ // set the menu items' actions to itemFired and their targets to
+ // the QCocoaMenuDelegate.
+ updateMenuBarImmediately();
+}
+
void QCocoaMenuBar::updateMenuBarImmediately()
{
QCocoaAutoReleasePool pool;
@@ -321,3 +374,13 @@ QPlatformMenu *QCocoaMenuBar::menuForTag(quintptr tag) const
return 0;
}
+
+NSMenuItem *QCocoaMenuBar::itemForRole(QPlatformMenuItem::MenuRole r)
+{
+ foreach (QCocoaMenu *m, m_menus)
+ foreach (QCocoaMenuItem *i, m->items())
+ if (i->effectiveRole() == r)
+ return i->nsItem();
+ return Q_NULLPTR;
+}
+