Merge branch 'blender-v4.0-release'
This commit is contained in:
@@ -56,6 +56,7 @@
|
||||
#endif
|
||||
#include <wayland-cursor.h>
|
||||
|
||||
#include <xkbcommon/xkbcommon-compose.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
/* Generated by `wayland-scanner`. */
|
||||
@@ -813,6 +814,12 @@ struct GWL_Seat {
|
||||
struct {
|
||||
xkb_context *context = nullptr;
|
||||
|
||||
/** The compose key table (check for null before use). */
|
||||
xkb_compose_table *compose_table = nullptr;
|
||||
|
||||
/** The compose state is expected to use the keyboard `state` (check for null before use). */
|
||||
xkb_compose_state *compose_state = nullptr;
|
||||
|
||||
xkb_state *state = nullptr;
|
||||
/**
|
||||
* Keep a state with no modifiers active, use for symbol lookups.
|
||||
@@ -1486,6 +1493,24 @@ static void gwl_registry_entry_update_all(GWL_Display *display, const int interf
|
||||
/** \name Private Utility Functions
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* Access the LOCALE (with a fallback).
|
||||
*/
|
||||
static const char *ghost_wl_locale_from_env_with_default()
|
||||
{
|
||||
const char *locale = getenv("LC_ALL");
|
||||
if (!locale || !*locale) {
|
||||
locale = getenv("LC_CTYPE");
|
||||
if (!locale || !*locale) {
|
||||
locale = getenv("LANG");
|
||||
if (!locale || !*locale) {
|
||||
locale = "C";
|
||||
}
|
||||
}
|
||||
}
|
||||
return locale;
|
||||
}
|
||||
|
||||
static void ghost_wl_display_report_error(wl_display *display)
|
||||
{
|
||||
int ecode = wl_display_get_error(display);
|
||||
@@ -3897,6 +3922,14 @@ static void keyboard_handle_keymap(void *data,
|
||||
|
||||
CLOG_INFO(LOG, 2, "keymap");
|
||||
|
||||
if (seat->xkb.compose_state) {
|
||||
xkb_compose_state_reset(seat->xkb.compose_state);
|
||||
}
|
||||
else {
|
||||
seat->xkb.compose_state = xkb_compose_state_new(seat->xkb.compose_table,
|
||||
XKB_COMPOSE_STATE_NO_FLAGS);
|
||||
}
|
||||
|
||||
/* In practice we can assume `xkb_state_new` always succeeds. */
|
||||
xkb_state_unref(seat->xkb.state);
|
||||
seat->xkb.state = xkb_state_new(keymap);
|
||||
@@ -4077,6 +4110,42 @@ static xkb_keysym_t xkb_state_key_get_one_sym_without_modifiers(
|
||||
return sym;
|
||||
}
|
||||
|
||||
static bool xkb_compose_state_feed_and_get_utf8(
|
||||
xkb_compose_state *compose_state,
|
||||
xkb_state *state,
|
||||
const xkb_keycode_t key,
|
||||
char r_utf8_buf[sizeof(GHOST_TEventKeyData::utf8_buf)])
|
||||
{
|
||||
const xkb_keysym_t sym = xkb_state_key_get_one_sym(state, key);
|
||||
const xkb_compose_feed_result result = xkb_compose_state_feed(compose_state, sym);
|
||||
bool handled = false;
|
||||
|
||||
if (result == XKB_COMPOSE_FEED_ACCEPTED) {
|
||||
switch (xkb_compose_state_get_status(compose_state)) {
|
||||
case XKB_COMPOSE_NOTHING: {
|
||||
break;
|
||||
}
|
||||
case XKB_COMPOSE_COMPOSING: {
|
||||
break;
|
||||
}
|
||||
case XKB_COMPOSE_COMPOSED: {
|
||||
char utf8_buf_compose[sizeof(GHOST_TEventKeyData::utf8_buf) + 1] = {'\0'};
|
||||
const int utf8_buf_compose_len = xkb_compose_state_get_utf8(
|
||||
compose_state, utf8_buf_compose, sizeof(utf8_buf_compose));
|
||||
if (utf8_buf_compose_len > 0) {
|
||||
memcpy(r_utf8_buf, utf8_buf_compose, utf8_buf_compose_len);
|
||||
handled = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XKB_COMPOSE_CANCELLED: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
/**
|
||||
* \note Caller must lock `timer_mutex`.
|
||||
*/
|
||||
@@ -4198,9 +4267,19 @@ static void keyboard_handle_key(void *data,
|
||||
}
|
||||
|
||||
const GHOST_TKey gkey = xkb_map_gkey_or_scan_code(sym, key);
|
||||
|
||||
char utf8_buf[sizeof(GHOST_TEventKeyData::utf8_buf)] = {'\0'};
|
||||
if (etype == GHOST_kEventKeyDown) {
|
||||
xkb_state_key_get_utf8(seat->xkb.state, key_code, utf8_buf, sizeof(utf8_buf));
|
||||
/* Handle key-compose (dead-keys). */
|
||||
if (seat->xkb.compose_state &&
|
||||
xkb_compose_state_feed_and_get_utf8(
|
||||
seat->xkb.compose_state, seat->xkb.state, key_code, utf8_buf))
|
||||
{
|
||||
/* `utf8_buf` has been filled by a compose action. */
|
||||
}
|
||||
else {
|
||||
xkb_state_key_get_utf8(seat->xkb.state, key_code, utf8_buf, sizeof(utf8_buf));
|
||||
}
|
||||
}
|
||||
|
||||
seat->data_source_serial = serial;
|
||||
@@ -4235,8 +4314,18 @@ static void keyboard_handle_key(void *data,
|
||||
GHOST_IWindow *win = ghost_wl_surface_user_data(wl_surface_focus);
|
||||
GHOST_SystemWayland *system = seat->system;
|
||||
/* Calculate this value every time in case modifier keys are pressed. */
|
||||
|
||||
char utf8_buf[sizeof(GHOST_TEventKeyData::utf8_buf)] = {'\0'};
|
||||
xkb_state_key_get_utf8(seat->xkb.state, payload->key_code, utf8_buf, sizeof(utf8_buf));
|
||||
if (seat->xkb.compose_state &&
|
||||
xkb_compose_state_feed_and_get_utf8(
|
||||
seat->xkb.compose_state, seat->xkb.state, payload->key_code, utf8_buf))
|
||||
{
|
||||
/* `utf8_buf` has been filled by a compose action. */
|
||||
}
|
||||
else {
|
||||
xkb_state_key_get_utf8(seat->xkb.state, payload->key_code, utf8_buf, sizeof(utf8_buf));
|
||||
}
|
||||
|
||||
system->pushEvent_maybe_pending(new GHOST_EventKey(system->getMilliSeconds(),
|
||||
GHOST_kEventKeyDown,
|
||||
win,
|
||||
@@ -5318,6 +5407,11 @@ static void gwl_registry_wl_seat_add(GWL_Display *display, const GWL_RegisteryAd
|
||||
GWL_Seat *seat = new GWL_Seat;
|
||||
seat->system = display->system;
|
||||
seat->xkb.context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
|
||||
/* May be null (skip dead-key support in this case). */
|
||||
seat->xkb.compose_table = xkb_compose_table_new_from_locale(
|
||||
seat->xkb.context, ghost_wl_locale_from_env_with_default(), XKB_COMPOSE_COMPILE_NO_FLAGS);
|
||||
|
||||
seat->data_source = new GWL_DataSource;
|
||||
seat->wl.seat = static_cast<wl_seat *>(
|
||||
wl_registry_bind(display->wl.registry, params->name, &wl_seat_interface, 5));
|
||||
@@ -5453,6 +5547,9 @@ static void gwl_registry_wl_seat_remove(GWL_Display *display, void *user_data, c
|
||||
xkb_state_unref(seat->xkb.state_empty_with_shift);
|
||||
xkb_state_unref(seat->xkb.state_empty_with_numlock);
|
||||
|
||||
xkb_compose_state_unref(seat->xkb.compose_state);
|
||||
xkb_compose_table_unref(seat->xkb.compose_table);
|
||||
|
||||
xkb_context_unref(seat->xkb.context);
|
||||
|
||||
/* Remove the seat. */
|
||||
|
||||
Reference in New Issue
Block a user