blob: 32391eb100cad6929c99f25f746514d2765f50d1 [file] [log] [blame]
bsheeaae09a2014-09-22 23:16:521// 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
5#include "ash/virtual_keyboard_controller.h"
6
rsadam9172bc8a2014-10-29 23:37:387#include <vector>
8
yhanada7e20c9b2016-11-25 00:03:199#include "ash/common/keyboard/keyboard_ui.h"
msw5c804fb22016-06-25 00:09:1510#include "ash/common/system/tray/system_tray_notifier.h"
skye2bde2172016-07-01 18:27:0211#include "ash/common/wm/maximize_mode/maximize_mode_controller.h"
sky88bd4be62016-06-09 17:34:4112#include "ash/common/wm_shell.h"
yhanada7e20c9b2016-11-25 00:03:1913#include "ash/common/wm_window.h"
14#include "ash/root_window_controller.h"
bsheeaae09a2014-09-22 23:16:5215#include "ash/shell.h"
rsadam9172bc8a2014-10-29 23:37:3816#include "base/command_line.h"
17#include "base/strings/string_util.h"
yhanada7e20c9b2016-11-25 00:03:1918#include "ui/display/display.h"
19#include "ui/display/screen.h"
dnicoara78a734702014-11-04 19:54:3820#include "ui/events/devices/input_device.h"
kylechare223f032016-06-03 15:02:5321#include "ui/events/devices/input_device_manager.h"
dnicoara78a734702014-11-04 19:54:3822#include "ui/events/devices/touchscreen_device.h"
yhanada7e20c9b2016-11-25 00:03:1923#include "ui/keyboard/keyboard_controller.h"
rsadam9172bc8a2014-10-29 23:37:3824#include "ui/keyboard/keyboard_switches.h"
bsheeaae09a2014-09-22 23:16:5225#include "ui/keyboard/keyboard_util.h"
26
27namespace ash {
rsadam47e23d22014-12-15 18:11:3728namespace {
29
30// Checks whether smart deployment is enabled.
31bool IsSmartVirtualKeyboardEnabled() {
rsadamf478ba762015-01-16 01:08:1132 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
33 keyboard::switches::kEnableVirtualKeyboard)) {
34 return false;
35 }
rsadam318530d2015-06-05 15:57:0336 return keyboard::IsSmartDeployEnabled();
rsadam47e23d22014-12-15 18:11:3737}
38
yhanada7e20c9b2016-11-25 00:03:1939void MoveKeyboardToDisplayInternal(const int64_t display_id) {
40 // Remove the keyboard from curent root window controller
41 WmShell::Get()->keyboard_ui()->Hide();
42 RootWindowController::ForWindow(
43 keyboard::KeyboardController::GetInstance()->GetContainerWindow())
44 ->DeactivateKeyboard(keyboard::KeyboardController::GetInstance());
45
46 for (RootWindowController* controller :
47 Shell::GetInstance()->GetAllRootWindowControllers()) {
48 if (display::Screen::GetScreen()
49 ->GetDisplayNearestWindow(controller->GetRootWindow())
50 .id() == display_id) {
51 controller->ActivateKeyboard(keyboard::KeyboardController::GetInstance());
52 break;
53 }
54 }
55}
56
57void MoveKeyboardToFirstTouchableDisplay() {
58 // Move the keyboard to the first display with touch capability.
59 for (const auto& display : display::Screen::GetScreen()->GetAllDisplays()) {
60 if (display.touch_support() ==
61 display::Display::TouchSupport::TOUCH_SUPPORT_AVAILABLE) {
62 MoveKeyboardToDisplayInternal(display.id());
63 return;
64 }
65 }
66}
67
rsadam47e23d22014-12-15 18:11:3768} // namespace
bsheeaae09a2014-09-22 23:16:5269
rsadam9172bc8a2014-10-29 23:37:3870VirtualKeyboardController::VirtualKeyboardController()
71 : has_external_keyboard_(false),
72 has_internal_keyboard_(false),
rsadamc727b6a2014-10-31 18:59:3373 has_touchscreen_(false),
74 ignore_external_keyboard_(false) {
sky88bd4be62016-06-09 17:34:4175 WmShell::Get()->AddShellObserver(this);
kylechare223f032016-06-03 15:02:5376 ui::InputDeviceManager::GetInstance()->AddObserver(this);
rsadam9172bc8a2014-10-29 23:37:3877 UpdateDevices();
bsheeaae09a2014-09-22 23:16:5278}
79
80VirtualKeyboardController::~VirtualKeyboardController() {
sky88bd4be62016-06-09 17:34:4181 WmShell::Get()->RemoveShellObserver(this);
kylechare223f032016-06-03 15:02:5382 ui::InputDeviceManager::GetInstance()->RemoveObserver(this);
bsheeaae09a2014-09-22 23:16:5283}
84
85void VirtualKeyboardController::OnMaximizeModeStarted() {
rsadamd4f6a0b2015-03-02 23:50:0886 if (!IsSmartVirtualKeyboardEnabled()) {
rsadam9172bc8a2014-10-29 23:37:3887 SetKeyboardEnabled(true);
rsadamd4f6a0b2015-03-02 23:50:0888 } else {
89 UpdateKeyboardEnabled();
90 }
bsheeaae09a2014-09-22 23:16:5291}
92
93void VirtualKeyboardController::OnMaximizeModeEnded() {
rsadamd4f6a0b2015-03-02 23:50:0894 if (!IsSmartVirtualKeyboardEnabled()) {
rsadam9172bc8a2014-10-29 23:37:3895 SetKeyboardEnabled(false);
rsadamd4f6a0b2015-03-02 23:50:0896 } else {
97 UpdateKeyboardEnabled();
98 }
rsadam9172bc8a2014-10-29 23:37:3899}
100
rsadamc727b6a2014-10-31 18:59:33101void VirtualKeyboardController::OnTouchscreenDeviceConfigurationChanged() {
102 UpdateDevices();
103}
104
105void VirtualKeyboardController::OnKeyboardDeviceConfigurationChanged() {
106 UpdateDevices();
107}
108
109void VirtualKeyboardController::ToggleIgnoreExternalKeyboard() {
110 ignore_external_keyboard_ = !ignore_external_keyboard_;
111 UpdateKeyboardEnabled();
112}
113
yhanada7e20c9b2016-11-25 00:03:19114void VirtualKeyboardController::MoveKeyboardToDisplay(int64_t display_id) {
115 DCHECK(keyboard::KeyboardController::GetInstance() != nullptr);
116 DCHECK(display_id != display::kInvalidDisplayId);
117
118 aura::Window* container =
119 keyboard::KeyboardController::GetInstance()->GetContainerWindow();
120 DCHECK(container != nullptr);
121 const display::Screen* screen = display::Screen::GetScreen();
122 const display::Display current_display =
123 screen->GetDisplayNearestWindow(container);
124
125 if (display_id != current_display.id())
126 MoveKeyboardToDisplayInternal(display_id);
127}
128
129void VirtualKeyboardController::MoveKeyboardToTouchableDisplay() {
130 DCHECK(keyboard::KeyboardController::GetInstance() != nullptr);
131
132 aura::Window* container =
133 keyboard::KeyboardController::GetInstance()->GetContainerWindow();
134 DCHECK(container != nullptr);
135
136 const display::Screen* screen = display::Screen::GetScreen();
137 const display::Display current_display =
138 screen->GetDisplayNearestWindow(container);
139
140 if (WmShell::Get()->GetFocusedWindow() != nullptr) {
141 // Move the virtual keyboard to the focused display if that display has
142 // touch capability or keyboard is locked
143 const display::Display focused_display =
144 WmShell::Get()->GetFocusedWindow()->GetDisplayNearestWindow();
145 if (current_display.id() != focused_display.id() &&
146 focused_display.id() != display::kInvalidDisplayId &&
147 focused_display.touch_support() ==
148 display::Display::TouchSupport::TOUCH_SUPPORT_AVAILABLE) {
149 MoveKeyboardToDisplayInternal(focused_display.id());
150 return;
151 }
152 }
153
154 if (current_display.touch_support() !=
155 display::Display::TouchSupport::TOUCH_SUPPORT_AVAILABLE) {
156 // The keyboard is currently on the display without touch capability.
157 MoveKeyboardToFirstTouchableDisplay();
158 }
159}
160
rsadam9172bc8a2014-10-29 23:37:38161void VirtualKeyboardController::UpdateDevices() {
kylechare223f032016-06-03 15:02:53162 ui::InputDeviceManager* device_data_manager =
163 ui::InputDeviceManager::GetInstance();
rsadam9172bc8a2014-10-29 23:37:38164
165 // Checks for touchscreens.
kylechare223f032016-06-03 15:02:53166 has_touchscreen_ = device_data_manager->GetTouchscreenDevices().size() > 0;
rsadam9172bc8a2014-10-29 23:37:38167
168 // Checks for keyboards.
169 has_external_keyboard_ = false;
170 has_internal_keyboard_ = false;
kylechar65cb32e42016-05-31 22:19:48171 for (const ui::InputDevice& device :
kylechare223f032016-06-03 15:02:53172 device_data_manager->GetKeyboardDevices()) {
rsadamf9719972014-11-05 02:57:59173 if (has_internal_keyboard_ && has_external_keyboard_)
174 break;
175 ui::InputDeviceType type = device.type;
rsadam9172bc8a2014-10-29 23:37:38176 if (type == ui::InputDeviceType::INPUT_DEVICE_INTERNAL)
177 has_internal_keyboard_ = true;
178 if (type == ui::InputDeviceType::INPUT_DEVICE_EXTERNAL)
179 has_external_keyboard_ = true;
180 }
181 // Update keyboard state.
182 UpdateKeyboardEnabled();
183}
184
rsadam9172bc8a2014-10-29 23:37:38185void VirtualKeyboardController::UpdateKeyboardEnabled() {
rsadam47e23d22014-12-15 18:11:37186 if (!IsSmartVirtualKeyboardEnabled()) {
skyc68696c2016-07-01 21:06:02187 SetKeyboardEnabled(WmShell::Get()
rsadam9172bc8a2014-10-29 23:37:38188 ->maximize_mode_controller()
189 ->IsMaximizeModeWindowManagerEnabled());
190 return;
191 }
skyc68696c2016-07-01 21:06:02192 bool ignore_internal_keyboard = WmShell::Get()
rsadamd4f6a0b2015-03-02 23:50:08193 ->maximize_mode_controller()
194 ->IsMaximizeModeWindowManagerEnabled();
195 bool is_internal_keyboard_active =
196 has_internal_keyboard_ && !ignore_internal_keyboard;
197 SetKeyboardEnabled(!is_internal_keyboard_active && has_touchscreen_ &&
rsadamc727b6a2014-10-31 18:59:33198 (!has_external_keyboard_ || ignore_external_keyboard_));
jamescookdcfe3d62016-06-21 18:58:42199 WmShell::Get()
rsadamc727b6a2014-10-31 18:59:33200 ->system_tray_notifier()
rsadamd4f6a0b2015-03-02 23:50:08201 ->NotifyVirtualKeyboardSuppressionChanged(!is_internal_keyboard_active &&
rsadamc727b6a2014-10-31 18:59:33202 has_touchscreen_ &&
203 has_external_keyboard_);
rsadam9172bc8a2014-10-29 23:37:38204}
205
rsadamc727b6a2014-10-31 18:59:33206void VirtualKeyboardController::SetKeyboardEnabled(bool enabled) {
rsadamf796de602015-08-24 16:09:05207 bool was_enabled = keyboard::IsKeyboardEnabled();
rsadamc727b6a2014-10-31 18:59:33208 keyboard::SetTouchKeyboardEnabled(enabled);
rsadamf796de602015-08-24 16:09:05209 bool is_enabled = keyboard::IsKeyboardEnabled();
210 if (is_enabled == was_enabled)
211 return;
212 if (is_enabled) {
rsadamc727b6a2014-10-31 18:59:33213 Shell::GetInstance()->CreateKeyboard();
214 } else {
rsadamf796de602015-08-24 16:09:05215 Shell::GetInstance()->DeactivateKeyboard();
rsadamc727b6a2014-10-31 18:59:33216 }
bsheeaae09a2014-09-22 23:16:52217}
218
219} // namespace ash