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
5 #include "ash/keyboard/keyboard_controller_impl.h"
6
7 #include <utility>
8
9 #include "ash/keyboard/ui/keyboard_ui_controller.h"
10 #include "ash/keyboard/ui/keyboard_ui_factory.h"
11 #include "ash/keyboard/virtual_keyboard_controller.h"
12 #include "ash/public/cpp/ash_constants.h"
13 #include "ash/public/cpp/ash_pref_names.h"
14 #include "ash/public/cpp/keyboard/keyboard_switches.h"
15 #include "ash/public/cpp/shell_window_ids.h"
16 #include "ash/root_window_controller.h"
17 #include "ash/session/session_controller_impl.h"
18 #include "ash/shelf/shelf.h"
19 #include "ash/shell.h"
20 #include "ash/shell_delegate.h"
21 #include "ash/wm/window_util.h"
22 #include "base/command_line.h"
23 #include "base/optional.h"
24 #include "components/pref_registry/pref_registry_syncable.h"
25 #include "components/prefs/pref_change_registrar.h"
26 #include "components/prefs/pref_service.h"
27 #include "ui/aura/env.h"
28 #include "ui/aura/window_delegate.h"
29 #include "ui/base/ui_base_features.h"
30 #include "ui/events/base_event_utils.h"
31 #include "ui/events/gestures/gesture_recognizer.h"
32 #include "ui/gfx/geometry/rect.h"
33 #include "ui/wm/core/coordinate_conversion.h"
34
35 using keyboard::KeyboardConfig;
36 using keyboard::KeyboardEnableFlag;
37
38 namespace ash {
39
40 namespace {
41
42 // Boolean controlling whether auto-complete for virtual keyboard is
43 // enabled.
44 const char kAutoCompleteEnabledKey[] = "auto_complete_enabled";
45 // Boolean controlling whether auto-correct for virtual keyboard is
46 // enabled.
47 const char kAutoCorrectEnabledKey[] = "auto_correct_enabled";
48 // Boolean controlling whether handwriting for virtual keyboard is
49 // enabled.
50 const char kHandwritingEnabledKey[] = "handwriting_enabled";
51 // Boolean controlling whether spell check for virtual keyboard is
52 // enabled.
53 const char kSpellCheckEnabledKey[] = "spell_check_enabled";
54 // Boolean controlling whether voice input for virtual keyboard is
55 // enabled.
56 const char kVoiceInputEnabledKey[] = "voice_input_enabled";
57
GetFirstTouchDisplay()58 base::Optional<display::Display> GetFirstTouchDisplay() {
59 for (const auto& display : display::Screen::GetScreen()->GetAllDisplays()) {
60 if (display.touch_support() == display::Display::TouchSupport::AVAILABLE)
61 return display;
62 }
63 return base::nullopt;
64 }
65
GetVirtualKeyboardFeatureValue(PrefService * prefs,const std::string & feature_path)66 bool GetVirtualKeyboardFeatureValue(PrefService* prefs,
67 const std::string& feature_path) {
68 DCHECK(prefs);
69 const base::DictionaryValue* features =
70 prefs->GetDictionary(prefs::kAccessibilityVirtualKeyboardFeatures);
71
72 if (!features)
73 return false;
74
75 bool feature_value = false;
76 return features->GetBoolean(feature_path, &feature_value) && feature_value;
77 }
78
79 } // namespace
80
KeyboardControllerImpl(SessionControllerImpl * session_controller)81 KeyboardControllerImpl::KeyboardControllerImpl(
82 SessionControllerImpl* session_controller)
83 : session_controller_(session_controller),
84 keyboard_ui_controller_(
85 std::make_unique<keyboard::KeyboardUIController>()) {
86 if (session_controller_) // May be null in tests.
87 session_controller_->AddObserver(this);
88 keyboard_ui_controller_->AddObserver(this);
89 }
90
~KeyboardControllerImpl()91 KeyboardControllerImpl::~KeyboardControllerImpl() {
92 keyboard_ui_controller_->RemoveObserver(this);
93 if (session_controller_) // May be null in tests.
94 session_controller_->RemoveObserver(this);
95 }
96
97 // static
RegisterProfilePrefs(PrefRegistrySimple * registry)98 void KeyboardControllerImpl::RegisterProfilePrefs(
99 PrefRegistrySimple* registry) {
100 registry->RegisterBooleanPref(
101 ash::prefs::kXkbAutoRepeatEnabled, ash::kDefaultKeyAutoRepeatEnabled,
102 user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
103 registry->RegisterIntegerPref(
104 ash::prefs::kXkbAutoRepeatDelay,
105 ash::kDefaultKeyAutoRepeatDelay.InMilliseconds(),
106 user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
107 registry->RegisterIntegerPref(
108 ash::prefs::kXkbAutoRepeatInterval,
109 ash::kDefaultKeyAutoRepeatInterval.InMilliseconds(),
110 user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF);
111 registry->RegisterDictionaryPref(
112 prefs::kAccessibilityVirtualKeyboardFeatures);
113 }
114
CreateVirtualKeyboard(std::unique_ptr<keyboard::KeyboardUIFactory> keyboard_ui_factory)115 void KeyboardControllerImpl::CreateVirtualKeyboard(
116 std::unique_ptr<keyboard::KeyboardUIFactory> keyboard_ui_factory) {
117 DCHECK(keyboard_ui_factory);
118 virtual_keyboard_controller_ = std::make_unique<VirtualKeyboardController>();
119 keyboard_ui_controller_->Initialize(std::move(keyboard_ui_factory), this);
120
121 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
122 keyboard::switches::kEnableVirtualKeyboard)) {
123 keyboard_ui_controller_->SetEnableFlag(
124 KeyboardEnableFlag::kCommandLineEnabled);
125 }
126 }
127
DestroyVirtualKeyboard()128 void KeyboardControllerImpl::DestroyVirtualKeyboard() {
129 virtual_keyboard_controller_.reset();
130 keyboard_ui_controller_->Shutdown();
131 }
132
SendOnKeyboardVisibleBoundsChanged(const gfx::Rect & screen_bounds)133 void KeyboardControllerImpl::SendOnKeyboardVisibleBoundsChanged(
134 const gfx::Rect& screen_bounds) {
135 DVLOG(1) << "OnKeyboardVisibleBoundsChanged: " << screen_bounds.ToString();
136 for (auto& observer : observers_)
137 observer.OnKeyboardVisibleBoundsChanged(screen_bounds);
138 }
139
SendOnKeyboardUIDestroyed()140 void KeyboardControllerImpl::SendOnKeyboardUIDestroyed() {
141 for (auto& observer : observers_)
142 observer.OnKeyboardUIDestroyed();
143 }
144
145 // ash::KeyboardController
146
GetKeyboardConfig()147 keyboard::KeyboardConfig KeyboardControllerImpl::GetKeyboardConfig() {
148 if (!keyboard_config_from_pref_enabled_)
149 return keyboard_ui_controller_->keyboard_config();
150
151 PrefService* prefs = pref_change_registrar_->prefs();
152 KeyboardConfig config;
153 config.auto_complete =
154 GetVirtualKeyboardFeatureValue(prefs, kAutoCompleteEnabledKey);
155 config.auto_correct =
156 GetVirtualKeyboardFeatureValue(prefs, kAutoCorrectEnabledKey);
157 config.handwriting =
158 GetVirtualKeyboardFeatureValue(prefs, kHandwritingEnabledKey);
159 config.spell_check =
160 GetVirtualKeyboardFeatureValue(prefs, kSpellCheckEnabledKey);
161 config.voice_input =
162 GetVirtualKeyboardFeatureValue(prefs, kVoiceInputEnabledKey);
163 return config;
164 }
165
SetKeyboardConfig(const KeyboardConfig & keyboard_config)166 void KeyboardControllerImpl::SetKeyboardConfig(
167 const KeyboardConfig& keyboard_config) {
168 keyboard_ui_controller_->UpdateKeyboardConfig(keyboard_config);
169 }
170
IsKeyboardEnabled()171 bool KeyboardControllerImpl::IsKeyboardEnabled() {
172 return keyboard_ui_controller_->IsEnabled();
173 }
174
SetEnableFlag(KeyboardEnableFlag flag)175 void KeyboardControllerImpl::SetEnableFlag(KeyboardEnableFlag flag) {
176 keyboard_ui_controller_->SetEnableFlag(flag);
177 }
178
ClearEnableFlag(KeyboardEnableFlag flag)179 void KeyboardControllerImpl::ClearEnableFlag(KeyboardEnableFlag flag) {
180 keyboard_ui_controller_->ClearEnableFlag(flag);
181 }
182
183 const std::set<keyboard::KeyboardEnableFlag>&
GetEnableFlags()184 KeyboardControllerImpl::GetEnableFlags() {
185 return keyboard_ui_controller_->keyboard_enable_flags();
186 }
187
ReloadKeyboardIfNeeded()188 void KeyboardControllerImpl::ReloadKeyboardIfNeeded() {
189 keyboard_ui_controller_->Reload();
190 }
191
RebuildKeyboardIfEnabled()192 void KeyboardControllerImpl::RebuildKeyboardIfEnabled() {
193 // Test IsKeyboardEnableRequested in case of an unlikely edge case where this
194 // is called while after the enable state changed to disabled (in which case
195 // we do not want to override the requested state).
196 keyboard_ui_controller_->RebuildKeyboardIfEnabled();
197 }
198
IsKeyboardVisible()199 bool KeyboardControllerImpl::IsKeyboardVisible() {
200 return keyboard_ui_controller_->IsKeyboardVisible();
201 }
202
ShowKeyboard()203 void KeyboardControllerImpl::ShowKeyboard() {
204 if (keyboard_ui_controller_->IsEnabled())
205 keyboard_ui_controller_->ShowKeyboard(false /* lock */);
206 }
207
HideKeyboard(HideReason reason)208 void KeyboardControllerImpl::HideKeyboard(HideReason reason) {
209 if (!keyboard_ui_controller_->IsEnabled())
210 return;
211 switch (reason) {
212 case HideReason::kUser:
213 keyboard_ui_controller_->HideKeyboardByUser();
214 break;
215 case HideReason::kSystem:
216 keyboard_ui_controller_->HideKeyboardExplicitlyBySystem();
217 break;
218 }
219 }
220
SetContainerType(keyboard::ContainerType container_type,const gfx::Rect & target_bounds,SetContainerTypeCallback callback)221 void KeyboardControllerImpl::SetContainerType(
222 keyboard::ContainerType container_type,
223 const gfx::Rect& target_bounds,
224 SetContainerTypeCallback callback) {
225 keyboard_ui_controller_->SetContainerType(container_type, target_bounds,
226 std::move(callback));
227 }
228
SetKeyboardLocked(bool locked)229 void KeyboardControllerImpl::SetKeyboardLocked(bool locked) {
230 keyboard_ui_controller_->set_keyboard_locked(locked);
231 }
232
SetOccludedBounds(const std::vector<gfx::Rect> & bounds)233 void KeyboardControllerImpl::SetOccludedBounds(
234 const std::vector<gfx::Rect>& bounds) {
235 // TODO(https://crbug.com/826617): Support occluded bounds with multiple
236 // rectangles.
237 keyboard_ui_controller_->SetOccludedBounds(bounds.empty() ? gfx::Rect()
238 : bounds[0]);
239 }
240
SetHitTestBounds(const std::vector<gfx::Rect> & bounds)241 void KeyboardControllerImpl::SetHitTestBounds(
242 const std::vector<gfx::Rect>& bounds) {
243 keyboard_ui_controller_->SetHitTestBounds(bounds);
244 }
245
SetAreaToRemainOnScreen(const gfx::Rect & bounds)246 bool KeyboardControllerImpl::SetAreaToRemainOnScreen(const gfx::Rect& bounds) {
247 return keyboard_ui_controller_->SetAreaToRemainOnScreen(bounds);
248 }
249
SetDraggableArea(const gfx::Rect & bounds)250 void KeyboardControllerImpl::SetDraggableArea(const gfx::Rect& bounds) {
251 keyboard_ui_controller_->SetDraggableArea(bounds);
252 }
253
SetWindowBoundsInScreen(const gfx::Rect & bounds_in_screen)254 bool KeyboardControllerImpl::SetWindowBoundsInScreen(
255 const gfx::Rect& bounds_in_screen) {
256 return keyboard_ui_controller_->SetKeyboardWindowBoundsInScreen(
257 bounds_in_screen);
258 }
259
SetKeyboardConfigFromPref(bool enabled)260 void KeyboardControllerImpl::SetKeyboardConfigFromPref(bool enabled) {
261 keyboard_config_from_pref_enabled_ = enabled;
262 SendKeyboardConfigUpdate();
263 }
264
ShouldOverscroll()265 bool KeyboardControllerImpl::ShouldOverscroll() {
266 return keyboard_ui_controller_->IsKeyboardOverscrollEnabled();
267 }
268
AddObserver(KeyboardControllerObserver * observer)269 void KeyboardControllerImpl::AddObserver(KeyboardControllerObserver* observer) {
270 observers_.AddObserver(observer);
271 }
272
RemoveObserver(KeyboardControllerObserver * observer)273 void KeyboardControllerImpl::RemoveObserver(
274 KeyboardControllerObserver* observer) {
275 observers_.RemoveObserver(observer);
276 }
277
GetKeyRepeatSettings()278 KeyRepeatSettings KeyboardControllerImpl::GetKeyRepeatSettings() {
279 PrefService* prefs = pref_change_registrar_->prefs();
280 bool enabled = prefs->GetBoolean(ash::prefs::kXkbAutoRepeatEnabled);
281 int delay_in_ms = prefs->GetInteger(ash::prefs::kXkbAutoRepeatDelay);
282 int interval_in_ms = prefs->GetInteger(ash::prefs::kXkbAutoRepeatInterval);
283 return KeyRepeatSettings{enabled,
284 base::TimeDelta::FromMilliseconds(delay_in_ms),
285 base::TimeDelta::FromMilliseconds(interval_in_ms)};
286 }
287
288 // SessionObserver
OnSessionStateChanged(session_manager::SessionState state)289 void KeyboardControllerImpl::OnSessionStateChanged(
290 session_manager::SessionState state) {
291 if (!keyboard_ui_controller_->IsEnabled())
292 return;
293
294 switch (state) {
295 case session_manager::SessionState::LOGGED_IN_NOT_ACTIVE:
296 case session_manager::SessionState::ACTIVE:
297 // Reload the keyboard on user profile change to refresh keyboard
298 // extensions with the new profile and ensure the extensions call the
299 // proper IME. |LOGGED_IN_NOT_ACTIVE| is needed so that the virtual
300 // keyboard works on supervised user creation, http://crbug.com/712873.
301 // |ACTIVE| is also needed for guest user workflow.
302 RebuildKeyboardIfEnabled();
303 break;
304 default:
305 break;
306 }
307 }
308
OnSigninScreenPrefServiceInitialized(PrefService * prefs)309 void KeyboardControllerImpl::OnSigninScreenPrefServiceInitialized(
310 PrefService* prefs) {
311 ObservePrefs(prefs);
312 }
313
OnActiveUserPrefServiceChanged(PrefService * prefs)314 void KeyboardControllerImpl::OnActiveUserPrefServiceChanged(
315 PrefService* prefs) {
316 ObservePrefs(prefs);
317 }
318
319 // Start listening to key repeat preferences from the given service.
320 // Also immediately update observers with the service's current preferences.
321 //
322 // We only need to observe the most recent PrefService. It will either be the
323 // active user's PrefService, or the signin screen's PrefService if nobody's
324 // logged in yet.
ObservePrefs(PrefService * prefs)325 void KeyboardControllerImpl::ObservePrefs(PrefService* prefs) {
326 pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
327 pref_change_registrar_->Init(prefs);
328
329 // Immediately tell all our observers to load this user's saved preferences.
330 SendKeyRepeatUpdate();
331 SendKeyboardConfigUpdate();
332
333 // Listen to prefs changes and forward them to all observers.
334 // |prefs| is assumed to outlive |pref_change_registrar_|, and therefore also
335 // its callbacks.
336 pref_change_registrar_->Add(
337 ash::prefs::kXkbAutoRepeatEnabled,
338 base::BindRepeating(&KeyboardControllerImpl::SendKeyRepeatUpdate,
339 base::Unretained(this)));
340 pref_change_registrar_->Add(
341 ash::prefs::kXkbAutoRepeatInterval,
342 base::BindRepeating(&KeyboardControllerImpl::SendKeyRepeatUpdate,
343 base::Unretained(this)));
344 pref_change_registrar_->Add(
345 ash::prefs::kXkbAutoRepeatDelay,
346 base::BindRepeating(&KeyboardControllerImpl::SendKeyRepeatUpdate,
347 base::Unretained(this)));
348 pref_change_registrar_->Add(
349 ash::prefs::kAccessibilityVirtualKeyboardFeatures,
350 base::BindRepeating(&KeyboardControllerImpl::SendKeyboardConfigUpdate,
351 base::Unretained(this)));
352 }
353
SendKeyRepeatUpdate()354 void KeyboardControllerImpl::SendKeyRepeatUpdate() {
355 OnKeyRepeatSettingsChanged(GetKeyRepeatSettings());
356 }
357
SendKeyboardConfigUpdate()358 void KeyboardControllerImpl::SendKeyboardConfigUpdate() {
359 keyboard_ui_controller_->UpdateKeyboardConfig(GetKeyboardConfig());
360 }
361
OnRootWindowClosing(aura::Window * root_window)362 void KeyboardControllerImpl::OnRootWindowClosing(aura::Window* root_window) {
363 if (keyboard_ui_controller_->GetRootWindow() == root_window) {
364 aura::Window* new_parent = GetContainerForDefaultDisplay();
365 DCHECK_NE(root_window, new_parent);
366 keyboard_ui_controller_->MoveToParentContainer(new_parent);
367 }
368 }
369
GetContainerForDisplay(const display::Display & display)370 aura::Window* KeyboardControllerImpl::GetContainerForDisplay(
371 const display::Display& display) {
372 DCHECK(display.is_valid());
373
374 RootWindowController* controller =
375 Shell::Get()->GetRootWindowControllerWithDisplayId(display.id());
376 aura::Window* container =
377 controller->GetContainer(kShellWindowId_VirtualKeyboardContainer);
378 DCHECK(container);
379 return container;
380 }
381
GetContainerForDefaultDisplay()382 aura::Window* KeyboardControllerImpl::GetContainerForDefaultDisplay() {
383 const display::Screen* screen = display::Screen::GetScreen();
384 const base::Optional<display::Display> first_touch_display =
385 GetFirstTouchDisplay();
386 const bool has_touch_display = first_touch_display.has_value();
387
388 if (window_util::GetFocusedWindow()) {
389 // Return the focused display if that display has touch capability or no
390 // other display has touch capability.
391 const display::Display focused_display =
392 screen->GetDisplayNearestWindow(window_util::GetFocusedWindow());
393 if (focused_display.is_valid() &&
394 (focused_display.touch_support() ==
395 display::Display::TouchSupport::AVAILABLE ||
396 !has_touch_display)) {
397 return GetContainerForDisplay(focused_display);
398 }
399 }
400
401 // Return the first touch display, or the primary display if there are none.
402 return GetContainerForDisplay(
403 has_touch_display ? *first_touch_display : screen->GetPrimaryDisplay());
404 }
405
TransferGestureEventToShelf(const ui::GestureEvent & e)406 void KeyboardControllerImpl::TransferGestureEventToShelf(
407 const ui::GestureEvent& e) {
408 ash::Shelf* shelf =
409 ash::Shelf::ForWindow(keyboard_ui_controller_->GetKeyboardWindow());
410 if (shelf) {
411 shelf->ProcessGestureEvent(e);
412 aura::Env::GetInstance()->gesture_recognizer()->TransferEventsTo(
413 keyboard_ui_controller_->GetGestureConsumer(), shelf->GetWindow(),
414 ui::TransferTouchesBehavior::kCancel);
415 HideKeyboard(HideReason::kUser);
416 }
417 }
418
OnKeyboardConfigChanged(const keyboard::KeyboardConfig & config)419 void KeyboardControllerImpl::OnKeyboardConfigChanged(
420 const keyboard::KeyboardConfig& config) {
421 for (auto& observer : observers_)
422 observer.OnKeyboardConfigChanged(config);
423 }
424
OnKeyRepeatSettingsChanged(const KeyRepeatSettings & settings)425 void KeyboardControllerImpl::OnKeyRepeatSettingsChanged(
426 const KeyRepeatSettings& settings) {
427 for (auto& observer : observers_)
428 observer.OnKeyRepeatSettingsChanged(settings);
429 }
430
OnKeyboardVisibilityChanged(bool is_visible)431 void KeyboardControllerImpl::OnKeyboardVisibilityChanged(bool is_visible) {
432 for (auto& observer : observers_)
433 observer.OnKeyboardVisibilityChanged(is_visible);
434 }
435
OnKeyboardVisibleBoundsChanged(const gfx::Rect & screen_bounds)436 void KeyboardControllerImpl::OnKeyboardVisibleBoundsChanged(
437 const gfx::Rect& screen_bounds) {
438 SendOnKeyboardVisibleBoundsChanged(screen_bounds);
439 }
440
OnKeyboardOccludedBoundsChanged(const gfx::Rect & screen_bounds)441 void KeyboardControllerImpl::OnKeyboardOccludedBoundsChanged(
442 const gfx::Rect& screen_bounds) {
443 DVLOG(1) << "OnKeyboardOccludedBoundsChanged: " << screen_bounds.ToString();
444 for (auto& observer : observers_)
445 observer.OnKeyboardOccludedBoundsChanged(screen_bounds);
446 }
447
OnKeyboardEnableFlagsChanged(const std::set<keyboard::KeyboardEnableFlag> & flags)448 void KeyboardControllerImpl::OnKeyboardEnableFlagsChanged(
449 const std::set<keyboard::KeyboardEnableFlag>& flags) {
450 for (auto& observer : observers_)
451 observer.OnKeyboardEnableFlagsChanged(flags);
452 }
453
OnKeyboardEnabledChanged(bool is_enabled)454 void KeyboardControllerImpl::OnKeyboardEnabledChanged(bool is_enabled) {
455 for (auto& observer : observers_)
456 observer.OnKeyboardEnabledChanged(is_enabled);
457 }
458
459 } // namespace ash
460