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