mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2025-01-22 07:32:07 -05:00
ime composition support (#589)
This commit is contained in:
parent
c8faa22072
commit
ba037771bd
11 changed files with 95 additions and 7 deletions
|
@ -66,6 +66,10 @@ void keyboard_on_text_input(char* text) {
|
|||
djui_interactable_on_text_input(text);
|
||||
}
|
||||
|
||||
void keyboard_on_text_editing(char* text, int cursorPos) {
|
||||
djui_interactable_on_text_editing(text, cursorPos);
|
||||
}
|
||||
|
||||
static void keyboard_add_binds(int mask, unsigned int *scancode) {
|
||||
for (int i = 0; i < MAX_BINDS && num_keybinds < MAX_KEYBINDS; ++i) {
|
||||
if (scancode[i] < VK_BASE_KEYBOARD + VK_SIZE) {
|
||||
|
|
|
@ -42,6 +42,7 @@ bool keyboard_on_key_down(int scancode);
|
|||
bool keyboard_on_key_up(int scancode);
|
||||
void keyboard_on_all_keys_up(void);
|
||||
void keyboard_on_text_input(char* text);
|
||||
void keyboard_on_text_editing(char* text, int cursorPos);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -651,7 +651,8 @@ static void crash_handler(const int signalNum, siginfo_t *info, UNUSED ucontext_
|
|||
// In case the game crashed before the game window opened
|
||||
if (!gGfxInited) {
|
||||
gfx_init(&WAPI, &RAPI, TITLE);
|
||||
WAPI.set_keyboard_callbacks(keyboard_on_key_down, keyboard_on_key_up, keyboard_on_all_keys_up, keyboard_on_text_input);
|
||||
WAPI.set_keyboard_callbacks(keyboard_on_key_down, keyboard_on_key_up, keyboard_on_all_keys_up,
|
||||
keyboard_on_text_input, keyboard_on_text_editing);
|
||||
}
|
||||
if (!gGameInited) djui_unicode_init();
|
||||
|
||||
|
|
|
@ -498,6 +498,10 @@ static void djui_chat_box_input_on_text_input(struct DjuiBase *base, char* text)
|
|||
}
|
||||
}
|
||||
|
||||
static void djui_chat_box_input_on_text_editing(struct DjuiBase *base, char* text, int cursorPos) {
|
||||
djui_inputbox_on_text_editing(base, text, cursorPos);
|
||||
}
|
||||
|
||||
void djui_chat_box_toggle(void) {
|
||||
if (gDjuiChatBox == NULL) { return; }
|
||||
if (!gDjuiChatBoxFocus) { sDjuiChatBoxClearText = true; }
|
||||
|
@ -550,6 +554,7 @@ struct DjuiChatBox* djui_chat_box_create(void) {
|
|||
djui_base_set_alignment(ciBase, DJUI_HALIGN_LEFT, DJUI_VALIGN_BOTTOM);
|
||||
djui_interactable_hook_key(&chatInput->base, djui_chat_box_input_on_key_down, djui_inputbox_on_key_up);
|
||||
djui_interactable_hook_text_input(&chatInput->base, djui_chat_box_input_on_text_input);
|
||||
djui_interactable_hook_text_editing(&chatInput->base, djui_chat_box_input_on_text_editing);
|
||||
chatBox->chatInput = chatInput;
|
||||
|
||||
gDjuiChatBox = chatBox;
|
||||
|
|
|
@ -397,6 +397,31 @@ void djui_inputbox_on_text_input(struct DjuiBase *base, char* text) {
|
|||
inputbox->selection[1] = inputbox->selection[0];
|
||||
sCursorBlink = 0;
|
||||
djui_inputbox_on_change(inputbox);
|
||||
|
||||
inputbox->imePos = 0;
|
||||
if (inputbox->imeBuffer != NULL) {
|
||||
free(inputbox->imeBuffer);
|
||||
inputbox->imeBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void djui_inputbox_on_text_editing(struct DjuiBase *base, char* text, int cursorPos) {
|
||||
struct DjuiInputbox *inputbox = (struct DjuiInputbox *) base;
|
||||
inputbox->imePos = (u16)cursorPos;
|
||||
|
||||
if (inputbox->imeBuffer != NULL) free(inputbox->imeBuffer);
|
||||
|
||||
if (*text == '\0') {
|
||||
inputbox->imeBuffer = NULL;
|
||||
}
|
||||
else {
|
||||
size_t size = strlen(text);
|
||||
char* copy = malloc(size + 1);
|
||||
strcpy(copy,text);
|
||||
inputbox->imeBuffer = copy;
|
||||
}
|
||||
|
||||
djui_inputbox_on_change(inputbox);
|
||||
}
|
||||
|
||||
static void djui_inputbox_render_char(struct DjuiInputbox* inputbox, char* c, f32* drawX, f32* additionalShift) {
|
||||
|
@ -444,11 +469,22 @@ static void djui_inputbox_render_selection(struct DjuiInputbox* inputbox) {
|
|||
}
|
||||
|
||||
sCursorBlink = (sCursorBlink + 1) % DJUI_INPUTBOX_MAX_BLINK;
|
||||
|
||||
|
||||
f32 renderX = x;
|
||||
|
||||
u16 imePos = inputbox->imePos;
|
||||
if (imePos != 0) {
|
||||
char* ime = inputbox->imeBuffer;
|
||||
for (u16 i = 0; i < imePos; i++) {
|
||||
renderX += font->char_width(ime);
|
||||
ime = djui_unicode_next_char(ime);
|
||||
}
|
||||
}
|
||||
|
||||
// render only cursor when there is no selection width
|
||||
if (selection[0] == selection[1]) {
|
||||
if (sCursorBlink < DJUI_INPUTBOX_MID_BLINK && djui_interactable_is_input_focus(&inputbox->base)) {
|
||||
create_dl_translation_matrix(DJUI_MTX_PUSH, x - DJUI_INPUTBOX_CURSOR_WIDTH / 2.0f, -0.1f, 0);
|
||||
create_dl_translation_matrix(DJUI_MTX_PUSH, renderX - DJUI_INPUTBOX_CURSOR_WIDTH / 2.0f, -0.1f, 0);
|
||||
create_dl_scale_matrix(DJUI_MTX_NOPUSH, DJUI_INPUTBOX_CURSOR_WIDTH, 0.8f, 1.0f);
|
||||
gDPSetEnvColor(gDisplayListHead++, 0, 0, 0, 255);
|
||||
gSPDisplayList(gDisplayListHead++, dl_djui_simple_rect);
|
||||
|
@ -547,13 +583,23 @@ static bool djui_inputbox_render(struct DjuiBase* base) {
|
|||
u16 selection[2] = { 0 };
|
||||
selection[0] = fmin(inputbox->selection[0], inputbox->selection[1]);
|
||||
selection[1] = fmax(inputbox->selection[0], inputbox->selection[1]);
|
||||
|
||||
|
||||
// render text
|
||||
char* c = inputbox->buffer;
|
||||
f32 drawX = inputbox->viewX;
|
||||
f32 additionalShift = 0;
|
||||
bool wasInsideSelection = false;
|
||||
for (u16 i = 0; i < inputbox->bufferSize; i++) {
|
||||
|
||||
//render composition text
|
||||
if (selection[0] == i && inputbox->imeBuffer != NULL) {
|
||||
char *ime = inputbox->imeBuffer;
|
||||
while (*ime != '\0') {
|
||||
djui_inputbox_render_char(inputbox, ime, &drawX, &additionalShift);
|
||||
ime = djui_unicode_next_char(ime);
|
||||
}
|
||||
}
|
||||
|
||||
if (*c == '\0') { break; }
|
||||
|
||||
// deal with seleciton color
|
||||
|
@ -598,6 +644,7 @@ struct DjuiInputbox* djui_inputbox_create(struct DjuiBase* parent, u16 bufferSiz
|
|||
djui_interactable_hook_key(base, djui_inputbox_on_key_down, djui_inputbox_on_key_up);
|
||||
djui_interactable_hook_focus(base, djui_inputbox_on_focus_begin, NULL, djui_inputbox_on_focus_end);
|
||||
djui_interactable_hook_text_input(base, djui_inputbox_on_text_input);
|
||||
djui_interactable_hook_text_editing(base, djui_inputbox_on_text_editing);
|
||||
|
||||
djui_inputbox_update_style(base);
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@ struct DjuiInputbox {
|
|||
struct DjuiColor textColor;
|
||||
void (*on_enter_press)(struct DjuiInputbox*);
|
||||
void (*on_escape_press)(struct DjuiInputbox*);
|
||||
char* imeBuffer;
|
||||
u16 imePos;
|
||||
};
|
||||
|
||||
void djui_inputbox_on_focus_begin(UNUSED struct DjuiBase* base);
|
||||
|
@ -25,5 +27,6 @@ void djui_inputbox_hook_escape_press(struct DjuiInputbox* inputbox, void (*on_es
|
|||
bool djui_inputbox_on_key_down(struct DjuiBase* base, int scancode);
|
||||
void djui_inputbox_on_key_up(struct DjuiBase* base, int scancode);
|
||||
void djui_inputbox_on_text_input(struct DjuiBase *base, char* text);
|
||||
void djui_inputbox_on_text_editing(struct DjuiBase *base, char* text, int cursorPos);
|
||||
|
||||
struct DjuiInputbox* djui_inputbox_create(struct DjuiBase* parent, u16 bufferSize);
|
||||
|
|
|
@ -328,6 +328,13 @@ void djui_interactable_on_text_input(char* text) {
|
|||
gInteractableFocus->interactable->on_text_input(gInteractableFocus, text);
|
||||
}
|
||||
|
||||
void djui_interactable_on_text_editing(char* text, int cursorPos) {
|
||||
if (gInteractableFocus == NULL) { return; }
|
||||
if (gInteractableFocus->interactable == NULL) { return; }
|
||||
if (gInteractableFocus->interactable->on_text_editing == NULL) { return; }
|
||||
gInteractableFocus->interactable->on_text_editing(gInteractableFocus, text, cursorPos);
|
||||
}
|
||||
|
||||
void djui_interactable_update_pad(void) {
|
||||
OSContPad* pad = &gInteractablePad;
|
||||
|
||||
|
@ -521,6 +528,12 @@ void djui_interactable_hook_text_input(struct DjuiBase *base,
|
|||
interactable->on_text_input = on_text_input;
|
||||
}
|
||||
|
||||
void djui_interactable_hook_text_editing(struct DjuiBase* base,
|
||||
void (*on_text_editing)(struct DjuiBase*, char*, int)) {
|
||||
struct DjuiInteractable *interactable = base->interactable;
|
||||
interactable->on_text_editing = on_text_editing;
|
||||
}
|
||||
|
||||
void djui_interactable_hook_enabled_change(struct DjuiBase *base,
|
||||
void (*on_enabled_change)(struct DjuiBase*)) {
|
||||
struct DjuiInteractable *interactable = base->interactable;
|
||||
|
|
|
@ -42,6 +42,7 @@ struct DjuiInteractable {
|
|||
bool (*on_key_down)(struct DjuiBase*, int scancode);
|
||||
void (*on_key_up)(struct DjuiBase*, int scancode);
|
||||
void (*on_text_input)(struct DjuiBase*, char* text);
|
||||
void (*on_text_editing)(struct DjuiBase*, char* text, int cursorPos);
|
||||
void (*on_enabled_change)(struct DjuiBase*);
|
||||
};
|
||||
|
||||
|
@ -62,6 +63,7 @@ bool djui_interactable_is_input_focus(struct DjuiBase* base);
|
|||
bool djui_interactable_on_key_down(int scancode);
|
||||
void djui_interactable_on_key_up(int scancode);
|
||||
void djui_interactable_on_text_input(char *text);
|
||||
void djui_interactable_on_text_editing(char* text, int cursorPos);
|
||||
|
||||
void djui_interactable_update(void);
|
||||
|
||||
|
@ -95,6 +97,9 @@ void djui_interactable_hook_key(struct DjuiBase* base,
|
|||
void djui_interactable_hook_text_input(struct DjuiBase* base,
|
||||
void (*on_text_input)(struct DjuiBase*, char*));
|
||||
|
||||
void djui_interactable_hook_text_editing(struct DjuiBase* base,
|
||||
void (*on_text_editing)(struct DjuiBase*, char*, int));
|
||||
|
||||
void djui_interactable_hook_enabled_change(struct DjuiBase *base,
|
||||
void (*on_enabled_change)(struct DjuiBase*));
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@ static kb_callback_t kb_key_down = NULL;
|
|||
static kb_callback_t kb_key_up = NULL;
|
||||
static void (*kb_all_keys_up)(void) = NULL;
|
||||
static void (*kb_text_input)(char*) = NULL;
|
||||
static void (*kb_text_editing)(char*, int) = NULL;
|
||||
|
||||
#define IS_FULLSCREEN() ((SDL_GetWindowFlags(wnd) & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0)
|
||||
|
||||
|
@ -211,6 +212,9 @@ static void gfx_sdl_handle_events(void) {
|
|||
case SDL_TEXTINPUT:
|
||||
kb_text_input(event.text.text);
|
||||
break;
|
||||
case SDL_TEXTEDITING: //IME composition
|
||||
kb_text_editing(event.edit.text,event.edit.start);
|
||||
break;
|
||||
case SDL_KEYDOWN:
|
||||
gfx_sdl_onkeydown(event.key.keysym.scancode);
|
||||
break;
|
||||
|
@ -249,11 +253,14 @@ static void gfx_sdl_handle_events(void) {
|
|||
}
|
||||
}
|
||||
|
||||
static void gfx_sdl_set_keyboard_callbacks(kb_callback_t on_key_down, kb_callback_t on_key_up, void (*on_all_keys_up)(void), void (*on_text_input)(char*)) {
|
||||
static void gfx_sdl_set_keyboard_callbacks(kb_callback_t on_key_down, kb_callback_t on_key_up,
|
||||
void (*on_all_keys_up)(void), void (*on_text_input)(char*), void (*on_text_editing)(char*, int))
|
||||
{
|
||||
kb_key_down = on_key_down;
|
||||
kb_key_up = on_key_up;
|
||||
kb_all_keys_up = on_all_keys_up;
|
||||
kb_text_input = on_text_input;
|
||||
kb_text_editing = on_text_editing;
|
||||
}
|
||||
|
||||
static bool gfx_sdl_start_frame(void) {
|
||||
|
|
|
@ -13,7 +13,8 @@ typedef bool (*kb_callback_t)(int code);
|
|||
|
||||
struct GfxWindowManagerAPI {
|
||||
void (*init)(const char *window_title);
|
||||
void (*set_keyboard_callbacks)(kb_callback_t on_key_down, kb_callback_t on_key_up, void (*on_all_keys_up)(void), void (*on_text_input)(char*));
|
||||
void (*set_keyboard_callbacks)(kb_callback_t on_key_down, kb_callback_t on_key_up, void (*on_all_keys_up)(void),
|
||||
void (*on_text_input)(char*), void (*on_text_editing)(char*, int));
|
||||
void (*main_loop)(void (*run_one_game_iter)(void));
|
||||
void (*get_dimensions)(uint32_t *width, uint32_t *height);
|
||||
void (*handle_events)(void);
|
||||
|
|
|
@ -439,7 +439,8 @@ int main(int argc, char *argv[]) {
|
|||
// create the window almost straight away
|
||||
if (!gGfxInited) {
|
||||
gfx_init(&WAPI, &RAPI, TITLE);
|
||||
WAPI.set_keyboard_callbacks(keyboard_on_key_down, keyboard_on_key_up, keyboard_on_all_keys_up, keyboard_on_text_input);
|
||||
WAPI.set_keyboard_callbacks(keyboard_on_key_down, keyboard_on_key_up, keyboard_on_all_keys_up,
|
||||
keyboard_on_text_input, keyboard_on_text_editing);
|
||||
}
|
||||
|
||||
// render the rom setup screen
|
||||
|
|
Loading…
Reference in a new issue