mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-25 11:34:55 +00:00
replace ImGuiNavInput with ImGuiKey
added repeat event selectable for each key.
This commit is contained in:
parent
33b1afb6a0
commit
df25e2da7b
@ -1,8 +1,5 @@
|
|||||||
// ime_dialog_ui.cpp
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
// ----------------------------------------------------------
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
// Full implementation of IME dialog UI with on‑screen keyboard
|
|
||||||
// (all original logic intact, bugs fixed).
|
|
||||||
// ----------------------------------------------------------
|
|
||||||
|
|
||||||
#include <cwchar>
|
#include <cwchar>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -52,13 +49,14 @@ static void KeyboardCallbackBridge(const VirtualKeyEvent* evt) {
|
|||||||
*─────────────────────────────────────────────────────────────*/
|
*─────────────────────────────────────────────────────────────*/
|
||||||
ImeDialogState::ImeDialogState(const OrbisImeDialogParam* param,
|
ImeDialogState::ImeDialogState(const OrbisImeDialogParam* param,
|
||||||
const OrbisImeParamExtended* extended) {
|
const OrbisImeParamExtended* extended) {
|
||||||
if (!param)
|
if (!param) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* basic param copy */
|
/* basic param copy */
|
||||||
user_id = param->user_id;
|
user_id = param->user_id;
|
||||||
is_multi_line = True(param->option & OrbisImeDialogOption::Multiline);
|
is_multi_line = True(param->option & OrbisImeDialogOption::Multiline);
|
||||||
is_numeric = (param->type == OrbisImeType::Number);
|
is_numeric = param->type == OrbisImeType::Number;
|
||||||
type = param->type;
|
type = param->type;
|
||||||
enter_label = param->enter_label;
|
enter_label = param->enter_label;
|
||||||
text_filter = param->filter;
|
text_filter = param->filter;
|
||||||
@ -262,7 +260,7 @@ ImeDialogUi::ImeDialogUi(ImeDialogUi&& other) noexcept
|
|||||||
other.status = nullptr;
|
other.status = nullptr;
|
||||||
other.result = nullptr;
|
other.result = nullptr;
|
||||||
|
|
||||||
if (state && status && *status == OrbisImeDialogStatus::Running) {
|
if (state && *status == OrbisImeDialogStatus::Running) {
|
||||||
AddLayer(this);
|
AddLayer(this);
|
||||||
ImeDialogUi::g_activeImeDialogUi = this;
|
ImeDialogUi::g_activeImeDialogUi = this;
|
||||||
}
|
}
|
||||||
@ -276,12 +274,11 @@ ImeDialogUi& ImeDialogUi::operator=(ImeDialogUi&& other) {
|
|||||||
status = other.status;
|
status = other.status;
|
||||||
result = other.result;
|
result = other.result;
|
||||||
first_render = other.first_render;
|
first_render = other.first_render;
|
||||||
|
|
||||||
other.state = nullptr;
|
other.state = nullptr;
|
||||||
other.status = nullptr;
|
other.status = nullptr;
|
||||||
other.result = nullptr;
|
other.result = nullptr;
|
||||||
|
|
||||||
if (state && status && *status == OrbisImeDialogStatus::Running) {
|
if (state && *status == OrbisImeDialogStatus::Running) {
|
||||||
AddLayer(this);
|
AddLayer(this);
|
||||||
ImeDialogUi::g_activeImeDialogUi = this;
|
ImeDialogUi::g_activeImeDialogUi = this;
|
||||||
}
|
}
|
||||||
@ -329,6 +326,7 @@ void ImeDialogUi::Draw() {
|
|||||||
if (Begin("IME Dialog##ImeDialog", nullptr,
|
if (Begin("IME Dialog##ImeDialog", nullptr,
|
||||||
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings)) {
|
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings)) {
|
||||||
DrawPrettyBackground();
|
DrawPrettyBackground();
|
||||||
|
|
||||||
/* ---------- title ---------- */
|
/* ---------- title ---------- */
|
||||||
if (!state->title.empty()) {
|
if (!state->title.empty()) {
|
||||||
SetCursorPosX(20.0f);
|
SetCursorPosX(20.0f);
|
||||||
@ -351,41 +349,47 @@ void ImeDialogUi::Draw() {
|
|||||||
DrawVirtualKeyboardSection();
|
DrawVirtualKeyboardSection();
|
||||||
|
|
||||||
/* ---------- OK / Cancel buttons ---------- */
|
/* ---------- OK / Cancel buttons ---------- */
|
||||||
/* {
|
/*
|
||||||
SetCursorPosY(GetCursorPosY() + 10.0f);
|
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 spacing = 10.0f;
|
const char* button_text;
|
||||||
float total_w = BUTTON_SIZE.x * 2 + spacing;
|
|
||||||
float x_start = (window_size.x - total_w) / 2.0f;
|
|
||||||
SetCursorPosX(x_start);
|
|
||||||
|
|
||||||
if (Button(ok_lbl, BUTTON_SIZE) ||
|
switch (state->enter_label) {
|
||||||
(!state->is_multi_line && IsKeyPressed(ImGuiKey_Enter))) {
|
case OrbisImeEnterLabel::Go:
|
||||||
*status = OrbisImeDialogStatus::Finished;
|
button_text = "Go##ImeDialogOK";
|
||||||
result->endstatus = OrbisImeDialogEndStatus::Ok;
|
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)) {
|
SetCursorPosX(button_start_pos);
|
||||||
*status = OrbisImeDialogStatus::Finished;
|
|
||||||
result->endstatus = OrbisImeDialogEndStatus::UserCanceled;
|
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();
|
End();
|
||||||
}
|
}
|
||||||
@ -397,65 +401,131 @@ void ImeDialogUi::Draw() {
|
|||||||
* helper draw functions (unchanged)
|
* helper draw functions (unchanged)
|
||||||
*─────────────────────────────────────────────────────────────*/
|
*─────────────────────────────────────────────────────────────*/
|
||||||
void ImeDialogUi::DrawInputText() {
|
void ImeDialogUi::DrawInputText() {
|
||||||
ImVec2 size(GetWindowWidth() - 40.0f, 0.0f);
|
ImVec2 input_size = {GetWindowWidth() - 40.0f, 0.0f};
|
||||||
SetCursorPosX(20.0f);
|
SetCursorPosX(20.0f);
|
||||||
if (first_render)
|
if (first_render) {
|
||||||
SetKeyboardFocusHere();
|
SetKeyboardFocusHere();
|
||||||
|
}
|
||||||
const char* ph = state->placeholder.empty() ? nullptr : state->placeholder.data();
|
const char* placeholder = state->placeholder.empty() ? nullptr : state->placeholder.data();
|
||||||
if (InputTextEx("##ImeDialogInput", ph, state->current_text.begin(), state->max_text_length,
|
if (InputTextEx("##ImeDialogInput", placeholder, state->current_text.begin(),
|
||||||
size, ImGuiInputTextFlags_CallbackCharFilter, InputTextCallback, this))
|
state->max_text_length, input_size, ImGuiInputTextFlags_CallbackCharFilter,
|
||||||
|
InputTextCallback, this)) {
|
||||||
state->input_changed = true;
|
state->input_changed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImeDialogUi::DrawMultiLineInputText() {
|
void ImeDialogUi::DrawMultiLineInputText() {
|
||||||
ImVec2 size(GetWindowWidth() - 40.0f, 200.0f);
|
ImVec2 input_size = {GetWindowWidth() - 40.0f, 200.0f};
|
||||||
SetCursorPosX(20.0f);
|
SetCursorPosX(20.0f);
|
||||||
ImGuiInputTextFlags flags = ImGuiInputTextFlags_CallbackCharFilter |
|
ImGuiInputTextFlags flags = ImGuiInputTextFlags_CallbackCharFilter |
|
||||||
static_cast<ImGuiInputTextFlags>(ImGuiInputTextFlags_Multiline);
|
static_cast<ImGuiInputTextFlags>(ImGuiInputTextFlags_Multiline);
|
||||||
if (first_render)
|
if (first_render) {
|
||||||
SetKeyboardFocusHere();
|
SetKeyboardFocusHere();
|
||||||
|
}
|
||||||
const char* ph = state->placeholder.empty() ? nullptr : state->placeholder.data();
|
const char* placeholder = state->placeholder.empty() ? nullptr : state->placeholder.data();
|
||||||
if (InputTextEx("##ImeDialogInput", ph, state->current_text.begin(), state->max_text_length,
|
if (InputTextEx("##ImeDialogInput", placeholder, state->current_text.begin(),
|
||||||
size, flags, InputTextCallback, this))
|
state->max_text_length, input_size, flags, InputTextCallback, this)) {
|
||||||
state->input_changed = true;
|
state->input_changed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int ImeDialogUi::InputTextCallback(ImGuiInputTextCallbackData* data) {
|
int ImeDialogUi::InputTextCallback(ImGuiInputTextCallbackData* data) {
|
||||||
ImeDialogUi* ui = static_cast<ImeDialogUi*>(data->UserData);
|
ImeDialogUi* ui = static_cast<ImeDialogUi*>(data->UserData);
|
||||||
ASSERT(ui);
|
ASSERT(ui);
|
||||||
|
|
||||||
/* numeric filter */
|
// Should we filter punctuation?
|
||||||
if (ui->state->is_numeric && (data->EventChar < '0' || data->EventChar > '9') &&
|
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;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ui->state->keyboard_filter)
|
if (!ui->state->keyboard_filter) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
char* ev_char = reinterpret_cast<char*>(&data->EventChar);
|
// ImGui encodes ImWchar32 as multi-byte UTF-8 characters
|
||||||
|
char* event_char = reinterpret_cast<char*>(&data->EventChar);
|
||||||
|
|
||||||
OrbisImeKeycode src{
|
// Call the keyboard filter
|
||||||
|
OrbisImeKeycode src_keycode = {
|
||||||
.keycode = 0,
|
.keycode = 0,
|
||||||
.character = 0,
|
.character = 0,
|
||||||
.status = 1,
|
.status = 1, // ??? 1 = key pressed, 0 = key released
|
||||||
.type = OrbisImeKeyboardType::ENGLISH_US,
|
.type = OrbisImeKeyboardType::ENGLISH_US, // TODO set this to the correct value (maybe use
|
||||||
|
// the current language?)
|
||||||
.user_id = ui->state->user_id,
|
.user_id = ui->state->user_id,
|
||||||
.resource_id = 0,
|
.resource_id = 0,
|
||||||
.timestamp = 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;
|
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;
|
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)
|
* helper draw functions (new)
|
||||||
*─────────────────────────────────────────────────────────────*/
|
*─────────────────────────────────────────────────────────────*/
|
||||||
@ -516,56 +586,4 @@ void ImeDialogUi::OnVirtualKeyEvent(const VirtualKeyEvent* evt) {
|
|||||||
}
|
}
|
||||||
/* Up is available if you need it later; currently ignored */
|
/* 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
|
} // namespace Libraries::ImeDialog
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstring> // for strncpy / memcpy
|
#include <cstring> // for strncpy / memcpy
|
||||||
@ -10,8 +13,6 @@
|
|||||||
#include "ime_keyboard_ui.h"
|
#include "ime_keyboard_ui.h"
|
||||||
#include "imgui/imgui_layer.h"
|
#include "imgui/imgui_layer.h"
|
||||||
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
namespace Libraries::ImeDialog {
|
namespace Libraries::ImeDialog {
|
||||||
|
|
||||||
// Forward declaration so we can befriend it
|
// Forward declaration so we can befriend it
|
||||||
@ -35,11 +36,10 @@ class ImeDialogState final {
|
|||||||
OrbisImeExtKeyboardFilter keyboard_filter{};
|
OrbisImeExtKeyboardFilter keyboard_filter{};
|
||||||
u32 max_text_length{};
|
u32 max_text_length{};
|
||||||
char16_t* text_buffer{};
|
char16_t* text_buffer{};
|
||||||
|
|
||||||
std::vector<char> title;
|
std::vector<char> title;
|
||||||
std::vector<char> placeholder;
|
std::vector<char> 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<ORBIS_IME_DIALOG_MAX_TEXT_LENGTH * 4> current_text;
|
Common::CString<ORBIS_IME_DIALOG_MAX_TEXT_LENGTH * 4> current_text;
|
||||||
|
|
||||||
// Optional custom keyboard style (from extended params)
|
// Optional custom keyboard style (from extended params)
|
||||||
@ -49,11 +49,13 @@ class ImeDialogState final {
|
|||||||
public:
|
public:
|
||||||
/*──────────────── constructors / rule‑of‑five ────────────────*/
|
/*──────────────── constructors / rule‑of‑five ────────────────*/
|
||||||
ImeDialogState(const OrbisImeDialogParam* param = nullptr,
|
ImeDialogState(const OrbisImeDialogParam* param = nullptr,
|
||||||
const OrbisImeParamExtended* ext = nullptr);
|
const OrbisImeParamExtended* extended = nullptr);
|
||||||
ImeDialogState(const ImeDialogState&) = delete;
|
ImeDialogState(const ImeDialogState& other) = delete;
|
||||||
ImeDialogState(ImeDialogState&&) noexcept;
|
ImeDialogState(ImeDialogState&& other) noexcept;
|
||||||
ImeDialogState& operator=(ImeDialogState&&);
|
ImeDialogState& operator=(ImeDialogState&& other);
|
||||||
|
|
||||||
|
bool CopyTextToOrbisBuffer();
|
||||||
|
bool CallTextFilter();
|
||||||
/*──────────────────── public read helpers ───────────────────*/
|
/*──────────────────── public read helpers ───────────────────*/
|
||||||
bool IsMultiLine() const {
|
bool IsMultiLine() const {
|
||||||
return is_multi_line;
|
return is_multi_line;
|
||||||
@ -103,17 +105,15 @@ public:
|
|||||||
input_changed = true;
|
input_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*──────────────────────── IME support ───────────────────────*/
|
|
||||||
bool CopyTextToOrbisBuffer();
|
|
||||||
bool CallTextFilter();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool CallKeyboardFilter(const OrbisImeKeycode* src_keycode, u16* out_keycode, u32* out_status);
|
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,
|
bool ConvertOrbisToUTF8(const char16_t* orbis_text, std::size_t orbis_text_len, char* utf8_text,
|
||||||
std::size_t utf8_text_len);
|
std::size_t native_text_len);
|
||||||
bool ConvertUTF8ToOrbis(const char* utf8_text, std::size_t utf8_text_len, char16_t* orbis_text,
|
bool ConvertUTF8ToOrbis(const char* native_text, std::size_t utf8_text_len,
|
||||||
std::size_t orbis_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,
|
explicit ImeDialogUi(ImeDialogState* state = nullptr, OrbisImeDialogStatus* status = nullptr,
|
||||||
OrbisImeDialogResult* result = nullptr);
|
OrbisImeDialogResult* result = nullptr);
|
||||||
~ImeDialogUi() override;
|
~ImeDialogUi() override;
|
||||||
ImeDialogUi(const ImeDialogUi&) = delete;
|
ImeDialogUi(const ImeDialogUi& other) = delete;
|
||||||
ImeDialogUi(ImeDialogUi&&) noexcept;
|
ImeDialogUi(ImeDialogUi&& other) noexcept;
|
||||||
ImeDialogUi& operator=(ImeDialogUi&&);
|
ImeDialogUi& operator=(ImeDialogUi&& other);
|
||||||
|
|
||||||
/*────────── main draw ───────────*/
|
/*────────── main draw ───────────*/
|
||||||
void Draw() override;
|
void Draw() override;
|
||||||
@ -149,8 +149,10 @@ public:
|
|||||||
private:
|
private:
|
||||||
/*── helpers ─*/
|
/*── helpers ─*/
|
||||||
void Free();
|
void Free();
|
||||||
|
|
||||||
void DrawInputText();
|
void DrawInputText();
|
||||||
void DrawMultiLineInputText();
|
void DrawMultiLineInputText();
|
||||||
|
|
||||||
static int InputTextCallback(ImGuiInputTextCallbackData* data);
|
static int InputTextCallback(ImGuiInputTextCallbackData* data);
|
||||||
|
|
||||||
/*── keyboard section ─*/
|
/*── keyboard section ─*/
|
||||||
@ -158,6 +160,18 @@ private:
|
|||||||
ShiftState shift_state = ShiftState::None;
|
ShiftState shift_state = ShiftState::None;
|
||||||
u64 kb_language = 0;
|
u64 kb_language = 0;
|
||||||
KeyboardStyle kb_style;
|
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 DrawVirtualKeyboardSection();
|
||||||
void DrawPredictionBarAnCancelButton();
|
void DrawPredictionBarAnCancelButton();
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
#include "ime_keyboard_layouts.h"
|
#include "ime_keyboard_layouts.h"
|
||||||
|
|
||||||
int c16rtomb(char* out, char16_t ch) {
|
int c16rtomb(char* out, char16_t ch) {
|
||||||
|
@ -20,7 +20,7 @@ struct KeyEntry {
|
|||||||
u8 rowspan;
|
u8 rowspan;
|
||||||
const char* label;
|
const char* label;
|
||||||
const char* controller_hint;
|
const char* controller_hint;
|
||||||
ImGuiNavInput bound_buttons[2];
|
ImGuiKey bound_buttons[2];
|
||||||
bool allow_repeat{false};
|
bool allow_repeat{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -33,22 +33,23 @@ extern const std::vector<KeyEntry> kLayoutEnAccentLettersLowercase;
|
|||||||
extern const std::vector<KeyEntry> kLayoutEnSymbols1;
|
extern const std::vector<KeyEntry> kLayoutEnSymbols1;
|
||||||
extern const std::vector<KeyEntry> kLayoutEnSymbols2;
|
extern const std::vector<KeyEntry> kLayoutEnSymbols2;
|
||||||
|
|
||||||
constexpr ImGuiNavInput None = ImGuiNavInput_COUNT;
|
constexpr ImGuiKey None = ImGuiKey::ImGuiKey_None;
|
||||||
constexpr auto L1 = ImGuiNavInput_FocusPrev;
|
constexpr ImGuiKey L1 = ImGuiKey::ImGuiKey_GamepadL1;
|
||||||
constexpr auto R1 = ImGuiNavInput_FocusNext;
|
constexpr ImGuiKey R1 = ImGuiKey::ImGuiKey_GamepadR1;
|
||||||
constexpr auto L2 = ImGuiNavInput_TweakSlow;
|
constexpr ImGuiKey L2 = ImGuiKey::ImGuiKey_GamepadL2;
|
||||||
constexpr auto R2 = ImGuiNavInput_TweakFast;
|
constexpr ImGuiKey R2 = ImGuiKey::ImGuiKey_GamepadR2;
|
||||||
constexpr auto L3 = ImGuiNavInput_DpadLeft; // adjust if needed
|
constexpr ImGuiKey L3 = ImGuiKey::ImGuiKey_GamepadL3;
|
||||||
constexpr auto R3 = ImGuiNavInput_DpadRight; // adjust if needed
|
constexpr ImGuiKey R3 = ImGuiKey::ImGuiKey_GamepadR3;
|
||||||
constexpr auto Up = ImGuiNavInput_DpadUp;
|
constexpr ImGuiKey Up = ImGuiKey::ImGuiKey_GamepadDpadUp;
|
||||||
constexpr auto Down = ImGuiNavInput_DpadDown;
|
constexpr ImGuiKey Down = ImGuiKey::ImGuiKey_GamepadDpadDown;
|
||||||
constexpr auto Left = ImGuiNavInput_DpadLeft;
|
constexpr ImGuiKey Left = ImGuiKey::ImGuiKey_GamepadDpadLeft;
|
||||||
constexpr auto Right = ImGuiNavInput_DpadRight;
|
constexpr ImGuiKey Right = ImGuiKey::ImGuiKey_GamepadDpadRight;
|
||||||
constexpr auto Cross = ImGuiNavInput_Activate;
|
constexpr ImGuiKey Cross = ImGuiKey::ImGuiKey_GamepadFaceDown; // X button
|
||||||
constexpr auto Circle = ImGuiNavInput_Menu;
|
constexpr ImGuiKey Circle = ImGuiKey::ImGuiKey_GamepadFaceRight; // O button
|
||||||
constexpr auto Square = ImGuiNavInput_Cancel;
|
constexpr ImGuiKey Square = ImGuiKey::ImGuiKey_GamepadFaceLeft; // [] button
|
||||||
constexpr auto Triangle = ImGuiNavInput_Input;
|
constexpr ImGuiKey Triangle = ImGuiKey::ImGuiKey_GamepadFaceUp; // /\ button
|
||||||
constexpr auto TouchPad = ImGuiNavInput_Menu; // reuse if needed
|
constexpr ImGuiKey Options = ImGuiKey::ImGuiKey_GraveAccent; // Options button
|
||||||
|
|
||||||
|
|
||||||
// Fake function keycodes
|
// Fake function keycodes
|
||||||
constexpr u16 KC_SYM1 = 0xF100;
|
constexpr u16 KC_SYM1 = 0xF100;
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
#include "ime_dialog.h"
|
#include "ime_dialog.h"
|
||||||
#include "ime_keyboard_layouts.h"
|
#include "ime_keyboard_layouts.h"
|
||||||
#include "ime_keyboard_ui.h"
|
#include "ime_keyboard_ui.h"
|
||||||
|
#include "ime_ui.h" // for ImeState
|
||||||
|
|
||||||
using namespace ImGui;
|
using namespace ImGui;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,8 +3,12 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "core/libraries/ime/ime.h"
|
||||||
#include "core/libraries/ime/ime_keyboard_layouts.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.)
|
* KeyboardMode: which layout we show (letters, accents, symbols, etc.)
|
||||||
|
Loading…
Reference in New Issue
Block a user