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-cursor.h"
|
||||||
#include "wayland-util.h"
|
#include "wayland-util.h"
|
||||||
#include "xkbcommon/xkbcommon.h"
|
#include "xkbcommon/xkbcommon.h"
|
||||||
|
#include "xkbcommon/xkbcommon-compose.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C"
|
||||||
|
|
|
@ -57,6 +57,7 @@
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
#include <xkbcommon/xkbcommon-compose.h>
|
||||||
|
|
||||||
/* Weston uses a ratio of 10 units per scroll tick */
|
/* Weston uses a ratio of 10 units per scroll tick */
|
||||||
#define WAYLAND_WHEEL_AXIS_UNIT 10
|
#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)
|
uint32_t format, int fd, uint32_t size)
|
||||||
{
|
{
|
||||||
struct SDL_WaylandInput *input = data;
|
struct SDL_WaylandInput *input = data;
|
||||||
char *map_str;
|
char *map_str, *locale;
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
close(fd);
|
close(fd);
|
||||||
|
@ -661,6 +662,30 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
|
||||||
input->xkb.keymap = NULL;
|
input->xkb.keymap = NULL;
|
||||||
return;
|
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
|
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;
|
SDL_WindowData *window = input->keyboard_focus;
|
||||||
const xkb_keysym_t *syms;
|
const xkb_keysym_t *syms;
|
||||||
|
xkb_keysym_t sym;
|
||||||
|
|
||||||
if (!window || window->keyboard_device != input || !input->xkb.state) {
|
if (!window || window->keyboard_device != input || !input->xkb.state) {
|
||||||
return SDL_FALSE;
|
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) {
|
if (WAYLAND_xkb_state_key_get_syms(input->xkb.state, key + 8, &syms) != 1) {
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
}
|
}
|
||||||
|
sym = syms[0];
|
||||||
|
|
||||||
#ifdef SDL_USE_IME
|
#ifdef SDL_USE_IME
|
||||||
if (SDL_IME_ProcessKeyEvent(syms[0], key + 8)) {
|
if (SDL_IME_ProcessKeyEvent(sym, key + 8)) {
|
||||||
*handled_by_ime = SDL_TRUE;
|
*handled_by_ime = SDL_TRUE;
|
||||||
return SDL_TRUE;
|
return SDL_TRUE;
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
static void
|
||||||
|
@ -1239,6 +1283,12 @@ void Wayland_display_destroy_input(SDL_VideoData *d)
|
||||||
if (input->seat)
|
if (input->seat)
|
||||||
wl_seat_destroy(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)
|
if (input->xkb.state)
|
||||||
WAYLAND_xkb_state_unref(input->xkb.state);
|
WAYLAND_xkb_state_unref(input->xkb.state);
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,8 @@ struct SDL_WaylandInput {
|
||||||
struct {
|
struct {
|
||||||
struct xkb_keymap *keymap;
|
struct xkb_keymap *keymap;
|
||||||
struct xkb_state *state;
|
struct xkb_state *state;
|
||||||
|
struct xkb_compose_table *compose_table;
|
||||||
|
struct xkb_compose_state *compose_state;
|
||||||
} xkb;
|
} xkb;
|
||||||
|
|
||||||
/* information about axis events on current frame */
|
/* 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 depressed_layout,\
|
||||||
xkb_layout_index_t latched_layout,\
|
xkb_layout_index_t latched_layout,\
|
||||||
xkb_layout_index_t locked_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(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 *,
|
SDL_WAYLAND_SYM(int, xkb_keymap_key_get_syms_by_level, (struct xkb_keymap *,
|
||||||
xkb_keycode_t,
|
xkb_keycode_t,
|
||||||
|
|
Loading…
Reference in New Issue