Redesign layout closer original

This commit is contained in:
w1naenator 2025-03-28 17:33:22 +02:00
parent 569ab0c87f
commit 5a874b18ba
7 changed files with 428 additions and 82 deletions

View File

@ -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_dialog.h
src/core/libraries/ime/ime_ui.cpp src/core/libraries/ime/ime_ui.cpp
src/core/libraries/ime/ime_ui.h 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.cpp
src/core/libraries/ime/ime_keyboard_ui.h src/core/libraries/ime/ime_keyboard_ui.h
src/core/libraries/ime/ime.cpp src/core/libraries/ime/ime.cpp

View File

@ -351,8 +351,15 @@ void ImeDialogUi::DrawKeyboard() {
has_logged = true; has_logged = true;
} }
bool done_pressed = false;
DrawVirtualKeyboard(state->current_text.begin(), state->max_text_length * 4, 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) { int ImeDialogUi::InputTextCallback(ImGuiInputTextCallbackData* data) {

View File

@ -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<Key> 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<Key> 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<Key> 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},
};

View File

@ -0,0 +1,41 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <string>
#include <vector>
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<Key> kUppercaseLayout;
extern const std::vector<Key> kLowercaseLayout;
extern const std::vector<Key> kSymbols1Layout;

View File

@ -1,96 +1,134 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <cctype>
#include <cstring> #include <cstring>
#include <string>
#include <imgui.h> #include <imgui.h>
#include "ime_keyboard_layouts.h"
#include "ime_keyboard_ui.h" #include "ime_keyboard_ui.h"
using namespace ImGui;
void DrawVirtualKeyboard(char* buffer, std::size_t buffer_capacity, bool* input_changed, 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) {
const char* row1_letters = "QWERTYUIOP"; const std::vector<Key>* layout = nullptr;
const char* row2_letters = "ASDFGHJKL";
const char* row3_letters = "ZXCVBNM";
const char* row1_symbols = "1234567890"; if (kb_mode == KeyboardMode::Symbols) {
const char* row2_symbols = "!@#$%^&*()"; layout = &kSymbols1Layout;
const char* row3_symbols = "-_=+[]{}"; } else {
layout = shift_enabled ? &kUppercaseLayout : &kLowercaseLayout;
}
auto draw_row = [&](const char* row, float offset_x) { RenderKeyboardLayout(*layout, buffer, buffer_capacity, input_changed, kb_mode, shift_enabled,
ImGui::SetCursorPosX(offset_x); done_pressed);
for (int i = 0; row[i] != '\0'; ++i) { }
char ch = shift_enabled ? row[i] : static_cast<char>(tolower(row[i]));
std::string key(1, ch); void RenderKeyboardLayout(const std::vector<Key>& layout, char* buffer, std::size_t buffer_capacity,
if (ImGui::Button(key.c_str(), ImVec2(35, 35))) { bool* input_changed, KeyboardMode& kb_mode, bool& shift_enabled,
size_t len = std::strlen(buffer); bool* done_pressed) {
if (len + 1 < buffer_capacity) { // Define desired total layout size (in pixels)
buffer[len] = ch; const float layout_width = 485.0f;
buffer[len + 1] = '\0'; const float layout_height = 200.0f;
if (input_changed) { const float cell_spacing = 4.0f;
*input_changed = true; 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<int>(key.colspan));
max_row = std::max(max_row, key.row + static_cast<int>(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;
} }
} }
} break;
ImGui::SameLine(); case KeyType::Backspace:
} if (buffer[0] != '\0') {
ImGui::NewLine(); size_t len = std::strlen(buffer);
}; buffer[len - 1] = '\0';
if (input_changed)
// SHIFT status label *input_changed = true;
if (shift_enabled) { }
ImGui::SetCursorPosX(20.0f); break;
ImGui::TextColored(ImVec4(0.2f, 0.6f, 1.0f, 1.0f), "SHIFT ENABLED"); case KeyType::Space:
} if (std::strlen(buffer) + 1 < buffer_capacity) {
std::strcat(buffer, " ");
draw_row(kb_mode == KeyboardMode::Letters ? row1_letters : row1_symbols, 20.0f); if (input_changed)
draw_row(kb_mode == KeyboardMode::Letters ? row2_letters : row2_symbols, 35.0f); *input_changed = true;
draw_row(kb_mode == KeyboardMode::Letters ? row3_letters : row3_symbols, 80.0f); }
break;
ImGui::SetCursorPosX(20.0f); case KeyType::Enter:
case KeyType::Done:
bool highlight = shift_enabled; if (done_pressed)
if (highlight) { *done_pressed = true;
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.2f, 0.6f, 1.0f, 1.0f)); break;
} case KeyType::Shift:
shift_enabled = !shift_enabled;
if (ImGui::Button("SHIFT", ImVec2(75, 35))) { break;
shift_enabled = !shift_enabled; case KeyType::SymbolsLayout:
} kb_mode = KeyboardMode::Symbols;
break;
if (highlight) { case KeyType::TextLayout:
ImGui::PopStyleColor(); kb_mode = KeyboardMode::Letters;
} break;
case KeyType::ToggleKeyboard:
ImGui::SameLine(); kb_mode = (kb_mode == KeyboardMode::Letters) ? KeyboardMode::Symbols
: KeyboardMode::Letters;
if (ImGui::Button("SPACE", ImVec2(100, 35))) { break;
size_t len = std::strlen(buffer); default:
if (len + 1 < buffer_capacity) { break;
buffer[len] = ' ';
buffer[len + 1] = '\0';
if (input_changed) {
*input_changed = true;
} }
} }
}
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))) { ImVec2 text_size =
size_t len = std::strlen(buffer); ImGui::CalcTextSize(key.controller_hint.c_str(), nullptr, false, -1.0f) *
if (len > 0) { (small_font_size / original_font_size);
buffer[len - 1] = '\0';
if (input_changed) { ImVec2 text_pos = pos + ImVec2(hint_padding, hint_padding);
*input_changed = true; 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;
}
} }

View File

@ -1,9 +1,23 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once
#include "common/cstring.h" #include "common/cstring.h"
#include "common/types.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 }; 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, 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<Key>& layout, char* buffer, std::size_t buffer_capacity,
bool* input_changed, KeyboardMode& kb_mode, bool& shift_enabled,
bool* done_pressed);

View File

@ -195,12 +195,19 @@ void ImeUi::DrawKeyboard() {
static bool has_logged = false; static bool has_logged = false;
if (!has_logged) { if (!has_logged) {
LOG_INFO(Lib_ImeDialog, "Virtual keyboard used from Ime"); LOG_INFO(Lib_Ime, "Virtual keyboard used from ImeUi");
has_logged = true; has_logged = true;
} }
DrawVirtualKeyboard(state->current_text.begin(), ime_param->maxTextLength * 4, nullptr, kb_mode, bool input_changed = false;
shift_enabled); 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) { int ImeUi::InputTextCallback(ImGuiInputTextCallbackData* data) {