From b494d859a7fc18ac3e6d9a57194c1ac7dc1855ab Mon Sep 17 00:00:00 2001
From: Richard Moe Gustavsen <richard.gustavsen@theqtcompany.com>
Date: Fri, 28 Aug 2015 10:57:44 +0200
Subject: [PATCH] iOS: filter first responder actions from edit menu
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

UIResponderStandardEditActions found in first responder will be prepended to
the edit menu automatically (or e.g made available as buttons on the virtual
keyboard). So we filter them out to avoid duplicates, and let first responder
handle the actions instead. In case of QIOSTextResponder, edit actions will be
converted to key events that ends up triggering the shortcuts of the filtered
menu items.

Change-Id: I046c6cc5b358d8a6f7623e10579e2dcd92f75139
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@theqtcompany.com>
---
 src/plugins/platforms/ios/qiosmenu.h  |  1 +
 src/plugins/platforms/ios/qiosmenu.mm | 32 ++++++++++++++++++++++++++-
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/src/plugins/platforms/ios/qiosmenu.h b/src/plugins/platforms/ios/qiosmenu.h
index 5bebcc3cc61..ec23b555078 100644
--- a/src/plugins/platforms/ios/qiosmenu.h
+++ b/src/plugins/platforms/ios/qiosmenu.h
@@ -135,6 +135,7 @@ private:
     void toggleShowUsingUIMenuController(bool show);
     void toggleShowUsingUIPickerView(bool show);
     QIOSMenuItemList visibleMenuItems() const;
+    QIOSMenuItemList filterFirstResponderActions(const QIOSMenuItemList &menuItems);
     void repositionMenu();
 };
 
diff --git a/src/plugins/platforms/ios/qiosmenu.mm b/src/plugins/platforms/ios/qiosmenu.mm
index 9936296ae8e..de77097bf8f 100644
--- a/src/plugins/platforms/ios/qiosmenu.mm
+++ b/src/plugins/platforms/ios/qiosmenu.mm
@@ -474,7 +474,7 @@ void QIOSMenu::toggleShowUsingUIMenuController(bool show)
 {
     if (show) {
         Q_ASSERT(!m_menuController);
-        m_menuController = [[QUIMenuController alloc] initWithVisibleMenuItems:visibleMenuItems()];
+        m_menuController = [[QUIMenuController alloc] initWithVisibleMenuItems:filterFirstResponderActions(visibleMenuItems())];
         repositionMenu();
         connect(qGuiApp->inputMethod(), &QInputMethod::keyboardRectangleChanged, this, &QIOSMenu::repositionMenu);
     } else {
@@ -547,6 +547,36 @@ QIOSMenuItemList QIOSMenu::visibleMenuItems() const
     return visibleMenuItems;
 }
 
+QIOSMenuItemList QIOSMenu::filterFirstResponderActions(const QIOSMenuItemList &menuItems)
+{
+    // UIResponderStandardEditActions found in first responder will be prepended to the edit
+    // menu automatically (or e.g made available as buttons on the virtual keyboard). So we
+    // filter them out to avoid duplicates, and let first responder handle the actions instead.
+    // In case of QIOSTextResponder, edit actions will be converted to key events that ends up
+    // triggering the shortcuts of the filtered menu items.
+    QIOSMenuItemList filteredMenuItems;
+    UIResponder *responder = [UIResponder currentFirstResponder];
+
+    for (int i = 0; i < menuItems.count(); ++i) {
+        QIOSMenuItem *menuItem = menuItems.at(i);
+        QKeySequence shortcut = menuItem->m_shortcut;
+        if ((shortcut == QKeySequence::Cut && [responder canPerformAction:@selector(cut:) withSender:nil])
+                || (shortcut == QKeySequence::Copy && [responder canPerformAction:@selector(copy:) withSender:nil])
+                || (shortcut == QKeySequence::Paste && [responder canPerformAction:@selector(paste:) withSender:nil])
+                || (shortcut == QKeySequence::Delete && [responder canPerformAction:@selector(delete:) withSender:nil])
+                || (shortcut == QKeySequence::SelectAll && [responder canPerformAction:@selector(selectAll:) withSender:nil])
+                || (shortcut == QKeySequence::Undo && [responder canPerformAction:@selector(undo:) withSender:nil])
+                || (shortcut == QKeySequence::Redo && [responder canPerformAction:@selector(redo:) withSender:nil])
+                || (shortcut == QKeySequence::Bold && [responder canPerformAction:@selector(toggleBoldface:) withSender:nil])
+                || (shortcut == QKeySequence::Italic && [responder canPerformAction:@selector(toggleItalics:) withSender:nil])
+                || (shortcut == QKeySequence::Underline && [responder canPerformAction:@selector(toggleUnderline:) withSender:nil])) {
+            continue;
+        }
+        filteredMenuItems.append(menuItem);
+    }
+    return filteredMenuItems;
+}
+
 void QIOSMenu::repositionMenu()
 {
     switch (m_effectiveMenuType) {
-- 
GitLab