| // Copyright (c) 2013 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. |
| |
| #ifndef UI_KEYBOARD_KEYBOARD_CONTROLLER_H_ |
| #define UI_KEYBOARD_KEYBOARD_CONTROLLER_H_ |
| |
| #include <memory> |
| |
| #include "base/macros.h" |
| #include "base/observer_list.h" |
| #include "base/time/time.h" |
| #include "ui/aura/window_observer.h" |
| #include "ui/base/ime/input_method_observer.h" |
| #include "ui/base/ime/text_input_type.h" |
| #include "ui/events/event.h" |
| #include "ui/gfx/geometry/rect.h" |
| #include "ui/gfx/geometry/vector2d.h" |
| #include "ui/keyboard/container_behavior.h" |
| #include "ui/keyboard/container_type.h" |
| #include "ui/keyboard/keyboard_event_filter.h" |
| #include "ui/keyboard/keyboard_export.h" |
| #include "ui/keyboard/keyboard_layout_delegate.h" |
| #include "ui/keyboard/keyboard_util.h" |
| #include "ui/keyboard/notification_manager.h" |
| #include "ui/keyboard/queued_container_type.h" |
| |
| namespace aura { |
| class Window; |
| } |
| namespace ui { |
| class InputMethod; |
| class TextInputClient; |
| } |
| |
| namespace keyboard { |
| |
| class CallbackAnimationObserver; |
| class KeyboardControllerObserver; |
| class KeyboardUI; |
| |
| // Represents the current state of the keyboard managed by the controller. |
| // Don't change the numeric value of the members because they are used in UMA |
| // - VirtualKeyboard.ControllerStateTransition. |
| // - VirtualKeyboard.LingeringIntermediateState |
| enum class KeyboardControllerState { |
| UNKNOWN = 0, |
| // Keyboard has never been shown. |
| INITIAL = 1, |
| // Waiting for an extension to be loaded. Will move to HIDDEN if this is |
| // loading pre-emptively, otherwise will move to SHOWN. |
| LOADING_EXTENSION = 2, |
| // Keyboard is shown. |
| SHOWN = 4, |
| // Keyboard is still shown, but will move to HIDING in a short period, or if |
| // an input element gets focused again, will move to SHOWN. |
| WILL_HIDE = 5, |
| // Keyboard is hidden, but has shown at least once. |
| HIDDEN = 7, |
| COUNT, |
| }; |
| |
| // Provides control of the virtual keyboard, including providing a container |
| // and controlling visibility. |
| class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver, |
| public aura::WindowObserver { |
| public: |
| // Different ways to hide the keyboard. |
| enum HideReason { |
| // System initiated. |
| HIDE_REASON_AUTOMATIC, |
| // User initiated. |
| HIDE_REASON_MANUAL, |
| }; |
| |
| KeyboardController(std::unique_ptr<KeyboardUI> ui, |
| KeyboardLayoutDelegate* delegate); |
| ~KeyboardController() override; |
| |
| // Returns the container for the keyboard, which is owned by |
| // KeyboardController. Creates the container if it's not already created. |
| aura::Window* GetContainerWindow(); |
| |
| // Same as GetContainerWindow except that this function doesn't create the |
| // window. |
| aura::Window* GetContainerWindowWithoutCreationForTest(); |
| |
| // Whether the container window for the keyboard has been initialized. |
| bool keyboard_container_initialized() const { return container_ != nullptr; } |
| |
| // Reloads the content of the keyboard. No-op if the keyboard content is not |
| // loaded yet. |
| void Reload(); |
| |
| // Notifies the observer for contents bounds changed. |
| void NotifyContentsBoundsChanging(const gfx::Rect& new_bounds); |
| |
| // Management of the observer list. |
| void AddObserver(KeyboardControllerObserver* observer); |
| bool HasObserver(KeyboardControllerObserver* observer) const; |
| void RemoveObserver(KeyboardControllerObserver* observer); |
| |
| KeyboardUI* ui() { return ui_.get(); } |
| |
| void set_keyboard_locked(bool lock) { keyboard_locked_ = lock; } |
| |
| bool keyboard_locked() const { return keyboard_locked_; } |
| |
| // Immediately starts hiding animation of virtual keyboard and notifies |
| // observers bounds change. This method forcibly sets keyboard_locked_ |
| // false while closing the keyboard. |
| void HideKeyboard(HideReason reason); |
| |
| // Force the keyboard to show up if not showing and lock the keyboard if |
| // |lock| is true. |
| void ShowKeyboard(bool lock); |
| |
| // Loads the keyboard UI contents in the background, but does not display |
| // the keyboard. |
| void LoadKeyboardUiInBackground(); |
| |
| // Force the keyboard to show up in the specific display if not showing and |
| // lock the keyboard |
| void ShowKeyboardInDisplay(const int64_t display_id); |
| |
| // Sets the active keyboard controller. KeyboardController takes ownership of |
| // the instance. Calling ResetIntance with a new instance destroys the |
| // previous one. May be called with NULL to clear the instance. |
| static void ResetInstance(KeyboardController* controller); |
| |
| // Retrieve the active keyboard controller. |
| static KeyboardController* GetInstance(); |
| |
| // Returns true if keyboard is in SHOWN or SHOWING state. |
| bool keyboard_visible() const; |
| |
| // Returns true if keyboard window has been created. |
| bool IsKeyboardWindowCreated(); |
| |
| // Returns the current keyboard bounds. An empty rectangle will get returned |
| // when the keyboard is not shown. |
| const gfx::Rect& current_keyboard_bounds() const { |
| return current_keyboard_bounds_; |
| } |
| |
| // Returns the current bounds that affect the workspace layout. If the |
| // keyboard is not shown or if the keyboard mode should not affect the usable |
| // region of the screen, an empty rectangle will get returned. |
| const gfx::Rect GetWorkspaceObscuringBounds() const; |
| |
| // Returns the current bounds that affect the window layout of the various |
| // lock screens. |
| const gfx::Rect GetKeyboardLockScreenOffsetBounds() const; |
| |
| KeyboardControllerState GetStateForTest() const { return state_; } |
| |
| ContainerType GetActiveContainerType() const { |
| return container_behavior_->GetType(); |
| } |
| |
| const gfx::Rect AdjustSetBoundsRequest( |
| const gfx::Rect& display_bounds, |
| const gfx::Rect& requested_bounds) const; |
| |
| // Returns true if overscroll is currently allowed by the active keyboard |
| // container behavior. |
| bool IsOverscrollAllowed() const; |
| |
| // Handle mouse and touch events on the keyboard. The effects of this method |
| // will not stop propagation to the keyboard extension. |
| void HandlePointerEvent(const ui::LocatedEvent& event); |
| |
| // Moves an already loaded keyboard. |
| void MoveKeyboard(const gfx::Rect new_bounds); |
| |
| // Sets the active container type. If the keyboard is currently shown, this |
| // will trigger a hide animation and a subsequent show animation. Otherwise |
| // the ContainerBehavior change is synchronous. |
| void SetContainerType(const ContainerType type, |
| base::OnceCallback<void(bool)> callback); |
| |
| // Sets floating keyboard drggable rect. |
| bool SetDraggableArea(const gfx::Rect& rect); |
| |
| private: |
| // For access to Observer methods for simulation. |
| friend class KeyboardControllerTest; |
| |
| // For access to SetContainerBounds. |
| friend class KeyboardLayoutManager; |
| |
| // For access to NotifyKeyboardConfigChanged |
| friend bool keyboard::UpdateKeyboardConfig( |
| const keyboard::KeyboardConfig& config); |
| |
| // aura::WindowObserver overrides |
| void OnWindowHierarchyChanged(const HierarchyChangeParams& params) override; |
| void OnWindowAddedToRootWindow(aura::Window* window) override; |
| void OnWindowRemovingFromRootWindow(aura::Window* window, |
| aura::Window* new_root) override; |
| void OnWindowBoundsChanged(aura::Window* window, |
| const gfx::Rect& old_bounds, |
| const gfx::Rect& new_bounds, |
| ui::PropertyChangeReason reason) override; |
| |
| // InputMethodObserver overrides |
| void OnBlur() override {} |
| void OnCaretBoundsChanged(const ui::TextInputClient* client) override {} |
| void OnFocus() override {} |
| void OnInputMethodDestroyed(const ui::InputMethod* input_method) override {} |
| void OnTextInputStateChanged(const ui::TextInputClient* client) override; |
| void OnShowImeIfNeeded() override; |
| |
| // Sets the bounds of the container window. Shows the keyboard if contents |
| // is first loaded and show_on_content_update_ is true. Called by |
| // KeyboardLayoutManager. |
| void SetContainerBounds(const gfx::Rect& new_bounds, |
| const bool contents_loaded); |
| |
| // Show virtual keyboard immediately with animation. |
| void ShowKeyboardInternal(int64_t display_id); |
| void PopulateKeyboardContent(int64_t display_id, bool show_keyboard); |
| |
| // Returns true if keyboard is scheduled to hide. |
| bool WillHideKeyboard() const; |
| |
| // Called when the hide animation finishes. |
| void HideAnimationFinished(); |
| |
| void NotifyKeyboardBoundsChangingAndEnsureCaretInWorkArea(); |
| |
| // Called when the keyboard mode is set or the keyboard is moved to another |
| // display. |
| void AdjustKeyboardBounds(); |
| |
| // Notifies keyboard config change to the observers. |
| // Only called from |UpdateKeyboardConfig| in keyboard_util. |
| void NotifyKeyboardConfigChanged(); |
| |
| // Validates the state transition. Called from ChangeState. |
| void CheckStateTransition(KeyboardControllerState prev, |
| KeyboardControllerState next); |
| |
| // Changes the current state and validates the transition. |
| void ChangeState(KeyboardControllerState state); |
| |
| // Reports error histogram in case lingering in an intermediate state. |
| void ReportLingeringState(); |
| |
| // Shows the keyboard if the last time the keyboard was hidden was a small |
| // time ago. |
| void ShowKeyboardIfWithinTransientBlurThreshold(); |
| |
| void SetContainerBehaviorInternal(const ContainerType type); |
| |
| std::unique_ptr<KeyboardUI> ui_; |
| KeyboardLayoutDelegate* layout_delegate_; |
| std::unique_ptr<aura::Window> container_; |
| // CallbackAnimationObserver should destructed before container_ because it |
| // uses container_'s animator. |
| std::unique_ptr<CallbackAnimationObserver> animation_observer_; |
| |
| // Current active visual behavior for the keyboard container. |
| std::unique_ptr<ContainerBehavior> container_behavior_; |
| |
| std::unique_ptr<QueuedContainerType> queued_container_type_; |
| |
| // If true, show the keyboard window when keyboard UI content updates. |
| bool show_on_content_update_; |
| |
| // If true, the keyboard is always visible even if no window has input focus. |
| bool keyboard_locked_; |
| KeyboardEventFilter event_filter_; |
| |
| base::ObserverList<KeyboardControllerObserver> observer_list_; |
| |
| // The currently used keyboard position. |
| // If the contents window is visible, this should be the same size as the |
| // contents window. If not, this should be empty. |
| gfx::Rect current_keyboard_bounds_; |
| |
| KeyboardControllerState state_; |
| |
| NotificationManager notification_manager_; |
| |
| base::Time time_of_last_blur_ = base::Time::UnixEpoch(); |
| |
| static KeyboardController* instance_; |
| |
| base::WeakPtrFactory<KeyboardController> weak_factory_report_lingering_state_; |
| base::WeakPtrFactory<KeyboardController> weak_factory_will_hide_; |
| |
| DISALLOW_COPY_AND_ASSIGN(KeyboardController); |
| }; |
| |
| } // namespace keyboard |
| |
| #endif // UI_KEYBOARD_KEYBOARD_CONTROLLER_H_ |