blob: 77eff28c76376cf84d2129a86058f2d8f7001a18 [file] [log] [blame]
// 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 "ui/aura/window_observer.h"
#include "ui/base/ime/input_method_observer.h"
#include "ui/base/ime/text_input_type.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/keyboard/keyboard_event_filter.h"
#include "ui/keyboard/keyboard_export.h"
#include "ui/keyboard/keyboard_layout_delegate.h"
namespace aura {
class Window;
}
namespace ui {
class InputMethod;
class TextInputClient;
}
namespace keyboard {
class CallbackAnimationObserver;
class KeyboardControllerObserver;
class KeyboardUI;
// Relative distance from the parent window, from which show animation starts
// or hide animation finishes.
constexpr int kAnimationDistance = 30;
// 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 SHOWING.
LOADING_EXTENSION = 2,
// Keyboard is being shown via animation.
SHOWING = 3,
// 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 being hidden via animation.
HIDING = 6,
// 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 or in FLOATING mode.
const gfx::Rect& current_keyboard_bounds() const {
return current_keyboard_bounds_;
}
KeyboardControllerState GetStateForTest() const { return state_; }
private:
// For access to Observer methods for simulation.
friend class KeyboardControllerTest;
// For access to SetContainerBounds.
friend class KeyboardLayoutManager;
bool show_on_resize() const { return show_on_resize_; }
// 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) 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_resize() is true. Called by
// KayboardLayoutManager.
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 show and hide animation finished successfully. If the animation
// is aborted, it won't be called.
void ShowAnimationFinished();
void HideAnimationFinished();
void NotifyKeyboardBoundsChangingAndEnsrueCaretInWorkArea();
// Called when the keyboard mode is set or the keyboard is moved to another
// display.
void AdjustKeyboardBounds();
// Validates the state transition. Called from ChangeState.
void CheckStateTransition(KeyboardControllerState prev,
KeyboardControllerState next);
// Changes the current state with validating the transition.
void ChangeState(KeyboardControllerState state);
// Reports error histogram in case lingering in an intermediate state.
void ReportLingeringState();
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_;
bool show_on_resize_;
// 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_;
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_