keyboard_controller_unittest.cc revision 58537e28ecd584eab876aee8be7156509866d23a
1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/bind.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
7ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/aura/client/focus_client.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/aura/root_window.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/aura/test/aura_test_helper.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/aura/test/event_generator.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/aura/test/test_window_delegate.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/aura/window.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/ime/input_method.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/ime/input_method_factory.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/ime/text_input_client.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/compositor/layer_type.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/gfx/rect.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/keyboard/keyboard_controller.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/keyboard/keyboard_controller_proxy.h"
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace keyboard {
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// An event handler that focuses a window when it is clicked/touched on. This is
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// used to match the focus manger behaviour in ash and views.
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class TestFocusController : public ui::EventHandler {
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  explicit TestFocusController(aura::RootWindow* root)
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : root_(root) {
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    root_->AddPreTargetHandler(this);
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~TestFocusController() {
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    root_->RemovePreTargetHandler(this);
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Overridden from ui::EventHandler:
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnEvent(ui::Event* event) OVERRIDE {
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    aura::Window* target = static_cast<aura::Window*>(event->target());
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (event->type() == ui::ET_MOUSE_PRESSED ||
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        event->type() == ui::ET_TOUCH_PRESSED) {
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      aura::client::GetFocusClient(target)->FocusWindow(target);
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  aura::Window* root_;
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TestFocusController);
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class TestKeyboardControllerProxy : public KeyboardControllerProxy {
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestKeyboardControllerProxy()
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : window_(new aura::Window(&delegate_)),
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        input_method_(ui::CreateInputMethod(NULL,
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                            gfx::kNullAcceleratedWidget)) {
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    window_->Init(ui::LAYER_NOT_DRAWN);
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    window_->set_owned_by_parent(false);
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~TestKeyboardControllerProxy() {
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Destroy the window before the delegate.
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    window_.reset();
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Overridden from KeyboardControllerProxy:
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual aura::Window* GetKeyboardWindow() OVERRIDE { return window_.get(); }
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual content::BrowserContext* GetBrowserContext() OVERRIDE { return NULL; }
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ui::InputMethod* GetInputMethod() OVERRIDE {
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return input_method_.get();
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void RequestAudioInput(content::WebContents* web_contents,
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      const content::MediaStreamRequest& request,
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      const content::MediaResponseCallback& callback) OVERRIDE { return; }
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<aura::Window> window_;
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  aura::test::TestWindowDelegate delegate_;
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<ui::InputMethod> input_method_;
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TestKeyboardControllerProxy);
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Keeps a count of all the events a window receives.
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class EventObserver : public ui::EventHandler {
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EventObserver() {}
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~EventObserver() {}
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int GetEventCount(ui::EventType type) {
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return event_counts_[type];
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Overridden from ui::EventHandler:
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnEvent(ui::Event* event) OVERRIDE {
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ui::EventHandler::OnEvent(event);
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    event_counts_[event->type()]++;
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::map<ui::EventType, int> event_counts_;
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(EventObserver);
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class TestTextInputClient : public ui::TextInputClient {
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  explicit TestTextInputClient(ui::TextInputType type)
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : type_(type) {}
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~TestTextInputClient() {}
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Overridden from ui::TextInputClient:
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void SetCompositionText(
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const ui::CompositionText& composition) OVERRIDE {}
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void ConfirmCompositionText() OVERRIDE {}
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void ClearCompositionText() OVERRIDE {}
1197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  virtual void InsertText(const base::string16& text) OVERRIDE {}
1207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  virtual void InsertChar(base::char16 ch, int flags) OVERRIDE {}
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE {
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return static_cast<gfx::NativeWindow>(NULL);
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ui::TextInputType GetTextInputType() const OVERRIDE {
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return type_;
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
127ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  virtual ui::TextInputMode GetTextInputMode() const OVERRIDE {
128ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return ui::TEXT_INPUT_MODE_DEFAULT;
129ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual bool CanComposeInline() const OVERRIDE { return false; }
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual gfx::Rect GetCaretBounds() OVERRIDE { return gfx::Rect(); }
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual bool GetCompositionCharacterBounds(uint32 index,
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                             gfx::Rect* rect) OVERRIDE {
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual bool HasCompositionText() OVERRIDE { return false; }
13858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual bool GetTextRange(gfx::Range* range) OVERRIDE { return false; }
13958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual bool GetCompositionTextRange(gfx::Range* range) OVERRIDE {
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
14258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual bool GetSelectionRange(gfx::Range* range) OVERRIDE { return false; }
14358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual bool SetSelectionRange(const gfx::Range& range) OVERRIDE {
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual bool DeleteRange(const gfx::Range& range) OVERRIDE { return false; }
14758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual bool GetTextFromRange(const gfx::Range& range,
1487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                base::string16* text) OVERRIDE {
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnInputMethodChanged() OVERRIDE {}
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual bool ChangeTextDirectionAndLayoutAlignment(
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::i18n::TextDirection direction) OVERRIDE { return false; }
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void ExtendSelectionAndDelete(size_t before, size_t after) OVERRIDE {}
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void EnsureCaretInRect(const gfx::Rect& rect) OVERRIDE {}
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ui::TextInputType type_;
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TestTextInputClient);
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
16258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)class KeyboardContainerObserver : public aura::WindowObserver {
16358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) public:
16458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  explicit KeyboardContainerObserver(aura::Window* window) : window_(window) {
16558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    window_->AddObserver(this);
16658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual ~KeyboardContainerObserver() {
16858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    window_->RemoveObserver(this);
16958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
17158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) private:
17258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual void OnWindowVisibilityChanged(aura::Window* window,
17358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                         bool visible) OVERRIDE {
17458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (!visible)
17558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      base::MessageLoop::current()->Quit();
17658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
17758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  aura::Window* window_;
17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
18058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(KeyboardContainerObserver);
18158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)};
18258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class KeyboardControllerTest : public testing::Test {
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  KeyboardControllerTest() {}
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~KeyboardControllerTest() {}
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    aura_test_helper_.reset(new aura::test::AuraTestHelper(&message_loop_));
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    aura_test_helper_->SetUp();
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ui::SetUpInputMethodFactoryForTesting();
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    focus_controller_.reset(new TestFocusController(root_window()));
19558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    proxy_ = new TestKeyboardControllerProxy();
19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    controller_.reset(new KeyboardController(proxy_));
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void TearDown() OVERRIDE {
200ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    focus_controller_.reset();
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    aura_test_helper_->TearDown();
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  aura::RootWindow* root_window() { return aura_test_helper_->root_window(); }
20558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  KeyboardControllerProxy* proxy() { return proxy_; }
20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  KeyboardController* controller() { return controller_.get(); }
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
20858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void ShowKeyboard() {
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    TestTextInputClient test_text_input_client(ui::TEXT_INPUT_TYPE_TEXT);
21058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    controller_->OnTextInputStateChanged(&test_text_input_client);
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected:
21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  bool WillHideKeyboard() {
21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return controller_->WillHideKeyboard();
21658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
21758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoopForUI message_loop_;
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<aura::test::AuraTestHelper> aura_test_helper_;
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<TestFocusController> focus_controller_;
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
22358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  KeyboardControllerProxy* proxy_;
22458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_ptr<KeyboardController> controller_;
22558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(KeyboardControllerTest);
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(KeyboardControllerTest, KeyboardSize) {
23058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_ptr<aura::Window> container(controller()->GetContainerWindow());
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Rect bounds(0, 0, 100, 100);
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  container->SetBounds(bounds);
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
23458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  const gfx::Rect& before_bounds = proxy()->GetKeyboardWindow()->bounds();
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Rect new_bounds(
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      before_bounds.x(), before_bounds.y(),
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      before_bounds.width() / 2, before_bounds.height() / 2);
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The KeyboardController's LayoutManager shouldn't let this happen
24058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  proxy()->GetKeyboardWindow()->SetBounds(new_bounds);
24158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ASSERT_EQ(before_bounds, proxy()->GetKeyboardWindow()->bounds());
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Tests that tapping/clicking inside the keyboard does not give it focus.
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(KeyboardControllerTest, ClickDoesNotFocusKeyboard) {
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const gfx::Rect& root_bounds = root_window()->bounds();
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  aura::test::EventCountDelegate delegate;
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<aura::Window> window(new aura::Window(&delegate));
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  window->Init(ui::LAYER_NOT_DRAWN);
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  window->SetBounds(root_bounds);
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  root_window()->AddChild(window.get());
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  window->Show();
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  window->Focus();
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
25558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_ptr<aura::Window> keyboard_container(
25658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      controller()->GetContainerWindow());
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  keyboard_container->SetBounds(root_bounds);
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  root_window()->AddChild(keyboard_container.get());
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  keyboard_container->Show();
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
26258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ShowKeyboard();
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(window->IsVisible());
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(keyboard_container->IsVisible());
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(window->HasFocus());
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(keyboard_container->HasFocus());
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Click on the keyboard. Make sure the keyboard receives the event, but does
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // not get focus.
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EventObserver observer;
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  keyboard_container->AddPreTargetHandler(&observer);
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  aura::test::EventGenerator generator(root_window());
27558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  generator.MoveMouseTo(proxy()->GetKeyboardWindow()->bounds().CenterPoint());
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  generator.ClickLeftButton();
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(window->HasFocus());
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(keyboard_container->HasFocus());
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ("0 0", delegate.GetMouseButtonCountsAndReset());
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(1, observer.GetEventCount(ui::ET_MOUSE_PRESSED));
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(1, observer.GetEventCount(ui::ET_MOUSE_RELEASED));
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Click outside of the keyboard. It should reach the window behind.
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  generator.MoveMouseTo(gfx::Point());
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  generator.ClickLeftButton();
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ("1 1", delegate.GetMouseButtonCountsAndReset());
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(KeyboardControllerTest, VisibilityChangeWithTextInputTypeChange) {
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const gfx::Rect& root_bounds = root_window()->bounds();
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
29258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ui::InputMethod* input_method = proxy()->GetInputMethod();
29358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  TestTextInputClient input_client_0(ui::TEXT_INPUT_TYPE_TEXT);
29458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  TestTextInputClient input_client_1(ui::TEXT_INPUT_TYPE_TEXT);
29558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  TestTextInputClient input_client_2(ui::TEXT_INPUT_TYPE_TEXT);
29658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  TestTextInputClient no_input_client_0(ui::TEXT_INPUT_TYPE_NONE);
29758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  TestTextInputClient no_input_client_1(ui::TEXT_INPUT_TYPE_NONE);
29858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  input_method->SetFocusedTextInputClient(&input_client_0);
29958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
30058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_ptr<aura::Window> keyboard_container(
30158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      controller()->GetContainerWindow());
30258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  scoped_ptr<KeyboardContainerObserver> keyboard_container_observer(
30358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      new KeyboardContainerObserver(keyboard_container.get()));
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  keyboard_container->SetBounds(root_bounds);
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  root_window()->AddChild(keyboard_container.get());
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(keyboard_container->IsVisible());
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
30958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  input_method->SetFocusedTextInputClient(&no_input_client_0);
31058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Keyboard should not immediately hide itself. It is delayed to avoid layout
31158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // flicker when the focus of input field quickly change.
31258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_TRUE(keyboard_container->IsVisible());
31358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_TRUE(WillHideKeyboard());
31458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Wait for hide keyboard to finish.
31558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  base::MessageLoop::current()->Run();
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_FALSE(keyboard_container->IsVisible());
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
31858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  input_method->SetFocusedTextInputClient(&input_client_1);
31958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_TRUE(keyboard_container->IsVisible());
32058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
32158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Schedule to hide keyboard.
32258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  input_method->SetFocusedTextInputClient(&no_input_client_1);
32358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_TRUE(WillHideKeyboard());
32458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Cancel keyboard hide.
32558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  input_method->SetFocusedTextInputClient(&input_client_2);
32658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
32758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EXPECT_FALSE(WillHideKeyboard());
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(keyboard_container->IsVisible());
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace keyboard
332