1 // Copyright 2013 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.
8 #include "chrome/browser/chromeos/input_method/input_method_util.h"
9 #include "chrome/browser/chromeos/input_method/mode_indicator_controller.h"
10 #include "chrome/test/base/in_process_browser_test.h"
11 #include "content/public/test/browser_test_utils.h"
12 #include "content/public/test/test_utils.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "ui/base/ime/chromeos/component_extension_ime_manager.h"
15 #include "ui/base/ime/chromeos/extension_ime_util.h"
16 #include "ui/base/ime/chromeos/ime_bridge.h"
17 #include "ui/base/ime/chromeos/input_method_manager.h"
18 #include "ui/base/ime/chromeos/input_method_whitelist.h"
19 #include "ui/base/ime/input_method_factory.h"
20 #include "ui/views/widget/widget.h"
21 #include "ui/views/widget/widget_observer.h"
24 namespace input_method
{
26 class ScopedModeIndicatorObserverForTesting
:
27 public ModeIndicatorObserverInterface
{
29 ScopedModeIndicatorObserverForTesting()
30 : max_widget_list_size_(0) {
31 ModeIndicatorController::SetModeIndicatorObserverForTesting(this);
34 virtual ~ScopedModeIndicatorObserverForTesting() {
35 for (size_t i
= 0; i
< widget_list_
.size(); ++i
) {
36 widget_list_
[i
]->RemoveObserver(this);
38 ModeIndicatorController::SetModeIndicatorObserverForTesting(NULL
);
41 gfx::Rect
last_bounds() const {
45 bool is_displayed() const {
49 const std::vector
<views::Widget
*>& widget_list() const {
53 size_t widget_list_size() const {
54 return widget_list_
.size();
57 size_t max_widget_list_size() const {
58 return max_widget_list_size_
;
61 // ModeIndicatorObserverInterface override:
62 virtual void AddModeIndicatorWidget(views::Widget
* widget
) override
{
63 widget_list_
.push_back(widget
);
64 max_widget_list_size_
=
65 std::max(max_widget_list_size_
, widget_list_
.size());
66 widget
->AddObserver(this);
69 // views::WidgetObserver override:
70 virtual void OnWidgetDestroying(views::Widget
* widget
) override
{
71 std::vector
<views::Widget
*>::iterator it
=
72 std::find(widget_list_
.begin(), widget_list_
.end(), widget
);
73 if (it
!= widget_list_
.end())
74 widget_list_
.erase(it
);
77 // views::WidgetObserver override:
78 virtual void OnWidgetVisibilityChanged(views::Widget
* widget
,
79 bool visible
) override
{
80 last_bounds_
= widget
->GetWindowBoundsInScreen();
81 is_displayed_
|= visible
;
86 gfx::Rect last_bounds_
;
87 size_t max_widget_list_size_
;
88 std::vector
<views::Widget
*> widget_list_
;
91 class ModeIndicatorBrowserTest
: public InProcessBrowserTest
{
93 ModeIndicatorBrowserTest()
94 : InProcessBrowserTest() {}
95 virtual ~ModeIndicatorBrowserTest() {}
97 virtual void SetUpInProcessBrowserTestFixture() override
{
98 ui::SetUpInputMethodFactoryForTesting();
101 void InitializeIMF() {
102 InputMethodManager::Get()
103 ->GetInputMethodUtil()
104 ->InitXkbInputMethodsForTesting();
108 DISALLOW_COPY_AND_ASSIGN(ModeIndicatorBrowserTest
);
112 // 43 is the designed size of the inner contents.
113 // This value corresponds with kMinSize defined in
114 // mode_indicator_delegate_view.cc.
115 const int kInnerSize
= 43;
118 IN_PROC_BROWSER_TEST_F(ModeIndicatorBrowserTest
, Bounds
) {
121 InputMethodManager
* imm
= InputMethodManager::Get();
124 std::vector
<std::string
> keyboard_layouts
;
125 keyboard_layouts
.push_back(
126 extension_ime_util::GetInputMethodIDByEngineID("xkb:fr::fra"));
128 // Add keyboard layouts to enable the mode indicator.
129 imm
->GetActiveIMEState()->EnableLoginLayouts("fr", keyboard_layouts
);
130 ASSERT_LT(1UL, imm
->GetActiveIMEState()->GetNumActiveInputMethods());
131 EXPECT_TRUE(imm
->GetActiveIMEState()->CanCycleInputMethod());
133 chromeos::IMECandidateWindowHandlerInterface
* candidate_window
=
134 chromeos::IMEBridge::Get()->GetCandidateWindowHandler();
135 candidate_window
->FocusStateChanged(true);
137 // Check if the size of the mode indicator is expected.
138 gfx::Rect
cursor1_bounds(100, 100, 1, 20);
139 gfx::Rect mi1_bounds
;
141 ScopedModeIndicatorObserverForTesting observer
;
142 candidate_window
->SetCursorBounds(cursor1_bounds
, cursor1_bounds
);
143 imm
->GetActiveIMEState()->SwitchToNextInputMethod();
144 mi1_bounds
= observer
.last_bounds();
145 // The bounds should be bigger than the inner size.
146 EXPECT_LE(kInnerSize
, mi1_bounds
.width());
147 EXPECT_LE(kInnerSize
, mi1_bounds
.height());
148 EXPECT_TRUE(observer
.is_displayed());
151 // Check if the location of the mode indicator is coresponded to
152 // the cursor bounds.
153 gfx::Rect
cursor2_bounds(50, 200, 1, 20);
154 gfx::Rect mi2_bounds
;
156 ScopedModeIndicatorObserverForTesting observer
;
157 candidate_window
->SetCursorBounds(cursor2_bounds
, cursor2_bounds
);
158 imm
->GetActiveIMEState()->SwitchToNextInputMethod();
159 mi2_bounds
= observer
.last_bounds();
160 EXPECT_TRUE(observer
.is_displayed());
163 EXPECT_EQ(cursor1_bounds
.x() - cursor2_bounds
.x(),
164 mi1_bounds
.x() - mi2_bounds
.x());
165 EXPECT_EQ(cursor1_bounds
.y() - cursor2_bounds
.y(),
166 mi1_bounds
.y() - mi2_bounds
.y());
167 EXPECT_EQ(mi1_bounds
.width(), mi2_bounds
.width());
168 EXPECT_EQ(mi1_bounds
.height(), mi2_bounds
.height());
170 const gfx::Rect screen_bounds
=
171 ash::Shell::GetScreen()->GetDisplayMatching(cursor1_bounds
).work_area();
173 // Check if the location of the mode indicator is concidered with
175 const gfx::Rect
cursor3_bounds(100, screen_bounds
.bottom() - 25, 1, 20);
176 gfx::Rect mi3_bounds
;
178 ScopedModeIndicatorObserverForTesting observer
;
179 candidate_window
->SetCursorBounds(cursor3_bounds
, cursor3_bounds
);
180 imm
->GetActiveIMEState()->SwitchToNextInputMethod();
181 mi3_bounds
= observer
.last_bounds();
182 EXPECT_TRUE(observer
.is_displayed());
183 EXPECT_LT(mi3_bounds
.bottom(), screen_bounds
.bottom());
187 IN_PROC_BROWSER_TEST_F(ModeIndicatorBrowserTest
, NumOfWidgets
) {
190 InputMethodManager
* imm
= InputMethodManager::Get();
193 std::vector
<std::string
> keyboard_layouts
;
194 keyboard_layouts
.push_back(
195 extension_ime_util::GetInputMethodIDByEngineID("xkb:fr::fra"));
197 // Add keyboard layouts to enable the mode indicator.
198 imm
->GetActiveIMEState()->EnableLoginLayouts("fr", keyboard_layouts
);
199 ASSERT_LT(1UL, imm
->GetActiveIMEState()->GetNumActiveInputMethods());
200 EXPECT_TRUE(imm
->GetActiveIMEState()->CanCycleInputMethod());
202 chromeos::IMECandidateWindowHandlerInterface
* candidate_window
=
203 chromeos::IMEBridge::Get()->GetCandidateWindowHandler();
204 candidate_window
->FocusStateChanged(true);
207 ScopedModeIndicatorObserverForTesting observer
;
209 imm
->GetActiveIMEState()->SwitchToNextInputMethod();
210 EXPECT_EQ(1UL, observer
.max_widget_list_size());
211 const views::Widget
* widget1
= observer
.widget_list()[0];
213 imm
->GetActiveIMEState()->SwitchToNextInputMethod();
214 EXPECT_EQ(2UL, observer
.max_widget_list_size());
216 // When a new mode indicator is displayed, the previous one should be
218 content::RunAllPendingInMessageLoop();
219 EXPECT_EQ(1UL, observer
.widget_list_size());
220 const views::Widget
* widget2
= observer
.widget_list()[0];
221 EXPECT_NE(widget1
, widget2
);
224 } // namespace input_method
225 } // namespace chromeos