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