zcr_keyboard_configuration.cc 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. // Copyright 2018 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/wayland/zcr_keyboard_configuration.h"
  5. #include <keyboard-configuration-unstable-v1-server-protocol.h>
  6. #include <linux/input.h>
  7. #include <wayland-server-core.h>
  8. #include <wayland-server-protocol-core.h>
  9. #include "ash/ime/ime_controller_impl.h"
  10. #include "ash/shell.h"
  11. #include "base/feature_list.h"
  12. #include "components/exo/keyboard.h"
  13. #include "components/exo/keyboard_device_configuration_delegate.h"
  14. #include "components/exo/keyboard_observer.h"
  15. #include "components/exo/wayland/server_util.h"
  16. #include "ui/events/devices/device_data_manager.h"
  17. #include "ui/events/devices/input_device_event_observer.h"
  18. #include "ui/events/ozone/evdev/event_device_util.h"
  19. #include "ui/ozone/public/input_controller.h"
  20. #include "ui/ozone/public/ozone_platform.h"
  21. namespace exo {
  22. namespace wayland {
  23. namespace {
  24. ////////////////////////////////////////////////////////////////////////////////
  25. // keyboard_device_configuration interface:
  26. class WaylandKeyboardDeviceConfigurationDelegate
  27. : public KeyboardDeviceConfigurationDelegate,
  28. public KeyboardObserver,
  29. public ash::ImeControllerImpl::Observer,
  30. public ui::InputDeviceEventObserver {
  31. public:
  32. WaylandKeyboardDeviceConfigurationDelegate(wl_resource* resource,
  33. Keyboard* keyboard)
  34. : resource_(resource), keyboard_(keyboard) {
  35. keyboard_->SetDeviceConfigurationDelegate(this);
  36. keyboard_->AddObserver(this);
  37. ash::ImeControllerImpl* ime_controller =
  38. ash::Shell::Get()->ime_controller();
  39. ime_controller->AddObserver(this);
  40. ui::DeviceDataManager::GetInstance()->AddObserver(this);
  41. ProcessKeyBitsUpdate();
  42. OnKeyboardLayoutNameChanged(ime_controller->keyboard_layout_name());
  43. }
  44. WaylandKeyboardDeviceConfigurationDelegate(
  45. const WaylandKeyboardDeviceConfigurationDelegate&) = delete;
  46. WaylandKeyboardDeviceConfigurationDelegate& operator=(
  47. const WaylandKeyboardDeviceConfigurationDelegate&) = delete;
  48. ~WaylandKeyboardDeviceConfigurationDelegate() override {
  49. ui::DeviceDataManager::GetInstance()->RemoveObserver(this);
  50. ash::Shell::Get()->ime_controller()->RemoveObserver(this);
  51. if (keyboard_) {
  52. keyboard_->SetDeviceConfigurationDelegate(nullptr);
  53. keyboard_->RemoveObserver(this);
  54. }
  55. }
  56. // Overridden from KeyboardObserver:
  57. void OnKeyboardDestroying(Keyboard* keyboard) override {
  58. keyboard_ = nullptr;
  59. }
  60. // Overridden from KeyboardDeviceConfigurationDelegate:
  61. void OnKeyboardTypeChanged(bool is_physical) override {
  62. zcr_keyboard_device_configuration_v1_send_type_change(
  63. resource_,
  64. is_physical
  65. ? ZCR_KEYBOARD_DEVICE_CONFIGURATION_V1_KEYBOARD_TYPE_PHYSICAL
  66. : ZCR_KEYBOARD_DEVICE_CONFIGURATION_V1_KEYBOARD_TYPE_VIRTUAL);
  67. wl_client_flush(client());
  68. }
  69. // Overridden from ImeControllerImpl::Observer:
  70. void OnCapsLockChanged(bool enabled) override {}
  71. void OnKeyboardLayoutNameChanged(const std::string& layout_name) override {
  72. zcr_keyboard_device_configuration_v1_send_layout_change(
  73. resource_, layout_name.c_str());
  74. wl_client_flush(client());
  75. }
  76. // Overridden from ui::InputDeviceEventObserver:
  77. void OnInputDeviceConfigurationChanged(uint8_t input_device_types) override {
  78. if (!(input_device_types & ui::InputDeviceEventObserver::kKeyboard)) {
  79. return;
  80. }
  81. ProcessKeyBitsUpdate();
  82. }
  83. private:
  84. // Notify key bits update.
  85. void ProcessKeyBitsUpdate() {
  86. if (wl_resource_get_version(resource_) <
  87. ZCR_KEYBOARD_DEVICE_CONFIGURATION_V1_SUPPORTED_KEY_BITS_SINCE_VERSION) {
  88. return;
  89. }
  90. // Preparing wayland keybits.
  91. wl_array wl_key_bits;
  92. wl_array_init(&wl_key_bits);
  93. size_t key_bits_len = EVDEV_BITS_TO_INT64(KEY_CNT) * sizeof(uint64_t);
  94. uint64_t* wl_key_bits_ptr =
  95. static_cast<uint64_t*>(wl_array_add(&wl_key_bits, key_bits_len));
  96. if (!wl_key_bits_ptr) {
  97. wl_array_release(&wl_key_bits);
  98. return;
  99. }
  100. memset(wl_key_bits_ptr, 0, key_bits_len);
  101. ui::InputController* input_controller =
  102. ui::OzonePlatform::GetInstance()->GetInputController();
  103. // Combine supported key bits from all keyboard into single key bits.
  104. for (const ui::InputDevice& device :
  105. ui::DeviceDataManager::GetInstance()->GetKeyboardDevices()) {
  106. const std::vector<uint64_t>& key_bits =
  107. input_controller->GetKeyboardKeyBits(device.id);
  108. for (size_t i = 0; i < key_bits.size(); i++) {
  109. wl_key_bits_ptr[i] |= key_bits[i];
  110. }
  111. }
  112. zcr_keyboard_device_configuration_v1_send_supported_key_bits(resource_,
  113. &wl_key_bits);
  114. wl_array_release(&wl_key_bits);
  115. wl_client_flush(client());
  116. }
  117. wl_client* client() const { return wl_resource_get_client(resource_); }
  118. wl_resource* resource_;
  119. Keyboard* keyboard_;
  120. };
  121. void keyboard_device_configuration_destroy(wl_client* client,
  122. wl_resource* resource) {
  123. wl_resource_destroy(resource);
  124. }
  125. const struct zcr_keyboard_device_configuration_v1_interface
  126. keyboard_device_configuration_implementation = {
  127. keyboard_device_configuration_destroy};
  128. ////////////////////////////////////////////////////////////////////////////////
  129. // keyboard_configuration interface:
  130. void keyboard_configuration_get_keyboard_device_configuration(
  131. wl_client* client,
  132. wl_resource* resource,
  133. uint32_t id,
  134. wl_resource* keyboard_resource) {
  135. Keyboard* keyboard = GetUserDataAs<Keyboard>(keyboard_resource);
  136. if (keyboard->HasDeviceConfigurationDelegate()) {
  137. wl_resource_post_error(
  138. resource,
  139. ZCR_KEYBOARD_CONFIGURATION_V1_ERROR_DEVICE_CONFIGURATION_EXISTS,
  140. "keyboard has already been associated with a device configuration "
  141. "object");
  142. return;
  143. }
  144. wl_resource* keyboard_device_configuration_resource = wl_resource_create(
  145. client, &zcr_keyboard_device_configuration_v1_interface,
  146. wl_resource_get_version(resource), id);
  147. SetImplementation(
  148. keyboard_device_configuration_resource,
  149. &keyboard_device_configuration_implementation,
  150. std::make_unique<WaylandKeyboardDeviceConfigurationDelegate>(
  151. keyboard_device_configuration_resource, keyboard));
  152. }
  153. const struct zcr_keyboard_configuration_v1_interface
  154. keyboard_configuration_implementation = {
  155. keyboard_configuration_get_keyboard_device_configuration};
  156. } // namespace
  157. void bind_keyboard_configuration(wl_client* client,
  158. void* data,
  159. uint32_t version,
  160. uint32_t id) {
  161. wl_resource* resource = wl_resource_create(
  162. client, &zcr_keyboard_configuration_v1_interface,
  163. std::min<uint32_t>(version,
  164. zcr_keyboard_configuration_v1_interface.version),
  165. id);
  166. wl_resource_set_implementation(
  167. resource, &keyboard_configuration_implementation, data, nullptr);
  168. }
  169. } // namespace wayland
  170. } // namespace exo