Commit c6a29b98 authored by Blake O'Hare's avatar Blake O'Hare Committed by Commit Bot

Add callback support to KeyboardController when setting container type

Currently, there is a field on KeyboardController for enqueuing a
container type change. Eventually we want to support invoking a JS
callback to notify the extension when a keyboard mode changes.

This is the first step in that direction. Instead of persisting a
single enum value for the enqueued container behavior, it tracks both
the type and a callback handle. This QueuedContainerBehavior object
will invoke the callback once it goes out of scope.

Change-Id: Iea4e96259314a34d31661342024a23617a9f4b74
Bug: 806189
Reviewed-on: https://chromium-review.googlesource.com/888119
Commit-Queue: Blake O'Hare <blakeo@chromium.org>
Reviewed-by: default avatarYuichiro Hanada <yhanada@chromium.org>
Cr-Commit-Position: refs/heads/master@{#533197}
parent 23fbbe66
......@@ -35,6 +35,8 @@ jumbo_component("keyboard") {
"keyboard_util.h",
"notification_manager.cc",
"notification_manager.h",
"queued_container_type.cc",
"queued_container_type.h",
]
defines = [ "KEYBOARD_IMPLEMENTATION" ]
......
......@@ -36,6 +36,7 @@
#include "ui/keyboard/keyboard_ui.h"
#include "ui/keyboard/keyboard_util.h"
#include "ui/keyboard/notification_manager.h"
#include "ui/keyboard/queued_container_type.h"
#include "ui/wm/core/window_animations.h"
#if defined(OS_CHROMEOS)
......@@ -202,12 +203,11 @@ KeyboardController::KeyboardController(std::unique_ptr<KeyboardUI> ui,
show_on_content_update_(false),
keyboard_locked_(false),
state_(KeyboardControllerState::UNKNOWN),
enqueued_container_type_(ContainerType::FULL_WIDTH),
weak_factory_report_lingering_state_(this),
weak_factory_will_hide_(this) {
ui_->GetInputMethod()->AddObserver(this);
ui_->SetController(this);
SetContainerBehaviorInternal(enqueued_container_type_);
SetContainerBehaviorInternal(ContainerType::FULL_WIDTH);
ChangeState(KeyboardControllerState::INITIAL);
}
......@@ -385,11 +385,8 @@ void KeyboardController::HideKeyboard(HideReason reason) {
}
void KeyboardController::HideAnimationFinished() {
if (state_ != KeyboardControllerState::HIDDEN)
return;
if (enqueued_container_type_ != container_behavior_->GetType()) {
SetContainerBehaviorInternal(enqueued_container_type_);
if (state_ == KeyboardControllerState::HIDDEN && queued_container_type_) {
SetContainerBehaviorInternal(queued_container_type_->container_type());
ShowKeyboard(false /* lock */);
}
}
......@@ -624,6 +621,10 @@ void KeyboardController::PopulateKeyboardContent(int64_t display_id,
container_behavior_->DoShowingAnimation(container_.get(), &settings);
// the queued container behavior will notify JS to change layout when it
// gets destroyed.
queued_container_type_ = nullptr;
ChangeState(KeyboardControllerState::SHOWN);
NotifyKeyboardBoundsChangingAndEnsureCaretInWorkArea();
}
......@@ -742,10 +743,20 @@ void KeyboardController::HandlePointerEvent(const ui::LocatedEvent& event) {
}
void KeyboardController::SetContainerType(const ContainerType type) {
if (container_behavior_->GetType() == type)
SetContainerType(type, base::BindOnce([](bool ignored) { /* noop */ }));
}
void KeyboardController::SetContainerType(
const ContainerType type,
base::OnceCallback<void(bool)> callback) {
if (container_behavior_->GetType() == type) {
std::move(callback).Run(false);
return;
}
queued_container_type_ =
std::make_unique<QueuedContainerType>(this, type, std::move(callback));
enqueued_container_type_ = type;
if (state_ == KeyboardControllerState::SHOWN) {
HideKeyboard(HIDE_REASON_AUTOMATIC);
} else {
......
......@@ -22,6 +22,7 @@
#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;
......@@ -152,6 +153,10 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver,
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;
......@@ -171,6 +176,8 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver,
// will trigger a hide animation and a subsequent show animation. Otherwise
// the ContainerBehavior change is synchronous.
void SetContainerType(const ContainerType type);
void SetContainerType(const ContainerType type,
base::OnceCallback<void(bool)> callback);
// Sets floating keyboard drggable rect.
bool SetDraggableArea(const gfx::Rect& rect);
......@@ -252,6 +259,8 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver,
// 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_;
......@@ -268,8 +277,6 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver,
KeyboardControllerState state_;
ContainerType enqueued_container_type_;
NotificationManager notification_manager_;
static KeyboardController* instance_;
......
......@@ -176,6 +176,32 @@ class TestKeyboardLayoutDelegate : public KeyboardLayoutDelegate {
DISALLOW_COPY_AND_ASSIGN(TestKeyboardLayoutDelegate);
};
class SetModeCallbackInvocationCounter {
public:
SetModeCallbackInvocationCounter() : weak_factory_invoke_(this) {}
void Invoke(bool status) {
if (status)
invocation_count_success_++;
else
invocation_count_failure_++;
}
base::OnceCallback<void(bool)> GetInvocationCallback() {
return base::BindOnce(&SetModeCallbackInvocationCounter::Invoke,
weak_factory_invoke_.GetWeakPtr());
}
int invocation_count_for_status(bool status) {
return status ? invocation_count_success_ : invocation_count_failure_;
}
private:
int invocation_count_success_ = 0;
int invocation_count_failure_ = 0;
base::WeakPtrFactory<SetModeCallbackInvocationCounter> weak_factory_invoke_;
};
} // namespace
class KeyboardControllerTest : public testing::Test,
......@@ -655,13 +681,27 @@ TEST_F(KeyboardControllerAnimationTest, ContainerAnimation) {
EXPECT_EQ(gfx::Rect(), notified_occluding_bounds());
EXPECT_FALSE(notified_is_available());
controller()->SetContainerType(ContainerType::FLOATING);
SetModeCallbackInvocationCounter invocation_counter;
controller()->SetContainerType(ContainerType::FLOATING,
invocation_counter.GetInvocationCallback());
EXPECT_EQ(0, invocation_counter.invocation_count_for_status(true));
EXPECT_EQ(0, invocation_counter.invocation_count_for_status(false));
ShowKeyboard();
RunAnimationForLayer(layer);
EXPECT_EQ(1, invocation_counter.invocation_count_for_status(true));
EXPECT_EQ(0, invocation_counter.invocation_count_for_status(false));
// Visible bounds and occluding bounds are now different.
EXPECT_EQ(keyboard_container()->bounds(), notified_visible_bounds());
EXPECT_EQ(gfx::Rect(), notified_occluding_bounds());
EXPECT_TRUE(notified_is_available());
// callback should do nothing when container mode is set to the current active
// container type. An unnecessary call gets registered synchronously as a
// failure status to the callback.
controller()->SetContainerType(ContainerType::FLOATING,
invocation_counter.GetInvocationCallback());
EXPECT_EQ(1, invocation_counter.invocation_count_for_status(true));
EXPECT_EQ(1, invocation_counter.invocation_count_for_status(false));
}
// Show keyboard during keyboard hide animation should abort the hide animation
......
// Copyright 2018 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.
#include "base/bind.h"
#include "ui/keyboard/keyboard_controller.h"
namespace keyboard {
QueuedContainerType::QueuedContainerType(
KeyboardController* controller,
ContainerType container_type,
base::OnceCallback<void(bool success)> callback)
: controller_(controller),
container_type_(container_type),
callback_(std::move(callback)){};
QueuedContainerType::~QueuedContainerType() {
bool change_successful =
controller_->GetActiveContainerType() == container_type_;
std::move(callback_).Run(change_successful);
};
} // namespace keyboard
// Copyright 2018 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_QUEUED_CONTAINER_TYPE_H_
#define UI_KEYBOARD_QUEUED_CONTAINER_TYPE_H_
#include "base/bind.h"
#include "ui/keyboard/container_type.h"
namespace keyboard {
class KeyboardController;
// Tracks a queued ContainerType change request. Couples a container type with a
// callback to invoke once the necessary animation and container changes are
// complete.
// The callback will be invoked once this object goes out of scope. Success
// is defined as the KeyboardController's current container behavior matching
// the same container type as the queued container type.
class QueuedContainerType {
public:
QueuedContainerType(KeyboardController* controller,
ContainerType container_type,
base::OnceCallback<void(bool success)> callback);
~QueuedContainerType();
ContainerType container_type() { return container_type_; }
private:
KeyboardController* controller_;
ContainerType container_type_;
base::OnceCallback<void(bool success)> callback_;
};
} // namespace keyboard
#endif // UI_KEYBOARD_QUEUED_CONTAINER_TYPE_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment