napi_value _GetKeyMap()

in src/keyboard_mac.mm [81:147]


napi_value _GetKeyMap(napi_env env, napi_callback_info info) {

  napi_value result;
  NAPI_CALL(env, napi_create_object(env, &result));

  TISInputSourceRef source = TISCopyCurrentKeyboardInputSource();
  CFDataRef layout_data = static_cast<CFDataRef>((TISGetInputSourceProperty(source, kTISPropertyUnicodeKeyLayoutData)));
  if (!layout_data) {
    // TISGetInputSourceProperty returns null with  Japanese keyboard layout.
    // Using TISCopyCurrentKeyboardLayoutInputSource to fix NULL return.
    source = TISCopyCurrentKeyboardLayoutInputSource();
    layout_data = static_cast<CFDataRef>((TISGetInputSourceProperty(source, kTISPropertyUnicodeKeyLayoutData)));
    if (!layout_data) {
      // https://developer.apple.com/library/mac/documentation/TextFonts/Reference/TextInputSourcesReference/#//apple_ref/c/func/TISGetInputSourceProperty
      return result;
    }
  }

  const UCKeyboardLayout* keyboardLayout = reinterpret_cast<const UCKeyboardLayout*>(CFDataGetBytePtr(layout_data));

  size_t cnt = sizeof(usb_keycode_map) / sizeof(usb_keycode_map[0]);

  napi_value _true;
  NAPI_CALL(env, napi_get_boolean(env, true, &_true));

  napi_value _false;
  NAPI_CALL(env, napi_get_boolean(env, false, &_false));

  for (size_t i = 0; i < cnt; ++i) {
    const char *code = usb_keycode_map[i].code;
    int native_keycode = usb_keycode_map[i].native_keycode;

    if (!code || native_keycode >= 0xffff) {
      continue;
    }

    napi_value entry;
    NAPI_CALL(env, napi_create_object(env, &entry));

    {
      std::pair<bool,std::string> value = ConvertKeyCodeToText(keyboardLayout, native_keycode, 0);
      NAPI_CALL(env, napi_set_named_property_string_utf8(env, entry, "value", value.second.c_str()));
      NAPI_CALL(env, napi_set_named_property(env, entry, "valueIsDeadKey", value.first ? _true : _false));
    }

    {
      std::pair<bool,std::string> withShift = ConvertKeyCodeToText(keyboardLayout, native_keycode, kShiftKeyModifierMask);
      NAPI_CALL(env, napi_set_named_property_string_utf8(env, entry, "withShift", withShift.second.c_str()));
      NAPI_CALL(env, napi_set_named_property(env, entry, "withShiftIsDeadKey", withShift.first ? _true : _false));
    }

    {
      std::pair<bool,std::string> withAltGr = ConvertKeyCodeToText(keyboardLayout, native_keycode, kAltKeyModifierMask);
      NAPI_CALL(env, napi_set_named_property_string_utf8(env, entry, "withAltGr", withAltGr.second.c_str()));
      NAPI_CALL(env, napi_set_named_property(env, entry, "withAltGrIsDeadKey", withAltGr.first ? _true : _false));
    }

    {
      std::pair<bool,std::string> withShiftAltGr = ConvertKeyCodeToText(keyboardLayout, native_keycode, kShiftKeyModifierMask | kAltKeyModifierMask);
      NAPI_CALL(env, napi_set_named_property_string_utf8(env, entry, "withShiftAltGr", withShiftAltGr.second.c_str()));
      NAPI_CALL(env, napi_set_named_property(env, entry, "withShiftAltGrIsDeadKey", withShiftAltGr.first ? _true : _false));
    }

    NAPI_CALL(env, napi_set_named_property(env, result, code, entry));
  }
  return result;
}