Commit d64ea8e4 authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard

winewayland.drv: Enumerate Xkb layouts and create matching HKL.

parent e8c96e2e
......@@ -702,6 +702,8 @@ INOTIFY_LIBS
INOTIFY_CFLAGS
PCSCLITE_LIBS
PCAP_LIBS
XKBREGISTRY_LIBS
XKBREGISTRY_CFLAGS
XKBCOMMON_LIBS
XKBCOMMON_CFLAGS
WAYLAND_SCANNER
......@@ -1797,6 +1799,8 @@ WAYLAND_CLIENT_CFLAGS
WAYLAND_CLIENT_LIBS
XKBCOMMON_CFLAGS
XKBCOMMON_LIBS
XKBREGISTRY_CFLAGS
XKBREGISTRY_LIBS
INOTIFY_CFLAGS
INOTIFY_LIBS
DBUS_CFLAGS
......@@ -2620,6 +2624,10 @@ Some influential environment variables:
C compiler flags for xkbcommon, overriding pkg-config
XKBCOMMON_LIBS
Linker flags for xkbcommon, overriding pkg-config
XKBREGISTRY_CFLAGS
C compiler flags for xkbregistry, overriding pkg-config
XKBREGISTRY_LIBS
Linker flags for xkbregistry, overriding pkg-config
INOTIFY_CFLAGS
C compiler flags for libinotify, overriding pkg-config
INOTIFY_LIBS
......@@ -15956,8 +15964,86 @@ fi
CPPFLAGS=$ac_save_CPPFLAGS
rm -f conftest.err
if ${XKBREGISTRY_CFLAGS:+false} :
then :
if test ${PKG_CONFIG+y}
then :
XKBREGISTRY_CFLAGS=`$PKG_CONFIG --cflags xkbregistry 2>conftest.err`
fi
fi
if ${XKBREGISTRY_LIBS:+false} :
then :
if test ${PKG_CONFIG+y}
then :
XKBREGISTRY_LIBS=`$PKG_CONFIG --libs xkbregistry 2>/dev/null`
fi
fi
printf "%s\n" "$as_me:${as_lineno-$LINENO}: xkbregistry cflags: $XKBREGISTRY_CFLAGS" >&5
printf "%s\n" "$as_me:${as_lineno-$LINENO}: xkbregistry libs: $XKBREGISTRY_LIBS" >&5
if test -s conftest.err; then
printf %s "$as_me:${as_lineno-$LINENO}: xkbregistry errors: " >&5
cat conftest.err >&5
fi
rm -f conftest.err
ac_save_CPPFLAGS=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $XKBREGISTRY_CFLAGS"
ac_fn_c_check_header_compile "$LINENO" "xkbcommon/xkbregistry.h" "ac_cv_header_xkbcommon_xkbregistry_h" "$ac_includes_default"
if test "x$ac_cv_header_xkbcommon_xkbregistry_h" = xyes
then :
printf "%s\n" "#define HAVE_XKBCOMMON_XKBREGISTRY_H 1" >>confdefs.h
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for rxkb_context_new in -lxkbregistry" >&5
printf %s "checking for rxkb_context_new in -lxkbregistry... " >&6; }
if test ${ac_cv_lib_xkbregistry_rxkb_context_new+y}
then :
printf %s "(cached) " >&6
else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lxkbregistry $XKBREGISTRY_LIBS $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
char rxkb_context_new ();
int
main (void)
{
return rxkb_context_new ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ac_cv_lib_xkbregistry_rxkb_context_new=yes
else $as_nop
ac_cv_lib_xkbregistry_rxkb_context_new=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xkbregistry_rxkb_context_new" >&5
printf "%s\n" "$ac_cv_lib_xkbregistry_rxkb_context_new" >&6; }
if test "x$ac_cv_lib_xkbregistry_rxkb_context_new" = xyes
then :
:
else $as_nop
XKBREGISTRY_LIBS=""
fi
CPPFLAGS=$ac_save_CPPFLAGS
fi
if test -z "$WAYLAND_CLIENT_LIBS" -o -z "$WAYLAND_SCANNER" -o -z "$XKBCOMMON_LIBS" -o "$ac_cv_header_linux_input_h" = "no"
if test -z "$WAYLAND_CLIENT_LIBS" -o -z "$WAYLAND_SCANNER" -o -z "$XKBCOMMON_LIBS" -o -z "$XKBREGISTRY_LIBS" -o "$ac_cv_header_linux_input_h" = "no"
then :
case "x$with_wayland" in
x) as_fn_append wine_notices "|Wayland ${notice_platform}development files not found, the Wayland driver won't be supported." ;;
......@@ -23545,6 +23631,8 @@ WAYLAND_CLIENT_LIBS = $WAYLAND_CLIENT_LIBS
WAYLAND_SCANNER = $WAYLAND_SCANNER
XKBCOMMON_CFLAGS = $XKBCOMMON_CFLAGS
XKBCOMMON_LIBS = $XKBCOMMON_LIBS
XKBREGISTRY_CFLAGS = $XKBREGISTRY_CFLAGS
XKBREGISTRY_LIBS = $XKBREGISTRY_LIBS
PCAP_LIBS = $PCAP_LIBS
PCSCLITE_LIBS = $PCSCLITE_LIBS
INOTIFY_CFLAGS = $INOTIFY_CFLAGS
......
......@@ -1380,8 +1380,11 @@ then
WINE_PACKAGE_FLAGS(XKBCOMMON,[xkbcommon],,,,
[AC_CHECK_HEADERS([xkbcommon/xkbcommon.h])
AC_CHECK_LIB(xkbcommon,xkb_context_new,[:],[XKBCOMMON_LIBS=""],[$XKBCOMMON_LIBS])])
WINE_PACKAGE_FLAGS(XKBREGISTRY,[xkbregistry],,,,
[AC_CHECK_HEADERS([xkbcommon/xkbregistry.h])
AC_CHECK_LIB(xkbregistry,rxkb_context_new,[:],[XKBREGISTRY_LIBS=""],[$XKBREGISTRY_LIBS])])
fi
WINE_NOTICE_WITH(wayland, [test -z "$WAYLAND_CLIENT_LIBS" -o -z "$WAYLAND_SCANNER" -o -z "$XKBCOMMON_LIBS" -o "$ac_cv_header_linux_input_h" = "no"],
WINE_NOTICE_WITH(wayland, [test -z "$WAYLAND_CLIENT_LIBS" -o -z "$WAYLAND_SCANNER" -o -z "$XKBCOMMON_LIBS" -o -z "$XKBREGISTRY_LIBS" -o "$ac_cv_header_linux_input_h" = "no"],
[Wayland ${notice_platform}development files not found, the Wayland driver won't be supported.],
[enable_winewayland_drv])
......
MODULE = winewayland.drv
UNIXLIB = winewayland.so
UNIX_CFLAGS = $(WAYLAND_CLIENT_CFLAGS) $(XKBCOMMON_CFLAGS)
UNIX_LIBS = -lwin32u $(WAYLAND_CLIENT_LIBS) $(XKBCOMMON_LIBS) $(PTHREAD_LIBS) -lm
UNIX_CFLAGS = $(WAYLAND_CLIENT_CFLAGS) $(XKBCOMMON_CFLAGS) $(XKBREGISTRY_CFLAGS)
UNIX_LIBS = -lwin32u $(WAYLAND_CLIENT_LIBS) $(XKBCOMMON_LIBS) $(XKBREGISTRY_LIBS) $(PTHREAD_LIBS) -lm
SOURCES = \
display.c \
......
......@@ -24,6 +24,7 @@
#endif
#include "config.h"
#include <stdlib.h>
#include <linux/input.h>
#undef SW_MAX /* Also defined in winuser.rh */
......@@ -36,6 +37,23 @@
WINE_DEFAULT_DEBUG_CHANNEL(keyboard);
WINE_DECLARE_DEBUG_CHANNEL(key);
struct layout
{
struct list entry;
char *xkb_layout;
int xkb_group;
LANGID lang;
WORD index;
/* "Layout Id", used by NtUserGetKeyboardLayoutName / LoadKeyboardLayoutW */
WORD layout_id;
};
/* These are only used from the wayland event thread and don't need locking */
static struct list xkb_layouts = LIST_INIT(xkb_layouts);
static struct rxkb_context *rxkb_context;
static HKL keyboard_hkl; /* the HKL matching the currently active xkb group */
static WORD key2scan(UINT key)
{
/* base keys can be mapped directly */
......@@ -122,6 +140,198 @@ static WORD key2scan(UINT key)
return 0x200 | (key & 0x7f);
}
static inline LANGID langid_from_xkb_layout(const char *layout, size_t layout_len)
{
#define MAKEINDEX(c0, c1) (MAKEWORD(c0, c1) - MAKEWORD('a', 'a'))
static const LANGID langids[] =
{
[MAKEINDEX('a','f')] = MAKELANGID(LANG_DARI, SUBLANG_DEFAULT),
[MAKEINDEX('a','l')] = MAKELANGID(LANG_ALBANIAN, SUBLANG_DEFAULT),
[MAKEINDEX('a','m')] = MAKELANGID(LANG_ARMENIAN, SUBLANG_DEFAULT),
[MAKEINDEX('a','t')] = MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN_AUSTRIAN),
[MAKEINDEX('a','z')] = MAKELANGID(LANG_AZERBAIJANI, SUBLANG_DEFAULT),
[MAKEINDEX('a','u')] = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_AUS),
[MAKEINDEX('b','a')] = MAKELANGID(LANG_BOSNIAN, SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC),
[MAKEINDEX('b','d')] = MAKELANGID(LANG_BANGLA, SUBLANG_DEFAULT),
[MAKEINDEX('b','e')] = MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_BELGIAN),
[MAKEINDEX('b','g')] = MAKELANGID(LANG_BULGARIAN, SUBLANG_DEFAULT),
[MAKEINDEX('b','r')] = MAKELANGID(LANG_PORTUGUESE, 2),
[MAKEINDEX('b','t')] = MAKELANGID(LANG_TIBETAN, 3),
[MAKEINDEX('b','w')] = MAKELANGID(LANG_TSWANA, SUBLANG_TSWANA_BOTSWANA),
[MAKEINDEX('b','y')] = MAKELANGID(LANG_BELARUSIAN, SUBLANG_DEFAULT),
[MAKEINDEX('c','a')] = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_CAN),
[MAKEINDEX('c','d')] = MAKELANGID(LANG_FRENCH, SUBLANG_CUSTOM_UNSPECIFIED),
[MAKEINDEX('c','h')] = MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN_SWISS),
[MAKEINDEX('c','m')] = MAKELANGID(LANG_FRENCH, 11),
[MAKEINDEX('c','n')] = MAKELANGID(LANG_CHINESE, SUBLANG_DEFAULT),
[MAKEINDEX('c','z')] = MAKELANGID(LANG_CZECH, SUBLANG_DEFAULT),
[MAKEINDEX('d','e')] = MAKELANGID(LANG_GERMAN, SUBLANG_DEFAULT),
[MAKEINDEX('d','k')] = MAKELANGID(LANG_DANISH, SUBLANG_DEFAULT),
[MAKEINDEX('d','z')] = MAKELANGID(LANG_TAMAZIGHT, SUBLANG_TAMAZIGHT_ALGERIA_LATIN),
[MAKEINDEX('e','e')] = MAKELANGID(LANG_ESTONIAN, SUBLANG_DEFAULT),
[MAKEINDEX('e','s')] = MAKELANGID(LANG_SPANISH, SUBLANG_DEFAULT),
[MAKEINDEX('e','t')] = MAKELANGID(LANG_AMHARIC, SUBLANG_DEFAULT),
[MAKEINDEX('f','i')] = MAKELANGID(LANG_FINNISH, SUBLANG_DEFAULT),
[MAKEINDEX('f','o')] = MAKELANGID(LANG_FAEROESE, SUBLANG_DEFAULT),
[MAKEINDEX('f','r')] = MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT),
[MAKEINDEX('g','b')] = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_UK),
[MAKEINDEX('g','e')] = MAKELANGID(LANG_GEORGIAN, SUBLANG_DEFAULT),
[MAKEINDEX('g','h')] = MAKELANGID(LANG_ENGLISH, SUBLANG_CUSTOM_UNSPECIFIED),
[MAKEINDEX('g','n')] = MAKELANGID(LANG_NEUTRAL, SUBLANG_CUSTOM_DEFAULT),
[MAKEINDEX('g','r')] = MAKELANGID(LANG_GREEK, SUBLANG_DEFAULT),
[MAKEINDEX('h','r')] = MAKELANGID(LANG_CROATIAN, SUBLANG_DEFAULT),
[MAKEINDEX('h','u')] = MAKELANGID(LANG_HUNGARIAN, SUBLANG_DEFAULT),
[MAKEINDEX('i','d')] = MAKELANGID(LANG_INDONESIAN, SUBLANG_DEFAULT),
[MAKEINDEX('i','e')] = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_EIRE),
[MAKEINDEX('i','l')] = MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT),
[MAKEINDEX('i','n')] = MAKELANGID(LANG_HINDI, SUBLANG_DEFAULT),
[MAKEINDEX('i','q')] = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_IRAQ),
[MAKEINDEX('i','r')] = MAKELANGID(LANG_PERSIAN, SUBLANG_DEFAULT),
[MAKEINDEX('i','s')] = MAKELANGID(LANG_ICELANDIC, SUBLANG_DEFAULT),
[MAKEINDEX('i','t')] = MAKELANGID(LANG_ITALIAN, SUBLANG_DEFAULT),
[MAKEINDEX('j','p')] = MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT),
[MAKEINDEX('k','e')] = MAKELANGID(LANG_NEUTRAL, SUBLANG_CUSTOM_DEFAULT),
[MAKEINDEX('k','g')] = MAKELANGID(LANG_KYRGYZ, SUBLANG_DEFAULT),
[MAKEINDEX('k','h')] = MAKELANGID(LANG_KHMER, SUBLANG_DEFAULT),
[MAKEINDEX('k','r')] = MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT),
[MAKEINDEX('k','z')] = MAKELANGID(LANG_KAZAK, SUBLANG_DEFAULT),
[MAKEINDEX('l','a')] = MAKELANGID(LANG_LAO, SUBLANG_DEFAULT),
[MAKEINDEX('l','k')] = MAKELANGID(LANG_SINHALESE, SUBLANG_DEFAULT),
[MAKEINDEX('l','t')] = MAKELANGID(LANG_LITHUANIAN, SUBLANG_DEFAULT),
[MAKEINDEX('l','v')] = MAKELANGID(LANG_LATVIAN, SUBLANG_DEFAULT),
[MAKEINDEX('m','a')] = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_MOROCCO),
[MAKEINDEX('m','d')] = MAKELANGID(LANG_ROMANIAN, SUBLANG_CUSTOM_UNSPECIFIED),
[MAKEINDEX('m','e')] = MAKELANGID(LANG_SERBIAN, SUBLANG_SERBIAN_MONTENEGRO_LATIN),
[MAKEINDEX('m','k')] = MAKELANGID(LANG_MACEDONIAN, SUBLANG_DEFAULT),
[MAKEINDEX('m','l')] = MAKELANGID(LANG_NEUTRAL, SUBLANG_CUSTOM_DEFAULT),
[MAKEINDEX('m','m')] = MAKELANGID(0x55 /*LANG_BURMESE*/, SUBLANG_DEFAULT),
[MAKEINDEX('m','n')] = MAKELANGID(LANG_MONGOLIAN, SUBLANG_DEFAULT),
[MAKEINDEX('m','t')] = MAKELANGID(LANG_MALTESE, SUBLANG_DEFAULT),
[MAKEINDEX('m','v')] = MAKELANGID(LANG_DIVEHI, SUBLANG_DEFAULT),
[MAKEINDEX('m','y')] = MAKELANGID(LANG_MALAY, SUBLANG_DEFAULT),
[MAKEINDEX('n','g')] = MAKELANGID(LANG_ENGLISH, SUBLANG_CUSTOM_UNSPECIFIED),
[MAKEINDEX('n','l')] = MAKELANGID(LANG_DUTCH, SUBLANG_DEFAULT),
[MAKEINDEX('n','o')] = MAKELANGID(LANG_NORWEGIAN, SUBLANG_DEFAULT),
[MAKEINDEX('n','p')] = MAKELANGID(LANG_NEPALI, SUBLANG_DEFAULT),
[MAKEINDEX('p','h')] = MAKELANGID(LANG_FILIPINO, SUBLANG_DEFAULT),
[MAKEINDEX('p','k')] = MAKELANGID(LANG_URDU, SUBLANG_DEFAULT),
[MAKEINDEX('p','l')] = MAKELANGID(LANG_POLISH, SUBLANG_DEFAULT),
[MAKEINDEX('p','t')] = MAKELANGID(LANG_PORTUGUESE, SUBLANG_DEFAULT),
[MAKEINDEX('r','o')] = MAKELANGID(LANG_ROMANIAN, SUBLANG_DEFAULT),
[MAKEINDEX('r','s')] = MAKELANGID(LANG_SERBIAN, SUBLANG_SERBIAN_LATIN),
[MAKEINDEX('r','u')] = MAKELANGID(LANG_RUSSIAN, SUBLANG_DEFAULT),
[MAKEINDEX('s','e')] = MAKELANGID(LANG_SWEDISH, SUBLANG_DEFAULT),
[MAKEINDEX('s','i')] = MAKELANGID(LANG_SLOVENIAN, SUBLANG_DEFAULT),
[MAKEINDEX('s','k')] = MAKELANGID(LANG_SLOVAK, SUBLANG_DEFAULT),
[MAKEINDEX('s','n')] = MAKELANGID(LANG_WOLOF, SUBLANG_DEFAULT),
[MAKEINDEX('s','y')] = MAKELANGID(LANG_SYRIAC, SUBLANG_DEFAULT),
[MAKEINDEX('t','g')] = MAKELANGID(LANG_FRENCH, SUBLANG_CUSTOM_UNSPECIFIED),
[MAKEINDEX('t','h')] = MAKELANGID(LANG_THAI, SUBLANG_DEFAULT),
[MAKEINDEX('t','j')] = MAKELANGID(LANG_TAJIK, SUBLANG_DEFAULT),
[MAKEINDEX('t','m')] = MAKELANGID(LANG_TURKMEN, SUBLANG_DEFAULT),
[MAKEINDEX('t','r')] = MAKELANGID(LANG_TURKISH, SUBLANG_DEFAULT),
[MAKEINDEX('t','w')] = MAKELANGID(LANG_CHINESE, SUBLANG_CUSTOM_UNSPECIFIED),
[MAKEINDEX('t','z')] = MAKELANGID(LANG_SWAHILI, SUBLANG_CUSTOM_UNSPECIFIED),
[MAKEINDEX('u','a')] = MAKELANGID(LANG_UKRAINIAN, SUBLANG_DEFAULT),
[MAKEINDEX('u','s')] = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
[MAKEINDEX('u','z')] = MAKELANGID(LANG_UZBEK, 2),
[MAKEINDEX('v','n')] = MAKELANGID(LANG_VIETNAMESE, SUBLANG_DEFAULT),
[MAKEINDEX('z','a')] = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_SOUTH_AFRICA),
};
LANGID langid;
if (layout_len == 2 && (langid = langids[MAKEINDEX(layout[0], layout[1])])) return langid;
if (layout_len == 3 && !memcmp(layout, "ara", layout_len)) return MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT);
if (layout_len == 3 && !memcmp(layout, "epo", layout_len)) return MAKELANGID(LANG_NEUTRAL, SUBLANG_CUSTOM_DEFAULT);
if (layout_len == 3 && !memcmp(layout, "mao", layout_len)) return MAKELANGID(LANG_MAORI, SUBLANG_DEFAULT);
if (layout_len == 4 && !memcmp(layout, "brai", layout_len)) return MAKELANGID(LANG_NEUTRAL, SUBLANG_CUSTOM_DEFAULT);
if (layout_len == 5 && !memcmp(layout, "latam", layout_len)) return MAKELANGID(LANG_SPANISH, SUBLANG_CUSTOM_UNSPECIFIED);
#undef MAKEINDEX
FIXME("Unknown layout language %s\n", debugstr_a(layout));
return MAKELANGID(LANG_NEUTRAL, SUBLANG_CUSTOM_UNSPECIFIED);
};
static HKL get_layout_hkl(struct layout *layout, LCID locale)
{
if (!layout->layout_id) return (HKL)(UINT_PTR)MAKELONG(locale, layout->lang);
else return (HKL)(UINT_PTR)MAKELONG(locale, 0xf000 | layout->layout_id);
}
static void add_xkb_layout(const char *xkb_layout, xkb_layout_index_t xkb_group, LANGID lang)
{
static WORD next_layout_id = 1;
struct layout *layout;
unsigned int len;
WORD index = 0;
char *ptr;
TRACE("xkb_layout=%s xkb_group=%u lang=%04x\n", xkb_layout, xkb_group, lang);
LIST_FOR_EACH_ENTRY(layout, &xkb_layouts, struct layout, entry)
if (layout->lang == lang) index++;
len = strlen(xkb_layout) + 1;
if (!(layout = calloc(1, sizeof(*layout) + len)))
{
ERR("Failed to allocate memory for Xkb layout entry\n");
return;
}
ptr = (char *)(layout + 1);
layout->xkb_layout = strcpy(ptr, xkb_layout);
layout->xkb_group = xkb_group;
layout->lang = lang;
layout->index = index;
if (index) layout->layout_id = next_layout_id++;
TRACE("Created layout entry=%p index=%04x lang=%04x id=%04x\n", layout, layout->index, layout->lang, layout->layout_id);
list_add_tail(&xkb_layouts, &layout->entry);
}
static void set_current_xkb_group(xkb_layout_index_t xkb_group)
{
struct wayland_keyboard *keyboard = &process_wayland.keyboard;
LCID locale = LOWORD(NtUserGetKeyboardLayout(0));
struct layout *layout;
HKL hkl;
LIST_FOR_EACH_ENTRY(layout, &xkb_layouts, struct layout, entry)
if (layout->xkb_group == xkb_group) break;
if (&layout->entry != &xkb_layouts)
hkl = get_layout_hkl(layout, locale);
else
{
ERR("Failed to find Xkb Layout for group %d\n", xkb_group);
hkl = keyboard_hkl;
}
if (hkl == keyboard_hkl) return;
keyboard_hkl = hkl;
TRACE("Changing keyboard layout to %p\n", hkl);
NtUserPostMessage(keyboard->focused_hwnd, WM_INPUTLANGCHANGEREQUEST, 0 /*FIXME*/,
(LPARAM)keyboard_hkl);
}
static BOOL find_xkb_layout_variant(const char *name, const char **layout, const char **variant)
{
struct rxkb_layout *iter;
for (iter = rxkb_layout_first(rxkb_context); iter; iter = rxkb_layout_next(iter))
{
if (!strcmp(name, rxkb_layout_get_description(iter)))
{
*layout = rxkb_layout_get_name(iter);
*variant = rxkb_layout_get_variant(iter);
return TRUE;
}
}
return FALSE;
}
/**********************************************************************
* Keyboard handling
*/
......@@ -143,7 +353,9 @@ static void keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard,
{
struct wayland_keyboard *keyboard = &process_wayland.keyboard;
struct xkb_keymap *xkb_keymap = NULL;
xkb_layout_index_t xkb_group;
struct xkb_state *xkb_state;
struct layout *entry, *next;
char *keymap_str;
TRACE("format=%d fd=%d size=%d\n", format, fd, size);
......@@ -169,12 +381,39 @@ static void keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard,
return;
}
LIST_FOR_EACH_ENTRY_SAFE(entry, next, &xkb_layouts, struct layout, entry)
{
list_remove(&entry->entry);
free(entry);
}
for (xkb_group = 0; xkb_group < xkb_keymap_num_layouts(xkb_keymap); xkb_group++)
{
const char *layout_name = xkb_keymap_layout_get_name(xkb_keymap, xkb_group);
const char *layout, *variant = NULL;
int layout_len, variant_len = 0;
char buffer[1024];
LANGID lang;
if (!find_xkb_layout_variant(layout_name, &layout, &variant)) layout = "us";
if (variant) variant_len = strlen(variant);
layout_len = strlen(layout);
TRACE("Found layout %u name %s -> %s:%s\n", xkb_group, layout_name, layout, variant);
lang = langid_from_xkb_layout(layout, layout_len);
snprintf(buffer, ARRAY_SIZE(buffer), "%.*s:%.*s", layout_len, layout, variant_len, variant);
add_xkb_layout(buffer, xkb_group, lang);
}
if ((xkb_state = xkb_state_new(xkb_keymap)))
{
pthread_mutex_lock(&keyboard->mutex);
xkb_state_unref(keyboard->xkb_state);
keyboard->xkb_state = xkb_state;
pthread_mutex_unlock(&keyboard->mutex);
set_current_xkb_group(0);
}
xkb_keymap_unref(xkb_keymap);
......@@ -198,7 +437,8 @@ static void keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard,
keyboard->focused_hwnd = hwnd;
pthread_mutex_unlock(&keyboard->mutex);
/* FIXME: update foreground window as well */
NtUserPostMessage(keyboard->focused_hwnd, WM_INPUTLANGCHANGEREQUEST, 0 /*FIXME*/,
(LPARAM)keyboard_hkl);
}
static void keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard,
......@@ -236,7 +476,7 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard,
input.type = INPUT_KEYBOARD;
input.ki.wScan = scan & 0xff;
input.ki.wVk = NtUserMapVirtualKeyEx(scan, MAPVK_VSC_TO_VK_EX, NtUserGetKeyboardLayout(0));
input.ki.wVk = NtUserMapVirtualKeyEx(scan, MAPVK_VSC_TO_VK_EX, keyboard_hkl);
if (scan & ~0xff) input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
if (state == WL_KEYBOARD_KEY_STATE_RELEASED) input.ki.dwFlags |= KEYEVENTF_KEYUP;
......@@ -260,6 +500,8 @@ static void keyboard_handle_modifiers(void *data, struct wl_keyboard *wl_keyboar
mods_locked, 0, 0, xkb_group);
pthread_mutex_unlock(&keyboard->mutex);
set_current_xkb_group(xkb_group);
/* FIXME: Sync wine modifier state with XKB modifier state. */
}
......@@ -299,6 +541,13 @@ void wayland_keyboard_init(struct wl_keyboard *wl_keyboard)
struct wayland_keyboard *keyboard = &process_wayland.keyboard;
struct xkb_context *xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (!(rxkb_context = rxkb_context_new(RXKB_CONTEXT_NO_FLAGS))
|| !rxkb_context_parse_default_ruleset(rxkb_context))
{
ERR("Failed to parse default Xkb ruleset\n");
return;
}
if (!xkb_context)
{
ERR("Failed to create XKB context\n");
......@@ -337,4 +586,10 @@ void wayland_keyboard_deinit(void)
keyboard->xkb_state = NULL;
}
pthread_mutex_unlock(&keyboard->mutex);
if (rxkb_context)
{
rxkb_context_unref(rxkb_context);
rxkb_context = NULL;
}
}
......@@ -28,6 +28,7 @@
#include <pthread.h>
#include <wayland-client.h>
#include <xkbcommon/xkbcommon.h>
#include <xkbcommon/xkbregistry.h>
#include "viewporter-client-protocol.h"
#include "xdg-output-unstable-v1-client-protocol.h"
#include "xdg-shell-client-protocol.h"
......
......@@ -675,6 +675,9 @@
/* Define to 1 if you have the <xkbcommon/xkbcommon.h> header file. */
#undef HAVE_XKBCOMMON_XKBCOMMON_H
/* Define to 1 if you have the <xkbcommon/xkbregistry.h> header file. */
#undef HAVE_XKBCOMMON_XKBREGISTRY_H
/* Define if Xrender has the XRenderCreateLinearGradient function */
#undef HAVE_XRENDERCREATELINEARGRADIENT
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment