summaryrefslogtreecommitdiff
path: root/chromium/ui/keyboard
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ui/keyboard')
-rw-r--r--chromium/ui/keyboard/BUILD.gn2
-rw-r--r--chromium/ui/keyboard/container_behavior.h6
-rw-r--r--chromium/ui/keyboard/container_floating_behavior.cc70
-rw-r--r--chromium/ui/keyboard/container_floating_behavior.h28
-rw-r--r--chromium/ui/keyboard/container_floating_behavior_unittest.cc69
-rw-r--r--chromium/ui/keyboard/container_full_width_behavior.cc6
-rw-r--r--chromium/ui/keyboard/container_full_width_behavior.h6
-rw-r--r--chromium/ui/keyboard/keyboard_controller.cc85
-rw-r--r--chromium/ui/keyboard/keyboard_controller.h19
-rw-r--r--chromium/ui/keyboard/keyboard_controller_observer.h10
-rw-r--r--chromium/ui/keyboard/keyboard_controller_unittest.cc167
-rw-r--r--chromium/ui/keyboard/keyboard_util.cc5
-rw-r--r--chromium/ui/keyboard/notification_manager.cc10
-rw-r--r--chromium/ui/keyboard/queued_container_type.cc24
-rw-r--r--chromium/ui/keyboard/queued_container_type.h37
-rw-r--r--chromium/ui/keyboard/resources/inputview_adapter.js7
16 files changed, 444 insertions, 107 deletions
diff --git a/chromium/ui/keyboard/BUILD.gn b/chromium/ui/keyboard/BUILD.gn
index 3b2816104d8..ccf79d43925 100644
--- a/chromium/ui/keyboard/BUILD.gn
+++ b/chromium/ui/keyboard/BUILD.gn
@@ -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" ]
diff --git a/chromium/ui/keyboard/container_behavior.h b/chromium/ui/keyboard/container_behavior.h
index e6224c3552d..d641d88bff6 100644
--- a/chromium/ui/keyboard/container_behavior.h
+++ b/chromium/ui/keyboard/container_behavior.h
@@ -60,9 +60,11 @@ class KEYBOARD_EXPORT ContainerBehavior {
virtual bool IsDragHandle(const gfx::Vector2d& offset,
const gfx::Size& keyboard_size) const = 0;
- virtual void SavePosition(const gfx::Point& position) = 0;
+ virtual void SavePosition(const gfx::Rect& keyboard_bounds,
+ const gfx::Size& screen_size) = 0;
- virtual void HandlePointerEvent(const ui::LocatedEvent& event) = 0;
+ virtual void HandlePointerEvent(const ui::LocatedEvent& event,
+ const gfx::Rect& display_bounds) = 0;
virtual ContainerType GetType() const = 0;
diff --git a/chromium/ui/keyboard/container_floating_behavior.cc b/chromium/ui/keyboard/container_floating_behavior.cc
index 9d93d393baf..855cdc202cf 100644
--- a/chromium/ui/keyboard/container_floating_behavior.cc
+++ b/chromium/ui/keyboard/container_floating_behavior.cc
@@ -69,7 +69,7 @@ const gfx::Rect ContainerFloatingBehavior::AdjustSetBoundsRequest(
const gfx::Rect& requested_bounds) {
gfx::Rect keyboard_bounds = requested_bounds;
- if (UseDefaultPosition()) {
+ if (!default_position_) {
// If the keyboard hasn't been shown yet, ignore the request and use
// default.
gfx::Point default_location =
@@ -80,18 +80,39 @@ const gfx::Rect ContainerFloatingBehavior::AdjustSetBoundsRequest(
// the screen.
keyboard_bounds =
ContainKeyboardToScreenBounds(keyboard_bounds, display_bounds);
+ SavePosition(keyboard_bounds, display_bounds.size());
}
return keyboard_bounds;
}
+void ContainerFloatingBehavior::SavePosition(const gfx::Rect& keyboard_bounds,
+ const gfx::Size& screen_size) {
+ int left_distance = keyboard_bounds.x();
+ int right_distance = screen_size.width() - (keyboard_bounds.right());
+ int top_distance = keyboard_bounds.y();
+ int bottom_distance = screen_size.height() - (keyboard_bounds.bottom());
+
+ double available_width = left_distance + right_distance;
+ double available_height = top_distance + bottom_distance;
+
+ if (!default_position_) {
+ default_position_ = std::make_unique<KeyboardPosition>();
+ }
+
+ default_position_->left_padding_allotment_ratio =
+ left_distance / available_width;
+ default_position_->top_padding_allotment_ratio =
+ top_distance / available_height;
+}
+
gfx::Rect ContainerFloatingBehavior::ContainKeyboardToScreenBounds(
const gfx::Rect& keyboard_bounds,
const gfx::Rect& display_bounds) const {
int left = keyboard_bounds.x();
int top = keyboard_bounds.y();
- int right = left + keyboard_bounds.width();
- int bottom = top + keyboard_bounds.height();
+ int right = keyboard_bounds.right();
+ int bottom = keyboard_bounds.bottom();
// Prevent keyboard from appearing off screen or overlapping with the edge.
if (left < 0) {
@@ -118,37 +139,36 @@ bool ContainerFloatingBehavior::IsOverscrollAllowed() const {
return false;
}
-bool ContainerFloatingBehavior::UseDefaultPosition() const {
- // (-1, -1) is used as a sentinel unset value.
- return default_position_.x() == -1;
-}
-
gfx::Point ContainerFloatingBehavior::GetPositionForShowingKeyboard(
const gfx::Size& keyboard_size,
const gfx::Rect& display_bounds) const {
// Start with the last saved position
- gfx::Point position = default_position_;
- if (UseDefaultPosition()) {
+ gfx::Point top_left_offset;
+ KeyboardPosition* position = default_position_.get();
+ if (position == nullptr) {
// If there is none, center the keyboard along the bottom of the screen.
- position.set_x(display_bounds.width() - keyboard_size.width() -
- kDefaultDistanceFromScreenRight);
- position.set_y(display_bounds.height() - keyboard_size.height() -
- kDefaultDistanceFromScreenBottom);
+ top_left_offset.set_x(display_bounds.width() - keyboard_size.width() -
+ kDefaultDistanceFromScreenRight);
+ top_left_offset.set_y(display_bounds.height() - keyboard_size.height() -
+ kDefaultDistanceFromScreenBottom);
+ } else {
+ double left = (display_bounds.width() - keyboard_size.width()) *
+ position->left_padding_allotment_ratio;
+ double top = (display_bounds.height() - keyboard_size.height()) *
+ position->top_padding_allotment_ratio;
+ top_left_offset.set_x((int)left);
+ top_left_offset.set_y((int)top);
}
// Make sure that this location is valid according to the current size of the
// screen.
- gfx::Rect keyboard_bounds = gfx::Rect(position, keyboard_size);
+ gfx::Rect keyboard_bounds = gfx::Rect(top_left_offset, keyboard_size);
gfx::Rect valid_keyboard_bounds =
ContainKeyboardToScreenBounds(keyboard_bounds, display_bounds);
return valid_keyboard_bounds.origin();
}
-void ContainerFloatingBehavior::SavePosition(const gfx::Point& position) {
- default_position_ = position;
-}
-
bool ContainerFloatingBehavior::IsDragHandle(
const gfx::Vector2d& offset,
const gfx::Size& keyboard_size) const {
@@ -156,7 +176,8 @@ bool ContainerFloatingBehavior::IsDragHandle(
}
void ContainerFloatingBehavior::HandlePointerEvent(
- const ui::LocatedEvent& event) {
+ const ui::LocatedEvent& event,
+ const gfx::Rect& display_bounds) {
// Cannot call UI-backed operations without a KeyboardController
DCHECK(controller_);
auto kb_offset = gfx::Vector2d(event.x(), event.y());
@@ -205,7 +226,7 @@ void ContainerFloatingBehavior::HandlePointerEvent(
const gfx::Rect new_bounds =
gfx::Rect(new_keyboard_location, keyboard_bounds.size());
controller_->MoveKeyboard(new_bounds);
- SavePosition(container->bounds().origin());
+ SavePosition(container->bounds(), display_bounds.size());
handle_drag = true;
}
if (!handle_drag && drag_descriptor_) {
@@ -219,9 +240,10 @@ void ContainerFloatingBehavior::SetCanonicalBounds(
const gfx::Rect& display_bounds) {
gfx::Point keyboard_location =
GetPositionForShowingKeyboard(container->bounds().size(), display_bounds);
- SavePosition(keyboard_location);
- container->SetBounds(
- gfx::Rect(keyboard_location, container->bounds().size()));
+ gfx::Rect keyboard_bounds =
+ gfx::Rect(keyboard_location, container->bounds().size());
+ SavePosition(keyboard_bounds, display_bounds.size());
+ container->SetBounds(keyboard_bounds);
}
bool ContainerFloatingBehavior::TextBlurHidesKeyboard() const {
diff --git a/chromium/ui/keyboard/container_floating_behavior.h b/chromium/ui/keyboard/container_floating_behavior.h
index 89124dfa9a4..6ea2b2abfde 100644
--- a/chromium/ui/keyboard/container_floating_behavior.h
+++ b/chromium/ui/keyboard/container_floating_behavior.h
@@ -23,6 +23,11 @@ namespace keyboard {
constexpr int kDefaultDistanceFromScreenBottom = 20;
constexpr int kDefaultDistanceFromScreenRight = 20;
+struct KeyboardPosition {
+ double left_padding_allotment_ratio;
+ double top_padding_allotment_ratio;
+};
+
class KEYBOARD_EXPORT ContainerFloatingBehavior : public ContainerBehavior {
public:
ContainerFloatingBehavior(KeyboardController* controller);
@@ -42,8 +47,10 @@ class KEYBOARD_EXPORT ContainerFloatingBehavior : public ContainerBehavior {
bool IsOverscrollAllowed() const override;
bool IsDragHandle(const gfx::Vector2d& offset,
const gfx::Size& keyboard_size) const override;
- void SavePosition(const gfx::Point& position) override;
- void HandlePointerEvent(const ui::LocatedEvent& event) override;
+ void SavePosition(const gfx::Rect& keyboard_bounds,
+ const gfx::Size& screen_size) override;
+ void HandlePointerEvent(const ui::LocatedEvent& event,
+ const gfx::Rect& display_bounds) override;
void SetCanonicalBounds(aura::Window* container,
const gfx::Rect& display_bounds) override;
ContainerType GetType() const override;
@@ -52,6 +59,11 @@ class KEYBOARD_EXPORT ContainerFloatingBehavior : public ContainerBehavior {
bool BoundsAffectWorkspaceLayout() const override;
bool SetDraggableArea(const gfx::Rect& rect) override;
+ // Calculate the position of the keyboard for when it is being shown.
+ gfx::Point GetPositionForShowingKeyboard(
+ const gfx::Size& keyboard_size,
+ const gfx::Rect& display_bounds) const;
+
private:
// Ensures that the keyboard is neither off the screen nor overlapping an
// edge.
@@ -62,19 +74,11 @@ class KEYBOARD_EXPORT ContainerFloatingBehavior : public ContainerBehavior {
// Saves the current keyboard location for use the next time it is displayed.
void UpdateLastPoint(const gfx::Point& position);
- // Returns true if the keyboard has not been display/moved yet and the default
- // position should be used.
- bool UseDefaultPosition() const;
-
- // Calculate the position of the keyboard for when it is being shown.
- gfx::Point GetPositionForShowingKeyboard(
- const gfx::Size& keyboard_size,
- const gfx::Rect& display_bounds) const;
-
KeyboardController* controller_;
// TODO(blakeo): cache the default_position_ on a per-display basis.
- gfx::Point default_position_ = gfx::Point(-1, -1);
+ std::unique_ptr<struct keyboard::KeyboardPosition> default_position_ =
+ nullptr;
// Current state of a cursor drag to move the keyboard, if one exists.
// Otherwise nullptr.
diff --git a/chromium/ui/keyboard/container_floating_behavior_unittest.cc b/chromium/ui/keyboard/container_floating_behavior_unittest.cc
index c3e81c710f4..6db3b404566 100644
--- a/chromium/ui/keyboard/container_floating_behavior_unittest.cc
+++ b/chromium/ui/keyboard/container_floating_behavior_unittest.cc
@@ -32,7 +32,8 @@ TEST(ContainerFloatingBehaviorTest, AdjustSetBoundsRequest) {
keyboard_height);
// Save an arbitrary position so that default location will not be used.
- floating_behavior.SavePosition(gfx::Point(0, 0));
+ floating_behavior.SavePosition(
+ gfx::Rect(0, 0, keyboard_width, keyboard_height), workspace.size());
gfx::Rect result =
floating_behavior.AdjustSetBoundsRequest(workspace, center);
@@ -49,6 +50,69 @@ TEST(ContainerFloatingBehaviorTest, AdjustSetBoundsRequest) {
result);
}
+TEST(ContainerFloatingBehaviorTest, AdjustSetBoundsRequestVariousSides) {
+ ContainerFloatingBehavior floating_behavior(nullptr);
+
+ const int keyboard_width = 100;
+ const int keyboard_height = 100;
+ gfx::Size keyboard_size = gfx::Size(keyboard_width, keyboard_height);
+ gfx::Rect workspace_wide(0, 0, 1000, 500);
+ gfx::Rect workspace_tall(0, 0, 500, 1000);
+ gfx::Rect top_left(0, 0, keyboard_width, keyboard_height);
+ gfx::Rect top_right(900, 0, keyboard_width, keyboard_height);
+ gfx::Rect bottom_left(0, 400, keyboard_width, keyboard_height);
+ gfx::Rect bottom_right(900, 400, keyboard_width, keyboard_height);
+ gfx::Rect bottomish_center(450, 390, keyboard_width, keyboard_height);
+
+ // Save an arbitrary position so that default location will not be used.
+ floating_behavior.SavePosition(
+ gfx::Rect(0, 0, keyboard_width, keyboard_height), workspace_wide.size());
+
+ floating_behavior.AdjustSetBoundsRequest(workspace_wide, top_left);
+ gfx::Point result = floating_behavior.GetPositionForShowingKeyboard(
+ keyboard_size, workspace_wide);
+ ASSERT_EQ(gfx::Point(0, 0), result);
+ result = floating_behavior.GetPositionForShowingKeyboard(keyboard_size,
+ workspace_tall);
+ ASSERT_EQ(gfx::Point(0, 0), result);
+
+ floating_behavior.AdjustSetBoundsRequest(workspace_wide, top_right);
+ result = floating_behavior.GetPositionForShowingKeyboard(keyboard_size,
+ workspace_wide);
+ ASSERT_EQ(gfx::Point(900, 0), result);
+ result = floating_behavior.GetPositionForShowingKeyboard(keyboard_size,
+ workspace_tall);
+ ASSERT_EQ(gfx::Point(400, 0), result);
+
+ floating_behavior.AdjustSetBoundsRequest(workspace_wide, bottom_left);
+ result = floating_behavior.GetPositionForShowingKeyboard(keyboard_size,
+ workspace_wide);
+ ASSERT_EQ(gfx::Point(0, 400), result);
+ result = floating_behavior.GetPositionForShowingKeyboard(keyboard_size,
+ workspace_tall);
+ ASSERT_EQ(gfx::Point(0, 900), result);
+
+ floating_behavior.AdjustSetBoundsRequest(workspace_wide, bottom_right);
+ result = floating_behavior.GetPositionForShowingKeyboard(keyboard_size,
+ workspace_wide);
+ ASSERT_EQ(gfx::Point(900, 400), result);
+ result = floating_behavior.GetPositionForShowingKeyboard(keyboard_size,
+ workspace_tall);
+ ASSERT_EQ(gfx::Point(400, 900), result);
+
+ floating_behavior.AdjustSetBoundsRequest(workspace_wide, bottomish_center);
+ result = floating_behavior.GetPositionForShowingKeyboard(keyboard_size,
+ workspace_wide);
+ ASSERT_EQ(gfx::Point(450, 390), result);
+ result = floating_behavior.GetPositionForShowingKeyboard(keyboard_size,
+ workspace_tall);
+
+ // rather than 400:0 for the vertical padding, use 390:10
+ // with 900 pixels available this ratio results in 877.5, which is truncated.
+ // 390 / 400 * 900 = 877.5
+ ASSERT_EQ(gfx::Point(200, 877), result);
+}
+
TEST(ContainerFloatingBehaviorTest, DontSaveCoordinatesUntilKeyboardMoved) {
ContainerFloatingBehavior floating_behavior(nullptr);
@@ -77,7 +141,8 @@ TEST(ContainerFloatingBehaviorTest, DontSaveCoordinatesUntilKeyboardMoved) {
// Simulate the user clicking and moving the keyboard to some arbitrary
// location (it doesn't matter where). Now that the coordinate is known to be
// user-determined.
- floating_behavior.SavePosition(gfx::Point(10, 10));
+ floating_behavior.SavePosition(
+ gfx::Rect(10, 10, keyboard_width, keyboard_height), workspace.size());
// Move the keyboard somewhere else. The coordinates should be taken as-is
// without being adjusted.
diff --git a/chromium/ui/keyboard/container_full_width_behavior.cc b/chromium/ui/keyboard/container_full_width_behavior.cc
index 15cbf04698c..2dca9c087ec 100644
--- a/chromium/ui/keyboard/container_full_width_behavior.cc
+++ b/chromium/ui/keyboard/container_full_width_behavior.cc
@@ -82,7 +82,8 @@ bool ContainerFullWidthBehavior::IsOverscrollAllowed() const {
return controller_ && !controller_->keyboard_locked();
}
-void ContainerFullWidthBehavior::SavePosition(const gfx::Point& position) {
+void ContainerFullWidthBehavior::SavePosition(const gfx::Rect& keyboard_bounds,
+ const gfx::Size& screen_size) {
// No-op. Nothing to save.
}
@@ -93,7 +94,8 @@ bool ContainerFullWidthBehavior::IsDragHandle(
}
void ContainerFullWidthBehavior::HandlePointerEvent(
- const ui::LocatedEvent& event) {
+ const ui::LocatedEvent& event,
+ const gfx::Rect& display_bounds) {
// No-op. Nothing special to do for pointer events.
}
diff --git a/chromium/ui/keyboard/container_full_width_behavior.h b/chromium/ui/keyboard/container_full_width_behavior.h
index 5a5d1a493d7..077d3b92eb6 100644
--- a/chromium/ui/keyboard/container_full_width_behavior.h
+++ b/chromium/ui/keyboard/container_full_width_behavior.h
@@ -39,8 +39,10 @@ class KEYBOARD_EXPORT ContainerFullWidthBehavior : public ContainerBehavior {
bool IsOverscrollAllowed() const override;
bool IsDragHandle(const gfx::Vector2d& offset,
const gfx::Size& keyboard_size) const override;
- void SavePosition(const gfx::Point& position) override;
- void HandlePointerEvent(const ui::LocatedEvent& event) override;
+ void SavePosition(const gfx::Rect& keyboard_bounds,
+ const gfx::Size& screen_size) override;
+ void HandlePointerEvent(const ui::LocatedEvent& event,
+ const gfx::Rect& display_bounds) override;
void SetCanonicalBounds(aura::Window* container,
const gfx::Rect& display_bounds) override;
ContainerType GetType() const override;
diff --git a/chromium/ui/keyboard/keyboard_controller.cc b/chromium/ui/keyboard/keyboard_controller.cc
index 76a576bfe09..b9ba7f519ef 100644
--- a/chromium/ui/keyboard/keyboard_controller.cc
+++ b/chromium/ui/keyboard/keyboard_controller.cc
@@ -12,6 +12,7 @@
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
@@ -25,6 +26,7 @@
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/display/types/display_constants.h"
+#include "ui/events/base_event_utils.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/path.h"
@@ -36,6 +38,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)
@@ -51,6 +54,13 @@ constexpr int kHideKeyboardDelayMs = 100;
// intermediate state for more than 5 seconds.
constexpr int kReportLingeringStateDelayMs = 5000;
+// Delay threshold after the keyboard enters the WILL_HIDE state. If text focus
+// is regained during this threshold, the keyboard will show again, even if it
+// is an asynchronous event. This is for the benefit of things like login flow
+// where the password field may get text focus after an animation that plays
+// after the user enters their username.
+constexpr int kTransientBlurThresholdMs = 3500;
+
// State transition diagram (document linked from crbug.com/719905)
bool isAllowedStateTransition(keyboard::KeyboardControllerState from,
keyboard::KeyboardControllerState to) {
@@ -202,12 +212,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 +394,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 */);
}
}
@@ -498,17 +504,36 @@ void KeyboardController::OnTextInputStateChanged(
return;
}
} else {
- // Abort a pending keyboard hide.
- if (WillHideKeyboard())
- ChangeState(KeyboardControllerState::SHOWN);
+ switch (state_) {
+ case KeyboardControllerState::WILL_HIDE:
+ // Abort a pending keyboard hide.
+ ChangeState(KeyboardControllerState::SHOWN);
+ return;
+ case KeyboardControllerState::HIDDEN:
+ if (focused)
+ ShowKeyboardIfWithinTransientBlurThreshold();
+ return;
+ default:
+ break;
+ }
// Do not explicitly show the Virtual keyboard unless it is in the process
- // of hiding. Instead, the virtual keyboard is shown in response to a user
- // gesture (mouse or touch) that is received while an element has input
- // focus. Showing the keyboard requires an explicit call to
- // OnShowImeIfNeeded.
+ // of hiding or the hide duration was very short (transient blur). Instead,
+ // the virtual keyboard is shown in response to a user gesture (mouse or
+ // touch) that is received while an element has input focus. Showing the
+ // keyboard requires an explicit call to OnShowImeIfNeeded.
}
}
+void KeyboardController::ShowKeyboardIfWithinTransientBlurThreshold() {
+ static const base::TimeDelta kTransientBlurThreshold =
+ base::TimeDelta::FromMilliseconds(kTransientBlurThresholdMs);
+
+ const base::Time now = base::Time::Now();
+ const base::TimeDelta time_since_last_blur = now - time_of_last_blur_;
+ if (time_since_last_blur < kTransientBlurThreshold)
+ ShowKeyboard(false);
+}
+
void KeyboardController::OnShowImeIfNeeded() {
// Calling |ShowKeyboardInternal| may move the keyboard to another display.
if (IsKeyboardEnabled() && !keyboard_locked())
@@ -624,6 +649,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();
}
@@ -678,6 +707,8 @@ void KeyboardController::ChangeState(KeyboardControllerState state) {
if (state_ == state)
return;
+ KeyboardControllerState original_state = state_;
+
state_ = state;
if (state != KeyboardControllerState::WILL_HIDE)
@@ -691,11 +722,16 @@ void KeyboardController::ChangeState(KeyboardControllerState state) {
switch (state_) {
case KeyboardControllerState::LOADING_EXTENSION:
case KeyboardControllerState::WILL_HIDE:
+ if (state_ == KeyboardControllerState::WILL_HIDE &&
+ original_state == KeyboardControllerState::SHOWN) {
+ time_of_last_blur_ = base::Time::Now();
+ }
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&KeyboardController::ReportLingeringState,
weak_factory_report_lingering_state_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(kReportLingeringStateDelayMs));
+
break;
default:
// Do nothing
@@ -737,18 +773,31 @@ bool KeyboardController::IsOverscrollAllowed() const {
}
void KeyboardController::HandlePointerEvent(const ui::LocatedEvent& event) {
- container_behavior_->HandlePointerEvent(event);
+ container_behavior_->HandlePointerEvent(
+ event, container_->GetRootWindow()->bounds());
}
-void KeyboardController::SetContainerType(const ContainerType type) {
- if (container_behavior_->GetType() == type)
+
+void KeyboardController::SetContainerType(
+ const ContainerType type,
+ base::OnceCallback<void(bool)> callback) {
+ if (container_behavior_->GetType() == type) {
+ std::move(callback).Run(false);
return;
+ }
- enqueued_container_type_ = type;
if (state_ == KeyboardControllerState::SHOWN) {
+ // Keyboard is already shown. Hiding the keyboard at first then switching
+ // container type.
+ queued_container_type_ =
+ std::make_unique<QueuedContainerType>(this, type, std::move(callback));
HideKeyboard(HIDE_REASON_AUTOMATIC);
} else {
+ // Keyboard is hidden. Switching the container type immediately and invoking
+ // the passed callback now.
SetContainerBehaviorInternal(type);
+ DCHECK(GetActiveContainerType() == type);
+ std::move(callback).Run(true /* change_successful */);
}
}
diff --git a/chromium/ui/keyboard/keyboard_controller.h b/chromium/ui/keyboard/keyboard_controller.h
index c702b72940b..ef9356317a4 100644
--- a/chromium/ui/keyboard/keyboard_controller.h
+++ b/chromium/ui/keyboard/keyboard_controller.h
@@ -9,6 +9,7 @@
#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"
@@ -22,6 +23,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 +154,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;
@@ -170,7 +176,8 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver,
// 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);
+ void SetContainerType(const ContainerType type,
+ base::OnceCallback<void(bool)> callback);
// Sets floating keyboard drggable rect.
bool SetDraggableArea(const gfx::Rect& rect);
@@ -240,6 +247,10 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver,
// 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_;
@@ -252,6 +263,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,10 +281,10 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver,
KeyboardControllerState state_;
- ContainerType enqueued_container_type_;
-
NotificationManager notification_manager_;
+ base::Time time_of_last_blur_ = base::Time::UnixEpoch();
+
static KeyboardController* instance_;
base::WeakPtrFactory<KeyboardController> weak_factory_report_lingering_state_;
diff --git a/chromium/ui/keyboard/keyboard_controller_observer.h b/chromium/ui/keyboard/keyboard_controller_observer.h
index bdaa053ac8d..822d07a3a1e 100644
--- a/chromium/ui/keyboard/keyboard_controller_observer.h
+++ b/chromium/ui/keyboard/keyboard_controller_observer.h
@@ -30,26 +30,26 @@ class KEYBOARD_EXPORT KeyboardControllerObserver {
virtual ~KeyboardControllerObserver() {}
// Called when the keyboard is shown or closed.
- virtual void OnKeyboardAvailabilityChanging(const bool is_available) {}
+ virtual void OnKeyboardAvailabilityChanged(const bool is_available) {}
// Called when the keyboard bounds are changing.
- virtual void OnKeyboardVisibleBoundsChanging(const gfx::Rect& new_bounds) {}
+ virtual void OnKeyboardVisibleBoundsChanged(const gfx::Rect& new_bounds) {}
// Called when the keyboard bounds have changed in a way that should affect
// the usable region of the workspace.
- virtual void OnKeyboardWorkspaceOccludedBoundsChanging(
+ virtual void OnKeyboardWorkspaceOccludedBoundsChanged(
const gfx::Rect& new_bounds) {}
// Called when the keyboard bounds have changed in a way that affects how the
// workspace should change to not take up the screen space occupied by the
// keyboard.
- virtual void OnKeyboardWorkspaceDisplacingBoundsChanging(
+ virtual void OnKeyboardWorkspaceDisplacingBoundsChanged(
const gfx::Rect& new_bounds){};
// Redundant with other various notification methods. Use this if the state of
// multiple properties need to be conveyed simultaneously to observer
// implementations without the need to track multiple stateful properties.
- virtual void OnKeyboardAppearanceChanging(
+ virtual void OnKeyboardAppearanceChanged(
const KeyboardStateDescriptor& state){};
// Called when the keyboard was closed.
diff --git a/chromium/ui/keyboard/keyboard_controller_unittest.cc b/chromium/ui/keyboard/keyboard_controller_unittest.cc
index fad8f1e77a7..8ecafe94069 100644
--- a/chromium/ui/keyboard/keyboard_controller_unittest.cc
+++ b/chromium/ui/keyboard/keyboard_controller_unittest.cc
@@ -14,7 +14,7 @@
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/client/focus_client.h"
-#include "ui/aura/test/aura_test_helper.h"
+#include "ui/aura/test/aura_test_base.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/window.h"
#include "ui/base/ime/dummy_text_input_client.h"
@@ -176,15 +176,39 @@ 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,
+class KeyboardControllerTest : public aura::test::AuraTestBase,
public KeyboardControllerObserver {
public:
KeyboardControllerTest()
- : scoped_task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::UI),
- visible_bounds_number_of_calls_(0),
+ : visible_bounds_number_of_calls_(0),
occluding_bounds_number_of_calls_(0),
is_available_number_of_calls_(0),
is_available_(false),
@@ -192,24 +216,14 @@ class KeyboardControllerTest : public testing::Test,
~KeyboardControllerTest() override {}
void SetUp() override {
- // The ContextFactory must exist before any Compositors are created.
- bool enable_pixel_output = false;
- ui::ContextFactory* context_factory = nullptr;
- ui::ContextFactoryPrivate* context_factory_private = nullptr;
-
- ui::InitializeContextFactoryForTests(enable_pixel_output, &context_factory,
- &context_factory_private);
-
ui::SetUpInputMethodFactoryForTesting();
- aura_test_helper_.reset(new aura::test::AuraTestHelper());
- aura_test_helper_->SetUp(context_factory, context_factory_private);
- new wm::DefaultActivationClient(aura_test_helper_->root_window());
+ aura::test::AuraTestBase::SetUp();
+ new wm::DefaultActivationClient(root_window());
focus_controller_.reset(new TestFocusController(root_window()));
layout_delegate_.reset(new TestKeyboardLayoutDelegate());
- controller_.reset(
- new KeyboardController(std::make_unique<TestKeyboardUI>(
- aura_test_helper_->host()->GetInputMethod()),
- layout_delegate_.get()));
+ controller_.reset(new KeyboardController(
+ std::make_unique<TestKeyboardUI>(host()->GetInputMethod()),
+ layout_delegate_.get()));
controller()->AddObserver(this);
}
@@ -218,11 +232,9 @@ class KeyboardControllerTest : public testing::Test,
controller()->RemoveObserver(this);
controller_.reset();
focus_controller_.reset();
- aura_test_helper_->TearDown();
- ui::TerminateContextFactoryForTests();
+ aura::test::AuraTestBase::TearDown();
}
- aura::Window* root_window() { return aura_test_helper_->root_window(); }
KeyboardUI* ui() { return controller_->ui(); }
KeyboardController* controller() { return controller_.get(); }
@@ -240,16 +252,16 @@ class KeyboardControllerTest : public testing::Test,
protected:
// KeyboardControllerObserver overrides
- void OnKeyboardVisibleBoundsChanging(const gfx::Rect& new_bounds) override {
+ void OnKeyboardVisibleBoundsChanged(const gfx::Rect& new_bounds) override {
visible_bounds_ = new_bounds;
visible_bounds_number_of_calls_++;
}
- void OnKeyboardWorkspaceOccludedBoundsChanging(
+ void OnKeyboardWorkspaceOccludedBoundsChanged(
const gfx::Rect& new_bounds) override {
occluding_bounds_ = new_bounds;
occluding_bounds_number_of_calls_++;
}
- void OnKeyboardAvailabilityChanging(bool is_available) override {
+ void OnKeyboardAvailabilityChanged(bool is_available) override {
is_available_ = is_available;
is_available_number_of_calls_++;
}
@@ -271,6 +283,15 @@ class KeyboardControllerTest : public testing::Test,
bool IsKeyboardClosed() { return keyboard_closed_; }
+ void SetProgrammaticFocus(ui::TextInputClient* client) {
+ controller_->OnTextInputStateChanged(client);
+ }
+
+ void AddTimeToTransientBlurCounter(double seconds) {
+ controller_->time_of_last_blur_ -=
+ base::TimeDelta::FromMilliseconds((int)(1000 * seconds));
+ }
+
void SetFocus(ui::TextInputClient* client) {
ui::InputMethod* input_method = ui()->GetInputMethod();
input_method->SetFocusedTextInputClient(client);
@@ -308,8 +329,6 @@ class KeyboardControllerTest : public testing::Test,
run_loop->Run();
}
- base::test::ScopedTaskEnvironment scoped_task_environment_;
- std::unique_ptr<aura::test::AuraTestHelper> aura_test_helper_;
std::unique_ptr<TestFocusController> focus_controller_;
private:
@@ -449,6 +468,82 @@ TEST_F(KeyboardControllerTest, ClickDoesNotFocusKeyboard) {
keyboard_container->RemovePreTargetHandler(&observer);
}
+// Tests that blur-then-focus that occur in less than the transient threshold
+// cause the keyboard to re-show.
+TEST_F(KeyboardControllerTest, TransientBlurShortDelay) {
+ ScopedAccessibilityKeyboardEnabler scoped_keyboard_enabler;
+ ui::DummyTextInputClient input_client(ui::TEXT_INPUT_TYPE_TEXT);
+ ui::DummyTextInputClient no_input_client(ui::TEXT_INPUT_TYPE_NONE);
+ base::RunLoop run_loop;
+ aura::Window* keyboard_container(controller()->GetContainerWindow());
+ std::unique_ptr<KeyboardContainerObserver> keyboard_container_observer(
+ new KeyboardContainerObserver(keyboard_container, &run_loop));
+ root_window()->AddChild(keyboard_container);
+
+ // Keyboard is hidden
+ EXPECT_FALSE(keyboard_container->IsVisible());
+
+ // Set programmatic focus to the text field. Nothing happens
+ SetProgrammaticFocus(&input_client);
+ EXPECT_FALSE(keyboard_container->IsVisible());
+
+ // Click it for real. Keyboard starts to appear.
+ SetFocus(&input_client);
+ EXPECT_TRUE(keyboard_container->IsVisible());
+
+ // Focus a non text field
+ SetFocus(&no_input_client);
+
+ // It waits 100 ms and then hides. Wait for this routine to finish.
+ EXPECT_TRUE(WillHideKeyboard());
+ RunLoop(&run_loop);
+ EXPECT_FALSE(keyboard_container->IsVisible());
+
+ // Virtually wait half a second
+ AddTimeToTransientBlurCounter(0.5);
+ // Apply programmatic focus to the text field.
+ SetProgrammaticFocus(&input_client);
+ EXPECT_TRUE(keyboard_container->IsVisible());
+ EXPECT_FALSE(WillHideKeyboard());
+}
+
+// Tests that blur-then-focus that occur past the transient threshold do not
+// cause the keyboard to re-show.
+TEST_F(KeyboardControllerTest, TransientBlurLongDelay) {
+ ScopedAccessibilityKeyboardEnabler scoped_keyboard_enabler;
+ ui::DummyTextInputClient input_client(ui::TEXT_INPUT_TYPE_TEXT);
+ ui::DummyTextInputClient no_input_client(ui::TEXT_INPUT_TYPE_NONE);
+ base::RunLoop run_loop;
+ aura::Window* keyboard_container(controller()->GetContainerWindow());
+ std::unique_ptr<KeyboardContainerObserver> keyboard_container_observer(
+ new KeyboardContainerObserver(keyboard_container, &run_loop));
+ root_window()->AddChild(keyboard_container);
+
+ // Keyboard is hidden
+ EXPECT_FALSE(keyboard_container->IsVisible());
+
+ // Set programmatic focus to the text field. Nothing happens
+ SetProgrammaticFocus(&input_client);
+ EXPECT_FALSE(keyboard_container->IsVisible());
+
+ // Click it for real. Keyboard starts to appear.
+ SetFocus(&input_client);
+ EXPECT_TRUE(keyboard_container->IsVisible());
+
+ // Focus a non text field
+ SetFocus(&no_input_client);
+
+ // It waits 100 ms and then hides. Wait for this routine to finish.
+ EXPECT_TRUE(WillHideKeyboard());
+ RunLoop(&run_loop);
+ EXPECT_FALSE(keyboard_container->IsVisible());
+
+ // Wait 5 seconds and then set programmatic focus to a text field
+ AddTimeToTransientBlurCounter(5.0);
+ SetProgrammaticFocus(&input_client);
+ EXPECT_FALSE(keyboard_container->IsVisible());
+}
+
TEST_F(KeyboardControllerTest, VisibilityChangeWithTextInputTypeChange) {
ScopedAccessibilityKeyboardEnabler scoped_keyboard_enabler;
ui::DummyTextInputClient input_client_0(ui::TEXT_INPUT_TYPE_TEXT);
@@ -655,13 +750,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(1, 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
diff --git a/chromium/ui/keyboard/keyboard_util.cc b/chromium/ui/keyboard/keyboard_util.cc
index 356253966e7..35b70957c3a 100644
--- a/chromium/ui/keyboard/keyboard_util.cc
+++ b/chromium/ui/keyboard/keyboard_util.cc
@@ -18,6 +18,7 @@
#include "ui/base/ime/input_method_base.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/base/ime/text_input_flags.h"
+#include "ui/base/ui_base_features.h"
#include "ui/base/ui_base_switches.h"
#include "ui/events/event_sink.h"
#include "ui/events/event_utils.h"
@@ -245,12 +246,14 @@ bool SendKeyEvent(const std::string type,
if (!input_method)
return false;
+ // This can be null if no text input field is not focused.
ui::TextInputClient* tic = input_method->GetTextInputClient();
SendProcessKeyEvent(ui::ET_KEY_PRESSED, host);
ui::KeyEvent char_event(key_value, code, ui::EF_NONE);
- tic->InsertChar(char_event);
+ if (tic)
+ tic->InsertChar(char_event);
SendProcessKeyEvent(ui::ET_KEY_RELEASED, host);
}
} else {
diff --git a/chromium/ui/keyboard/notification_manager.cc b/chromium/ui/keyboard/notification_manager.cc
index 5ef18d8da2a..4838d2b3fc2 100644
--- a/chromium/ui/keyboard/notification_manager.cc
+++ b/chromium/ui/keyboard/notification_manager.cc
@@ -59,20 +59,20 @@ void NotificationManager::SendNotifications(
for (KeyboardControllerObserver& observer : observers) {
if (send_availability_notification)
- observer.OnKeyboardAvailabilityChanging(is_available);
+ observer.OnKeyboardAvailabilityChanged(is_available);
if (send_visual_bounds_notification)
- observer.OnKeyboardVisibleBoundsChanging(bounds);
+ observer.OnKeyboardVisibleBoundsChanged(bounds);
if (send_occluded_bounds_notification)
- observer.OnKeyboardWorkspaceOccludedBoundsChanging(occluded_region);
+ observer.OnKeyboardWorkspaceOccludedBoundsChanged(occluded_region);
if (send_displaced_bounds_notification) {
- observer.OnKeyboardWorkspaceDisplacingBoundsChanging(
+ observer.OnKeyboardWorkspaceDisplacingBoundsChanged(
workspace_layout_offset_region);
}
- observer.OnKeyboardAppearanceChanging(state);
+ observer.OnKeyboardAppearanceChanged(state);
}
}
diff --git a/chromium/ui/keyboard/queued_container_type.cc b/chromium/ui/keyboard/queued_container_type.cc
new file mode 100644
index 00000000000..2cf7b882e24
--- /dev/null
+++ b/chromium/ui/keyboard/queued_container_type.cc
@@ -0,0 +1,24 @@
+// 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
diff --git a/chromium/ui/keyboard/queued_container_type.h b/chromium/ui/keyboard/queued_container_type.h
new file mode 100644
index 00000000000..ce58d930e28
--- /dev/null
+++ b/chromium/ui/keyboard/queued_container_type.h
@@ -0,0 +1,37 @@
+// 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_
diff --git a/chromium/ui/keyboard/resources/inputview_adapter.js b/chromium/ui/keyboard/resources/inputview_adapter.js
index cbafd012b8b..eedf5648d8e 100644
--- a/chromium/ui/keyboard/resources/inputview_adapter.js
+++ b/chromium/ui/keyboard/resources/inputview_adapter.js
@@ -163,7 +163,8 @@ function registerInputviewApi() {
NONE: 0,
ALT: 8,
CONTROL: 4,
- SHIFT: 2
+ SHIFT: 2,
+ CAPSLOCK: 256
};
// Mapping from keyName to keyCode (see ui::KeyEvent).
@@ -295,8 +296,10 @@ function registerInputviewApi() {
event.modifiers |= Modifier.ALT;
if (data.ctrlKey)
event.modifiers |= Modifier.CONTROL;
- if (data.shiftKey || data.capsLock)
+ if (data.shiftKey)
event.modifiers |= Modifier.SHIFT;
+ if (data.capsLock)
+ event.modifiers |= Modifier.CAPSLOCK;
chrome.virtualKeyboardPrivate.sendKeyEvent(event, logIfError_);
});