mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-14 05:35:58 +00:00
Initial caret draw/control
This commit is contained in:
parent
020e1d0574
commit
bdd2b4d4c9
4 changed files with 87 additions and 11 deletions
|
@ -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
|
||||
|
|
|
@ -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<unsigned char>(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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue