1 // Copyright (c) 2013 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 #ifndef ASH_KEYBOARD_UI_KEYBOARD_UI_CONTROLLER_H_ 6 #define ASH_KEYBOARD_UI_KEYBOARD_UI_CONTROLLER_H_ 7 8 #include <memory> 9 #include <set> 10 #include <utility> 11 #include <vector> 12 13 #include "ash/keyboard/ui/container_behavior.h" 14 #include "ash/keyboard/ui/display_util.h" 15 #include "ash/keyboard/ui/keyboard_event_handler.h" 16 #include "ash/keyboard/ui/keyboard_export.h" 17 #include "ash/keyboard/ui/keyboard_layout_delegate.h" 18 #include "ash/keyboard/ui/keyboard_ui_model.h" 19 #include "ash/keyboard/ui/keyboard_ukm_recorder.h" 20 #include "ash/keyboard/ui/notification_manager.h" 21 #include "ash/keyboard/ui/queued_container_type.h" 22 #include "ash/keyboard/ui/queued_display_change.h" 23 #include "ash/public/cpp/keyboard/keyboard_config.h" 24 #include "ash/public/cpp/keyboard/keyboard_types.h" 25 #include "base/macros.h" 26 #include "base/observer_list.h" 27 #include "base/scoped_observer.h" 28 #include "base/time/time.h" 29 #include "ui/aura/window_observer.h" 30 #include "ui/base/ime/input_method.h" 31 #include "ui/base/ime/input_method_keyboard_controller.h" 32 #include "ui/base/ime/input_method_observer.h" 33 #include "ui/base/ime/text_input_type.h" 34 #include "ui/events/event.h" 35 #include "ui/events/gestures/gesture_types.h" 36 #include "ui/gfx/geometry/rect.h" 37 #include "ui/gfx/geometry/vector2d.h" 38 39 namespace aura { 40 class Window; 41 } 42 namespace ash { 43 class KeyboardControllerObserver; 44 } 45 namespace ui { 46 class TextInputClient; 47 } // namespace ui 48 49 namespace keyboard { 50 51 class CallbackAnimationObserver; 52 class KeyboardUI; 53 class KeyboardUIFactory; 54 55 // Provides control of the virtual keyboard, including enabling/disabling the 56 // keyboard and controlling its visibility. 57 // TODO(shend): Move non-UI related logic to KeyboardControllerImpl. 58 class KEYBOARD_EXPORT KeyboardUIController 59 : public ui::InputMethodObserver, 60 public aura::WindowObserver, 61 public ContainerBehavior::Delegate { 62 public: 63 KeyboardUIController(); 64 ~KeyboardUIController() override; 65 66 // Initialize the virtual keyboard controller with two delegates: 67 // - ui_factory: Responsible for keyboard window loading. 68 // - layout_delegate: Responsible for moving keyboard window across displays. 69 void Initialize(std::unique_ptr<KeyboardUIFactory> ui_factory, 70 KeyboardLayoutDelegate* layout_delegate); 71 72 // Resets all the flags and disables the virtual keyboard. 73 void Shutdown(); 74 75 // Retrieves the active keyboard controller. Guaranteed to not be null while 76 // there is an ash::Shell. 77 // TODO(stevenjb/shuchen/shend): Remove all access from src/chrome. 78 // https://crbug.com/843332. 79 // TODO(shend): Make this not a singleton. 80 static KeyboardUIController* Get(); 81 82 // Returns true if there is a valid KeyboardUIController instance (e.g. while 83 // there is an ash::Shell). 84 static bool HasInstance(); 85 86 // Returns the keyboard window, or null if the keyboard window has not been 87 // created yet. 88 aura::Window* GetKeyboardWindow() const; 89 90 // Returns the gesture consumer for the keyboard, or null if the keyboard 91 // window has not been created yet. 92 ui::GestureConsumer* GetGestureConsumer() const; 93 94 // Returns the root window that this keyboard controller is attached to, or 95 // null if the keyboard has not been attached to any root window. 96 aura::Window* GetRootWindow() const; 97 98 // Move the keyboard window to a different parent container. |parent| must not 99 // be null. 100 void MoveToParentContainer(aura::Window* parent); 101 102 // Sets the bounds of the keyboard window, relative to the root window. 103 void SetKeyboardWindowBounds(const gfx::Rect& new_bounds_in_root); 104 105 // Reloads the content of the keyboard. No-op if the keyboard content is not 106 // loaded yet. 107 void Reload(); 108 109 // Rebuilds the keyboard by disabling and enabling it again. 110 // TODO(https://crbug.com/845780): Can this be replaced with |Reload|? 111 void RebuildKeyboardIfEnabled(); 112 113 // Management of the observer list. 114 void AddObserver(ash::KeyboardControllerObserver* observer); 115 bool HasObserver(ash::KeyboardControllerObserver* observer) const; 116 void RemoveObserver(ash::KeyboardControllerObserver* observer); 117 118 // Updates |keyboard_config_| with |config|. Returns |false| if there is no 119 // change, otherwise returns true and notifies observers if this is enabled. 120 bool UpdateKeyboardConfig(const KeyboardConfig& config); keyboard_config()121 const KeyboardConfig& keyboard_config() { return keyboard_config_; } 122 123 // Sets and clears |keyboard_enable_flags_| entries. 124 void SetEnableFlag(KeyboardEnableFlag flag); 125 void ClearEnableFlag(KeyboardEnableFlag flag); 126 bool IsEnableFlagSet(KeyboardEnableFlag flag) const; keyboard_enable_flags()127 const std::set<KeyboardEnableFlag>& keyboard_enable_flags() const { 128 return keyboard_enable_flags_; 129 } 130 131 // Returns true if keyboard overscroll is enabled. 132 bool IsKeyboardOverscrollEnabled() const; 133 134 // Hide the keyboard because the user has chosen to specifically hide the 135 // keyboard, such as pressing the dismiss button. 136 // TODO(https://crbug.com/845780): Rename this to 137 // HideKeyboardExplicitlyByUser. 138 // TODO(https://crbug.com/845780): Audit and switch callers to 139 // HideKeyboardImplicitlyByUser where appropriate. 140 void HideKeyboardByUser(); 141 142 // Hide the keyboard as a secondary effect of a user action, such as tapping 143 // the shelf. The keyboard should not hide if it's locked. 144 void HideKeyboardImplicitlyByUser(); 145 146 // Hide the keyboard due to some internally generated change to change the 147 // state of the keyboard. For example, moving from the docked keyboard to the 148 // floating keyboard. 149 void HideKeyboardTemporarilyForTransition(); 150 151 // Hide the keyboard as an effect of a system action, such as opening the 152 // settings page from the keyboard. There should be no reason the keyboard 153 // should remain open. 154 void HideKeyboardExplicitlyBySystem(); 155 156 // Hide the keyboard as a secondary effect of a system action, such as losing 157 // focus of a text element. If focus is returned to any text element, it is 158 // desirable to re-show the keyboard in this case. 159 void HideKeyboardImplicitlyBySystem(); 160 161 // Force the keyboard to show up if not showing and lock the keyboard if 162 // |lock| is true. 163 void ShowKeyboard(bool lock); 164 165 // Force the keyboard to show up in the specific display if not showing and 166 // lock the keyboard 167 void ShowKeyboardInDisplay(const display::Display& display); 168 169 // Returns the bounds in root window for the visible portion of the keyboard. 170 // An empty rectangle will get returned when the keyboard is hidden. visual_bounds_in_root()171 const gfx::Rect& visual_bounds_in_root() const { 172 return visual_bounds_in_root_; 173 } 174 175 // Returns the bounds in screen for the visible portion of the keyboard. An 176 // empty rectangle will get returned when the keyboard is hidden. 177 gfx::Rect GetVisualBoundsInScreen() const; 178 179 // Returns the current bounds that affect the workspace layout. If the 180 // keyboard is not shown or if the keyboard mode should not affect the usable 181 // region of the screen, an empty rectangle will be returned. Bounds are 182 // relative to the screen. 183 gfx::Rect GetWorkspaceOccludedBoundsInScreen() const; 184 185 // Returns the current bounds that affect the window layout of the various 186 // lock screens. Bounds are relative to the root window. 187 gfx::Rect GetKeyboardLockScreenOffsetBounds() const; 188 189 // Set the area on the keyboard window that occlude whatever is behind it. 190 void SetOccludedBounds(const gfx::Rect& bounds_in_window); 191 192 // Set the areas on the keyboard window where events should be handled. 193 // Does not do anything if there is no keyboard window. Bounds are relative to 194 // the keyboard window. 195 void SetHitTestBounds(const std::vector<gfx::Rect>& bounds_in_window); 196 197 // Sets the area of the keyboard window that should not move off screen. Any 198 // area outside of this can be moved off the user's screen. Note the bounds 199 // here are relative to the window's origin. 200 bool SetAreaToRemainOnScreen(const gfx::Rect& bounds_in_window); 201 202 // Sets the bounds of the keyboard window in screen coordinates. 203 bool SetKeyboardWindowBoundsInScreen(const gfx::Rect& bounds_in_screen); 204 GetActiveContainerType()205 ContainerType GetActiveContainerType() const { 206 return container_behavior_->GetType(); 207 } 208 209 // Adjusts |requested_bounds| according to the current container behavior. 210 // (e.g. prevent the keyboard from moving off screen). 211 gfx::Rect AdjustSetBoundsRequest( 212 const gfx::Rect& display_bounds, 213 const gfx::Rect& requested_bounds_in_screen) const; 214 215 // Returns true if overscroll is currently allowed by the active keyboard 216 // container behavior. 217 bool IsOverscrollAllowed() const; 218 219 // Whether the keyboard has been enabled, i.e. EnableKeyboard() has been 220 // called. IsEnabled()221 bool IsEnabled() const { return ui_ != nullptr; } 222 223 // Handle mouse and touch events on the keyboard. The effects of this method 224 // will not stop propagation to the keyboard extension. 225 bool HandlePointerEvent(const ui::LocatedEvent& event); 226 bool HandleGestureEvent(const ui::GestureEvent& event); 227 228 // Sets the active container type. If the keyboard is currently shown, this 229 // will trigger a hide animation and a subsequent show animation. Otherwise 230 // the ContainerBehavior change is synchronous. 231 void SetContainerType(ContainerType type, 232 const gfx::Rect& target_bounds_in_root, 233 base::OnceCallback<void(bool)> callback); 234 235 // Sets floating keyboard draggable rect. 236 void SetDraggableArea(const gfx::Rect& rect); 237 238 bool IsKeyboardVisible(); 239 240 void KeyboardContentsLoaded(); 241 parent_container()242 aura::Window* parent_container() { return parent_container_; } 243 input_method_keyboard_controller()244 ui::InputMethodKeyboardController* input_method_keyboard_controller() { 245 return input_method_keyboard_controller_.get(); 246 } 247 keyboard_locked()248 bool keyboard_locked() const { return keyboard_locked_; } set_keyboard_locked(bool lock)249 void set_keyboard_locked(bool lock) { keyboard_locked_ = lock; } 250 set_container_behavior_for_test(std::unique_ptr<ContainerBehavior> container_behavior)251 void set_container_behavior_for_test( 252 std::unique_ptr<ContainerBehavior> container_behavior) { 253 container_behavior_ = std::move(container_behavior); 254 } GetStateForTest()255 KeyboardUIState GetStateForTest() const { return model_.state(); } 256 ui::InputMethod* GetInputMethodForTest(); 257 void EnsureCaretInWorkAreaForTest(const gfx::Rect& occluded_bounds_in_screen); 258 259 private: 260 // For access to Observer methods for simulation. 261 friend class KeyboardUIControllerTest; 262 263 // Different ways to hide the keyboard. 264 enum HideReason { 265 // System initiated due to an active event, where the user does not want 266 // to maintain any association with the previous text entry session. 267 HIDE_REASON_SYSTEM_EXPLICIT, 268 269 // System initiated due to a passive event, such as clicking on a non-text 270 // control in a web page. Implicit hide events can be treated as passive 271 // and can possibly be a transient loss of focus. This will generally cause 272 // the keyboard to stay open for a brief moment and then hide, and possibly 273 // come back if focus is regained within a short amount of time (transient 274 // blur). 275 HIDE_REASON_SYSTEM_IMPLICIT, 276 277 // Keyboard is hidden temporarily for transitional reasons. Examples include 278 // moving the keyboard to a different display (which closes it and re-opens 279 // it on the new screen) or changing the container type (e.g. full-width to 280 // floating) 281 HIDE_REASON_SYSTEM_TEMPORARY, 282 283 // User explicitly hiding the keyboard via the close button. Also hides 284 // locked keyboards. 285 HIDE_REASON_USER_EXPLICIT, 286 287 // Keyboard is hidden as an indirect consequence of some user action. 288 // Examples include opening the window overview mode, or tapping on the 289 // shelf status area. Does not hide locked keyboards. 290 HIDE_REASON_USER_IMPLICIT, 291 }; 292 293 // ContainerBehavior::Delegate overrides 294 bool IsKeyboardLocked() const override; 295 gfx::Rect GetBoundsInScreen() const override; 296 void MoveKeyboardWindow(const gfx::Rect& new_bounds) override; 297 void MoveKeyboardWindowToDisplay(const display::Display& display, 298 const gfx::Rect& new_bounds) override; 299 void TransferGestureEventToShelf(const ui::GestureEvent& e) override; 300 301 // aura::WindowObserver overrides 302 void OnWindowAddedToRootWindow(aura::Window* window) override; 303 void OnWindowBoundsChanged(aura::Window* window, 304 const gfx::Rect& old_bounds, 305 const gfx::Rect& new_bounds, 306 ui::PropertyChangeReason reason) override; 307 308 // InputMethodObserver overrides OnBlur()309 void OnBlur() override {} OnCaretBoundsChanged(const ui::TextInputClient * client)310 void OnCaretBoundsChanged(const ui::TextInputClient* client) override {} OnFocus()311 void OnFocus() override {} 312 void OnInputMethodDestroyed(const ui::InputMethod* input_method) override; 313 void OnTextInputStateChanged(const ui::TextInputClient* client) override; 314 void OnShowVirtualKeyboardIfEnabled() override; 315 316 // Enables the virtual keyboard. 317 // Immediately starts pre-loading the keyboard window in the background. 318 // Does nothing if the keyboard is already enabled. 319 void EnableKeyboard(); 320 321 // Disables the virtual keyboard. Resets the keyboard to its initial disabled 322 // state and destroys the keyboard window. 323 // Does nothing if the keyboard is already disabled. 324 void DisableKeyboard(); 325 326 // Returns true if the keyboard should be enabled, i.e. the current result 327 // of Set/ClearEnableFlag should cause the keyboard to be enabled. 328 bool IsKeyboardEnableRequested() const; 329 330 // Enables or disables the keyboard based on |IsKeyboardEnableRequested|, 331 // as requested by |flag|. 332 void UpdateKeyboardAsRequestedBy(KeyboardEnableFlag flag); 333 334 // Attach the keyboard window as a child of the given parent window. 335 // Can only be called when the keyboard is not activated. |parent| must not 336 // have any children. 337 void ActivateKeyboardInContainer(aura::Window* parent); 338 339 // Detach the keyboard window from its parent container window. 340 // Can only be called when the keyboard is activated. Explicitly hides the 341 // keyboard if it is currently visible. 342 void DeactivateKeyboard(); 343 344 // Loads the keyboard window in the background, but does not display 345 // the keyboard. 346 void LoadKeyboardWindowInBackground(); 347 348 // Show virtual keyboard immediately with animation. 349 void ShowKeyboardInternal(aura::Window* target_container); 350 void PopulateKeyboardContent(aura::Window* target_container); 351 352 // Returns true if keyboard is scheduled to hide. 353 bool WillHideKeyboard() const; 354 355 // Immediately starts hiding animation of virtual keyboard and notifies 356 // observers bounds change. This method forcibly sets keyboard_locked_ 357 // false while closing the keyboard. 358 void HideKeyboard(HideReason reason); 359 360 // Called when the hide animation finished. 361 void HideAnimationFinished(); 362 // Called when the show animation finished. 363 void ShowAnimationFinished(); 364 365 // Notifies keyboard config change to the observers. 366 // Only called from |UpdateKeyboardConfig| in keyboard_util. 367 void NotifyKeyboardConfigChanged(); 368 369 // Notifies observers that the visual or occluded bounds of the keyboard 370 // window are changing. 371 void NotifyKeyboardBoundsChanging(const gfx::Rect& new_bounds_in_root); 372 373 // Called when the keyboard window has loaded. Shows the keyboard if 374 // |show_on_keyboard_window_load_| is true. 375 void NotifyKeyboardWindowLoaded(); 376 377 // Validates the state transition. Called from ChangeState. 378 void CheckStateTransition(KeyboardUIState prev, KeyboardUIState next); 379 380 // Changes the current state and validates the transition. 381 void ChangeState(KeyboardUIState state); 382 383 // Reports error histogram in case lingering in an intermediate state. 384 void ReportLingeringState(); 385 386 // Shows the keyboard if the last time the keyboard was hidden was a small 387 // time ago. 388 void ShowKeyboardIfWithinTransientBlurThreshold(); 389 390 void SetContainerBehaviorInternal(ContainerType type); 391 392 // Records that keyboard was shown on the currently focused UKM source. 393 void RecordUkmKeyboardShown(); 394 395 // Gets the currently focused text input client. 396 ui::TextInputClient* GetTextInputClient(); 397 398 // Ensures that the current IME is observed if it is changed. 399 void UpdateInputMethodObserver(); 400 401 // Ensures caret in current work area (not occluded by virtual keyboard 402 // window). 403 void EnsureCaretInWorkArea(const gfx::Rect& occluded_bounds_in_screen); 404 405 // Marks that the keyboard load has started. This is used to measure the time 406 // it takes to fully load the keyboard. This should be called before 407 // MarkKeyboardLoadFinished. 408 void MarkKeyboardLoadStarted(); 409 410 // Marks that the keyboard load has ended. This finishes measuring that the 411 // keyboard is loaded. 412 void MarkKeyboardLoadFinished(); 413 414 // Called when the enable flags change. Notifies observers of the change. 415 void EnableFlagsChanged(); 416 417 std::unique_ptr<KeyboardUIFactory> ui_factory_; 418 std::unique_ptr<KeyboardUI> ui_; 419 std::unique_ptr<ui::InputMethodKeyboardController> 420 input_method_keyboard_controller_; 421 KeyboardLayoutDelegate* layout_delegate_ = nullptr; 422 ScopedObserver<ui::InputMethod, ui::InputMethodObserver> ime_observer_{this}; 423 424 // Container window that the keyboard window is a child of. 425 aura::Window* parent_container_ = nullptr; 426 427 // CallbackAnimationObserver should be destroyed before |ui_| because it uses 428 // |ui_|'s animator. 429 std::unique_ptr<CallbackAnimationObserver> animation_observer_; 430 431 // Current active visual behavior for the keyboard container. 432 std::unique_ptr<ContainerBehavior> container_behavior_; 433 434 std::unique_ptr<QueuedContainerType> queued_container_type_; 435 std::unique_ptr<QueuedDisplayChange> queued_display_change_; 436 437 // If true, show the keyboard window when it loads. 438 bool show_on_keyboard_window_load_ = false; 439 440 // If true, the keyboard is always visible even if no window has input focus. 441 // TODO(https://crbug.com/964191): Move this to the UI model. 442 bool keyboard_locked_ = false; 443 KeyboardEventHandler event_handler_; 444 445 base::ObserverList<ash::KeyboardControllerObserver>::Unchecked observer_list_; 446 447 KeyboardUIModel model_; 448 449 // The bounds for the visible portion of the keyboard, relative to the root 450 // window. If the keyboard window is visible, this should be the same size as 451 // the keyboard window. If not, this should be empty. 452 gfx::Rect visual_bounds_in_root_; 453 454 // Keyboard configuration associated with the controller. 455 KeyboardConfig keyboard_config_; 456 457 // Set of active enabled request flags. Used to determine whether the keyboard 458 // should be enabled. 459 std::set<KeyboardEnableFlag> keyboard_enable_flags_; 460 461 NotificationManager notification_manager_; 462 463 base::Time time_of_last_blur_ = base::Time::UnixEpoch(); 464 465 DisplayUtil display_util_; 466 467 bool keyboard_load_time_logged_ = false; 468 base::Time keyboard_load_time_start_; 469 470 base::WeakPtrFactory<KeyboardUIController> 471 weak_factory_report_lingering_state_{this}; 472 base::WeakPtrFactory<KeyboardUIController> weak_factory_will_hide_{this}; 473 474 DISALLOW_COPY_AND_ASSIGN(KeyboardUIController); 475 }; 476 477 } // namespace keyboard 478 479 #endif // ASH_KEYBOARD_UI_KEYBOARD_UI_CONTROLLER_H_ 480