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/mode_indicator_controller.h"
9 #include "chrome/test/base/in_process_browser_test.h"
10 #include "chromeos/ime/component_extension_ime_manager.h"
11 #include "chromeos/ime/input_method_manager.h"
12 #include "content/public/test/browser_test_utils.h"
13 #include "content/public/test/test_utils.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "ui/base/ime/chromeos/ibus_bridge.h"
16 #include "ui/base/ime/input_method_factory.h"
17 #include "ui/views/widget/widget.h"
18 #include "ui/views/widget/widget_observer.h"
21 namespace input_method
{
23 class ScopedModeIndicatorObserverForTesting
:
24 public ModeIndicatorObserverInterface
{
26 ScopedModeIndicatorObserverForTesting()
27 : max_widget_list_size_(0) {
28 ModeIndicatorController::SetModeIndicatorObserverForTesting(this);
31 virtual ~ScopedModeIndicatorObserverForTesting() {
32 for (size_t i
= 0; i
< widget_list_
.size(); ++i
) {
33 widget_list_
[i
]->RemoveObserver(this);
35 ModeIndicatorController::SetModeIndicatorObserverForTesting(NULL
);
38 gfx::Rect
last_bounds() const {
42 bool is_displayed() const {
46 const std::vector
<views::Widget
*>& widget_list() const {
50 size_t widget_list_size() const {
51 return widget_list_
.size();
54 size_t max_widget_list_size() const {
55 return max_widget_list_size_
;
58 // ModeIndicatorObserverInterface override:
59 virtual void AddModeIndicatorWidget(views::Widget
* widget
) OVERRIDE
{
60 widget_list_
.push_back(widget
);
61 max_widget_list_size_
=
62 std::max(max_widget_list_size_
, widget_list_
.size());
63 widget
->AddObserver(this);
66 // views::WidgetObserver override:
67 virtual void OnWidgetDestroying(views::Widget
* widget
) OVERRIDE
{
68 std::vector
<views::Widget
*>::iterator it
=
69 std::find(widget_list_
.begin(), widget_list_
.end(), widget
);
70 if (it
!= widget_list_
.end())
71 widget_list_
.erase(it
);
74 // views::WidgetObserver override:
75 virtual void OnWidgetVisibilityChanged(views::Widget
* widget
,
76 bool visible
) OVERRIDE
{
77 last_bounds_
= widget
->GetWindowBoundsInScreen();
78 is_displayed_
|= visible
;
83 gfx::Rect last_bounds_
;
84 size_t max_widget_list_size_
;
85 std::vector
<views::Widget
*> widget_list_
;
88 class ModeIndicatorBrowserTest
: public InProcessBrowserTest
{
90 ModeIndicatorBrowserTest()
91 : InProcessBrowserTest() {}
92 virtual ~ModeIndicatorBrowserTest() {}
94 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE
{
95 ui::SetUpInputMethodFactoryForTesting();
98 void InitializeIMF() {
99 // Make sure ComponentExtensionIMEManager is initialized.
100 // ComponentExtensionIMEManagerImpl::InitializeAsync posts
101 // ReadComponentExtensionsInfo to the FILE thread for the
102 // initialization. If it is never initialized for some reasons,
103 // the test is timed out and failed.
104 ComponentExtensionIMEManager
* ceimm
=
105 InputMethodManager::Get()->GetComponentExtensionIMEManager();
106 while (!ceimm
->IsInitialized()) {
107 content::RunAllPendingInMessageLoop(content::BrowserThread::FILE);
112 DISALLOW_COPY_AND_ASSIGN(ModeIndicatorBrowserTest
);
116 // 43 is the designed size of the inner contents.
117 // This value corresponds with kMinSize defined in
118 // mode_indicator_delegate_view.cc.
119 const int kInnerSize
= 43;
122 IN_PROC_BROWSER_TEST_F(ModeIndicatorBrowserTest
, Bounds
) {
125 InputMethodManager
* imm
= InputMethodManager::Get();
128 // Add keyboard layouts to enable the mode indicator.
129 imm
->EnableLayouts("fr", "xkb:fr::fra");
130 ASSERT_LT(1UL, imm
->GetNumActiveInputMethods());
132 chromeos::IBusPanelCandidateWindowHandlerInterface
* candidate_window
=
133 chromeos::IBusBridge::Get()->GetCandidateWindowHandler();
134 candidate_window
->FocusStateChanged(true);
136 // Check if the size of the mode indicator is expected.
137 gfx::Rect
cursor1_bounds(100, 100, 1, 20);
138 gfx::Rect mi1_bounds
;
140 ScopedModeIndicatorObserverForTesting observer
;
141 candidate_window
->SetCursorBounds(cursor1_bounds
, cursor1_bounds
);
142 EXPECT_TRUE(imm
->SwitchToNextInputMethod());
143 mi1_bounds
= observer
.last_bounds();
144 // The bounds should be bigger than the inner size.
145 EXPECT_LE(kInnerSize
, mi1_bounds
.width());
146 EXPECT_LE(kInnerSize
, mi1_bounds
.height());
147 EXPECT_TRUE(observer
.is_displayed());
150 // Check if the location of the mode indicator is coresponded to
151 // the cursor bounds.
152 gfx::Rect
cursor2_bounds(50, 200, 1, 20);
153 gfx::Rect mi2_bounds
;
155 ScopedModeIndicatorObserverForTesting observer
;
156 candidate_window
->SetCursorBounds(cursor2_bounds
, cursor2_bounds
);
157 EXPECT_TRUE(imm
->SwitchToNextInputMethod());
158 mi2_bounds
= observer
.last_bounds();
159 EXPECT_TRUE(observer
.is_displayed());
162 EXPECT_EQ(cursor1_bounds
.x() - cursor2_bounds
.x(),
163 mi1_bounds
.x() - mi2_bounds
.x());
164 EXPECT_EQ(cursor1_bounds
.y() - cursor2_bounds
.y(),
165 mi1_bounds
.y() - mi2_bounds
.y());
166 EXPECT_EQ(mi1_bounds
.width(), mi2_bounds
.width());
167 EXPECT_EQ(mi1_bounds
.height(), mi2_bounds
.height());
169 const gfx::Rect screen_bounds
=
170 ash::Shell::GetScreen()->GetDisplayMatching(cursor1_bounds
).work_area();
172 // Check if the location of the mode indicator is concidered with
174 const gfx::Rect
cursor3_bounds(100, screen_bounds
.bottom() - 25, 1, 20);
175 gfx::Rect mi3_bounds
;
177 ScopedModeIndicatorObserverForTesting observer
;
178 candidate_window
->SetCursorBounds(cursor3_bounds
, cursor3_bounds
);
179 EXPECT_TRUE(imm
->SwitchToNextInputMethod());
180 mi3_bounds
= observer
.last_bounds();
181 EXPECT_TRUE(observer
.is_displayed());
182 EXPECT_LT(mi3_bounds
.bottom(), screen_bounds
.bottom());
186 IN_PROC_BROWSER_TEST_F(ModeIndicatorBrowserTest
, NumOfWidgets
) {
189 InputMethodManager
* imm
= InputMethodManager::Get();
192 // Add keyboard layouts to enable the mode indicator.
193 imm
->EnableLayouts("fr", "xkb:fr::fra");
194 ASSERT_LT(1UL, imm
->GetNumActiveInputMethods());
196 chromeos::IBusPanelCandidateWindowHandlerInterface
* candidate_window
=
197 chromeos::IBusBridge::Get()->GetCandidateWindowHandler();
198 candidate_window
->FocusStateChanged(true);
201 ScopedModeIndicatorObserverForTesting observer
;
203 EXPECT_TRUE(imm
->SwitchToNextInputMethod());
204 EXPECT_EQ(1UL, observer
.max_widget_list_size());
205 const views::Widget
* widget1
= observer
.widget_list()[0];
207 EXPECT_TRUE(imm
->SwitchToNextInputMethod());
208 EXPECT_EQ(2UL, observer
.max_widget_list_size());
210 // When a new mode indicator is displayed, the previous one should be
212 content::RunAllPendingInMessageLoop();
213 EXPECT_EQ(1UL, observer
.widget_list_size());
214 const views::Widget
* widget2
= observer
.widget_list()[0];
215 EXPECT_NE(widget1
, widget2
);
218 } // namespace input_method
219 } // namespace chromeos