summaryrefslogtreecommitdiffstats
path: root/src/yuzu/applets/qt_software_keyboard.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/yuzu/applets/qt_software_keyboard.h')
-rw-r--r--src/yuzu/applets/qt_software_keyboard.h285
1 files changed, 285 insertions, 0 deletions
diff --git a/src/yuzu/applets/qt_software_keyboard.h b/src/yuzu/applets/qt_software_keyboard.h
new file mode 100644
index 000000000..1a03c098c
--- /dev/null
+++ b/src/yuzu/applets/qt_software_keyboard.h
@@ -0,0 +1,285 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <array>
+#include <atomic>
+#include <memory>
+#include <thread>
+
+#include <QDialog>
+#include <QValidator>
+
+#include "core/frontend/applets/software_keyboard.h"
+
+enum class HIDButton : u8;
+
+class InputInterpreter;
+
+namespace Core {
+class System;
+}
+
+namespace Ui {
+class QtSoftwareKeyboardDialog;
+}
+
+class GMainWindow;
+
+class QtSoftwareKeyboardDialog final : public QDialog {
+ Q_OBJECT
+
+public:
+ QtSoftwareKeyboardDialog(QWidget* parent, Core::System& system_, bool is_inline_,
+ Core::Frontend::KeyboardInitializeParameters initialize_parameters_);
+ ~QtSoftwareKeyboardDialog() override;
+
+ void ShowNormalKeyboard(QPoint pos, QSize size);
+
+ void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result,
+ std::u16string text_check_message);
+
+ void ShowInlineKeyboard(Core::Frontend::InlineAppearParameters appear_parameters, QPoint pos,
+ QSize size);
+
+ void HideInlineKeyboard();
+
+ void InlineTextChanged(Core::Frontend::InlineTextParameters text_parameters);
+
+ void ExitKeyboard();
+
+signals:
+ void SubmitNormalText(Service::AM::Applets::SwkbdResult result,
+ std::u16string submitted_text) const;
+
+ void SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type,
+ std::u16string submitted_text, s32 cursor_position) const;
+
+public slots:
+ void open() override;
+ void reject() override;
+
+protected:
+ /// We override the keyPressEvent for inputting text into the inline software keyboard.
+ void keyPressEvent(QKeyEvent* event) override;
+
+private:
+ enum class Direction {
+ Left,
+ Up,
+ Right,
+ Down,
+ };
+
+ enum class BottomOSKIndex {
+ LowerCase,
+ UpperCase,
+ NumberPad,
+ };
+
+ /**
+ * Moves and resizes the window to a specified position and size.
+ *
+ * @param pos Top-left window position
+ * @param size Window size
+ */
+ void MoveAndResizeWindow(QPoint pos, QSize size);
+
+ /**
+ * Rescales all keyboard elements to account for High DPI displays.
+ *
+ * @param width Window width
+ * @param height Window height
+ * @param dpi_scale Display scaling factor
+ */
+ void RescaleKeyboardElements(float width, float height, float dpi_scale);
+
+ /// Sets the keyboard type based on initialize_parameters.
+ void SetKeyboardType();
+
+ /// Sets the password mode based on initialize_parameters.
+ void SetPasswordMode();
+
+ /// Sets the text draw type based on initialize_parameters.
+ void SetTextDrawType();
+
+ /// Sets the controller image at the bottom left of the software keyboard.
+ void SetControllerImage();
+
+ /// Disables buttons based on initialize_parameters.
+ void DisableKeyboardButtons();
+
+ /// Changes whether the backspace or/and ok buttons should be enabled or disabled.
+ void SetBackspaceOkEnabled();
+
+ /**
+ * Validates the input text sent in based on the parameters in initialize_parameters.
+ *
+ * @param input_text Input text
+ *
+ * @returns True if the input text is valid, false otherwise.
+ */
+ bool ValidateInputText(const QString& input_text);
+
+ /// Switches between LowerCase and UpperCase (Shift and Caps Lock)
+ void ChangeBottomOSKIndex();
+
+ /// Processes a keyboard button click from the UI as normal keyboard input.
+ void NormalKeyboardButtonClicked(QPushButton* button);
+
+ /// Processes a keyboard button click from the UI as inline keyboard input.
+ void InlineKeyboardButtonClicked(QPushButton* button);
+
+ /**
+ * Inserts a string of arbitrary length into the current_text at the current cursor position.
+ * This is only used for the inline software keyboard.
+ */
+ void InlineTextInsertString(std::u16string_view string);
+
+ /// Setup the mouse hover workaround for "focusing" buttons. This should only be called once.
+ void SetupMouseHover();
+
+ /**
+ * Handles button presses and converts them into keyboard input.
+ *
+ * @tparam HIDButton The list of buttons that can be converted into keyboard input.
+ */
+ template <HIDButton... T>
+ void HandleButtonPressedOnce();
+
+ /**
+ * Handles button holds and converts them into keyboard input.
+ *
+ * @tparam HIDButton The list of buttons that can be converted into keyboard input.
+ */
+ template <HIDButton... T>
+ void HandleButtonHold();
+
+ /**
+ * Translates a button press to focus or click a keyboard button.
+ *
+ * @param button The button press to process.
+ */
+ void TranslateButtonPress(HIDButton button);
+
+ /**
+ * Moves the focus of a button in a certain direction.
+ *
+ * @param direction The direction to move.
+ */
+ void MoveButtonDirection(Direction direction);
+
+ /**
+ * Moves the text cursor in a certain direction.
+ *
+ * @param direction The direction to move.
+ */
+ void MoveTextCursorDirection(Direction direction);
+
+ void StartInputThread();
+ void StopInputThread();
+
+ /// The thread where input is being polled and processed.
+ void InputThread();
+
+ std::unique_ptr<Ui::QtSoftwareKeyboardDialog> ui;
+
+ Core::System& system;
+
+ // True if it is the inline software keyboard.
+ bool is_inline;
+
+ // Common software keyboard initialize parameters.
+ Core::Frontend::KeyboardInitializeParameters initialize_parameters;
+
+ // Used only by the inline software keyboard since the QLineEdit or QTextEdit is hidden.
+ std::u16string current_text;
+ s32 cursor_position{0};
+
+ static constexpr std::size_t NUM_ROWS_NORMAL = 5;
+ static constexpr std::size_t NUM_COLUMNS_NORMAL = 12;
+ static constexpr std::size_t NUM_ROWS_NUMPAD = 4;
+ static constexpr std::size_t NUM_COLUMNS_NUMPAD = 4;
+
+ // Stores the normal keyboard layout.
+ std::array<std::array<std::array<QPushButton*, NUM_COLUMNS_NORMAL>, NUM_ROWS_NORMAL>, 2>
+ keyboard_buttons;
+ // Stores the numberpad keyboard layout.
+ 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::size_t row{0};
+ std::size_t column{0};
+
+ BottomOSKIndex bottom_osk_index{BottomOSKIndex::LowerCase};
+ std::atomic<bool> caps_lock_enabled{false};
+
+ std::unique_ptr<InputInterpreter> input_interpreter;
+
+ std::thread input_thread;
+
+ std::atomic<bool> input_thread_running{};
+};
+
+class QtSoftwareKeyboard final : public QObject, public Core::Frontend::SoftwareKeyboardApplet {
+ Q_OBJECT
+
+public:
+ explicit QtSoftwareKeyboard(GMainWindow& parent);
+ ~QtSoftwareKeyboard() override;
+
+ void InitializeKeyboard(
+ bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters,
+ std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)>
+ submit_normal_callback_,
+ std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
+ submit_inline_callback_) override;
+
+ void ShowNormalKeyboard() const override;
+
+ void ShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result,
+ std::u16string text_check_message) const override;
+
+ void ShowInlineKeyboard(
+ Core::Frontend::InlineAppearParameters appear_parameters) const override;
+
+ void HideInlineKeyboard() const override;
+
+ void InlineTextChanged(Core::Frontend::InlineTextParameters text_parameters) const override;
+
+ void ExitKeyboard() const override;
+
+signals:
+ void MainWindowInitializeKeyboard(
+ bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters) const;
+
+ void MainWindowShowNormalKeyboard() const;
+
+ void MainWindowShowTextCheckDialog(Service::AM::Applets::SwkbdTextCheckResult text_check_result,
+ std::u16string text_check_message) const;
+
+ void MainWindowShowInlineKeyboard(
+ Core::Frontend::InlineAppearParameters appear_parameters) const;
+
+ void MainWindowHideInlineKeyboard() const;
+
+ void MainWindowInlineTextChanged(Core::Frontend::InlineTextParameters text_parameters) const;
+
+ void MainWindowExitKeyboard() const;
+
+private:
+ void SubmitNormalText(Service::AM::Applets::SwkbdResult result,
+ std::u16string submitted_text) const;
+
+ void SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type,
+ std::u16string submitted_text, s32 cursor_position) const;
+
+ mutable std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)>
+ submit_normal_callback;
+ mutable std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
+ submit_inline_callback;
+};