Commit ee4d1a64 authored by kevers@chromium.org's avatar kevers@chromium.org

Prevent a11y on-screen keyboard from occluding active text field.

Notifies the workspace layout manager when the on-screen keyboard is shown to reposition the focused window, preventing occlusion of the active text field.

BUG=235811

Review URL: https://codereview.chromium.org/313463002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@274842 0039d316-1c4b-4281-b951-d872f2087c98
parent 3b149b73
......@@ -688,6 +688,7 @@ void RootWindowController::ActivateKeyboard(
keyboard_controller->AddObserver(shelf()->shelf_layout_manager());
keyboard_controller->AddObserver(panel_layout_manager_);
keyboard_controller->AddObserver(docked_layout_manager_);
keyboard_controller->AddObserver(workspace_controller_->layout_manager());
Shell::GetInstance()->delegate()->VirtualKeyboardActivated(true);
}
aura::Window* parent = GetContainer(
......@@ -722,6 +723,8 @@ void RootWindowController::DeactivateKeyboard(
keyboard_controller->RemoveObserver(shelf()->shelf_layout_manager());
keyboard_controller->RemoveObserver(panel_layout_manager_);
keyboard_controller->RemoveObserver(docked_layout_manager_);
keyboard_controller->RemoveObserver(
workspace_controller_->layout_manager());
Shell::GetInstance()->delegate()->VirtualKeyboardActivated(false);
}
}
......
......@@ -21,10 +21,13 @@
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/base/ui_base_types.h"
#include "ui/compositor/layer.h"
#include "ui/events/event.h"
#include "ui/gfx/screen.h"
#include "ui/keyboard/keyboard_controller_observer.h"
#include "ui/wm/core/window_util.h"
#include "ui/wm/public/activation_client.h"
......@@ -123,6 +126,32 @@ void WorkspaceLayoutManager::SetChildBounds(
UpdateShelfVisibility();
}
//////////////////////////////////////////////////////////////////////////////
// WorkspaceLayoutManager, keyboard::KeyboardControllerObserver implementation:
void WorkspaceLayoutManager::OnKeyboardBoundsChanging(
const gfx::Rect& new_bounds) {
aura::Window* root_window = window_->GetRootWindow();
ui::InputMethod* input_method =
root_window->GetProperty(aura::client::kRootWindowInputMethodKey);
ui::TextInputClient* text_input_client = input_method->GetTextInputClient();
if(!text_input_client)
return;
aura::Window *window = text_input_client->GetAttachedWindow();
if (!window || !window_->Contains(window))
return;
gfx::Rect window_bounds = ScreenUtil::ConvertRectToScreen(
window_,
window->GetTargetBounds());
gfx::Rect intersect = gfx::IntersectRects(window_bounds, new_bounds);
int shift = std::min(intersect.height(),
window->bounds().y() - work_area_in_parent_.y());
if (shift > 0) {
gfx::Point origin(window->bounds().x(), window->bounds().y() - shift);
SetChildBounds(window, gfx::Rect(origin, window->bounds().size()));
}
}
//////////////////////////////////////////////////////////////////////////////
// WorkspaceLayoutManager, ash::ShellObserver implementation:
......
......@@ -17,6 +17,7 @@
#include "ui/aura/layout_manager.h"
#include "ui/aura/window_observer.h"
#include "ui/gfx/rect.h"
#include "ui/keyboard/keyboard_controller_observer.h"
#include "ui/wm/public/activation_change_observer.h"
namespace aura {
......@@ -42,6 +43,7 @@ class ASH_EXPORT WorkspaceLayoutManager
: public aura::LayoutManager,
public aura::WindowObserver,
public aura::client::ActivationChangeObserver,
public keyboard::KeyboardControllerObserver,
public ShellObserver,
public wm::WindowStateObserver {
public:
......@@ -85,6 +87,9 @@ class ASH_EXPORT WorkspaceLayoutManager
virtual void OnWindowActivated(aura::Window* gained_active,
aura::Window* lost_active) OVERRIDE;
// keyboard::KeyboardControllerObserver overrides:
virtual void OnKeyboardBoundsChanging(const gfx::Rect& new_bounds) OVERRIDE;
// WindowStateObserver overrides:
virtual void OnPostWindowStateTypeChange(
wm::WindowState* window_state,
......
......@@ -25,6 +25,8 @@
#include "ui/aura/test/test_windows.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/base/ime/dummy_text_input_client.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ui_base_types.h"
#include "ui/gfx/insets.h"
#include "ui/gfx/screen.h"
......@@ -940,4 +942,104 @@ TEST_F(WorkspaceLayoutManagerBackdropTest, VerifyBackdropAndItsStacking) {
window3.get()));
}
class WorkspaceLayoutManagerKeyboardTest : public test::AshTestBase {
public:
WorkspaceLayoutManagerKeyboardTest() {}
virtual ~WorkspaceLayoutManagerKeyboardTest() {}
virtual void SetUp() OVERRIDE {
test::AshTestBase::SetUp();
UpdateDisplay("800x600");
aura::Window* default_container = Shell::GetContainer(
Shell::GetPrimaryRootWindow(), kShellWindowId_DefaultContainer);
layout_manager_ = new WorkspaceLayoutManager(Shell::GetPrimaryRootWindow());
default_container->SetLayoutManager(layout_manager_);
}
aura::Window* CreateTestWindow(const gfx::Rect& bounds) {
return CreateTestWindowInShellWithBounds(bounds);
}
void ShowKeyboard() {
restore_work_area_insets_ = Shell::GetScreen()->GetPrimaryDisplay().
GetWorkAreaInsets();
Shell::GetInstance()->SetDisplayWorkAreaInsets(
Shell::GetPrimaryRootWindow(),
gfx::Insets(0, 0, keyboard_bounds_.height(), 0));
layout_manager_->OnKeyboardBoundsChanging(keyboard_bounds_);
}
void HideKeyboard() {
Shell::GetInstance()->SetDisplayWorkAreaInsets(
Shell::GetPrimaryRootWindow(),
restore_work_area_insets_);
layout_manager_->OnKeyboardBoundsChanging(gfx::Rect());
}
void SetKeyboardBounds(const gfx::Rect& bounds) {
keyboard_bounds_ = bounds;
}
private:
gfx::Insets restore_work_area_insets_;
gfx::Rect keyboard_bounds_;
WorkspaceLayoutManager *layout_manager_;
DISALLOW_COPY_AND_ASSIGN(WorkspaceLayoutManagerKeyboardTest);
};
class FakeTextInputClient : public ui::DummyTextInputClient {
public:
FakeTextInputClient(gfx::NativeWindow window) : window_(window) {}
virtual ~FakeTextInputClient() {}
virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE {
return window_;
}
private:
gfx::NativeWindow window_;
DISALLOW_COPY_AND_ASSIGN(FakeTextInputClient);
};
TEST_F(WorkspaceLayoutManagerKeyboardTest, AdjustWindowForA11yKeyboard) {
gfx::Rect work_area(
Shell::GetScreen()->GetPrimaryDisplay().work_area());
gfx::Rect keyboard_bounds(work_area.x(),
work_area.y() + work_area.height() / 2,
work_area.width(),
work_area.height() / 2);
SetKeyboardBounds(keyboard_bounds);
scoped_ptr<aura::Window> window(
CreateTestWindowInShellWithBounds(work_area));
aura::Window* root_window = ash::Shell::GetInstance()->GetPrimaryRootWindow();
FakeTextInputClient text_input_client(window.get());
ui::InputMethod* input_method =
root_window->GetProperty(aura::client::kRootWindowInputMethodKey);
input_method->SetFocusedTextInputClient(&text_input_client);
int available_height =
Shell::GetScreen()->GetPrimaryDisplay().bounds().height() -
keyboard_bounds.height();
EXPECT_EQ(gfx::Rect(work_area).ToString(),
window->bounds().ToString());
ShowKeyboard();
EXPECT_EQ(gfx::Rect(work_area.origin(),
gfx::Size(work_area.width(), available_height)).ToString(),
window->bounds().ToString());
HideKeyboard();
window->SetBounds(gfx::Rect(50, 50, 100, 500));
EXPECT_EQ("50,50 100x500", window->bounds().ToString());
ShowKeyboard();
EXPECT_EQ(gfx::Rect(50, 0, 100, available_height).ToString(),
window->bounds().ToString());
HideKeyboard();
input_method->SetFocusedTextInputClient(NULL);
}
} // namespace ash
......@@ -41,6 +41,8 @@ class ASH_EXPORT WorkspaceController {
void SetMaximizeBackdropDelegate(
scoped_ptr<WorkspaceLayoutManagerDelegate> delegate);
WorkspaceLayoutManager* layout_manager() { return layout_manager_; }
private:
friend class WorkspaceControllerTestHelper;
......
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