1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ui/wm/core/input_method_event_filter.h"
6
7#include "testing/gtest/include/gtest/gtest.h"
8#include "ui/aura/client/aura_constants.h"
9#include "ui/aura/test/aura_test_base.h"
10#include "ui/aura/test/test_windows.h"
11#include "ui/aura/window_event_dispatcher.h"
12#include "ui/base/ime/dummy_text_input_client.h"
13#include "ui/base/ime/input_method.h"
14#include "ui/base/ime/text_input_focus_manager.h"
15#include "ui/base/ui_base_switches_util.h"
16#include "ui/events/test/event_generator.h"
17#include "ui/events/test/test_event_handler.h"
18#include "ui/wm/core/compound_event_filter.h"
19#include "ui/wm/core/default_activation_client.h"
20#include "ui/wm/public/activation_client.h"
21
22#if !defined(OS_WIN) && !defined(USE_X11)
23// On platforms except Windows and X11, ui::test::EventGenerator::PressKey
24// generates a key event without native_event(), which is not supported by
25// ui::MockInputMethod.
26#define TestInputMethodKeyEventPropagation \
27DISABLED_TestInputMethodKeyEventPropagation
28#endif
29
30namespace wm {
31
32class TestTextInputClient : public ui::DummyTextInputClient {
33 public:
34  explicit TestTextInputClient(aura::Window* window) : window_(window) {}
35
36  virtual aura::Window* GetAttachedWindow() const OVERRIDE { return window_; }
37
38 private:
39  aura::Window* window_;
40
41  DISALLOW_COPY_AND_ASSIGN(TestTextInputClient);
42};
43
44class InputMethodEventFilterTest : public aura::test::AuraTestBase {
45 public:
46  InputMethodEventFilterTest() {}
47  virtual ~InputMethodEventFilterTest() {}
48
49  // testing::Test overrides:
50  virtual void SetUp() OVERRIDE {
51    aura::test::AuraTestBase::SetUp();
52
53    root_window()->AddPreTargetHandler(&root_filter_);
54    input_method_event_filter_.reset(
55        new InputMethodEventFilter(host()->GetAcceleratedWidget()));
56    input_method_event_filter_->SetInputMethodPropertyInRootWindow(
57        root_window());
58    root_filter_.AddHandler(input_method_event_filter_.get());
59    root_filter_.AddHandler(&test_filter_);
60
61    test_window_.reset(aura::test::CreateTestWindowWithDelegate(
62        &test_window_delegate_, -1, gfx::Rect(), root_window()));
63    test_input_client_.reset(new TestTextInputClient(test_window_.get()));
64
65    input_method_event_filter_->input_method()->SetFocusedTextInputClient(
66        test_input_client_.get());
67  }
68
69  virtual void TearDown() OVERRIDE {
70    test_window_.reset();
71    root_filter_.RemoveHandler(&test_filter_);
72    root_filter_.RemoveHandler(input_method_event_filter_.get());
73    root_window()->RemovePreTargetHandler(&root_filter_);
74
75    input_method_event_filter_.reset();
76    test_input_client_.reset();
77    aura::test::AuraTestBase::TearDown();
78  }
79
80 protected:
81  CompoundEventFilter root_filter_;
82  ui::test::TestEventHandler test_filter_;
83  scoped_ptr<InputMethodEventFilter> input_method_event_filter_;
84  aura::test::TestWindowDelegate test_window_delegate_;
85  scoped_ptr<aura::Window> test_window_;
86  scoped_ptr<TestTextInputClient> test_input_client_;
87
88 private:
89  DISALLOW_COPY_AND_ASSIGN(InputMethodEventFilterTest);
90};
91
92TEST_F(InputMethodEventFilterTest, TestInputMethodProperty) {
93  // Tests if InputMethodEventFilter adds a window property on its
94  // construction.
95  EXPECT_TRUE(root_window()->GetProperty(
96      aura::client::kRootWindowInputMethodKey));
97}
98
99// Tests if InputMethodEventFilter dispatches a ui::ET_TRANSLATED_KEY_* event to
100// the root window.
101TEST_F(InputMethodEventFilterTest, TestInputMethodKeyEventPropagation) {
102  // Send a fake key event to the root window. InputMethodEventFilter, which is
103  // automatically set up by AshTestBase, consumes it and sends a new
104  // ui::ET_TRANSLATED_KEY_* event to the root window, which will be consumed by
105  // the test event filter.
106  ui::test::EventGenerator generator(root_window());
107  EXPECT_EQ(0, test_filter_.num_key_events());
108  generator.PressKey(ui::VKEY_SPACE, 0);
109  EXPECT_EQ(1, test_filter_.num_key_events());
110  generator.ReleaseKey(ui::VKEY_SPACE, 0);
111  EXPECT_EQ(2, test_filter_.num_key_events());
112}
113
114TEST_F(InputMethodEventFilterTest, TestEventDispatching) {
115  ui::KeyEvent evt(ui::ET_KEY_PRESSED,
116                   ui::VKEY_PROCESSKEY,
117                   ui::EF_IME_FABRICATED_KEY);
118  // Calls DispatchKeyEventPostIME() without a focused text input client.
119  if (switches::IsTextInputFocusManagerEnabled())
120    ui::TextInputFocusManager::GetInstance()->FocusTextInputClient(NULL);
121  else
122    input_method_event_filter_->input_method()->SetFocusedTextInputClient(NULL);
123  input_method_event_filter_->input_method()->DispatchKeyEvent(evt);
124  // Verifies 0 key event happened because InputMethodEventFilter::
125  // DispatchKeyEventPostIME() returns false.
126  EXPECT_EQ(0, test_filter_.num_key_events());
127
128  // Calls DispatchKeyEventPostIME() with a focused text input client.
129  if (switches::IsTextInputFocusManagerEnabled()) {
130    ui::TextInputFocusManager::GetInstance()->FocusTextInputClient(
131        test_input_client_.get());
132  } else {
133    input_method_event_filter_->input_method()->SetFocusedTextInputClient(
134        test_input_client_.get());
135  }
136  input_method_event_filter_->input_method()->DispatchKeyEvent(evt);
137  // Verifies 1 key event happened because InputMethodEventFilter::
138  // DispatchKeyEventPostIME() returns true.
139  EXPECT_EQ(1, test_filter_.num_key_events());
140}
141
142}  // namespace wm
143