Commit 8bc2d0a3 authored by Darren Shen's avatar Darren Shen Committed by Commit Bot

[VK] Prevent floating keyboard from moving the focused window.

Currently, when the keyboard is shown, we check if it obscures the
focused window. If it does, we move the focused window upwards so that
it's no longer obscured by the text field.

While this works well for the docked keyboard, it doesn't make much
sense for the floating keyboard. Thus, we change the logic to use
the occluded bounds of the keyboard to check whether it obscures the
focused window. The occluded bounds is the same as the actual bounds
for the docked keyboard, but is empty for the floating keyboard. This
means that the floating keyboard will no longer cause the focused
window to move upwards.

Bug: 838731
Change-Id: Id5de5c35980c69443be114631840bdfb64f26b3e
Reviewed-on: https://chromium-review.googlesource.com/1059976Reviewed-by: default avatarJames Cook <jamescook@chromium.org>
Reviewed-by: default avatarYuichiro Hanada <yhanada@chromium.org>
Commit-Queue: Darren Shen <shend@chromium.org>
Cr-Commit-Position: refs/heads/master@{#559336}
parent 19d18966
......@@ -1057,7 +1057,7 @@ TEST_F(VirtualKeyboardRootWindowControllerTest, EnsureCaretInWorkArea) {
root_window->bounds(), keyboard_height));
contents_window->Show();
ui->EnsureCaretInWorkArea();
ui->EnsureCaretInWorkArea(contents_window->GetBoundsInScreen());
ASSERT_EQ(root_window->bounds().width(),
text_input_client.caret_exclude_rect().width());
ASSERT_EQ(keyboard_height, text_input_client.caret_exclude_rect().height());
......@@ -1098,7 +1098,7 @@ TEST_F(VirtualKeyboardRootWindowControllerTest,
primary_root_window->bounds(), keyboard_height));
contents_window->Show();
ui->EnsureCaretInWorkArea();
ui->EnsureCaretInWorkArea(contents_window->GetBoundsInScreen());
EXPECT_TRUE(primary_root_window->GetBoundsInScreen().Contains(
text_input_client.caret_exclude_rect()));
EXPECT_EQ(primary_root_window->GetBoundsInScreen().width(),
......@@ -1112,7 +1112,7 @@ TEST_F(VirtualKeyboardRootWindowControllerTest,
contents_window->SetBounds(keyboard::KeyboardBoundsFromRootBounds(
secondary_root_window->bounds(), keyboard_height));
ui->EnsureCaretInWorkArea();
ui->EnsureCaretInWorkArea(contents_window->GetBoundsInScreen());
EXPECT_FALSE(primary_root_window->GetBoundsInScreen().Contains(
text_input_client.caret_exclude_rect()));
EXPECT_TRUE(secondary_root_window->GetBoundsInScreen().Contains(
......
......@@ -156,6 +156,7 @@ test("keyboard_unittests") {
"//base",
"//base/test:test_support",
"//mojo/edk",
"//testing/gmock",
"//testing/gtest",
"//ui/aura:test_support",
"//ui/base",
......
......@@ -391,7 +391,7 @@ void KeyboardController::HideKeyboard(HideReason reason) {
for (KeyboardControllerObserver& observer : observer_list_)
observer.OnKeyboardHidden();
ui_->EnsureCaretInWorkArea();
ui_->EnsureCaretInWorkArea(gfx::Rect());
break;
}
......@@ -708,7 +708,9 @@ void KeyboardController::
// Notify observers after animation finished to prevent reveal desktop
// background during animation.
NotifyContentsBoundsChanging(container_->bounds());
ui_->EnsureCaretInWorkArea();
ui_->EnsureCaretInWorkArea(container_behavior_->BoundsObscureUsableRegion()
? current_keyboard_bounds_
: gfx::Rect());
}
void KeyboardController::NotifyKeyboardConfigChanged() {
......
......@@ -11,6 +11,7 @@
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
#include "build/build_config.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/test/aura_test_base.h"
......@@ -868,4 +869,31 @@ TEST_F(KeyboardControllerTest, TextInputMode) {
EXPECT_TRUE(keyboard_container->IsVisible());
}
// Checks that floating keyboard does not cause focused window to move upwards.
// Refer to crbug.com/838731.
TEST_F(KeyboardControllerAnimationTest, FloatingKeyboardEnsureCaretInWorkArea) {
// Mock TextInputClient to intercept calls to EnsureCaretNotInRect.
struct MockTextInputClient : public ui::DummyTextInputClient {
MockTextInputClient() : DummyTextInputClient(ui::TEXT_INPUT_TYPE_TEXT) {}
MOCK_METHOD1(EnsureCaretNotInRect, void(const gfx::Rect&));
};
// Floating keyboard should call EnsureCaretNotInRect with the empty rect.
MockTextInputClient mock_input_client;
EXPECT_CALL(mock_input_client, EnsureCaretNotInRect(gfx::Rect())).Times(1);
ScopedAccessibilityKeyboardEnabler scoped_keyboard_enabler;
controller()->SetContainerType(keyboard::ContainerType::FLOATING,
base::nullopt, base::DoNothing());
ASSERT_EQ(keyboard::ContainerType::FLOATING,
controller()->GetActiveContainerType());
// Ensure keyboard ui is populated
ui::Layer* layer = keyboard_container()->layer();
SetFocus(&mock_input_client);
RunAnimationForLayer(layer);
EXPECT_TRUE(keyboard_container()->IsVisible());
}
} // namespace keyboard
......@@ -36,22 +36,17 @@ void KeyboardUI::HideKeyboardContainer(aura::Window* container) {
}
}
void KeyboardUI::EnsureCaretInWorkArea() {
void KeyboardUI::EnsureCaretInWorkArea(const gfx::Rect& occluded_bounds) {
if (!GetInputMethod())
return;
TRACE_EVENT0("vk", "EnsureCaretInWorkArea");
const aura::Window* contents_window = GetContentsWindow();
const gfx::Rect keyboard_bounds_in_screen =
contents_window->IsVisible() ? contents_window->GetBoundsInScreen()
: gfx::Rect();
if (keyboard_controller_->IsOverscrollAllowed()) {
GetInputMethod()->SetOnScreenKeyboardBounds(keyboard_bounds_in_screen);
GetInputMethod()->SetOnScreenKeyboardBounds(occluded_bounds);
} else if (GetInputMethod()->GetTextInputClient()) {
GetInputMethod()->GetTextInputClient()->EnsureCaretNotInRect(
keyboard_bounds_in_screen);
occluded_bounds);
}
}
......
......@@ -58,7 +58,7 @@ class KEYBOARD_EXPORT KeyboardUI {
// Ensures caret in current work area (not occluded by virtual keyboard
// window).
virtual void EnsureCaretInWorkArea();
virtual void EnsureCaretInWorkArea(const gfx::Rect& occluded_bounds);
// KeyboardController owns the KeyboardUI instance so KeyboardUI subclasses
// should not take ownership of the |controller|. |controller| can be null
......
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