Skip to content

Commit

Permalink
Respect current effective group index when getting key map (microsoft…
Browse files Browse the repository at this point in the history
  • Loading branch information
alexdima committed Oct 12, 2021
1 parent 9fe9d4e commit 91db859
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 6 deletions.
1 change: 1 addition & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export interface IWindowsKeyboardLayoutInfo {

export interface ILinuxKeyboardLayoutInfo {
model: string;
group: number;
layout: string;
variant: string;
options: string;
Expand Down
28 changes: 22 additions & 6 deletions src/keyboard_x.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,17 @@ class KeyModifierMaskToXModifierMask {
mode_switch_modifier = 0;
level3_modifier = 0; // AltGr is often mapped to the level3 modifier
level5_modifier = 0; // AltGr is mapped to the level5 modifier in the Neo layout family
effective_group_index = 0;

if (!display) {
return;
}

// See https://www.x.org/releases/X11R7.6/doc/libX11/specs/XKB/xkblib.html#determining_keyboard_state
XkbStateRec xkbState;
XkbGetState(display, XkbUseCoreKbd, &xkbState);
effective_group_index = xkbState.group;

XModifierKeymap* mod_map = XGetModifierMapping(display);
int max_mod_keys = mod_map->max_keypermod;
for (int mod_index = 0; mod_index <= 8; ++mod_index) {
Expand Down Expand Up @@ -76,7 +82,7 @@ class KeyModifierMaskToXModifierMask {
XFreeModifiermap(mod_map);
}

int XModFromKeyMod(int keyMod) {
int XStateFromKeyMod(int keyMod) {
int x_modifier = 0;

// Ctrl + Alt => AltGr
Expand Down Expand Up @@ -108,6 +114,9 @@ class KeyModifierMaskToXModifierMask {
x_modifier |= level5_modifier;
}

// See https://www.x.org/releases/X11R7.6/doc/libX11/specs/XKB/xkblib.html#xkb_state_to_core_protocol_state_transformation
x_modifier |= (effective_group_index << 13);

return x_modifier;
}

Expand All @@ -122,6 +131,7 @@ class KeyModifierMaskToXModifierMask {
int mode_switch_modifier;
int level3_modifier;
int level5_modifier;
int effective_group_index;

DISALLOW_COPY_AND_ASSIGN(KeyModifierMaskToXModifierMask);
};
Expand Down Expand Up @@ -191,33 +201,33 @@ napi_value _GetKeyMap(napi_env env, napi_callback_info info) {
}

{
key_event->state = mask_provider->XModFromKeyMod(kShiftKeyModifierMask);
key_event->state = mask_provider->XStateFromKeyMod(kShiftKeyModifierMask);
std::string withShift = GetStrFromXEvent(&event);
NAPI_CALL(env, napi_set_named_property_string_utf8(env, entry, "withShift", withShift.c_str()));
}

{
key_event->state = mask_provider->XModFromKeyMod(kLevel3KeyModifierMask);
key_event->state = mask_provider->XStateFromKeyMod(kLevel3KeyModifierMask);
std::string withAltGr = GetStrFromXEvent(&event);
NAPI_CALL(env, napi_set_named_property_string_utf8(env, entry, "withAltGr", withAltGr.c_str()));
}

{
key_event->state = mask_provider->XModFromKeyMod(kShiftKeyModifierMask | kLevel3KeyModifierMask);
key_event->state = mask_provider->XStateFromKeyMod(kShiftKeyModifierMask | kLevel3KeyModifierMask);
std::string withShiftAltGr = GetStrFromXEvent(&event);
NAPI_CALL(env, napi_set_named_property_string_utf8(env, entry, "withShiftAltGr", withShiftAltGr.c_str()));
}

{
// level 5 is important for the Neo layout family
key_event->state = mask_provider->XModFromKeyMod(kLevel5KeyModifierMask);
key_event->state = mask_provider->XStateFromKeyMod(kLevel5KeyModifierMask);
std::string withLevel5 = GetStrFromXEvent(&event);
NAPI_CALL(env, napi_set_named_property_string_utf8(env, entry, "withLevel5", withLevel5.c_str()));
}

{
// level3 + level5 is Level 6 in terms of the Neo layout family. (Shift + level5 has no special meaning.)
key_event->state = mask_provider->XModFromKeyMod(kLevel3KeyModifierMask | kLevel5KeyModifierMask);
key_event->state = mask_provider->XStateFromKeyMod(kLevel3KeyModifierMask | kLevel5KeyModifierMask);
std::string withLevel3Level5 = GetStrFromXEvent(&event);
NAPI_CALL(env, napi_set_named_property_string_utf8(env, entry, "withLevel3Level5", withLevel3Level5.c_str()));
}
Expand All @@ -241,13 +251,19 @@ napi_value _GetCurrentKeyboardLayout(napi_env env, napi_callback_info info) {
return result;
}

// See https://www.x.org/releases/X11R7.6/doc/libX11/specs/XKB/xkblib.html#determining_keyboard_state
XkbStateRec xkbState;
XkbGetState(display, XkbUseCoreKbd, &xkbState);
int effective_group_index = xkbState.group;

XkbRF_VarDefsRec vdr;
char *tmp = NULL;
int res = XkbRF_GetNamesProp(display, &tmp, &vdr);
if (res) {
NAPI_CALL(env, napi_create_object(env, &result));

NAPI_CALL(env, napi_set_named_property_string_utf8(env, result, "model", vdr.model ? vdr.model : ""));
NAPI_CALL(env, napi_set_named_property_int32(env, result, "group", effective_group_index));
NAPI_CALL(env, napi_set_named_property_string_utf8(env, result, "layout", vdr.layout ? vdr.layout : ""));
NAPI_CALL(env, napi_set_named_property_string_utf8(env, result, "variant", vdr.variant ? vdr.variant : ""));
NAPI_CALL(env, napi_set_named_property_string_utf8(env, result, "options", vdr.options ? vdr.options : ""));
Expand Down
7 changes: 7 additions & 0 deletions src/keymapping.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ napi_status napi_set_named_property_string_utf8(napi_env env, napi_value object,
return napi_ok;
}

napi_status napi_set_named_property_int32(napi_env env, napi_value object, const char *utf8Name, int value) {
napi_value _value;
NAPI_CALL_RETURN_STATUS(env, napi_create_int32(env, value, &_value));
NAPI_CALL_RETURN_STATUS(env, napi_set_named_property(env, object, utf8Name, _value));
return napi_ok;
}

napi_value napi_fetch_null(napi_env env) {
napi_value result;
NAPI_CALL(env, napi_get_null(env, &result));
Expand Down
1 change: 1 addition & 0 deletions src/keymapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ napi_value _OnDidChangeKeyboardLayout(napi_env env, napi_callback_info info);
napi_value _isISOKeyboard(napi_env env, napi_callback_info info);

napi_status napi_set_named_property_string_utf8(napi_env env, napi_value object, const char *utf8Name, const char *value);
napi_status napi_set_named_property_int32(napi_env env, napi_value object, const char *utf8Name, int value);
napi_value napi_fetch_null(napi_env env);
napi_value napi_fetch_undefined(napi_env env);
napi_value napi_fetch_boolean(napi_env env, bool value);
Expand Down

0 comments on commit 91db859

Please sign in to comment.