summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2021-10-19 19:22:32 +0200
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2021-10-21 16:05:47 +0200
commitd42cfeb84faf154b46f2811b2059946b396fcc12 (patch)
tree983dd633326c9ceb4908f79066c29a6641bae17e /src/plugins/platforms
parente2fc3246d24e2b3a64ec2005e51efae88cbdc32e (diff)
macOS: add default Edit menu items, if not added by AppKit
AppKit automatically appends "Start Dictation..." and "Emoji & Symbols" menu items, after a separator, to a menu in the menu bar that has the title "Edit" in the operating system language. Qt applications might however be translated to some other language, in which case the "Edit" menu is not recognized by AppKit, and the menu items won't be added. This is bad for accessibility and for users wanting to type emojis. If we have a menu that has the title "Edit" as translated in Qt's i18n system, then create those items manually. To prevent a duplication of the system- provided menu items, don't add the items if there already is one with the action being set to the relevant selector. Otherwise, perform the selector or call the NSApplication method ourselves. This then results in the relevant keyboard input through regular code paths. Fixes: QTBUG-79565 Change-Id: Ifd06036211756277550d398034689aca8e770133 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenubar.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenubar.mm47
2 files changed, 49 insertions, 0 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.h b/src/plugins/platforms/cocoa/qcocoamenubar.h
index 7186e48829..0054cdf6ad 100644
--- a/src/plugins/platforms/cocoa/qcocoamenubar.h
+++ b/src/plugins/platforms/cocoa/qcocoamenubar.h
@@ -80,12 +80,14 @@ private:
bool needsImmediateUpdate();
bool shouldDisable(QCocoaWindow *active) const;
+ void insertDefaultEditItems(QCocoaMenu *menu);
NSMenuItem *nativeItemForMenu(QCocoaMenu *menu) const;
QList<QPointer<QCocoaMenu> > m_menus;
NSMenu *m_nativeMenu;
QPointer<QCocoaWindow> m_window;
+ QList<QPointer<QCocoaMenuItem>> m_defaultEditMenuItems;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm
index 2e0eeb06e3..524746f952 100644
--- a/src/plugins/platforms/cocoa/qcocoamenubar.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm
@@ -194,6 +194,11 @@ void QCocoaMenuBar::syncMenu_helper(QPlatformMenu *menu, bool menubarUpdate)
for (QCocoaMenuItem *item : cocoaMenu->items())
cocoaMenu->syncMenuItem_helper(item, menubarUpdate);
+ const QString captionNoAmpersand = QString::fromNSString(cocoaMenu->nsMenu().title)
+ .remove(QLatin1Char('&'));
+ if (captionNoAmpersand == QCoreApplication::translate("QCocoaMenu", "Edit"))
+ insertDefaultEditItems(cocoaMenu);
+
BOOL shouldHide = YES;
if (cocoaMenu->isVisible()) {
// If the NSMenu has no visible items, or only separators, we should hide it
@@ -400,6 +405,48 @@ QCocoaWindow *QCocoaMenuBar::cocoaWindow() const
return m_window.data();
}
+void QCocoaMenuBar::insertDefaultEditItems(QCocoaMenu *menu)
+{
+ if (menu->items().isEmpty())
+ return;
+
+ NSMenu *nsEditMenu = menu->nsMenu();
+ if ([nsEditMenu itemAtIndex:nsEditMenu.numberOfItems - 1].action
+ == @selector(orderFrontCharacterPalette:)) {
+ for (auto defaultEditMenuItem : qAsConst(m_defaultEditMenuItems)) {
+ if (menu->items().contains(defaultEditMenuItem))
+ menu->removeMenuItem(defaultEditMenuItem);
+ }
+ qDeleteAll(m_defaultEditMenuItems);
+ m_defaultEditMenuItems.clear();
+ } else {
+ if (m_defaultEditMenuItems.isEmpty()) {
+ QCocoaMenuItem *separator = new QCocoaMenuItem;
+ separator->setIsSeparator(true);
+
+ QCocoaMenuItem *dictationItem = new QCocoaMenuItem;
+ dictationItem->setText(QCoreApplication::translate("QCocoaMenuItem", "Start Dictation..."));
+ QObject::connect(dictationItem, &QPlatformMenuItem::activated, this, []{
+ [NSApplication.sharedApplication performSelector:@selector(startDictation:)];
+ });
+
+ QCocoaMenuItem *emojiItem = new QCocoaMenuItem;
+ emojiItem->setText(QCoreApplication::translate("QCocoaMenuItem", "Emoji && Symbols"));
+ emojiItem->setShortcut(QKeyCombination(Qt::MetaModifier|Qt::ControlModifier, Qt::Key_Space));
+ QObject::connect(emojiItem, &QPlatformMenuItem::activated, this, []{
+ [NSApplication.sharedApplication orderFrontCharacterPalette:nil];
+ });
+
+ m_defaultEditMenuItems << separator << dictationItem << emojiItem;
+ }
+ for (auto defaultEditMenuItem : qAsConst(m_defaultEditMenuItems)) {
+ if (menu->items().contains(defaultEditMenuItem))
+ menu->removeMenuItem(defaultEditMenuItem);
+ menu->insertMenuItem(defaultEditMenuItem, nullptr);
+ }
+ }
+}
+
QT_END_NAMESPACE
#include "moc_qcocoamenubar.cpp"