virtual_keyboard_controller.cc 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // Copyright 2014 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 "ash/keyboard/virtual_keyboard_controller.h"
  5. #include <vector>
  6. #include "ash/constants/ash_features.h"
  7. #include "ash/ime/ime_controller_impl.h"
  8. #include "ash/keyboard/keyboard_controller_impl.h"
  9. #include "ash/keyboard/ui/keyboard_ui_controller.h"
  10. #include "ash/keyboard/ui/keyboard_util.h"
  11. #include "ash/public/cpp/shell_window_ids.h"
  12. #include "ash/session/session_controller_impl.h"
  13. #include "ash/shell.h"
  14. #include "ash/system/tray/system_tray_notifier.h"
  15. #include "ash/wm/tablet_mode/tablet_mode_controller.h"
  16. #include "base/bind.h"
  17. #include "base/callback_helpers.h"
  18. #include "base/feature_list.h"
  19. #include "base/strings/string_util.h"
  20. #include "ui/base/emoji/emoji_panel_helper.h"
  21. #include "ui/display/display.h"
  22. #include "ui/display/screen.h"
  23. #include "ui/events/devices/device_data_manager.h"
  24. #include "ui/events/devices/input_device.h"
  25. namespace ash {
  26. namespace {
  27. void ResetVirtualKeyboard() {
  28. keyboard::SetKeyboardEnabledFromShelf(false);
  29. // This function can get called asynchronously after the shell has been
  30. // destroyed, so check for an instance.
  31. if (Shell::HasInstance()) {
  32. // Reset the keyset after disabling the virtual keyboard to prevent the IME
  33. // extension from accidentally loading the default keyset while it's
  34. // shutting down. See https://crbug.com/875456.
  35. Shell::Get()->ime_controller()->OverrideKeyboardKeyset(
  36. input_method::ImeKeyset::kNone);
  37. }
  38. }
  39. } // namespace
  40. VirtualKeyboardController::VirtualKeyboardController()
  41. : has_internal_keyboard_(false),
  42. ignore_external_keyboard_(false),
  43. ignore_internal_keyboard_(false) {
  44. Shell::Get()->tablet_mode_controller()->AddObserver(this);
  45. Shell::Get()->session_controller()->AddObserver(this);
  46. ui::DeviceDataManager::GetInstance()->AddObserver(this);
  47. UpdateDevices();
  48. // Set callback to show the emoji panel
  49. ui::SetTabletModeShowEmojiKeyboardCallback(base::BindRepeating(
  50. &VirtualKeyboardController::ForceShowKeyboardWithKeyset,
  51. base::Unretained(this), input_method::ImeKeyset::kEmoji));
  52. keyboard::KeyboardUIController::Get()->AddObserver(this);
  53. bluetooth_devices_observer_ =
  54. std::make_unique<BluetoothDevicesObserver>(base::BindRepeating(
  55. &VirtualKeyboardController::OnBluetoothAdapterOrDeviceChanged,
  56. base::Unretained(this)));
  57. }
  58. VirtualKeyboardController::~VirtualKeyboardController() {
  59. keyboard::KeyboardUIController::Get()->RemoveObserver(this);
  60. if (Shell::Get()->tablet_mode_controller())
  61. Shell::Get()->tablet_mode_controller()->RemoveObserver(this);
  62. if (Shell::Get()->session_controller())
  63. Shell::Get()->session_controller()->RemoveObserver(this);
  64. ui::DeviceDataManager::GetInstance()->RemoveObserver(this);
  65. // Reset the emoji panel callback
  66. ui::SetShowEmojiKeyboardCallback(base::DoNothing());
  67. }
  68. void VirtualKeyboardController::ForceShowKeyboardWithKeyset(
  69. input_method::ImeKeyset keyset) {
  70. Shell::Get()->ime_controller()->OverrideKeyboardKeyset(
  71. keyset, base::BindOnce(&VirtualKeyboardController::ForceShowKeyboard,
  72. base::Unretained(this)));
  73. }
  74. void VirtualKeyboardController::OnTabletModeEventsBlockingChanged() {
  75. UpdateKeyboardEnabled();
  76. }
  77. void VirtualKeyboardController::OnInputDeviceConfigurationChanged(
  78. uint8_t input_device_types) {
  79. if (input_device_types & (ui::InputDeviceEventObserver::kKeyboard |
  80. ui::InputDeviceEventObserver::kTouchscreen)) {
  81. UpdateDevices();
  82. }
  83. }
  84. void VirtualKeyboardController::ToggleIgnoreExternalKeyboard() {
  85. ignore_external_keyboard_ = !ignore_external_keyboard_;
  86. UpdateKeyboardEnabled();
  87. }
  88. void VirtualKeyboardController::UpdateDevices() {
  89. ui::DeviceDataManager* device_data_manager =
  90. ui::DeviceDataManager::GetInstance();
  91. touchscreens_ = device_data_manager->GetTouchscreenDevices();
  92. // Checks for keyboards.
  93. external_keyboards_.clear();
  94. has_internal_keyboard_ = false;
  95. for (const ui::InputDevice& device :
  96. device_data_manager->GetKeyboardDevices()) {
  97. ui::InputDeviceType type = device.type;
  98. if (type == ui::InputDeviceType::INPUT_DEVICE_INTERNAL)
  99. has_internal_keyboard_ = true;
  100. if ((type == ui::InputDeviceType::INPUT_DEVICE_USB ||
  101. (type == ui::InputDeviceType::INPUT_DEVICE_BLUETOOTH &&
  102. bluetooth_devices_observer_->IsConnectedBluetoothDevice(device))) &&
  103. !device.suspected_imposter) {
  104. external_keyboards_.push_back(device);
  105. }
  106. }
  107. // Update keyboard state.
  108. UpdateKeyboardEnabled();
  109. }
  110. void VirtualKeyboardController::UpdateKeyboardEnabled() {
  111. bool ignore_internal_keyboard_ = Shell::Get()
  112. ->tablet_mode_controller()
  113. ->AreInternalInputDeviceEventsBlocked();
  114. bool is_internal_keyboard_active =
  115. has_internal_keyboard_ && !ignore_internal_keyboard_;
  116. keyboard::SetTouchKeyboardEnabled(
  117. !is_internal_keyboard_active && !touchscreens_.empty() &&
  118. (external_keyboards_.empty() || ignore_external_keyboard_));
  119. Shell::Get()->system_tray_notifier()->NotifyVirtualKeyboardSuppressionChanged(
  120. !is_internal_keyboard_active && !touchscreens_.empty() &&
  121. !external_keyboards_.empty());
  122. }
  123. void VirtualKeyboardController::ForceShowKeyboard() {
  124. // If the virtual keyboard is enabled, show the keyboard directly.
  125. auto* keyboard_controller = keyboard::KeyboardUIController::Get();
  126. if (keyboard_controller->IsEnabled()) {
  127. keyboard_controller->ShowKeyboard(false /* locked */);
  128. return;
  129. }
  130. // Otherwise, temporarily enable the virtual keyboard until it is dismissed.
  131. DCHECK(!keyboard::GetKeyboardEnabledFromShelf());
  132. keyboard::SetKeyboardEnabledFromShelf(true);
  133. keyboard_controller->ShowKeyboard(false);
  134. }
  135. void VirtualKeyboardController::OnKeyboardEnabledChanged(bool is_enabled) {
  136. if (!is_enabled) {
  137. // TODO(shend/shuchen): Consider moving this logic to ImeController.
  138. // https://crbug.com/896284.
  139. Shell::Get()->ime_controller()->OverrideKeyboardKeyset(
  140. input_method::ImeKeyset::kNone);
  141. }
  142. }
  143. void VirtualKeyboardController::OnKeyboardHidden(bool is_temporary_hide) {
  144. // The keyboard may temporarily hide (e.g. to change container behaviors).
  145. // The keyset should not be reset in this case.
  146. if (is_temporary_hide)
  147. return;
  148. // Post a task to reset the virtual keyboard to its original state.
  149. base::ThreadTaskRunnerHandle::Get()->PostTask(
  150. FROM_HERE, base::BindOnce(ResetVirtualKeyboard));
  151. }
  152. void VirtualKeyboardController::OnActiveUserSessionChanged(
  153. const AccountId& account_id) {
  154. // Force on-screen keyboard to reset.
  155. Shell::Get()->keyboard_controller()->RebuildKeyboardIfEnabled();
  156. }
  157. void VirtualKeyboardController::OnBluetoothAdapterOrDeviceChanged(
  158. device::BluetoothDevice* device) {
  159. // We only care about keyboard type bluetooth device change.
  160. if (!device ||
  161. device->GetDeviceType() == device::BluetoothDeviceType::KEYBOARD ||
  162. device->GetDeviceType() ==
  163. device::BluetoothDeviceType::KEYBOARD_MOUSE_COMBO) {
  164. UpdateDevices();
  165. }
  166. }
  167. bool VirtualKeyboardController::HasInternalKeyboard() const {
  168. return has_internal_keyboard_;
  169. }
  170. const std::vector<ui::InputDevice>&
  171. VirtualKeyboardController::GetExternalKeyboards() const {
  172. return external_keyboards_;
  173. }
  174. const std::vector<ui::TouchscreenDevice>&
  175. VirtualKeyboardController::GetTouchscreens() const {
  176. return touchscreens_;
  177. }
  178. bool VirtualKeyboardController::IsInternalKeyboardIgnored() const {
  179. return ignore_internal_keyboard_;
  180. }
  181. bool VirtualKeyboardController::IsExternalKeyboardIgnored() const {
  182. return ignore_external_keyboard_;
  183. }
  184. } // namespace ash