mirror of https://github.com/encounter/SDL.git
Support key composing (i.e. dead keys) in Wayland driver (#4296)
Based on an old patch by chw from the old Bugzilla issue tracker. Authored-by: chw Co-authored-by: Sam Lantinga <slouken@libsdl.org>
This commit is contained in:
parent
b04136e75e
commit
5c78df9c23
|
@ -38,6 +38,7 @@ struct wl_shm;
|
|||
#include "wayland-cursor.h"
|
||||
#include "wayland-util.h"
|
||||
#include "xkbcommon/xkbcommon.h"
|
||||
#include "xkbcommon/xkbcommon-compose.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include <poll.h>
|
||||
#include <unistd.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <xkbcommon/xkbcommon-compose.h>
|
||||
|
||||
/* Weston uses a ratio of 10 units per scroll tick */
|
||||
#define WAYLAND_WHEEL_AXIS_UNIT 10
|
||||
|
@ -624,7 +625,7 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
|
|||
uint32_t format, int fd, uint32_t size)
|
||||
{
|
||||
struct SDL_WaylandInput *input = data;
|
||||
char *map_str;
|
||||
char *map_str, *locale;
|
||||
|
||||
if (!data) {
|
||||
close(fd);
|
||||
|
@ -661,6 +662,30 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
|
|||
input->xkb.keymap = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* See https://blogs.s-osg.org/compose-key-support-weston/
|
||||
* for further explanation on dead keys in Wayland.
|
||||
*/
|
||||
|
||||
/* Look up the preferred locale, falling back to "C" as default */
|
||||
if (!(locale = SDL_getenv("LC_ALL")))
|
||||
if (!(locale = SDL_getenv("LC_CTYPE")))
|
||||
if (!(locale = SDL_getenv("LANG")))
|
||||
locale = "C";
|
||||
/* Set up XKB compose table */
|
||||
input->xkb.compose_table = WAYLAND_xkb_compose_table_new_from_locale(input->display->xkb_context,
|
||||
locale, XKB_COMPOSE_COMPILE_NO_FLAGS);
|
||||
if (input->xkb.compose_table) {
|
||||
/* Set up XKB compose state */
|
||||
input->xkb.compose_state = WAYLAND_xkb_compose_state_new(input->xkb.compose_table,
|
||||
XKB_COMPOSE_STATE_NO_FLAGS);
|
||||
if (!input->xkb.compose_state) {
|
||||
fprintf(stderr, "could not create XKB compose state\n");
|
||||
WAYLAND_xkb_compose_table_unref(input->xkb.compose_table);
|
||||
input->xkb.compose_table = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -709,6 +734,7 @@ keyboard_input_get_text(char text[8], const struct SDL_WaylandInput *input, uint
|
|||
{
|
||||
SDL_WindowData *window = input->keyboard_focus;
|
||||
const xkb_keysym_t *syms;
|
||||
xkb_keysym_t sym;
|
||||
|
||||
if (!window || window->keyboard_device != input || !input->xkb.state) {
|
||||
return SDL_FALSE;
|
||||
|
@ -718,15 +744,33 @@ keyboard_input_get_text(char text[8], const struct SDL_WaylandInput *input, uint
|
|||
if (WAYLAND_xkb_state_key_get_syms(input->xkb.state, key + 8, &syms) != 1) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
sym = syms[0];
|
||||
|
||||
#ifdef SDL_USE_IME
|
||||
if (SDL_IME_ProcessKeyEvent(syms[0], key + 8)) {
|
||||
if (SDL_IME_ProcessKeyEvent(sym, key + 8)) {
|
||||
*handled_by_ime = SDL_TRUE;
|
||||
return SDL_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return WAYLAND_xkb_keysym_to_utf8(syms[0], text, 8) > 0;
|
||||
if (WAYLAND_xkb_compose_state_feed(input->xkb.compose_state, sym) == XKB_COMPOSE_FEED_ACCEPTED) {
|
||||
switch(WAYLAND_xkb_compose_state_get_status(input->xkb.compose_state)) {
|
||||
case XKB_COMPOSE_COMPOSING:
|
||||
*handled_by_ime = SDL_TRUE;
|
||||
return SDL_TRUE;
|
||||
case XKB_COMPOSE_CANCELLED:
|
||||
default:
|
||||
sym = XKB_KEY_NoSymbol;
|
||||
break;
|
||||
case XKB_COMPOSE_NOTHING:
|
||||
break;
|
||||
case XKB_COMPOSE_COMPOSED:
|
||||
sym = WAYLAND_xkb_compose_state_get_one_sym(input->xkb.compose_state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return WAYLAND_xkb_keysym_to_utf8(sym, text, 8) > 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1239,6 +1283,12 @@ void Wayland_display_destroy_input(SDL_VideoData *d)
|
|||
if (input->seat)
|
||||
wl_seat_destroy(input->seat);
|
||||
|
||||
if (input->xkb.compose_state)
|
||||
WAYLAND_xkb_compose_state_unref(input->xkb.compose_state);
|
||||
|
||||
if (input->xkb.compose_table)
|
||||
WAYLAND_xkb_compose_table_unref(input->xkb.compose_table);
|
||||
|
||||
if (input->xkb.state)
|
||||
WAYLAND_xkb_state_unref(input->xkb.state);
|
||||
|
||||
|
|
|
@ -64,6 +64,8 @@ struct SDL_WaylandInput {
|
|||
struct {
|
||||
struct xkb_keymap *keymap;
|
||||
struct xkb_state *state;
|
||||
struct xkb_compose_table *compose_table;
|
||||
struct xkb_compose_state *compose_state;
|
||||
} xkb;
|
||||
|
||||
/* information about axis events on current frame */
|
||||
|
|
|
@ -118,6 +118,14 @@ SDL_WAYLAND_SYM(enum xkb_state_component, xkb_state_update_mask, (struct xkb_sta
|
|||
xkb_layout_index_t depressed_layout,\
|
||||
xkb_layout_index_t latched_layout,\
|
||||
xkb_layout_index_t locked_layout) )
|
||||
SDL_WAYLAND_SYM(struct xkb_compose_table *, xkb_compose_table_new_from_locale, (struct xkb_context *,\
|
||||
const char *locale, enum xkb_compose_compile_flags) )
|
||||
SDL_WAYLAND_SYM(void, xkb_compose_table_unref, (struct xkb_compose_table *) )
|
||||
SDL_WAYLAND_SYM(struct xkb_compose_state *, xkb_compose_state_new, (struct xkb_compose_table *, enum xkb_compose_state_flags) )
|
||||
SDL_WAYLAND_SYM(void, xkb_compose_state_unref, (struct xkb_compose_state *) )
|
||||
SDL_WAYLAND_SYM(enum xkb_compose_feed_result, xkb_compose_state_feed, (struct xkb_compose_state *, xkb_keysym_t) )
|
||||
SDL_WAYLAND_SYM(enum xkb_compose_status, xkb_compose_state_get_status, (struct xkb_compose_state *) )
|
||||
SDL_WAYLAND_SYM(xkb_keysym_t, xkb_compose_state_get_one_sym, (struct xkb_compose_state *) )
|
||||
SDL_WAYLAND_SYM(void, xkb_keymap_key_for_each, (struct xkb_keymap *, xkb_keymap_key_iter_t, void*) )
|
||||
SDL_WAYLAND_SYM(int, xkb_keymap_key_get_syms_by_level, (struct xkb_keymap *,
|
||||
xkb_keycode_t,
|
||||
|
|
Loading…
Reference in New Issue