xkb_tracker.cc 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/exo/xkb_tracker.h"
  5. #if BUILDFLAG(USE_XKBCOMMON)
  6. #include "components/exo/keyboard_modifiers.h"
  7. #include "ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.h"
  8. #endif
  9. namespace exo {
  10. #if BUILDFLAG(USE_XKBCOMMON)
  11. XkbTracker::XkbTracker() {
  12. UpdateKeyboardLayoutInternal(nullptr);
  13. UpdateKeyboardModifiersInternal();
  14. }
  15. #else
  16. XkbTracker::XkbTracker() = default;
  17. #endif
  18. XkbTracker::~XkbTracker() = default;
  19. #if BUILDFLAG(USE_XKBCOMMON)
  20. void XkbTracker::UpdateKeyboardLayout(const std::string& name) {
  21. std::string layout_id, layout_variant;
  22. ui::XkbKeyboardLayoutEngine::ParseLayoutName(name, &layout_id,
  23. &layout_variant);
  24. xkb_rule_names names = {.rules = nullptr,
  25. .model = "pc101",
  26. .layout = layout_id.c_str(),
  27. .variant = layout_variant.c_str(),
  28. .options = ""};
  29. UpdateKeyboardLayoutInternal(&names);
  30. UpdateKeyboardModifiersInternal();
  31. }
  32. void XkbTracker::UpdateKeyboardModifiers(int modifier_flags) {
  33. // CrOS treats numlock as always on, but its event flags actually have that
  34. // key disabled, (i.e. chromeos apps specially handle numpad key events as
  35. // though numlock is on). In order to get the same result from the linux apps,
  36. // we need to ensure they always treat numlock as on.
  37. modifier_flags_ = modifier_flags | ui::EF_NUM_LOCK_ON;
  38. UpdateKeyboardModifiersInternal();
  39. }
  40. uint32_t XkbTracker::GetKeysym(uint32_t xkb_keycode) const {
  41. return xkb_state_key_get_one_sym(xkb_state_.get(), xkb_keycode);
  42. }
  43. std::unique_ptr<char, base::FreeDeleter> XkbTracker::GetKeymap() const {
  44. return std::unique_ptr<char, base::FreeDeleter>(
  45. xkb_keymap_get_as_string(xkb_keymap_.get(), XKB_KEYMAP_FORMAT_TEXT_V1));
  46. }
  47. KeyboardModifiers XkbTracker::GetModifiers() const {
  48. return {
  49. xkb_state_serialize_mods(xkb_state_.get(), XKB_STATE_MODS_DEPRESSED),
  50. xkb_state_serialize_mods(xkb_state_.get(), XKB_STATE_MODS_LOCKED),
  51. xkb_state_serialize_mods(xkb_state_.get(), XKB_STATE_MODS_LATCHED),
  52. xkb_state_serialize_layout(xkb_state_.get(), XKB_STATE_LAYOUT_EFFECTIVE),
  53. };
  54. }
  55. void XkbTracker::UpdateKeyboardLayoutInternal(const xkb_rule_names* names) {
  56. xkb_keymap_.reset(xkb_keymap_new_from_names(xkb_context_.get(), names,
  57. XKB_KEYMAP_COMPILE_NO_FLAGS));
  58. xkb_state_.reset(xkb_state_new(xkb_keymap_.get()));
  59. xkb_modifier_converter_ =
  60. ui::XkbModifierConverter::CreateFromKeymap(xkb_keymap_.get());
  61. }
  62. void XkbTracker::UpdateKeyboardModifiersInternal() {
  63. xkb_mod_mask_t xkb_modifiers =
  64. xkb_modifier_converter_.MaskFromUiFlags(modifier_flags_);
  65. xkb_state_update_mask(xkb_state_.get(), xkb_modifiers, 0, 0, 0, 0, 0);
  66. }
  67. #endif // BUILDFLAG(USE_XKBCOMMON)
  68. } // namespace exo