- add sources.
[platform/framework/web/crosswalk.git] / src / ui / views / focus / focus_manager_unittest_win.cc
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/views/focus/focus_manager.h"
6
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"
15
16 namespace views {
17
18 namespace {
19
20 class MessageTrackingView : public View {
21  public:
22   MessageTrackingView() : accelerator_pressed_(false) {
23   }
24
25   void Reset() {
26     accelerator_pressed_ = false;
27     keys_pressed_.clear();
28     keys_released_.clear();
29   }
30
31   const std::vector<ui::KeyboardCode>& keys_pressed() const {
32     return keys_pressed_;
33   }
34
35   const std::vector<ui::KeyboardCode>& keys_released() const {
36     return keys_released_;
37   }
38
39   bool accelerator_pressed() const {
40     return accelerator_pressed_;
41   }
42
43   // Overridden from View:
44   virtual bool OnKeyPressed(const ui::KeyEvent& e) OVERRIDE {
45     keys_pressed_.push_back(e.key_code());
46     return true;
47   }
48   virtual bool OnKeyReleased(const ui::KeyEvent& e) OVERRIDE {
49     keys_released_.push_back(e.key_code());
50     return true;
51   }
52   virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE {
53     accelerator_pressed_ = true;
54     return true;
55   }
56
57  private:
58   bool accelerator_pressed_;
59   std::vector<ui::KeyboardCode> keys_pressed_;
60   std::vector<ui::KeyboardCode> keys_released_;
61
62   DISALLOW_COPY_AND_ASSIGN(MessageTrackingView);
63 };
64
65 }  // namespace
66
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();
72
73   LabelButton* button = new LabelButton(NULL, ASCIIToUTF16("Press me"));
74   button->SetStyle(Button::STYLE_NATIVE_TEXTBUTTON);
75   View* view = new View();
76   view->set_focusable(true);
77
78   GetContentsView()->AddChildView(button);
79   button->SetBounds(10, 10, 200, 30);
80   GetContentsView()->AddChildView(view);
81   RunPendingMessages();
82
83   TestFocusChangeListener listener;
84   AddFocusChangeListener(&listener);
85
86   view->RequestFocus();
87   RunPendingMessages();
88
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;
91
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();
99
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();
106
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();
115
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();
121
122   /*
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);
130
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));
135   */
136 }
137
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);
149
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);
155
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);
164
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);
169
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);
175
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);
179
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);
185
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);
190
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);
195
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);
200
201   DestroyWindow(hwnd);
202 }
203
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);
215
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();
229
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();
254
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();
264
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();
279 }
280
281 }  // namespace views