From 297a17b23720c03baf329b26cff5be7b05693be1 Mon Sep 17 00:00:00 2001 From: w1naenator Date: Thu, 27 Mar 2025 16:17:29 +0200 Subject: [PATCH 01/20] Add initial on-screen keyboard support (mouse input, works in BB) --- src/core/libraries/ime/ime_dialog_ui.cpp | 92 +++++++++++++++++++++++- src/core/libraries/ime/ime_dialog_ui.h | 2 + 2 files changed, 92 insertions(+), 2 deletions(-) diff --git a/src/core/libraries/ime/ime_dialog_ui.cpp b/src/core/libraries/ime/ime_dialog_ui.cpp index 51183c79b..c1a10400f 100644 --- a/src/core/libraries/ime/ime_dialog_ui.cpp +++ b/src/core/libraries/ime/ime_dialog_ui.cpp @@ -234,10 +234,12 @@ void ImeDialogUi::Draw() { ImVec2 window_size; + const float keyboard_height = 200.0f; + if (state->is_multi_line) { - window_size = {500.0f, 300.0f}; + window_size = {500.0f, 300.0f + keyboard_height}; } else { - window_size = {500.0f, 150.0f}; + window_size = {500.0f, 150.0f + keyboard_height}; } CentralizeNextWindow(); @@ -263,6 +265,7 @@ void ImeDialogUi::Draw() { } else { DrawInputText(); } + DrawKeyboard(); SetCursorPosY(GetCursorPosY() + 10.0f); @@ -337,6 +340,91 @@ void ImeDialogUi::DrawMultiLineInputText() { } } +void ImeDialogUi::DrawKeyboard() { + static bool shift_enabled = false; + enum class KeyboardMode { Letters, Symbols }; + static KeyboardMode kb_mode = KeyboardMode::Letters; + + const char* row1_letters = "QWERTYUIOP"; + const char* row2_letters = "ASDFGHJKL"; + const char* row3_letters = "ZXCVBNM"; + + const char* row1_symbols = "1234567890"; + const char* row2_symbols = "!@#$%^&*()"; + const char* row3_symbols = "-_=+[]{}"; + + auto draw_row = [&](const char* row, float offset_x) { + SetCursorPosX(offset_x); + for (int i = 0; row[i]; ++i) { + char ch = shift_enabled ? row[i] : (char)tolower(row[i]); + std::string key(1, ch); + if (ImGui::Button(key.c_str(), ImVec2(35, 35))) { + char* buffer = state->current_text.begin(); + size_t len = strlen(buffer); + if (len + 1 < state->max_text_length * 4) { + buffer[len] = ch; + buffer[len + 1] = '\0'; + state->input_changed = true; + } + } + ImGui::SameLine(); + } + ImGui::NewLine(); + }; + + if (shift_enabled) { + SetCursorPosX(20.0f); + TextColored(ImVec4(0.2f, 0.6f, 1.0f, 1.0f), "SHIFT ENABLED"); + } + + draw_row(kb_mode == KeyboardMode::Letters ? row1_letters : row1_symbols, 20.0f); + draw_row(kb_mode == KeyboardMode::Letters ? row2_letters : row2_symbols, 35.0f); + draw_row(kb_mode == KeyboardMode::Letters ? row3_letters : row3_symbols, 80.0f); + + SetCursorPosX(20.0f); + + if (shift_enabled) + PushStyleColor(ImGuiCol_Button, ImVec4(0.2f, 0.6f, 1.0f, 1.0f)); + + if (Button("SHIFT", ImVec2(75, 35))) { + shift_enabled = !shift_enabled; + } + + if (shift_enabled) + PopStyleColor(); + + SameLine(); + + if (Button("SPACE", ImVec2(100, 35))) { + char* buffer = state->current_text.begin(); + size_t len = strlen(buffer); + if (len + 1 < state->max_text_length * 4) { + buffer[len] = ' '; + buffer[len + 1] = '\0'; + state->input_changed = true; + } + } + + SameLine(); + + if (Button("DELETE", ImVec2(75, 35))) { + char* buffer = state->current_text.begin(); + size_t len = strlen(buffer); + if (len > 0) { + buffer[len - 1] = '\0'; + state->input_changed = true; + } + } + + SameLine(); + + if (Button(kb_mode == KeyboardMode::Letters ? "123" : "ABC", ImVec2(60, 35))) { + kb_mode = + (kb_mode == KeyboardMode::Letters) ? KeyboardMode::Symbols : KeyboardMode::Letters; + } +} + + int ImeDialogUi::InputTextCallback(ImGuiInputTextCallbackData* data) { ImeDialogUi* ui = static_cast(data->UserData); ASSERT(ui); diff --git a/src/core/libraries/ime/ime_dialog_ui.h b/src/core/libraries/ime/ime_dialog_ui.h index 10dff5eeb..380874fa6 100644 --- a/src/core/libraries/ime/ime_dialog_ui.h +++ b/src/core/libraries/ime/ime_dialog_ui.h @@ -78,6 +78,8 @@ private: void DrawInputText(); void DrawMultiLineInputText(); + void DrawKeyboard(); + static int InputTextCallback(ImGuiInputTextCallbackData* data); }; From bc0319e7ed804bcccf4be9e54803eed2dcbd3f61 Mon Sep 17 00:00:00 2001 From: w1naenator Date: Thu, 27 Mar 2025 16:40:44 +0200 Subject: [PATCH 02/20] Fix crash on Shift press. --- src/core/libraries/ime/ime_dialog_ui.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/core/libraries/ime/ime_dialog_ui.cpp b/src/core/libraries/ime/ime_dialog_ui.cpp index c1a10400f..c3de3f99f 100644 --- a/src/core/libraries/ime/ime_dialog_ui.cpp +++ b/src/core/libraries/ime/ime_dialog_ui.cpp @@ -372,6 +372,7 @@ void ImeDialogUi::DrawKeyboard() { ImGui::NewLine(); }; + // SHIFT status label if (shift_enabled) { SetCursorPosX(20.0f); TextColored(ImVec4(0.2f, 0.6f, 1.0f, 1.0f), "SHIFT ENABLED"); @@ -383,14 +384,16 @@ void ImeDialogUi::DrawKeyboard() { SetCursorPosX(20.0f); - if (shift_enabled) + // Fix: safely push/pop style only if shift was enabled before clicking + bool highlight = shift_enabled; + if (highlight) PushStyleColor(ImGuiCol_Button, ImVec4(0.2f, 0.6f, 1.0f, 1.0f)); if (Button("SHIFT", ImVec2(75, 35))) { shift_enabled = !shift_enabled; } - if (shift_enabled) + if (highlight) PopStyleColor(); SameLine(); @@ -425,6 +428,7 @@ void ImeDialogUi::DrawKeyboard() { } + int ImeDialogUi::InputTextCallback(ImGuiInputTextCallbackData* data) { ImeDialogUi* ui = static_cast(data->UserData); ASSERT(ui); From 51cadf9c29e38b3a8297529a34d7947f8aa663f0 Mon Sep 17 00:00:00 2001 From: w1naenator Date: Thu, 27 Mar 2025 16:54:09 +0200 Subject: [PATCH 03/20] Fix clang-format --- src/core/libraries/ime/ime_dialog_ui.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/libraries/ime/ime_dialog_ui.cpp b/src/core/libraries/ime/ime_dialog_ui.cpp index c3de3f99f..02169830b 100644 --- a/src/core/libraries/ime/ime_dialog_ui.cpp +++ b/src/core/libraries/ime/ime_dialog_ui.cpp @@ -427,8 +427,6 @@ void ImeDialogUi::DrawKeyboard() { } } - - int ImeDialogUi::InputTextCallback(ImGuiInputTextCallbackData* data) { ImeDialogUi* ui = static_cast(data->UserData); ASSERT(ui); From c93706616f79f7d8994e66ff47978f861c0c7498 Mon Sep 17 00:00:00 2001 From: w1naenator Date: Thu, 27 Mar 2025 17:49:09 +0200 Subject: [PATCH 04/20] Some fixes from @polybiusproxy comments --- src/core/libraries/ime/ime_dialog_ui.cpp | 9 +++++---- src/core/libraries/ime/ime_dialog_ui.h | 2 ++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/core/libraries/ime/ime_dialog_ui.cpp b/src/core/libraries/ime/ime_dialog_ui.cpp index 02169830b..e1ff23acc 100644 --- a/src/core/libraries/ime/ime_dialog_ui.cpp +++ b/src/core/libraries/ime/ime_dialog_ui.cpp @@ -342,7 +342,6 @@ void ImeDialogUi::DrawMultiLineInputText() { void ImeDialogUi::DrawKeyboard() { static bool shift_enabled = false; - enum class KeyboardMode { Letters, Symbols }; static KeyboardMode kb_mode = KeyboardMode::Letters; const char* row1_letters = "QWERTYUIOP"; @@ -355,7 +354,7 @@ void ImeDialogUi::DrawKeyboard() { auto draw_row = [&](const char* row, float offset_x) { SetCursorPosX(offset_x); - for (int i = 0; row[i]; ++i) { + for (int i = 0; row[i] != '\0'; ++i) { char ch = shift_enabled ? row[i] : (char)tolower(row[i]); std::string key(1, ch); if (ImGui::Button(key.c_str(), ImVec2(35, 35))) { @@ -386,15 +385,17 @@ void ImeDialogUi::DrawKeyboard() { // Fix: safely push/pop style only if shift was enabled before clicking bool highlight = shift_enabled; - if (highlight) + if (highlight) { PushStyleColor(ImGuiCol_Button, ImVec4(0.2f, 0.6f, 1.0f, 1.0f)); + } if (Button("SHIFT", ImVec2(75, 35))) { shift_enabled = !shift_enabled; } - if (highlight) + if (highlight) { PopStyleColor(); + } SameLine(); diff --git a/src/core/libraries/ime/ime_dialog_ui.h b/src/core/libraries/ime/ime_dialog_ui.h index 380874fa6..b613ed970 100644 --- a/src/core/libraries/ime/ime_dialog_ui.h +++ b/src/core/libraries/ime/ime_dialog_ui.h @@ -62,6 +62,8 @@ class ImeDialogUi final : public ImGui::Layer { bool first_render = true; std::mutex draw_mutex; + enum class KeyboardMode { Letters, Symbols }; + public: explicit ImeDialogUi(ImeDialogState* state = nullptr, OrbisImeDialogStatus* status = nullptr, OrbisImeDialogResult* result = nullptr); From 569ab0c87f8a1b53bc955f1fd37ddcef0faaf7f6 Mon Sep 17 00:00:00 2001 From: w1naenator Date: Fri, 28 Mar 2025 10:53:52 +0200 Subject: [PATCH 05/20] Use vierual keyboard in ImeUi and ImeDialogUi Added some spam to log. Some files added, CMakeList modified. --- CMakeLists.txt | 2 + src/core/libraries/ime/ime_dialog_ui.cpp | 89 ++------------------ src/core/libraries/ime/ime_dialog_ui.h | 3 +- src/core/libraries/ime/ime_keyboard_ui.cpp | 96 ++++++++++++++++++++++ src/core/libraries/ime/ime_keyboard_ui.h | 9 ++ src/core/libraries/ime/ime_ui.cpp | 16 ++++ src/core/libraries/ime/ime_ui.h | 2 + 7 files changed, 134 insertions(+), 83 deletions(-) create mode 100644 src/core/libraries/ime/ime_keyboard_ui.cpp create mode 100644 src/core/libraries/ime/ime_keyboard_ui.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c0932b5c..77e288b62 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -446,6 +446,8 @@ set(IME_LIB src/core/libraries/ime/error_dialog.cpp src/core/libraries/ime/ime_dialog.h src/core/libraries/ime/ime_ui.cpp src/core/libraries/ime/ime_ui.h + src/core/libraries/ime/ime_keyboard_ui.cpp + src/core/libraries/ime/ime_keyboard_ui.h src/core/libraries/ime/ime.cpp src/core/libraries/ime/ime.h src/core/libraries/ime/ime_error.h diff --git a/src/core/libraries/ime/ime_dialog_ui.cpp b/src/core/libraries/ime/ime_dialog_ui.cpp index e1ff23acc..bd41488ae 100644 --- a/src/core/libraries/ime/ime_dialog_ui.cpp +++ b/src/core/libraries/ime/ime_dialog_ui.cpp @@ -10,6 +10,7 @@ #include "common/logging/log.h" #include "core/libraries/ime/ime_dialog.h" #include "core/libraries/ime/ime_dialog_ui.h" +#include "core/libraries/ime/ime_keyboard_ui.h" #include "core/tls.h" #include "imgui/imgui_std.h" @@ -341,91 +342,17 @@ void ImeDialogUi::DrawMultiLineInputText() { } void ImeDialogUi::DrawKeyboard() { - static bool shift_enabled = false; static KeyboardMode kb_mode = KeyboardMode::Letters; + static bool shift_enabled = false; - const char* row1_letters = "QWERTYUIOP"; - const char* row2_letters = "ASDFGHJKL"; - const char* row3_letters = "ZXCVBNM"; - - const char* row1_symbols = "1234567890"; - const char* row2_symbols = "!@#$%^&*()"; - const char* row3_symbols = "-_=+[]{}"; - - auto draw_row = [&](const char* row, float offset_x) { - SetCursorPosX(offset_x); - for (int i = 0; row[i] != '\0'; ++i) { - char ch = shift_enabled ? row[i] : (char)tolower(row[i]); - std::string key(1, ch); - if (ImGui::Button(key.c_str(), ImVec2(35, 35))) { - char* buffer = state->current_text.begin(); - size_t len = strlen(buffer); - if (len + 1 < state->max_text_length * 4) { - buffer[len] = ch; - buffer[len + 1] = '\0'; - state->input_changed = true; - } - } - ImGui::SameLine(); - } - ImGui::NewLine(); - }; - - // SHIFT status label - if (shift_enabled) { - SetCursorPosX(20.0f); - TextColored(ImVec4(0.2f, 0.6f, 1.0f, 1.0f), "SHIFT ENABLED"); + static bool has_logged = false; + if (!has_logged) { + LOG_INFO(Lib_ImeDialog, "Virtual keyboard used from ImeDialog"); + has_logged = true; } - draw_row(kb_mode == KeyboardMode::Letters ? row1_letters : row1_symbols, 20.0f); - draw_row(kb_mode == KeyboardMode::Letters ? row2_letters : row2_symbols, 35.0f); - draw_row(kb_mode == KeyboardMode::Letters ? row3_letters : row3_symbols, 80.0f); - - SetCursorPosX(20.0f); - - // Fix: safely push/pop style only if shift was enabled before clicking - bool highlight = shift_enabled; - if (highlight) { - PushStyleColor(ImGuiCol_Button, ImVec4(0.2f, 0.6f, 1.0f, 1.0f)); - } - - if (Button("SHIFT", ImVec2(75, 35))) { - shift_enabled = !shift_enabled; - } - - if (highlight) { - PopStyleColor(); - } - - SameLine(); - - if (Button("SPACE", ImVec2(100, 35))) { - char* buffer = state->current_text.begin(); - size_t len = strlen(buffer); - if (len + 1 < state->max_text_length * 4) { - buffer[len] = ' '; - buffer[len + 1] = '\0'; - state->input_changed = true; - } - } - - SameLine(); - - if (Button("DELETE", ImVec2(75, 35))) { - char* buffer = state->current_text.begin(); - size_t len = strlen(buffer); - if (len > 0) { - buffer[len - 1] = '\0'; - state->input_changed = true; - } - } - - SameLine(); - - if (Button(kb_mode == KeyboardMode::Letters ? "123" : "ABC", ImVec2(60, 35))) { - kb_mode = - (kb_mode == KeyboardMode::Letters) ? KeyboardMode::Symbols : KeyboardMode::Letters; - } + DrawVirtualKeyboard(state->current_text.begin(), state->max_text_length * 4, + &state->input_changed, kb_mode, shift_enabled); } int ImeDialogUi::InputTextCallback(ImGuiInputTextCallbackData* data) { diff --git a/src/core/libraries/ime/ime_dialog_ui.h b/src/core/libraries/ime/ime_dialog_ui.h index b613ed970..af47610a2 100644 --- a/src/core/libraries/ime/ime_dialog_ui.h +++ b/src/core/libraries/ime/ime_dialog_ui.h @@ -9,6 +9,7 @@ #include "common/cstring.h" #include "common/types.h" #include "core/libraries/ime/ime_dialog.h" +#include "core/libraries/ime/ime_keyboard_ui.h" #include "imgui/imgui_layer.h" namespace Libraries::ImeDialog { @@ -62,8 +63,6 @@ class ImeDialogUi final : public ImGui::Layer { bool first_render = true; std::mutex draw_mutex; - enum class KeyboardMode { Letters, Symbols }; - public: explicit ImeDialogUi(ImeDialogState* state = nullptr, OrbisImeDialogStatus* status = nullptr, OrbisImeDialogResult* result = nullptr); diff --git a/src/core/libraries/ime/ime_keyboard_ui.cpp b/src/core/libraries/ime/ime_keyboard_ui.cpp new file mode 100644 index 000000000..bbf2435ed --- /dev/null +++ b/src/core/libraries/ime/ime_keyboard_ui.cpp @@ -0,0 +1,96 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include +#include +#include +#include "ime_keyboard_ui.h" + +void DrawVirtualKeyboard(char* buffer, std::size_t buffer_capacity, bool* input_changed, + KeyboardMode& kb_mode, bool& shift_enabled) { + const char* row1_letters = "QWERTYUIOP"; + const char* row2_letters = "ASDFGHJKL"; + const char* row3_letters = "ZXCVBNM"; + + const char* row1_symbols = "1234567890"; + const char* row2_symbols = "!@#$%^&*()"; + const char* row3_symbols = "-_=+[]{}"; + + auto draw_row = [&](const char* row, float offset_x) { + ImGui::SetCursorPosX(offset_x); + for (int i = 0; row[i] != '\0'; ++i) { + char ch = shift_enabled ? row[i] : static_cast(tolower(row[i])); + std::string key(1, ch); + if (ImGui::Button(key.c_str(), ImVec2(35, 35))) { + size_t len = std::strlen(buffer); + if (len + 1 < buffer_capacity) { + buffer[len] = ch; + buffer[len + 1] = '\0'; + if (input_changed) { + *input_changed = true; + } + } + } + ImGui::SameLine(); + } + ImGui::NewLine(); + }; + + // SHIFT status label + if (shift_enabled) { + ImGui::SetCursorPosX(20.0f); + ImGui::TextColored(ImVec4(0.2f, 0.6f, 1.0f, 1.0f), "SHIFT ENABLED"); + } + + draw_row(kb_mode == KeyboardMode::Letters ? row1_letters : row1_symbols, 20.0f); + draw_row(kb_mode == KeyboardMode::Letters ? row2_letters : row2_symbols, 35.0f); + draw_row(kb_mode == KeyboardMode::Letters ? row3_letters : row3_symbols, 80.0f); + + ImGui::SetCursorPosX(20.0f); + + bool highlight = shift_enabled; + if (highlight) { + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.2f, 0.6f, 1.0f, 1.0f)); + } + + if (ImGui::Button("SHIFT", ImVec2(75, 35))) { + shift_enabled = !shift_enabled; + } + + if (highlight) { + ImGui::PopStyleColor(); + } + + ImGui::SameLine(); + + if (ImGui::Button("SPACE", ImVec2(100, 35))) { + size_t len = std::strlen(buffer); + if (len + 1 < buffer_capacity) { + buffer[len] = ' '; + buffer[len + 1] = '\0'; + if (input_changed) { + *input_changed = true; + } + } + } + + ImGui::SameLine(); + + if (ImGui::Button("DELETE", ImVec2(75, 35))) { + size_t len = std::strlen(buffer); + if (len > 0) { + buffer[len - 1] = '\0'; + if (input_changed) { + *input_changed = true; + } + } + } + + ImGui::SameLine(); + + if (ImGui::Button(kb_mode == KeyboardMode::Letters ? "123" : "ABC", ImVec2(60, 35))) { + kb_mode = + (kb_mode == KeyboardMode::Letters) ? KeyboardMode::Symbols : KeyboardMode::Letters; + } +} diff --git a/src/core/libraries/ime/ime_keyboard_ui.h b/src/core/libraries/ime/ime_keyboard_ui.h new file mode 100644 index 000000000..0a5393bcc --- /dev/null +++ b/src/core/libraries/ime/ime_keyboard_ui.h @@ -0,0 +1,9 @@ +#pragma once + +#include "common/cstring.h" +#include "common/types.h" + +enum class KeyboardMode { Letters, Symbols }; + +void DrawVirtualKeyboard(char* buffer, std::size_t buffer_capacity, bool* input_changed, + KeyboardMode& kb_mode, bool& shift_enabled); diff --git a/src/core/libraries/ime/ime_ui.cpp b/src/core/libraries/ime/ime_ui.cpp index 37f25e200..43bbf6a85 100644 --- a/src/core/libraries/ime/ime_ui.cpp +++ b/src/core/libraries/ime/ime_ui.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "ime_keyboard_ui.h" #include "ime_ui.h" #include "imgui/imgui_std.h" @@ -150,6 +151,7 @@ void ImeUi::Draw() { DrawPrettyBackground(); DrawInputText(); + DrawKeyboard(); SetCursorPosY(GetCursorPosY() + 10.0f); const char* button_text; @@ -187,6 +189,20 @@ void ImeUi::DrawInputText() { } } +void ImeUi::DrawKeyboard() { + static KeyboardMode kb_mode = KeyboardMode::Letters; + static bool shift_enabled = false; + + static bool has_logged = false; + if (!has_logged) { + LOG_INFO(Lib_ImeDialog, "Virtual keyboard used from Ime"); + has_logged = true; + } + + DrawVirtualKeyboard(state->current_text.begin(), ime_param->maxTextLength * 4, nullptr, kb_mode, + shift_enabled); +} + int ImeUi::InputTextCallback(ImGuiInputTextCallbackData* data) { ImeUi* ui = static_cast(data->UserData); ASSERT(ui); diff --git a/src/core/libraries/ime/ime_ui.h b/src/core/libraries/ime/ime_ui.h index 3eea22b8c..3dbc647eb 100644 --- a/src/core/libraries/ime/ime_ui.h +++ b/src/core/libraries/ime/ime_ui.h @@ -70,6 +70,8 @@ private: void DrawInputText(); + void DrawKeyboard(); + static int InputTextCallback(ImGuiInputTextCallbackData* data); }; From 5a874b18bad728cd2f339409e0e122ebaf759014 Mon Sep 17 00:00:00 2001 From: w1naenator Date: Fri, 28 Mar 2025 17:33:22 +0200 Subject: [PATCH 06/20] Redesign layout closer original --- CMakeLists.txt | 2 + src/core/libraries/ime/ime_dialog_ui.cpp | 9 +- .../libraries/ime/ime_keyboard_layouts.cpp | 237 ++++++++++++++++++ src/core/libraries/ime/ime_keyboard_layouts.h | 41 +++ src/core/libraries/ime/ime_keyboard_ui.cpp | 192 ++++++++------ src/core/libraries/ime/ime_keyboard_ui.h | 16 +- src/core/libraries/ime/ime_ui.cpp | 13 +- 7 files changed, 428 insertions(+), 82 deletions(-) create mode 100644 src/core/libraries/ime/ime_keyboard_layouts.cpp create mode 100644 src/core/libraries/ime/ime_keyboard_layouts.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 77e288b62..22b8af192 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -446,6 +446,8 @@ set(IME_LIB src/core/libraries/ime/error_dialog.cpp src/core/libraries/ime/ime_dialog.h src/core/libraries/ime/ime_ui.cpp src/core/libraries/ime/ime_ui.h + src/core/libraries/ime/ime_keyboard_layouts.cpp + src/core/libraries/ime/ime_keyboard_layouts.h src/core/libraries/ime/ime_keyboard_ui.cpp src/core/libraries/ime/ime_keyboard_ui.h src/core/libraries/ime/ime.cpp diff --git a/src/core/libraries/ime/ime_dialog_ui.cpp b/src/core/libraries/ime/ime_dialog_ui.cpp index bd41488ae..3c576059d 100644 --- a/src/core/libraries/ime/ime_dialog_ui.cpp +++ b/src/core/libraries/ime/ime_dialog_ui.cpp @@ -351,8 +351,15 @@ void ImeDialogUi::DrawKeyboard() { has_logged = true; } + bool done_pressed = false; + DrawVirtualKeyboard(state->current_text.begin(), state->max_text_length * 4, - &state->input_changed, kb_mode, shift_enabled); + &state->input_changed, kb_mode, shift_enabled, &done_pressed); + + if (done_pressed) { + *status = OrbisImeDialogStatus::Finished; + result->endstatus = OrbisImeDialogEndStatus::Ok; + } } int ImeDialogUi::InputTextCallback(ImGuiInputTextCallbackData* data) { diff --git a/src/core/libraries/ime/ime_keyboard_layouts.cpp b/src/core/libraries/ime/ime_keyboard_layouts.cpp new file mode 100644 index 000000000..a6e4548ea --- /dev/null +++ b/src/core/libraries/ime/ime_keyboard_layouts.cpp @@ -0,0 +1,237 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "ime_keyboard_layouts.h" + +const std::vector kUppercaseLayout = { + // Row 1 + {0, 0, 1, 1, "1", "", KeyType::Text}, + {0, 1, 1, 1, "2", "", KeyType::Text}, + {0, 2, 1, 1, "3", "", KeyType::Text}, + {0, 3, 1, 1, "4", "", KeyType::Text}, + {0, 4, 1, 1, "5", "", KeyType::Text}, + {0, 5, 1, 1, "6", "", KeyType::Text}, + {0, 6, 1, 1, "7", "", KeyType::Text}, + {0, 7, 1, 1, "8", "", KeyType::Text}, + {0, 8, 1, 1, "9", "", KeyType::Text}, + {0, 9, 1, 1, "0", "", KeyType::Text}, + + // Row 2 + {1, 0, 1, 1, "Q", "", KeyType::Text}, + {1, 1, 1, 1, "W", "", KeyType::Text}, + {1, 2, 1, 1, "E", "", KeyType::Text}, + {1, 3, 1, 1, "R", "", KeyType::Text}, + {1, 4, 1, 1, "T", "", KeyType::Text}, + {1, 5, 1, 1, "Y", "", KeyType::Text}, + {1, 6, 1, 1, "U", "", KeyType::Text}, + {1, 7, 1, 1, "I", "", KeyType::Text}, + {1, 8, 1, 1, "O", "", KeyType::Text}, + {1, 9, 1, 1, "P", "", KeyType::Text}, + + // Row 3 + {2, 0, 1, 1, "A", "", KeyType::Text}, + {2, 1, 1, 1, "S", "", KeyType::Text}, + {2, 2, 1, 1, "D", "", KeyType::Text}, + {2, 3, 1, 1, "F", "", KeyType::Text}, + {2, 4, 1, 1, "G", "", KeyType::Text}, + {2, 5, 1, 1, "H", "", KeyType::Text}, + {2, 6, 1, 1, "J", "", KeyType::Text}, + {2, 7, 1, 1, "K", "", KeyType::Text}, + {2, 8, 1, 1, "L", "", KeyType::Text}, + {2, 9, 1, 1, "\"", "", KeyType::Text}, + + // Row 4 + {3, 0, 1, 1, "Z", "", KeyType::Text}, + {3, 1, 1, 1, "X", "", KeyType::Text}, + {3, 2, 1, 1, "C", "", KeyType::Text}, + {3, 3, 1, 1, "V", "", KeyType::Text}, + {3, 4, 1, 1, "B", "", KeyType::Text}, + {3, 5, 1, 1, "N", "", KeyType::Text}, + {3, 6, 1, 1, "M", "", KeyType::Text}, + {3, 7, 1, 1, "-", "", KeyType::Text}, + {3, 8, 1, 1, "_", "", KeyType::Text}, + {3, 9, 1, 1, "/", "", KeyType::Text}, + + // Row 5 + {4, 0, 1, 1, "SF", "L2", KeyType::Shift}, //{4, 0, 1, 1, "⇧", "L2", KeyType::Shift}, + {4, 1, 1, 1, "@#:", "L2+TRI", KeyType::SymbolsLayout}, + {4, 2, 1, 1, "à", "L3", KeyType::UnknownFunction}, + {4, 3, 4, 1, "Space", "TRI", KeyType::Space}, //{4, 3, 4, 1, "Space", "△", KeyType::Space}, + //{4, 4, 4, 1, "Space", "△", KeyType::Space}, + //{4, 5, 4, 1, "Space", "△", KeyType::Space}, + //{4, 6, 4, 1, "Space", "△", KeyType::Space}, + {4, 7, 1, 1, "", "", KeyType::Disabled}, + {4, 8, 2, 1, "DEL", "SQR", KeyType::Backspace}, //{4, 8, 2, 1, "⌫", "▢", KeyType::Backspace}, + //{4, 9, 2, 1, "⌫", "▢", KeyType::Backspace}, + + // Row 6 + {5, 0, 1, 1, "UP", "", KeyType::CursorUp}, //{5, 0, 1, 1, "▲", "", KeyType::CursorUp}, + {5, 1, 1, 1, "DN", "", KeyType::CursorDown}, //{5, 1, 1, 1, "▼", "", KeyType::CursorDown}, + {5, 2, 1, 1, "LT", "L1", KeyType::CursorLeft}, //{5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft}, + {5, 3, 1, 1, "RT", "R1", + KeyType::CursorRight}, //{5, 3, 1, 1, "▶", "R1", KeyType::CursorRight}, + {5, 4, 1, 1, "KB", "", + KeyType::ToggleKeyboard}, //{5, 4, 1, 1, "⌨", "", KeyType::ToggleKeyboard}, + {5, 5, 1, 1, "...", "", KeyType::MoreOptions}, //{5, 5, 1, 1, "…", "", KeyType::MoreOptions}, + {5, 6, 1, 1, "CR", "R1", + KeyType::ControllerAction}, //{5, 6, 1, 1, "🎮⊕", "R1", KeyType::ControllerAction}, + {5, 7, 1, 1, "", "", KeyType::Disabled}, + {5, 8, 2, 1, "Done", "R2", KeyType::Done}, + //{5, 9, 2, 1, "Done", "R2", KeyType::Done}, +}; + +const std::vector kLowercaseLayout = { + // Row 1 + {0, 0, 1, 1, "1", "", KeyType::Text}, + {0, 1, 1, 1, "2", "", KeyType::Text}, + {0, 2, 1, 1, "3", "", KeyType::Text}, + {0, 3, 1, 1, "4", "", KeyType::Text}, + {0, 4, 1, 1, "5", "", KeyType::Text}, + {0, 5, 1, 1, "6", "", KeyType::Text}, + {0, 6, 1, 1, "7", "", KeyType::Text}, + {0, 7, 1, 1, "8", "", KeyType::Text}, + {0, 8, 1, 1, "9", "", KeyType::Text}, + {0, 9, 1, 1, "0", "", KeyType::Text}, + + // Row 2 + {1, 0, 1, 1, "q", "", KeyType::Text}, + {1, 1, 1, 1, "w", "", KeyType::Text}, + {1, 2, 1, 1, "e", "", KeyType::Text}, + {1, 3, 1, 1, "r", "", KeyType::Text}, + {1, 4, 1, 1, "t", "", KeyType::Text}, + {1, 5, 1, 1, "y", "", KeyType::Text}, + {1, 6, 1, 1, "u", "", KeyType::Text}, + {1, 7, 1, 1, "i", "", KeyType::Text}, + {1, 8, 1, 1, "o", "", KeyType::Text}, + {1, 9, 1, 1, "p", "", KeyType::Text}, + + // Row 3 + {2, 0, 1, 1, "a", "", KeyType::Text}, + {2, 1, 1, 1, "s", "", KeyType::Text}, + {2, 2, 1, 1, "d", "", KeyType::Text}, + {2, 3, 1, 1, "f", "", KeyType::Text}, + {2, 4, 1, 1, "g", "", KeyType::Text}, + {2, 5, 1, 1, "h", "", KeyType::Text}, + {2, 6, 1, 1, "j", "", KeyType::Text}, + {2, 7, 1, 1, "k", "", KeyType::Text}, + {2, 8, 1, 1, "l", "", KeyType::Text}, + {2, 9, 1, 1, "-", "", KeyType::Text}, + + // Row 4 + {3, 0, 1, 1, "z", "", KeyType::Text}, + {3, 1, 1, 1, "x", "", KeyType::Text}, + {3, 2, 1, 1, "c", "", KeyType::Text}, + {3, 3, 1, 1, "v", "", KeyType::Text}, + {3, 4, 1, 1, "b", "", KeyType::Text}, + {3, 5, 1, 1, "n", "", KeyType::Text}, + {3, 6, 1, 1, "m", "", KeyType::Text}, + {3, 7, 1, 1, "@", "", KeyType::Text}, + {3, 8, 1, 1, ".", "", KeyType::Text}, + {3, 9, 1, 1, "_", "", KeyType::Text}, + + // Row 5 + {4, 0, 1, 1, "SF", "L2", KeyType::Shift}, //{4, 0, 1, 1, "⇧", "L2", KeyType::Shift}, + {4, 1, 1, 1, "@#:", "L2+TRI", + KeyType::SymbolsLayout}, //{4, 1, 1, 1, "@#:", "L2+△", KeyType::Symbols}, + {4, 2, 1, 1, "à", "L3", KeyType::UnknownFunction}, + {4, 3, 4, 1, "Space", "TRI", KeyType::Space}, //{4, 3, 4, 1, "Space", "△", KeyType::Space}, + //{4, 4, 4, 1, "Space", "△", KeyType::Space}, + //{4, 5, 4, 1, "Space", "△", KeyType::Space}, + //{4, 6, 4, 1, "Space", "△", KeyType::Space}, + {4, 7, 1, 1, "", "", KeyType::Disabled}, + {4, 8, 2, 1, "DEL", "SQR", KeyType::Backspace}, //{4, 8, 2, 1, "⌫", "▢", KeyType::Backspace}, + //{4, 8, 2, 1, "⌫", "▢", KeyType::Backspace}, + + // Row 6 + {5, 0, 1, 1, "UP", "", KeyType::CursorUp}, // {5, 0, 1, 1, "▲", "", KeyType::CursorUp}, + {5, 1, 1, 1, "DN", "", KeyType::CursorDown}, //{5, 1, 1, 1, "▼", "", KeyType::CursorDown}, + {5, 2, 1, 1, "LT", "L1", KeyType::CursorLeft}, //{5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft}, + {5, 3, 1, 1, "RT", "R1", + KeyType::CursorRight}, //{5, 3, 1, 1, "▶", "R1", KeyType::CursorRight}, + {5, 4, 1, 1, "KB", "", + KeyType::ToggleKeyboard}, //{5, 4, 1, 1, "⌨", "", KeyType::ToggleKeyboard}, + {5, 5, 1, 1, "...", "", KeyType::MoreOptions}, //{5, 5, 1, 1, "…", "", KeyType::MoreOptions}, + {5, 6, 1, 1, "CR", "R1", + KeyType::ControllerAction}, //{5, 6, 1, 1, "🎮⊕", "R1", KeyType::ControllerAction}, + {5, 7, 1, 1, "", "", KeyType::Disabled}, + {5, 8, 2, 1, "Done", "R2", KeyType::Done}, + //{5, 9, 2, 1, "Done", "R2", KeyType::Done}, +}; + +const std::vector kSymbols1Layout = { + // Row 1 + {0, 0, 1, 1, "!", "", KeyType::Text}, + {0, 1, 1, 1, "?", "", KeyType::Text}, + {0, 2, 1, 1, "\"", "", KeyType::Text}, + {0, 3, 1, 1, "'", "", KeyType::Text}, + {0, 4, 1, 1, "#", "", KeyType::Text}, + {0, 5, 1, 1, "%", "", KeyType::Text}, + {0, 6, 1, 1, "(", "", KeyType::Text}, + {0, 7, 1, 1, ")", "", KeyType::Text}, + {0, 8, 1, 1, "()", "", KeyType::Text}, + {0, 9, 1, 1, "/", "", KeyType::Text}, + + // Row 2 + {1, 0, 1, 1, "-", "", KeyType::Text}, + {1, 1, 1, 1, "_", "", KeyType::Text}, + {1, 2, 1, 1, ",", "", KeyType::Text}, + {1, 3, 1, 1, ".", "", KeyType::Text}, + {1, 4, 1, 1, ":", "", KeyType::Text}, + {1, 5, 1, 1, ";", "", KeyType::Text}, + {1, 6, 1, 1, "*", "", KeyType::Text}, + {1, 7, 1, 1, "+", "", KeyType::Text}, + {1, 8, 1, 1, "=", "", KeyType::Text}, + {1, 9, 1, 1, "&", "", KeyType::Text}, + + // Row 3 + {2, 0, 1, 1, "<", "", KeyType::Text}, + {2, 1, 1, 1, ">", "", KeyType::Text}, + {2, 2, 1, 1, "@", "", KeyType::Text}, + {2, 3, 1, 1, "[", "", KeyType::Text}, + {2, 4, 1, 1, "]", "", KeyType::Text}, + {2, 5, 1, 1, "[]", "", KeyType::Text}, + {2, 6, 1, 1, "{", "", KeyType::Text}, + {2, 7, 1, 1, "}", "", KeyType::Text}, + {2, 8, 1, 1, "{}", "", KeyType::Text}, + {2, 9, 1, 2, "→", "", KeyType::UnknownFunction}, // Next symbols page (SYM2) + + // Row 4 + {3, 0, 1, 1, "\\", "", KeyType::Text}, + {3, 1, 1, 1, "|", "", KeyType::Text}, + {3, 2, 1, 1, "^", "", KeyType::Text}, + {3, 3, 1, 1, "`", "", KeyType::Text}, + {3, 4, 1, 1, "$", "", KeyType::Text}, + {3, 5, 1, 1, "€", "", KeyType::Text}, + {3, 6, 1, 1, "´", "", KeyType::Text}, + {3, 7, 1, 1, "ˊ", "", KeyType::Text}, + {3, 8, 1, 1, "ˊ", "", KeyType::Text}, + //{3, 9, 1, 2, "→", "", KeyType::UnknownFunction}, // Next symbols page (SYM2) + + // Row 5 + {4, 0, 1, 1, "", "", KeyType::Disabled}, + {4, 1, 1, 1, "ABC", "L2+TRI", + KeyType::TextLayout}, //{4, 1, 1, 1, "ABC", "L2+△", KeyType::Symbols}, + {4, 2, 1, 1, "", "", KeyType::Disabled}, + {4, 3, 4, 1, "Space", "TRI", KeyType::Space}, //{4, 3, 4, 1, "Space", "△", KeyType::Space}, + //{4, 4, 4, 1, "Space", "△", KeyType::Space}, + //{4, 5, 4, 1, "Space", "△", KeyType::Space}, + //{4, 6, 4, 1, "Space", "△", KeyType::Space}, + {4, 7, 1, 1, "", "", KeyType::Disabled}, + {4, 8, 2, 1, "DEL", "SQR", KeyType::Backspace}, //{4, 8, 2, 1, "⌫", "▢", KeyType::Backspace}, + //{4, 9, 2, 1, "⌫", "▢", KeyType::Backspace}, + + // Row 6 + {5, 0, 1, 1, "UP", "", KeyType::CursorUp}, // {5, 0, 1, 1, "▲", "", KeyType::CursorUp}, + {5, 1, 1, 1, "DN", "", KeyType::CursorDown}, //{5, 1, 1, 1, "▼", "", KeyType::CursorDown}, + {5, 2, 1, 1, "LT", "L1", KeyType::CursorLeft}, //{5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft}, + {5, 3, 1, 1, "RT", "R1", + KeyType::CursorRight}, //{5, 3, 1, 1, "▶", "R1", KeyType::CursorRight}, + {5, 4, 1, 1, "KB", "", + KeyType::ToggleKeyboard}, //{5, 4, 1, 1, "⌨", "", KeyType::ToggleKeyboard}, + {5, 5, 1, 1, "...", "", KeyType::MoreOptions}, //{5, 5, 1, 1, "…", "", KeyType::MoreOptions}, + {5, 6, 1, 1, "CR", "R1", + KeyType::ControllerAction}, //{5, 6, 1, 1, "🎮⊕", "R1", KeyType::ControllerAction}, + {5, 7, 1, 1, "", "", KeyType::Disabled}, + {5, 8, 2, 1, "Done", "R2", KeyType::Done}, + //{5, 9, 2, 1, "Done", "R2", KeyType::Done}, +}; diff --git a/src/core/libraries/ime/ime_keyboard_layouts.h b/src/core/libraries/ime/ime_keyboard_layouts.h new file mode 100644 index 000000000..0f51509c6 --- /dev/null +++ b/src/core/libraries/ime/ime_keyboard_layouts.h @@ -0,0 +1,41 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +enum class KeyType { + Text, // Inserts character(s) into input buffer + Backspace, // Deletes last character + Space, // Adds space + Enter, // Submits input + Shift, // Toggle uppercase/lowercase + SymbolsLayout, // Switch to symbols layout + TextLayout, // Switch to text layout + Done, // Finish and close keyboard + CursorLeft, + CursorRight, + CursorUp, + CursorDown, + ToggleKeyboard, // Toggles keyboard layout + MoreOptions, // "..." button + ControllerAction, // e.g. R3 🎮⊕ + Disabled, // Filler or placeholder + UnknownFunction, // now same as disabled +}; + +struct Key { + int row; + int col; + int colspan = 1; + int rowspan = 1; + std::string label; + std::string controller_hint; + KeyType type = KeyType::Text; // default to Text input +}; + +extern const std::vector kUppercaseLayout; +extern const std::vector kLowercaseLayout; +extern const std::vector kSymbols1Layout; diff --git a/src/core/libraries/ime/ime_keyboard_ui.cpp b/src/core/libraries/ime/ime_keyboard_ui.cpp index bbf2435ed..6322eb2f7 100644 --- a/src/core/libraries/ime/ime_keyboard_ui.cpp +++ b/src/core/libraries/ime/ime_keyboard_ui.cpp @@ -1,96 +1,134 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include #include -#include #include +#include "ime_keyboard_layouts.h" #include "ime_keyboard_ui.h" +using namespace ImGui; + void DrawVirtualKeyboard(char* buffer, std::size_t buffer_capacity, bool* input_changed, - KeyboardMode& kb_mode, bool& shift_enabled) { - const char* row1_letters = "QWERTYUIOP"; - const char* row2_letters = "ASDFGHJKL"; - const char* row3_letters = "ZXCVBNM"; + KeyboardMode& kb_mode, bool& shift_enabled, bool* done_pressed) { + const std::vector* layout = nullptr; - const char* row1_symbols = "1234567890"; - const char* row2_symbols = "!@#$%^&*()"; - const char* row3_symbols = "-_=+[]{}"; + if (kb_mode == KeyboardMode::Symbols) { + layout = &kSymbols1Layout; + } else { + layout = shift_enabled ? &kUppercaseLayout : &kLowercaseLayout; + } - auto draw_row = [&](const char* row, float offset_x) { - ImGui::SetCursorPosX(offset_x); - for (int i = 0; row[i] != '\0'; ++i) { - char ch = shift_enabled ? row[i] : static_cast(tolower(row[i])); - std::string key(1, ch); - if (ImGui::Button(key.c_str(), ImVec2(35, 35))) { - size_t len = std::strlen(buffer); - if (len + 1 < buffer_capacity) { - buffer[len] = ch; - buffer[len + 1] = '\0'; - if (input_changed) { - *input_changed = true; + RenderKeyboardLayout(*layout, buffer, buffer_capacity, input_changed, kb_mode, shift_enabled, + done_pressed); +} + +void RenderKeyboardLayout(const std::vector& layout, char* buffer, std::size_t buffer_capacity, + bool* input_changed, KeyboardMode& kb_mode, bool& shift_enabled, + bool* done_pressed) { + // Define desired total layout size (in pixels) + const float layout_width = 485.0f; + const float layout_height = 200.0f; + const float cell_spacing = 4.0f; + const float hint_padding = 2.0f; + + // Find max rows and columns + int max_col = 0; + int max_row = 0; + for (const Key& key : layout) { + max_col = std::max(max_col, key.col + static_cast(key.colspan)); + max_row = std::max(max_row, key.row + static_cast(key.rowspan)); + } + + // Calculate cell size dynamically + const float cell_width = (layout_width - (max_col - 1) * cell_spacing) / max_col; + const float cell_height = (layout_height - (max_row - 1) * cell_spacing) / max_row; + + const ImVec2 origin = ImGui::GetCursorScreenPos(); + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + + for (const Key& key : layout) { + float x = origin.x + key.col * (cell_width + cell_spacing); + float y = origin.y + key.row * (cell_height + cell_spacing); + + ImVec2 pos(x, y); + ImVec2 size(key.colspan * cell_width + (key.colspan - 1) * cell_spacing, + key.rowspan * cell_height + (key.rowspan - 1) * cell_spacing); + + std::string button_id = + key.label.empty() ? "##empty_" + std::to_string(key.row) + "_" + std::to_string(key.col) + : key.label; + + ImGui::SetCursorScreenPos(pos); + + if (ImGui::Button(button_id.c_str(), size)) { + switch (key.type) { + case KeyType::Text: + if (!key.label.empty()) { + size_t len = std::strlen(buffer); + if (len + key.label.size() < buffer_capacity) { + std::strcat(buffer, key.label.c_str()); + if (input_changed) + *input_changed = true; } } - } - ImGui::SameLine(); - } - ImGui::NewLine(); - }; - - // SHIFT status label - if (shift_enabled) { - ImGui::SetCursorPosX(20.0f); - ImGui::TextColored(ImVec4(0.2f, 0.6f, 1.0f, 1.0f), "SHIFT ENABLED"); - } - - draw_row(kb_mode == KeyboardMode::Letters ? row1_letters : row1_symbols, 20.0f); - draw_row(kb_mode == KeyboardMode::Letters ? row2_letters : row2_symbols, 35.0f); - draw_row(kb_mode == KeyboardMode::Letters ? row3_letters : row3_symbols, 80.0f); - - ImGui::SetCursorPosX(20.0f); - - bool highlight = shift_enabled; - if (highlight) { - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.2f, 0.6f, 1.0f, 1.0f)); - } - - if (ImGui::Button("SHIFT", ImVec2(75, 35))) { - shift_enabled = !shift_enabled; - } - - if (highlight) { - ImGui::PopStyleColor(); - } - - ImGui::SameLine(); - - if (ImGui::Button("SPACE", ImVec2(100, 35))) { - size_t len = std::strlen(buffer); - if (len + 1 < buffer_capacity) { - buffer[len] = ' '; - buffer[len + 1] = '\0'; - if (input_changed) { - *input_changed = true; + break; + case KeyType::Backspace: + if (buffer[0] != '\0') { + size_t len = std::strlen(buffer); + buffer[len - 1] = '\0'; + if (input_changed) + *input_changed = true; + } + break; + case KeyType::Space: + if (std::strlen(buffer) + 1 < buffer_capacity) { + std::strcat(buffer, " "); + if (input_changed) + *input_changed = true; + } + break; + case KeyType::Enter: + case KeyType::Done: + if (done_pressed) + *done_pressed = true; + break; + case KeyType::Shift: + shift_enabled = !shift_enabled; + break; + case KeyType::SymbolsLayout: + kb_mode = KeyboardMode::Symbols; + break; + case KeyType::TextLayout: + kb_mode = KeyboardMode::Letters; + break; + case KeyType::ToggleKeyboard: + kb_mode = (kb_mode == KeyboardMode::Letters) ? KeyboardMode::Symbols + : KeyboardMode::Letters; + break; + default: + break; } } - } - ImGui::SameLine(); + // Controller hint + if (!key.controller_hint.empty()) { + float original_font_size = ImGui::GetFontSize(); + float small_font_size = original_font_size * 0.5f; - if (ImGui::Button("DELETE", ImVec2(75, 35))) { - size_t len = std::strlen(buffer); - if (len > 0) { - buffer[len - 1] = '\0'; - if (input_changed) { - *input_changed = true; - } + ImVec2 text_size = + ImGui::CalcTextSize(key.controller_hint.c_str(), nullptr, false, -1.0f) * + (small_font_size / original_font_size); + + ImVec2 text_pos = pos + ImVec2(hint_padding, hint_padding); + ImVec2 bg_min = text_pos - ImVec2(1.0f, 1.0f); + ImVec2 bg_max = text_pos + text_size + ImVec2(2.0f, 1.0f); + + ImU32 bg_color = IM_COL32(0, 0, 0, 160); + ImU32 fg_color = IM_COL32(255, 255, 255, 200); + + draw_list->AddRectFilled(bg_min, bg_max, bg_color, 2.0f); + draw_list->AddText(nullptr, small_font_size, text_pos, fg_color, + key.controller_hint.c_str()); } } - - ImGui::SameLine(); - - if (ImGui::Button(kb_mode == KeyboardMode::Letters ? "123" : "ABC", ImVec2(60, 35))) { - kb_mode = - (kb_mode == KeyboardMode::Letters) ? KeyboardMode::Symbols : KeyboardMode::Letters; - } } diff --git a/src/core/libraries/ime/ime_keyboard_ui.h b/src/core/libraries/ime/ime_keyboard_ui.h index 0a5393bcc..19be74a9d 100644 --- a/src/core/libraries/ime/ime_keyboard_ui.h +++ b/src/core/libraries/ime/ime_keyboard_ui.h @@ -1,9 +1,23 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + #pragma once #include "common/cstring.h" #include "common/types.h" +#include "core/libraries/ime/ime_dialog.h" +#include "core/libraries/ime/ime_keyboard_layouts.h" enum class KeyboardMode { Letters, Symbols }; +// Renders the virtual keyboard and modifies buffer if a key is pressed. +// Flags: +// - `input_changed`: set to true if the text buffer changes +// - `done_pressed`: set to true if the Done/Enter key was pressed void DrawVirtualKeyboard(char* buffer, std::size_t buffer_capacity, bool* input_changed, - KeyboardMode& kb_mode, bool& shift_enabled); + KeyboardMode& kb_mode, bool& shift_enabled, bool* done_pressed); + +// Renders a specific keyboard layout and processes key events. +void RenderKeyboardLayout(const std::vector& layout, char* buffer, std::size_t buffer_capacity, + bool* input_changed, KeyboardMode& kb_mode, bool& shift_enabled, + bool* done_pressed); diff --git a/src/core/libraries/ime/ime_ui.cpp b/src/core/libraries/ime/ime_ui.cpp index 43bbf6a85..0ba2dc433 100644 --- a/src/core/libraries/ime/ime_ui.cpp +++ b/src/core/libraries/ime/ime_ui.cpp @@ -195,12 +195,19 @@ void ImeUi::DrawKeyboard() { static bool has_logged = false; if (!has_logged) { - LOG_INFO(Lib_ImeDialog, "Virtual keyboard used from Ime"); + LOG_INFO(Lib_Ime, "Virtual keyboard used from ImeUi"); has_logged = true; } - DrawVirtualKeyboard(state->current_text.begin(), ime_param->maxTextLength * 4, nullptr, kb_mode, - shift_enabled); + bool input_changed = false; + bool done_pressed = false; + + DrawVirtualKeyboard(state->current_text.begin(), state->current_text.capacity(), &input_changed, + kb_mode, shift_enabled, &done_pressed); + + if (done_pressed) { + state->SendEnterEvent(); // Submit action + } } int ImeUi::InputTextCallback(ImGuiInputTextCallbackData* data) { From 57a997ecff6d1db2ff8bda2852695be1c9e202a3 Mon Sep 17 00:00:00 2001 From: w1naenator Date: Fri, 28 Mar 2025 17:48:27 +0200 Subject: [PATCH 07/20] CLang fix --- .../libraries/ime/ime_keyboard_layouts.cpp | 21 ++++++++----------- src/core/libraries/ime/ime_keyboard_layouts.h | 16 +++++++------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/core/libraries/ime/ime_keyboard_layouts.cpp b/src/core/libraries/ime/ime_keyboard_layouts.cpp index a6e4548ea..41cf784cb 100644 --- a/src/core/libraries/ime/ime_keyboard_layouts.cpp +++ b/src/core/libraries/ime/ime_keyboard_layouts.cpp @@ -67,11 +67,10 @@ const std::vector kUppercaseLayout = { // Row 6 {5, 0, 1, 1, "UP", "", KeyType::CursorUp}, //{5, 0, 1, 1, "▲", "", KeyType::CursorUp}, {5, 1, 1, 1, "DN", "", KeyType::CursorDown}, //{5, 1, 1, 1, "▼", "", KeyType::CursorDown}, - {5, 2, 1, 1, "LT", "L1", KeyType::CursorLeft}, //{5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft}, - {5, 3, 1, 1, "RT", "R1", - KeyType::CursorRight}, //{5, 3, 1, 1, "▶", "R1", KeyType::CursorRight}, + {5, 2, 1, 1, "LT", "L1", KeyType::CursorLeft}, //{5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft}, + {5, 3, 1, 1, "RT", "R1", KeyType::CursorRight}, //{5, 3, 1, 1, "▶", "R1", KeyType::CursorRight}, {5, 4, 1, 1, "KB", "", - KeyType::ToggleKeyboard}, //{5, 4, 1, 1, "⌨", "", KeyType::ToggleKeyboard}, + KeyType::ToggleKeyboard}, //{5, 4, 1, 1, "⌨", "", KeyType::ToggleKeyboard}, {5, 5, 1, 1, "...", "", KeyType::MoreOptions}, //{5, 5, 1, 1, "…", "", KeyType::MoreOptions}, {5, 6, 1, 1, "CR", "R1", KeyType::ControllerAction}, //{5, 6, 1, 1, "🎮⊕", "R1", KeyType::ControllerAction}, @@ -145,11 +144,10 @@ const std::vector kLowercaseLayout = { // Row 6 {5, 0, 1, 1, "UP", "", KeyType::CursorUp}, // {5, 0, 1, 1, "▲", "", KeyType::CursorUp}, {5, 1, 1, 1, "DN", "", KeyType::CursorDown}, //{5, 1, 1, 1, "▼", "", KeyType::CursorDown}, - {5, 2, 1, 1, "LT", "L1", KeyType::CursorLeft}, //{5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft}, - {5, 3, 1, 1, "RT", "R1", - KeyType::CursorRight}, //{5, 3, 1, 1, "▶", "R1", KeyType::CursorRight}, + {5, 2, 1, 1, "LT", "L1", KeyType::CursorLeft}, //{5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft}, + {5, 3, 1, 1, "RT", "R1", KeyType::CursorRight}, //{5, 3, 1, 1, "▶", "R1", KeyType::CursorRight}, {5, 4, 1, 1, "KB", "", - KeyType::ToggleKeyboard}, //{5, 4, 1, 1, "⌨", "", KeyType::ToggleKeyboard}, + KeyType::ToggleKeyboard}, //{5, 4, 1, 1, "⌨", "", KeyType::ToggleKeyboard}, {5, 5, 1, 1, "...", "", KeyType::MoreOptions}, //{5, 5, 1, 1, "…", "", KeyType::MoreOptions}, {5, 6, 1, 1, "CR", "R1", KeyType::ControllerAction}, //{5, 6, 1, 1, "🎮⊕", "R1", KeyType::ControllerAction}, @@ -223,11 +221,10 @@ const std::vector kSymbols1Layout = { // Row 6 {5, 0, 1, 1, "UP", "", KeyType::CursorUp}, // {5, 0, 1, 1, "▲", "", KeyType::CursorUp}, {5, 1, 1, 1, "DN", "", KeyType::CursorDown}, //{5, 1, 1, 1, "▼", "", KeyType::CursorDown}, - {5, 2, 1, 1, "LT", "L1", KeyType::CursorLeft}, //{5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft}, - {5, 3, 1, 1, "RT", "R1", - KeyType::CursorRight}, //{5, 3, 1, 1, "▶", "R1", KeyType::CursorRight}, + {5, 2, 1, 1, "LT", "L1", KeyType::CursorLeft}, //{5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft}, + {5, 3, 1, 1, "RT", "R1", KeyType::CursorRight}, //{5, 3, 1, 1, "▶", "R1", KeyType::CursorRight}, {5, 4, 1, 1, "KB", "", - KeyType::ToggleKeyboard}, //{5, 4, 1, 1, "⌨", "", KeyType::ToggleKeyboard}, + KeyType::ToggleKeyboard}, //{5, 4, 1, 1, "⌨", "", KeyType::ToggleKeyboard}, {5, 5, 1, 1, "...", "", KeyType::MoreOptions}, //{5, 5, 1, 1, "…", "", KeyType::MoreOptions}, {5, 6, 1, 1, "CR", "R1", KeyType::ControllerAction}, //{5, 6, 1, 1, "🎮⊕", "R1", KeyType::ControllerAction}, diff --git a/src/core/libraries/ime/ime_keyboard_layouts.h b/src/core/libraries/ime/ime_keyboard_layouts.h index 0f51509c6..ebadfdb80 100644 --- a/src/core/libraries/ime/ime_keyboard_layouts.h +++ b/src/core/libraries/ime/ime_keyboard_layouts.h @@ -7,14 +7,14 @@ #include enum class KeyType { - Text, // Inserts character(s) into input buffer - Backspace, // Deletes last character - Space, // Adds space - Enter, // Submits input - Shift, // Toggle uppercase/lowercase - SymbolsLayout, // Switch to symbols layout - TextLayout, // Switch to text layout - Done, // Finish and close keyboard + Text, // Inserts character(s) into input buffer + Backspace, // Deletes last character + Space, // Adds space + Enter, // Submits input + Shift, // Toggle uppercase/lowercase + SymbolsLayout, // Switch to symbols layout + TextLayout, // Switch to text layout + Done, // Finish and close keyboard CursorLeft, CursorRight, CursorUp, From d3de64f1ffb7ca37a03773d9ea990de093b16359 Mon Sep 17 00:00:00 2001 From: w1naenator Date: Mon, 31 Mar 2025 12:59:11 +0300 Subject: [PATCH 08/20] some font fixes --- CMakeSettings.json | 2 +- .../libraries/ime/ime_keyboard_layouts.cpp | 63 +++++++++---------- src/imgui/renderer/imgui_core.cpp | 33 ++++++++++ 3 files changed, 63 insertions(+), 35 deletions(-) diff --git a/CMakeSettings.json b/CMakeSettings.json index bb522fcfc..1e9e3594c 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -6,7 +6,7 @@ "configurationType": "Release", "buildRoot": "${projectDir}\\Build\\${name}", "installRoot": "${projectDir}\\Install\\${name}", - "cmakeCommandArgs": "", + "cmakeCommandArgs": "-DENABLE_QT_GUI=ON -DCMAKE_PREFIX_PATH=C:\\Qt\\6.8.2\\msvc2022_64", "buildCommandArgs": "", "ctestCommandArgs": "", "inheritEnvironments": [ "clang_cl_x64_x64" ], diff --git a/src/core/libraries/ime/ime_keyboard_layouts.cpp b/src/core/libraries/ime/ime_keyboard_layouts.cpp index 41cf784cb..ece10520d 100644 --- a/src/core/libraries/ime/ime_keyboard_layouts.cpp +++ b/src/core/libraries/ime/ime_keyboard_layouts.cpp @@ -53,27 +53,26 @@ const std::vector kUppercaseLayout = { {3, 9, 1, 1, "/", "", KeyType::Text}, // Row 5 - {4, 0, 1, 1, "SF", "L2", KeyType::Shift}, //{4, 0, 1, 1, "⇧", "L2", KeyType::Shift}, - {4, 1, 1, 1, "@#:", "L2+TRI", KeyType::SymbolsLayout}, + {4, 0, 1, 1, "⬆", "L2", KeyType::Shift}, + {4, 1, 1, 1, "@#:", "L2+△", KeyType::SymbolsLayout}, {4, 2, 1, 1, "à", "L3", KeyType::UnknownFunction}, - {4, 3, 4, 1, "Space", "TRI", KeyType::Space}, //{4, 3, 4, 1, "Space", "△", KeyType::Space}, + {4, 3, 4, 1, "Space", "△", KeyType::Space}, //{4, 4, 4, 1, "Space", "△", KeyType::Space}, //{4, 5, 4, 1, "Space", "△", KeyType::Space}, //{4, 6, 4, 1, "Space", "△", KeyType::Space}, {4, 7, 1, 1, "", "", KeyType::Disabled}, - {4, 8, 2, 1, "DEL", "SQR", KeyType::Backspace}, //{4, 8, 2, 1, "⌫", "▢", KeyType::Backspace}, - //{4, 9, 2, 1, "⌫", "▢", KeyType::Backspace}, + {4, 8, 2, 1, "⇦", "□", KeyType::Backspace}, //{4, 8, 2, 1, "⌫", "□", KeyType::Backspace}, + //{4, 9, 2, 1, "⌫", "□", KeyType::Backspace}, // Row 6 - {5, 0, 1, 1, "UP", "", KeyType::CursorUp}, //{5, 0, 1, 1, "▲", "", KeyType::CursorUp}, - {5, 1, 1, 1, "DN", "", KeyType::CursorDown}, //{5, 1, 1, 1, "▼", "", KeyType::CursorDown}, - {5, 2, 1, 1, "LT", "L1", KeyType::CursorLeft}, //{5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft}, - {5, 3, 1, 1, "RT", "R1", KeyType::CursorRight}, //{5, 3, 1, 1, "▶", "R1", KeyType::CursorRight}, + {5, 0, 1, 1, "▲", "", KeyType::CursorUp}, + {5, 1, 1, 1, "▼", "", KeyType::CursorDown}, + {5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft}, + {5, 3, 1, 1, "▶", "R1", KeyType::CursorRight}, {5, 4, 1, 1, "KB", "", KeyType::ToggleKeyboard}, //{5, 4, 1, 1, "⌨", "", KeyType::ToggleKeyboard}, {5, 5, 1, 1, "...", "", KeyType::MoreOptions}, //{5, 5, 1, 1, "…", "", KeyType::MoreOptions}, - {5, 6, 1, 1, "CR", "R1", - KeyType::ControllerAction}, //{5, 6, 1, 1, "🎮⊕", "R1", KeyType::ControllerAction}, + {5, 6, 1, 1, "+/⊗", "R3", KeyType::ControllerAction}, {5, 7, 1, 1, "", "", KeyType::Disabled}, {5, 8, 2, 1, "Done", "R2", KeyType::Done}, //{5, 9, 2, 1, "Done", "R2", KeyType::Done}, @@ -129,28 +128,26 @@ const std::vector kLowercaseLayout = { {3, 9, 1, 1, "_", "", KeyType::Text}, // Row 5 - {4, 0, 1, 1, "SF", "L2", KeyType::Shift}, //{4, 0, 1, 1, "⇧", "L2", KeyType::Shift}, - {4, 1, 1, 1, "@#:", "L2+TRI", - KeyType::SymbolsLayout}, //{4, 1, 1, 1, "@#:", "L2+△", KeyType::Symbols}, + {4, 0, 1, 1, "⇧", "L2", KeyType::Shift}, + {4, 1, 1, 1, "@#:", "L2+△", KeyType::SymbolsLayout}, {4, 2, 1, 1, "à", "L3", KeyType::UnknownFunction}, - {4, 3, 4, 1, "Space", "TRI", KeyType::Space}, //{4, 3, 4, 1, "Space", "△", KeyType::Space}, + {4, 3, 4, 1, "Space", "△", KeyType::Space}, //{4, 4, 4, 1, "Space", "△", KeyType::Space}, //{4, 5, 4, 1, "Space", "△", KeyType::Space}, //{4, 6, 4, 1, "Space", "△", KeyType::Space}, {4, 7, 1, 1, "", "", KeyType::Disabled}, - {4, 8, 2, 1, "DEL", "SQR", KeyType::Backspace}, //{4, 8, 2, 1, "⌫", "▢", KeyType::Backspace}, - //{4, 8, 2, 1, "⌫", "▢", KeyType::Backspace}, + {4, 8, 2, 1, "⇦", "□", KeyType::Backspace}, //{4, 8, 2, 1, "⌫", "□", KeyType::Backspace}, + //{4, 8, 2, 1, "⌫", "□", KeyType::Backspace}, // Row 6 - {5, 0, 1, 1, "UP", "", KeyType::CursorUp}, // {5, 0, 1, 1, "▲", "", KeyType::CursorUp}, - {5, 1, 1, 1, "DN", "", KeyType::CursorDown}, //{5, 1, 1, 1, "▼", "", KeyType::CursorDown}, - {5, 2, 1, 1, "LT", "L1", KeyType::CursorLeft}, //{5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft}, - {5, 3, 1, 1, "RT", "R1", KeyType::CursorRight}, //{5, 3, 1, 1, "▶", "R1", KeyType::CursorRight}, + {5, 0, 1, 1, "▲", "", KeyType::CursorUp}, + {5, 1, 1, 1, "▼", "", KeyType::CursorDown}, + {5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft}, + {5, 3, 1, 1, "▶", "R1", KeyType::CursorRight}, {5, 4, 1, 1, "KB", "", KeyType::ToggleKeyboard}, //{5, 4, 1, 1, "⌨", "", KeyType::ToggleKeyboard}, {5, 5, 1, 1, "...", "", KeyType::MoreOptions}, //{5, 5, 1, 1, "…", "", KeyType::MoreOptions}, - {5, 6, 1, 1, "CR", "R1", - KeyType::ControllerAction}, //{5, 6, 1, 1, "🎮⊕", "R1", KeyType::ControllerAction}, + {5, 6, 1, 1, "+/⊗", "R3", KeyType::ControllerAction}, {5, 7, 1, 1, "", "", KeyType::Disabled}, {5, 8, 2, 1, "Done", "R2", KeyType::Done}, //{5, 9, 2, 1, "Done", "R2", KeyType::Done}, @@ -207,27 +204,25 @@ const std::vector kSymbols1Layout = { // Row 5 {4, 0, 1, 1, "", "", KeyType::Disabled}, - {4, 1, 1, 1, "ABC", "L2+TRI", - KeyType::TextLayout}, //{4, 1, 1, 1, "ABC", "L2+△", KeyType::Symbols}, + {4, 1, 1, 1, "ABC", "L2+△", KeyType::TextLayout}, {4, 2, 1, 1, "", "", KeyType::Disabled}, - {4, 3, 4, 1, "Space", "TRI", KeyType::Space}, //{4, 3, 4, 1, "Space", "△", KeyType::Space}, + {4, 3, 4, 1, "Space", "△", KeyType::Space}, //{4, 4, 4, 1, "Space", "△", KeyType::Space}, //{4, 5, 4, 1, "Space", "△", KeyType::Space}, //{4, 6, 4, 1, "Space", "△", KeyType::Space}, {4, 7, 1, 1, "", "", KeyType::Disabled}, - {4, 8, 2, 1, "DEL", "SQR", KeyType::Backspace}, //{4, 8, 2, 1, "⌫", "▢", KeyType::Backspace}, - //{4, 9, 2, 1, "⌫", "▢", KeyType::Backspace}, + {4, 8, 2, 1, "⇦", "□", KeyType::Backspace}, //{4, 8, 2, 1, "⌫", "□", KeyType::Backspace}, + //{4, 9, 2, 1, "⌫", "□", KeyType::Backspace}, // Row 6 - {5, 0, 1, 1, "UP", "", KeyType::CursorUp}, // {5, 0, 1, 1, "▲", "", KeyType::CursorUp}, - {5, 1, 1, 1, "DN", "", KeyType::CursorDown}, //{5, 1, 1, 1, "▼", "", KeyType::CursorDown}, - {5, 2, 1, 1, "LT", "L1", KeyType::CursorLeft}, //{5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft}, - {5, 3, 1, 1, "RT", "R1", KeyType::CursorRight}, //{5, 3, 1, 1, "▶", "R1", KeyType::CursorRight}, + {5, 0, 1, 1, "▲", "", KeyType::CursorUp}, + {5, 1, 1, 1, "▼", "", KeyType::CursorDown}, + {5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft}, + {5, 3, 1, 1, "▶", "R1", KeyType::CursorRight}, {5, 4, 1, 1, "KB", "", KeyType::ToggleKeyboard}, //{5, 4, 1, 1, "⌨", "", KeyType::ToggleKeyboard}, {5, 5, 1, 1, "...", "", KeyType::MoreOptions}, //{5, 5, 1, 1, "…", "", KeyType::MoreOptions}, - {5, 6, 1, 1, "CR", "R1", - KeyType::ControllerAction}, //{5, 6, 1, 1, "🎮⊕", "R1", KeyType::ControllerAction}, + {5, 6, 1, 1, "+/⊗", "R3", KeyType::ControllerAction}, {5, 7, 1, 1, "", "", KeyType::Disabled}, {5, 8, 2, 1, "Done", "R2", KeyType::Done}, //{5, 9, 2, 1, "Done", "R2", KeyType::Done}, diff --git a/src/imgui/renderer/imgui_core.cpp b/src/imgui/renderer/imgui_core.cpp index 50ce41ebf..5ce2686a7 100644 --- a/src/imgui/renderer/imgui_core.cpp +++ b/src/imgui/renderer/imgui_core.cpp @@ -69,14 +69,47 @@ void Initialize(const ::Vulkan::Instance& instance, const Frontend::WindowSDL& w rb.AddRanges(io.Fonts->GetGlyphRangesKorean()); rb.AddRanges(io.Fonts->GetGlyphRangesJapanese()); rb.AddRanges(io.Fonts->GetGlyphRangesCyrillic()); + rb.AddChar(0x00D7); // × Cross + rb.AddChar(0x25CB); // ○ Circle + rb.AddChar(0x25B3); // △ Triangle + rb.AddChar(0x25A1); // □ Square + rb.AddChar(0x2191); // ↑ Up Arrow + rb.AddChar(0x2193); // ↓ Down Arrow + rb.AddChar(0x2190); // ← Left Arrow + rb.AddChar(0x2192); // → Right Arrow + + rb.AddChar(0x2297); // ⊗ Circled Times (often used as cross) + rb.AddChar(0x2BBE); // ⮾ Circled X (if supported by font) + rb.AddChar(0x1F5D9); // 🗙 Cancellation X (heavy) + + rb.AddChar(0x25C0); // ◀ Black Left-Pointing Triangle + rb.AddChar(0x25B2); // ▲ Black Up-Pointing Triangle + rb.AddChar(0x25B6); // ▶ Black Right-Pointing Triangle + rb.AddChar(0x25BC); // ▼ Black Down-Pointing Triangle + + rb.AddChar(0x232B); // ⌫ Backspace + + rb.AddChar(0x21E7); // ⇧ UPWARDS WHITE ARROW + rb.AddChar(0x2B06); // ⬆ UPWARDS BLACK ARROW + + rb.AddChar(0x21E6); // ⇦ Leftwards White Arrow + + + //rb.AddRanges(io.Fonts->GetGlyphRangesDefault()); + // Manually add full BMP range + //for (ImWchar c = 0x0020; c <= 0xFFFF; ++c) { + // rb.AddChar(c); + //} ImVector ranges{}; rb.BuildRanges(&ranges); ImFontConfig font_cfg{}; font_cfg.OversampleH = 2; font_cfg.OversampleV = 1; + font_cfg.MergeMode = false; io.FontDefault = io.Fonts->AddFontFromMemoryCompressedTTF( imgui_font_notosansjp_regular_compressed_data, imgui_font_notosansjp_regular_compressed_size, 16.0f, &font_cfg, ranges.Data); + font_cfg.MergeMode = true; io.Fonts->AddFontFromMemoryCompressedTTF(imgui_font_proggyvector_regular_compressed_data, imgui_font_proggyvector_regular_compressed_size, 16.0f); From 9f5afa812e2bb86a8dd4e70a57168cf7820258bd Mon Sep 17 00:00:00 2001 From: w1naenator Date: Tue, 1 Apr 2025 09:34:23 +0300 Subject: [PATCH 09/20] added controller shortcuts to key configuration --- .../libraries/ime/ime_keyboard_layouts.cpp | 385 +++++++++--------- src/core/libraries/ime/ime_keyboard_layouts.h | 3 + src/core/libraries/ime/ime_keyboard_ui.cpp | 79 +++- src/core/libraries/ime/ime_keyboard_ui.h | 16 +- 4 files changed, 287 insertions(+), 196 deletions(-) diff --git a/src/core/libraries/ime/ime_keyboard_layouts.cpp b/src/core/libraries/ime/ime_keyboard_layouts.cpp index ece10520d..e81bfb209 100644 --- a/src/core/libraries/ime/ime_keyboard_layouts.cpp +++ b/src/core/libraries/ime/ime_keyboard_layouts.cpp @@ -1,229 +1,248 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "core/libraries/pad/pad.h" #include "ime_keyboard_layouts.h" +using B = Libraries::Pad::OrbisPadButtonDataOffset; + +constexpr auto L1 = B::L1; +constexpr auto R1 = B::R1; +constexpr auto L2 = B::L2; +constexpr auto R2 = B::R2; +constexpr auto L3 = B::L3; +constexpr auto R3 = B::R3; +constexpr auto Up = B::Up; +constexpr auto Down = B::Down; +constexpr auto Left = B::Left; +constexpr auto Right = B::Right; +constexpr auto Cross = B::Cross; +constexpr auto Circle = B::Circle; +constexpr auto Square = B::Square; +constexpr auto Triangle = B::Triangle; +constexpr auto TouchPad = B::TouchPad; const std::vector kUppercaseLayout = { // Row 1 - {0, 0, 1, 1, "1", "", KeyType::Text}, - {0, 1, 1, 1, "2", "", KeyType::Text}, - {0, 2, 1, 1, "3", "", KeyType::Text}, - {0, 3, 1, 1, "4", "", KeyType::Text}, - {0, 4, 1, 1, "5", "", KeyType::Text}, - {0, 5, 1, 1, "6", "", KeyType::Text}, - {0, 6, 1, 1, "7", "", KeyType::Text}, - {0, 7, 1, 1, "8", "", KeyType::Text}, - {0, 8, 1, 1, "9", "", KeyType::Text}, - {0, 9, 1, 1, "0", "", KeyType::Text}, + {0, 0, 1, 1, "1", "", KeyType::Text, {}}, + {0, 1, 1, 1, "2", "", KeyType::Text, {}}, + {0, 2, 1, 1, "3", "", KeyType::Text, {}}, + {0, 3, 1, 1, "4", "", KeyType::Text, {}}, + {0, 4, 1, 1, "5", "", KeyType::Text, {}}, + {0, 5, 1, 1, "6", "", KeyType::Text, {}}, + {0, 6, 1, 1, "7", "", KeyType::Text, {}}, + {0, 7, 1, 1, "8", "", KeyType::Text, {}}, + {0, 8, 1, 1, "9", "", KeyType::Text, {}}, + {0, 9, 1, 1, "0", "", KeyType::Text, {}}, // Row 2 - {1, 0, 1, 1, "Q", "", KeyType::Text}, - {1, 1, 1, 1, "W", "", KeyType::Text}, - {1, 2, 1, 1, "E", "", KeyType::Text}, - {1, 3, 1, 1, "R", "", KeyType::Text}, - {1, 4, 1, 1, "T", "", KeyType::Text}, - {1, 5, 1, 1, "Y", "", KeyType::Text}, - {1, 6, 1, 1, "U", "", KeyType::Text}, - {1, 7, 1, 1, "I", "", KeyType::Text}, - {1, 8, 1, 1, "O", "", KeyType::Text}, - {1, 9, 1, 1, "P", "", KeyType::Text}, + {1, 0, 1, 1, "Q", "", KeyType::Text, {}}, + {1, 1, 1, 1, "W", "", KeyType::Text, {}}, + {1, 2, 1, 1, "E", "", KeyType::Text, {}}, + {1, 3, 1, 1, "R", "", KeyType::Text, {}}, + {1, 4, 1, 1, "T", "", KeyType::Text, {}}, + {1, 5, 1, 1, "Y", "", KeyType::Text, {}}, + {1, 6, 1, 1, "U", "", KeyType::Text, {}}, + {1, 7, 1, 1, "I", "", KeyType::Text, {}}, + {1, 8, 1, 1, "O", "", KeyType::Text, {}}, + {1, 9, 1, 1, "P", "", KeyType::Text, {}}, // Row 3 - {2, 0, 1, 1, "A", "", KeyType::Text}, - {2, 1, 1, 1, "S", "", KeyType::Text}, - {2, 2, 1, 1, "D", "", KeyType::Text}, - {2, 3, 1, 1, "F", "", KeyType::Text}, - {2, 4, 1, 1, "G", "", KeyType::Text}, - {2, 5, 1, 1, "H", "", KeyType::Text}, - {2, 6, 1, 1, "J", "", KeyType::Text}, - {2, 7, 1, 1, "K", "", KeyType::Text}, - {2, 8, 1, 1, "L", "", KeyType::Text}, - {2, 9, 1, 1, "\"", "", KeyType::Text}, + {2, 0, 1, 1, "A", "", KeyType::Text, {}}, + {2, 1, 1, 1, "S", "", KeyType::Text, {}}, + {2, 2, 1, 1, "D", "", KeyType::Text, {}}, + {2, 3, 1, 1, "F", "", KeyType::Text, {}}, + {2, 4, 1, 1, "G", "", KeyType::Text, {}}, + {2, 5, 1, 1, "H", "", KeyType::Text, {}}, + {2, 6, 1, 1, "J", "", KeyType::Text, {}}, + {2, 7, 1, 1, "K", "", KeyType::Text, {}}, + {2, 8, 1, 1, "L", "", KeyType::Text, {}}, + {2, 9, 1, 1, "\"", "", KeyType::Text, {}}, // Row 4 - {3, 0, 1, 1, "Z", "", KeyType::Text}, - {3, 1, 1, 1, "X", "", KeyType::Text}, - {3, 2, 1, 1, "C", "", KeyType::Text}, - {3, 3, 1, 1, "V", "", KeyType::Text}, - {3, 4, 1, 1, "B", "", KeyType::Text}, - {3, 5, 1, 1, "N", "", KeyType::Text}, - {3, 6, 1, 1, "M", "", KeyType::Text}, - {3, 7, 1, 1, "-", "", KeyType::Text}, - {3, 8, 1, 1, "_", "", KeyType::Text}, - {3, 9, 1, 1, "/", "", KeyType::Text}, + {3, 0, 1, 1, "Z", "", KeyType::Text, {}}, + {3, 1, 1, 1, "X", "", KeyType::Text, {}}, + {3, 2, 1, 1, "C", "", KeyType::Text, {}}, + {3, 3, 1, 1, "V", "", KeyType::Text, {}}, + {3, 4, 1, 1, "B", "", KeyType::Text, {}}, + {3, 5, 1, 1, "N", "", KeyType::Text, {}}, + {3, 6, 1, 1, "M", "", KeyType::Text, {}}, + {3, 7, 1, 1, "-", "", KeyType::Text, {}}, + {3, 8, 1, 1, "_", "", KeyType::Text, {}}, + {3, 9, 1, 1, "/", "", KeyType::Text, {}}, // Row 5 - {4, 0, 1, 1, "⬆", "L2", KeyType::Shift}, - {4, 1, 1, 1, "@#:", "L2+△", KeyType::SymbolsLayout}, - {4, 2, 1, 1, "à", "L3", KeyType::UnknownFunction}, - {4, 3, 4, 1, "Space", "△", KeyType::Space}, - //{4, 4, 4, 1, "Space", "△", KeyType::Space}, - //{4, 5, 4, 1, "Space", "△", KeyType::Space}, - //{4, 6, 4, 1, "Space", "△", KeyType::Space}, - {4, 7, 1, 1, "", "", KeyType::Disabled}, - {4, 8, 2, 1, "⇦", "□", KeyType::Backspace}, //{4, 8, 2, 1, "⌫", "□", KeyType::Backspace}, - //{4, 9, 2, 1, "⌫", "□", KeyType::Backspace}, + {4, 0, 1, 1, "⬆", "L2", KeyType::Shift, {L2}}, + + {4, 1, 1, 1, "@#:", "L2+△", KeyType::SymbolsLayout, {L3, Triangle}}, + {4, 2, 1, 1, "à", "L3", KeyType::UnknownFunction, {L3}}, + {4, 3, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, + //{4, 4, 4, 1, "Space", "△", KeyType::Space,{}}, + //{4, 5, 4, 1, "Space", "△", KeyType::Space,{}}, + //{4, 6, 4, 1, "Space", "△", KeyType::Space,{}}, + {4, 7, 1, 1, "", "", KeyType::Disabled, {}}, + {4, 8, 2, 1, "⇦", "□", KeyType::Backspace, {Square}}, + //{4, 9, 2, 1, "⇦", "□", KeyType::Backspace,{}}, // Row 6 - {5, 0, 1, 1, "▲", "", KeyType::CursorUp}, - {5, 1, 1, 1, "▼", "", KeyType::CursorDown}, - {5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft}, - {5, 3, 1, 1, "▶", "R1", KeyType::CursorRight}, - {5, 4, 1, 1, "KB", "", - KeyType::ToggleKeyboard}, //{5, 4, 1, 1, "⌨", "", KeyType::ToggleKeyboard}, - {5, 5, 1, 1, "...", "", KeyType::MoreOptions}, //{5, 5, 1, 1, "…", "", KeyType::MoreOptions}, - {5, 6, 1, 1, "+/⊗", "R3", KeyType::ControllerAction}, - {5, 7, 1, 1, "", "", KeyType::Disabled}, - {5, 8, 2, 1, "Done", "R2", KeyType::Done}, - //{5, 9, 2, 1, "Done", "R2", KeyType::Done}, + {5, 0, 1, 1, "▲", "", KeyType::CursorUp, {Up}}, + {5, 1, 1, 1, "▼", "", KeyType::CursorDown, {Down}}, + {5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft, {L1}}, + {5, 3, 1, 1, "▶", "R1", KeyType::CursorRight, {R1}}, + {5, 4, 1, 1, "KB", "", KeyType::ToggleKeyboard, {}}, + //{5, 4, 1, 1, "⌨", "", KeyType::ToggleKeyboard,{}}, + {5, 5, 1, 1, "...", "", KeyType::MoreOptions, {}}, + //{5, 5, 1, 1, "…", "", KeyType::MoreOptions,{}}, + {5, 6, 1, 1, "+/⊗", "R3", KeyType::ControllerAction, {R3}}, + {5, 7, 1, 1, "", "", KeyType::Disabled, {}}, + {5, 8, 2, 1, "Done", "R2", KeyType::Done, {R2}}, + //{5, 9, 2, 1, "Done", "R2", KeyType::Done,{}}, }; const std::vector kLowercaseLayout = { // Row 1 - {0, 0, 1, 1, "1", "", KeyType::Text}, - {0, 1, 1, 1, "2", "", KeyType::Text}, - {0, 2, 1, 1, "3", "", KeyType::Text}, - {0, 3, 1, 1, "4", "", KeyType::Text}, - {0, 4, 1, 1, "5", "", KeyType::Text}, - {0, 5, 1, 1, "6", "", KeyType::Text}, - {0, 6, 1, 1, "7", "", KeyType::Text}, - {0, 7, 1, 1, "8", "", KeyType::Text}, - {0, 8, 1, 1, "9", "", KeyType::Text}, - {0, 9, 1, 1, "0", "", KeyType::Text}, + {0, 0, 1, 1, "1", "", KeyType::Text, {}}, + {0, 1, 1, 1, "2", "", KeyType::Text, {}}, + {0, 2, 1, 1, "3", "", KeyType::Text, {}}, + {0, 3, 1, 1, "4", "", KeyType::Text, {}}, + {0, 4, 1, 1, "5", "", KeyType::Text, {}}, + {0, 5, 1, 1, "6", "", KeyType::Text, {}}, + {0, 6, 1, 1, "7", "", KeyType::Text, {}}, + {0, 7, 1, 1, "8", "", KeyType::Text, {}}, + {0, 8, 1, 1, "9", "", KeyType::Text, {}}, + {0, 9, 1, 1, "0", "", KeyType::Text, {}}, // Row 2 - {1, 0, 1, 1, "q", "", KeyType::Text}, - {1, 1, 1, 1, "w", "", KeyType::Text}, - {1, 2, 1, 1, "e", "", KeyType::Text}, - {1, 3, 1, 1, "r", "", KeyType::Text}, - {1, 4, 1, 1, "t", "", KeyType::Text}, - {1, 5, 1, 1, "y", "", KeyType::Text}, - {1, 6, 1, 1, "u", "", KeyType::Text}, - {1, 7, 1, 1, "i", "", KeyType::Text}, - {1, 8, 1, 1, "o", "", KeyType::Text}, - {1, 9, 1, 1, "p", "", KeyType::Text}, + {1, 0, 1, 1, "q", "", KeyType::Text, {}}, + {1, 1, 1, 1, "w", "", KeyType::Text, {}}, + {1, 2, 1, 1, "e", "", KeyType::Text, {}}, + {1, 3, 1, 1, "r", "", KeyType::Text, {}}, + {1, 4, 1, 1, "t", "", KeyType::Text, {}}, + {1, 5, 1, 1, "y", "", KeyType::Text, {}}, + {1, 6, 1, 1, "u", "", KeyType::Text, {}}, + {1, 7, 1, 1, "i", "", KeyType::Text, {}}, + {1, 8, 1, 1, "o", "", KeyType::Text, {}}, + {1, 9, 1, 1, "p", "", KeyType::Text, {}}, // Row 3 - {2, 0, 1, 1, "a", "", KeyType::Text}, - {2, 1, 1, 1, "s", "", KeyType::Text}, - {2, 2, 1, 1, "d", "", KeyType::Text}, - {2, 3, 1, 1, "f", "", KeyType::Text}, - {2, 4, 1, 1, "g", "", KeyType::Text}, - {2, 5, 1, 1, "h", "", KeyType::Text}, - {2, 6, 1, 1, "j", "", KeyType::Text}, - {2, 7, 1, 1, "k", "", KeyType::Text}, - {2, 8, 1, 1, "l", "", KeyType::Text}, - {2, 9, 1, 1, "-", "", KeyType::Text}, + {2, 0, 1, 1, "a", "", KeyType::Text, {}}, + {2, 1, 1, 1, "s", "", KeyType::Text, {}}, + {2, 2, 1, 1, "d", "", KeyType::Text, {}}, + {2, 3, 1, 1, "f", "", KeyType::Text, {}}, + {2, 4, 1, 1, "g", "", KeyType::Text, {}}, + {2, 5, 1, 1, "h", "", KeyType::Text, {}}, + {2, 6, 1, 1, "j", "", KeyType::Text, {}}, + {2, 7, 1, 1, "k", "", KeyType::Text, {}}, + {2, 8, 1, 1, "l", "", KeyType::Text, {}}, + {2, 9, 1, 1, "-", "", KeyType::Text, {}}, // Row 4 - {3, 0, 1, 1, "z", "", KeyType::Text}, - {3, 1, 1, 1, "x", "", KeyType::Text}, - {3, 2, 1, 1, "c", "", KeyType::Text}, - {3, 3, 1, 1, "v", "", KeyType::Text}, - {3, 4, 1, 1, "b", "", KeyType::Text}, - {3, 5, 1, 1, "n", "", KeyType::Text}, - {3, 6, 1, 1, "m", "", KeyType::Text}, - {3, 7, 1, 1, "@", "", KeyType::Text}, - {3, 8, 1, 1, ".", "", KeyType::Text}, - {3, 9, 1, 1, "_", "", KeyType::Text}, + {3, 0, 1, 1, "z", "", KeyType::Text, {}}, + {3, 1, 1, 1, "x", "", KeyType::Text, {}}, + {3, 2, 1, 1, "c", "", KeyType::Text, {}}, + {3, 3, 1, 1, "v", "", KeyType::Text, {}}, + {3, 4, 1, 1, "b", "", KeyType::Text, {}}, + {3, 5, 1, 1, "n", "", KeyType::Text, {}}, + {3, 6, 1, 1, "m", "", KeyType::Text, {}}, + {3, 7, 1, 1, "@", "", KeyType::Text, {}}, + {3, 8, 1, 1, ".", "", KeyType::Text, {}}, + {3, 9, 1, 1, "_", "", KeyType::Text, {}}, // Row 5 - {4, 0, 1, 1, "⇧", "L2", KeyType::Shift}, - {4, 1, 1, 1, "@#:", "L2+△", KeyType::SymbolsLayout}, - {4, 2, 1, 1, "à", "L3", KeyType::UnknownFunction}, - {4, 3, 4, 1, "Space", "△", KeyType::Space}, - //{4, 4, 4, 1, "Space", "△", KeyType::Space}, - //{4, 5, 4, 1, "Space", "△", KeyType::Space}, - //{4, 6, 4, 1, "Space", "△", KeyType::Space}, - {4, 7, 1, 1, "", "", KeyType::Disabled}, - {4, 8, 2, 1, "⇦", "□", KeyType::Backspace}, //{4, 8, 2, 1, "⌫", "□", KeyType::Backspace}, - //{4, 8, 2, 1, "⌫", "□", KeyType::Backspace}, + {4, 0, 1, 1, "⇧", "L2", KeyType::Shift, {L2}}, + {4, 1, 1, 1, "@#:", "L2+△", KeyType::SymbolsLayout, {L2, Triangle}}, + {4, 2, 1, 1, "à", "L3", KeyType::UnknownFunction, {L3}}, + {4, 3, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, + //{4, 4, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, + //{4, 5, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, + //{4, 6, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, + {4, 7, 1, 1, "", "", KeyType::Disabled, {}}, + {4, 8, 2, 1, "⇦", "□", KeyType::Backspace, {Square}}, + //{4, 8, 2, 1, "⇦", "□", KeyType::Backspace, {Square}}, // Row 6 - {5, 0, 1, 1, "▲", "", KeyType::CursorUp}, - {5, 1, 1, 1, "▼", "", KeyType::CursorDown}, - {5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft}, - {5, 3, 1, 1, "▶", "R1", KeyType::CursorRight}, - {5, 4, 1, 1, "KB", "", - KeyType::ToggleKeyboard}, //{5, 4, 1, 1, "⌨", "", KeyType::ToggleKeyboard}, - {5, 5, 1, 1, "...", "", KeyType::MoreOptions}, //{5, 5, 1, 1, "…", "", KeyType::MoreOptions}, - {5, 6, 1, 1, "+/⊗", "R3", KeyType::ControllerAction}, - {5, 7, 1, 1, "", "", KeyType::Disabled}, - {5, 8, 2, 1, "Done", "R2", KeyType::Done}, - //{5, 9, 2, 1, "Done", "R2", KeyType::Done}, + {5, 0, 1, 1, "▲", "", KeyType::CursorUp, {Up}}, + {5, 1, 1, 1, "▼", "", KeyType::CursorDown, {Down}}, + {5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft, {L1}}, + {5, 3, 1, 1, "▶", "R1", KeyType::CursorRight, {R1}}, + {5, 4, 1, 1, "KB", "", KeyType::ToggleKeyboard, {}}, + {5, 5, 1, 1, "...", "", KeyType::MoreOptions, {}}, + {5, 6, 1, 1, "+/⊗", "R3", KeyType::ControllerAction, {R3}}, + {5, 7, 1, 1, "", "", KeyType::Disabled, {}}, + {5, 8, 2, 1, "Done", "R2", KeyType::Done, {R2}}, + //{5, 9, 2, 1, "Done", "R2", KeyType::Done, {R2}}, }; const std::vector kSymbols1Layout = { // Row 1 - {0, 0, 1, 1, "!", "", KeyType::Text}, - {0, 1, 1, 1, "?", "", KeyType::Text}, - {0, 2, 1, 1, "\"", "", KeyType::Text}, - {0, 3, 1, 1, "'", "", KeyType::Text}, - {0, 4, 1, 1, "#", "", KeyType::Text}, - {0, 5, 1, 1, "%", "", KeyType::Text}, - {0, 6, 1, 1, "(", "", KeyType::Text}, - {0, 7, 1, 1, ")", "", KeyType::Text}, - {0, 8, 1, 1, "()", "", KeyType::Text}, - {0, 9, 1, 1, "/", "", KeyType::Text}, + {0, 0, 1, 1, "!", "", KeyType::Text, {}}, + {0, 1, 1, 1, "?", "", KeyType::Text, {}}, + {0, 2, 1, 1, "\"", "", KeyType::Text, {}}, + {0, 3, 1, 1, "'", "", KeyType::Text, {}}, + {0, 4, 1, 1, "#", "", KeyType::Text, {}}, + {0, 5, 1, 1, "%", "", KeyType::Text, {}}, + {0, 6, 1, 1, "(", "", KeyType::Text, {}}, + {0, 7, 1, 1, ")", "", KeyType::Text, {}}, + {0, 8, 1, 1, "()", "", KeyType::Text, {}}, + {0, 9, 1, 1, "/", "", KeyType::Text, {}}, // Row 2 - {1, 0, 1, 1, "-", "", KeyType::Text}, - {1, 1, 1, 1, "_", "", KeyType::Text}, - {1, 2, 1, 1, ",", "", KeyType::Text}, - {1, 3, 1, 1, ".", "", KeyType::Text}, - {1, 4, 1, 1, ":", "", KeyType::Text}, - {1, 5, 1, 1, ";", "", KeyType::Text}, - {1, 6, 1, 1, "*", "", KeyType::Text}, - {1, 7, 1, 1, "+", "", KeyType::Text}, - {1, 8, 1, 1, "=", "", KeyType::Text}, - {1, 9, 1, 1, "&", "", KeyType::Text}, + {1, 0, 1, 1, "-", "", KeyType::Text, {}}, + {1, 1, 1, 1, "_", "", KeyType::Text, {}}, + {1, 2, 1, 1, ",", "", KeyType::Text, {}}, + {1, 3, 1, 1, ".", "", KeyType::Text, {}}, + {1, 4, 1, 1, ":", "", KeyType::Text, {}}, + {1, 5, 1, 1, ";", "", KeyType::Text, {}}, + {1, 6, 1, 1, "*", "", KeyType::Text, {}}, + {1, 7, 1, 1, "+", "", KeyType::Text, {}}, + {1, 8, 1, 1, "=", "", KeyType::Text, {}}, + {1, 9, 1, 1, "&", "", KeyType::Text, {}}, // Row 3 - {2, 0, 1, 1, "<", "", KeyType::Text}, - {2, 1, 1, 1, ">", "", KeyType::Text}, - {2, 2, 1, 1, "@", "", KeyType::Text}, - {2, 3, 1, 1, "[", "", KeyType::Text}, - {2, 4, 1, 1, "]", "", KeyType::Text}, - {2, 5, 1, 1, "[]", "", KeyType::Text}, - {2, 6, 1, 1, "{", "", KeyType::Text}, - {2, 7, 1, 1, "}", "", KeyType::Text}, - {2, 8, 1, 1, "{}", "", KeyType::Text}, - {2, 9, 1, 2, "→", "", KeyType::UnknownFunction}, // Next symbols page (SYM2) + {2, 0, 1, 1, "<", "", KeyType::Text, {}}, + {2, 1, 1, 1, ">", "", KeyType::Text, {}}, + {2, 2, 1, 1, "@", "", KeyType::Text, {}}, + {2, 3, 1, 1, "[", "", KeyType::Text, {}}, + {2, 4, 1, 1, "]", "", KeyType::Text, {}}, + {2, 5, 1, 1, "[]", "", KeyType::Text, {}}, + {2, 6, 1, 1, "{", "", KeyType::Text, {}}, + {2, 7, 1, 1, "}", "", KeyType::Text, {}}, + {2, 8, 1, 1, "{}", "", KeyType::Text, {}}, + {2, 9, 1, 2, "→", "", KeyType::UnknownFunction, {}}, // Row 4 - {3, 0, 1, 1, "\\", "", KeyType::Text}, - {3, 1, 1, 1, "|", "", KeyType::Text}, - {3, 2, 1, 1, "^", "", KeyType::Text}, - {3, 3, 1, 1, "`", "", KeyType::Text}, - {3, 4, 1, 1, "$", "", KeyType::Text}, - {3, 5, 1, 1, "€", "", KeyType::Text}, - {3, 6, 1, 1, "´", "", KeyType::Text}, - {3, 7, 1, 1, "ˊ", "", KeyType::Text}, - {3, 8, 1, 1, "ˊ", "", KeyType::Text}, - //{3, 9, 1, 2, "→", "", KeyType::UnknownFunction}, // Next symbols page (SYM2) + {3, 0, 1, 1, "\\", "", KeyType::Text, {}}, + {3, 1, 1, 1, "|", "", KeyType::Text, {}}, + {3, 2, 1, 1, "^", "", KeyType::Text, {}}, + {3, 3, 1, 1, "`", "", KeyType::Text, {}}, + {3, 4, 1, 1, "$", "", KeyType::Text, {}}, + {3, 5, 1, 1, "€", "", KeyType::Text, {}}, + {3, 6, 1, 1, "´", "", KeyType::Text, {}}, + {3, 7, 1, 1, "ˊ", "", KeyType::Text, {}}, + {3, 8, 1, 1, "ˊ", "", KeyType::Text, {}}, + //{3, 9, 1, 2, "→", "", KeyType::UnknownFunction,{}}, // Row 5 - {4, 0, 1, 1, "", "", KeyType::Disabled}, - {4, 1, 1, 1, "ABC", "L2+△", KeyType::TextLayout}, - {4, 2, 1, 1, "", "", KeyType::Disabled}, - {4, 3, 4, 1, "Space", "△", KeyType::Space}, - //{4, 4, 4, 1, "Space", "△", KeyType::Space}, - //{4, 5, 4, 1, "Space", "△", KeyType::Space}, - //{4, 6, 4, 1, "Space", "△", KeyType::Space}, - {4, 7, 1, 1, "", "", KeyType::Disabled}, - {4, 8, 2, 1, "⇦", "□", KeyType::Backspace}, //{4, 8, 2, 1, "⌫", "□", KeyType::Backspace}, - //{4, 9, 2, 1, "⌫", "□", KeyType::Backspace}, + {4, 0, 1, 1, "", "", KeyType::Disabled, {}}, + {4, 1, 1, 1, "ABC", "L2+△", KeyType::TextLayout, {L2, Triangle}}, + {4, 2, 1, 1, "", "", KeyType::Disabled, {}}, + {4, 3, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, + //{4, 4, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, + //{4, 5, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, + //{4, 6, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, + {4, 7, 1, 1, "", "", KeyType::Disabled, {}}, + {4, 8, 2, 1, "⇦", "□", KeyType::Backspace, {Square}}, + //{4, 9, 2, 1, "⇦", "□", KeyType::Backspace, {Square}}, // Row 6 - {5, 0, 1, 1, "▲", "", KeyType::CursorUp}, - {5, 1, 1, 1, "▼", "", KeyType::CursorDown}, - {5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft}, - {5, 3, 1, 1, "▶", "R1", KeyType::CursorRight}, - {5, 4, 1, 1, "KB", "", - KeyType::ToggleKeyboard}, //{5, 4, 1, 1, "⌨", "", KeyType::ToggleKeyboard}, - {5, 5, 1, 1, "...", "", KeyType::MoreOptions}, //{5, 5, 1, 1, "…", "", KeyType::MoreOptions}, - {5, 6, 1, 1, "+/⊗", "R3", KeyType::ControllerAction}, - {5, 7, 1, 1, "", "", KeyType::Disabled}, - {5, 8, 2, 1, "Done", "R2", KeyType::Done}, - //{5, 9, 2, 1, "Done", "R2", KeyType::Done}, + {5, 0, 1, 1, "▲", "", KeyType::CursorUp, {Up}}, + {5, 1, 1, 1, "▼", "", KeyType::CursorDown, {Down}}, + {5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft, {L1}}, + {5, 3, 1, 1, "▶", "R1", KeyType::CursorRight, {R1}}, + {5, 4, 1, 1, "KB", "", KeyType::ToggleKeyboard, {}}, + {5, 5, 1, 1, "...", "", KeyType::MoreOptions, {}}, + {5, 6, 1, 1, "+/⊗", "R3", KeyType::ControllerAction, {R3}}, + {5, 7, 1, 1, "", "", KeyType::Disabled, {}}, + {5, 8, 2, 1, "Done", "R2", KeyType::Done, {R2}}, + //{5, 9, 2, 1, "Done", "R2", KeyType::Done, {R2}}, + }; diff --git a/src/core/libraries/ime/ime_keyboard_layouts.h b/src/core/libraries/ime/ime_keyboard_layouts.h index ebadfdb80..2a0f4819b 100644 --- a/src/core/libraries/ime/ime_keyboard_layouts.h +++ b/src/core/libraries/ime/ime_keyboard_layouts.h @@ -5,6 +5,8 @@ #include #include +#include "core/libraries/pad/pad.h" +// using B = Libraries::Pad::OrbisPadButtonDataOffset; enum class KeyType { Text, // Inserts character(s) into input buffer @@ -34,6 +36,7 @@ struct Key { std::string label; std::string controller_hint; KeyType type = KeyType::Text; // default to Text input + std::vector bound_buttons = {}; // new field }; extern const std::vector kUppercaseLayout; diff --git a/src/core/libraries/ime/ime_keyboard_ui.cpp b/src/core/libraries/ime/ime_keyboard_ui.cpp index 6322eb2f7..7fe56d39a 100644 --- a/src/core/libraries/ime/ime_keyboard_ui.cpp +++ b/src/core/libraries/ime/ime_keyboard_ui.cpp @@ -5,6 +5,9 @@ #include #include "ime_keyboard_layouts.h" #include "ime_keyboard_ui.h" +#include "input/controller.h" + +#include "common/singleton.h" using namespace ImGui; @@ -18,13 +21,17 @@ void DrawVirtualKeyboard(char* buffer, std::size_t buffer_capacity, bool* input_ layout = shift_enabled ? &kUppercaseLayout : &kLowercaseLayout; } + auto current_pad_button = + Common::Singleton::Instance()->GetLastState().buttonsState; + RenderKeyboardLayout(*layout, buffer, buffer_capacity, input_changed, kb_mode, shift_enabled, - done_pressed); + done_pressed, current_pad_button); } void RenderKeyboardLayout(const std::vector& layout, char* buffer, std::size_t buffer_capacity, bool* input_changed, KeyboardMode& kb_mode, bool& shift_enabled, - bool* done_pressed) { + bool* done_pressed, + Libraries::Pad::OrbisPadButtonDataOffset current_pad_button) { // Define desired total layout size (in pixels) const float layout_width = 485.0f; const float layout_height = 200.0f; @@ -70,6 +77,72 @@ void RenderKeyboardLayout(const std::vector& layout, char* buffer, std::siz if (input_changed) *input_changed = true; } + // Controller debug injection + for (Libraries::Pad::OrbisPadButtonDataOffset button : key.bound_buttons) { + if (current_pad_button == button) { + // DEBUG: always insert "ok" when a key is triggered via gamepad + size_t len = std::strlen(buffer); + if (len + 2 < buffer_capacity) { + std::strcat(buffer, "ok"); + if (input_changed) + *input_changed = true; + } + } + } + + // Controller press simulation + for (Libraries::Pad::OrbisPadButtonDataOffset button : key.bound_buttons) { + if (current_pad_button == button) { + switch (key.type) { + case KeyType::Text: + if (!key.label.empty()) { + size_t len = std::strlen(buffer); + if (len + key.label.size() < buffer_capacity) { + std::strcat(buffer, key.label.c_str()); + if (input_changed) + *input_changed = true; + } + } + break; + case KeyType::Backspace: + if (buffer[0] != '\0') { + size_t len = std::strlen(buffer); + buffer[len - 1] = '\0'; + if (input_changed) + *input_changed = true; + } + break; + case KeyType::Space: + if (std::strlen(buffer) + 1 < buffer_capacity) { + std::strcat(buffer, " "); + if (input_changed) + *input_changed = true; + } + break; + case KeyType::Enter: + case KeyType::Done: + if (done_pressed) + *done_pressed = true; + break; + case KeyType::Shift: + shift_enabled = !shift_enabled; + break; + case KeyType::SymbolsLayout: + kb_mode = KeyboardMode::Symbols; + break; + case KeyType::TextLayout: + kb_mode = KeyboardMode::Letters; + break; + case KeyType::ToggleKeyboard: + kb_mode = (kb_mode == KeyboardMode::Letters) + ? KeyboardMode::Symbols + : KeyboardMode::Letters; + break; + default: + break; + } + } + } } break; case KeyType::Backspace: @@ -131,4 +204,4 @@ void RenderKeyboardLayout(const std::vector& layout, char* buffer, std::siz key.controller_hint.c_str()); } } -} +} \ No newline at end of file diff --git a/src/core/libraries/ime/ime_keyboard_ui.h b/src/core/libraries/ime/ime_keyboard_ui.h index 19be74a9d..73220646e 100644 --- a/src/core/libraries/ime/ime_keyboard_ui.h +++ b/src/core/libraries/ime/ime_keyboard_ui.h @@ -3,21 +3,17 @@ #pragma once -#include "common/cstring.h" -#include "common/types.h" -#include "core/libraries/ime/ime_dialog.h" -#include "core/libraries/ime/ime_keyboard_layouts.h" +#include +#include +#include +#include "ime_keyboard_layouts.h" enum class KeyboardMode { Letters, Symbols }; -// Renders the virtual keyboard and modifies buffer if a key is pressed. -// Flags: -// - `input_changed`: set to true if the text buffer changes -// - `done_pressed`: set to true if the Done/Enter key was pressed void DrawVirtualKeyboard(char* buffer, std::size_t buffer_capacity, bool* input_changed, KeyboardMode& kb_mode, bool& shift_enabled, bool* done_pressed); -// Renders a specific keyboard layout and processes key events. void RenderKeyboardLayout(const std::vector& layout, char* buffer, std::size_t buffer_capacity, bool* input_changed, KeyboardMode& kb_mode, bool& shift_enabled, - bool* done_pressed); + bool* done_pressed, + Libraries::Pad::OrbisPadButtonDataOffset current_pad_button); From 3b662681cbee0448455bc290c4c18fd88e84e7d2 Mon Sep 17 00:00:00 2001 From: w1naenator Date: Wed, 2 Apr 2025 17:56:35 +0300 Subject: [PATCH 10/20] Build: Recovered CMakeSettings.json configuration file Input Handling: Temporarily removed custom keyboard shortcut code; navigation is now handled via ImGui's native navigation system Virtual Keyboard: Modified first symbols layout (based on PS5 layout) Added second symbols layout (based on PS5 layout) Fonts: Added required symbols to ImGui font atlas for correct rendering in keyboard layouts --- CMakeSettings.json | 2 +- src/core/libraries/ime/ime_dialog_ui.cpp | 2 +- .../libraries/ime/ime_keyboard_layouts.cpp | 201 +++++++++++++++--- src/core/libraries/ime/ime_keyboard_layouts.h | 11 +- src/core/libraries/ime/ime_keyboard_ui.cpp | 131 ++++-------- src/core/libraries/ime/ime_keyboard_ui.h | 11 +- src/core/libraries/ime/ime_ui.cpp | 28 ++- src/imgui/renderer/imgui_core.cpp | 63 +++--- 8 files changed, 293 insertions(+), 156 deletions(-) diff --git a/CMakeSettings.json b/CMakeSettings.json index 1e9e3594c..bb522fcfc 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -6,7 +6,7 @@ "configurationType": "Release", "buildRoot": "${projectDir}\\Build\\${name}", "installRoot": "${projectDir}\\Install\\${name}", - "cmakeCommandArgs": "-DENABLE_QT_GUI=ON -DCMAKE_PREFIX_PATH=C:\\Qt\\6.8.2\\msvc2022_64", + "cmakeCommandArgs": "", "buildCommandArgs": "", "ctestCommandArgs": "", "inheritEnvironments": [ "clang_cl_x64_x64" ], diff --git a/src/core/libraries/ime/ime_dialog_ui.cpp b/src/core/libraries/ime/ime_dialog_ui.cpp index 3c576059d..e34fd064e 100644 --- a/src/core/libraries/ime/ime_dialog_ui.cpp +++ b/src/core/libraries/ime/ime_dialog_ui.cpp @@ -342,7 +342,7 @@ void ImeDialogUi::DrawMultiLineInputText() { } void ImeDialogUi::DrawKeyboard() { - static KeyboardMode kb_mode = KeyboardMode::Letters; + static KeyboardMode kb_mode = KeyboardMode::Letters1; static bool shift_enabled = false; static bool has_logged = false; diff --git a/src/core/libraries/ime/ime_keyboard_layouts.cpp b/src/core/libraries/ime/ime_keyboard_layouts.cpp index e81bfb209..87ea2931a 100644 --- a/src/core/libraries/ime/ime_keyboard_layouts.cpp +++ b/src/core/libraries/ime/ime_keyboard_layouts.cpp @@ -1,25 +1,24 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "core/libraries/pad/pad.h" +#include #include "ime_keyboard_layouts.h" -using B = Libraries::Pad::OrbisPadButtonDataOffset; -constexpr auto L1 = B::L1; -constexpr auto R1 = B::R1; -constexpr auto L2 = B::L2; -constexpr auto R2 = B::R2; -constexpr auto L3 = B::L3; -constexpr auto R3 = B::R3; -constexpr auto Up = B::Up; -constexpr auto Down = B::Down; -constexpr auto Left = B::Left; -constexpr auto Right = B::Right; -constexpr auto Cross = B::Cross; -constexpr auto Circle = B::Circle; -constexpr auto Square = B::Square; -constexpr auto Triangle = B::Triangle; -constexpr auto TouchPad = B::TouchPad; +constexpr auto L1 = ImGuiNavInput_FocusPrev; +constexpr auto R1 = ImGuiNavInput_FocusNext; +constexpr auto L2 = ImGuiNavInput_TweakSlow; +constexpr auto R2 = ImGuiNavInput_TweakFast; +constexpr auto L3 = ImGuiNavInput_DpadLeft; // adjust if needed +constexpr auto R3 = ImGuiNavInput_DpadRight; // adjust if needed +constexpr auto Up = ImGuiNavInput_DpadUp; +constexpr auto Down = ImGuiNavInput_DpadDown; +constexpr auto Left = ImGuiNavInput_DpadLeft; +constexpr auto Right = ImGuiNavInput_DpadRight; +constexpr auto Cross = ImGuiNavInput_Activate; +constexpr auto Circle = ImGuiNavInput_Menu; +constexpr auto Square = ImGuiNavInput_Cancel; +constexpr auto Triangle = ImGuiNavInput_Input; +constexpr auto TouchPad = ImGuiNavInput_Menu; // reuse if needed const std::vector kUppercaseLayout = { // Row 1 @@ -73,15 +72,15 @@ const std::vector kUppercaseLayout = { // Row 5 {4, 0, 1, 1, "⬆", "L2", KeyType::Shift, {L2}}, - {4, 1, 1, 1, "@#:", "L2+△", KeyType::SymbolsLayout, {L3, Triangle}}, + {4, 1, 1, 1, "@#:", "L2+△", KeyType::Symbols1Layout, {L3, Triangle}}, {4, 2, 1, 1, "à", "L3", KeyType::UnknownFunction, {L3}}, {4, 3, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, - //{4, 4, 4, 1, "Space", "△", KeyType::Space,{}}, - //{4, 5, 4, 1, "Space", "△", KeyType::Space,{}}, - //{4, 6, 4, 1, "Space", "△", KeyType::Space,{}}, + //{4, 4, 4, 1, "Space", "△", KeyType::Space,{Triangle}}, + //{4, 5, 4, 1, "Space", "△", KeyType::Space,{Triangle}}, + //{4, 6, 4, 1, "Space", "△", KeyType::Space,{Triangle}}, {4, 7, 1, 1, "", "", KeyType::Disabled, {}}, {4, 8, 2, 1, "⇦", "□", KeyType::Backspace, {Square}}, - //{4, 9, 2, 1, "⇦", "□", KeyType::Backspace,{}}, + //{4, 9, 2, 1, "⇦", "□", KeyType::Backspace,{Square}}, // Row 6 {5, 0, 1, 1, "▲", "", KeyType::CursorUp, {Up}}, @@ -95,7 +94,7 @@ const std::vector kUppercaseLayout = { {5, 6, 1, 1, "+/⊗", "R3", KeyType::ControllerAction, {R3}}, {5, 7, 1, 1, "", "", KeyType::Disabled, {}}, {5, 8, 2, 1, "Done", "R2", KeyType::Done, {R2}}, - //{5, 9, 2, 1, "Done", "R2", KeyType::Done,{}}, + //{5, 9, 2, 1, "Done", "R2", KeyType::Done,{R2}}, }; const std::vector kLowercaseLayout = { @@ -149,7 +148,7 @@ const std::vector kLowercaseLayout = { // Row 5 {4, 0, 1, 1, "⇧", "L2", KeyType::Shift, {L2}}, - {4, 1, 1, 1, "@#:", "L2+△", KeyType::SymbolsLayout, {L2, Triangle}}, + {4, 1, 1, 1, "@#:", "L2+△", KeyType::Symbols1Layout, {L2, Triangle}}, {4, 2, 1, 1, "à", "L3", KeyType::UnknownFunction, {L3}}, {4, 3, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, //{4, 4, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, @@ -171,7 +170,7 @@ const std::vector kLowercaseLayout = { {5, 8, 2, 1, "Done", "R2", KeyType::Done, {R2}}, //{5, 9, 2, 1, "Done", "R2", KeyType::Done, {R2}}, }; - +/* const std::vector kSymbols1Layout = { // Row 1 {0, 0, 1, 1, "!", "", KeyType::Text, {}}, @@ -246,3 +245,155 @@ const std::vector kSymbols1Layout = { //{5, 9, 2, 1, "Done", "R2", KeyType::Done, {R2}}, }; +*/ +// From PS5 +const std::vector kSymbols1Layout = { + // Row 1 + {0, 0, 1, 1, "!", "", KeyType::Text, {}}, + {0, 1, 1, 1, "?", "", KeyType::Text, {}}, + {0, 2, 1, 1, "\"", "", KeyType::Text, {}}, + {0, 3, 1, 1, "'", "", KeyType::Text, {}}, + {0, 4, 1, 1, "#", "", KeyType::Text, {}}, + {0, 5, 1, 1, "%", "", KeyType::Text, {}}, + {0, 6, 1, 1, "(", "", KeyType::Text, {}}, + {0, 7, 1, 1, ")", "", KeyType::Text, {}}, + {0, 8, 1, 1, "()", "", KeyType::Text, {}}, + {0, 9, 1, 1, "/", "", KeyType::Text, {}}, + + // Row 2 + {1, 0, 1, 1, "-", "", KeyType::Text, {}}, + {1, 1, 1, 1, "_", "", KeyType::Text, {}}, + {1, 2, 1, 1, ",", "", KeyType::Text, {}}, + {1, 3, 1, 1, ".", "", KeyType::Text, {}}, + {1, 4, 1, 1, ":", "", KeyType::Text, {}}, + {1, 5, 1, 1, ";", "", KeyType::Text, {}}, + {1, 6, 1, 1, "*", "", KeyType::Text, {}}, + {1, 7, 1, 1, "&", "", KeyType::Text, {}}, + {1, 8, 1, 1, "+", "", KeyType::Text, {}}, + {1, 9, 1, 1, "=", "", KeyType::Text, {}}, + + // Row 3 + {2, 0, 1, 1, "<", "", KeyType::Text, {}}, + {2, 1, 1, 1, ">", "", KeyType::Text, {}}, + {2, 2, 1, 1, "@", "", KeyType::Text, {}}, + {2, 3, 1, 1, "[", "", KeyType::Text, {}}, + {2, 4, 1, 1, "]", "", KeyType::Text, {}}, + {2, 5, 1, 1, "[]", "", KeyType::Text, {}}, + {2, 6, 1, 1, "{", "", KeyType::Text, {}}, + {2, 7, 1, 1, "}", "", KeyType::Text, {}}, + {2, 8, 1, 1, "{}", "", KeyType::Text, {}}, + {2, 9, 1, 2, "→", "", KeyType::Symbols2Layout, {}}, + + // Row 4 + {3, 0, 1, 1, "\\", "", KeyType::Text, {}}, + {3, 1, 1, 1, "|", "", KeyType::Text, {}}, + {3, 2, 1, 1, "^", "", KeyType::Text, {}}, + {3, 3, 1, 1, "`", "", KeyType::Text, {}}, + {3, 4, 1, 1, "$", "", KeyType::Text, {}}, + {3, 5, 1, 1, "€", "", KeyType::Text, {}}, + {3, 6, 1, 1, "£", "", KeyType::Text, {}}, + {3, 7, 1, 1, "¥", "", KeyType::Text, {}}, + {3, 8, 1, 1, "₩", "", KeyType::Text, {}}, + //{3, 9, 1, 2, "→", "", KeyType::Symbols2Layout,{}}, + + // Row 5 + {4, 0, 1, 1, "", "", KeyType::Disabled, {}}, + {4, 1, 1, 1, "ABC", "L2+△", KeyType::TextLayout, {L2, Triangle}}, + {4, 2, 1, 1, "", "", KeyType::Disabled, {}}, + {4, 3, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, + //{4, 4, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, + //{4, 5, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, + //{4, 6, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, + {4, 7, 1, 1, "", "", KeyType::Disabled, {}}, + {4, 8, 2, 1, "⇦", "□", KeyType::Backspace, {Square}}, + //{4, 9, 2, 1, "⇦", "□", KeyType::Backspace, {Square}}, + + // Row 6 + {5, 0, 1, 1, "▲", "", KeyType::CursorUp, {Up}}, + {5, 1, 1, 1, "▼", "", KeyType::CursorDown, {Down}}, + {5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft, {L1}}, + {5, 3, 1, 1, "▶", "R1", KeyType::CursorRight, {R1}}, + {5, 4, 1, 1, "KB", "", KeyType::ToggleKeyboard, {}}, + {5, 5, 1, 1, "...", "", KeyType::MoreOptions, {}}, + {5, 6, 1, 1, "+/⊗", "R3", KeyType::ControllerAction, {R3}}, + {5, 7, 1, 1, "", "", KeyType::Disabled, {}}, + {5, 8, 2, 1, "Done", "R2", KeyType::Done, {R2}}, + //{5, 9, 2, 1, "Done", "R2", KeyType::Done, {R2}}, + +}; + +// From PS5 +const std::vector kSymbols2Layout = { + // Row 1 + {0, 0, 1, 1, "“", "", KeyType::Text, {}}, + {0, 1, 1, 1, "”", "", KeyType::Text, {}}, + {0, 2, 1, 1, "„", "", KeyType::Text, {}}, + {0, 3, 1, 1, "¡", "", KeyType::Text, {}}, + {0, 4, 1, 1, "‼", "", KeyType::Text, {}}, + {0, 5, 1, 1, "¿", "", KeyType::Text, {}}, + {0, 6, 1, 1, "⁇", "", KeyType::Text, {}}, + {0, 7, 1, 1, "~", "", KeyType::Text, {}}, + {0, 8, 1, 1, "·", "", KeyType::Text, {}}, + {0, 9, 1, 1, "", "", KeyType::Disabled, {}}, + + // Row 2 + {1, 0, 1, 1, "×", "", KeyType::Text, {}}, + {1, 1, 1, 1, "÷", "", KeyType::Text, {}}, + {1, 2, 1, 1, "‹", "", KeyType::Text, {}}, + {1, 3, 1, 1, "›", "", KeyType::Text, {}}, + {1, 4, 1, 1, "«", "", KeyType::Text, {}}, + {1, 5, 1, 1, "»", "", KeyType::Text, {}}, + {1, 6, 1, 1, "º", "", KeyType::Text, {}}, + {1, 7, 1, 1, "ª", "", KeyType::Text, {}}, + {1, 8, 1, 1, "°", "", KeyType::Text, {}}, + {1, 9, 1, 1, "§", "", KeyType::Text, {}}, + + // Row 3 + {2, 0, 1, 2, "←", "", KeyType::Symbols1Layout, {}}, + {2, 1, 1, 1, "¦", "", KeyType::Text, {}}, + {2, 2, 1, 1, "µ", "", KeyType::Text, {}}, + {2, 3, 1, 1, "¬", "", KeyType::Text, {}}, + {2, 4, 1, 1, "¹", "", KeyType::Text, {}}, + {2, 5, 1, 1, "²", "", KeyType::Text, {}}, + {2, 6, 1, 1, "³", "", KeyType::Text, {}}, + {2, 7, 1, 1, "¼", "", KeyType::Text, {}}, + {2, 8, 1, 1, "½", "", KeyType::Text, {}}, + {2, 9, 1, 1, "¾", "", KeyType::Text, {}}, + + // Row 4 + //{3, 0, 1, 1, "←", "", KeyType::Symbols1Layout, {}}, + {3, 1, 1, 1, "¢", "", KeyType::Text, {}}, + {3, 2, 1, 1, "¤", "", KeyType::Text, {}}, + {3, 3, 1, 1, "’", "", KeyType::Text, {}},//not sure + {3, 4, 1, 1, "‘", "", KeyType::Text, {}},//not sure + {3, 5, 1, 1, "‛", "", KeyType::Text, {}},//not sure + {3, 6, 1, 1, "‚", "", KeyType::Text, {}},//not sure + {3, 7, 1, 1, "№", "", KeyType::Text, {}}, + {3, 8, 1, 1, "", "", KeyType::Disabled, {}}, + {3, 9, 1, 1, "", "", KeyType::Disabled,{}}, + + // Row 5 + {4, 0, 1, 1, "", "", KeyType::Disabled, {}}, + {4, 1, 1, 1, "ABC", "L2+△", KeyType::TextLayout, {L2, Triangle}}, + {4, 2, 1, 1, "", "", KeyType::Disabled, {}}, + {4, 3, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, + //{4, 4, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, + //{4, 5, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, + //{4, 6, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, + {4, 7, 1, 1, "", "", KeyType::Disabled, {}}, + {4, 8, 2, 1, "⇦", "□", KeyType::Backspace, {Square}}, + //{4, 9, 2, 1, "⇦", "□", KeyType::Backspace, {Square}}, + + // Row 6 + {5, 0, 1, 1, "▲", "", KeyType::CursorUp, {Up}}, + {5, 1, 1, 1, "▼", "", KeyType::CursorDown, {Down}}, + {5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft, {L1}}, + {5, 3, 1, 1, "▶", "R1", KeyType::CursorRight, {R1}}, + {5, 4, 1, 1, "KB", "", KeyType::ToggleKeyboard, {}}, + {5, 5, 1, 1, "...", "", KeyType::MoreOptions, {}}, + {5, 6, 1, 1, "+/⊗", "R3", KeyType::ControllerAction, {R3}}, + {5, 7, 1, 1, "", "", KeyType::Disabled, {}}, + {5, 8, 2, 1, "Done", "R2", KeyType::Done, {R2}}, + //{5, 9, 2, 1, "Done", "R2", KeyType::Done, {R2}}, + +}; \ No newline at end of file diff --git a/src/core/libraries/ime/ime_keyboard_layouts.h b/src/core/libraries/ime/ime_keyboard_layouts.h index 2a0f4819b..3da681219 100644 --- a/src/core/libraries/ime/ime_keyboard_layouts.h +++ b/src/core/libraries/ime/ime_keyboard_layouts.h @@ -5,8 +5,7 @@ #include #include -#include "core/libraries/pad/pad.h" -// using B = Libraries::Pad::OrbisPadButtonDataOffset; +#include enum class KeyType { Text, // Inserts character(s) into input buffer @@ -14,7 +13,8 @@ enum class KeyType { Space, // Adds space Enter, // Submits input Shift, // Toggle uppercase/lowercase - SymbolsLayout, // Switch to symbols layout + Symbols1Layout, // Switch to symbols layout + Symbols2Layout, // Switch to symbols layout TextLayout, // Switch to text layout Done, // Finish and close keyboard CursorLeft, @@ -35,10 +35,11 @@ struct Key { int rowspan = 1; std::string label; std::string controller_hint; - KeyType type = KeyType::Text; // default to Text input - std::vector bound_buttons = {}; // new field + KeyType type = KeyType::Text; + std::vector bound_buttons = {}; // Now using ImGui navigation inputs }; extern const std::vector kUppercaseLayout; extern const std::vector kLowercaseLayout; extern const std::vector kSymbols1Layout; +extern const std::vector kSymbols2Layout; diff --git a/src/core/libraries/ime/ime_keyboard_ui.cpp b/src/core/libraries/ime/ime_keyboard_ui.cpp index 7fe56d39a..08185c6ed 100644 --- a/src/core/libraries/ime/ime_keyboard_ui.cpp +++ b/src/core/libraries/ime/ime_keyboard_ui.cpp @@ -5,40 +5,55 @@ #include #include "ime_keyboard_layouts.h" #include "ime_keyboard_ui.h" -#include "input/controller.h" - -#include "common/singleton.h" +#include "ime_ui.h" // for ImeState +#include "ime_common.h" using namespace ImGui; +// --- UTF-8 safe backspace helper --- +void Utf8SafeBackspace(char* buffer) { + size_t len = std::strlen(buffer); + if (len == 0) + return; + + while (len > 0 && (static_cast(buffer[len]) & 0b11000000) == 0b10000000) { + --len; + } + + if (len > 0) { + buffer[len - 1] = '\0'; + buffer[len] = '\0'; + } +} + void DrawVirtualKeyboard(char* buffer, std::size_t buffer_capacity, bool* input_changed, KeyboardMode& kb_mode, bool& shift_enabled, bool* done_pressed) { const std::vector* layout = nullptr; - if (kb_mode == KeyboardMode::Symbols) { + switch (kb_mode) { + case KeyboardMode::Symbols1: layout = &kSymbols1Layout; - } else { + break; + case KeyboardMode::Symbols2: + layout = &kSymbols2Layout; + break; + default: layout = shift_enabled ? &kUppercaseLayout : &kLowercaseLayout; + break; } - auto current_pad_button = - Common::Singleton::Instance()->GetLastState().buttonsState; - RenderKeyboardLayout(*layout, buffer, buffer_capacity, input_changed, kb_mode, shift_enabled, - done_pressed, current_pad_button); + done_pressed); } void RenderKeyboardLayout(const std::vector& layout, char* buffer, std::size_t buffer_capacity, bool* input_changed, KeyboardMode& kb_mode, bool& shift_enabled, - bool* done_pressed, - Libraries::Pad::OrbisPadButtonDataOffset current_pad_button) { - // Define desired total layout size (in pixels) + bool* done_pressed) { const float layout_width = 485.0f; const float layout_height = 200.0f; const float cell_spacing = 4.0f; const float hint_padding = 2.0f; - // Find max rows and columns int max_col = 0; int max_row = 0; for (const Key& key : layout) { @@ -46,7 +61,6 @@ void RenderKeyboardLayout(const std::vector& layout, char* buffer, std::siz max_row = std::max(max_row, key.row + static_cast(key.rowspan)); } - // Calculate cell size dynamically const float cell_width = (layout_width - (max_col - 1) * cell_spacing) / max_col; const float cell_height = (layout_height - (max_row - 1) * cell_spacing) / max_row; @@ -66,8 +80,9 @@ void RenderKeyboardLayout(const std::vector& layout, char* buffer, std::siz : key.label; ImGui::SetCursorScreenPos(pos); + bool key_activated = ImGui::Button(button_id.c_str(), size); - if (ImGui::Button(button_id.c_str(), size)) { + if (key_activated) { switch (key.type) { case KeyType::Text: if (!key.label.empty()) { @@ -77,78 +92,11 @@ void RenderKeyboardLayout(const std::vector& layout, char* buffer, std::siz if (input_changed) *input_changed = true; } - // Controller debug injection - for (Libraries::Pad::OrbisPadButtonDataOffset button : key.bound_buttons) { - if (current_pad_button == button) { - // DEBUG: always insert "ok" when a key is triggered via gamepad - size_t len = std::strlen(buffer); - if (len + 2 < buffer_capacity) { - std::strcat(buffer, "ok"); - if (input_changed) - *input_changed = true; - } - } - } - - // Controller press simulation - for (Libraries::Pad::OrbisPadButtonDataOffset button : key.bound_buttons) { - if (current_pad_button == button) { - switch (key.type) { - case KeyType::Text: - if (!key.label.empty()) { - size_t len = std::strlen(buffer); - if (len + key.label.size() < buffer_capacity) { - std::strcat(buffer, key.label.c_str()); - if (input_changed) - *input_changed = true; - } - } - break; - case KeyType::Backspace: - if (buffer[0] != '\0') { - size_t len = std::strlen(buffer); - buffer[len - 1] = '\0'; - if (input_changed) - *input_changed = true; - } - break; - case KeyType::Space: - if (std::strlen(buffer) + 1 < buffer_capacity) { - std::strcat(buffer, " "); - if (input_changed) - *input_changed = true; - } - break; - case KeyType::Enter: - case KeyType::Done: - if (done_pressed) - *done_pressed = true; - break; - case KeyType::Shift: - shift_enabled = !shift_enabled; - break; - case KeyType::SymbolsLayout: - kb_mode = KeyboardMode::Symbols; - break; - case KeyType::TextLayout: - kb_mode = KeyboardMode::Letters; - break; - case KeyType::ToggleKeyboard: - kb_mode = (kb_mode == KeyboardMode::Letters) - ? KeyboardMode::Symbols - : KeyboardMode::Letters; - break; - default: - break; - } - } - } } break; case KeyType::Backspace: if (buffer[0] != '\0') { - size_t len = std::strlen(buffer); - buffer[len - 1] = '\0'; + Utf8SafeBackspace(buffer); if (input_changed) *input_changed = true; } @@ -168,22 +116,25 @@ void RenderKeyboardLayout(const std::vector& layout, char* buffer, std::siz case KeyType::Shift: shift_enabled = !shift_enabled; break; - case KeyType::SymbolsLayout: - kb_mode = KeyboardMode::Symbols; + case KeyType::Symbols1Layout: + kb_mode = KeyboardMode::Symbols1; + break; + case KeyType::Symbols2Layout: + kb_mode = KeyboardMode::Symbols2; break; case KeyType::TextLayout: - kb_mode = KeyboardMode::Letters; + kb_mode = KeyboardMode::Letters1; break; case KeyType::ToggleKeyboard: - kb_mode = (kb_mode == KeyboardMode::Letters) ? KeyboardMode::Symbols - : KeyboardMode::Letters; + kb_mode = (kb_mode == KeyboardMode::Letters1) ? KeyboardMode::Symbols1 + : KeyboardMode::Letters1; break; default: break; } } - // Controller hint + // Draw controller hint label if (!key.controller_hint.empty()) { float original_font_size = ImGui::GetFontSize(); float small_font_size = original_font_size * 0.5f; @@ -204,4 +155,4 @@ void RenderKeyboardLayout(const std::vector& layout, char* buffer, std::siz key.controller_hint.c_str()); } } -} \ No newline at end of file +} diff --git a/src/core/libraries/ime/ime_keyboard_ui.h b/src/core/libraries/ime/ime_keyboard_ui.h index 73220646e..bbe6f7852 100644 --- a/src/core/libraries/ime/ime_keyboard_ui.h +++ b/src/core/libraries/ime/ime_keyboard_ui.h @@ -6,14 +6,19 @@ #include #include #include +#include "core/libraries/pad/pad.h" #include "ime_keyboard_layouts.h" +#include "core/libraries/ime/ime.h" +#include "core/libraries/ime/ime_error.h" +#include "core/libraries/ime/ime_ui.h" +#include "core/libraries/ime/ime_common.h" -enum class KeyboardMode { Letters, Symbols }; +enum class KeyboardMode { Letters1, Letters2, Symbols1, Symbols2 }; void DrawVirtualKeyboard(char* buffer, std::size_t buffer_capacity, bool* input_changed, KeyboardMode& kb_mode, bool& shift_enabled, bool* done_pressed); + void RenderKeyboardLayout(const std::vector& layout, char* buffer, std::size_t buffer_capacity, bool* input_changed, KeyboardMode& kb_mode, bool& shift_enabled, - bool* done_pressed, - Libraries::Pad::OrbisPadButtonDataOffset current_pad_button); + bool* done_pressed); \ No newline at end of file diff --git a/src/core/libraries/ime/ime_ui.cpp b/src/core/libraries/ime/ime_ui.cpp index 0ba2dc433..a3b1e2e92 100644 --- a/src/core/libraries/ime/ime_ui.cpp +++ b/src/core/libraries/ime/ime_ui.cpp @@ -190,7 +190,7 @@ void ImeUi::DrawInputText() { } void ImeUi::DrawKeyboard() { - static KeyboardMode kb_mode = KeyboardMode::Letters; + static KeyboardMode kb_mode = KeyboardMode::Letters1; static bool shift_enabled = false; static bool has_logged = false; @@ -205,11 +205,35 @@ void ImeUi::DrawKeyboard() { DrawVirtualKeyboard(state->current_text.begin(), state->current_text.capacity(), &input_changed, kb_mode, shift_enabled, &done_pressed); + if (input_changed) { + OrbisImeEditText eventParam{}; + eventParam.str = reinterpret_cast(ime_param->work); + eventParam.caret_index = std::strlen(state->current_text.begin()); + eventParam.area_num = 1; + eventParam.text_area[0].mode = 1; + eventParam.text_area[0].index = 0; + eventParam.text_area[0].length = eventParam.caret_index; + + state->ConvertUTF8ToOrbis(state->current_text.begin(), eventParam.caret_index, + eventParam.str, ime_param->maxTextLength); + state->ConvertUTF8ToOrbis(state->current_text.begin(), eventParam.caret_index, + ime_param->inputTextBuffer, ime_param->maxTextLength); + + OrbisImeEvent event{}; + event.id = OrbisImeEventId::UpdateText; + event.param.text = eventParam; + state->SendEvent(&event); + } + if (done_pressed) { - state->SendEnterEvent(); // Submit action + state->SendEnterEvent(); } } + + + + int ImeUi::InputTextCallback(ImGuiInputTextCallbackData* data) { ImeUi* ui = static_cast(data->UserData); ASSERT(ui); diff --git a/src/imgui/renderer/imgui_core.cpp b/src/imgui/renderer/imgui_core.cpp index 5ce2686a7..9f2c961cc 100644 --- a/src/imgui/renderer/imgui_core.cpp +++ b/src/imgui/renderer/imgui_core.cpp @@ -69,37 +69,42 @@ void Initialize(const ::Vulkan::Instance& instance, const Frontend::WindowSDL& w rb.AddRanges(io.Fonts->GetGlyphRangesKorean()); rb.AddRanges(io.Fonts->GetGlyphRangesJapanese()); rb.AddRanges(io.Fonts->GetGlyphRangesCyrillic()); - rb.AddChar(0x00D7); // × Cross - rb.AddChar(0x25CB); // ○ Circle - rb.AddChar(0x25B3); // △ Triangle - rb.AddChar(0x25A1); // □ Square - rb.AddChar(0x2191); // ↑ Up Arrow - rb.AddChar(0x2193); // ↓ Down Arrow - rb.AddChar(0x2190); // ← Left Arrow - rb.AddChar(0x2192); // → Right Arrow - - rb.AddChar(0x2297); // ⊗ Circled Times (often used as cross) - rb.AddChar(0x2BBE); // ⮾ Circled X (if supported by font) - rb.AddChar(0x1F5D9); // 🗙 Cancellation X (heavy) - - rb.AddChar(0x25C0); // ◀ Black Left-Pointing Triangle - rb.AddChar(0x25B2); // ▲ Black Up-Pointing Triangle - rb.AddChar(0x25B6); // ▶ Black Right-Pointing Triangle - rb.AddChar(0x25BC); // ▼ Black Down-Pointing Triangle - - rb.AddChar(0x232B); // ⌫ Backspace - - rb.AddChar(0x21E7); // ⇧ UPWARDS WHITE ARROW - rb.AddChar(0x2B06); // ⬆ UPWARDS BLACK ARROW - - rb.AddChar(0x21E6); // ⇦ Leftwards White Arrow + //For keyboard + rb.AddChar(U'×'); + rb.AddChar(U'○'); + rb.AddChar(U'△'); + rb.AddChar(U'□'); + rb.AddChar(U'↑'); + rb.AddChar(U'↓'); + rb.AddChar(U'←'); + rb.AddChar(U'→'); + rb.AddChar(U'⊗'); + rb.AddChar(U'⮾'); + rb.AddChar(U'🗙'); + rb.AddChar(U'◀'); + rb.AddChar(U'▲'); + rb.AddChar(U'▶'); + rb.AddChar(U'▼'); + rb.AddChar(U'⇧'); + rb.AddChar(U'⬆'); + rb.AddChar(U'⇦'); + rb.AddChar(U'€'); + rb.AddChar(U'₩'); + rb.AddChar(U'“'); + rb.AddChar(U'”'); + rb.AddChar(U'„'); + rb.AddChar(U'‼'); + rb.AddChar(U'¿'); + rb.AddChar(U'⁇'); + rb.AddChar(U'‹'); + rb.AddChar(U'›'); + rb.AddChar(U'’'); + rb.AddChar(U'‘'); + rb.AddChar(U'‛'); + rb.AddChar(U'‚'); + rb.AddChar(U'№'); - //rb.AddRanges(io.Fonts->GetGlyphRangesDefault()); - // Manually add full BMP range - //for (ImWchar c = 0x0020; c <= 0xFFFF; ++c) { - // rb.AddChar(c); - //} ImVector ranges{}; rb.BuildRanges(&ranges); ImFontConfig font_cfg{}; From 2ac099264dd8c674c300cd78ec87ecdb18680d56 Mon Sep 17 00:00:00 2001 From: w1naenator Date: Wed, 2 Apr 2025 18:08:39 +0300 Subject: [PATCH 11/20] CLang fixes --- src/core/libraries/ime/ime_keyboard_layouts.cpp | 10 +++++----- src/core/libraries/ime/ime_keyboard_layouts.h | 14 +++++++------- src/core/libraries/ime/ime_keyboard_ui.cpp | 4 ++-- src/core/libraries/ime/ime_keyboard_ui.h | 7 +++---- src/core/libraries/ime/ime_ui.cpp | 4 ---- src/imgui/renderer/imgui_core.cpp | 3 +-- 6 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/core/libraries/ime/ime_keyboard_layouts.cpp b/src/core/libraries/ime/ime_keyboard_layouts.cpp index 87ea2931a..0247ea8a5 100644 --- a/src/core/libraries/ime/ime_keyboard_layouts.cpp +++ b/src/core/libraries/ime/ime_keyboard_layouts.cpp @@ -364,13 +364,13 @@ const std::vector kSymbols2Layout = { //{3, 0, 1, 1, "←", "", KeyType::Symbols1Layout, {}}, {3, 1, 1, 1, "¢", "", KeyType::Text, {}}, {3, 2, 1, 1, "¤", "", KeyType::Text, {}}, - {3, 3, 1, 1, "’", "", KeyType::Text, {}},//not sure - {3, 4, 1, 1, "‘", "", KeyType::Text, {}},//not sure - {3, 5, 1, 1, "‛", "", KeyType::Text, {}},//not sure - {3, 6, 1, 1, "‚", "", KeyType::Text, {}},//not sure + {3, 3, 1, 1, "’", "", KeyType::Text, {}}, // not sure + {3, 4, 1, 1, "‘", "", KeyType::Text, {}}, // not sure + {3, 5, 1, 1, "‛", "", KeyType::Text, {}}, // not sure + {3, 6, 1, 1, "‚", "", KeyType::Text, {}}, // not sure {3, 7, 1, 1, "№", "", KeyType::Text, {}}, {3, 8, 1, 1, "", "", KeyType::Disabled, {}}, - {3, 9, 1, 1, "", "", KeyType::Disabled,{}}, + {3, 9, 1, 1, "", "", KeyType::Disabled, {}}, // Row 5 {4, 0, 1, 1, "", "", KeyType::Disabled, {}}, diff --git a/src/core/libraries/ime/ime_keyboard_layouts.h b/src/core/libraries/ime/ime_keyboard_layouts.h index 3da681219..7d4e8d8f5 100644 --- a/src/core/libraries/ime/ime_keyboard_layouts.h +++ b/src/core/libraries/ime/ime_keyboard_layouts.h @@ -8,15 +8,15 @@ #include enum class KeyType { - Text, // Inserts character(s) into input buffer - Backspace, // Deletes last character - Space, // Adds space - Enter, // Submits input - Shift, // Toggle uppercase/lowercase + Text, // Inserts character(s) into input buffer + Backspace, // Deletes last character + Space, // Adds space + Enter, // Submits input + Shift, // Toggle uppercase/lowercase Symbols1Layout, // Switch to symbols layout Symbols2Layout, // Switch to symbols layout - TextLayout, // Switch to text layout - Done, // Finish and close keyboard + TextLayout, // Switch to text layout + Done, // Finish and close keyboard CursorLeft, CursorRight, CursorUp, diff --git a/src/core/libraries/ime/ime_keyboard_ui.cpp b/src/core/libraries/ime/ime_keyboard_ui.cpp index 08185c6ed..066bedc4e 100644 --- a/src/core/libraries/ime/ime_keyboard_ui.cpp +++ b/src/core/libraries/ime/ime_keyboard_ui.cpp @@ -3,10 +3,10 @@ #include #include +#include "ime_common.h" #include "ime_keyboard_layouts.h" #include "ime_keyboard_ui.h" #include "ime_ui.h" // for ImeState -#include "ime_common.h" using namespace ImGui; @@ -127,7 +127,7 @@ void RenderKeyboardLayout(const std::vector& layout, char* buffer, std::siz break; case KeyType::ToggleKeyboard: kb_mode = (kb_mode == KeyboardMode::Letters1) ? KeyboardMode::Symbols1 - : KeyboardMode::Letters1; + : KeyboardMode::Letters1; break; default: break; diff --git a/src/core/libraries/ime/ime_keyboard_ui.h b/src/core/libraries/ime/ime_keyboard_ui.h index bbe6f7852..8b4f4af3e 100644 --- a/src/core/libraries/ime/ime_keyboard_ui.h +++ b/src/core/libraries/ime/ime_keyboard_ui.h @@ -6,19 +6,18 @@ #include #include #include -#include "core/libraries/pad/pad.h" -#include "ime_keyboard_layouts.h" #include "core/libraries/ime/ime.h" +#include "core/libraries/ime/ime_common.h" #include "core/libraries/ime/ime_error.h" #include "core/libraries/ime/ime_ui.h" -#include "core/libraries/ime/ime_common.h" +#include "core/libraries/pad/pad.h" +#include "ime_keyboard_layouts.h" enum class KeyboardMode { Letters1, Letters2, Symbols1, Symbols2 }; void DrawVirtualKeyboard(char* buffer, std::size_t buffer_capacity, bool* input_changed, KeyboardMode& kb_mode, bool& shift_enabled, bool* done_pressed); - void RenderKeyboardLayout(const std::vector& layout, char* buffer, std::size_t buffer_capacity, bool* input_changed, KeyboardMode& kb_mode, bool& shift_enabled, bool* done_pressed); \ No newline at end of file diff --git a/src/core/libraries/ime/ime_ui.cpp b/src/core/libraries/ime/ime_ui.cpp index a3b1e2e92..918abe191 100644 --- a/src/core/libraries/ime/ime_ui.cpp +++ b/src/core/libraries/ime/ime_ui.cpp @@ -230,10 +230,6 @@ void ImeUi::DrawKeyboard() { } } - - - - int ImeUi::InputTextCallback(ImGuiInputTextCallbackData* data) { ImeUi* ui = static_cast(data->UserData); ASSERT(ui); diff --git a/src/imgui/renderer/imgui_core.cpp b/src/imgui/renderer/imgui_core.cpp index 9f2c961cc..28fdc618d 100644 --- a/src/imgui/renderer/imgui_core.cpp +++ b/src/imgui/renderer/imgui_core.cpp @@ -69,7 +69,7 @@ void Initialize(const ::Vulkan::Instance& instance, const Frontend::WindowSDL& w rb.AddRanges(io.Fonts->GetGlyphRangesKorean()); rb.AddRanges(io.Fonts->GetGlyphRangesJapanese()); rb.AddRanges(io.Fonts->GetGlyphRangesCyrillic()); - //For keyboard + // For keyboard rb.AddChar(U'×'); rb.AddChar(U'○'); rb.AddChar(U'△'); @@ -104,7 +104,6 @@ void Initialize(const ::Vulkan::Instance& instance, const Frontend::WindowSDL& w rb.AddChar(U'‚'); rb.AddChar(U'№'); - ImVector ranges{}; rb.BuildRanges(&ranges); ImFontConfig font_cfg{}; From 22145d2b0ac5a4e27225aea40a390df3c9e30529 Mon Sep 17 00:00:00 2001 From: w1naenator Date: Thu, 3 Apr 2025 21:19:55 +0300 Subject: [PATCH 12/20] Added accent letters layouts for english (from PS5) --- .../libraries/ime/ime_keyboard_layouts.cpp | 268 ++++++++++++------ src/core/libraries/ime/ime_keyboard_layouts.h | 31 +- src/core/libraries/ime/ime_keyboard_ui.cpp | 17 +- 3 files changed, 211 insertions(+), 105 deletions(-) diff --git a/src/core/libraries/ime/ime_keyboard_layouts.cpp b/src/core/libraries/ime/ime_keyboard_layouts.cpp index 0247ea8a5..485293105 100644 --- a/src/core/libraries/ime/ime_keyboard_layouts.cpp +++ b/src/core/libraries/ime/ime_keyboard_layouts.cpp @@ -20,7 +20,7 @@ constexpr auto Square = ImGuiNavInput_Cancel; constexpr auto Triangle = ImGuiNavInput_Input; constexpr auto TouchPad = ImGuiNavInput_Menu; // reuse if needed -const std::vector kUppercaseLayout = { +const std::vector kLayoutEnLettersUppercase = { // Row 1 {0, 0, 1, 1, "1", "", KeyType::Text, {}}, {0, 1, 1, 1, "2", "", KeyType::Text, {}}, @@ -71,9 +71,8 @@ const std::vector kUppercaseLayout = { // Row 5 {4, 0, 1, 1, "⬆", "L2", KeyType::Shift, {L2}}, - {4, 1, 1, 1, "@#:", "L2+△", KeyType::Symbols1Layout, {L3, Triangle}}, - {4, 2, 1, 1, "à", "L3", KeyType::UnknownFunction, {L3}}, + {4, 2, 1, 1, "à", "L3", KeyType::AccentLettersLayout, {L3}}, {4, 3, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, //{4, 4, 4, 1, "Space", "△", KeyType::Space,{Triangle}}, //{4, 5, 4, 1, "Space", "△", KeyType::Space,{Triangle}}, @@ -88,16 +87,14 @@ const std::vector kUppercaseLayout = { {5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft, {L1}}, {5, 3, 1, 1, "▶", "R1", KeyType::CursorRight, {R1}}, {5, 4, 1, 1, "KB", "", KeyType::ToggleKeyboard, {}}, - //{5, 4, 1, 1, "⌨", "", KeyType::ToggleKeyboard,{}}, {5, 5, 1, 1, "...", "", KeyType::MoreOptions, {}}, - //{5, 5, 1, 1, "…", "", KeyType::MoreOptions,{}}, {5, 6, 1, 1, "+/⊗", "R3", KeyType::ControllerAction, {R3}}, {5, 7, 1, 1, "", "", KeyType::Disabled, {}}, {5, 8, 2, 1, "Done", "R2", KeyType::Done, {R2}}, //{5, 9, 2, 1, "Done", "R2", KeyType::Done,{R2}}, }; -const std::vector kLowercaseLayout = { +const std::vector kLayoutEnLettersLowercase = { // Row 1 {0, 0, 1, 1, "1", "", KeyType::Text, {}}, {0, 1, 1, 1, "2", "", KeyType::Text, {}}, @@ -149,7 +146,7 @@ const std::vector kLowercaseLayout = { // Row 5 {4, 0, 1, 1, "⇧", "L2", KeyType::Shift, {L2}}, {4, 1, 1, 1, "@#:", "L2+△", KeyType::Symbols1Layout, {L2, Triangle}}, - {4, 2, 1, 1, "à", "L3", KeyType::UnknownFunction, {L3}}, + {4, 2, 1, 1, "à", "L3", KeyType::AccentLettersLayout, {L3}}, {4, 3, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, //{4, 4, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, //{4, 5, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, @@ -170,84 +167,8 @@ const std::vector kLowercaseLayout = { {5, 8, 2, 1, "Done", "R2", KeyType::Done, {R2}}, //{5, 9, 2, 1, "Done", "R2", KeyType::Done, {R2}}, }; -/* -const std::vector kSymbols1Layout = { - // Row 1 - {0, 0, 1, 1, "!", "", KeyType::Text, {}}, - {0, 1, 1, 1, "?", "", KeyType::Text, {}}, - {0, 2, 1, 1, "\"", "", KeyType::Text, {}}, - {0, 3, 1, 1, "'", "", KeyType::Text, {}}, - {0, 4, 1, 1, "#", "", KeyType::Text, {}}, - {0, 5, 1, 1, "%", "", KeyType::Text, {}}, - {0, 6, 1, 1, "(", "", KeyType::Text, {}}, - {0, 7, 1, 1, ")", "", KeyType::Text, {}}, - {0, 8, 1, 1, "()", "", KeyType::Text, {}}, - {0, 9, 1, 1, "/", "", KeyType::Text, {}}, - - // Row 2 - {1, 0, 1, 1, "-", "", KeyType::Text, {}}, - {1, 1, 1, 1, "_", "", KeyType::Text, {}}, - {1, 2, 1, 1, ",", "", KeyType::Text, {}}, - {1, 3, 1, 1, ".", "", KeyType::Text, {}}, - {1, 4, 1, 1, ":", "", KeyType::Text, {}}, - {1, 5, 1, 1, ";", "", KeyType::Text, {}}, - {1, 6, 1, 1, "*", "", KeyType::Text, {}}, - {1, 7, 1, 1, "+", "", KeyType::Text, {}}, - {1, 8, 1, 1, "=", "", KeyType::Text, {}}, - {1, 9, 1, 1, "&", "", KeyType::Text, {}}, - - // Row 3 - {2, 0, 1, 1, "<", "", KeyType::Text, {}}, - {2, 1, 1, 1, ">", "", KeyType::Text, {}}, - {2, 2, 1, 1, "@", "", KeyType::Text, {}}, - {2, 3, 1, 1, "[", "", KeyType::Text, {}}, - {2, 4, 1, 1, "]", "", KeyType::Text, {}}, - {2, 5, 1, 1, "[]", "", KeyType::Text, {}}, - {2, 6, 1, 1, "{", "", KeyType::Text, {}}, - {2, 7, 1, 1, "}", "", KeyType::Text, {}}, - {2, 8, 1, 1, "{}", "", KeyType::Text, {}}, - {2, 9, 1, 2, "→", "", KeyType::UnknownFunction, {}}, - - // Row 4 - {3, 0, 1, 1, "\\", "", KeyType::Text, {}}, - {3, 1, 1, 1, "|", "", KeyType::Text, {}}, - {3, 2, 1, 1, "^", "", KeyType::Text, {}}, - {3, 3, 1, 1, "`", "", KeyType::Text, {}}, - {3, 4, 1, 1, "$", "", KeyType::Text, {}}, - {3, 5, 1, 1, "€", "", KeyType::Text, {}}, - {3, 6, 1, 1, "´", "", KeyType::Text, {}}, - {3, 7, 1, 1, "ˊ", "", KeyType::Text, {}}, - {3, 8, 1, 1, "ˊ", "", KeyType::Text, {}}, - //{3, 9, 1, 2, "→", "", KeyType::UnknownFunction,{}}, - - // Row 5 - {4, 0, 1, 1, "", "", KeyType::Disabled, {}}, - {4, 1, 1, 1, "ABC", "L2+△", KeyType::TextLayout, {L2, Triangle}}, - {4, 2, 1, 1, "", "", KeyType::Disabled, {}}, - {4, 3, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, - //{4, 4, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, - //{4, 5, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, - //{4, 6, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, - {4, 7, 1, 1, "", "", KeyType::Disabled, {}}, - {4, 8, 2, 1, "⇦", "□", KeyType::Backspace, {Square}}, - //{4, 9, 2, 1, "⇦", "□", KeyType::Backspace, {Square}}, - - // Row 6 - {5, 0, 1, 1, "▲", "", KeyType::CursorUp, {Up}}, - {5, 1, 1, 1, "▼", "", KeyType::CursorDown, {Down}}, - {5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft, {L1}}, - {5, 3, 1, 1, "▶", "R1", KeyType::CursorRight, {R1}}, - {5, 4, 1, 1, "KB", "", KeyType::ToggleKeyboard, {}}, - {5, 5, 1, 1, "...", "", KeyType::MoreOptions, {}}, - {5, 6, 1, 1, "+/⊗", "R3", KeyType::ControllerAction, {R3}}, - {5, 7, 1, 1, "", "", KeyType::Disabled, {}}, - {5, 8, 2, 1, "Done", "R2", KeyType::Done, {R2}}, - //{5, 9, 2, 1, "Done", "R2", KeyType::Done, {R2}}, - -}; -*/ // From PS5 -const std::vector kSymbols1Layout = { +const std::vector kLayoutEnSymbols1 = { // Row 1 {0, 0, 1, 1, "!", "", KeyType::Text, {}}, {0, 1, 1, 1, "?", "", KeyType::Text, {}}, @@ -298,7 +219,7 @@ const std::vector kSymbols1Layout = { // Row 5 {4, 0, 1, 1, "", "", KeyType::Disabled, {}}, - {4, 1, 1, 1, "ABC", "L2+△", KeyType::TextLayout, {L2, Triangle}}, + {4, 1, 1, 1, "ABC", "L2+△", KeyType::LettersLayout, {L2, Triangle}}, {4, 2, 1, 1, "", "", KeyType::Disabled, {}}, {4, 3, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, //{4, 4, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, @@ -323,7 +244,7 @@ const std::vector kSymbols1Layout = { }; // From PS5 -const std::vector kSymbols2Layout = { +const std::vector kLayoutEnSymbols2 = { // Row 1 {0, 0, 1, 1, "“", "", KeyType::Text, {}}, {0, 1, 1, 1, "”", "", KeyType::Text, {}}, @@ -374,7 +295,7 @@ const std::vector kSymbols2Layout = { // Row 5 {4, 0, 1, 1, "", "", KeyType::Disabled, {}}, - {4, 1, 1, 1, "ABC", "L2+△", KeyType::TextLayout, {L2, Triangle}}, + {4, 1, 1, 1, "ABC", "L2+△", KeyType::LettersLayout, {L2, Triangle}}, {4, 2, 1, 1, "", "", KeyType::Disabled, {}}, {4, 3, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, //{4, 4, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, @@ -396,4 +317,177 @@ const std::vector kSymbols2Layout = { {5, 8, 2, 1, "Done", "R2", KeyType::Done, {R2}}, //{5, 9, 2, 1, "Done", "R2", KeyType::Done, {R2}}, +}; + +const std::vector kLayoutEnAccentLettersUppercase = { + // Row 0 + {0, 0, 1, 1, "À", "", KeyType::Text, {}}, + {0, 1, 1, 1, "Á", "", KeyType::Text, {}}, + {0, 2, 1, 1, "Â", "", KeyType::Text, {}}, + {0, 3, 1, 1, "Ã", "", KeyType::Text, {}}, + {0, 4, 1, 1, "Ä", "", KeyType::Text, {}}, + {0, 5, 1, 1, "Å", "", KeyType::Text, {}}, + {0, 6, 1, 1, "Ą", "", KeyType::Text, {}}, + {0, 7, 1, 1, "Æ", "", KeyType::Text, {}}, + {0, 8, 1, 1, "Ç", "", KeyType::Text, {}}, + {0, 9, 1, 1, "Ć", "", KeyType::Text, {}}, + + // Row 1 + {1, 0, 1, 1, "È", "", KeyType::Text, {}}, + {1, 1, 1, 1, "É", "", KeyType::Text, {}}, + {1, 2, 1, 1, "Ê", "", KeyType::Text, {}}, + {1, 3, 1, 1, "Ë", "", KeyType::Text, {}}, + {1, 4, 1, 1, "Ę", "", KeyType::Text, {}}, + {1, 5, 1, 1, "Ğ", "", KeyType::Text, {}}, + {1, 6, 1, 1, "Ì", "", KeyType::Text, {}}, + {1, 7, 1, 1, "Í", "", KeyType::Text, {}}, + {1, 8, 1, 1, "Î", "", KeyType::Text, {}}, + {1, 9, 1, 1, "Ï", "", KeyType::Text, {}}, + + // Row 2 + {2, 0, 1, 1, "İ", "", KeyType::Text, {}}, + {2, 1, 1, 1, "Ł", "", KeyType::Text, {}}, + {2, 2, 1, 1, "Ñ", "", KeyType::Text, {}}, + {2, 3, 1, 1, "Ń", "", KeyType::Text, {}}, + {2, 4, 1, 1, "Ò", "", KeyType::Text, {}}, + {2, 5, 1, 1, "Ó", "", KeyType::Text, {}}, + {2, 6, 1, 1, "Ô", "", KeyType::Text, {}}, + {2, 7, 1, 1, "Õ", "", KeyType::Text, {}}, + {2, 8, 1, 1, "Ö", "", KeyType::Text, {}}, + {2, 9, 1, 1, "Ø", "", KeyType::Text, {}}, + + // Row 3 + {3, 0, 1, 1, "Œ", "", KeyType::Text, {}}, + {3, 1, 1, 1, "Ś", "", KeyType::Text, {}}, + {3, 2, 1, 1, "Ş", "", KeyType::Text, {}}, + {3, 3, 1, 1, "Š", "", KeyType::Text, {}}, + {3, 4, 1, 1, "ß", "", KeyType::Text, {}}, + {3, 5, 1, 1, "Ù", "", KeyType::Text, {}}, + {3, 6, 1, 1, "Ú", "", KeyType::Text, {}}, + {3, 7, 1, 1, "Û", "", KeyType::Text, {}}, + {3, 8, 1, 1, "Ü", "", KeyType::Text, {}}, + {3, 9, 1, 1, "Ý", "", KeyType::Text, {}}, + + // Row 4 + {4, 0, 1, 1, "Ÿ", "", KeyType::Text, {}}, + {4, 1, 1, 1, "Ź", "", KeyType::Text, {}}, + {4, 2, 1, 1, "Ż", "", KeyType::Text, {}}, + {4, 3, 1, 1, "Ž", "", KeyType::Text, {}}, + {4, 4, 1, 1, "Ð", "", KeyType::Text, {}}, + {4, 5, 1, 1, "Þ", "", KeyType::Text, {}}, + {4, 6, 1, 1, "", "", KeyType::Disabled, {}}, + {4, 7, 1, 1, "", "", KeyType::Disabled, {}}, + {4, 8, 1, 1, "", "", KeyType::Disabled, {}}, + {4, 9, 1, 1, "", "", KeyType::Disabled, {}}, + + // Row 5 + {5, 0, 1, 1, "⬆", "L2", KeyType::Shift, {L2}}, + {5, 1, 1, 1, "@#:", "L2+△", KeyType::Symbols1Layout, {L3, Triangle}}, + {5, 2, 1, 1, "à", "L3", KeyType::AccentLettersLayout, {L3}}, + {5, 3, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, + //{4, 4, 4, 1, "Space", "△", KeyType::Space,{Triangle}}, + //{4, 5, 4, 1, "Space", "△", KeyType::Space,{Triangle}}, + //{4, 6, 4, 1, "Space", "△", KeyType::Space,{Triangle}}, + {4, 7, 1, 1, "", "", KeyType::Disabled, {}}, + {5, 8, 2, 1, "⇦", "□", KeyType::Backspace, {Square}}, + //{4, 9, 2, 1, "⇦", "□", KeyType::Backspace,{Square}}, + + // Row 6 + {6, 0, 1, 1, "▲", "", KeyType::CursorUp, {Up}}, + {6, 1, 1, 1, "▼", "", KeyType::CursorDown, {Down}}, + {6, 2, 1, 1, "◀", "L1", KeyType::CursorLeft, {L1}}, + {6, 3, 1, 1, "▶", "R1", KeyType::CursorRight, {R1}}, + {6, 4, 1, 1, "KB", "", KeyType::ToggleKeyboard, {}}, + {6, 5, 1, 1, "...", "", KeyType::MoreOptions, {}}, + {6, 6, 1, 1, "+/⊗", "R3", KeyType::ControllerAction, {R3}}, + {5, 7, 1, 1, "", "", KeyType::Disabled, {}}, + {6, 8, 2, 1, "Done", "R2", KeyType::Done, {R2}}, + //{5, 9, 2, 1, "Done", "R2", KeyType::Done,{R2}}, +}; + +const std::vector kLayoutEnAccentLettersLowercase = { + // Row 0 + {0, 0, 1, 1, "à", "", KeyType::Text, {}}, + {0, 1, 1, 1, "á", "", KeyType::Text, {}}, + {0, 2, 1, 1, "â", "", KeyType::Text, {}}, + {0, 3, 1, 1, "ã", "", KeyType::Text, {}}, + {0, 4, 1, 1, "ä", "", KeyType::Text, {}}, + {0, 5, 1, 1, "å", "", KeyType::Text, {}}, + {0, 6, 1, 1, "ą", "", KeyType::Text, {}}, + {0, 7, 1, 1, "æ", "", KeyType::Text, {}}, + {0, 8, 1, 1, "ç", "", KeyType::Text, {}}, + {0, 9, 1, 1, "ć", "", KeyType::Text, {}}, + + // Row 1 + {1, 0, 1, 1, "è", "", KeyType::Text, {}}, + {1, 1, 1, 1, "é", "", KeyType::Text, {}}, + {1, 2, 1, 1, "ê", "", KeyType::Text, {}}, + {1, 3, 1, 1, "ë", "", KeyType::Text, {}}, + {1, 4, 1, 1, "ę", "", KeyType::Text, {}}, + {1, 5, 1, 1, "ğ", "", KeyType::Text, {}}, + {1, 6, 1, 1, "ì", "", KeyType::Text, {}}, + {1, 7, 1, 1, "í", "", KeyType::Text, {}}, + {1, 8, 1, 1, "î", "", KeyType::Text, {}}, + {1, 9, 1, 1, "ï", "", KeyType::Text, {}}, + + // Row 2 + {2, 0, 1, 1, "ı", "", KeyType::Text, {}}, + {2, 1, 1, 1, "ł", "", KeyType::Text, {}}, + {2, 2, 1, 1, "ñ", "", KeyType::Text, {}}, + {2, 3, 1, 1, "ń", "", KeyType::Text, {}}, + {2, 4, 1, 1, "ò", "", KeyType::Text, {}}, + {2, 5, 1, 1, "ó", "", KeyType::Text, {}}, + {2, 6, 1, 1, "ô", "", KeyType::Text, {}}, + {2, 7, 1, 1, "õ", "", KeyType::Text, {}}, + {2, 8, 1, 1, "ö", "", KeyType::Text, {}}, + {2, 9, 1, 1, "ø", "", KeyType::Text, {}}, + + // Row 3 + {3, 0, 1, 1, "œ", "", KeyType::Text, {}}, + {3, 1, 1, 1, "ś", "", KeyType::Text, {}}, + {3, 2, 1, 1, "ş", "", KeyType::Text, {}}, + {3, 3, 1, 1, "š", "", KeyType::Text, {}}, + {3, 4, 1, 1, "ß", "", KeyType::Text, {}}, + {3, 5, 1, 1, "ù", "", KeyType::Text, {}}, + {3, 6, 1, 1, "ú", "", KeyType::Text, {}}, + {3, 7, 1, 1, "û", "", KeyType::Text, {}}, + {3, 8, 1, 1, "ü", "", KeyType::Text, {}}, + {3, 9, 1, 1, "ý", "", KeyType::Text, {}}, + + // Row 4 + {4, 0, 1, 1, "ÿ", "", KeyType::Text, {}}, + {4, 1, 1, 1, "ź", "", KeyType::Text, {}}, + {4, 2, 1, 1, "ż", "", KeyType::Text, {}}, + {4, 3, 1, 1, "ž", "", KeyType::Text, {}}, + {4, 4, 1, 1, "ð", "", KeyType::Text, {}}, + {4, 5, 1, 1, "þ", "", KeyType::Text, {}}, + {4, 6, 1, 1, "", "", KeyType::Disabled, {}}, + {4, 7, 1, 1, "", "", KeyType::Disabled, {}}, + {4, 8, 1, 1, "", "", KeyType::Disabled, {}}, + {4, 9, 1, 1, "", "", KeyType::Disabled, {}}, + + // Row 5 + {5, 0, 1, 1, "⬆", "L2", KeyType::Shift, {L2}}, + {5, 1, 1, 1, "@#:", "L2+△", KeyType::Symbols1Layout, {L3, Triangle}}, + {5, 2, 1, 1, "à", "L3", KeyType::AccentLettersLayout, {L3}}, + {5, 3, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, + //{4, 4, 4, 1, "Space", "△", KeyType::Space,{Triangle}}, + //{4, 5, 4, 1, "Space", "△", KeyType::Space,{Triangle}}, + //{4, 6, 4, 1, "Space", "△", KeyType::Space,{Triangle}}, + {4, 7, 1, 1, "", "", KeyType::Disabled, {}}, + {5, 8, 2, 1, "⇦", "□", KeyType::Backspace, {Square}}, + //{4, 9, 2, 1, "⇦", "□", KeyType::Backspace,{Square}}, + + // Row 6 + {6, 0, 1, 1, "▲", "", KeyType::CursorUp, {Up}}, + {6, 1, 1, 1, "▼", "", KeyType::CursorDown, {Down}}, + {6, 2, 1, 1, "◀", "L1", KeyType::CursorLeft, {L1}}, + {6, 3, 1, 1, "▶", "R1", KeyType::CursorRight, {R1}}, + {6, 4, 1, 1, "KB", "", KeyType::ToggleKeyboard, {}}, + {6, 5, 1, 1, "...", "", KeyType::MoreOptions, {}}, + //{5, 5, 1, 1, "…", "", KeyType::MoreOptions,{}}, + {6, 6, 1, 1, "+/⊗", "R3", KeyType::ControllerAction, {R3}}, + {5, 7, 1, 1, "", "", KeyType::Disabled, {}}, + {6, 8, 2, 1, "Done", "R2", KeyType::Done, {R2}}, + //{5, 9, 2, 1, "Done", "R2", KeyType::Done,{R2}}, }; \ No newline at end of file diff --git a/src/core/libraries/ime/ime_keyboard_layouts.h b/src/core/libraries/ime/ime_keyboard_layouts.h index 7d4e8d8f5..69b05576f 100644 --- a/src/core/libraries/ime/ime_keyboard_layouts.h +++ b/src/core/libraries/ime/ime_keyboard_layouts.h @@ -8,22 +8,23 @@ #include enum class KeyType { - Text, // Inserts character(s) into input buffer - Backspace, // Deletes last character - Space, // Adds space - Enter, // Submits input - Shift, // Toggle uppercase/lowercase - Symbols1Layout, // Switch to symbols layout - Symbols2Layout, // Switch to symbols layout - TextLayout, // Switch to text layout - Done, // Finish and close keyboard + Text, // Inserts character(s) into input buffer + Backspace, // Deletes last character + Space, // Adds space + Enter, // Submits input + Shift, // Toggle uppercase/lowercase + Symbols1Layout, // Switch to symbols layout + Symbols2Layout, // Switch to symbols layout + LettersLayout, // Switch to text layout + AccentLettersLayout, // Switch to accent text layout + Done, // Finish and close keyboard CursorLeft, CursorRight, CursorUp, CursorDown, ToggleKeyboard, // Toggles keyboard layout MoreOptions, // "..." button - ControllerAction, // e.g. R3 🎮⊕ + ControllerAction, // e.g. R3 +/⊕ Disabled, // Filler or placeholder UnknownFunction, // now same as disabled }; @@ -39,7 +40,9 @@ struct Key { std::vector bound_buttons = {}; // Now using ImGui navigation inputs }; -extern const std::vector kUppercaseLayout; -extern const std::vector kLowercaseLayout; -extern const std::vector kSymbols1Layout; -extern const std::vector kSymbols2Layout; +extern const std::vector kLayoutEnLettersUppercase; +extern const std::vector kLayoutEnLettersLowercase; +extern const std::vector kLayoutEnAccentLettersUppercase; +extern const std::vector kLayoutEnAccentLettersLowercase; +extern const std::vector kLayoutEnSymbols1; +extern const std::vector kLayoutEnSymbols2; diff --git a/src/core/libraries/ime/ime_keyboard_ui.cpp b/src/core/libraries/ime/ime_keyboard_ui.cpp index 066bedc4e..a71bba129 100644 --- a/src/core/libraries/ime/ime_keyboard_ui.cpp +++ b/src/core/libraries/ime/ime_keyboard_ui.cpp @@ -32,13 +32,18 @@ void DrawVirtualKeyboard(char* buffer, std::size_t buffer_capacity, bool* input_ switch (kb_mode) { case KeyboardMode::Symbols1: - layout = &kSymbols1Layout; + layout = &kLayoutEnSymbols1; break; case KeyboardMode::Symbols2: - layout = &kSymbols2Layout; + layout = &kLayoutEnSymbols2; break; + case KeyboardMode::Letters2: + layout = + shift_enabled ? &kLayoutEnAccentLettersUppercase : &kLayoutEnAccentLettersLowercase; + break; + case KeyboardMode::Letters1: default: - layout = shift_enabled ? &kUppercaseLayout : &kLowercaseLayout; + layout = shift_enabled ? &kLayoutEnLettersUppercase : &kLayoutEnLettersLowercase; break; } @@ -122,9 +127,13 @@ void RenderKeyboardLayout(const std::vector& layout, char* buffer, std::siz case KeyType::Symbols2Layout: kb_mode = KeyboardMode::Symbols2; break; - case KeyType::TextLayout: + case KeyType::LettersLayout: kb_mode = KeyboardMode::Letters1; break; + case KeyType::AccentLettersLayout: + kb_mode = KeyboardMode::Letters2; + break; + case KeyType::ToggleKeyboard: kb_mode = (kb_mode == KeyboardMode::Letters1) ? KeyboardMode::Symbols1 : KeyboardMode::Letters1; From 7bf3f54b3835422379288448ea5c90f1b97d7a66 Mon Sep 17 00:00:00 2001 From: w1naenator Date: Sun, 20 Apr 2025 01:16:35 +0300 Subject: [PATCH 13/20] full redesign. --- src/core/libraries/ime/ime_dialog_ui.cpp | 372 +++++--- src/core/libraries/ime/ime_dialog_ui.h | 137 ++- .../libraries/ime/ime_keyboard_layouts.cpp | 815 +++++++++--------- src/core/libraries/ime/ime_keyboard_layouts.h | 106 ++- src/core/libraries/ime/ime_keyboard_ui.cpp | 292 ++++--- src/core/libraries/ime/ime_keyboard_ui.h | 87 +- src/core/libraries/ime/ime_ui.cpp | 45 +- src/core/libraries/ime/ime_ui.h | 2 - src/imgui/renderer/imgui_core.cpp | 2 +- 9 files changed, 1095 insertions(+), 763 deletions(-) diff --git a/src/core/libraries/ime/ime_dialog_ui.cpp b/src/core/libraries/ime/ime_dialog_ui.cpp index e34fd064e..9bffc8959 100644 --- a/src/core/libraries/ime/ime_dialog_ui.cpp +++ b/src/core/libraries/ime/ime_dialog_ui.cpp @@ -1,5 +1,8 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later +// ime_dialog_ui.cpp +// ---------------------------------------------------------- +// Full implementation of IME dialog UI with on‑screen keyboard +// (all original logic intact, bugs fixed). +// ---------------------------------------------------------- #include #include @@ -10,25 +13,52 @@ #include "common/logging/log.h" #include "core/libraries/ime/ime_dialog.h" #include "core/libraries/ime/ime_dialog_ui.h" -#include "core/libraries/ime/ime_keyboard_ui.h" #include "core/tls.h" #include "imgui/imgui_std.h" +#include "ime_keyboard_layouts.h" // c16rtomb, layout tables +#include "ime_keyboard_ui.h" // DrawVirtualKeyboard, Utf8SafeBackspace + using namespace ImGui; +/* small helper for the OK/Cancel buttons */ static constexpr ImVec2 BUTTON_SIZE{100.0f, 30.0f}; +/* convert palette colour from Orbis struct to ImGui format */ +static ImU32 ConvertColor(const Libraries::ImeDialog::OrbisImeColor& c) { + return IM_COL32(c.r, c.g, c.b, c.a); +} + +/*─────────────────────────────────────────────────────────────* + * Libraries::ImeDialog implementation + *─────────────────────────────────────────────────────────────*/ namespace Libraries::ImeDialog { +/* ---------------------------------------------------------- + * class‑static pointer – single definition + * ----------------------------------------------------------*/ +ImeDialogUi* ImeDialogUi::g_activeImeDialogUi = nullptr; + +/* ---------------------------------------------------------- + * keyboard‑to‑dialog event bridge + * ----------------------------------------------------------*/ +static void KeyboardCallbackBridge(const VirtualKeyEvent* evt) { + if (ImeDialogUi::g_activeImeDialogUi && evt) + ImeDialogUi::g_activeImeDialogUi->OnVirtualKeyEvent(evt); +} + +/*─────────────────────────────────────────────────────────────* + * ImeDialogState : constructors, helpers + *─────────────────────────────────────────────────────────────*/ ImeDialogState::ImeDialogState(const OrbisImeDialogParam* param, const OrbisImeParamExtended* extended) { - if (!param) { + if (!param) return; - } + /* basic param copy */ user_id = param->user_id; is_multi_line = True(param->option & OrbisImeDialogOption::Multiline); - is_numeric = param->type == OrbisImeType::Number; + is_numeric = (param->type == OrbisImeType::Number); type = param->type; enter_label = param->enter_label; text_filter = param->filter; @@ -36,6 +66,35 @@ ImeDialogState::ImeDialogState(const OrbisImeDialogParam* param, max_text_length = param->max_text_length; text_buffer = param->input_text_buffer; + /* default keyboard style */ + has_custom_kb_style = false; + custom_kb_style.layout_width = 485.0f; + custom_kb_style.layout_height = 200.0f; + custom_kb_style.key_spacing = 2.0f; + custom_kb_style.color_text = IM_COL32(225, 225, 225, 255); + custom_kb_style.color_line = IM_COL32(88, 88, 88, 255); + custom_kb_style.color_button_default = IM_COL32(35, 35, 35, 255); + custom_kb_style.color_button_function = IM_COL32(50, 50, 50, 255); + custom_kb_style.color_special = IM_COL32(0, 140, 200, 255); + custom_kb_style.color_button_symbol = IM_COL32(60, 60, 60, 255); + custom_kb_style.use_button_symbol_color = false; + + /* optional extended palette */ + if (extended) { + custom_kb_style.layout_width = 600.0f; + custom_kb_style.layout_height = 220.0f; + custom_kb_style.key_spacing = 3.0f; + custom_kb_style.color_text = ConvertColor(extended->color_text); + custom_kb_style.color_line = ConvertColor(extended->color_line); + custom_kb_style.color_button_default = ConvertColor(extended->color_button_default); + custom_kb_style.color_button_function = ConvertColor(extended->color_button_function); + custom_kb_style.color_button_symbol = ConvertColor(extended->color_button_symbol); + custom_kb_style.color_special = ConvertColor(extended->color_special); + custom_kb_style.use_button_symbol_color = true; + has_custom_kb_style = true; + } + + /* UTF‑16 → UTF‑8 conversions */ if (param->title) { std::size_t title_len = std::char_traits::length(param->title); title.resize(title_len * 4 + 1); @@ -167,12 +226,20 @@ bool ImeDialogState::ConvertUTF8ToOrbis(const char* utf8_text, std::size_t utf8_ return true; } +/*─────────────────────────────────────────────────────────────* + * ImeDialogUi : constructor / destructor / move + *─────────────────────────────────────────────────────────────*/ ImeDialogUi::ImeDialogUi(ImeDialogState* state, OrbisImeDialogStatus* status, OrbisImeDialogResult* result) : state(state), status(status), result(result) { if (state && *status == OrbisImeDialogStatus::Running) { AddLayer(this); + ImeDialogUi::g_activeImeDialogUi = this; + } + + if (state && state->has_custom_kb_style) { + kb_style = state->custom_kb_style; } } @@ -180,6 +247,10 @@ ImeDialogUi::~ImeDialogUi() { std::scoped_lock lock(draw_mutex); Free(); + + if (ImeDialogUi::g_activeImeDialogUi == this) { + ImeDialogUi::g_activeImeDialogUi = nullptr; + } } ImeDialogUi::ImeDialogUi(ImeDialogUi&& other) noexcept @@ -191,8 +262,9 @@ ImeDialogUi::ImeDialogUi(ImeDialogUi&& other) noexcept other.status = nullptr; other.result = nullptr; - if (state && *status == OrbisImeDialogStatus::Running) { + if (state && status && *status == OrbisImeDialogStatus::Running) { AddLayer(this); + ImeDialogUi::g_activeImeDialogUi = this; } } @@ -204,12 +276,14 @@ ImeDialogUi& ImeDialogUi::operator=(ImeDialogUi&& other) { status = other.status; result = other.result; first_render = other.first_render; + other.state = nullptr; other.status = nullptr; other.result = nullptr; - if (state && *status == OrbisImeDialogStatus::Running) { + if (state && status && *status == OrbisImeDialogStatus::Running) { AddLayer(this); + ImeDialogUi::g_activeImeDialogUi = this; } return *this; @@ -219,6 +293,9 @@ void ImeDialogUi::Free() { RemoveLayer(this); } +/*─────────────────────────────────────────────────────────────* + * ImeDialogUi : main ImGui draw routine + *─────────────────────────────────────────────────────────────*/ void ImeDialogUi::Draw() { std::unique_lock lock{draw_mutex}; @@ -235,12 +312,10 @@ void ImeDialogUi::Draw() { ImVec2 window_size; - const float keyboard_height = 200.0f; - if (state->is_multi_line) { - window_size = {500.0f, 300.0f + keyboard_height}; + window_size = {500.0f, 500.0f}; } else { - window_size = {500.0f, 150.0f + keyboard_height}; + window_size = {500.0f, 350.0f}; } CentralizeNextWindow(); @@ -254,157 +329,244 @@ void ImeDialogUi::Draw() { if (Begin("IME Dialog##ImeDialog", nullptr, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings)) { DrawPrettyBackground(); - + /* ---------- title ---------- */ if (!state->title.empty()) { + SetCursorPosX(20.0f); SetWindowFontScale(1.7f); TextUnformatted(state->title.data()); SetWindowFontScale(1.0f); } + /* ---------- input box ---------- */ if (state->is_multi_line) { DrawMultiLineInputText(); } else { DrawInputText(); } - DrawKeyboard(); - SetCursorPosY(GetCursorPosY() + 10.0f); + /* ---------- dummy prediction bar with Cancel button ---------- */ + DrawPredictionBarAnCancelButton(); - const char* button_text; + /* ---------- on‑screen keyboard ---------- */ + DrawVirtualKeyboardSection(); - switch (state->enter_label) { - case OrbisImeEnterLabel::Go: - button_text = "Go##ImeDialogOK"; - break; - case OrbisImeEnterLabel::Search: - button_text = "Search##ImeDialogOK"; - break; - case OrbisImeEnterLabel::Send: - button_text = "Send##ImeDialogOK"; - break; - case OrbisImeEnterLabel::Default: - default: - button_text = "OK##ImeDialogOK"; - break; - } + /* ---------- OK / Cancel buttons ---------- */ + /* { + SetCursorPosY(GetCursorPosY() + 10.0f); + const char* ok_lbl = "OK##ImeDialogOK"; + switch (state->enter_label) { + case OrbisImeEnterLabel::Go: + ok_lbl = "Go##ImeDialogOK"; + break; + case OrbisImeEnterLabel::Search: + ok_lbl = "Search##ImeDialogOK"; + break; + case OrbisImeEnterLabel::Send: + ok_lbl = "Send##ImeDialogOK"; + break; + default: + break; + } - float button_spacing = 10.0f; - float total_button_width = BUTTON_SIZE.x * 2 + button_spacing; - float button_start_pos = (window_size.x - total_button_width) / 2.0f; + float spacing = 10.0f; + float total_w = BUTTON_SIZE.x * 2 + spacing; + float x_start = (window_size.x - total_w) / 2.0f; + SetCursorPosX(x_start); - SetCursorPosX(button_start_pos); + if (Button(ok_lbl, BUTTON_SIZE) || + (!state->is_multi_line && IsKeyPressed(ImGuiKey_Enter))) { + *status = OrbisImeDialogStatus::Finished; + result->endstatus = OrbisImeDialogEndStatus::Ok; + } - if (Button(button_text, BUTTON_SIZE) || - (!state->is_multi_line && IsKeyPressed(ImGuiKey_Enter))) { - *status = OrbisImeDialogStatus::Finished; - result->endstatus = OrbisImeDialogEndStatus::Ok; - } + SameLine(0.0f, spacing); - SameLine(0.0f, button_spacing); + if (Button("Cancel##ImeDialogCancel", BUTTON_SIZE)) { + *status = OrbisImeDialogStatus::Finished; + result->endstatus = OrbisImeDialogEndStatus::UserCanceled; + } + }*/ - if (Button("Cancel##ImeDialogCancel", BUTTON_SIZE)) { - *status = OrbisImeDialogStatus::Finished; - result->endstatus = OrbisImeDialogEndStatus::UserCanceled; - } + End(); } - End(); first_render = false; } +/*─────────────────────────────────────────────────────────────* + * helper draw functions (unchanged) + *─────────────────────────────────────────────────────────────*/ void ImeDialogUi::DrawInputText() { - ImVec2 input_size = {GetWindowWidth() - 40.0f, 0.0f}; + ImVec2 size(GetWindowWidth() - 40.0f, 0.0f); SetCursorPosX(20.0f); - if (first_render) { + if (first_render) SetKeyboardFocusHere(); - } - const char* placeholder = state->placeholder.empty() ? nullptr : state->placeholder.data(); - if (InputTextEx("##ImeDialogInput", placeholder, state->current_text.begin(), - state->max_text_length, input_size, ImGuiInputTextFlags_CallbackCharFilter, - InputTextCallback, this)) { + + const char* ph = state->placeholder.empty() ? nullptr : state->placeholder.data(); + if (InputTextEx("##ImeDialogInput", ph, state->current_text.begin(), state->max_text_length, + size, ImGuiInputTextFlags_CallbackCharFilter, InputTextCallback, this)) state->input_changed = true; - } } void ImeDialogUi::DrawMultiLineInputText() { - ImVec2 input_size = {GetWindowWidth() - 40.0f, 200.0f}; + ImVec2 size(GetWindowWidth() - 40.0f, 200.0f); SetCursorPosX(20.0f); ImGuiInputTextFlags flags = ImGuiInputTextFlags_CallbackCharFilter | static_cast(ImGuiInputTextFlags_Multiline); - if (first_render) { + if (first_render) SetKeyboardFocusHere(); - } - const char* placeholder = state->placeholder.empty() ? nullptr : state->placeholder.data(); - if (InputTextEx("##ImeDialogInput", placeholder, state->current_text.begin(), - state->max_text_length, input_size, flags, InputTextCallback, this)) { + + const char* ph = state->placeholder.empty() ? nullptr : state->placeholder.data(); + if (InputTextEx("##ImeDialogInput", ph, state->current_text.begin(), state->max_text_length, + size, flags, InputTextCallback, this)) state->input_changed = true; - } -} - -void ImeDialogUi::DrawKeyboard() { - static KeyboardMode kb_mode = KeyboardMode::Letters1; - static bool shift_enabled = false; - - static bool has_logged = false; - if (!has_logged) { - LOG_INFO(Lib_ImeDialog, "Virtual keyboard used from ImeDialog"); - has_logged = true; - } - - bool done_pressed = false; - - DrawVirtualKeyboard(state->current_text.begin(), state->max_text_length * 4, - &state->input_changed, kb_mode, shift_enabled, &done_pressed); - - if (done_pressed) { - *status = OrbisImeDialogStatus::Finished; - result->endstatus = OrbisImeDialogEndStatus::Ok; - } } int ImeDialogUi::InputTextCallback(ImGuiInputTextCallbackData* data) { ImeDialogUi* ui = static_cast(data->UserData); ASSERT(ui); - // Should we filter punctuation? + /* numeric filter */ if (ui->state->is_numeric && (data->EventChar < '0' || data->EventChar > '9') && - data->EventChar != '\b' && data->EventChar != ',' && data->EventChar != '.') { + data->EventChar != '\b' && data->EventChar != ',' && data->EventChar != '.') return 1; - } - if (!ui->state->keyboard_filter) { + if (!ui->state->keyboard_filter) return 0; - } - // ImGui encodes ImWchar32 as multi-byte UTF-8 characters - char* event_char = reinterpret_cast(&data->EventChar); + char* ev_char = reinterpret_cast(&data->EventChar); - // Call the keyboard filter - OrbisImeKeycode src_keycode = { + OrbisImeKeycode src{ .keycode = 0, .character = 0, - .status = 1, // ??? 1 = key pressed, 0 = key released - .type = OrbisImeKeyboardType::ENGLISH_US, // TODO set this to the correct value (maybe use - // the current language?) + .status = 1, + .type = OrbisImeKeyboardType::ENGLISH_US, .user_id = ui->state->user_id, .resource_id = 0, .timestamp = 0, }; - if (!ui->state->ConvertUTF8ToOrbis(event_char, 4, &src_keycode.character, 1)) { - LOG_ERROR(Lib_ImeDialog, "Failed to convert orbis char to utf8"); + if (!ui->state->ConvertUTF8ToOrbis(ev_char, 4, &src.character, 1)) return 0; - } - src_keycode.keycode = src_keycode.character; // TODO set this to the correct value - - u16 out_keycode; - u32 out_status; - - ui->state->CallKeyboardFilter(&src_keycode, &out_keycode, &out_status); - - // TODO. set the keycode + src.keycode = src.character; + u16 out_code; + u32 out_stat; + ui->state->CallKeyboardFilter(&src, &out_code, &out_stat); return 0; } +/*─────────────────────────────────────────────────────────────* + * helper draw functions (new) + *─────────────────────────────────────────────────────────────*/ +void ImeDialogUi::OnVirtualKeyEvent(const VirtualKeyEvent* evt) { + if (!evt || !state || !evt->key) + return; + + const KeyEntry* key = evt->key; + + /* Treat Repeat exactly like Down */ + if (evt->type == VirtualKeyEventType::Down || evt->type == VirtualKeyEventType::Repeat) { + switch (key->type) { + case KeyType::Character: { + char utf8[8]{}; + int n = c16rtomb(utf8, key->character); + if (n > 0) + state->AppendUtf8(utf8, (size_t)n); + break; + } + case KeyType::Function: + switch (key->keycode) { + case 0x08: + state->BackspaceUtf8(); + break; // Backspace + case 0x0D: + *status = OrbisImeDialogStatus::Finished; // Enter + result->endstatus = OrbisImeDialogEndStatus::Ok; + break; + + case KC_SYM1: + kb_mode = KeyboardMode::Symbols1; + break; + case KC_SYM2: + kb_mode = KeyboardMode::Symbols2; + break; + case KC_ACCENTS: + kb_mode = KeyboardMode::AccentLetters; + break; + case KC_LETTERS: + kb_mode = KeyboardMode::Letters; + break; + + case 0x10: // Shift / Caps + case 0x105: + shift_state = (shift_state == ShiftState::None) + ? ShiftState::Shift + : (shift_state == ShiftState::Shift ? ShiftState::CapsLock + : ShiftState::None); + break; + default: + break; + } + break; + + default: + break; + } + } + /* Up is available if you need it later; currently ignored */ +} + +/* draw keyboard in a sub‑ID scope */ +void ImeDialogUi::DrawVirtualKeyboardSection() { + ImGui::PushID("VirtualKeyboardSection"); + DrawVirtualKeyboard(kb_mode, state->type, shift_state, kb_language, KeyboardCallbackBridge, + kb_style); + ImGui::PopID(); +} + +void ImeDialogUi::DrawPredictionBarAnCancelButton() { + const float pad = 5.0f; + const float width = kb_style.layout_width; + const float bar_h = 25.0f; + + SetCursorPosX(0.0f); + ImVec2 p0 = GetCursorScreenPos(); + ImVec2 p1 = ImVec2(p0.x + width - bar_h - 2 * pad, p0.y + bar_h); + // GetWindowDrawList()->AddRectFilled(p0, p1, IM_COL32(0, 0, 0, 255)); + + /* label */ + // ImGui::SetCursorScreenPos(ImVec2(p0.x, p0.y)); + // ImGui::PushStyleColor(ImGuiCol_Text, kb_style.color_text); + // Selectable("dummy prediction", false, 0, ImVec2(width - bar_h, bar_h)); + // ImGui::PopStyleColor(); + + SetCursorPosX(pad); + ImGui::PushStyleColor(ImGuiCol_Button, IM_COL32(0, 0, 0, 255)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, IM_COL32(0, 0, 0, 255)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, IM_COL32(0, 0, 0, 255)); + ImGui::PushStyleColor(ImGuiCol_Text, kb_style.color_text); + + if (ImGui::Button("predict", ImVec2(width - bar_h - 3 * pad, bar_h))) { + } + ImGui::PopStyleColor(4); + + /* X button */ + // ImGui::SameLine(width - bar_h); + ImGui::SetCursorScreenPos(ImVec2(p0.x + width - bar_h - pad, p0.y)); + + ImGui::PushStyleColor(ImGuiCol_Button, kb_style.color_button_function); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, kb_style.color_button_function); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, kb_style.color_button_function); + ImGui::PushStyleColor(ImGuiCol_Text, kb_style.color_text); + + if (ImGui::Button("╳", ImVec2(bar_h, bar_h))) { + *status = OrbisImeDialogStatus::Finished; + result->endstatus = OrbisImeDialogEndStatus::UserCanceled; + } + ImGui::PopStyleColor(4); + SetCursorPosX(0.0f); + SetCursorPosY(GetCursorPosY() + 5.0f); +} + } // namespace Libraries::ImeDialog diff --git a/src/core/libraries/ime/ime_dialog_ui.h b/src/core/libraries/ime/ime_dialog_ui.h index af47610a2..0c7c26a71 100644 --- a/src/core/libraries/ime/ime_dialog_ui.h +++ b/src/core/libraries/ime/ime_dialog_ui.h @@ -1,24 +1,29 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - #pragma once +#include // for strncpy / memcpy #include #include #include #include "common/cstring.h" #include "common/types.h" #include "core/libraries/ime/ime_dialog.h" -#include "core/libraries/ime/ime_keyboard_ui.h" +#include "ime_keyboard_ui.h" #include "imgui/imgui_layer.h" +#include + namespace Libraries::ImeDialog { +// Forward declaration so we can befriend it class ImeDialogUi; +//--------------------------------------------------------------------- +// ImeDialogState — holds the text and options for the IME dialog +//--------------------------------------------------------------------- class ImeDialogState final { - friend ImeDialogUi; + friend class ImeDialogUi; // full access for the dialog‑UI layer + /*────────────────────────── private data ─────────────────────────*/ bool input_changed = false; s32 user_id{}; @@ -30,19 +35,75 @@ class ImeDialogState final { OrbisImeExtKeyboardFilter keyboard_filter{}; u32 max_text_length{}; char16_t* text_buffer{}; + std::vector title; std::vector placeholder; - // A character can hold up to 4 bytes in UTF-8 + // One UTF‑8 code‑point may take up to 4 bytes Common::CString current_text; -public: - ImeDialogState(const OrbisImeDialogParam* param = nullptr, - const OrbisImeParamExtended* extended = nullptr); - ImeDialogState(const ImeDialogState& other) = delete; - ImeDialogState(ImeDialogState&& other) noexcept; - ImeDialogState& operator=(ImeDialogState&& other); + // Optional custom keyboard style (from extended params) + bool has_custom_kb_style = false; + KeyboardStyle custom_kb_style{}; +public: + /*──────────────── constructors / rule‑of‑five ────────────────*/ + ImeDialogState(const OrbisImeDialogParam* param = nullptr, + const OrbisImeParamExtended* ext = nullptr); + ImeDialogState(const ImeDialogState&) = delete; + ImeDialogState(ImeDialogState&&) noexcept; + ImeDialogState& operator=(ImeDialogState&&); + + /*──────────────────── public read helpers ───────────────────*/ + bool IsMultiLine() const { + return is_multi_line; + } + bool IsNumeric() const { + return is_numeric; + } + u32 MaxTextLength() const { + return max_text_length; + } + + const char* TitleUtf8() const { + return title.empty() ? nullptr : title.data(); + } + const char* PlaceholderUtf8() const { + return placeholder.empty() ? nullptr : placeholder.data(); + } + const char* CurrentTextUtf8() const { + return current_text.begin(); + } + + /*─────────────────── public write helpers ───────────────────*/ + // Replace the whole text buffer + void SetTextUtf8(const char* utf8) { + if (!utf8) + return; + std::strncpy(current_text.begin(), utf8, current_text.capacity() - 1); + current_text[current_text.capacity() - 1] = '\0'; + input_changed = true; + } + + // Append raw UTF‑8 sequence of length 'len' + void AppendUtf8(const char* utf8, std::size_t len) { + if (!utf8 || len == 0) + return; + std::size_t old = std::strlen(current_text.begin()); + if (old + len >= current_text.capacity()) + return; // full: silently ignore + std::memcpy(current_text.begin() + old, utf8, len); + current_text[old + len] = '\0'; + input_changed = true; + } + + // Remove one UTF‑8 code‑point from the end (safe backspace) + void BackspaceUtf8() { + Utf8SafeBackspace(current_text.begin()); + input_changed = true; + } + + /*──────────────────────── IME support ───────────────────────*/ bool CopyTextToOrbisBuffer(); bool CallTextFilter(); @@ -50,12 +111,16 @@ private: bool CallKeyboardFilter(const OrbisImeKeycode* src_keycode, u16* out_keycode, u32* out_status); bool ConvertOrbisToUTF8(const char16_t* orbis_text, std::size_t orbis_text_len, char* utf8_text, - std::size_t native_text_len); - bool ConvertUTF8ToOrbis(const char* native_text, std::size_t utf8_text_len, - char16_t* orbis_text, std::size_t orbis_text_len); + std::size_t utf8_text_len); + bool ConvertUTF8ToOrbis(const char* utf8_text, std::size_t utf8_text_len, char16_t* orbis_text, + std::size_t orbis_text_len); }; +//--------------------------------------------------------------------- +// ImeDialogUi — draws the IME dialog & on‑screen keyboard +//--------------------------------------------------------------------- class ImeDialogUi final : public ImGui::Layer { + /*────────── private data ─────────*/ ImeDialogState* state{}; OrbisImeDialogStatus* status{}; OrbisImeDialogResult* result{}; @@ -64,24 +129,50 @@ class ImeDialogUi final : public ImGui::Layer { std::mutex draw_mutex; public: + // Global pointer to the active dialog‑UI (used by the callback bridge) + static ImeDialogUi* g_activeImeDialogUi; + + /*───────── ctors / dtor ─────────*/ explicit ImeDialogUi(ImeDialogState* state = nullptr, OrbisImeDialogStatus* status = nullptr, OrbisImeDialogResult* result = nullptr); ~ImeDialogUi() override; - ImeDialogUi(const ImeDialogUi& other) = delete; - ImeDialogUi(ImeDialogUi&& other) noexcept; - ImeDialogUi& operator=(ImeDialogUi&& other); + ImeDialogUi(const ImeDialogUi&) = delete; + ImeDialogUi(ImeDialogUi&&) noexcept; + ImeDialogUi& operator=(ImeDialogUi&&); + /*────────── main draw ───────────*/ void Draw() override; -private: - void Free(); + /*────────── keyboard events ─────*/ + void OnVirtualKeyEvent(const VirtualKeyEvent* evt); +private: + /*── helpers ─*/ + void Free(); void DrawInputText(); void DrawMultiLineInputText(); - - void DrawKeyboard(); - static int InputTextCallback(ImGuiInputTextCallbackData* data); + + /*── keyboard section ─*/ + KeyboardMode kb_mode = KeyboardMode::Letters; + ShiftState shift_state = ShiftState::None; + u64 kb_language = 0; + KeyboardStyle kb_style; + /* KeyboardStyle kb_style{ + .layout_width = 500.0f, + .layout_height = 250.0f, + .key_spacing = 5.0f, + .color_text = IM_COL32(225,225,225,255), + .color_line = IM_COL32( 88, 88, 88,255), + .color_button_default = IM_COL32( 35, 35, 35,255), + .color_button_function = IM_COL32( 50, 50, 50,255), + .color_special = IM_COL32( 0,140,200,255), + .use_button_symbol_color= false, + .color_button_symbol = IM_COL32( 60, 60, 60,255), + };*/ + + void DrawVirtualKeyboardSection(); + void DrawPredictionBarAnCancelButton(); }; } // namespace Libraries::ImeDialog diff --git a/src/core/libraries/ime/ime_keyboard_layouts.cpp b/src/core/libraries/ime/ime_keyboard_layouts.cpp index 485293105..7642fcc22 100644 --- a/src/core/libraries/ime/ime_keyboard_layouts.cpp +++ b/src/core/libraries/ime/ime_keyboard_layouts.cpp @@ -4,490 +4,463 @@ #include #include "ime_keyboard_layouts.h" -constexpr auto L1 = ImGuiNavInput_FocusPrev; -constexpr auto R1 = ImGuiNavInput_FocusNext; -constexpr auto L2 = ImGuiNavInput_TweakSlow; -constexpr auto R2 = ImGuiNavInput_TweakFast; -constexpr auto L3 = ImGuiNavInput_DpadLeft; // adjust if needed -constexpr auto R3 = ImGuiNavInput_DpadRight; // adjust if needed -constexpr auto Up = ImGuiNavInput_DpadUp; -constexpr auto Down = ImGuiNavInput_DpadDown; -constexpr auto Left = ImGuiNavInput_DpadLeft; -constexpr auto Right = ImGuiNavInput_DpadRight; -constexpr auto Cross = ImGuiNavInput_Activate; -constexpr auto Circle = ImGuiNavInput_Menu; -constexpr auto Square = ImGuiNavInput_Cancel; -constexpr auto Triangle = ImGuiNavInput_Input; -constexpr auto TouchPad = ImGuiNavInput_Menu; // reuse if needed +int c16rtomb(char* out, char16_t ch) { + if (ch <= 0x7F) { + out[0] = static_cast(ch); + out[1] = '\0'; + return 1; + } else if (ch <= 0x7FF) { + out[0] = 0xC0 | ((ch >> 6) & 0x1F); + out[1] = 0x80 | (ch & 0x3F); + out[2] = '\0'; + return 2; + } else { + out[0] = 0xE0 | ((ch >> 12) & 0x0F); + out[1] = 0x80 | ((ch >> 6) & 0x3F); + out[2] = 0x80 | (ch & 0x3F); + out[3] = '\0'; + return 3; + } +} + +const std::vector kLayoutEnLettersUppercase = { + // Row 0 + {0x31, u'1', KeyType::Character, 0, 0, 1, 1, "1", "", {None, None}}, + {0x32, u'2', KeyType::Character, 0, 1, 1, 1, "2", "", {None, None}}, + {0x33, u'3', KeyType::Character, 0, 2, 1, 1, "3", "", {None, None}}, + {0x34, u'4', KeyType::Character, 0, 3, 1, 1, "4", "", {None, None}}, + {0x35, u'5', KeyType::Character, 0, 4, 1, 1, "5", "", {None, None}}, + {0x36, u'6', KeyType::Character, 0, 5, 1, 1, "6", "", {None, None}}, + {0x37, u'7', KeyType::Character, 0, 6, 1, 1, "7", "", {None, None}}, + {0x38, u'8', KeyType::Character, 0, 7, 1, 1, "8", "", {None, None}}, + {0x39, u'9', KeyType::Character, 0, 8, 1, 1, "9", "", {None, None}}, + {0x30, u'0', KeyType::Character, 0, 9, 1, 1, "0", "", {None, None}}, -const std::vector kLayoutEnLettersUppercase = { // Row 1 - {0, 0, 1, 1, "1", "", KeyType::Text, {}}, - {0, 1, 1, 1, "2", "", KeyType::Text, {}}, - {0, 2, 1, 1, "3", "", KeyType::Text, {}}, - {0, 3, 1, 1, "4", "", KeyType::Text, {}}, - {0, 4, 1, 1, "5", "", KeyType::Text, {}}, - {0, 5, 1, 1, "6", "", KeyType::Text, {}}, - {0, 6, 1, 1, "7", "", KeyType::Text, {}}, - {0, 7, 1, 1, "8", "", KeyType::Text, {}}, - {0, 8, 1, 1, "9", "", KeyType::Text, {}}, - {0, 9, 1, 1, "0", "", KeyType::Text, {}}, + {0x51, u'Q', KeyType::Character, 1, 0, 1, 1, "Q", "", {None, None}}, + {0x57, u'W', KeyType::Character, 1, 1, 1, 1, "W", "", {None, None}}, + {0x45, u'E', KeyType::Character, 1, 2, 1, 1, "E", "", {None, None}}, + {0x52, u'R', KeyType::Character, 1, 3, 1, 1, "R", "", {None, None}}, + {0x54, u'T', KeyType::Character, 1, 4, 1, 1, "T", "", {None, None}}, + {0x59, u'Y', KeyType::Character, 1, 5, 1, 1, "Y", "", {None, None}}, + {0x55, u'U', KeyType::Character, 1, 6, 1, 1, "U", "", {None, None}}, + {0x49, u'I', KeyType::Character, 1, 7, 1, 1, "I", "", {None, None}}, + {0x4F, u'O', KeyType::Character, 1, 8, 1, 1, "O", "", {None, None}}, + {0x50, u'P', KeyType::Character, 1, 9, 1, 1, "P", "", {None, None}}, // Row 2 - {1, 0, 1, 1, "Q", "", KeyType::Text, {}}, - {1, 1, 1, 1, "W", "", KeyType::Text, {}}, - {1, 2, 1, 1, "E", "", KeyType::Text, {}}, - {1, 3, 1, 1, "R", "", KeyType::Text, {}}, - {1, 4, 1, 1, "T", "", KeyType::Text, {}}, - {1, 5, 1, 1, "Y", "", KeyType::Text, {}}, - {1, 6, 1, 1, "U", "", KeyType::Text, {}}, - {1, 7, 1, 1, "I", "", KeyType::Text, {}}, - {1, 8, 1, 1, "O", "", KeyType::Text, {}}, - {1, 9, 1, 1, "P", "", KeyType::Text, {}}, + {0x41, u'A', KeyType::Character, 2, 0, 1, 1, "A", "", {None, None}}, + {0x53, u'S', KeyType::Character, 2, 1, 1, 1, "S", "", {None, None}}, + {0x44, u'D', KeyType::Character, 2, 2, 1, 1, "D", "", {None, None}}, + {0x46, u'F', KeyType::Character, 2, 3, 1, 1, "F", "", {None, None}}, + {0x47, u'G', KeyType::Character, 2, 4, 1, 1, "G", "", {None, None}}, + {0x48, u'H', KeyType::Character, 2, 5, 1, 1, "H", "", {None, None}}, + {0x4A, u'J', KeyType::Character, 2, 6, 1, 1, "J", "", {None, None}}, + {0x4B, u'K', KeyType::Character, 2, 7, 1, 1, "K", "", {None, None}}, + {0x4C, u'L', KeyType::Character, 2, 8, 1, 1, "L", "", {None, None}}, + {0x22, u'"', KeyType::Character, 2, 9, 1, 1, "\"", "", {None, None}}, // Row 3 - {2, 0, 1, 1, "A", "", KeyType::Text, {}}, - {2, 1, 1, 1, "S", "", KeyType::Text, {}}, - {2, 2, 1, 1, "D", "", KeyType::Text, {}}, - {2, 3, 1, 1, "F", "", KeyType::Text, {}}, - {2, 4, 1, 1, "G", "", KeyType::Text, {}}, - {2, 5, 1, 1, "H", "", KeyType::Text, {}}, - {2, 6, 1, 1, "J", "", KeyType::Text, {}}, - {2, 7, 1, 1, "K", "", KeyType::Text, {}}, - {2, 8, 1, 1, "L", "", KeyType::Text, {}}, - {2, 9, 1, 1, "\"", "", KeyType::Text, {}}, + {0x5A, u'Z', KeyType::Character, 3, 0, 1, 1, "Z", "", {None, None}}, + {0x58, u'X', KeyType::Character, 3, 1, 1, 1, "X", "", {None, None}}, + {0x43, u'C', KeyType::Character, 3, 2, 1, 1, "C", "", {None, None}}, + {0x56, u'V', KeyType::Character, 3, 3, 1, 1, "V", "", {None, None}}, + {0x42, u'B', KeyType::Character, 3, 4, 1, 1, "B", "", {None, None}}, + {0x4E, u'N', KeyType::Character, 3, 5, 1, 1, "N", "", {None, None}}, + {0x4D, u'M', KeyType::Character, 3, 6, 1, 1, "M", "", {None, None}}, + {0x2D, u'-', KeyType::Character, 3, 7, 1, 1, "-", "", {None, None}}, + {0x5F, u'_', KeyType::Character, 3, 8, 1, 1, "_", "", {None, None}}, + {0x2F, u'/', KeyType::Character, 3, 9, 1, 1, "/", "", {None, None}}, // Row 4 - {3, 0, 1, 1, "Z", "", KeyType::Text, {}}, - {3, 1, 1, 1, "X", "", KeyType::Text, {}}, - {3, 2, 1, 1, "C", "", KeyType::Text, {}}, - {3, 3, 1, 1, "V", "", KeyType::Text, {}}, - {3, 4, 1, 1, "B", "", KeyType::Text, {}}, - {3, 5, 1, 1, "N", "", KeyType::Text, {}}, - {3, 6, 1, 1, "M", "", KeyType::Text, {}}, - {3, 7, 1, 1, "-", "", KeyType::Text, {}}, - {3, 8, 1, 1, "_", "", KeyType::Text, {}}, - {3, 9, 1, 1, "/", "", KeyType::Text, {}}, + {0x10, u'\0', KeyType::Function, 4, 0, 1, 1, "⬆", "L2", {L2, None}}, + {KC_SYM1, u'\0', KeyType::Function, 4, 1, 1, 1, "@#:", "△", {Triangle, None}}, // TODO: + {KC_ACCENTS, u'\0', KeyType::Function, 4, 2, 1, 1, "à", "", {None, None}}, // TODO: + {0x20, u' ', KeyType::Character, 4, 3, 4, 1, "Space", "△", {Triangle, None}}, + {0x0000, u'\0', KeyType::Disabled, 4, 7, 1, 1, "", "", {None, None}}, + {0x08, u'\0', KeyType::Function, 4, 8, 2, 1, "⇦", "□", {Square, None}, true}, // Row 5 - {4, 0, 1, 1, "⬆", "L2", KeyType::Shift, {L2}}, - {4, 1, 1, 1, "@#:", "L2+△", KeyType::Symbols1Layout, {L3, Triangle}}, - {4, 2, 1, 1, "à", "L3", KeyType::AccentLettersLayout, {L3}}, - {4, 3, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, - //{4, 4, 4, 1, "Space", "△", KeyType::Space,{Triangle}}, - //{4, 5, 4, 1, "Space", "△", KeyType::Space,{Triangle}}, - //{4, 6, 4, 1, "Space", "△", KeyType::Space,{Triangle}}, - {4, 7, 1, 1, "", "", KeyType::Disabled, {}}, - {4, 8, 2, 1, "⇦", "□", KeyType::Backspace, {Square}}, - //{4, 9, 2, 1, "⇦", "□", KeyType::Backspace,{Square}}, + {0xF020, u'\0', KeyType::Function, 5, 0, 1, 1, "▲", "", {Up, None}}, + {0xF021, u'\0', KeyType::Function, 5, 1, 1, 1, "▼", "", {Down, None}}, + {0xF022, u'\0', KeyType::Function, 5, 2, 1, 1, "◀", "L1", {L1, None}}, + {0xF023, u'\0', KeyType::Function, 5, 3, 1, 1, "▶", "R1", {R1, None}}, + {KC_KB, u'\0', KeyType::Function, 5, 4, 1, 1, "KB", "", {None, None}}, // TODO: + {KC_OPT, u'\0', KeyType::Function, 5, 5, 1, 1, "...", "", {None, None}}, + {KC_GYRO, u'\0', KeyType::Function, 5, 6, 1, 1, "+/⊗", "R3", {R3, None}}, // TODO: + {0x0000, u'\0', KeyType::Disabled, 5, 7, 1, 1, "", "", {None, None}}, + {0x0D, u'\r', KeyType::Function, 5, 8, 2, 1, "Done", "R2", {R2, None}}, - // Row 6 - {5, 0, 1, 1, "▲", "", KeyType::CursorUp, {Up}}, - {5, 1, 1, 1, "▼", "", KeyType::CursorDown, {Down}}, - {5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft, {L1}}, - {5, 3, 1, 1, "▶", "R1", KeyType::CursorRight, {R1}}, - {5, 4, 1, 1, "KB", "", KeyType::ToggleKeyboard, {}}, - {5, 5, 1, 1, "...", "", KeyType::MoreOptions, {}}, - {5, 6, 1, 1, "+/⊗", "R3", KeyType::ControllerAction, {R3}}, - {5, 7, 1, 1, "", "", KeyType::Disabled, {}}, - {5, 8, 2, 1, "Done", "R2", KeyType::Done, {R2}}, - //{5, 9, 2, 1, "Done", "R2", KeyType::Done,{R2}}, }; -const std::vector kLayoutEnLettersLowercase = { +const std::vector kLayoutEnLettersLowercase = { + // Row 0 + {0x31, u'1', KeyType::Character, 0, 0, 1, 1, "1", "", {None, None}}, + {0x32, u'2', KeyType::Character, 0, 1, 1, 1, "2", "", {None, None}}, + {0x33, u'3', KeyType::Character, 0, 2, 1, 1, "3", "", {None, None}}, + {0x34, u'4', KeyType::Character, 0, 3, 1, 1, "4", "", {None, None}}, + {0x35, u'5', KeyType::Character, 0, 4, 1, 1, "5", "", {None, None}}, + {0x36, u'6', KeyType::Character, 0, 5, 1, 1, "6", "", {None, None}}, + {0x37, u'7', KeyType::Character, 0, 6, 1, 1, "7", "", {None, None}}, + {0x38, u'8', KeyType::Character, 0, 7, 1, 1, "8", "", {None, None}}, + {0x39, u'9', KeyType::Character, 0, 8, 1, 1, "9", "", {None, None}}, + {0x30, u'0', KeyType::Character, 0, 9, 1, 1, "0", "", {None, None}}, + // Row 1 - {0, 0, 1, 1, "1", "", KeyType::Text, {}}, - {0, 1, 1, 1, "2", "", KeyType::Text, {}}, - {0, 2, 1, 1, "3", "", KeyType::Text, {}}, - {0, 3, 1, 1, "4", "", KeyType::Text, {}}, - {0, 4, 1, 1, "5", "", KeyType::Text, {}}, - {0, 5, 1, 1, "6", "", KeyType::Text, {}}, - {0, 6, 1, 1, "7", "", KeyType::Text, {}}, - {0, 7, 1, 1, "8", "", KeyType::Text, {}}, - {0, 8, 1, 1, "9", "", KeyType::Text, {}}, - {0, 9, 1, 1, "0", "", KeyType::Text, {}}, + {0x71, u'q', KeyType::Character, 1, 0, 1, 1, "q", "", {None, None}}, + {0x77, u'w', KeyType::Character, 1, 1, 1, 1, "w", "", {None, None}}, + {0x65, u'e', KeyType::Character, 1, 2, 1, 1, "e", "", {None, None}}, + {0x72, u'r', KeyType::Character, 1, 3, 1, 1, "r", "", {None, None}}, + {0x74, u't', KeyType::Character, 1, 4, 1, 1, "t", "", {None, None}}, + {0x79, u'y', KeyType::Character, 1, 5, 1, 1, "y", "", {None, None}}, + {0x75, u'u', KeyType::Character, 1, 6, 1, 1, "u", "", {None, None}}, + {0x69, u'i', KeyType::Character, 1, 7, 1, 1, "i", "", {None, None}}, + {0x6F, u'o', KeyType::Character, 1, 8, 1, 1, "o", "", {None, None}}, + {0x70, u'p', KeyType::Character, 1, 9, 1, 1, "p", "", {None, None}}, // Row 2 - {1, 0, 1, 1, "q", "", KeyType::Text, {}}, - {1, 1, 1, 1, "w", "", KeyType::Text, {}}, - {1, 2, 1, 1, "e", "", KeyType::Text, {}}, - {1, 3, 1, 1, "r", "", KeyType::Text, {}}, - {1, 4, 1, 1, "t", "", KeyType::Text, {}}, - {1, 5, 1, 1, "y", "", KeyType::Text, {}}, - {1, 6, 1, 1, "u", "", KeyType::Text, {}}, - {1, 7, 1, 1, "i", "", KeyType::Text, {}}, - {1, 8, 1, 1, "o", "", KeyType::Text, {}}, - {1, 9, 1, 1, "p", "", KeyType::Text, {}}, + {0x61, u'a', KeyType::Character, 2, 0, 1, 1, "a", "", {None, None}}, + {0x73, u's', KeyType::Character, 2, 1, 1, 1, "s", "", {None, None}}, + {0x64, u'd', KeyType::Character, 2, 2, 1, 1, "d", "", {None, None}}, + {0x66, u'f', KeyType::Character, 2, 3, 1, 1, "f", "", {None, None}}, + {0x67, u'g', KeyType::Character, 2, 4, 1, 1, "g", "", {None, None}}, + {0x68, u'h', KeyType::Character, 2, 5, 1, 1, "h", "", {None, None}}, + {0x6A, u'j', KeyType::Character, 2, 6, 1, 1, "j", "", {None, None}}, + {0x6B, u'k', KeyType::Character, 2, 7, 1, 1, "k", "", {None, None}}, + {0x6C, u'l', KeyType::Character, 2, 8, 1, 1, "l", "", {None, None}}, + {0x22, u'"', KeyType::Character, 2, 9, 1, 1, "\"", "", {None, None}}, // Row 3 - {2, 0, 1, 1, "a", "", KeyType::Text, {}}, - {2, 1, 1, 1, "s", "", KeyType::Text, {}}, - {2, 2, 1, 1, "d", "", KeyType::Text, {}}, - {2, 3, 1, 1, "f", "", KeyType::Text, {}}, - {2, 4, 1, 1, "g", "", KeyType::Text, {}}, - {2, 5, 1, 1, "h", "", KeyType::Text, {}}, - {2, 6, 1, 1, "j", "", KeyType::Text, {}}, - {2, 7, 1, 1, "k", "", KeyType::Text, {}}, - {2, 8, 1, 1, "l", "", KeyType::Text, {}}, - {2, 9, 1, 1, "-", "", KeyType::Text, {}}, + {0x7A, u'z', KeyType::Character, 3, 0, 1, 1, "z", "", {None, None}}, + {0x78, u'x', KeyType::Character, 3, 1, 1, 1, "x", "", {None, None}}, + {0x63, u'c', KeyType::Character, 3, 2, 1, 1, "c", "", {None, None}}, + {0x76, u'v', KeyType::Character, 3, 3, 1, 1, "v", "", {None, None}}, + {0x62, u'b', KeyType::Character, 3, 4, 1, 1, "b", "", {None, None}}, + {0x6E, u'n', KeyType::Character, 3, 5, 1, 1, "n", "", {None, None}}, + {0x6D, u'm', KeyType::Character, 3, 6, 1, 1, "m", "", {None, None}}, + {0x2D, u'-', KeyType::Character, 3, 7, 1, 1, "-", "", {None, None}}, + {0x5F, u'_', KeyType::Character, 3, 8, 1, 1, "_", "", {None, None}}, + {0x2F, u'/', KeyType::Character, 3, 9, 1, 1, "/", "", {None, None}}, // Row 4 - {3, 0, 1, 1, "z", "", KeyType::Text, {}}, - {3, 1, 1, 1, "x", "", KeyType::Text, {}}, - {3, 2, 1, 1, "c", "", KeyType::Text, {}}, - {3, 3, 1, 1, "v", "", KeyType::Text, {}}, - {3, 4, 1, 1, "b", "", KeyType::Text, {}}, - {3, 5, 1, 1, "n", "", KeyType::Text, {}}, - {3, 6, 1, 1, "m", "", KeyType::Text, {}}, - {3, 7, 1, 1, "@", "", KeyType::Text, {}}, - {3, 8, 1, 1, ".", "", KeyType::Text, {}}, - {3, 9, 1, 1, "_", "", KeyType::Text, {}}, + {0x105, u'\0', KeyType::Function, 4, 0, 1, 1, "⬆", "L2", {L2, None}}, + {KC_SYM1, u'\0', KeyType::Function, 4, 1, 1, 1, "@#:", "△", {Triangle, None}}, // TODO + {KC_ACCENTS, u'\0', KeyType::Function, 4, 2, 1, 1, "à", "", {None, None}}, // TODO + {0x20, u' ', KeyType::Character, 4, 3, 4, 1, "Space", "△", {Triangle, None}}, + {0x00, u'\0', KeyType::Disabled, 4, 7, 1, 1, "", "", {None, None}}, + {0x08, u'\0', KeyType::Function, 4, 8, 2, 1, "⇦", "□", {Square, None}, true}, // Row 5 - {4, 0, 1, 1, "⇧", "L2", KeyType::Shift, {L2}}, - {4, 1, 1, 1, "@#:", "L2+△", KeyType::Symbols1Layout, {L2, Triangle}}, - {4, 2, 1, 1, "à", "L3", KeyType::AccentLettersLayout, {L3}}, - {4, 3, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, - //{4, 4, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, - //{4, 5, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, - //{4, 6, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, - {4, 7, 1, 1, "", "", KeyType::Disabled, {}}, - {4, 8, 2, 1, "⇦", "□", KeyType::Backspace, {Square}}, - //{4, 8, 2, 1, "⇦", "□", KeyType::Backspace, {Square}}, - - // Row 6 - {5, 0, 1, 1, "▲", "", KeyType::CursorUp, {Up}}, - {5, 1, 1, 1, "▼", "", KeyType::CursorDown, {Down}}, - {5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft, {L1}}, - {5, 3, 1, 1, "▶", "R1", KeyType::CursorRight, {R1}}, - {5, 4, 1, 1, "KB", "", KeyType::ToggleKeyboard, {}}, - {5, 5, 1, 1, "...", "", KeyType::MoreOptions, {}}, - {5, 6, 1, 1, "+/⊗", "R3", KeyType::ControllerAction, {R3}}, - {5, 7, 1, 1, "", "", KeyType::Disabled, {}}, - {5, 8, 2, 1, "Done", "R2", KeyType::Done, {R2}}, - //{5, 9, 2, 1, "Done", "R2", KeyType::Done, {R2}}, -}; -// From PS5 -const std::vector kLayoutEnSymbols1 = { - // Row 1 - {0, 0, 1, 1, "!", "", KeyType::Text, {}}, - {0, 1, 1, 1, "?", "", KeyType::Text, {}}, - {0, 2, 1, 1, "\"", "", KeyType::Text, {}}, - {0, 3, 1, 1, "'", "", KeyType::Text, {}}, - {0, 4, 1, 1, "#", "", KeyType::Text, {}}, - {0, 5, 1, 1, "%", "", KeyType::Text, {}}, - {0, 6, 1, 1, "(", "", KeyType::Text, {}}, - {0, 7, 1, 1, ")", "", KeyType::Text, {}}, - {0, 8, 1, 1, "()", "", KeyType::Text, {}}, - {0, 9, 1, 1, "/", "", KeyType::Text, {}}, - - // Row 2 - {1, 0, 1, 1, "-", "", KeyType::Text, {}}, - {1, 1, 1, 1, "_", "", KeyType::Text, {}}, - {1, 2, 1, 1, ",", "", KeyType::Text, {}}, - {1, 3, 1, 1, ".", "", KeyType::Text, {}}, - {1, 4, 1, 1, ":", "", KeyType::Text, {}}, - {1, 5, 1, 1, ";", "", KeyType::Text, {}}, - {1, 6, 1, 1, "*", "", KeyType::Text, {}}, - {1, 7, 1, 1, "&", "", KeyType::Text, {}}, - {1, 8, 1, 1, "+", "", KeyType::Text, {}}, - {1, 9, 1, 1, "=", "", KeyType::Text, {}}, - - // Row 3 - {2, 0, 1, 1, "<", "", KeyType::Text, {}}, - {2, 1, 1, 1, ">", "", KeyType::Text, {}}, - {2, 2, 1, 1, "@", "", KeyType::Text, {}}, - {2, 3, 1, 1, "[", "", KeyType::Text, {}}, - {2, 4, 1, 1, "]", "", KeyType::Text, {}}, - {2, 5, 1, 1, "[]", "", KeyType::Text, {}}, - {2, 6, 1, 1, "{", "", KeyType::Text, {}}, - {2, 7, 1, 1, "}", "", KeyType::Text, {}}, - {2, 8, 1, 1, "{}", "", KeyType::Text, {}}, - {2, 9, 1, 2, "→", "", KeyType::Symbols2Layout, {}}, - - // Row 4 - {3, 0, 1, 1, "\\", "", KeyType::Text, {}}, - {3, 1, 1, 1, "|", "", KeyType::Text, {}}, - {3, 2, 1, 1, "^", "", KeyType::Text, {}}, - {3, 3, 1, 1, "`", "", KeyType::Text, {}}, - {3, 4, 1, 1, "$", "", KeyType::Text, {}}, - {3, 5, 1, 1, "€", "", KeyType::Text, {}}, - {3, 6, 1, 1, "£", "", KeyType::Text, {}}, - {3, 7, 1, 1, "¥", "", KeyType::Text, {}}, - {3, 8, 1, 1, "₩", "", KeyType::Text, {}}, - //{3, 9, 1, 2, "→", "", KeyType::Symbols2Layout,{}}, - - // Row 5 - {4, 0, 1, 1, "", "", KeyType::Disabled, {}}, - {4, 1, 1, 1, "ABC", "L2+△", KeyType::LettersLayout, {L2, Triangle}}, - {4, 2, 1, 1, "", "", KeyType::Disabled, {}}, - {4, 3, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, - //{4, 4, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, - //{4, 5, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, - //{4, 6, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, - {4, 7, 1, 1, "", "", KeyType::Disabled, {}}, - {4, 8, 2, 1, "⇦", "□", KeyType::Backspace, {Square}}, - //{4, 9, 2, 1, "⇦", "□", KeyType::Backspace, {Square}}, - - // Row 6 - {5, 0, 1, 1, "▲", "", KeyType::CursorUp, {Up}}, - {5, 1, 1, 1, "▼", "", KeyType::CursorDown, {Down}}, - {5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft, {L1}}, - {5, 3, 1, 1, "▶", "R1", KeyType::CursorRight, {R1}}, - {5, 4, 1, 1, "KB", "", KeyType::ToggleKeyboard, {}}, - {5, 5, 1, 1, "...", "", KeyType::MoreOptions, {}}, - {5, 6, 1, 1, "+/⊗", "R3", KeyType::ControllerAction, {R3}}, - {5, 7, 1, 1, "", "", KeyType::Disabled, {}}, - {5, 8, 2, 1, "Done", "R2", KeyType::Done, {R2}}, - //{5, 9, 2, 1, "Done", "R2", KeyType::Done, {R2}}, + {0xF020, u'\0', KeyType::Function, 5, 0, 1, 1, "▲", "", {Up, None}}, + {0xF021, u'\0', KeyType::Function, 5, 1, 1, 1, "▼", "", {Down, None}}, + {0xF022, u'\0', KeyType::Function, 5, 2, 1, 1, "◀", "L1", {L1, None}}, + {0xF023, u'\0', KeyType::Function, 5, 3, 1, 1, "▶", "R1", {R1, None}}, + {KC_KB, u'\0', KeyType::Function, 5, 4, 1, 1, "KB", "", {None, None}}, // TODO + {KC_OPT, u'\0', KeyType::Function, 5, 5, 1, 1, "...", "", {None, None}}, // TODO + {KC_GYRO, u'\0', KeyType::Function, 5, 6, 1, 1, "+/⊗", "R3", {R3, None}}, // TODO + {0x0000, u'\0', KeyType::Disabled, 5, 7, 1, 1, "", "", {None, None}}, + {0x0D, u'\r', KeyType::Function, 5, 8, 2, 1, "Done", "R2", {R2, None}}, }; // From PS5 -const std::vector kLayoutEnSymbols2 = { +const std::vector kLayoutEnSymbols1 = { // Row 1 - {0, 0, 1, 1, "“", "", KeyType::Text, {}}, - {0, 1, 1, 1, "”", "", KeyType::Text, {}}, - {0, 2, 1, 1, "„", "", KeyType::Text, {}}, - {0, 3, 1, 1, "¡", "", KeyType::Text, {}}, - {0, 4, 1, 1, "‼", "", KeyType::Text, {}}, - {0, 5, 1, 1, "¿", "", KeyType::Text, {}}, - {0, 6, 1, 1, "⁇", "", KeyType::Text, {}}, - {0, 7, 1, 1, "~", "", KeyType::Text, {}}, - {0, 8, 1, 1, "·", "", KeyType::Text, {}}, - {0, 9, 1, 1, "", "", KeyType::Disabled, {}}, + {0x21, u'!', KeyType::Character, 0, 0, 1, 1, "!", "", {None, None}}, + {0x3F, u'?', KeyType::Character, 0, 1, 1, 1, "?", "", {None, None}}, + {0x22, u'"', KeyType::Character, 0, 2, 1, 1, "\"", "", {None, None}}, + {0x27, u'\'', KeyType::Character, 0, 3, 1, 1, "'", "", {None, None}}, + {0x23, u'#', KeyType::Character, 0, 4, 1, 1, "#", "", {None, None}}, + {0x25, u'%', KeyType::Character, 0, 5, 1, 1, "%", "", {None, None}}, + {0x28, u'(', KeyType::Character, 0, 6, 1, 1, "(", "", {None, None}}, + {0x29, u')', KeyType::Character, 0, 7, 1, 1, ")", "", {None, None}}, + {0xF001, u'\0', KeyType::Function, 0, 8, 1, 1, "()", "", {None, None}}, + {0x2F, u'/', KeyType::Character, 0, 9, 1, 1, "/", "", {None, None}}, // Row 2 - {1, 0, 1, 1, "×", "", KeyType::Text, {}}, - {1, 1, 1, 1, "÷", "", KeyType::Text, {}}, - {1, 2, 1, 1, "‹", "", KeyType::Text, {}}, - {1, 3, 1, 1, "›", "", KeyType::Text, {}}, - {1, 4, 1, 1, "«", "", KeyType::Text, {}}, - {1, 5, 1, 1, "»", "", KeyType::Text, {}}, - {1, 6, 1, 1, "º", "", KeyType::Text, {}}, - {1, 7, 1, 1, "ª", "", KeyType::Text, {}}, - {1, 8, 1, 1, "°", "", KeyType::Text, {}}, - {1, 9, 1, 1, "§", "", KeyType::Text, {}}, + {0x2D, u'-', KeyType::Character, 1, 0, 1, 1, "-", "", {None, None}}, + {0x5F, u'_', KeyType::Character, 1, 1, 1, 1, "_", "", {None, None}}, + {0x2C, u',', KeyType::Character, 1, 2, 1, 1, ",", "", {None, None}}, + {0x2E, u'.', KeyType::Character, 1, 3, 1, 1, ".", "", {None, None}}, + {0x3A, u':', KeyType::Character, 1, 4, 1, 1, ":", "", {None, None}}, + {0x3B, u';', KeyType::Character, 1, 5, 1, 1, ";", "", {None, None}}, + {0x2A, u'*', KeyType::Character, 1, 6, 1, 1, "*", "", {None, None}}, + {0x26, u'&', KeyType::Character, 1, 7, 1, 1, "&", "", {None, None}}, + {0x2B, u'+', KeyType::Character, 1, 8, 1, 1, "+", "", {None, None}}, + {0x3D, u'=', KeyType::Character, 1, 9, 1, 1, "=", "", {None, None}}, // Row 3 - {2, 0, 1, 2, "←", "", KeyType::Symbols1Layout, {}}, - {2, 1, 1, 1, "¦", "", KeyType::Text, {}}, - {2, 2, 1, 1, "µ", "", KeyType::Text, {}}, - {2, 3, 1, 1, "¬", "", KeyType::Text, {}}, - {2, 4, 1, 1, "¹", "", KeyType::Text, {}}, - {2, 5, 1, 1, "²", "", KeyType::Text, {}}, - {2, 6, 1, 1, "³", "", KeyType::Text, {}}, - {2, 7, 1, 1, "¼", "", KeyType::Text, {}}, - {2, 8, 1, 1, "½", "", KeyType::Text, {}}, - {2, 9, 1, 1, "¾", "", KeyType::Text, {}}, + {0x3C, u'<', KeyType::Character, 2, 0, 1, 1, "<", "", {None, None}}, + {0x3E, u'>', KeyType::Character, 2, 1, 1, 1, ">", "", {None, None}}, + {0x40, u'@', KeyType::Character, 2, 2, 1, 1, "@", "", {None, None}}, + {0x5B, u'[', KeyType::Character, 2, 3, 1, 1, "[", "", {None, None}}, + {0x5D, u']', KeyType::Character, 2, 4, 1, 1, "]", "", {None, None}}, + {0xF002, u'\0', KeyType::Function, 2, 5, 1, 1, "[]", "", {None, None}}, + {0x7B, u'{', KeyType::Character, 2, 6, 1, 1, "{", "", {None, None}}, + {0x7D, u'}', KeyType::Character, 2, 7, 1, 1, "}", "", {None, None}}, + {0xF004, u'\0', KeyType::Function, 2, 8, 1, 1, "{}", "", {None, None}}, + {KC_SYM2, u'\0', KeyType::Function, 2, 9, 1, 2, "→", "", {None, None}}, // Row 4 - //{3, 0, 1, 1, "←", "", KeyType::Symbols1Layout, {}}, - {3, 1, 1, 1, "¢", "", KeyType::Text, {}}, - {3, 2, 1, 1, "¤", "", KeyType::Text, {}}, - {3, 3, 1, 1, "’", "", KeyType::Text, {}}, // not sure - {3, 4, 1, 1, "‘", "", KeyType::Text, {}}, // not sure - {3, 5, 1, 1, "‛", "", KeyType::Text, {}}, // not sure - {3, 6, 1, 1, "‚", "", KeyType::Text, {}}, // not sure - {3, 7, 1, 1, "№", "", KeyType::Text, {}}, - {3, 8, 1, 1, "", "", KeyType::Disabled, {}}, - {3, 9, 1, 1, "", "", KeyType::Disabled, {}}, + {0x5C, u'\\', KeyType::Character, 3, 0, 1, 1, "\\", "", {None, None}}, + {0x7C, u'|', KeyType::Character, 3, 1, 1, 1, "|", "", {None, None}}, + {0x5E, u'^', KeyType::Character, 3, 2, 1, 1, "^", "", {None, None}}, + {0x60, u'`', KeyType::Character, 3, 3, 1, 1, "`", "", {None, None}}, + {0x24, u'$', KeyType::Character, 3, 4, 1, 1, "$", "", {None, None}}, + {0x20AC, u'\u20AC', KeyType::Character, 3, 5, 1, 1, "€", "", {None, None}}, + {0x00A3, u'\u00A3', KeyType::Character, 3, 6, 1, 1, "£", "", {None, None}}, + {0x00A5, u'\u00A5', KeyType::Character, 3, 7, 1, 1, "¥", "", {None, None}}, + {0x20A9, u'\u20A9', KeyType::Character, 3, 8, 1, 1, "₩", "", {None, None}}, // Row 5 - {4, 0, 1, 1, "", "", KeyType::Disabled, {}}, - {4, 1, 1, 1, "ABC", "L2+△", KeyType::LettersLayout, {L2, Triangle}}, - {4, 2, 1, 1, "", "", KeyType::Disabled, {}}, - {4, 3, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, - //{4, 4, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, - //{4, 5, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, - //{4, 6, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, - {4, 7, 1, 1, "", "", KeyType::Disabled, {}}, - {4, 8, 2, 1, "⇦", "□", KeyType::Backspace, {Square}}, - //{4, 9, 2, 1, "⇦", "□", KeyType::Backspace, {Square}}, + {0x0000, u'\0', KeyType::Disabled, 4, 0, 1, 1, "", "", {None, None}}, + {KC_LETTERS, u'\0', KeyType::Function, 4, 1, 1, 1, "ABC", "L2+△", {L2, Triangle}}, // TODO: + {0x0000, u'\0', KeyType::Disabled, 4, 2, 1, 1, "", "", {None, None}}, + {0x0020, u' ', KeyType::Character, 4, 3, 4, 1, "Space", "△", {Triangle, None}}, + {0x0000, u'\0', KeyType::Disabled, 4, 7, 1, 1, "", "", {None, None}}, + {0x0008, u'\0', KeyType::Function, 4, 8, 2, 1, "⇦", "□", {Square, None}, true}, // Row 6 - {5, 0, 1, 1, "▲", "", KeyType::CursorUp, {Up}}, - {5, 1, 1, 1, "▼", "", KeyType::CursorDown, {Down}}, - {5, 2, 1, 1, "◀", "L1", KeyType::CursorLeft, {L1}}, - {5, 3, 1, 1, "▶", "R1", KeyType::CursorRight, {R1}}, - {5, 4, 1, 1, "KB", "", KeyType::ToggleKeyboard, {}}, - {5, 5, 1, 1, "...", "", KeyType::MoreOptions, {}}, - {5, 6, 1, 1, "+/⊗", "R3", KeyType::ControllerAction, {R3}}, - {5, 7, 1, 1, "", "", KeyType::Disabled, {}}, - {5, 8, 2, 1, "Done", "R2", KeyType::Done, {R2}}, - //{5, 9, 2, 1, "Done", "R2", KeyType::Done, {R2}}, + {0xF020, u'\0', KeyType::Function, 5, 0, 1, 1, "▲", "", {Up, None}}, + {0xF021, u'\0', KeyType::Function, 5, 1, 1, 1, "▼", "", {Down, None}}, + {0xF022, u'\0', KeyType::Function, 5, 2, 1, 1, "◀", "L1", {L1, None}}, + {0xF023, u'\0', KeyType::Function, 5, 3, 1, 1, "▶", "R1", {R1, None}}, + {KC_KB, u'\0', KeyType::Function, 5, 4, 1, 1, "KB", "", {None, None}}, // TODO: + {KC_OPT, u'\0', KeyType::Function, 5, 5, 1, 1, "...", "", {None, None}}, // TODO: + {KC_GYRO, u'\0', KeyType::Function, 5, 6, 1, 1, "+/⊗", "R3", {R3, None}}, // TODO: + {0x0000, u'\0', KeyType::Disabled, 5, 7, 1, 1, "", "", {None, None}}, + {0x000D, u'\r', KeyType::Function, 5, 8, 2, 1, "Done", "R2", {R2, None}}, }; -const std::vector kLayoutEnAccentLettersUppercase = { - // Row 0 - {0, 0, 1, 1, "À", "", KeyType::Text, {}}, - {0, 1, 1, 1, "Á", "", KeyType::Text, {}}, - {0, 2, 1, 1, "Â", "", KeyType::Text, {}}, - {0, 3, 1, 1, "Ã", "", KeyType::Text, {}}, - {0, 4, 1, 1, "Ä", "", KeyType::Text, {}}, - {0, 5, 1, 1, "Å", "", KeyType::Text, {}}, - {0, 6, 1, 1, "Ą", "", KeyType::Text, {}}, - {0, 7, 1, 1, "Æ", "", KeyType::Text, {}}, - {0, 8, 1, 1, "Ç", "", KeyType::Text, {}}, - {0, 9, 1, 1, "Ć", "", KeyType::Text, {}}, - +// From PS5 +const std::vector kLayoutEnSymbols2 = { // Row 1 - {1, 0, 1, 1, "È", "", KeyType::Text, {}}, - {1, 1, 1, 1, "É", "", KeyType::Text, {}}, - {1, 2, 1, 1, "Ê", "", KeyType::Text, {}}, - {1, 3, 1, 1, "Ë", "", KeyType::Text, {}}, - {1, 4, 1, 1, "Ę", "", KeyType::Text, {}}, - {1, 5, 1, 1, "Ğ", "", KeyType::Text, {}}, - {1, 6, 1, 1, "Ì", "", KeyType::Text, {}}, - {1, 7, 1, 1, "Í", "", KeyType::Text, {}}, - {1, 8, 1, 1, "Î", "", KeyType::Text, {}}, - {1, 9, 1, 1, "Ï", "", KeyType::Text, {}}, + {0x201C, u'“', KeyType::Character, 0, 0, 1, 1, "“", "", {None, None}}, + {0x201D, u'”', KeyType::Character, 0, 1, 1, 1, "”", "", {None, None}}, + {0x201E, u'„', KeyType::Character, 0, 2, 1, 1, "„", "", {None, None}}, + {0x00A1, u'¡', KeyType::Character, 0, 3, 1, 1, "¡", "", {None, None}}, + {0xF013, u'\0', KeyType::Function, 0, 4, 1, 1, "¡!", "", {None, None}}, + {0x00BF, u'¿', KeyType::Character, 0, 5, 1, 1, "¿", "", {None, None}}, + {0xF014, u'\0', KeyType::Function, 0, 6, 1, 1, "¿?", "", {None, None}}, + {0x007E, u'~', KeyType::Character, 0, 7, 1, 1, "~", "", {None, None}}, + {0x00B7, u'·', KeyType::Character, 0, 8, 1, 1, "·", "", {None, None}}, + {0x0000, u'\0', KeyType::Disabled, 0, 9, 1, 1, "", "", {None, None}}, // Row 2 - {2, 0, 1, 1, "İ", "", KeyType::Text, {}}, - {2, 1, 1, 1, "Ł", "", KeyType::Text, {}}, - {2, 2, 1, 1, "Ñ", "", KeyType::Text, {}}, - {2, 3, 1, 1, "Ń", "", KeyType::Text, {}}, - {2, 4, 1, 1, "Ò", "", KeyType::Text, {}}, - {2, 5, 1, 1, "Ó", "", KeyType::Text, {}}, - {2, 6, 1, 1, "Ô", "", KeyType::Text, {}}, - {2, 7, 1, 1, "Õ", "", KeyType::Text, {}}, - {2, 8, 1, 1, "Ö", "", KeyType::Text, {}}, - {2, 9, 1, 1, "Ø", "", KeyType::Text, {}}, + {0x00D7, u'×', KeyType::Character, 1, 0, 1, 1, "×", "", {None, None}}, + {0x00F7, u'÷', KeyType::Character, 1, 1, 1, 1, "÷", "", {None, None}}, + {0x2039, u'‹', KeyType::Character, 1, 2, 1, 1, "‹", "", {None, None}}, + {0x203A, u'›', KeyType::Character, 1, 3, 1, 1, "›", "", {None, None}}, + {0x00AB, u'«', KeyType::Character, 1, 4, 1, 1, "«", "", {None, None}}, + {0x00BB, u'»', KeyType::Character, 1, 5, 1, 1, "»", "", {None, None}}, + {0x00BA, u'º', KeyType::Character, 1, 6, 1, 1, "º", "", {None, None}}, + {0x00AA, u'ª', KeyType::Character, 1, 7, 1, 1, "ª", "", {None, None}}, + {0x00B0, u'°', KeyType::Character, 1, 8, 1, 1, "°", "", {None, None}}, + {0x00A7, u'§', KeyType::Character, 1, 9, 1, 1, "§", "", {None, None}}, // Row 3 - {3, 0, 1, 1, "Œ", "", KeyType::Text, {}}, - {3, 1, 1, 1, "Ś", "", KeyType::Text, {}}, - {3, 2, 1, 1, "Ş", "", KeyType::Text, {}}, - {3, 3, 1, 1, "Š", "", KeyType::Text, {}}, - {3, 4, 1, 1, "ß", "", KeyType::Text, {}}, - {3, 5, 1, 1, "Ù", "", KeyType::Text, {}}, - {3, 6, 1, 1, "Ú", "", KeyType::Text, {}}, - {3, 7, 1, 1, "Û", "", KeyType::Text, {}}, - {3, 8, 1, 1, "Ü", "", KeyType::Text, {}}, - {3, 9, 1, 1, "Ý", "", KeyType::Text, {}}, + {KC_SYM1, u'\0', KeyType::Function, 2, 0, 1, 2, "←", "", {None, None}}, + {0x00A6, u'¦', KeyType::Character, 2, 1, 1, 1, "¦", "", {None, None}}, + {0x00B5, u'µ', KeyType::Character, 2, 2, 1, 1, "µ", "", {None, None}}, + {0x00AC, u'¬', KeyType::Character, 2, 3, 1, 1, "¬", "", {None, None}}, + {0x00B9, u'¹', KeyType::Character, 2, 4, 1, 1, "¹", "", {None, None}}, + {0x00B2, u'²', KeyType::Character, 2, 5, 1, 1, "²", "", {None, None}}, + {0x00B3, u'³', KeyType::Character, 2, 6, 1, 1, "³", "", {None, None}}, + {0x00BC, u'¼', KeyType::Character, 2, 7, 1, 1, "¼", "", {None, None}}, + {0x00BD, u'½', KeyType::Character, 2, 8, 1, 1, "½", "", {None, None}}, + {0x00BE, u'¾', KeyType::Character, 2, 9, 1, 1, "¾", "", {None, None}}, // Row 4 - {4, 0, 1, 1, "Ÿ", "", KeyType::Text, {}}, - {4, 1, 1, 1, "Ź", "", KeyType::Text, {}}, - {4, 2, 1, 1, "Ż", "", KeyType::Text, {}}, - {4, 3, 1, 1, "Ž", "", KeyType::Text, {}}, - {4, 4, 1, 1, "Ð", "", KeyType::Text, {}}, - {4, 5, 1, 1, "Þ", "", KeyType::Text, {}}, - {4, 6, 1, 1, "", "", KeyType::Disabled, {}}, - {4, 7, 1, 1, "", "", KeyType::Disabled, {}}, - {4, 8, 1, 1, "", "", KeyType::Disabled, {}}, - {4, 9, 1, 1, "", "", KeyType::Disabled, {}}, + {0x00A2, u'¢', KeyType::Character, 3, 1, 1, 1, "¢", "", {None, None}}, + {0x00A4, u'¤', KeyType::Character, 3, 2, 1, 1, "¤", "", {None, None}}, + {0x2019, u'’', KeyType::Character, 3, 3, 1, 1, "’", "", {None, None}}, + {0x2018, u'‘', KeyType::Character, 3, 4, 1, 1, "‘", "", {None, None}}, + {0x201B, u'‛', KeyType::Character, 3, 5, 1, 1, "‛", "", {None, None}}, + {0x201A, u'‚', KeyType::Character, 3, 6, 1, 1, "‚", "", {None, None}}, + {0x2116, u'№', KeyType::Character, 3, 7, 1, 1, "№", "", {None, None}}, + {0x0000, u'\0', KeyType::Disabled, 3, 8, 1, 1, "", "", {None, None}}, + {0x0000, u'\0', KeyType::Disabled, 3, 9, 1, 1, "", "", {None, None}}, // Row 5 - {5, 0, 1, 1, "⬆", "L2", KeyType::Shift, {L2}}, - {5, 1, 1, 1, "@#:", "L2+△", KeyType::Symbols1Layout, {L3, Triangle}}, - {5, 2, 1, 1, "à", "L3", KeyType::AccentLettersLayout, {L3}}, - {5, 3, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, - //{4, 4, 4, 1, "Space", "△", KeyType::Space,{Triangle}}, - //{4, 5, 4, 1, "Space", "△", KeyType::Space,{Triangle}}, - //{4, 6, 4, 1, "Space", "△", KeyType::Space,{Triangle}}, - {4, 7, 1, 1, "", "", KeyType::Disabled, {}}, - {5, 8, 2, 1, "⇦", "□", KeyType::Backspace, {Square}}, - //{4, 9, 2, 1, "⇦", "□", KeyType::Backspace,{Square}}, + {0x0000, u'\0', KeyType::Disabled, 4, 0, 1, 1, "", "", {None, None}}, + {KC_LETTERS, u'\0', KeyType::Function, 4, 1, 1, 1, "ABC", "L2+△", {L2, Triangle}}, + {0x0000, u'\0', KeyType::Disabled, 4, 2, 1, 1, "", "", {None, None}}, + {0x20, u' ', KeyType::Character, 4, 3, 4, 1, "Space", "△", {Triangle, None}}, + {0x0000, u'\0', KeyType::Disabled, 4, 7, 1, 1, "", "", {None, None}}, + {0x08, u'\0', KeyType::Function, 4, 8, 2, 1, "⇦", "□", {Square, None}, true}, // Row 6 - {6, 0, 1, 1, "▲", "", KeyType::CursorUp, {Up}}, - {6, 1, 1, 1, "▼", "", KeyType::CursorDown, {Down}}, - {6, 2, 1, 1, "◀", "L1", KeyType::CursorLeft, {L1}}, - {6, 3, 1, 1, "▶", "R1", KeyType::CursorRight, {R1}}, - {6, 4, 1, 1, "KB", "", KeyType::ToggleKeyboard, {}}, - {6, 5, 1, 1, "...", "", KeyType::MoreOptions, {}}, - {6, 6, 1, 1, "+/⊗", "R3", KeyType::ControllerAction, {R3}}, - {5, 7, 1, 1, "", "", KeyType::Disabled, {}}, - {6, 8, 2, 1, "Done", "R2", KeyType::Done, {R2}}, - //{5, 9, 2, 1, "Done", "R2", KeyType::Done,{R2}}, + {0xF020, u'\0', KeyType::Function, 5, 0, 1, 1, "▲", "", {Up, None}}, + {0xF021, u'\0', KeyType::Function, 5, 1, 1, 1, "▼", "", {Down, None}}, + {0xF022, u'\0', KeyType::Function, 5, 2, 1, 1, "◀", "L1", {L1, None}}, + {0xF023, u'\0', KeyType::Function, 5, 3, 1, 1, "▶", "R1", {R1, None}}, + {KC_KB, u'\0', KeyType::Function, 5, 4, 1, 1, "KB", "", {None, None}}, // TODO + {KC_OPT, u'\0', KeyType::Function, 5, 5, 1, 1, "...", "", {None, None}}, // TODO + {KC_GYRO, u'\0', KeyType::Function, 5, 6, 1, 1, "+/⊗", "R3", {R3, None}}, // TODO + {0x0000, u'\0', KeyType::Disabled, 5, 7, 1, 1, "", "", {None, None}}, + {0x0D, u'\r', KeyType::Function, 5, 8, 2, 1, "Done", "R2", {R2, None}}, + }; -const std::vector kLayoutEnAccentLettersLowercase = { +const std::vector kLayoutEnAccentLettersUppercase = { // Row 0 - {0, 0, 1, 1, "à", "", KeyType::Text, {}}, - {0, 1, 1, 1, "á", "", KeyType::Text, {}}, - {0, 2, 1, 1, "â", "", KeyType::Text, {}}, - {0, 3, 1, 1, "ã", "", KeyType::Text, {}}, - {0, 4, 1, 1, "ä", "", KeyType::Text, {}}, - {0, 5, 1, 1, "å", "", KeyType::Text, {}}, - {0, 6, 1, 1, "ą", "", KeyType::Text, {}}, - {0, 7, 1, 1, "æ", "", KeyType::Text, {}}, - {0, 8, 1, 1, "ç", "", KeyType::Text, {}}, - {0, 9, 1, 1, "ć", "", KeyType::Text, {}}, + {0x00C0, u'À', KeyType::Character, 0, 0, 1, 1, "À", "", {None, None}}, + {0x00C1, u'Á', KeyType::Character, 0, 1, 1, 1, "Á", "", {None, None}}, + {0x00C2, u'Â', KeyType::Character, 0, 2, 1, 1, "Â", "", {None, None}}, + {0x00C3, u'Ã', KeyType::Character, 0, 3, 1, 1, "Ã", "", {None, None}}, + {0x00C4, u'Ä', KeyType::Character, 0, 4, 1, 1, "Ä", "", {None, None}}, + {0x00C5, u'Å', KeyType::Character, 0, 5, 1, 1, "Å", "", {None, None}}, + {0x0104, u'Ą', KeyType::Character, 0, 6, 1, 1, "Ą", "", {None, None}}, + {0x00C6, u'Æ', KeyType::Character, 0, 7, 1, 1, "Æ", "", {None, None}}, + {0x00C7, u'Ç', KeyType::Character, 0, 8, 1, 1, "Ç", "", {None, None}}, + {0x0106, u'Ć', KeyType::Character, 0, 9, 1, 1, "Ć", "", {None, None}}, // Row 1 - {1, 0, 1, 1, "è", "", KeyType::Text, {}}, - {1, 1, 1, 1, "é", "", KeyType::Text, {}}, - {1, 2, 1, 1, "ê", "", KeyType::Text, {}}, - {1, 3, 1, 1, "ë", "", KeyType::Text, {}}, - {1, 4, 1, 1, "ę", "", KeyType::Text, {}}, - {1, 5, 1, 1, "ğ", "", KeyType::Text, {}}, - {1, 6, 1, 1, "ì", "", KeyType::Text, {}}, - {1, 7, 1, 1, "í", "", KeyType::Text, {}}, - {1, 8, 1, 1, "î", "", KeyType::Text, {}}, - {1, 9, 1, 1, "ï", "", KeyType::Text, {}}, + {0x00C8, u'È', KeyType::Character, 1, 0, 1, 1, "È", "", {None, None}}, + {0x00C9, u'É', KeyType::Character, 1, 1, 1, 1, "É", "", {None, None}}, + {0x00CA, u'Ê', KeyType::Character, 1, 2, 1, 1, "Ê", "", {None, None}}, + {0x00CB, u'Ë', KeyType::Character, 1, 3, 1, 1, "Ë", "", {None, None}}, + {0x0118, u'Ę', KeyType::Character, 1, 4, 1, 1, "Ę", "", {None, None}}, + {0x011E, u'Ğ', KeyType::Character, 1, 5, 1, 1, "Ğ", "", {None, None}}, + {0x00CC, u'Ì', KeyType::Character, 1, 6, 1, 1, "Ì", "", {None, None}}, + {0x00CD, u'Í', KeyType::Character, 1, 7, 1, 1, "Í", "", {None, None}}, + {0x00CE, u'Î', KeyType::Character, 1, 8, 1, 1, "Î", "", {None, None}}, + {0x00CF, u'Ï', KeyType::Character, 1, 9, 1, 1, "Ï", "", {None, None}}, // Row 2 - {2, 0, 1, 1, "ı", "", KeyType::Text, {}}, - {2, 1, 1, 1, "ł", "", KeyType::Text, {}}, - {2, 2, 1, 1, "ñ", "", KeyType::Text, {}}, - {2, 3, 1, 1, "ń", "", KeyType::Text, {}}, - {2, 4, 1, 1, "ò", "", KeyType::Text, {}}, - {2, 5, 1, 1, "ó", "", KeyType::Text, {}}, - {2, 6, 1, 1, "ô", "", KeyType::Text, {}}, - {2, 7, 1, 1, "õ", "", KeyType::Text, {}}, - {2, 8, 1, 1, "ö", "", KeyType::Text, {}}, - {2, 9, 1, 1, "ø", "", KeyType::Text, {}}, + {0x0130, u'İ', KeyType::Character, 2, 0, 1, 1, "İ", "", {None, None}}, + {0x0141, u'Ł', KeyType::Character, 2, 1, 1, 1, "Ł", "", {None, None}}, + {0x00D1, u'Ñ', KeyType::Character, 2, 2, 1, 1, "Ñ", "", {None, None}}, + {0x0143, u'Ń', KeyType::Character, 2, 3, 1, 1, "Ń", "", {None, None}}, + {0x00D2, u'Ò', KeyType::Character, 2, 4, 1, 1, "Ò", "", {None, None}}, + {0x00D3, u'Ó', KeyType::Character, 2, 5, 1, 1, "Ó", "", {None, None}}, + {0x00D4, u'Ô', KeyType::Character, 2, 6, 1, 1, "Ô", "", {None, None}}, + {0x00D5, u'Õ', KeyType::Character, 2, 7, 1, 1, "Õ", "", {None, None}}, + {0x00D6, u'Ö', KeyType::Character, 2, 8, 1, 1, "Ö", "", {None, None}}, + {0x00D8, u'Ø', KeyType::Character, 2, 9, 1, 1, "Ø", "", {None, None}}, // Row 3 - {3, 0, 1, 1, "œ", "", KeyType::Text, {}}, - {3, 1, 1, 1, "ś", "", KeyType::Text, {}}, - {3, 2, 1, 1, "ş", "", KeyType::Text, {}}, - {3, 3, 1, 1, "š", "", KeyType::Text, {}}, - {3, 4, 1, 1, "ß", "", KeyType::Text, {}}, - {3, 5, 1, 1, "ù", "", KeyType::Text, {}}, - {3, 6, 1, 1, "ú", "", KeyType::Text, {}}, - {3, 7, 1, 1, "û", "", KeyType::Text, {}}, - {3, 8, 1, 1, "ü", "", KeyType::Text, {}}, - {3, 9, 1, 1, "ý", "", KeyType::Text, {}}, + {0x0152, u'Œ', KeyType::Character, 3, 0, 1, 1, "Œ", "", {None, None}}, + {0x015A, u'Ś', KeyType::Character, 3, 1, 1, 1, "Ś", "", {None, None}}, + {0x015E, u'Ş', KeyType::Character, 3, 2, 1, 1, "Ş", "", {None, None}}, + {0x0160, u'Š', KeyType::Character, 3, 3, 1, 1, "Š", "", {None, None}}, + {0x00DF, u'ß', KeyType::Character, 3, 4, 1, 1, "ß", "", {None, None}}, + {0x00D9, u'Ù', KeyType::Character, 3, 5, 1, 1, "Ù", "", {None, None}}, + {0x00DA, u'Ú', KeyType::Character, 3, 6, 1, 1, "Ú", "", {None, None}}, + {0x00DB, u'Û', KeyType::Character, 3, 7, 1, 1, "Û", "", {None, None}}, + {0x00DC, u'Ü', KeyType::Character, 3, 8, 1, 1, "Ü", "", {None, None}}, + {0x00DD, u'Ý', KeyType::Character, 3, 9, 1, 1, "Ý", "", {None, None}}, // Row 4 - {4, 0, 1, 1, "ÿ", "", KeyType::Text, {}}, - {4, 1, 1, 1, "ź", "", KeyType::Text, {}}, - {4, 2, 1, 1, "ż", "", KeyType::Text, {}}, - {4, 3, 1, 1, "ž", "", KeyType::Text, {}}, - {4, 4, 1, 1, "ð", "", KeyType::Text, {}}, - {4, 5, 1, 1, "þ", "", KeyType::Text, {}}, - {4, 6, 1, 1, "", "", KeyType::Disabled, {}}, - {4, 7, 1, 1, "", "", KeyType::Disabled, {}}, - {4, 8, 1, 1, "", "", KeyType::Disabled, {}}, - {4, 9, 1, 1, "", "", KeyType::Disabled, {}}, + {0x0178, u'Ÿ', KeyType::Character, 4, 0, 1, 1, "Ÿ", "", {None, None}}, + {0x0179, u'Ź', KeyType::Character, 4, 1, 1, 1, "Ź", "", {None, None}}, + {0x017B, u'Ż', KeyType::Character, 4, 2, 1, 1, "Ż", "", {None, None}}, + {0x017D, u'Ž', KeyType::Character, 4, 3, 1, 1, "Ž", "", {None, None}}, + {0x00D0, u'Ð', KeyType::Character, 4, 4, 1, 1, "Ð", "", {None, None}}, + {0x00DE, u'Þ', KeyType::Character, 4, 5, 1, 1, "Þ", "", {None, None}}, + {0x0000, u'\0', KeyType::Disabled, 4, 6, 1, 1, "", "", {None, None}}, + {0x0000, u'\0', KeyType::Disabled, 4, 7, 1, 1, "", "", {None, None}}, + {0x0000, u'\0', KeyType::Disabled, 4, 8, 1, 1, "", "", {None, None}}, + {0x0000, u'\0', KeyType::Disabled, 4, 9, 1, 1, "", "", {None, None}}, // Row 5 - {5, 0, 1, 1, "⬆", "L2", KeyType::Shift, {L2}}, - {5, 1, 1, 1, "@#:", "L2+△", KeyType::Symbols1Layout, {L3, Triangle}}, - {5, 2, 1, 1, "à", "L3", KeyType::AccentLettersLayout, {L3}}, - {5, 3, 4, 1, "Space", "△", KeyType::Space, {Triangle}}, - //{4, 4, 4, 1, "Space", "△", KeyType::Space,{Triangle}}, - //{4, 5, 4, 1, "Space", "△", KeyType::Space,{Triangle}}, - //{4, 6, 4, 1, "Space", "△", KeyType::Space,{Triangle}}, - {4, 7, 1, 1, "", "", KeyType::Disabled, {}}, - {5, 8, 2, 1, "⇦", "□", KeyType::Backspace, {Square}}, - //{4, 9, 2, 1, "⇦", "□", KeyType::Backspace,{Square}}, + {0x0010, u'\0', KeyType::Function, 5, 0, 1, 1, "⬆", "L2", {L2, None}}, + {KC_LETTERS, u'\0', KeyType::Function, 5, 1, 1, 1, "ABC", "L2+△", {L3, Triangle}}, // TODO: + {0x0000, u'\0', KeyType::Disabled, 5, 2, 1, 1, "", "", {None, None}}, // TODO: + {0x0020, u' ', KeyType::Character, 5, 3, 4, 1, "Space", "△", {Triangle, None}}, + {0x0000, u'\0', KeyType::Disabled, 5, 7, 1, 1, "", "", {None, None}}, + {0x0008, u'\0', KeyType::Function, 5, 8, 2, 1, "⇦", "□", {Square, None}, true}, // Row 6 - {6, 0, 1, 1, "▲", "", KeyType::CursorUp, {Up}}, - {6, 1, 1, 1, "▼", "", KeyType::CursorDown, {Down}}, - {6, 2, 1, 1, "◀", "L1", KeyType::CursorLeft, {L1}}, - {6, 3, 1, 1, "▶", "R1", KeyType::CursorRight, {R1}}, - {6, 4, 1, 1, "KB", "", KeyType::ToggleKeyboard, {}}, - {6, 5, 1, 1, "...", "", KeyType::MoreOptions, {}}, - //{5, 5, 1, 1, "…", "", KeyType::MoreOptions,{}}, - {6, 6, 1, 1, "+/⊗", "R3", KeyType::ControllerAction, {R3}}, - {5, 7, 1, 1, "", "", KeyType::Disabled, {}}, - {6, 8, 2, 1, "Done", "R2", KeyType::Done, {R2}}, - //{5, 9, 2, 1, "Done", "R2", KeyType::Done,{R2}}, -}; \ No newline at end of file + {0xF020, u'\0', KeyType::Function, 6, 0, 1, 1, "▲", "", {Up, None}}, + {0xF021, u'\0', KeyType::Function, 6, 1, 1, 1, "▼", "", {Down, None}}, + {0xF022, u'\0', KeyType::Function, 6, 2, 1, 1, "◀", "L1", {L1, None}}, + {0xF023, u'\0', KeyType::Function, 6, 3, 1, 1, "▶", "R1", {R1, None}}, + {KC_KB, u'\0', KeyType::Function, 6, 4, 1, 1, "KB", "", {None, None}}, // TODO + {KC_OPT, u'\0', KeyType::Function, 6, 5, 1, 1, "...", "", {None, None}}, // TODO + {KC_GYRO, u'\0', KeyType::Function, 6, 6, 1, 1, "+/⊗", "R3", {R3, None}}, // TODO + {0x0000, u'\0', KeyType::Disabled, 6, 7, 1, 1, "", "", {None, None}}, + {0x000D, u'\r', KeyType::Function, 6, 8, 2, 1, "Done", "R2", {R2, None}}, +}; + +const std::vector kLayoutEnAccentLettersLowercase = { + // Row 0 + {0x00E0, u'à', KeyType::Character, 0, 0, 1, 1, "à", "", {None, None}}, + {0x00E1, u'á', KeyType::Character, 0, 1, 1, 1, "á", "", {None, None}}, + {0x00E2, u'â', KeyType::Character, 0, 2, 1, 1, "â", "", {None, None}}, + {0x00E3, u'ã', KeyType::Character, 0, 3, 1, 1, "ã", "", {None, None}}, + {0x00E4, u'ä', KeyType::Character, 0, 4, 1, 1, "ä", "", {None, None}}, + {0x00E5, u'å', KeyType::Character, 0, 5, 1, 1, "å", "", {None, None}}, + {0x0105, u'ą', KeyType::Character, 0, 6, 1, 1, "ą", "", {None, None}}, + {0x00E6, u'æ', KeyType::Character, 0, 7, 1, 1, "æ", "", {None, None}}, + {0x00E7, u'ç', KeyType::Character, 0, 8, 1, 1, "ç", "", {None, None}}, + {0x0107, u'ć', KeyType::Character, 0, 9, 1, 1, "ć", "", {None, None}}, + + // Row 1 + {0x00E8, u'è', KeyType::Character, 1, 0, 1, 1, "è", "", {None, None}}, + {0x00E9, u'é', KeyType::Character, 1, 1, 1, 1, "é", "", {None, None}}, + {0x00EA, u'ê', KeyType::Character, 1, 2, 1, 1, "ê", "", {None, None}}, + {0x00EB, u'ë', KeyType::Character, 1, 3, 1, 1, "ë", "", {None, None}}, + {0x0119, u'ę', KeyType::Character, 1, 4, 1, 1, "ę", "", {None, None}}, + {0x011F, u'ğ', KeyType::Character, 1, 5, 1, 1, "ğ", "", {None, None}}, + {0x00EC, u'ì', KeyType::Character, 1, 6, 1, 1, "ì", "", {None, None}}, + {0x00ED, u'í', KeyType::Character, 1, 7, 1, 1, "í", "", {None, None}}, + {0x00EE, u'î', KeyType::Character, 1, 8, 1, 1, "î", "", {None, None}}, + {0x00EF, u'ï', KeyType::Character, 1, 9, 1, 1, "ï", "", {None, None}}, + + // Row 2 + {0x0131, u'ı', KeyType::Character, 2, 0, 1, 1, "ı", "", {None, None}}, + {0x0142, u'ł', KeyType::Character, 2, 1, 1, 1, "ł", "", {None, None}}, + {0x00F1, u'ñ', KeyType::Character, 2, 2, 1, 1, "ñ", "", {None, None}}, + {0x0144, u'ń', KeyType::Character, 2, 3, 1, 1, "ń", "", {None, None}}, + {0x00F2, u'ò', KeyType::Character, 2, 4, 1, 1, "ò", "", {None, None}}, + {0x00F3, u'ó', KeyType::Character, 2, 5, 1, 1, "ó", "", {None, None}}, + {0x00F4, u'ô', KeyType::Character, 2, 6, 1, 1, "ô", "", {None, None}}, + {0x00F5, u'õ', KeyType::Character, 2, 7, 1, 1, "õ", "", {None, None}}, + {0x00F6, u'ö', KeyType::Character, 2, 8, 1, 1, "ö", "", {None, None}}, + {0x00F8, u'ø', KeyType::Character, 2, 9, 1, 1, "ø", "", {None, None}}, + + // Row 3 + {0x0153, u'œ', KeyType::Character, 3, 0, 1, 1, "œ", "", {None, None}}, + {0x015B, u'ś', KeyType::Character, 3, 1, 1, 1, "ś", "", {None, None}}, + {0x015F, u'ş', KeyType::Character, 3, 2, 1, 1, "ş", "", {None, None}}, + {0x0161, u'š', KeyType::Character, 3, 3, 1, 1, "š", "", {None, None}}, + {0x00DF, u'ß', KeyType::Character, 3, 4, 1, 1, "ß", "", {None, None}}, + {0x00F9, u'ù', KeyType::Character, 3, 5, 1, 1, "ù", "", {None, None}}, + {0x00FA, u'ú', KeyType::Character, 3, 6, 1, 1, "ú", "", {None, None}}, + {0x00FB, u'û', KeyType::Character, 3, 7, 1, 1, "û", "", {None, None}}, + {0x00FC, u'ü', KeyType::Character, 3, 8, 1, 1, "ü", "", {None, None}}, + {0x00FD, u'ý', KeyType::Character, 3, 9, 1, 1, "ý", "", {None, None}}, + + // Row 4 + {0x00FF, u'ÿ', KeyType::Character, 4, 0, 1, 1, "ÿ", "", {None, None}}, + {0x017A, u'ź', KeyType::Character, 4, 1, 1, 1, "ź", "", {None, None}}, + {0x017C, u'ż', KeyType::Character, 4, 2, 1, 1, "ż", "", {None, None}}, + {0x017E, u'ž', KeyType::Character, 4, 3, 1, 1, "ž", "", {None, None}}, + {0x00F0, u'ð', KeyType::Character, 4, 4, 1, 1, "ð", "", {None, None}}, + {0x00FE, u'þ', KeyType::Character, 4, 5, 1, 1, "þ", "", {None, None}}, + {0x0000, u'\0', KeyType::Disabled, 4, 6, 1, 1, "", "", {None, None}}, + {0x0000, u'\0', KeyType::Disabled, 4, 7, 1, 1, "", "", {None, None}}, + {0x0000, u'\0', KeyType::Disabled, 4, 8, 1, 1, "", "", {None, None}}, + {0x0000, u'\0', KeyType::Disabled, 4, 9, 1, 1, "", "", {None, None}}, + + // Row 5 + {0x0010, u'\0', KeyType::Function, 5, 0, 1, 1, "⬆", "L2", {L2, None}}, + {KC_LETTERS, u'\0', KeyType::Function, 5, 1, 1, 1, "ABC", "L2+△", {L3, Triangle}}, // TODO + {0x0000, u'\0', KeyType::Disabled, 5, 2, 1, 1, "", "", {None, None}}, // TODO + {0x0020, u' ', KeyType::Character, 5, 3, 4, 1, "Space", "△", {Triangle, None}}, + {0x0000, u'\0', KeyType::Disabled, 5, 7, 1, 1, "", "", {None, None}}, + {0x0008, u'\0', KeyType::Function, 5, 8, 2, 1, "⇦", "□", {Square, None}, true}, + + // Row 6 + {0xF020, u'\0', KeyType::Function, 6, 0, 1, 1, "▲", "", {Up, None}}, + {0xF021, u'\0', KeyType::Function, 6, 1, 1, 1, "▼", "", {Down, None}}, + {0xF022, u'\0', KeyType::Function, 6, 2, 1, 1, "◀", "L1", {L1, None}}, + {0xF023, u'\0', KeyType::Function, 6, 3, 1, 1, "▶", "R1", {R1, None}}, + {KC_KB, u'\0', KeyType::Function, 6, 4, 1, 1, "KB", "", {None, None}}, // TODO + {KC_OPT, u'\0', KeyType::Function, 6, 5, 1, 1, "...", "", {None, None}}, // TODO + {KC_GYRO, u'\0', KeyType::Function, 6, 6, 1, 1, "+/⊗", "R3", {R3, None}}, // TODO + {0x0000, u'\0', KeyType::Disabled, 6, 7, 1, 1, "", "", {None, None}}, + {0x000D, u'\r', KeyType::Function, 6, 8, 2, 1, "Done", "R2", {R2, None}}, +}; diff --git a/src/core/libraries/ime/ime_keyboard_layouts.h b/src/core/libraries/ime/ime_keyboard_layouts.h index 69b05576f..a727c4e1e 100644 --- a/src/core/libraries/ime/ime_keyboard_layouts.h +++ b/src/core/libraries/ime/ime_keyboard_layouts.h @@ -6,43 +6,77 @@ #include #include #include +#include "common/types.h" -enum class KeyType { - Text, // Inserts character(s) into input buffer - Backspace, // Deletes last character - Space, // Adds space - Enter, // Submits input - Shift, // Toggle uppercase/lowercase - Symbols1Layout, // Switch to symbols layout - Symbols2Layout, // Switch to symbols layout - LettersLayout, // Switch to text layout - AccentLettersLayout, // Switch to accent text layout - Done, // Finish and close keyboard - CursorLeft, - CursorRight, - CursorUp, - CursorDown, - ToggleKeyboard, // Toggles keyboard layout - MoreOptions, // "..." button - ControllerAction, // e.g. R3 +/⊕ - Disabled, // Filler or placeholder - UnknownFunction, // now same as disabled +/* +enum class OrbisImeKeyEntryType : u8 { + ORBIS_IME_KEY_TYPE_CHARACTER = 0, + ORBIS_IME_KEY_TYPE_FUNCTION = 1, + ORBIS_IME_KEY_TYPE_DISABLED = 2 +}; +*/ +/* +struct OrbisImeKeyEntry { + u16 keycode; + char16_t character; + OrbisImeKeyEntryType type; + u8 row; + u8 col; + u8 colspan; + u8 rowspan; + const char* label; + const char* controller_hint; + OrbisPadButtonDataOffset bound_buttons[2]; +}; +*/ + +enum class KeyType : u8 { Character = 0, Function = 1, Disabled = 2 }; + +struct KeyEntry { + u16 keycode; // 0xF100+ unused, so can be used as temporary defined keys for unknown + char16_t character; + KeyType type; + u8 row; + u8 col; + u8 colspan; + u8 rowspan; + const char* label; + const char* controller_hint; + ImGuiNavInput bound_buttons[2]; + bool allow_repeat{false}; }; -struct Key { - int row; - int col; - int colspan = 1; - int rowspan = 1; - std::string label; - std::string controller_hint; - KeyType type = KeyType::Text; - std::vector bound_buttons = {}; // Now using ImGui navigation inputs -}; +int c16rtomb(char* out, char16_t ch); -extern const std::vector kLayoutEnLettersUppercase; -extern const std::vector kLayoutEnLettersLowercase; -extern const std::vector kLayoutEnAccentLettersUppercase; -extern const std::vector kLayoutEnAccentLettersLowercase; -extern const std::vector kLayoutEnSymbols1; -extern const std::vector kLayoutEnSymbols2; +extern const std::vector kLayoutEnLettersUppercase; +extern const std::vector kLayoutEnLettersLowercase; +extern const std::vector kLayoutEnAccentLettersUppercase; +extern const std::vector kLayoutEnAccentLettersLowercase; +extern const std::vector kLayoutEnSymbols1; +extern const std::vector kLayoutEnSymbols2; + +constexpr ImGuiNavInput None = ImGuiNavInput_COUNT; +constexpr auto L1 = ImGuiNavInput_FocusPrev; +constexpr auto R1 = ImGuiNavInput_FocusNext; +constexpr auto L2 = ImGuiNavInput_TweakSlow; +constexpr auto R2 = ImGuiNavInput_TweakFast; +constexpr auto L3 = ImGuiNavInput_DpadLeft; // adjust if needed +constexpr auto R3 = ImGuiNavInput_DpadRight; // adjust if needed +constexpr auto Up = ImGuiNavInput_DpadUp; +constexpr auto Down = ImGuiNavInput_DpadDown; +constexpr auto Left = ImGuiNavInput_DpadLeft; +constexpr auto Right = ImGuiNavInput_DpadRight; +constexpr auto Cross = ImGuiNavInput_Activate; +constexpr auto Circle = ImGuiNavInput_Menu; +constexpr auto Square = ImGuiNavInput_Cancel; +constexpr auto Triangle = ImGuiNavInput_Input; +constexpr auto TouchPad = ImGuiNavInput_Menu; // reuse if needed + +// Fake function keycodes +constexpr u16 KC_SYM1 = 0xF100; +constexpr u16 KC_SYM2 = 0xF101; +constexpr u16 KC_ACCENTS = 0xF102; +constexpr u16 KC_LETTERS = 0xF103; +constexpr u16 KC_KB = 0xF104; +constexpr u16 KC_GYRO = 0xF105; +constexpr u16 KC_OPT = 0xF106; \ No newline at end of file diff --git a/src/core/libraries/ime/ime_keyboard_ui.cpp b/src/core/libraries/ime/ime_keyboard_ui.cpp index a71bba129..68674488c 100644 --- a/src/core/libraries/ime/ime_keyboard_ui.cpp +++ b/src/core/libraries/ime/ime_keyboard_ui.cpp @@ -1,167 +1,215 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - #include +#include #include +#include + #include "ime_common.h" +#include "ime_dialog.h" #include "ime_keyboard_layouts.h" #include "ime_keyboard_ui.h" #include "ime_ui.h" // for ImeState using namespace ImGui; -// --- UTF-8 safe backspace helper --- +/** + * Removes one UTF-8 codepoint from the end of 'buffer', if present. + */ void Utf8SafeBackspace(char* buffer) { size_t len = std::strlen(buffer); if (len == 0) return; + // Move backward over any continuation bytes. while (len > 0 && (static_cast(buffer[len]) & 0b11000000) == 0b10000000) { --len; } if (len > 0) { + // Remove one codepoint. buffer[len - 1] = '\0'; buffer[len] = '\0'; } } -void DrawVirtualKeyboard(char* buffer, std::size_t buffer_capacity, bool* input_changed, - KeyboardMode& kb_mode, bool& shift_enabled, bool* done_pressed) { - const std::vector* layout = nullptr; +/** + * Picks which layout vector we want for OrbisImeType, kb_mode, shift_state, etc. + */ +const std::vector* GetKeyboardLayout(OrbisImeType type, KeyboardMode mode, + ShiftState shift, u64 language) { + switch (type) { + case OrbisImeType::Number: + // For numeric input, you might have a dedicated numeric layout, + // but here we reuse kLayoutEnSymbols1. + return &kLayoutEnSymbols1; - switch (kb_mode) { - case KeyboardMode::Symbols1: - layout = &kLayoutEnSymbols1; - break; - case KeyboardMode::Symbols2: - layout = &kLayoutEnSymbols2; - break; - case KeyboardMode::Letters2: - layout = - shift_enabled ? &kLayoutEnAccentLettersUppercase : &kLayoutEnAccentLettersLowercase; - break; - case KeyboardMode::Letters1: + case OrbisImeType::Url: + case OrbisImeType::Mail: + // Use letters; uppercase if SHIFT is on. + if (shift == ShiftState::CapsLock || shift == ShiftState::Shift) { + return &kLayoutEnLettersUppercase; + } else { + return &kLayoutEnLettersLowercase; + } + + case OrbisImeType::BasicLatin: + case OrbisImeType::Default: default: - layout = shift_enabled ? &kLayoutEnLettersUppercase : &kLayoutEnLettersLowercase; - break; + switch (mode) { + case KeyboardMode::Symbols1: + return &kLayoutEnSymbols1; + case KeyboardMode::Symbols2: + return &kLayoutEnSymbols2; + case KeyboardMode::AccentLetters: + if (shift == ShiftState::CapsLock || shift == ShiftState::Shift) { + return &kLayoutEnAccentLettersUppercase; + } else { + return &kLayoutEnAccentLettersLowercase; + } + case KeyboardMode::Letters: + default: + if (shift == ShiftState::CapsLock || shift == ShiftState::Shift) { + return &kLayoutEnLettersUppercase; + } else { + return &kLayoutEnLettersLowercase; + } + } } - - RenderKeyboardLayout(*layout, buffer, buffer_capacity, input_changed, kb_mode, shift_enabled, - done_pressed); } -void RenderKeyboardLayout(const std::vector& layout, char* buffer, std::size_t buffer_capacity, - bool* input_changed, KeyboardMode& kb_mode, bool& shift_enabled, - bool* done_pressed) { - const float layout_width = 485.0f; - const float layout_height = 200.0f; - const float cell_spacing = 4.0f; - const float hint_padding = 2.0f; +/** + * Renders the given layout using the style logic: + * - For symbols layout and if style.use_button_symbol_color is true, + * character keys get style.color_button_symbol. + * - Function keys get style.color_button_function. + * - The "Done"/"Enter" key (keycode 0x0D) gets style.color_special. + * - Otherwise, keys use style.color_button_default. + * + * This version retains all GUI layout details (positions, colors, sizes, etc.) exactly as in your + * base files. The only change is in key event detection: after drawing each key with Button(), we + * use IsItemActive() to determine the pressed state so that the backend key processing works + * correctly. + */ +void RenderKeyboardLayout(const std::vector& layout, KeyboardMode mode, + void (*on_key_event)(const VirtualKeyEvent*), + const KeyboardStyle& style) { + ImGui::BeginGroup(); - int max_col = 0; - int max_row = 0; - for (const Key& key : layout) { - max_col = std::max(max_col, key.col + static_cast(key.colspan)); - max_row = std::max(max_row, key.row + static_cast(key.rowspan)); + /* ─────────────── 1. grid size & cell metrics ─────────────── */ + int max_col = 0, max_row = 0; + for (const KeyEntry& k : layout) { + max_col = std::max(max_col, k.col + (int)k.colspan); + max_row = std::max(max_row, k.row + (int)k.rowspan); + } + if (max_col == 0 || max_row == 0) { + ImGui::EndGroup(); + return; } - const float cell_width = (layout_width - (max_col - 1) * cell_spacing) / max_col; - const float cell_height = (layout_height - (max_row - 1) * cell_spacing) / max_row; + const float pad = 20.0f; + const float spacing_w = (max_col - 1) * style.key_spacing; + const float spacing_h = (max_row - 1) * style.key_spacing; + const float cell_w = std::floor((style.layout_width - spacing_w - 2 * pad) / max_col + 0.5f); + const float cell_h = std::floor((style.layout_height - spacing_h - 85.0f) / max_row + 0.5f); - const ImVec2 origin = ImGui::GetCursorScreenPos(); - ImDrawList* draw_list = ImGui::GetWindowDrawList(); + ImVec2 origin = ImGui::GetCursorScreenPos(); + origin.x += pad; - for (const Key& key : layout) { - float x = origin.x + key.col * (cell_width + cell_spacing); - float y = origin.y + key.row * (cell_height + cell_spacing); + ImGui::PushStyleColor(ImGuiCol_NavHighlight, style.color_line); + ImGui::SetWindowFontScale(1.50f); - ImVec2 pos(x, y); - ImVec2 size(key.colspan * cell_width + (key.colspan - 1) * cell_spacing, - key.rowspan * cell_height + (key.rowspan - 1) * cell_spacing); + const int function_rows_start = std::max(0, max_row - 2); - std::string button_id = - key.label.empty() ? "##empty_" + std::to_string(key.row) + "_" + std::to_string(key.col) - : key.label; + /* ─────────────── 2. draw every key ───────────────────────── */ + for (const KeyEntry& key : layout) { + /* position & size */ + float x = origin.x + key.col * (cell_w + style.key_spacing); + float y = origin.y + key.row * (cell_h + style.key_spacing); + float w = key.colspan * cell_w + (key.colspan - 1) * style.key_spacing; + float h = key.rowspan * cell_h + (key.rowspan - 1) * style.key_spacing; + ImVec2 pos(x, y), size(w, h); + + /* ------------ background colour decision --------------- */ + const bool in_function_rows = (key.row >= function_rows_start); + const bool is_done_enter = (key.keycode == 0x0D); + + ImU32 bg_color; + if (is_done_enter) { + bg_color = style.color_special; // always wins + } else if (in_function_rows) { + bg_color = style.color_button_function; // bottom two rows + } else if ((mode == KeyboardMode::Symbols1 || mode == KeyboardMode::Symbols2) && + style.use_button_symbol_color) { + bg_color = style.color_button_symbol; // symbol tint + } else { + bg_color = style.color_button_default; // normal default + } + + /* label */ + std::string label = (key.label && key.label[0]) ? key.label : " "; + + /* ---------- ImGui button ---------- */ + ImGui::PushID(&key); + ImGui::PushStyleColor(ImGuiCol_Text, style.color_text); + ImGui::PushStyleColor(ImGuiCol_Button, bg_color); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, + IM_COL32((bg_color >> IM_COL32_R_SHIFT & 0xFF) * 220 / 255, + (bg_color >> IM_COL32_G_SHIFT & 0xFF) * 220 / 255, + (bg_color >> IM_COL32_B_SHIFT & 0xFF) * 220 / 255, + (bg_color >> IM_COL32_A_SHIFT & 0xFF))); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, + IM_COL32((bg_color >> IM_COL32_R_SHIFT & 0xFF) * 180 / 255, + (bg_color >> IM_COL32_G_SHIFT & 0xFF) * 180 / 255, + (bg_color >> IM_COL32_B_SHIFT & 0xFF) * 180 / 255, + (bg_color >> IM_COL32_A_SHIFT & 0xFF))); + ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.0f); + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f); + + if (key.allow_repeat) + ImGui::PushButtonRepeat(true); ImGui::SetCursorScreenPos(pos); - bool key_activated = ImGui::Button(button_id.c_str(), size); + bool pressed = ImGui::Button(label.c_str(), size); // Down + repeats - if (key_activated) { - switch (key.type) { - case KeyType::Text: - if (!key.label.empty()) { - size_t len = std::strlen(buffer); - if (len + key.label.size() < buffer_capacity) { - std::strcat(buffer, key.label.c_str()); - if (input_changed) - *input_changed = true; - } - } - break; - case KeyType::Backspace: - if (buffer[0] != '\0') { - Utf8SafeBackspace(buffer); - if (input_changed) - *input_changed = true; - } - break; - case KeyType::Space: - if (std::strlen(buffer) + 1 < buffer_capacity) { - std::strcat(buffer, " "); - if (input_changed) - *input_changed = true; - } - break; - case KeyType::Enter: - case KeyType::Done: - if (done_pressed) - *done_pressed = true; - break; - case KeyType::Shift: - shift_enabled = !shift_enabled; - break; - case KeyType::Symbols1Layout: - kb_mode = KeyboardMode::Symbols1; - break; - case KeyType::Symbols2Layout: - kb_mode = KeyboardMode::Symbols2; - break; - case KeyType::LettersLayout: - kb_mode = KeyboardMode::Letters1; - break; - case KeyType::AccentLettersLayout: - kb_mode = KeyboardMode::Letters2; - break; + if (key.allow_repeat) + ImGui::PopButtonRepeat(); - case KeyType::ToggleKeyboard: - kb_mode = (kb_mode == KeyboardMode::Letters1) ? KeyboardMode::Symbols1 - : KeyboardMode::Letters1; - break; - default: - break; + /* ---------- event generation ---------- */ + if (on_key_event) { + if (ImGui::IsItemActivated()) { + VirtualKeyEvent ev{VirtualKeyEventType::Down, &key}; + on_key_event(&ev); + } else if (pressed && key.allow_repeat) { + VirtualKeyEvent ev{VirtualKeyEventType::Repeat, &key}; + on_key_event(&ev); + } + + if (ImGui::IsItemDeactivated()) { + VirtualKeyEvent ev{VirtualKeyEventType::Up, &key}; + on_key_event(&ev); } } - // Draw controller hint label - if (!key.controller_hint.empty()) { - float original_font_size = ImGui::GetFontSize(); - float small_font_size = original_font_size * 0.5f; - - ImVec2 text_size = - ImGui::CalcTextSize(key.controller_hint.c_str(), nullptr, false, -1.0f) * - (small_font_size / original_font_size); - - ImVec2 text_pos = pos + ImVec2(hint_padding, hint_padding); - ImVec2 bg_min = text_pos - ImVec2(1.0f, 1.0f); - ImVec2 bg_max = text_pos + text_size + ImVec2(2.0f, 1.0f); - - ImU32 bg_color = IM_COL32(0, 0, 0, 160); - ImU32 fg_color = IM_COL32(255, 255, 255, 200); - - draw_list->AddRectFilled(bg_min, bg_max, bg_color, 2.0f); - draw_list->AddText(nullptr, small_font_size, text_pos, fg_color, - key.controller_hint.c_str()); - } + /* cleanup */ + ImGui::PopStyleVar(2); + ImGui::PopStyleColor(4); + ImGui::PopID(); } + + ImGui::SetWindowFontScale(1.0f); + ImGui::PopStyleColor(); // NavHighlight + ImGui::EndGroup(); +} + +/** + * Selects the correct layout via GetKeyboardLayout() then calls RenderKeyboardLayout(). + */ +void DrawVirtualKeyboard(KeyboardMode kb_mode, OrbisImeType ime_type, ShiftState shift_state, + u64 language, void (*on_key_event)(const VirtualKeyEvent*), + const KeyboardStyle& style) { + const std::vector* layout = + GetKeyboardLayout(ime_type, kb_mode, shift_state, language); + if (!layout) + return; + + RenderKeyboardLayout(*layout, kb_mode, on_key_event, style); } diff --git a/src/core/libraries/ime/ime_keyboard_ui.h b/src/core/libraries/ime/ime_keyboard_ui.h index 8b4f4af3e..9e8fdef86 100644 --- a/src/core/libraries/ime/ime_keyboard_ui.h +++ b/src/core/libraries/ime/ime_keyboard_ui.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - #pragma once #include @@ -13,11 +10,83 @@ #include "core/libraries/pad/pad.h" #include "ime_keyboard_layouts.h" -enum class KeyboardMode { Letters1, Letters2, Symbols1, Symbols2 }; +/** + * KeyboardMode: which layout we show (letters, accents, symbols, etc.) + */ +enum class KeyboardMode { Letters, AccentLetters, Symbols1, Symbols2 }; -void DrawVirtualKeyboard(char* buffer, std::size_t buffer_capacity, bool* input_changed, - KeyboardMode& kb_mode, bool& shift_enabled, bool* done_pressed); +/** + * We handle raw key "Down" or "Up" events from an on-screen keyboard. + */ +enum class VirtualKeyEventType { Down, Up, Repeat }; -void RenderKeyboardLayout(const std::vector& layout, char* buffer, std::size_t buffer_capacity, - bool* input_changed, KeyboardMode& kb_mode, bool& shift_enabled, - bool* done_pressed); \ No newline at end of file +struct VirtualKeyEvent { + VirtualKeyEventType type; + const KeyEntry* key; +}; + +enum class ShiftState : u8 { + None = 0, // lowercase + Shift = 1, // temporary uppercase + CapsLock = 2 // full uppercase +}; + +/** + * This struct holds all visual parameters for the on-screen keyboard, + * including layout size, spacing, and button colors. + * + * If extended parameters are present, it override these defaults + * in IME code. Then pass the result to DrawVirtualKeyboard(...). + */ +struct KeyboardStyle { + float layout_width = 500.0f; + float layout_height = 300.0f; + float key_spacing = 5.0f; + + // For text, lines, etc. + ImU32 color_text = IM_COL32(225, 225, 225, 255); + ImU32 color_line = IM_COL32(88, 88, 88, 255); + + // Button colors + ImU32 color_button_default = IM_COL32(35, 35, 35, 255); + ImU32 color_button_function = IM_COL32(50, 50, 50, 255); + ImU32 color_special = IM_COL32(0, 140, 200, 255); + + // If you're on a symbols layout, you may want to color them differently. + bool use_button_symbol_color = false; + ImU32 color_button_symbol = IM_COL32(60, 60, 60, 255); +}; + +/** + * Safely remove one UTF-8 glyph from the end of 'buffer'. + */ +void Utf8SafeBackspace(char* buffer); + +/** + * Returns the appropriate layout (vector of KeyEntry) for the given + * OrbisImeType, KeyboardMode, ShiftState, and language bitmask. + */ +const std::vector* GetKeyboardLayout(OrbisImeType type, KeyboardMode mode, + ShiftState shift, u64 language); + +/** + * Renders a given layout using the style logic: + * - If 'mode' is a symbols layout (Symbols1 or Symbols2) AND style.use_button_symbol_color == true, + * then normal character keys are drawn with style.color_button_symbol + * - Function keys => style.color_button_function + * - The "Done" or "Enter" key (keycode 0x0D) => style.color_special + * - Otherwise => style.color_button_default + * + * We call on_key_event(...) with VirtualKeyEventType::Down/Up when the user clicks or releases a + * key. + */ +void RenderKeyboardLayout(const std::vector& layout, KeyboardMode mode, + void (*on_key_event)(const VirtualKeyEvent*), const KeyboardStyle& style); + +/** + * Picks the correct layout from GetKeyboardLayout() for the given + * kb_mode, shift_state, etc., then calls RenderKeyboardLayout(). + */ +void DrawVirtualKeyboard(KeyboardMode kb_mode, OrbisImeType ime_type, ShiftState shift_state, + u64 language, void (*on_key_event)(const VirtualKeyEvent*), + const KeyboardStyle& style); diff --git a/src/core/libraries/ime/ime_ui.cpp b/src/core/libraries/ime/ime_ui.cpp index 918abe191..eb6680dea 100644 --- a/src/core/libraries/ime/ime_ui.cpp +++ b/src/core/libraries/ime/ime_ui.cpp @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "ime_keyboard_ui.h" #include "ime_ui.h" #include "imgui/imgui_std.h" @@ -151,7 +150,6 @@ void ImeUi::Draw() { DrawPrettyBackground(); DrawInputText(); - DrawKeyboard(); SetCursorPosY(GetCursorPosY() + 10.0f); const char* button_text; @@ -189,47 +187,6 @@ void ImeUi::DrawInputText() { } } -void ImeUi::DrawKeyboard() { - static KeyboardMode kb_mode = KeyboardMode::Letters1; - static bool shift_enabled = false; - - static bool has_logged = false; - if (!has_logged) { - LOG_INFO(Lib_Ime, "Virtual keyboard used from ImeUi"); - has_logged = true; - } - - bool input_changed = false; - bool done_pressed = false; - - DrawVirtualKeyboard(state->current_text.begin(), state->current_text.capacity(), &input_changed, - kb_mode, shift_enabled, &done_pressed); - - if (input_changed) { - OrbisImeEditText eventParam{}; - eventParam.str = reinterpret_cast(ime_param->work); - eventParam.caret_index = std::strlen(state->current_text.begin()); - eventParam.area_num = 1; - eventParam.text_area[0].mode = 1; - eventParam.text_area[0].index = 0; - eventParam.text_area[0].length = eventParam.caret_index; - - state->ConvertUTF8ToOrbis(state->current_text.begin(), eventParam.caret_index, - eventParam.str, ime_param->maxTextLength); - state->ConvertUTF8ToOrbis(state->current_text.begin(), eventParam.caret_index, - ime_param->inputTextBuffer, ime_param->maxTextLength); - - OrbisImeEvent event{}; - event.id = OrbisImeEventId::UpdateText; - event.param.text = eventParam; - state->SendEvent(&event); - } - - if (done_pressed) { - state->SendEnterEvent(); - } -} - int ImeUi::InputTextCallback(ImGuiInputTextCallbackData* data) { ImeUi* ui = static_cast(data->UserData); ASSERT(ui); @@ -293,4 +250,4 @@ void ImeUi::Free() { RemoveLayer(this); } -}; // namespace Libraries::Ime +}; // namespace Libraries::Ime \ No newline at end of file diff --git a/src/core/libraries/ime/ime_ui.h b/src/core/libraries/ime/ime_ui.h index 3dbc647eb..3eea22b8c 100644 --- a/src/core/libraries/ime/ime_ui.h +++ b/src/core/libraries/ime/ime_ui.h @@ -70,8 +70,6 @@ private: void DrawInputText(); - void DrawKeyboard(); - static int InputTextCallback(ImGuiInputTextCallbackData* data); }; diff --git a/src/imgui/renderer/imgui_core.cpp b/src/imgui/renderer/imgui_core.cpp index 28fdc618d..53471e669 100644 --- a/src/imgui/renderer/imgui_core.cpp +++ b/src/imgui/renderer/imgui_core.cpp @@ -80,7 +80,7 @@ void Initialize(const ::Vulkan::Instance& instance, const Frontend::WindowSDL& w rb.AddChar(U'→'); rb.AddChar(U'⊗'); rb.AddChar(U'⮾'); - rb.AddChar(U'🗙'); + rb.AddChar(U'╳'); rb.AddChar(U'◀'); rb.AddChar(U'▲'); rb.AddChar(U'▶'); From 23b31367b2a84c9f76fd60aa0ac5667aeb4ad0af Mon Sep 17 00:00:00 2001 From: w1naenator Date: Sun, 20 Apr 2025 01:38:13 +0300 Subject: [PATCH 14/20] Full redesign --- src/core/libraries/ime/ime_dialog_ui.cpp | 1 - src/core/libraries/ime/ime_dialog_ui.h | 12 ---------- .../libraries/ime/ime_keyboard_layouts.cpp | 1 + src/core/libraries/ime/ime_keyboard_layouts.h | 22 ------------------- src/core/libraries/ime/ime_keyboard_ui.cpp | 2 -- src/core/libraries/ime/ime_keyboard_ui.h | 8 ++----- src/core/libraries/ime/ime_ui.cpp | 1 - src/core/libraries/ime/ime_ui.h | 1 - 8 files changed, 3 insertions(+), 45 deletions(-) diff --git a/src/core/libraries/ime/ime_dialog_ui.cpp b/src/core/libraries/ime/ime_dialog_ui.cpp index 9bffc8959..89aba7cbf 100644 --- a/src/core/libraries/ime/ime_dialog_ui.cpp +++ b/src/core/libraries/ime/ime_dialog_ui.cpp @@ -517,7 +517,6 @@ void ImeDialogUi::OnVirtualKeyEvent(const VirtualKeyEvent* evt) { /* Up is available if you need it later; currently ignored */ } -/* draw keyboard in a sub‑ID scope */ void ImeDialogUi::DrawVirtualKeyboardSection() { ImGui::PushID("VirtualKeyboardSection"); DrawVirtualKeyboard(kb_mode, state->type, shift_state, kb_language, KeyboardCallbackBridge, diff --git a/src/core/libraries/ime/ime_dialog_ui.h b/src/core/libraries/ime/ime_dialog_ui.h index 0c7c26a71..0984602ce 100644 --- a/src/core/libraries/ime/ime_dialog_ui.h +++ b/src/core/libraries/ime/ime_dialog_ui.h @@ -158,18 +158,6 @@ private: ShiftState shift_state = ShiftState::None; u64 kb_language = 0; KeyboardStyle kb_style; - /* KeyboardStyle kb_style{ - .layout_width = 500.0f, - .layout_height = 250.0f, - .key_spacing = 5.0f, - .color_text = IM_COL32(225,225,225,255), - .color_line = IM_COL32( 88, 88, 88,255), - .color_button_default = IM_COL32( 35, 35, 35,255), - .color_button_function = IM_COL32( 50, 50, 50,255), - .color_special = IM_COL32( 0,140,200,255), - .use_button_symbol_color= false, - .color_button_symbol = IM_COL32( 60, 60, 60,255), - };*/ void DrawVirtualKeyboardSection(); void DrawPredictionBarAnCancelButton(); diff --git a/src/core/libraries/ime/ime_keyboard_layouts.cpp b/src/core/libraries/ime/ime_keyboard_layouts.cpp index 7642fcc22..7d009119a 100644 --- a/src/core/libraries/ime/ime_keyboard_layouts.cpp +++ b/src/core/libraries/ime/ime_keyboard_layouts.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include + #include "ime_keyboard_layouts.h" int c16rtomb(char* out, char16_t ch) { diff --git a/src/core/libraries/ime/ime_keyboard_layouts.h b/src/core/libraries/ime/ime_keyboard_layouts.h index a727c4e1e..73e83ec82 100644 --- a/src/core/libraries/ime/ime_keyboard_layouts.h +++ b/src/core/libraries/ime/ime_keyboard_layouts.h @@ -8,28 +8,6 @@ #include #include "common/types.h" -/* -enum class OrbisImeKeyEntryType : u8 { - ORBIS_IME_KEY_TYPE_CHARACTER = 0, - ORBIS_IME_KEY_TYPE_FUNCTION = 1, - ORBIS_IME_KEY_TYPE_DISABLED = 2 -}; -*/ -/* -struct OrbisImeKeyEntry { - u16 keycode; - char16_t character; - OrbisImeKeyEntryType type; - u8 row; - u8 col; - u8 colspan; - u8 rowspan; - const char* label; - const char* controller_hint; - OrbisPadButtonDataOffset bound_buttons[2]; -}; -*/ - enum class KeyType : u8 { Character = 0, Function = 1, Disabled = 2 }; struct KeyEntry { diff --git a/src/core/libraries/ime/ime_keyboard_ui.cpp b/src/core/libraries/ime/ime_keyboard_ui.cpp index 68674488c..927df0feb 100644 --- a/src/core/libraries/ime/ime_keyboard_ui.cpp +++ b/src/core/libraries/ime/ime_keyboard_ui.cpp @@ -7,8 +7,6 @@ #include "ime_dialog.h" #include "ime_keyboard_layouts.h" #include "ime_keyboard_ui.h" -#include "ime_ui.h" // for ImeState - using namespace ImGui; /** diff --git a/src/core/libraries/ime/ime_keyboard_ui.h b/src/core/libraries/ime/ime_keyboard_ui.h index 9e8fdef86..c2507c346 100644 --- a/src/core/libraries/ime/ime_keyboard_ui.h +++ b/src/core/libraries/ime/ime_keyboard_ui.h @@ -3,12 +3,8 @@ #include #include #include -#include "core/libraries/ime/ime.h" -#include "core/libraries/ime/ime_common.h" -#include "core/libraries/ime/ime_error.h" -#include "core/libraries/ime/ime_ui.h" -#include "core/libraries/pad/pad.h" -#include "ime_keyboard_layouts.h" + +#include "core/libraries/ime/ime_keyboard_layouts.h" /** * KeyboardMode: which layout we show (letters, accents, symbols, etc.) diff --git a/src/core/libraries/ime/ime_ui.cpp b/src/core/libraries/ime/ime_ui.cpp index eb6680dea..811370098 100644 --- a/src/core/libraries/ime/ime_ui.cpp +++ b/src/core/libraries/ime/ime_ui.cpp @@ -249,5 +249,4 @@ int ImeUi::InputTextCallback(ImGuiInputTextCallbackData* data) { void ImeUi::Free() { RemoveLayer(this); } - }; // namespace Libraries::Ime \ No newline at end of file diff --git a/src/core/libraries/ime/ime_ui.h b/src/core/libraries/ime/ime_ui.h index 3eea22b8c..880e623d6 100644 --- a/src/core/libraries/ime/ime_ui.h +++ b/src/core/libraries/ime/ime_ui.h @@ -72,5 +72,4 @@ private: static int InputTextCallback(ImGuiInputTextCallbackData* data); }; - }; // namespace Libraries::Ime \ No newline at end of file From df25e2da7ba024aa3e0c63357710dfec1942f031 Mon Sep 17 00:00:00 2001 From: w1naenator Date: Mon, 21 Apr 2025 03:05:49 +0300 Subject: [PATCH 15/20] replace ImGuiNavInput with ImGuiKey added repeat event selectable for each key. --- src/core/libraries/ime/ime_dialog_ui.cpp | 252 ++++++++++-------- src/core/libraries/ime/ime_dialog_ui.h | 48 ++-- .../libraries/ime/ime_keyboard_layouts.cpp | 1 - src/core/libraries/ime/ime_keyboard_layouts.h | 35 +-- src/core/libraries/ime/ime_keyboard_ui.cpp | 2 + src/core/libraries/ime/ime_keyboard_ui.h | 8 +- 6 files changed, 192 insertions(+), 154 deletions(-) diff --git a/src/core/libraries/ime/ime_dialog_ui.cpp b/src/core/libraries/ime/ime_dialog_ui.cpp index 89aba7cbf..3c8bcfddf 100644 --- a/src/core/libraries/ime/ime_dialog_ui.cpp +++ b/src/core/libraries/ime/ime_dialog_ui.cpp @@ -1,8 +1,5 @@ -// ime_dialog_ui.cpp -// ---------------------------------------------------------- -// Full implementation of IME dialog UI with on‑screen keyboard -// (all original logic intact, bugs fixed). -// ---------------------------------------------------------- +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #include #include @@ -52,13 +49,14 @@ static void KeyboardCallbackBridge(const VirtualKeyEvent* evt) { *─────────────────────────────────────────────────────────────*/ ImeDialogState::ImeDialogState(const OrbisImeDialogParam* param, const OrbisImeParamExtended* extended) { - if (!param) + if (!param) { return; + } /* basic param copy */ user_id = param->user_id; is_multi_line = True(param->option & OrbisImeDialogOption::Multiline); - is_numeric = (param->type == OrbisImeType::Number); + is_numeric = param->type == OrbisImeType::Number; type = param->type; enter_label = param->enter_label; text_filter = param->filter; @@ -262,7 +260,7 @@ ImeDialogUi::ImeDialogUi(ImeDialogUi&& other) noexcept other.status = nullptr; other.result = nullptr; - if (state && status && *status == OrbisImeDialogStatus::Running) { + if (state && *status == OrbisImeDialogStatus::Running) { AddLayer(this); ImeDialogUi::g_activeImeDialogUi = this; } @@ -276,12 +274,11 @@ ImeDialogUi& ImeDialogUi::operator=(ImeDialogUi&& other) { status = other.status; result = other.result; first_render = other.first_render; - other.state = nullptr; other.status = nullptr; other.result = nullptr; - if (state && status && *status == OrbisImeDialogStatus::Running) { + if (state && *status == OrbisImeDialogStatus::Running) { AddLayer(this); ImeDialogUi::g_activeImeDialogUi = this; } @@ -329,6 +326,7 @@ void ImeDialogUi::Draw() { if (Begin("IME Dialog##ImeDialog", nullptr, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings)) { DrawPrettyBackground(); + /* ---------- title ---------- */ if (!state->title.empty()) { SetCursorPosX(20.0f); @@ -351,41 +349,47 @@ void ImeDialogUi::Draw() { DrawVirtualKeyboardSection(); /* ---------- OK / Cancel buttons ---------- */ - /* { - SetCursorPosY(GetCursorPosY() + 10.0f); - const char* ok_lbl = "OK##ImeDialogOK"; - switch (state->enter_label) { - case OrbisImeEnterLabel::Go: - ok_lbl = "Go##ImeDialogOK"; - break; - case OrbisImeEnterLabel::Search: - ok_lbl = "Search##ImeDialogOK"; - break; - case OrbisImeEnterLabel::Send: - ok_lbl = "Send##ImeDialogOK"; - break; - default: - break; - } + /* + SetCursorPosY(GetCursorPosY() + 10.0f); - float spacing = 10.0f; - float total_w = BUTTON_SIZE.x * 2 + spacing; - float x_start = (window_size.x - total_w) / 2.0f; - SetCursorPosX(x_start); + const char* button_text; - if (Button(ok_lbl, BUTTON_SIZE) || - (!state->is_multi_line && IsKeyPressed(ImGuiKey_Enter))) { - *status = OrbisImeDialogStatus::Finished; - result->endstatus = OrbisImeDialogEndStatus::Ok; - } + switch (state->enter_label) { + case OrbisImeEnterLabel::Go: + button_text = "Go##ImeDialogOK"; + break; + case OrbisImeEnterLabel::Search: + button_text = "Search##ImeDialogOK"; + break; + case OrbisImeEnterLabel::Send: + button_text = "Send##ImeDialogOK"; + break; + case OrbisImeEnterLabel::Default: + default: + button_text = "OK##ImeDialogOK"; + break; + } - SameLine(0.0f, spacing); + float button_spacing = 10.0f; + float total_button_width = BUTTON_SIZE.x * 2 + button_spacing; + float button_start_pos = (window_size.x - total_button_width) / 2.0f; - if (Button("Cancel##ImeDialogCancel", BUTTON_SIZE)) { - *status = OrbisImeDialogStatus::Finished; - result->endstatus = OrbisImeDialogEndStatus::UserCanceled; - } - }*/ + SetCursorPosX(button_start_pos); + + if (Button(button_text, BUTTON_SIZE) || + (!state->is_multi_line && IsKeyPressed(ImGuiKey_Enter))) { + *status = OrbisImeDialogStatus::Finished; + result->endstatus = OrbisImeDialogEndStatus::Ok; + } + + SameLine(0.0f, button_spacing); + + if (Button("Cancel##ImeDialogCancel", BUTTON_SIZE)) { + *status = OrbisImeDialogStatus::Finished; + result->endstatus = OrbisImeDialogEndStatus::UserCanceled; + } + } + */ End(); } @@ -397,65 +401,131 @@ void ImeDialogUi::Draw() { * helper draw functions (unchanged) *─────────────────────────────────────────────────────────────*/ void ImeDialogUi::DrawInputText() { - ImVec2 size(GetWindowWidth() - 40.0f, 0.0f); + ImVec2 input_size = {GetWindowWidth() - 40.0f, 0.0f}; SetCursorPosX(20.0f); - if (first_render) + if (first_render) { SetKeyboardFocusHere(); - - const char* ph = state->placeholder.empty() ? nullptr : state->placeholder.data(); - if (InputTextEx("##ImeDialogInput", ph, state->current_text.begin(), state->max_text_length, - size, ImGuiInputTextFlags_CallbackCharFilter, InputTextCallback, this)) + } + const char* placeholder = state->placeholder.empty() ? nullptr : state->placeholder.data(); + if (InputTextEx("##ImeDialogInput", placeholder, state->current_text.begin(), + state->max_text_length, input_size, ImGuiInputTextFlags_CallbackCharFilter, + InputTextCallback, this)) { state->input_changed = true; + } } void ImeDialogUi::DrawMultiLineInputText() { - ImVec2 size(GetWindowWidth() - 40.0f, 200.0f); + ImVec2 input_size = {GetWindowWidth() - 40.0f, 200.0f}; SetCursorPosX(20.0f); ImGuiInputTextFlags flags = ImGuiInputTextFlags_CallbackCharFilter | static_cast(ImGuiInputTextFlags_Multiline); - if (first_render) + if (first_render) { SetKeyboardFocusHere(); - - const char* ph = state->placeholder.empty() ? nullptr : state->placeholder.data(); - if (InputTextEx("##ImeDialogInput", ph, state->current_text.begin(), state->max_text_length, - size, flags, InputTextCallback, this)) + } + const char* placeholder = state->placeholder.empty() ? nullptr : state->placeholder.data(); + if (InputTextEx("##ImeDialogInput", placeholder, state->current_text.begin(), + state->max_text_length, input_size, flags, InputTextCallback, this)) { state->input_changed = true; + } } int ImeDialogUi::InputTextCallback(ImGuiInputTextCallbackData* data) { ImeDialogUi* ui = static_cast(data->UserData); ASSERT(ui); - /* numeric filter */ + // Should we filter punctuation? if (ui->state->is_numeric && (data->EventChar < '0' || data->EventChar > '9') && - data->EventChar != '\b' && data->EventChar != ',' && data->EventChar != '.') + data->EventChar != '\b' && data->EventChar != ',' && data->EventChar != '.') { return 1; + } - if (!ui->state->keyboard_filter) + if (!ui->state->keyboard_filter) { return 0; + } - char* ev_char = reinterpret_cast(&data->EventChar); + // ImGui encodes ImWchar32 as multi-byte UTF-8 characters + char* event_char = reinterpret_cast(&data->EventChar); - OrbisImeKeycode src{ + // Call the keyboard filter + OrbisImeKeycode src_keycode = { .keycode = 0, .character = 0, - .status = 1, - .type = OrbisImeKeyboardType::ENGLISH_US, + .status = 1, // ??? 1 = key pressed, 0 = key released + .type = OrbisImeKeyboardType::ENGLISH_US, // TODO set this to the correct value (maybe use + // the current language?) .user_id = ui->state->user_id, .resource_id = 0, .timestamp = 0, }; - if (!ui->state->ConvertUTF8ToOrbis(ev_char, 4, &src.character, 1)) + if (!ui->state->ConvertUTF8ToOrbis(event_char, 4, &src_keycode.character, 1)) { + LOG_ERROR(Lib_ImeDialog, "Failed to convert orbis char to utf8"); return 0; - src.keycode = src.character; + } + src_keycode.keycode = src_keycode.character; // TODO set this to the correct value + + u16 out_keycode; + u32 out_status; + + ui->state->CallKeyboardFilter(&src_keycode, &out_keycode, &out_status); + + // TODO. set the keycode - u16 out_code; - u32 out_stat; - ui->state->CallKeyboardFilter(&src, &out_code, &out_stat); return 0; } +/* draw keyboard in a sub‑ID scope */ +void ImeDialogUi::DrawVirtualKeyboardSection() { + ImGui::PushID("VirtualKeyboardSection"); + DrawVirtualKeyboard(kb_mode, state->type, shift_state, kb_language, KeyboardCallbackBridge, + kb_style); + ImGui::PopID(); +} + +void ImeDialogUi::DrawPredictionBarAnCancelButton() { + const float pad = 5.0f; + const float width = kb_style.layout_width; + const float bar_h = 25.0f; + + SetCursorPosX(0.0f); + ImVec2 p0 = GetCursorScreenPos(); + ImVec2 p1 = ImVec2(p0.x + width - bar_h - 2 * pad, p0.y + bar_h); + // GetWindowDrawList()->AddRectFilled(p0, p1, IM_COL32(0, 0, 0, 255)); + + /* label */ + // ImGui::SetCursorScreenPos(ImVec2(p0.x, p0.y)); + // ImGui::PushStyleColor(ImGuiCol_Text, kb_style.color_text); + // Selectable("dummy prediction", false, 0, ImVec2(width - bar_h, bar_h)); + // ImGui::PopStyleColor(); + + SetCursorPosX(pad); + ImGui::PushStyleColor(ImGuiCol_Button, IM_COL32(0, 0, 0, 255)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, IM_COL32(0, 0, 0, 255)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, IM_COL32(0, 0, 0, 255)); + ImGui::PushStyleColor(ImGuiCol_Text, kb_style.color_text); + + if (ImGui::Button("predict", ImVec2(width - bar_h - 3 * pad, bar_h))) { + } + ImGui::PopStyleColor(4); + + /* X button */ + // ImGui::SameLine(width - bar_h); + ImGui::SetCursorScreenPos(ImVec2(p0.x + width - bar_h - pad, p0.y)); + + ImGui::PushStyleColor(ImGuiCol_Button, kb_style.color_button_function); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, kb_style.color_button_function); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, kb_style.color_button_function); + ImGui::PushStyleColor(ImGuiCol_Text, kb_style.color_text); + + if (ImGui::Button("╳", ImVec2(bar_h, bar_h))) { + *status = OrbisImeDialogStatus::Finished; + result->endstatus = OrbisImeDialogEndStatus::UserCanceled; + } + ImGui::PopStyleColor(4); + SetCursorPosX(0.0f); + SetCursorPosY(GetCursorPosY() + 5.0f); +} + /*─────────────────────────────────────────────────────────────* * helper draw functions (new) *─────────────────────────────────────────────────────────────*/ @@ -516,56 +586,4 @@ void ImeDialogUi::OnVirtualKeyEvent(const VirtualKeyEvent* evt) { } /* Up is available if you need it later; currently ignored */ } - -void ImeDialogUi::DrawVirtualKeyboardSection() { - ImGui::PushID("VirtualKeyboardSection"); - DrawVirtualKeyboard(kb_mode, state->type, shift_state, kb_language, KeyboardCallbackBridge, - kb_style); - ImGui::PopID(); -} - -void ImeDialogUi::DrawPredictionBarAnCancelButton() { - const float pad = 5.0f; - const float width = kb_style.layout_width; - const float bar_h = 25.0f; - - SetCursorPosX(0.0f); - ImVec2 p0 = GetCursorScreenPos(); - ImVec2 p1 = ImVec2(p0.x + width - bar_h - 2 * pad, p0.y + bar_h); - // GetWindowDrawList()->AddRectFilled(p0, p1, IM_COL32(0, 0, 0, 255)); - - /* label */ - // ImGui::SetCursorScreenPos(ImVec2(p0.x, p0.y)); - // ImGui::PushStyleColor(ImGuiCol_Text, kb_style.color_text); - // Selectable("dummy prediction", false, 0, ImVec2(width - bar_h, bar_h)); - // ImGui::PopStyleColor(); - - SetCursorPosX(pad); - ImGui::PushStyleColor(ImGuiCol_Button, IM_COL32(0, 0, 0, 255)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, IM_COL32(0, 0, 0, 255)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, IM_COL32(0, 0, 0, 255)); - ImGui::PushStyleColor(ImGuiCol_Text, kb_style.color_text); - - if (ImGui::Button("predict", ImVec2(width - bar_h - 3 * pad, bar_h))) { - } - ImGui::PopStyleColor(4); - - /* X button */ - // ImGui::SameLine(width - bar_h); - ImGui::SetCursorScreenPos(ImVec2(p0.x + width - bar_h - pad, p0.y)); - - ImGui::PushStyleColor(ImGuiCol_Button, kb_style.color_button_function); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, kb_style.color_button_function); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, kb_style.color_button_function); - ImGui::PushStyleColor(ImGuiCol_Text, kb_style.color_text); - - if (ImGui::Button("╳", ImVec2(bar_h, bar_h))) { - *status = OrbisImeDialogStatus::Finished; - result->endstatus = OrbisImeDialogEndStatus::UserCanceled; - } - ImGui::PopStyleColor(4); - SetCursorPosX(0.0f); - SetCursorPosY(GetCursorPosY() + 5.0f); -} - } // namespace Libraries::ImeDialog diff --git a/src/core/libraries/ime/ime_dialog_ui.h b/src/core/libraries/ime/ime_dialog_ui.h index 0984602ce..b262207ca 100644 --- a/src/core/libraries/ime/ime_dialog_ui.h +++ b/src/core/libraries/ime/ime_dialog_ui.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + #pragma once #include // for strncpy / memcpy @@ -10,8 +13,6 @@ #include "ime_keyboard_ui.h" #include "imgui/imgui_layer.h" -#include - namespace Libraries::ImeDialog { // Forward declaration so we can befriend it @@ -35,11 +36,10 @@ class ImeDialogState final { OrbisImeExtKeyboardFilter keyboard_filter{}; u32 max_text_length{}; char16_t* text_buffer{}; - std::vector title; std::vector placeholder; - // One UTF‑8 code‑point may take up to 4 bytes + // A character can hold up to 4 bytes in UTF-8 Common::CString current_text; // Optional custom keyboard style (from extended params) @@ -49,11 +49,13 @@ class ImeDialogState final { public: /*──────────────── constructors / rule‑of‑five ────────────────*/ ImeDialogState(const OrbisImeDialogParam* param = nullptr, - const OrbisImeParamExtended* ext = nullptr); - ImeDialogState(const ImeDialogState&) = delete; - ImeDialogState(ImeDialogState&&) noexcept; - ImeDialogState& operator=(ImeDialogState&&); + const OrbisImeParamExtended* extended = nullptr); + ImeDialogState(const ImeDialogState& other) = delete; + ImeDialogState(ImeDialogState&& other) noexcept; + ImeDialogState& operator=(ImeDialogState&& other); + bool CopyTextToOrbisBuffer(); + bool CallTextFilter(); /*──────────────────── public read helpers ───────────────────*/ bool IsMultiLine() const { return is_multi_line; @@ -103,17 +105,15 @@ public: input_changed = true; } - /*──────────────────────── IME support ───────────────────────*/ - bool CopyTextToOrbisBuffer(); - bool CallTextFilter(); + private: bool CallKeyboardFilter(const OrbisImeKeycode* src_keycode, u16* out_keycode, u32* out_status); bool ConvertOrbisToUTF8(const char16_t* orbis_text, std::size_t orbis_text_len, char* utf8_text, - std::size_t utf8_text_len); - bool ConvertUTF8ToOrbis(const char* utf8_text, std::size_t utf8_text_len, char16_t* orbis_text, - std::size_t orbis_text_len); + std::size_t native_text_len); + bool ConvertUTF8ToOrbis(const char* native_text, std::size_t utf8_text_len, + char16_t* orbis_text, std::size_t orbis_text_len); }; //--------------------------------------------------------------------- @@ -136,9 +136,9 @@ public: explicit ImeDialogUi(ImeDialogState* state = nullptr, OrbisImeDialogStatus* status = nullptr, OrbisImeDialogResult* result = nullptr); ~ImeDialogUi() override; - ImeDialogUi(const ImeDialogUi&) = delete; - ImeDialogUi(ImeDialogUi&&) noexcept; - ImeDialogUi& operator=(ImeDialogUi&&); + ImeDialogUi(const ImeDialogUi& other) = delete; + ImeDialogUi(ImeDialogUi&& other) noexcept; + ImeDialogUi& operator=(ImeDialogUi&& other); /*────────── main draw ───────────*/ void Draw() override; @@ -149,8 +149,10 @@ public: private: /*── helpers ─*/ void Free(); + void DrawInputText(); void DrawMultiLineInputText(); + static int InputTextCallback(ImGuiInputTextCallbackData* data); /*── keyboard section ─*/ @@ -158,6 +160,18 @@ private: ShiftState shift_state = ShiftState::None; u64 kb_language = 0; KeyboardStyle kb_style; + /* KeyboardStyle kb_style{ + .layout_width = 500.0f, + .layout_height = 250.0f, + .key_spacing = 5.0f, + .color_text = IM_COL32(225,225,225,255), + .color_line = IM_COL32( 88, 88, 88,255), + .color_button_default = IM_COL32( 35, 35, 35,255), + .color_button_function = IM_COL32( 50, 50, 50,255), + .color_special = IM_COL32( 0,140,200,255), + .use_button_symbol_color= false, + .color_button_symbol = IM_COL32( 60, 60, 60,255), + };*/ void DrawVirtualKeyboardSection(); void DrawPredictionBarAnCancelButton(); diff --git a/src/core/libraries/ime/ime_keyboard_layouts.cpp b/src/core/libraries/ime/ime_keyboard_layouts.cpp index 7d009119a..7642fcc22 100644 --- a/src/core/libraries/ime/ime_keyboard_layouts.cpp +++ b/src/core/libraries/ime/ime_keyboard_layouts.cpp @@ -2,7 +2,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include - #include "ime_keyboard_layouts.h" int c16rtomb(char* out, char16_t ch) { diff --git a/src/core/libraries/ime/ime_keyboard_layouts.h b/src/core/libraries/ime/ime_keyboard_layouts.h index 73e83ec82..b6eb8575c 100644 --- a/src/core/libraries/ime/ime_keyboard_layouts.h +++ b/src/core/libraries/ime/ime_keyboard_layouts.h @@ -20,7 +20,7 @@ struct KeyEntry { u8 rowspan; const char* label; const char* controller_hint; - ImGuiNavInput bound_buttons[2]; + ImGuiKey bound_buttons[2]; bool allow_repeat{false}; }; @@ -33,22 +33,23 @@ extern const std::vector kLayoutEnAccentLettersLowercase; extern const std::vector kLayoutEnSymbols1; extern const std::vector kLayoutEnSymbols2; -constexpr ImGuiNavInput None = ImGuiNavInput_COUNT; -constexpr auto L1 = ImGuiNavInput_FocusPrev; -constexpr auto R1 = ImGuiNavInput_FocusNext; -constexpr auto L2 = ImGuiNavInput_TweakSlow; -constexpr auto R2 = ImGuiNavInput_TweakFast; -constexpr auto L3 = ImGuiNavInput_DpadLeft; // adjust if needed -constexpr auto R3 = ImGuiNavInput_DpadRight; // adjust if needed -constexpr auto Up = ImGuiNavInput_DpadUp; -constexpr auto Down = ImGuiNavInput_DpadDown; -constexpr auto Left = ImGuiNavInput_DpadLeft; -constexpr auto Right = ImGuiNavInput_DpadRight; -constexpr auto Cross = ImGuiNavInput_Activate; -constexpr auto Circle = ImGuiNavInput_Menu; -constexpr auto Square = ImGuiNavInput_Cancel; -constexpr auto Triangle = ImGuiNavInput_Input; -constexpr auto TouchPad = ImGuiNavInput_Menu; // reuse if needed +constexpr ImGuiKey None = ImGuiKey::ImGuiKey_None; +constexpr ImGuiKey L1 = ImGuiKey::ImGuiKey_GamepadL1; +constexpr ImGuiKey R1 = ImGuiKey::ImGuiKey_GamepadR1; +constexpr ImGuiKey L2 = ImGuiKey::ImGuiKey_GamepadL2; +constexpr ImGuiKey R2 = ImGuiKey::ImGuiKey_GamepadR2; +constexpr ImGuiKey L3 = ImGuiKey::ImGuiKey_GamepadL3; +constexpr ImGuiKey R3 = ImGuiKey::ImGuiKey_GamepadR3; +constexpr ImGuiKey Up = ImGuiKey::ImGuiKey_GamepadDpadUp; +constexpr ImGuiKey Down = ImGuiKey::ImGuiKey_GamepadDpadDown; +constexpr ImGuiKey Left = ImGuiKey::ImGuiKey_GamepadDpadLeft; +constexpr ImGuiKey Right = ImGuiKey::ImGuiKey_GamepadDpadRight; +constexpr ImGuiKey Cross = ImGuiKey::ImGuiKey_GamepadFaceDown; // X button +constexpr ImGuiKey Circle = ImGuiKey::ImGuiKey_GamepadFaceRight; // O button +constexpr ImGuiKey Square = ImGuiKey::ImGuiKey_GamepadFaceLeft; // [] button +constexpr ImGuiKey Triangle = ImGuiKey::ImGuiKey_GamepadFaceUp; // /\ button +constexpr ImGuiKey Options = ImGuiKey::ImGuiKey_GraveAccent; // Options button + // Fake function keycodes constexpr u16 KC_SYM1 = 0xF100; diff --git a/src/core/libraries/ime/ime_keyboard_ui.cpp b/src/core/libraries/ime/ime_keyboard_ui.cpp index 927df0feb..68674488c 100644 --- a/src/core/libraries/ime/ime_keyboard_ui.cpp +++ b/src/core/libraries/ime/ime_keyboard_ui.cpp @@ -7,6 +7,8 @@ #include "ime_dialog.h" #include "ime_keyboard_layouts.h" #include "ime_keyboard_ui.h" +#include "ime_ui.h" // for ImeState + using namespace ImGui; /** diff --git a/src/core/libraries/ime/ime_keyboard_ui.h b/src/core/libraries/ime/ime_keyboard_ui.h index c2507c346..9e8fdef86 100644 --- a/src/core/libraries/ime/ime_keyboard_ui.h +++ b/src/core/libraries/ime/ime_keyboard_ui.h @@ -3,8 +3,12 @@ #include #include #include - -#include "core/libraries/ime/ime_keyboard_layouts.h" +#include "core/libraries/ime/ime.h" +#include "core/libraries/ime/ime_common.h" +#include "core/libraries/ime/ime_error.h" +#include "core/libraries/ime/ime_ui.h" +#include "core/libraries/pad/pad.h" +#include "ime_keyboard_layouts.h" /** * KeyboardMode: which layout we show (letters, accents, symbols, etc.) From f125317b0a7c8e6309b298267a3ac46758c39be8 Mon Sep 17 00:00:00 2001 From: w1naenator Date: Mon, 21 Apr 2025 03:46:53 +0300 Subject: [PATCH 16/20] extfx --- externals/MoltenVK/MoltenVK | 2 +- externals/MoltenVK/SPIRV-Cross | 2 +- externals/MoltenVK/cereal | 2 +- externals/date | 2 +- externals/dear_imgui | 2 +- externals/discord-rpc | 2 +- externals/ffmpeg-core | 2 +- externals/fmt | 2 +- externals/glslang | 2 +- externals/magic_enum | 2 +- externals/pugixml | 2 +- externals/robin-map | 2 +- externals/sdl3 | 2 +- externals/sirit | 2 +- externals/toml11 | 2 +- externals/vma | 2 +- externals/vulkan-headers | 2 +- externals/winpthreads | 2 +- externals/xbyak | 2 +- externals/xxhash | 2 +- externals/zlib-ng | 2 +- externals/zydis | 2 +- 22 files changed, 22 insertions(+), 22 deletions(-) diff --git a/externals/MoltenVK/MoltenVK b/externals/MoltenVK/MoltenVK index 2048427e5..067fc6c85 160000 --- a/externals/MoltenVK/MoltenVK +++ b/externals/MoltenVK/MoltenVK @@ -1 +1 @@ -Subproject commit 2048427e50f9eb20f2b8f98d316ecaee398c9b91 +Subproject commit 067fc6c85b02f37dfda58eeda49d8458e093ed60 diff --git a/externals/MoltenVK/SPIRV-Cross b/externals/MoltenVK/SPIRV-Cross index 2c32b6bf8..185833a61 160000 --- a/externals/MoltenVK/SPIRV-Cross +++ b/externals/MoltenVK/SPIRV-Cross @@ -1 +1 @@ -Subproject commit 2c32b6bf86f3c4a5539aa1f0bacbd59fe61759cf +Subproject commit 185833a61cbe29ce3bfb5a499ffb3dfeaee3bbe7 diff --git a/externals/MoltenVK/cereal b/externals/MoltenVK/cereal index d1fcec807..a56bad8bb 160000 --- a/externals/MoltenVK/cereal +++ b/externals/MoltenVK/cereal @@ -1 +1 @@ -Subproject commit d1fcec807b372f04e4c1041b3058e11c12853e6e +Subproject commit a56bad8bbb770ee266e930c95d37fff2a5be7fea diff --git a/externals/date b/externals/date index 28b7b2325..a45ea7c17 160000 --- a/externals/date +++ b/externals/date @@ -1 +1 @@ -Subproject commit 28b7b232521ace2c8ef3f2ad4126daec3569c14f +Subproject commit a45ea7c17b4a7f320e199b71436074bd624c9e15 diff --git a/externals/dear_imgui b/externals/dear_imgui index 636cd4a7d..f4d935909 160000 --- a/externals/dear_imgui +++ b/externals/dear_imgui @@ -1 +1 @@ -Subproject commit 636cd4a7d623a2bc9bf59bb3acbb4ca075befba3 +Subproject commit f4d9359095eff3eb03f685921edc1cf0e37b1687 diff --git a/externals/discord-rpc b/externals/discord-rpc index 51b09d426..19f66e6dc 160000 --- a/externals/discord-rpc +++ b/externals/discord-rpc @@ -1 +1 @@ -Subproject commit 51b09d426a4a1bcfa6ee6d4894e57d669f4a2e65 +Subproject commit 19f66e6dcabb2268965f453db9e5774ede43238f diff --git a/externals/ffmpeg-core b/externals/ffmpeg-core index 27de97c82..b0de1dcca 160000 --- a/externals/ffmpeg-core +++ b/externals/ffmpeg-core @@ -1 +1 @@ -Subproject commit 27de97c826b6b40c255891c37ac046a25836a575 +Subproject commit b0de1dcca26c0ebfb8011b8e59dd17fc399db0ff diff --git a/externals/fmt b/externals/fmt index 8ee89546f..64db979e3 160000 --- a/externals/fmt +++ b/externals/fmt @@ -1 +1 @@ -Subproject commit 8ee89546ffcf046309d1f0d38c0393f02fde56c8 +Subproject commit 64db979e38ec644b1798e41610b28c8d2c8a2739 diff --git a/externals/glslang b/externals/glslang index a0995c49e..ba1640446 160000 --- a/externals/glslang +++ b/externals/glslang @@ -1 +1 @@ -Subproject commit a0995c49ebcaca2c6d3b03efbabf74f3843decdb +Subproject commit ba1640446f3826a518721d1f083f3a8cca1120c3 diff --git a/externals/magic_enum b/externals/magic_enum index 1a1824df7..a413fcc9c 160000 --- a/externals/magic_enum +++ b/externals/magic_enum @@ -1 +1 @@ -Subproject commit 1a1824df7ac798177a521eed952720681b0bf482 +Subproject commit a413fcc9c46a020a746907136a384c227f3cd095 diff --git a/externals/pugixml b/externals/pugixml index 4bc14418d..caade5a28 160000 --- a/externals/pugixml +++ b/externals/pugixml @@ -1 +1 @@ -Subproject commit 4bc14418d12d289dd9978fdce9490a45deeb653e +Subproject commit caade5a28aad86b92a4b5337a9dc70c4ba73c5eb diff --git a/externals/robin-map b/externals/robin-map index fe845fd78..4ec1bf19c 160000 --- a/externals/robin-map +++ b/externals/robin-map @@ -1 +1 @@ -Subproject commit fe845fd7852ef541c5479ae23b3d36b57f8608ee +Subproject commit 4ec1bf19c6a96125ea22062f38c2cf5b958e448e diff --git a/externals/sdl3 b/externals/sdl3 index a336b62d8..4093e4a19 160000 --- a/externals/sdl3 +++ b/externals/sdl3 @@ -1 +1 @@ -Subproject commit a336b62d8b0b97b09214e053203e442e2b6e2be5 +Subproject commit 4093e4a193971ef1d4928158e0a1832be42e4599 diff --git a/externals/sirit b/externals/sirit index 8b9b12c20..427a42c9e 160000 --- a/externals/sirit +++ b/externals/sirit @@ -1 +1 @@ -Subproject commit 8b9b12c2089505ac8b10fa56bf56b3ed49d9d7b0 +Subproject commit 427a42c9ed99b38204d9107bc3dc14e92458acf1 diff --git a/externals/toml11 b/externals/toml11 index 7f6c574ff..a01fe3b4c 160000 --- a/externals/toml11 +++ b/externals/toml11 @@ -1 +1 @@ -Subproject commit 7f6c574ff5aa1053534e7e19c0a4f22bf4c6aaca +Subproject commit a01fe3b4c14c6d7b99ee3f07c9e80058c6403097 diff --git a/externals/vma b/externals/vma index 5a53a1989..f378e7b3f 160000 --- a/externals/vma +++ b/externals/vma @@ -1 +1 @@ -Subproject commit 5a53a198945ba8260fbc58fadb788745ce6aa263 +Subproject commit f378e7b3f18f6e2b06b957f6ba7b1c7207d2a536 diff --git a/externals/vulkan-headers b/externals/vulkan-headers index a03d2f6d5..5ceb9ed48 160000 --- a/externals/vulkan-headers +++ b/externals/vulkan-headers @@ -1 +1 @@ -Subproject commit a03d2f6d5753b365d704d58161825890baad0755 +Subproject commit 5ceb9ed481e58e705d0d9b5326537daedd06b97d diff --git a/externals/winpthreads b/externals/winpthreads index f00c973a6..f35b0948d 160000 --- a/externals/winpthreads +++ b/externals/winpthreads @@ -1 +1 @@ -Subproject commit f00c973a6ab2a23573708568b8ef4acc20a9d36b +Subproject commit f35b0948d36a736e6a2d052ae295a3ffde09703f diff --git a/externals/xbyak b/externals/xbyak index 4e44f4614..44a72f369 160000 --- a/externals/xbyak +++ b/externals/xbyak @@ -1 +1 @@ -Subproject commit 4e44f4614ddbf038f2a6296f5b906d5c72691e0f +Subproject commit 44a72f369268f7d552650891b296693e91db86bb diff --git a/externals/xxhash b/externals/xxhash index 2bf8313b9..953a09abc 160000 --- a/externals/xxhash +++ b/externals/xxhash @@ -1 +1 @@ -Subproject commit 2bf8313b934633b2a5b7e8fd239645b85e10c852 +Subproject commit 953a09abc39096da9e216b6eb0002c681cdc1199 diff --git a/externals/zlib-ng b/externals/zlib-ng index d54e3769b..fd0d263ce 160000 --- a/externals/zlib-ng +++ b/externals/zlib-ng @@ -1 +1 @@ -Subproject commit d54e3769be0c522015b784eca2af258b1c026107 +Subproject commit fd0d263cedab1a136f40d65199987e3eaeecfcbd diff --git a/externals/zydis b/externals/zydis index bffbb610c..120e0e705 160000 --- a/externals/zydis +++ b/externals/zydis @@ -1 +1 @@ -Subproject commit bffbb610cfea643b98e87658b9058382f7522807 +Subproject commit 120e0e705f8e3b507dc49377ac2879979f0d545c From e91e36c350de1c6c5d1ec1d11282279532a1da47 Mon Sep 17 00:00:00 2001 From: w1naenator Date: Mon, 21 Apr 2025 23:56:26 +0300 Subject: [PATCH 17/20] clang, reuse fixes. --- src/core/libraries/ime/ime_dialog_ui.cpp | 4 ++-- src/core/libraries/ime/ime_dialog_ui.h | 4 +--- src/core/libraries/ime/ime_keyboard_layouts.cpp | 3 +-- src/core/libraries/ime/ime_keyboard_layouts.h | 6 ++---- src/core/libraries/ime/ime_keyboard_ui.cpp | 17 ++++++++--------- src/core/libraries/ime/ime_keyboard_ui.h | 13 +++++-------- src/core/libraries/ime/ime_ui.cpp | 3 ++- src/core/libraries/ime/ime_ui.h | 1 + 8 files changed, 22 insertions(+), 29 deletions(-) diff --git a/src/core/libraries/ime/ime_dialog_ui.cpp b/src/core/libraries/ime/ime_dialog_ui.cpp index 3c8bcfddf..e21871897 100644 --- a/src/core/libraries/ime/ime_dialog_ui.cpp +++ b/src/core/libraries/ime/ime_dialog_ui.cpp @@ -13,8 +13,8 @@ #include "core/tls.h" #include "imgui/imgui_std.h" -#include "ime_keyboard_layouts.h" // c16rtomb, layout tables -#include "ime_keyboard_ui.h" // DrawVirtualKeyboard, Utf8SafeBackspace +#include "core/libraries/ime/ime_keyboard_layouts.h" // c16rtomb, layout tables +#include "core/libraries/ime/ime_keyboard_ui.h" // DrawVirtualKeyboard, Utf8SafeBackspace using namespace ImGui; diff --git a/src/core/libraries/ime/ime_dialog_ui.h b/src/core/libraries/ime/ime_dialog_ui.h index b262207ca..19e805635 100644 --- a/src/core/libraries/ime/ime_dialog_ui.h +++ b/src/core/libraries/ime/ime_dialog_ui.h @@ -10,7 +10,7 @@ #include "common/cstring.h" #include "common/types.h" #include "core/libraries/ime/ime_dialog.h" -#include "ime_keyboard_ui.h" +#include "core/libraries/ime/ime_keyboard_ui.h" #include "imgui/imgui_layer.h" namespace Libraries::ImeDialog { @@ -105,8 +105,6 @@ public: input_changed = true; } - - private: bool CallKeyboardFilter(const OrbisImeKeycode* src_keycode, u16* out_keycode, u32* out_status); diff --git a/src/core/libraries/ime/ime_keyboard_layouts.cpp b/src/core/libraries/ime/ime_keyboard_layouts.cpp index 7642fcc22..f7b10d4a6 100644 --- a/src/core/libraries/ime/ime_keyboard_layouts.cpp +++ b/src/core/libraries/ime/ime_keyboard_layouts.cpp @@ -1,8 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include -#include "ime_keyboard_layouts.h" +#include "core/libraries/ime/ime_keyboard_layouts.h" int c16rtomb(char* out, char16_t ch) { if (ch <= 0x7F) { diff --git a/src/core/libraries/ime/ime_keyboard_layouts.h b/src/core/libraries/ime/ime_keyboard_layouts.h index b6eb8575c..045b06503 100644 --- a/src/core/libraries/ime/ime_keyboard_layouts.h +++ b/src/core/libraries/ime/ime_keyboard_layouts.h @@ -3,7 +3,6 @@ #pragma once -#include #include #include #include "common/types.h" @@ -44,12 +43,11 @@ constexpr ImGuiKey Up = ImGuiKey::ImGuiKey_GamepadDpadUp; constexpr ImGuiKey Down = ImGuiKey::ImGuiKey_GamepadDpadDown; constexpr ImGuiKey Left = ImGuiKey::ImGuiKey_GamepadDpadLeft; constexpr ImGuiKey Right = ImGuiKey::ImGuiKey_GamepadDpadRight; -constexpr ImGuiKey Cross = ImGuiKey::ImGuiKey_GamepadFaceDown; // X button +constexpr ImGuiKey Cross = ImGuiKey::ImGuiKey_GamepadFaceDown; // X button constexpr ImGuiKey Circle = ImGuiKey::ImGuiKey_GamepadFaceRight; // O button constexpr ImGuiKey Square = ImGuiKey::ImGuiKey_GamepadFaceLeft; // [] button constexpr ImGuiKey Triangle = ImGuiKey::ImGuiKey_GamepadFaceUp; // /\ button -constexpr ImGuiKey Options = ImGuiKey::ImGuiKey_GraveAccent; // Options button - +constexpr ImGuiKey Options = ImGuiKey::ImGuiKey_GraveAccent; // Options button // Fake function keycodes constexpr u16 KC_SYM1 = 0xF100; diff --git a/src/core/libraries/ime/ime_keyboard_ui.cpp b/src/core/libraries/ime/ime_keyboard_ui.cpp index 68674488c..607af8b5d 100644 --- a/src/core/libraries/ime/ime_keyboard_ui.cpp +++ b/src/core/libraries/ime/ime_keyboard_ui.cpp @@ -1,13 +1,12 @@ -#include -#include -#include -#include +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later -#include "ime_common.h" -#include "ime_dialog.h" -#include "ime_keyboard_layouts.h" -#include "ime_keyboard_ui.h" -#include "ime_ui.h" // for ImeState +// #include +#include +#include "common/cstring.h" +#include "core/libraries/ime/ime_common.h" +#include "core/libraries/ime/ime_keyboard_layouts.h" +#include "core/libraries/ime/ime_keyboard_ui.h" using namespace ImGui; diff --git a/src/core/libraries/ime/ime_keyboard_ui.h b/src/core/libraries/ime/ime_keyboard_ui.h index 9e8fdef86..8b1e43745 100644 --- a/src/core/libraries/ime/ime_keyboard_ui.h +++ b/src/core/libraries/ime/ime_keyboard_ui.h @@ -1,14 +1,11 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + #pragma once -#include -#include #include -#include "core/libraries/ime/ime.h" #include "core/libraries/ime/ime_common.h" -#include "core/libraries/ime/ime_error.h" -#include "core/libraries/ime/ime_ui.h" -#include "core/libraries/pad/pad.h" -#include "ime_keyboard_layouts.h" +#include "core/libraries/ime/ime_keyboard_layouts.h" /** * KeyboardMode: which layout we show (letters, accents, symbols, etc.) @@ -89,4 +86,4 @@ void RenderKeyboardLayout(const std::vector& layout, KeyboardMode mode */ void DrawVirtualKeyboard(KeyboardMode kb_mode, OrbisImeType ime_type, ShiftState shift_state, u64 language, void (*on_key_event)(const VirtualKeyEvent*), - const KeyboardStyle& style); + const KeyboardStyle& style); \ No newline at end of file diff --git a/src/core/libraries/ime/ime_ui.cpp b/src/core/libraries/ime/ime_ui.cpp index 811370098..37f25e200 100644 --- a/src/core/libraries/ime/ime_ui.cpp +++ b/src/core/libraries/ime/ime_ui.cpp @@ -249,4 +249,5 @@ int ImeUi::InputTextCallback(ImGuiInputTextCallbackData* data) { void ImeUi::Free() { RemoveLayer(this); } -}; // namespace Libraries::Ime \ No newline at end of file + +}; // namespace Libraries::Ime diff --git a/src/core/libraries/ime/ime_ui.h b/src/core/libraries/ime/ime_ui.h index 880e623d6..3eea22b8c 100644 --- a/src/core/libraries/ime/ime_ui.h +++ b/src/core/libraries/ime/ime_ui.h @@ -72,4 +72,5 @@ private: static int InputTextCallback(ImGuiInputTextCallbackData* data); }; + }; // namespace Libraries::Ime \ No newline at end of file From 978ce111100cf54042acac1e79f263d15315c9e6 Mon Sep 17 00:00:00 2001 From: w1naenator Date: Wed, 23 Apr 2025 18:06:01 +0300 Subject: [PATCH 18/20] Use the colors from OrbisImeParamExtended if they are defined; otherwise, use the default colors. --- src/core/libraries/ime/ime_dialog_ui.cpp | 234 +++++++++++++-------- src/core/libraries/ime/ime_dialog_ui.h | 26 ++- src/core/libraries/ime/ime_keyboard_ui.cpp | 8 + 3 files changed, 167 insertions(+), 101 deletions(-) diff --git a/src/core/libraries/ime/ime_dialog_ui.cpp b/src/core/libraries/ime/ime_dialog_ui.cpp index e21871897..e1fb7cf86 100644 --- a/src/core/libraries/ime/ime_dialog_ui.cpp +++ b/src/core/libraries/ime/ime_dialog_ui.cpp @@ -48,7 +48,8 @@ static void KeyboardCallbackBridge(const VirtualKeyEvent* evt) { * ImeDialogState : constructors, helpers *─────────────────────────────────────────────────────────────*/ ImeDialogState::ImeDialogState(const OrbisImeDialogParam* param, - const OrbisImeParamExtended* extended) { + const OrbisImeParamExtended* extended) + : extended_param_(extended) { if (!param) { return; } @@ -64,34 +65,6 @@ ImeDialogState::ImeDialogState(const OrbisImeDialogParam* param, max_text_length = param->max_text_length; text_buffer = param->input_text_buffer; - /* default keyboard style */ - has_custom_kb_style = false; - custom_kb_style.layout_width = 485.0f; - custom_kb_style.layout_height = 200.0f; - custom_kb_style.key_spacing = 2.0f; - custom_kb_style.color_text = IM_COL32(225, 225, 225, 255); - custom_kb_style.color_line = IM_COL32(88, 88, 88, 255); - custom_kb_style.color_button_default = IM_COL32(35, 35, 35, 255); - custom_kb_style.color_button_function = IM_COL32(50, 50, 50, 255); - custom_kb_style.color_special = IM_COL32(0, 140, 200, 255); - custom_kb_style.color_button_symbol = IM_COL32(60, 60, 60, 255); - custom_kb_style.use_button_symbol_color = false; - - /* optional extended palette */ - if (extended) { - custom_kb_style.layout_width = 600.0f; - custom_kb_style.layout_height = 220.0f; - custom_kb_style.key_spacing = 3.0f; - custom_kb_style.color_text = ConvertColor(extended->color_text); - custom_kb_style.color_line = ConvertColor(extended->color_line); - custom_kb_style.color_button_default = ConvertColor(extended->color_button_default); - custom_kb_style.color_button_function = ConvertColor(extended->color_button_function); - custom_kb_style.color_button_symbol = ConvertColor(extended->color_button_symbol); - custom_kb_style.color_special = ConvertColor(extended->color_special); - custom_kb_style.use_button_symbol_color = true; - has_custom_kb_style = true; - } - /* UTF‑16 → UTF‑8 conversions */ if (param->title) { std::size_t title_len = std::char_traits::length(param->title); @@ -230,15 +203,39 @@ bool ImeDialogState::ConvertUTF8ToOrbis(const char* utf8_text, std::size_t utf8_ ImeDialogUi::ImeDialogUi(ImeDialogState* state, OrbisImeDialogStatus* status, OrbisImeDialogResult* result) : state(state), status(status), result(result) { + const OrbisImeParamExtended* incoming = state ? state->GetExtendedParam() : nullptr; + if (incoming) { + // copy caller’s palette + ext_ = *incoming; + } else { + // zero-init and then overwrite the color fields you need + std::memset(&ext_, 0, sizeof(ext_)); + ext_.color_base = {19, 19, 21, 240}; + ext_.color_line = {255, 255, 255, 255}; + ext_.color_text_field = {26, 26, 28, 240}; + ext_.color_preedit = {0, 0, 0, 255}; + ext_.color_button_default = {35, 35, 35, 255}; + ext_.color_button_function = {72, 72, 74, 255}; + ext_.color_button_symbol = {96, 96, 98, 255}; + ext_.color_text = {255, 255, 255, 255}; + ext_.color_special = {0, 123, 200, 255}; + ext_.priority = OrbisImePanelPriority::Default; + } + + // For text, lines, etc. + kb_style.color_text = ConvertColor(ext_.color_text); + kb_style.color_line = ConvertColor(ext_.color_line); + + // Button colors + kb_style.color_button_default = ConvertColor(ext_.color_button_default); + kb_style.color_button_symbol = ConvertColor(ext_.color_button_symbol); + kb_style.color_button_function = ConvertColor(ext_.color_button_function); + kb_style.color_special = ConvertColor(ext_.color_special); if (state && *status == OrbisImeDialogStatus::Running) { AddLayer(this); ImeDialogUi::g_activeImeDialogUi = this; } - - if (state && state->has_custom_kb_style) { - kb_style = state->custom_kb_style; - } } ImeDialogUi::~ImeDialogUi() { @@ -303,7 +300,7 @@ void ImeDialogUi::Draw() { if (!status || *status != OrbisImeDialogStatus::Running) { return; } - + ImGui::PushStyleColor(ImGuiCol_WindowBg, ConvertColor(ext_.color_base)); const auto& ctx = *GetCurrentContext(); const auto& io = ctx.IO; @@ -325,15 +322,10 @@ void ImeDialogUi::Draw() { if (Begin("IME Dialog##ImeDialog", nullptr, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings)) { - DrawPrettyBackground(); + // DrawPrettyBackground(); /* ---------- title ---------- */ - if (!state->title.empty()) { - SetCursorPosX(20.0f); - SetWindowFontScale(1.7f); - TextUnformatted(state->title.data()); - SetWindowFontScale(1.0f); - } + DrawTitle(); /* ---------- input box ---------- */ if (state->is_multi_line) { @@ -350,50 +342,14 @@ void ImeDialogUi::Draw() { /* ---------- OK / Cancel buttons ---------- */ /* - SetCursorPosY(GetCursorPosY() + 10.0f); - - const char* button_text; - - switch (state->enter_label) { - case OrbisImeEnterLabel::Go: - button_text = "Go##ImeDialogOK"; - break; - case OrbisImeEnterLabel::Search: - button_text = "Search##ImeDialogOK"; - break; - case OrbisImeEnterLabel::Send: - button_text = "Send##ImeDialogOK"; - break; - case OrbisImeEnterLabel::Default: - default: - button_text = "OK##ImeDialogOK"; - break; - } - - float button_spacing = 10.0f; - float total_button_width = BUTTON_SIZE.x * 2 + button_spacing; - float button_start_pos = (window_size.x - total_button_width) / 2.0f; - - SetCursorPosX(button_start_pos); - - if (Button(button_text, BUTTON_SIZE) || - (!state->is_multi_line && IsKeyPressed(ImGuiKey_Enter))) { - *status = OrbisImeDialogStatus::Finished; - result->endstatus = OrbisImeDialogEndStatus::Ok; - } - - SameLine(0.0f, button_spacing); - - if (Button("Cancel##ImeDialogCancel", BUTTON_SIZE)) { - *status = OrbisImeDialogStatus::Finished; - result->endstatus = OrbisImeDialogEndStatus::UserCanceled; - } - } - */ + DrawOkAndCancelButtons(); + */ End(); } + ImGui::PopStyleColor(); + first_render = false; } @@ -401,20 +357,50 @@ void ImeDialogUi::Draw() { * helper draw functions (unchanged) *─────────────────────────────────────────────────────────────*/ void ImeDialogUi::DrawInputText() { + ImGui::BeginGroup(); + // ─── Apply ext_ colors ─────────────────────────────────────────────────── + ImGui::PushStyleColor(ImGuiCol_NavHighlight, ConvertColor(ext_.color_line)); + + ImGui::PushStyleColor(ImGuiCol_FrameBg, ConvertColor(ext_.color_text_field)); // background + ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ConvertColor(ext_.color_text_field)); + ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ConvertColor(ext_.color_text_field)); + ImGui::PushStyleColor(ImGuiCol_Border, ConvertColor(ext_.color_line)); // border line + ImGui::PushStyleColor(ImGuiCol_Text, ConvertColor(ext_.color_text)); // typed text + // ───────────────────────────────────────────────────────────────────────── ImVec2 input_size = {GetWindowWidth() - 40.0f, 0.0f}; SetCursorPosX(20.0f); if (first_render) { SetKeyboardFocusHere(); } + const char* placeholder = state->placeholder.empty() ? nullptr : state->placeholder.data(); if (InputTextEx("##ImeDialogInput", placeholder, state->current_text.begin(), state->max_text_length, input_size, ImGuiInputTextFlags_CallbackCharFilter, InputTextCallback, this)) { state->input_changed = true; } + // ────── replicate keyboard’s hover→nav focus highlight ────── + if (ImGui::IsItemHovered()) { + ImGui::SetItemCurrentNavFocus(); + ImGui::KeepNavHighlight(); + } + + // ────── pop ALL style colors (5 for input + 1 for NavHighlight) ────── + ImGui::PopStyleColor(6); + ImGui::EndGroup(); } void ImeDialogUi::DrawMultiLineInputText() { + ImGui::BeginGroup(); + // ─── Apply the same ext_ colors ─────────────────────────────────────────── + ImGui::PushStyleColor(ImGuiCol_NavHighlight, ConvertColor(ext_.color_line)); + + ImGui::PushStyleColor(ImGuiCol_FrameBg, ConvertColor(ext_.color_text_field)); + ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ConvertColor(ext_.color_text_field)); + ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ConvertColor(ext_.color_text_field)); + ImGui::PushStyleColor(ImGuiCol_Border, ConvertColor(ext_.color_line)); + ImGui::PushStyleColor(ImGuiCol_Text, ConvertColor(ext_.color_text)); + // ───────────────────────────────────────────────────────────────────────── ImVec2 input_size = {GetWindowWidth() - 40.0f, 200.0f}; SetCursorPosX(20.0f); ImGuiInputTextFlags flags = ImGuiInputTextFlags_CallbackCharFilter | @@ -423,10 +409,18 @@ void ImeDialogUi::DrawMultiLineInputText() { SetKeyboardFocusHere(); } const char* placeholder = state->placeholder.empty() ? nullptr : state->placeholder.data(); + if (InputTextEx("##ImeDialogInput", placeholder, state->current_text.begin(), state->max_text_length, input_size, flags, InputTextCallback, this)) { state->input_changed = true; } + if (ImGui::IsItemHovered()) { + ImGui::SetItemCurrentNavFocus(); + ImGui::KeepNavHighlight(); + } + + ImGui::PopStyleColor(6); + ImGui::EndGroup(); } int ImeDialogUi::InputTextCallback(ImGuiInputTextCallbackData* data) { @@ -474,6 +468,58 @@ int ImeDialogUi::InputTextCallback(ImGuiInputTextCallbackData* data) { return 0; } +void ImeDialogUi::DrawTitle() { + if (!state->title.empty()) { + SetCursorPosX(20.0f); + ImGui::PushStyleColor(ImGuiCol_Text, ConvertColor(ext_.color_text)); + SetWindowFontScale(1.7f); + TextUnformatted(state->title.data()); + SetWindowFontScale(1.0f); + ImGui::PopStyleColor(); + } +} + +void ImeDialogUi::DrawOkAndCancelButtons() { + SetCursorPosY(GetCursorPosY() + 10.0f); + + const char* button_text; + + switch (state->enter_label) { + case OrbisImeEnterLabel::Go: + button_text = "Go##ImeDialogOK"; + break; + case OrbisImeEnterLabel::Search: + button_text = "Search##ImeDialogOK"; + break; + case OrbisImeEnterLabel::Send: + button_text = "Send##ImeDialogOK"; + break; + case OrbisImeEnterLabel::Default: + default: + button_text = "OK##ImeDialogOK"; + break; + } + + float button_spacing = 10.0f; + float total_button_width = BUTTON_SIZE.x * 2 + button_spacing; + float button_start_pos = (GetWindowWidth() - total_button_width) / 2.0f; + + SetCursorPosX(button_start_pos); + + if (Button(button_text, BUTTON_SIZE) || + (!state->is_multi_line && IsKeyPressed(ImGuiKey_Enter))) { + *status = OrbisImeDialogStatus::Finished; + result->endstatus = OrbisImeDialogEndStatus::Ok; + } + + SameLine(0.0f, button_spacing); + + if (Button("Cancel##ImeDialogCancel", BUTTON_SIZE)) { + *status = OrbisImeDialogStatus::Finished; + result->endstatus = OrbisImeDialogEndStatus::UserCanceled; + } +} + /* draw keyboard in a sub‑ID scope */ void ImeDialogUi::DrawVirtualKeyboardSection() { ImGui::PushID("VirtualKeyboardSection"); @@ -486,7 +532,7 @@ void ImeDialogUi::DrawPredictionBarAnCancelButton() { const float pad = 5.0f; const float width = kb_style.layout_width; const float bar_h = 25.0f; - + SetCursorPosY(GetCursorPosY() + 5.0f); SetCursorPosX(0.0f); ImVec2 p0 = GetCursorScreenPos(); ImVec2 p1 = ImVec2(p0.x + width - bar_h - 2 * pad, p0.y + bar_h); @@ -499,13 +545,20 @@ void ImeDialogUi::DrawPredictionBarAnCancelButton() { // ImGui::PopStyleColor(); SetCursorPosX(pad); - ImGui::PushStyleColor(ImGuiCol_Button, IM_COL32(0, 0, 0, 255)); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, IM_COL32(0, 0, 0, 255)); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, IM_COL32(0, 0, 0, 255)); - ImGui::PushStyleColor(ImGuiCol_Text, kb_style.color_text); + ImGui::PushStyleColor(ImGuiCol_NavHighlight, ConvertColor(ext_.color_line)); + ImGui::PushStyleColor(ImGuiCol_Button, ConvertColor(ext_.color_preedit)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ConvertColor(ext_.color_preedit)); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ConvertColor(ext_.color_preedit)); + ImGui::PushStyleColor(ImGuiCol_Text, ConvertColor(ext_.color_text)); if (ImGui::Button("predict", ImVec2(width - bar_h - 3 * pad, bar_h))) { } + + if (ImGui::IsItemHovered()) { + ImGui::SetItemCurrentNavFocus(); + ImGui::KeepNavHighlight(); + } + ImGui::PopStyleColor(4); /* X button */ @@ -521,7 +574,14 @@ void ImeDialogUi::DrawPredictionBarAnCancelButton() { *status = OrbisImeDialogStatus::Finished; result->endstatus = OrbisImeDialogEndStatus::UserCanceled; } - ImGui::PopStyleColor(4); + + if (ImGui::IsItemHovered()) { + ImGui::SetItemCurrentNavFocus(); + ImGui::KeepNavHighlight(); + } + + ImGui::PopStyleColor(5); + SetCursorPosX(0.0f); SetCursorPosY(GetCursorPosY() + 5.0f); } diff --git a/src/core/libraries/ime/ime_dialog_ui.h b/src/core/libraries/ime/ime_dialog_ui.h index 19e805635..516a30785 100644 --- a/src/core/libraries/ime/ime_dialog_ui.h +++ b/src/core/libraries/ime/ime_dialog_ui.h @@ -38,12 +38,12 @@ class ImeDialogState final { char16_t* text_buffer{}; std::vector title; std::vector placeholder; - + const OrbisImeParamExtended* extended_param_ = nullptr; // A character can hold up to 4 bytes in UTF-8 Common::CString current_text; // Optional custom keyboard style (from extended params) - bool has_custom_kb_style = false; + bool has_custom_style = false; KeyboardStyle custom_kb_style{}; public: @@ -77,6 +77,10 @@ public: return current_text.begin(); } + const OrbisImeParamExtended* GetExtendedParam() const { + return extended_param_; + } + /*─────────────────── public write helpers ───────────────────*/ // Replace the whole text buffer void SetTextUtf8(const char* utf8) { @@ -126,6 +130,8 @@ class ImeDialogUi final : public ImGui::Layer { bool first_render = true; std::mutex draw_mutex; + OrbisImeParamExtended ext_; + public: // Global pointer to the active dialog‑UI (used by the callback bridge) static ImeDialogUi* g_activeImeDialogUi; @@ -153,23 +159,15 @@ private: static int InputTextCallback(ImGuiInputTextCallbackData* data); + void DrawTitle(); + + void DrawOkAndCancelButtons(); + /*── keyboard section ─*/ KeyboardMode kb_mode = KeyboardMode::Letters; ShiftState shift_state = ShiftState::None; u64 kb_language = 0; KeyboardStyle kb_style; - /* KeyboardStyle kb_style{ - .layout_width = 500.0f, - .layout_height = 250.0f, - .key_spacing = 5.0f, - .color_text = IM_COL32(225,225,225,255), - .color_line = IM_COL32( 88, 88, 88,255), - .color_button_default = IM_COL32( 35, 35, 35,255), - .color_button_function = IM_COL32( 50, 50, 50,255), - .color_special = IM_COL32( 0,140,200,255), - .use_button_symbol_color= false, - .color_button_symbol = IM_COL32( 60, 60, 60,255), - };*/ void DrawVirtualKeyboardSection(); void DrawPredictionBarAnCancelButton(); diff --git a/src/core/libraries/ime/ime_keyboard_ui.cpp b/src/core/libraries/ime/ime_keyboard_ui.cpp index 607af8b5d..1f5b6b97c 100644 --- a/src/core/libraries/ime/ime_keyboard_ui.cpp +++ b/src/core/libraries/ime/ime_keyboard_ui.cpp @@ -4,9 +4,11 @@ // #include #include #include "common/cstring.h" +#include "common/types.h" #include "core/libraries/ime/ime_common.h" #include "core/libraries/ime/ime_keyboard_layouts.h" #include "core/libraries/ime/ime_keyboard_ui.h" +#include "imgui/imgui_std.h" using namespace ImGui; @@ -169,6 +171,12 @@ void RenderKeyboardLayout(const std::vector& layout, KeyboardMode mode ImGui::SetCursorScreenPos(pos); bool pressed = ImGui::Button(label.c_str(), size); // Down + repeats + // ——— use ImGui’s built‑in hover highlight ——— + if (ImGui::IsItemHovered()) { + ImGui::SetItemCurrentNavFocus(); + ImGui::KeepNavHighlight(); + } + if (key.allow_repeat) ImGui::PopButtonRepeat(); From 0aca8726b99fdae486a97f4d62d6ac53c3066be9 Mon Sep 17 00:00:00 2001 From: w1naenator Date: Sun, 27 Apr 2025 03:39:48 +0300 Subject: [PATCH 19/20] Undertale softlock fix. --- src/core/libraries/ime/ime_dialog.cpp | 86 +++++++++++++++++++++++- src/core/libraries/ime/ime_dialog.h | 2 +- src/core/libraries/ime/ime_dialog_ui.cpp | 6 +- 3 files changed, 89 insertions(+), 5 deletions(-) diff --git a/src/core/libraries/ime/ime_dialog.cpp b/src/core/libraries/ime/ime_dialog.cpp index 9151aa64e..90ae65def 100644 --- a/src/core/libraries/ime/ime_dialog.cpp +++ b/src/core/libraries/ime/ime_dialog.cpp @@ -122,7 +122,91 @@ OrbisImeDialogStatus PS4_SYSV_ABI sceImeDialogGetStatus() { return g_ime_dlg_status; } +#include + +#include + +static std::string ConvertUtf16ToUtf8(const char16_t* src) { + if (!src) { + return "(null)"; + } + + std::string result; + while (*src) { + char16_t c = *src++; + + if (c < 0x80) { + result += static_cast(c); + } else if (c < 0x800) { + result += static_cast(0xC0 | (c >> 6)); + result += static_cast(0x80 | (c & 0x3F)); + } else { + result += static_cast(0xE0 | (c >> 12)); + result += static_cast(0x80 | ((c >> 6) & 0x3F)); + result += static_cast(0x80 | (c & 0x3F)); + } + } + + return result; +} + +void DumpImeDialogParam(const Libraries::ImeDialog::OrbisImeDialogParam* param, + const Libraries::ImeDialog::OrbisImeParamExtended* ext_param) { + if (!param) { + LOG_INFO(Lib_ImeDialog, "OpenImeDialog called with null param."); + return; + } + + // UTF-16 to UTF-8 conversion using your safe method + std::string title_utf8 = "(null)"; + std::string placeholder_utf8 = "(null)"; + title_utf8 = ConvertUtf16ToUtf8(param->title); + placeholder_utf8 = ConvertUtf16ToUtf8(param->placeholder); + + LOG_INFO( + Lib_ImeDialog, + "OpenImeDialog:\n" + " user_id={}, type={}, option=0x{:X}, max_text_length={}, supported_languages=0x{:X}\n" + " title=\"{}\", placeholder=\"{}\", input_text_buffer={}", + param->user_id, static_cast(param->type), static_cast(param->option), + param->max_text_length, param->supported_languages, title_utf8, placeholder_utf8, + param->input_text_buffer ? reinterpret_cast(param->input_text_buffer) : 0); + + if (ext_param) { + LOG_INFO(Lib_ImeDialog, + "ExtendedParam:\n" + " color_base=({}, {}, {}, {}) color_line=({}, {}, {}, {}) color_text_field=({}, " + "{}, {}, {})\n" + " color_preedit=({}, {}, {}, {}) color_button_default=({}, {}, {}, {}) " + "color_button_function=({}, {}, {}, {})\n" + " color_button_symbol=({}, {}, {}, {}) color_text=({}, {}, {}, {}) " + "color_special=({}, {}, {}, {})\n" + " priority={}", + ext_param->color_base.r, ext_param->color_base.g, ext_param->color_base.b, + ext_param->color_base.a, ext_param->color_line.r, ext_param->color_line.g, + ext_param->color_line.b, ext_param->color_line.a, ext_param->color_text_field.r, + ext_param->color_text_field.g, ext_param->color_text_field.b, + ext_param->color_text_field.a, ext_param->color_preedit.r, + ext_param->color_preedit.g, ext_param->color_preedit.b, ext_param->color_preedit.a, + ext_param->color_button_default.r, ext_param->color_button_default.g, + ext_param->color_button_default.b, ext_param->color_button_default.a, + ext_param->color_button_function.r, ext_param->color_button_function.g, + ext_param->color_button_function.b, ext_param->color_button_function.a, + ext_param->color_button_symbol.r, ext_param->color_button_symbol.g, + ext_param->color_button_symbol.b, ext_param->color_button_symbol.a, + ext_param->color_text.r, ext_param->color_text.g, ext_param->color_text.b, + ext_param->color_text.a, ext_param->color_special.r, ext_param->color_special.g, + ext_param->color_special.b, ext_param->color_special.a, + static_cast(ext_param->priority)); + } else { + LOG_INFO(Lib_ImeDialog, "ExtendedParam: (none)"); + } +} + Error PS4_SYSV_ABI sceImeDialogInit(OrbisImeDialogParam* param, OrbisImeParamExtended* extended) { + + DumpImeDialogParam(param, extended); + if (g_ime_dlg_status != OrbisImeDialogStatus::None) { LOG_INFO(Lib_ImeDialog, "IME dialog is already running"); return Error::BUSY; @@ -195,7 +279,7 @@ Error PS4_SYSV_ABI sceImeDialogInit(OrbisImeDialogParam* param, OrbisImeParamExt } if (param->max_text_length > ORBIS_IME_DIALOG_MAX_TEXT_LENGTH) { - LOG_INFO(Lib_ImeDialog, "Invalid param->maxTextLength"); + LOG_INFO(Lib_ImeDialog, "Invalid param->maxTextLength ({})", param->max_text_length); return Error::INVALID_MAX_TEXT_LENGTH; } diff --git a/src/core/libraries/ime/ime_dialog.h b/src/core/libraries/ime/ime_dialog.h index c8b228498..e19070274 100644 --- a/src/core/libraries/ime/ime_dialog.h +++ b/src/core/libraries/ime/ime_dialog.h @@ -13,7 +13,7 @@ class SymbolsResolver; namespace Libraries::ImeDialog { -constexpr u32 ORBIS_IME_DIALOG_MAX_TEXT_LENGTH = 0x78; +constexpr u32 ORBIS_IME_DIALOG_MAX_TEXT_LENGTH = 0x3FF; // 0x78; enum class Error : u32 { OK = 0x0, diff --git a/src/core/libraries/ime/ime_dialog_ui.cpp b/src/core/libraries/ime/ime_dialog_ui.cpp index e1fb7cf86..698f531f0 100644 --- a/src/core/libraries/ime/ime_dialog_ui.cpp +++ b/src/core/libraries/ime/ime_dialog_ui.cpp @@ -214,7 +214,7 @@ ImeDialogUi::ImeDialogUi(ImeDialogState* state, OrbisImeDialogStatus* status, ext_.color_line = {255, 255, 255, 255}; ext_.color_text_field = {26, 26, 28, 240}; ext_.color_preedit = {0, 0, 0, 255}; - ext_.color_button_default = {35, 35, 35, 255}; + ext_.color_button_default = {45, 45, 45, 255}; ext_.color_button_function = {72, 72, 74, 255}; ext_.color_button_symbol = {96, 96, 98, 255}; ext_.color_text = {255, 255, 255, 255}; @@ -445,8 +445,8 @@ int ImeDialogUi::InputTextCallback(ImGuiInputTextCallbackData* data) { .keycode = 0, .character = 0, .status = 1, // ??? 1 = key pressed, 0 = key released - .type = OrbisImeKeyboardType::ENGLISH_US, // TODO set this to the correct value (maybe use - // the current language?) + .type = OrbisImeKeyboardType::ENGLISH_US, // TODO set this to the correct value (maybe + // use the current language?) .user_id = ui->state->user_id, .resource_id = 0, .timestamp = 0, From bdd2b4d4c9c15791c7f588b9e7a4d0d3ba81899e Mon Sep 17 00:00:00 2001 From: w1naenator Date: Wed, 30 Apr 2025 01:47:43 +0300 Subject: [PATCH 20/20] Initial caret draw/control --- src/core/libraries/ime/ime_dialog_ui.cpp | 27 +++++++++-- src/core/libraries/ime/ime_dialog_ui.h | 46 ++++++++++++++++--- src/core/libraries/ime/ime_keyboard_layouts.h | 6 ++- src/imgui/imgui_std.h | 19 ++++++++ 4 files changed, 87 insertions(+), 11 deletions(-) diff --git a/src/core/libraries/ime/ime_dialog_ui.cpp b/src/core/libraries/ime/ime_dialog_ui.cpp index 698f531f0..92a1a630b 100644 --- a/src/core/libraries/ime/ime_dialog_ui.cpp +++ b/src/core/libraries/ime/ime_dialog_ui.cpp @@ -379,6 +379,16 @@ void ImeDialogUi::DrawInputText() { InputTextCallback, this)) { state->input_changed = true; } + + // CARET: manually render even if not focused + if (!ImGui::IsItemActive()) { + // Calculate input field position + ImVec2 input_pos = ImGui::GetItemRectMin(); + + // Find where to draw the caret + DrawCaretForInputText(state->current_text.begin(), state->caret_index, input_pos); + } + // ────── replicate keyboard’s hover→nav focus highlight ────── if (ImGui::IsItemHovered()) { ImGui::SetItemCurrentNavFocus(); @@ -601,14 +611,25 @@ void ImeDialogUi::OnVirtualKeyEvent(const VirtualKeyEvent* evt) { case KeyType::Character: { char utf8[8]{}; int n = c16rtomb(utf8, key->character); - if (n > 0) - state->AppendUtf8(utf8, (size_t)n); + if (n > 0) { + state->InsertUtf8AtCaret(utf8, (size_t)n); + } break; } case KeyType::Function: switch (key->keycode) { + case KC_LEFT: // Your custom code for ◀ button + if (state->caret_index > 0) + state->caret_index--; + LOG_INFO(Lib_ImeDialog, "Caret index = {}", state->caret_index); + break; + case KC_RIGHT: // Your custom code for ▶ button + if (state->caret_index < (int)state->current_text.size()) + state->caret_index++; + LOG_INFO(Lib_ImeDialog, "Caret index = {}", state->caret_index); + break; case 0x08: - state->BackspaceUtf8(); + state->BackspaceUtf8AtCaret(); break; // Backspace case 0x0D: *status = OrbisImeDialogStatus::Finished; // Enter diff --git a/src/core/libraries/ime/ime_dialog_ui.h b/src/core/libraries/ime/ime_dialog_ui.h index 516a30785..e1a3c0b40 100644 --- a/src/core/libraries/ime/ime_dialog_ui.h +++ b/src/core/libraries/ime/ime_dialog_ui.h @@ -45,6 +45,7 @@ class ImeDialogState final { // Optional custom keyboard style (from extended params) bool has_custom_style = false; KeyboardStyle custom_kb_style{}; + int caret_index = 0; public: /*──────────────── constructors / rule‑of‑five ────────────────*/ @@ -91,15 +92,23 @@ public: input_changed = true; } - // Append raw UTF‑8 sequence of length 'len' - void AppendUtf8(const char* utf8, std::size_t len) { + void InsertUtf8AtCaret(const char* utf8, std::size_t len) { if (!utf8 || len == 0) return; - std::size_t old = std::strlen(current_text.begin()); - if (old + len >= current_text.capacity()) - return; // full: silently ignore - std::memcpy(current_text.begin() + old, utf8, len); - current_text[old + len] = '\0'; + + std::size_t old_len = std::strlen(current_text.begin()); + if (old_len + len >= current_text.capacity()) + return; // full, silently ignore + + // Move the text after caret forward + char* text_begin = current_text.begin(); + std::memmove(text_begin + caret_index + len, text_begin + caret_index, + old_len - caret_index + 1); // +1 for null-terminator + + // Copy the inserted text at caret position + std::memcpy(text_begin + caret_index, utf8, len); + + caret_index += (int)len; // Move caret after inserted text input_changed = true; } @@ -109,6 +118,29 @@ public: input_changed = true; } + void BackspaceUtf8AtCaret() { + char* buf = current_text.begin(); + size_t len = std::strlen(buf); + + if (caret_index == 0 || len == 0) + return; + + // Find byte index just before caret (start of previous codepoint) + int remove_start = caret_index - 1; + while (remove_start > 0 && + (static_cast(buf[remove_start]) & 0b11000000) == 0b10000000) + --remove_start; + + int remove_len = caret_index - remove_start; + + // Shift everything after caret to the left + std::memmove(buf + remove_start, buf + caret_index, + len - caret_index + 1); // +1 to move null terminator + caret_index = remove_start; + + input_changed = true; + } + private: bool CallKeyboardFilter(const OrbisImeKeycode* src_keycode, u16* out_keycode, u32* out_status); diff --git a/src/core/libraries/ime/ime_keyboard_layouts.h b/src/core/libraries/ime/ime_keyboard_layouts.h index 045b06503..4e5cdc18a 100644 --- a/src/core/libraries/ime/ime_keyboard_layouts.h +++ b/src/core/libraries/ime/ime_keyboard_layouts.h @@ -56,4 +56,8 @@ constexpr u16 KC_ACCENTS = 0xF102; constexpr u16 KC_LETTERS = 0xF103; constexpr u16 KC_KB = 0xF104; constexpr u16 KC_GYRO = 0xF105; -constexpr u16 KC_OPT = 0xF106; \ No newline at end of file +constexpr u16 KC_OPT = 0xF106; +constexpr u16 KC_UP = 0xF020; +constexpr u16 KC_DOWN = 0xF021; +constexpr u16 KC_LEFT = 0xF022; +constexpr u16 KC_RIGHT = 0xF023; diff --git a/src/imgui/imgui_std.h b/src/imgui/imgui_std.h index 743702657..82770258e 100644 --- a/src/imgui/imgui_std.h +++ b/src/imgui/imgui_std.h @@ -88,4 +88,23 @@ static void DrawCenteredText(const char* text, const char* text_end = nullptr, SetCursorPos(pos + content); } +inline void DrawCaretForInputText(const char* text, int caret_index, ImVec2 input_pos, + float padding_x = 4.0f, float padding_y = 3.0f) { + ImVec2 text_size = ImGui::CalcTextSize(text, text + caret_index); + float caret_x = input_pos.x + padding_x + text_size.x; + float caret_y = input_pos.y + padding_y; + + float caret_height = ImGui::GetTextLineHeight(); + + // Optional: make caret blink like ImGui does + float time = ImGui::GetTime(); + bool visible = (fmodf(time, 1.2f) < 0.8f); + if (!visible) + return; + + ImGui::GetWindowDrawList()->AddLine(ImVec2(caret_x, caret_y), + ImVec2(caret_x, caret_y + caret_height), + IM_COL32(255, 255, 255, 255), 1.0f); +} + } // namespace ImGui