diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index 5e17e12ff..62a2557ec 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -216,6 +216,12 @@ Wayland_PumpEvents(_THIS) WAYLAND_wl_display_flush(d->display); +#ifdef SDL_USE_IME + if (SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE) { + SDL_IME_PumpEvents(); + } +#endif + if (input) { uint32_t now = SDL_GetTicks(); keyboard_repeat_handle(&input->keyboard_repeat, now); @@ -677,6 +683,9 @@ keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, window->keyboard_device = input; SDL_SetKeyboardFocus(window->sdlwindow); } +#ifdef SDL_USE_IME + SDL_IME_SetFocus(SDL_TRUE); +#endif } static void @@ -690,10 +699,13 @@ keyboard_handle_leave(void *data, struct wl_keyboard *keyboard, /* This will release any keys still pressed */ SDL_SetKeyboardFocus(NULL); +#ifdef SDL_USE_IME + SDL_IME_SetFocus(SDL_FALSE); +#endif } static SDL_bool -keyboard_input_get_text(char text[8], const struct SDL_WaylandInput *input, uint32_t key) +keyboard_input_get_text(char text[8], const struct SDL_WaylandInput *input, uint32_t key, SDL_bool *handled_by_ime) { SDL_WindowData *window = input->keyboard_focus; const xkb_keysym_t *syms; @@ -707,6 +719,13 @@ keyboard_input_get_text(char text[8], const struct SDL_WaylandInput *input, uint return SDL_FALSE; } +#ifdef SDL_USE_IME + if (SDL_IME_ProcessKeyEvent(syms[0], key + 8)) { + *handled_by_ime = SDL_TRUE; + return SDL_TRUE; + } +#endif + return WAYLAND_xkb_keysym_to_utf8(syms[0], text, 8) > 0; } @@ -719,8 +738,14 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard, enum wl_keyboard_key_state state = state_w; uint32_t scancode = SDL_SCANCODE_UNKNOWN; char text[8]; + SDL_bool has_text = SDL_FALSE; + SDL_bool handled_by_ime = SDL_FALSE; - if (key < SDL_arraysize(xfree86_scancode_table2)) { + if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { + has_text = keyboard_input_get_text(text, input, key, &handled_by_ime); + } + + if (!handled_by_ime && key < SDL_arraysize(xfree86_scancode_table2)) { scancode = xfree86_scancode_table2[key]; if (scancode != SDL_SCANCODE_UNKNOWN) { @@ -730,10 +755,11 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard, } if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { - SDL_bool has_text = keyboard_input_get_text(text, input, key); if (has_text) { Wayland_data_device_set_serial(input->data_device, serial); - SDL_SendKeyboardText(text); + if (!handled_by_ime) { + SDL_SendKeyboardText(text); + } } keyboard_repeat_set(&input->keyboard_repeat, scancode, has_text, text); } else { diff --git a/src/video/wayland/SDL_waylandkeyboard.c b/src/video/wayland/SDL_waylandkeyboard.c new file mode 100644 index 000000000..88384b351 --- /dev/null +++ b/src/video/wayland/SDL_waylandkeyboard.c @@ -0,0 +1,75 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_WAYLAND + +#include "../SDL_sysvideo.h" +#include "SDL_waylandvideo.h" + +int +Wayland_InitKeyboard(_THIS) +{ +#ifdef SDL_USE_IME + SDL_IME_Init(); +#endif + + return 0; +} + +void +Wayland_QuitKeyboard(_THIS) +{ +#ifdef SDL_USE_IME + SDL_IME_Quit(); +#endif +} + +void +Wayland_StartTextInput(_THIS) +{ + /* No-op */ +} + +void +Wayland_StopTextInput(_THIS) +{ +#ifdef SDL_USE_IME + SDL_IME_Reset(); +#endif +} + +void +Wayland_SetTextInputRect(_THIS, SDL_Rect *rect) +{ + if (!rect) { + SDL_InvalidParamError("rect"); + return; + } + +#ifdef SDL_USE_IME + SDL_IME_UpdateTextRect(rect); +#endif +} + +#endif /* SDL_VIDEO_DRIVER_WAYLAND */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/wayland/SDL_waylandkeyboard.h b/src/video/wayland/SDL_waylandkeyboard.h new file mode 100644 index 000000000..cca8ac8d9 --- /dev/null +++ b/src/video/wayland/SDL_waylandkeyboard.h @@ -0,0 +1,34 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifndef SDL_waylandkeyboard_h_ +#define SDL_waylandkeyboard_h_ + +extern int Wayland_InitKeyboard(_THIS); +extern void Wayland_QuitKeyboard(_THIS); +extern void Wayland_StartTextInput(_THIS); +extern void Wayland_StopTextInput(_THIS); +extern void Wayland_SetTextInputRect(_THIS, SDL_Rect *rect); + +#endif /* SDL_waylandkeyboard_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index 95b1af936..e43fb4cce 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/src/video/wayland/SDL_waylandvideo.c @@ -33,6 +33,7 @@ #include "SDL_waylandwindow.h" #include "SDL_waylandopengles.h" #include "SDL_waylandmouse.h" +#include "SDL_waylandkeyboard.h" #include "SDL_waylandtouch.h" #include "SDL_waylandclipboard.h" #include "SDL_waylandvulkan.h" @@ -215,6 +216,9 @@ Wayland_CreateDevice(int devindex) device->SetClipboardText = Wayland_SetClipboardText; device->GetClipboardText = Wayland_GetClipboardText; device->HasClipboardText = Wayland_HasClipboardText; + device->StartTextInput = Wayland_StartTextInput; + device->StopTextInput = Wayland_StopTextInput; + device->SetTextInputRect = Wayland_SetTextInputRect; #if SDL_VIDEO_VULKAN device->Vulkan_LoadLibrary = Wayland_Vulkan_LoadLibrary; @@ -478,6 +482,8 @@ Wayland_VideoInit(_THIS) WAYLAND_wl_display_flush(data->display); + Wayland_InitKeyboard(_this); + #if SDL_USE_LIBDBUS SDL_DBus_Init(); #endif @@ -567,6 +573,8 @@ Wayland_VideoQuit(_THIS) if (data->registry) wl_registry_destroy(data->registry); + Wayland_QuitKeyboard(_this); + /* !!! FIXME: other subsystems use D-Bus, so we shouldn't quit it here; have SDL.c do this at a higher level, or add refcounting. */ #if SDL_USE_LIBDBUS diff --git a/src/video/wayland/SDL_waylandvideo.h b/src/video/wayland/SDL_waylandvideo.h index e4b865d51..867422440 100644 --- a/src/video/wayland/SDL_waylandvideo.h +++ b/src/video/wayland/SDL_waylandvideo.h @@ -40,6 +40,7 @@ #include "wayland-util.h" #include "../../core/linux/SDL_dbus.h" +#include "../../core/linux/SDL_ime.h" struct xkb_context; struct SDL_WaylandInput;