123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- // Copyright 2014 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ash/keyboard/virtual_keyboard_controller.h"
- #include <vector>
- #include "ash/constants/ash_features.h"
- #include "ash/ime/ime_controller_impl.h"
- #include "ash/keyboard/keyboard_controller_impl.h"
- #include "ash/keyboard/ui/keyboard_ui_controller.h"
- #include "ash/keyboard/ui/keyboard_util.h"
- #include "ash/public/cpp/shell_window_ids.h"
- #include "ash/session/session_controller_impl.h"
- #include "ash/shell.h"
- #include "ash/system/tray/system_tray_notifier.h"
- #include "ash/wm/tablet_mode/tablet_mode_controller.h"
- #include "base/bind.h"
- #include "base/callback_helpers.h"
- #include "base/feature_list.h"
- #include "base/strings/string_util.h"
- #include "ui/base/emoji/emoji_panel_helper.h"
- #include "ui/display/display.h"
- #include "ui/display/screen.h"
- #include "ui/events/devices/device_data_manager.h"
- #include "ui/events/devices/input_device.h"
- namespace ash {
- namespace {
- void ResetVirtualKeyboard() {
- keyboard::SetKeyboardEnabledFromShelf(false);
- // This function can get called asynchronously after the shell has been
- // destroyed, so check for an instance.
- if (Shell::HasInstance()) {
- // Reset the keyset after disabling the virtual keyboard to prevent the IME
- // extension from accidentally loading the default keyset while it's
- // shutting down. See https://crbug.com/875456.
- Shell::Get()->ime_controller()->OverrideKeyboardKeyset(
- input_method::ImeKeyset::kNone);
- }
- }
- } // namespace
- VirtualKeyboardController::VirtualKeyboardController()
- : has_internal_keyboard_(false),
- ignore_external_keyboard_(false),
- ignore_internal_keyboard_(false) {
- Shell::Get()->tablet_mode_controller()->AddObserver(this);
- Shell::Get()->session_controller()->AddObserver(this);
- ui::DeviceDataManager::GetInstance()->AddObserver(this);
- UpdateDevices();
- // Set callback to show the emoji panel
- ui::SetTabletModeShowEmojiKeyboardCallback(base::BindRepeating(
- &VirtualKeyboardController::ForceShowKeyboardWithKeyset,
- base::Unretained(this), input_method::ImeKeyset::kEmoji));
- keyboard::KeyboardUIController::Get()->AddObserver(this);
- bluetooth_devices_observer_ =
- std::make_unique<BluetoothDevicesObserver>(base::BindRepeating(
- &VirtualKeyboardController::OnBluetoothAdapterOrDeviceChanged,
- base::Unretained(this)));
- }
- VirtualKeyboardController::~VirtualKeyboardController() {
- keyboard::KeyboardUIController::Get()->RemoveObserver(this);
- if (Shell::Get()->tablet_mode_controller())
- Shell::Get()->tablet_mode_controller()->RemoveObserver(this);
- if (Shell::Get()->session_controller())
- Shell::Get()->session_controller()->RemoveObserver(this);
- ui::DeviceDataManager::GetInstance()->RemoveObserver(this);
- // Reset the emoji panel callback
- ui::SetShowEmojiKeyboardCallback(base::DoNothing());
- }
- void VirtualKeyboardController::ForceShowKeyboardWithKeyset(
- input_method::ImeKeyset keyset) {
- Shell::Get()->ime_controller()->OverrideKeyboardKeyset(
- keyset, base::BindOnce(&VirtualKeyboardController::ForceShowKeyboard,
- base::Unretained(this)));
- }
- void VirtualKeyboardController::OnTabletModeEventsBlockingChanged() {
- UpdateKeyboardEnabled();
- }
- void VirtualKeyboardController::OnInputDeviceConfigurationChanged(
- uint8_t input_device_types) {
- if (input_device_types & (ui::InputDeviceEventObserver::kKeyboard |
- ui::InputDeviceEventObserver::kTouchscreen)) {
- UpdateDevices();
- }
- }
- void VirtualKeyboardController::ToggleIgnoreExternalKeyboard() {
- ignore_external_keyboard_ = !ignore_external_keyboard_;
- UpdateKeyboardEnabled();
- }
- void VirtualKeyboardController::UpdateDevices() {
- ui::DeviceDataManager* device_data_manager =
- ui::DeviceDataManager::GetInstance();
- touchscreens_ = device_data_manager->GetTouchscreenDevices();
- // Checks for keyboards.
- external_keyboards_.clear();
- has_internal_keyboard_ = false;
- for (const ui::InputDevice& device :
- device_data_manager->GetKeyboardDevices()) {
- ui::InputDeviceType type = device.type;
- if (type == ui::InputDeviceType::INPUT_DEVICE_INTERNAL)
- has_internal_keyboard_ = true;
- if ((type == ui::InputDeviceType::INPUT_DEVICE_USB ||
- (type == ui::InputDeviceType::INPUT_DEVICE_BLUETOOTH &&
- bluetooth_devices_observer_->IsConnectedBluetoothDevice(device))) &&
- !device.suspected_imposter) {
- external_keyboards_.push_back(device);
- }
- }
- // Update keyboard state.
- UpdateKeyboardEnabled();
- }
- void VirtualKeyboardController::UpdateKeyboardEnabled() {
- bool ignore_internal_keyboard_ = Shell::Get()
- ->tablet_mode_controller()
- ->AreInternalInputDeviceEventsBlocked();
- bool is_internal_keyboard_active =
- has_internal_keyboard_ && !ignore_internal_keyboard_;
- keyboard::SetTouchKeyboardEnabled(
- !is_internal_keyboard_active && !touchscreens_.empty() &&
- (external_keyboards_.empty() || ignore_external_keyboard_));
- Shell::Get()->system_tray_notifier()->NotifyVirtualKeyboardSuppressionChanged(
- !is_internal_keyboard_active && !touchscreens_.empty() &&
- !external_keyboards_.empty());
- }
- void VirtualKeyboardController::ForceShowKeyboard() {
- // If the virtual keyboard is enabled, show the keyboard directly.
- auto* keyboard_controller = keyboard::KeyboardUIController::Get();
- if (keyboard_controller->IsEnabled()) {
- keyboard_controller->ShowKeyboard(false /* locked */);
- return;
- }
- // Otherwise, temporarily enable the virtual keyboard until it is dismissed.
- DCHECK(!keyboard::GetKeyboardEnabledFromShelf());
- keyboard::SetKeyboardEnabledFromShelf(true);
- keyboard_controller->ShowKeyboard(false);
- }
- void VirtualKeyboardController::OnKeyboardEnabledChanged(bool is_enabled) {
- if (!is_enabled) {
- // TODO(shend/shuchen): Consider moving this logic to ImeController.
- // https://crbug.com/896284.
- Shell::Get()->ime_controller()->OverrideKeyboardKeyset(
- input_method::ImeKeyset::kNone);
- }
- }
- void VirtualKeyboardController::OnKeyboardHidden(bool is_temporary_hide) {
- // The keyboard may temporarily hide (e.g. to change container behaviors).
- // The keyset should not be reset in this case.
- if (is_temporary_hide)
- return;
- // Post a task to reset the virtual keyboard to its original state.
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(ResetVirtualKeyboard));
- }
- void VirtualKeyboardController::OnActiveUserSessionChanged(
- const AccountId& account_id) {
- // Force on-screen keyboard to reset.
- Shell::Get()->keyboard_controller()->RebuildKeyboardIfEnabled();
- }
- void VirtualKeyboardController::OnBluetoothAdapterOrDeviceChanged(
- device::BluetoothDevice* device) {
- // We only care about keyboard type bluetooth device change.
- if (!device ||
- device->GetDeviceType() == device::BluetoothDeviceType::KEYBOARD ||
- device->GetDeviceType() ==
- device::BluetoothDeviceType::KEYBOARD_MOUSE_COMBO) {
- UpdateDevices();
- }
- }
- bool VirtualKeyboardController::HasInternalKeyboard() const {
- return has_internal_keyboard_;
- }
- const std::vector<ui::InputDevice>&
- VirtualKeyboardController::GetExternalKeyboards() const {
- return external_keyboards_;
- }
- const std::vector<ui::TouchscreenDevice>&
- VirtualKeyboardController::GetTouchscreens() const {
- return touchscreens_;
- }
- bool VirtualKeyboardController::IsInternalKeyboardIgnored() const {
- return ignore_internal_keyboard_;
- }
- bool VirtualKeyboardController::IsExternalKeyboardIgnored() const {
- return ignore_external_keyboard_;
- }
- } // namespace ash
|