From bee823db3a4c464cea910c7db7f208ab7f64030f Mon Sep 17 00:00:00 2001
From: Morph <39850852+Morph1984@users.noreply.github.com>
Date: Sun, 24 Jul 2022 07:21:02 -0400
Subject: [PATCH] applet/swkbd: Implement optional symbol keys

These are only used in the numeric keyboard, and correspond to the keys to the left and right of the "0" key on the numeric keyboard.
---
 src/core/frontend/applets/software_keyboard.h |  2 +
 .../am/applets/applet_software_keyboard.cpp   |  6 +++
 src/yuzu/applets/qt_software_keyboard.cpp     | 23 +++++++++--
 src/yuzu/applets/qt_software_keyboard.h       |  2 +-
 src/yuzu/applets/qt_software_keyboard.ui      | 38 +++++++++++++++++++
 5 files changed, 67 insertions(+), 4 deletions(-)

diff --git a/src/core/frontend/applets/software_keyboard.h b/src/core/frontend/applets/software_keyboard.h
index a405e3c94..094d1e713 100644
--- a/src/core/frontend/applets/software_keyboard.h
+++ b/src/core/frontend/applets/software_keyboard.h
@@ -17,6 +17,8 @@ struct KeyboardInitializeParameters {
     std::u16string sub_text;
     std::u16string guide_text;
     std::u16string initial_text;
+    char16_t left_optional_symbol_key;
+    char16_t right_optional_symbol_key;
     u32 max_text_length;
     u32 min_text_length;
     s32 initial_cursor_position;
diff --git a/src/core/hle/service/am/applets/applet_software_keyboard.cpp b/src/core/hle/service/am/applets/applet_software_keyboard.cpp
index faa092957..c18236045 100644
--- a/src/core/hle/service/am/applets/applet_software_keyboard.cpp
+++ b/src/core/hle/service/am/applets/applet_software_keyboard.cpp
@@ -536,6 +536,8 @@ void SoftwareKeyboard::InitializeFrontendNormalKeyboard() {
         .sub_text{std::move(sub_text)},
         .guide_text{std::move(guide_text)},
         .initial_text{initial_text},
+        .left_optional_symbol_key{swkbd_config_common.left_optional_symbol_key},
+        .right_optional_symbol_key{swkbd_config_common.right_optional_symbol_key},
         .max_text_length{max_text_length},
         .min_text_length{min_text_length},
         .initial_cursor_position{initial_cursor_position},
@@ -591,6 +593,8 @@ void SoftwareKeyboard::InitializeFrontendInlineKeyboardOld() {
         .sub_text{},
         .guide_text{},
         .initial_text{current_text},
+        .left_optional_symbol_key{appear_arg.left_optional_symbol_key},
+        .right_optional_symbol_key{appear_arg.right_optional_symbol_key},
         .max_text_length{max_text_length},
         .min_text_length{min_text_length},
         .initial_cursor_position{initial_cursor_position},
@@ -632,6 +636,8 @@ void SoftwareKeyboard::InitializeFrontendInlineKeyboardNew() {
         .sub_text{},
         .guide_text{},
         .initial_text{current_text},
+        .left_optional_symbol_key{appear_arg.left_optional_symbol_key},
+        .right_optional_symbol_key{appear_arg.right_optional_symbol_key},
         .max_text_length{max_text_length},
         .min_text_length{min_text_length},
         .initial_cursor_position{initial_cursor_position},
diff --git a/src/yuzu/applets/qt_software_keyboard.cpp b/src/yuzu/applets/qt_software_keyboard.cpp
index e8b217d90..91dca2760 100644
--- a/src/yuzu/applets/qt_software_keyboard.cpp
+++ b/src/yuzu/applets/qt_software_keyboard.cpp
@@ -213,9 +213,9 @@ QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog(
             ui->button_ok_num,
         },
         {
-            nullptr,
+            ui->button_left_optional_num,
             ui->button_0_num,
-            nullptr,
+            ui->button_right_optional_num,
             ui->button_ok_num,
         },
     }};
@@ -330,7 +330,9 @@ QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog(
         ui->button_7_num,
         ui->button_8_num,
         ui->button_9_num,
+        ui->button_left_optional_num,
         ui->button_0_num,
+        ui->button_right_optional_num,
     };
 
     SetupMouseHover();
@@ -342,6 +344,9 @@ QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog(
     ui->label_header->setText(QString::fromStdU16String(initialize_parameters.header_text));
     ui->label_sub->setText(QString::fromStdU16String(initialize_parameters.sub_text));
 
+    ui->button_left_optional_num->setText(QChar{initialize_parameters.left_optional_symbol_key});
+    ui->button_right_optional_num->setText(QChar{initialize_parameters.right_optional_symbol_key});
+
     current_text = initialize_parameters.initial_text;
     cursor_position = initialize_parameters.initial_cursor_position;
 
@@ -932,6 +937,15 @@ void QtSoftwareKeyboardDialog::DisableKeyboardButtons() {
                 button->setEnabled(true);
             }
         }
+
+        const auto enable_left_optional = initialize_parameters.left_optional_symbol_key != '\0';
+        const auto enable_right_optional = initialize_parameters.right_optional_symbol_key != '\0';
+
+        ui->button_left_optional_num->setEnabled(enable_left_optional);
+        ui->button_left_optional_num->setVisible(enable_left_optional);
+
+        ui->button_right_optional_num->setEnabled(enable_right_optional);
+        ui->button_right_optional_num->setVisible(enable_right_optional);
         break;
     }
     }
@@ -1019,7 +1033,10 @@ bool QtSoftwareKeyboardDialog::ValidateInputText(const QString& input_text) {
     }
 
     if (bottom_osk_index == BottomOSKIndex::NumberPad &&
-        std::any_of(input_text.begin(), input_text.end(), [](QChar c) { return !c.isDigit(); })) {
+        std::any_of(input_text.begin(), input_text.end(), [this](QChar c) {
+            return !c.isDigit() && c != QChar{initialize_parameters.left_optional_symbol_key} &&
+                   c != QChar{initialize_parameters.right_optional_symbol_key};
+        })) {
         return false;
     }
 
diff --git a/src/yuzu/applets/qt_software_keyboard.h b/src/yuzu/applets/qt_software_keyboard.h
index 1c489fbb6..35d4ee2ef 100644
--- a/src/yuzu/applets/qt_software_keyboard.h
+++ b/src/yuzu/applets/qt_software_keyboard.h
@@ -211,7 +211,7 @@ private:
     std::array<std::array<QPushButton*, NUM_COLUMNS_NUMPAD>, NUM_ROWS_NUMPAD> numberpad_buttons;
 
     // Contains a set of all buttons used in keyboard_buttons and numberpad_buttons.
-    std::array<QPushButton*, 110> all_buttons;
+    std::array<QPushButton*, 112> all_buttons;
 
     std::size_t row{0};
     std::size_t column{0};
diff --git a/src/yuzu/applets/qt_software_keyboard.ui b/src/yuzu/applets/qt_software_keyboard.ui
index b0a1fcde9..9661cb260 100644
--- a/src/yuzu/applets/qt_software_keyboard.ui
+++ b/src/yuzu/applets/qt_software_keyboard.ui
@@ -3298,6 +3298,24 @@ p, li { white-space: pre-wrap; }
               </property>
              </widget>
             </item>
+            <item row="4" column="2">
+             <widget class="QPushButton" name="button_left_optional_num">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+                <horstretch>1</horstretch>
+                <verstretch>1</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="font">
+               <font>
+                <pointsize>28</pointsize>
+               </font>
+              </property>
+              <property name="text">
+               <string notr="true"></string>
+              </property>
+             </widget>
+            </item>
             <item row="4" column="3">
              <widget class="QPushButton" name="button_0_num">
               <property name="sizePolicy">
@@ -3316,6 +3334,24 @@ p, li { white-space: pre-wrap; }
               </property>
              </widget>
             </item>
+            <item row="4" column="4">
+             <widget class="QPushButton" name="button_right_optional_num">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+                <horstretch>1</horstretch>
+                <verstretch>1</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="font">
+               <font>
+                <pointsize>28</pointsize>
+               </font>
+              </property>
+              <property name="text">
+               <string notr="true"></string>
+              </property>
+             </widget>
+            </item>
             <item row="1" column="4">
              <widget class="QPushButton" name="button_3_num">
               <property name="sizePolicy">
@@ -3494,7 +3530,9 @@ p, li { white-space: pre-wrap; }
   <tabstop>button_7_num</tabstop>
   <tabstop>button_8_num</tabstop>
   <tabstop>button_9_num</tabstop>
+  <tabstop>button_left_optional_num</tabstop>
   <tabstop>button_0_num</tabstop>
+  <tabstop>button_right_optional_num</tabstop>
  </tabstops>
  <resources>
   <include location="../../../dist/icons/overlay/overlay.qrc"/>