Roll icu to 241739 and drop a version from icudt*dat
[chromium-blink-merge.git] / ui / views / focus / focus_manager_unittest_win.cc
blob267a8b78df3c1ca8ee2d25fd37adb0fc9a7c979e
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.
5 #include "ui/views/focus/focus_manager.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/run_loop.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "ui/events/event.h"
11 #include "ui/views/controls/button/label_button.h"
12 #include "ui/views/focus/accelerator_handler.h"
13 #include "ui/views/focus/focus_manager_test.h"
14 #include "ui/views/widget/widget.h"
16 namespace views {
18 namespace {
20 class MessageTrackingView : public View {
21 public:
22 MessageTrackingView() : accelerator_pressed_(false) {
25 void Reset() {
26 accelerator_pressed_ = false;
27 keys_pressed_.clear();
28 keys_released_.clear();
31 const std::vector<ui::KeyboardCode>& keys_pressed() const {
32 return keys_pressed_;
35 const std::vector<ui::KeyboardCode>& keys_released() const {
36 return keys_released_;
39 bool accelerator_pressed() const {
40 return accelerator_pressed_;
43 // Overridden from View:
44 virtual bool OnKeyPressed(const ui::KeyEvent& e) OVERRIDE {
45 keys_pressed_.push_back(e.key_code());
46 return true;
48 virtual bool OnKeyReleased(const ui::KeyEvent& e) OVERRIDE {
49 keys_released_.push_back(e.key_code());
50 return true;
52 virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE {
53 accelerator_pressed_ = true;
54 return true;
57 private:
58 bool accelerator_pressed_;
59 std::vector<ui::KeyboardCode> keys_pressed_;
60 std::vector<ui::KeyboardCode> keys_released_;
62 DISALLOW_COPY_AND_ASSIGN(MessageTrackingView);
65 } // namespace
67 // Test that when activating/deactivating the top window, the focus is stored/
68 // restored properly.
69 TEST_F(FocusManagerTest, FocusStoreRestore) {
70 // Simulate an activate, otherwise the deactivate isn't going to do anything.
71 SimulateActivateWindow();
73 LabelButton* button = new LabelButton(NULL, ASCIIToUTF16("Press me"));
74 button->SetStyle(Button::STYLE_NATIVE_TEXTBUTTON);
75 View* view = new View();
76 view->SetFocusable(true);
78 GetContentsView()->AddChildView(button);
79 button->SetBounds(10, 10, 200, 30);
80 GetContentsView()->AddChildView(view);
81 RunPendingMessages();
83 TestFocusChangeListener listener;
84 AddFocusChangeListener(&listener);
86 view->RequestFocus();
87 RunPendingMessages();
89 // Required for VS2010: http://connect.microsoft.com/VisualStudio/feedback/details/520043/error-converting-from-null-to-a-pointer-type-in-std-pair
90 views::View* null_view = NULL;
92 // Deacivate the window, it should store its focus.
93 SimulateDeactivateWindow();
94 EXPECT_EQ(NULL, GetFocusManager()->GetFocusedView());
95 ASSERT_EQ(2, static_cast<int>(listener.focus_changes().size()));
96 EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, view));
97 EXPECT_TRUE(listener.focus_changes()[1] == ViewPair(view, null_view));
98 listener.ClearFocusChanges();
100 // Reactivate, focus should come-back to the previously focused view.
101 SimulateActivateWindow();
102 EXPECT_EQ(view, GetFocusManager()->GetFocusedView());
103 ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size()));
104 EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, view));
105 listener.ClearFocusChanges();
107 // Same test with a NativeControl.
108 button->RequestFocus();
109 SimulateDeactivateWindow();
110 EXPECT_EQ(NULL, GetFocusManager()->GetFocusedView());
111 ASSERT_EQ(2, static_cast<int>(listener.focus_changes().size()));
112 EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(view, button));
113 EXPECT_TRUE(listener.focus_changes()[1] == ViewPair(button, null_view));
114 listener.ClearFocusChanges();
116 SimulateActivateWindow();
117 EXPECT_EQ(button, GetFocusManager()->GetFocusedView());
118 ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size()));
119 EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, button));
120 listener.ClearFocusChanges();
123 // Now test that while the window is inactive we can change the focused view
124 // (we do that in several places).
125 SimulateDeactivateWindow();
126 // TODO: would have to mock the window being inactive (with a TestWidgetWin
127 // that would return false on IsActive()).
128 GetFocusManager()->SetFocusedView(view);
129 ::SendMessage(window_->GetNativeWindow(), WM_ACTIVATE, WA_ACTIVE, NULL);
131 EXPECT_EQ(view, GetFocusManager()->GetFocusedView());
132 ASSERT_EQ(2, static_cast<int>(listener.focus_changes().size()));
133 EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(button, null_view));
134 EXPECT_TRUE(listener.focus_changes()[1] == ViewPair(null_view, view));
138 // Test that the focus manager is created successfully for the first view
139 // window parented to a native dialog.
140 TEST_F(FocusManagerTest, CreationForNativeRoot) {
141 // Create a window class.
142 WNDCLASSEX class_ex;
143 memset(&class_ex, 0, sizeof(class_ex));
144 class_ex.cbSize = sizeof(WNDCLASSEX);
145 class_ex.lpfnWndProc = &DefWindowProc;
146 class_ex.lpszClassName = L"TestWindow";
147 ATOM atom = RegisterClassEx(&class_ex);
148 ASSERT_TRUE(atom);
150 // Create a native dialog window.
151 HWND hwnd = CreateWindowEx(0, class_ex.lpszClassName, NULL,
152 WS_OVERLAPPEDWINDOW, 0, 0, 200, 200,
153 NULL, NULL, NULL, NULL);
154 ASSERT_TRUE(hwnd);
156 // Create a view window parented to native dialog.
157 scoped_ptr<Widget> widget1(new Widget);
158 Widget::InitParams params(Widget::InitParams::TYPE_CONTROL);
159 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
160 params.parent = hwnd;
161 params.bounds = gfx::Rect(0, 0, 100, 100);
162 params.top_level = true; // This is top level in views hierarchy.
163 widget1->Init(params);
165 // Get the focus manager directly from the first window. Should exist
166 // because the first window is the root widget.
167 views::FocusManager* focus_manager1 = widget1->GetFocusManager();
168 EXPECT_TRUE(focus_manager1);
170 // Create another view window parented to the first view window.
171 scoped_ptr<Widget> widget2(new Widget);
172 params.parent = widget1->GetNativeView();
173 params.top_level = false; // This is child widget.
174 widget2->Init(params);
176 // Access the shared focus manager directly from the second window.
177 views::FocusManager* focus_manager2 = widget2->GetFocusManager();
178 EXPECT_EQ(focus_manager2, focus_manager1);
180 // Access the shared focus manager indirectly from the first window handle.
181 gfx::NativeWindow native_window = widget1->GetNativeWindow();
182 views::Widget* widget =
183 views::Widget::GetWidgetForNativeWindow(native_window);
184 EXPECT_EQ(widget->GetFocusManager(), focus_manager1);
186 // Access the shared focus manager indirectly from the second window handle.
187 native_window = widget2->GetNativeWindow();
188 widget = views::Widget::GetWidgetForNativeWindow(native_window);
189 EXPECT_EQ(widget->GetFocusManager(), focus_manager1);
191 // Access the shared focus manager indirectly from the first view handle.
192 gfx::NativeView native_view = widget1->GetNativeView();
193 widget = views::Widget::GetTopLevelWidgetForNativeView(native_view);
194 EXPECT_EQ(widget->GetFocusManager(), focus_manager1);
196 // Access the shared focus manager indirectly from the second view handle.
197 native_view = widget2->GetNativeView();
198 widget = views::Widget::GetTopLevelWidgetForNativeView(native_view);
199 EXPECT_EQ(widget->GetFocusManager(), focus_manager1);
201 DestroyWindow(hwnd);
204 // Tests that the keyup messages are eaten for accelerators.
205 // Windows-only, Windows is the only platform that handles accelerators in
206 // AcceleratorHandler. NativeWidgetAura::OnKeyEvent handles them in other
207 // configurations.
208 TEST_F(FocusManagerTest, IgnoreKeyupForAccelerators) {
209 FocusManager* focus_manager = GetFocusManager();
210 MessageTrackingView* mtv = new MessageTrackingView();
211 mtv->AddAccelerator(ui::Accelerator(ui::VKEY_0, ui::EF_NONE));
212 mtv->AddAccelerator(ui::Accelerator(ui::VKEY_1, ui::EF_NONE));
213 GetContentsView()->AddChildView(mtv);
214 focus_manager->SetFocusedView(mtv);
216 // First send a non-accelerator key sequence.
217 PostKeyDown(ui::VKEY_9);
218 PostKeyUp(ui::VKEY_9);
219 AcceleratorHandler accelerator_handler;
220 scoped_ptr<base::RunLoop> run_loop(new base::RunLoop(&accelerator_handler));
221 run_loop->RunUntilIdle();
222 // Make sure we get a key-up and key-down.
223 ASSERT_EQ(1U, mtv->keys_pressed().size());
224 EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[0]);
225 ASSERT_EQ(1U, mtv->keys_released().size());
226 EXPECT_EQ(ui::VKEY_9, mtv->keys_released()[0]);
227 EXPECT_FALSE(mtv->accelerator_pressed());
228 mtv->Reset();
230 // Same thing with repeat and more than one key at once.
231 PostKeyDown(ui::VKEY_9);
232 PostKeyDown(ui::VKEY_9);
233 PostKeyDown(ui::VKEY_8);
234 PostKeyDown(ui::VKEY_9);
235 PostKeyDown(ui::VKEY_7);
236 PostKeyUp(ui::VKEY_9);
237 PostKeyUp(ui::VKEY_7);
238 PostKeyUp(ui::VKEY_8);
239 run_loop.reset(new base::RunLoop(&accelerator_handler));
240 run_loop->RunUntilIdle();
241 // Make sure we get a key-up and key-down.
242 ASSERT_EQ(5U, mtv->keys_pressed().size());
243 EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[0]);
244 EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[1]);
245 EXPECT_EQ(ui::VKEY_8, mtv->keys_pressed()[2]);
246 EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[3]);
247 EXPECT_EQ(ui::VKEY_7, mtv->keys_pressed()[4]);
248 ASSERT_EQ(3U, mtv->keys_released().size());
249 EXPECT_EQ(ui::VKEY_9, mtv->keys_released()[0]);
250 EXPECT_EQ(ui::VKEY_7, mtv->keys_released()[1]);
251 EXPECT_EQ(ui::VKEY_8, mtv->keys_released()[2]);
252 EXPECT_FALSE(mtv->accelerator_pressed());
253 mtv->Reset();
255 // Now send an accelerator key sequence.
256 PostKeyDown(ui::VKEY_0);
257 PostKeyUp(ui::VKEY_0);
258 run_loop.reset(new base::RunLoop(&accelerator_handler));
259 run_loop->RunUntilIdle();
260 EXPECT_TRUE(mtv->keys_pressed().empty());
261 EXPECT_TRUE(mtv->keys_released().empty());
262 EXPECT_TRUE(mtv->accelerator_pressed());
263 mtv->Reset();
265 // Same thing with repeat and more than one key at once.
266 PostKeyDown(ui::VKEY_0);
267 PostKeyDown(ui::VKEY_1);
268 PostKeyDown(ui::VKEY_1);
269 PostKeyDown(ui::VKEY_0);
270 PostKeyDown(ui::VKEY_0);
271 PostKeyUp(ui::VKEY_1);
272 PostKeyUp(ui::VKEY_0);
273 run_loop.reset(new base::RunLoop(&accelerator_handler));
274 run_loop->RunUntilIdle();
275 EXPECT_TRUE(mtv->keys_pressed().empty());
276 EXPECT_TRUE(mtv->keys_released().empty());
277 EXPECT_TRUE(mtv->accelerator_pressed());
278 mtv->Reset();
281 } // namespace views