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