OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/basictypes.h" | 5 #include "base/basictypes.h" |
6 #include "base/bind.h" | 6 #include "base/bind.h" |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/path_service.h" | 8 #include "base/path_service.h" |
9 #include "base/run_loop.h" | 9 #include "base/run_loop.h" |
10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
12 #include "ui/aura/window.h" | |
13 #include "ui/aura/window_tree_host.h" | |
14 #include "ui/base/ime/input_method.h" | 12 #include "ui/base/ime/input_method.h" |
15 #include "ui/base/ime/text_input_client.h" | 13 #include "ui/base/ime/text_input_client.h" |
16 #include "ui/base/resource/resource_bundle.h" | 14 #include "ui/base/resource/resource_bundle.h" |
17 #include "ui/base/ui_base_paths.h" | 15 #include "ui/base/ui_base_paths.h" |
18 #include "ui/base/ui_base_switches.h" | 16 #include "ui/base/ui_base_switches.h" |
19 #include "ui/events/event_processor.h" | 17 #include "ui/events/event_processor.h" |
20 #include "ui/events/event_utils.h" | 18 #include "ui/events/event_utils.h" |
21 #include "ui/events/test/event_generator.h" | 19 #include "ui/events/test/event_generator.h" |
22 #include "ui/gfx/native_widget_types.h" | 20 #include "ui/gfx/native_widget_types.h" |
23 #include "ui/gl/gl_surface.h" | 21 #include "ui/gl/gl_surface.h" |
24 #include "ui/views/controls/textfield/textfield.h" | 22 #include "ui/views/controls/textfield/textfield.h" |
25 #include "ui/views/controls/textfield/textfield_test_api.h" | 23 #include "ui/views/controls/textfield/textfield_test_api.h" |
26 #include "ui/views/focus/focus_manager.h" | 24 #include "ui/views/focus/focus_manager.h" |
27 #include "ui/views/ime/input_method.h" | 25 #include "ui/views/ime/input_method.h" |
28 #include "ui/views/test/focus_manager_test.h" | 26 #include "ui/views/test/focus_manager_test.h" |
29 #include "ui/views/test/widget_test.h" | 27 #include "ui/views/test/widget_test.h" |
30 #include "ui/views/touchui/touch_selection_controller_impl.h" | 28 #include "ui/views/touchui/touch_selection_controller_impl.h" |
31 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" | |
32 #include "ui/views/widget/widget.h" | 29 #include "ui/views/widget/widget.h" |
33 #include "ui/views/window/dialog_delegate.h" | 30 #include "ui/views/window/dialog_delegate.h" |
34 #include "ui/wm/public/activation_client.h" | 31 #include "ui/wm/public/activation_client.h" |
35 | 32 |
36 #if defined(OS_WIN) | 33 #if defined(OS_WIN) |
| 34 #include "ui/aura/window.h" |
| 35 #include "ui/aura/window_tree_host.h" |
| 36 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" |
37 #include "ui/views/win/hwnd_util.h" | 37 #include "ui/views/win/hwnd_util.h" |
38 #elif defined(USE_X11) | |
39 #include "ui/base/x/x11_util.h" | |
40 #include "ui/views/test/x11_property_change_waiter.h" | |
41 #endif | 38 #endif |
42 | 39 |
43 namespace views { | 40 namespace views { |
44 namespace test { | 41 namespace test { |
45 | 42 |
46 namespace { | 43 namespace { |
47 | 44 |
48 // A View that closes the Widget and exits the current message-loop when it | 45 // A View that closes the Widget and exits the current message-loop when it |
49 // receives a mouse-release event. | 46 // receives a mouse-release event. |
50 class ExitLoopOnRelease : public View { | 47 class ExitLoopOnRelease : public View { |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 | 147 |
151 Widget* widget_; | 148 Widget* widget_; |
152 | 149 |
153 DISALLOW_COPY_AND_ASSIGN(NestedLoopCaptureView); | 150 DISALLOW_COPY_AND_ASSIGN(NestedLoopCaptureView); |
154 }; | 151 }; |
155 | 152 |
156 // Spins a run loop until a Widget's active state matches a desired state. | 153 // Spins a run loop until a Widget's active state matches a desired state. |
157 class WidgetActivationWaiter : public WidgetObserver { | 154 class WidgetActivationWaiter : public WidgetObserver { |
158 public: | 155 public: |
159 WidgetActivationWaiter(Widget* widget, bool active) : observed_(false) { | 156 WidgetActivationWaiter(Widget* widget, bool active) : observed_(false) { |
| 157 #if defined(OS_WIN) |
| 158 // On Windows, a HWND can receive a WM_ACTIVATE message without the value |
| 159 // of ::GetActiveWindow() updating to reflect that change. This can cause |
| 160 // the active window reported by IsActive() to get out of sync. Usually this |
| 161 // happens after a call to HWNDMessageHandler::Deactivate() which works by |
| 162 // activating some other window, which might be in another application. |
| 163 // Doing this can trigger the native OS activation-blocker, causing the |
| 164 // taskbar icon to flash instead. But since activation of native widgets on |
| 165 // Windows is synchronous, we never have to wait anyway, so it's safe to |
| 166 // return here. |
| 167 if (active == widget->IsActive()) { |
| 168 observed_ = true; |
| 169 return; |
| 170 } |
| 171 #endif |
160 // Always expect a change for tests using this. | 172 // Always expect a change for tests using this. |
161 EXPECT_NE(active, widget->IsActive()); | 173 EXPECT_NE(active, widget->IsActive()); |
162 widget->AddObserver(this); | 174 widget->AddObserver(this); |
163 } | 175 } |
164 | 176 |
165 void Wait() { | 177 void Wait() { |
166 if (!observed_) | 178 if (!observed_) |
167 run_loop_.Run(); | 179 run_loop_.Run(); |
168 } | 180 } |
169 | 181 |
170 void OnWidgetActivationChanged(Widget* widget, bool active) override { | 182 void OnWidgetActivationChanged(Widget* widget, bool active) override { |
171 observed_ = true; | 183 observed_ = true; |
172 widget->RemoveObserver(this); | 184 widget->RemoveObserver(this); |
173 if (run_loop_.running()) | 185 if (run_loop_.running()) |
174 run_loop_.Quit(); | 186 run_loop_.Quit(); |
175 } | 187 } |
176 | 188 |
177 private: | 189 private: |
178 base::RunLoop run_loop_; | 190 base::RunLoop run_loop_; |
179 bool observed_; | 191 bool observed_; |
180 | 192 |
181 DISALLOW_COPY_AND_ASSIGN(WidgetActivationWaiter); | 193 DISALLOW_COPY_AND_ASSIGN(WidgetActivationWaiter); |
182 }; | 194 }; |
183 | 195 |
184 #if defined(USE_X11) | |
185 class WidgetActivationWaiterX11 : public X11PropertyChangeWaiter { | |
186 public: | |
187 explicit WidgetActivationWaiterX11(Widget* widget, bool active) | |
188 : X11PropertyChangeWaiter(ui::GetX11RootWindow(), "_NET_ACTIVE_WINDOW"), | |
189 window_(widget->GetNativeWindow()->GetHost()->GetAcceleratedWidget()) { | |
190 EXPECT_NE(active, widget->IsActive()); | |
191 } | |
192 | |
193 ~WidgetActivationWaiterX11() override {} | |
194 | |
195 private: | |
196 // X11PropertyChangeWaiter: | |
197 bool ShouldKeepOnWaiting(const ui::PlatformEvent& event) override { | |
198 XID xid = 0; | |
199 ui::GetXIDProperty(ui::GetX11RootWindow(), "_NET_ACTIVE_WINDOW", &xid); | |
200 return xid != window_; | |
201 } | |
202 | |
203 XID window_; | |
204 | |
205 DISALLOW_COPY_AND_ASSIGN(WidgetActivationWaiterX11); | |
206 }; | |
207 #endif | |
208 | |
209 ui::WindowShowState GetWidgetShowState(const Widget* widget) { | 196 ui::WindowShowState GetWidgetShowState(const Widget* widget) { |
210 // Use IsMaximized/IsMinimized/IsFullScreen instead of GetWindowPlacement | 197 // Use IsMaximized/IsMinimized/IsFullScreen instead of GetWindowPlacement |
211 // because the former is implemented on all platforms but the latter is not. | 198 // because the former is implemented on all platforms but the latter is not. |
212 return widget->IsFullscreen() ? ui::SHOW_STATE_FULLSCREEN : | 199 return widget->IsFullscreen() ? ui::SHOW_STATE_FULLSCREEN : |
213 widget->IsMaximized() ? ui::SHOW_STATE_MAXIMIZED : | 200 widget->IsMaximized() ? ui::SHOW_STATE_MAXIMIZED : |
214 widget->IsMinimized() ? ui::SHOW_STATE_MINIMIZED : | 201 widget->IsMinimized() ? ui::SHOW_STATE_MINIMIZED : |
215 widget->IsActive() ? ui::SHOW_STATE_NORMAL : | 202 widget->IsActive() ? ui::SHOW_STATE_NORMAL : |
216 ui::SHOW_STATE_INACTIVE; | 203 ui::SHOW_STATE_INACTIVE; |
217 } | 204 } |
218 | 205 |
(...skipping 19 matching lines...) Expand all Loading... |
238 } | 225 } |
239 | 226 |
240 // Like for ActivateSync(), wait for a widget to become active, but Show() the | 227 // Like for ActivateSync(), wait for a widget to become active, but Show() the |
241 // widget rather than calling Activate(). | 228 // widget rather than calling Activate(). |
242 void ShowSync(Widget* widget) { | 229 void ShowSync(Widget* widget) { |
243 WidgetActivationWaiter waiter(widget, true); | 230 WidgetActivationWaiter waiter(widget, true); |
244 widget->Show(); | 231 widget->Show(); |
245 waiter.Wait(); | 232 waiter.Wait(); |
246 } | 233 } |
247 | 234 |
248 #if defined(USE_AURA) | 235 void DeactivateSync(Widget* widget) { |
249 void ActivatePlatformWindowSync(Widget* widget) { | 236 #if defined(OS_MACOSX) |
| 237 // Deactivation of a window isn't a concept on Mac: If an application is |
| 238 // active and it has any activatable windows, then one of them is always |
| 239 // active. But we can simulate deactivation (e.g. as if another application |
| 240 // became active) by temporarily making |widget| non-activatable, then |
| 241 // activating (and closing) a temporary widget. |
| 242 widget->widget_delegate()->set_can_activate(false); |
| 243 Widget* stealer = new Widget; |
| 244 stealer->Init(Widget::InitParams(Widget::InitParams::TYPE_WINDOW)); |
| 245 ShowSync(stealer); |
| 246 stealer->CloseNow(); |
| 247 widget->widget_delegate()->set_can_activate(true); |
| 248 #else |
| 249 WidgetActivationWaiter waiter(widget, false); |
| 250 widget->Deactivate(); |
| 251 waiter.Wait(); |
| 252 #endif |
| 253 } |
| 254 |
250 #if defined(OS_WIN) | 255 #if defined(OS_WIN) |
| 256 void ActivatePlatformWindow(Widget* widget) { |
251 ::SetActiveWindow( | 257 ::SetActiveWindow( |
252 widget->GetNativeWindow()->GetHost()->GetAcceleratedWidget()); | 258 widget->GetNativeWindow()->GetHost()->GetAcceleratedWidget()); |
253 #elif defined(OS_CHROMEOS) | |
254 widget->Activate(); | |
255 #elif defined(USE_X11) | |
256 if (!widget->IsActive()) { | |
257 WidgetActivationWaiterX11 waiter(widget, true); | |
258 widget->Activate(); | |
259 waiter.Wait(); | |
260 } | |
261 #else | |
262 ActivateSync(widget); | |
263 #endif | |
264 } | 259 } |
265 #endif | 260 #endif |
266 | 261 |
267 // Calls ShowInactive() on a Widget, and spins a run loop. The goal is to give | 262 // Calls ShowInactive() on a Widget, and spins a run loop. The goal is to give |
268 // the OS a chance to activate a widget. However, for this case, the test | 263 // the OS a chance to activate a widget. However, for this case, the test |
269 // doesn't expect that to happen, so there is nothing to wait for. | 264 // doesn't expect that to happen, so there is nothing to wait for. |
270 void ShowInactiveSync(Widget* widget) { | 265 void ShowInactiveSync(Widget* widget) { |
271 widget->ShowInactive(); | 266 widget->ShowInactive(); |
272 RunPendingMessagesForActiveStatusChange(); | 267 RunPendingMessagesForActiveStatusChange(); |
273 } | 268 } |
(...skipping 25 matching lines...) Expand all Loading... |
299 controller->ContextMenuTimerFired(); | 294 controller->ContextMenuTimerFired(); |
300 #endif | 295 #endif |
301 } | 296 } |
302 } | 297 } |
303 | 298 |
304 static bool IsQuickMenuVisible(TouchSelectionControllerImpl* controller) { | 299 static bool IsQuickMenuVisible(TouchSelectionControllerImpl* controller) { |
305 DCHECK(controller); | 300 DCHECK(controller); |
306 return controller->context_menu_ && controller->context_menu_->visible(); | 301 return controller->context_menu_ && controller->context_menu_->visible(); |
307 } | 302 } |
308 | 303 |
309 scoped_ptr<Widget> CreateWidget() { | 304 Widget* CreateWidget() { |
310 #if !defined(USE_AURA) | 305 Widget* widget = CreateNativeDesktopWidget(); |
311 return NULL; | 306 widget->SetBounds(gfx::Rect(0, 0, 200, 200)); |
312 #else | 307 return widget; |
313 scoped_ptr<Widget> widget(new Widget); | |
314 Widget::InitParams params = | |
315 CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS); | |
316 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
317 params.bounds = gfx::Rect(0, 0, 200, 200); | |
318 #if defined(OS_CHROMEOS) | |
319 params.native_widget = NULL; | |
320 #else | |
321 params.native_widget = new DesktopNativeWidgetAura(widget.get()); | |
322 #endif | |
323 widget->Init(params); | |
324 return widget.Pass(); | |
325 #endif | |
326 } | 308 } |
327 }; | 309 }; |
328 | 310 |
329 #if defined(OS_WIN) | 311 #if defined(OS_WIN) |
330 // Tests whether activation and focus change works correctly in Windows. | 312 // Tests whether activation and focus change works correctly in Windows. |
331 // We test the following:- | 313 // We test the following:- |
332 // 1. If the active aura window is correctly set when a top level widget is | 314 // 1. If the active aura window is correctly set when a top level widget is |
333 // created. | 315 // created. |
334 // 2. If the active aura window in widget 1 created above, is set to NULL when | 316 // 2. If the active aura window in widget 1 created above, is set to NULL when |
335 // another top level widget is created and focused. | 317 // another top level widget is created and focused. |
336 // 3. On focusing the native platform window for widget 1, the active aura | 318 // 3. On focusing the native platform window for widget 1, the active aura |
337 // window for widget 1 should be set and that for widget 2 should reset. | 319 // window for widget 1 should be set and that for widget 2 should reset. |
338 // TODO(ananta): Discuss with erg on how to write this test for linux x11 aura. | 320 // TODO(ananta): Discuss with erg on how to write this test for linux x11 aura. |
339 TEST_F(WidgetTestInteractive, DesktopNativeWidgetAuraActivationAndFocusTest) { | 321 TEST_F(WidgetTestInteractive, DesktopNativeWidgetAuraActivationAndFocusTest) { |
340 // Create widget 1 and expect the active window to be its window. | 322 // Create widget 1 and expect the active window to be its window. |
341 View* contents_view1 = new View; | 323 View* focusable_view1 = new View; |
342 contents_view1->SetFocusable(true); | 324 focusable_view1->SetFocusable(true); |
343 scoped_ptr<Widget> widget1(CreateWidget()); | 325 Widget* widget1 = CreateWidget(); |
344 widget1->SetContentsView(contents_view1); | 326 widget1->GetContentsView()->AddChildView(focusable_view1); |
345 widget1->Show(); | 327 widget1->Show(); |
346 aura::Window* root_window1= widget1->GetNativeView()->GetRootWindow(); | 328 aura::Window* root_window1 = widget1->GetNativeView()->GetRootWindow(); |
347 contents_view1->RequestFocus(); | 329 focusable_view1->RequestFocus(); |
348 | 330 |
349 EXPECT_TRUE(root_window1 != NULL); | 331 EXPECT_TRUE(root_window1 != NULL); |
350 aura::client::ActivationClient* activation_client1 = | 332 aura::client::ActivationClient* activation_client1 = |
351 aura::client::GetActivationClient(root_window1); | 333 aura::client::GetActivationClient(root_window1); |
352 EXPECT_TRUE(activation_client1 != NULL); | 334 EXPECT_TRUE(activation_client1 != NULL); |
353 EXPECT_EQ(activation_client1->GetActiveWindow(), widget1->GetNativeView()); | 335 EXPECT_EQ(activation_client1->GetActiveWindow(), widget1->GetNativeView()); |
354 | 336 |
355 // Create widget 2 and expect the active window to be its window. | 337 // Create widget 2 and expect the active window to be its window. |
356 View* contents_view2 = new View; | 338 View* focusable_view2 = new View; |
357 scoped_ptr<Widget> widget2(CreateWidget()); | 339 Widget* widget2 = CreateWidget(); |
358 widget2->SetContentsView(contents_view2); | 340 widget1->GetContentsView()->AddChildView(focusable_view2); |
359 widget2->Show(); | 341 widget2->Show(); |
360 aura::Window* root_window2 = widget2->GetNativeView()->GetRootWindow(); | 342 aura::Window* root_window2 = widget2->GetNativeView()->GetRootWindow(); |
361 contents_view2->RequestFocus(); | 343 focusable_view2->RequestFocus(); |
362 ActivatePlatformWindowSync(widget2.get()); | 344 ActivatePlatformWindow(widget2); |
363 | 345 |
364 aura::client::ActivationClient* activation_client2 = | 346 aura::client::ActivationClient* activation_client2 = |
365 aura::client::GetActivationClient(root_window2); | 347 aura::client::GetActivationClient(root_window2); |
366 EXPECT_TRUE(activation_client2 != NULL); | 348 EXPECT_TRUE(activation_client2 != NULL); |
367 EXPECT_EQ(activation_client2->GetActiveWindow(), widget2->GetNativeView()); | 349 EXPECT_EQ(activation_client2->GetActiveWindow(), widget2->GetNativeView()); |
368 EXPECT_EQ(activation_client1->GetActiveWindow(), | 350 EXPECT_EQ(activation_client1->GetActiveWindow(), |
369 reinterpret_cast<aura::Window*>(NULL)); | 351 reinterpret_cast<aura::Window*>(NULL)); |
370 | 352 |
371 // Now set focus back to widget 1 and expect the active window to be its | 353 // Now set focus back to widget 1 and expect the active window to be its |
372 // window. | 354 // window. |
373 contents_view1->RequestFocus(); | 355 focusable_view1->RequestFocus(); |
374 ActivatePlatformWindowSync(widget1.get()); | 356 ActivatePlatformWindow(widget1); |
375 EXPECT_EQ(activation_client2->GetActiveWindow(), | 357 EXPECT_EQ(activation_client2->GetActiveWindow(), |
376 reinterpret_cast<aura::Window*>(NULL)); | 358 reinterpret_cast<aura::Window*>(NULL)); |
377 EXPECT_EQ(activation_client1->GetActiveWindow(), widget1->GetNativeView()); | 359 EXPECT_EQ(activation_client1->GetActiveWindow(), widget1->GetNativeView()); |
| 360 |
| 361 widget2->CloseNow(); |
| 362 widget1->CloseNow(); |
378 } | 363 } |
379 #endif // defined(OS_WIN) | 364 #endif // defined(OS_WIN) |
380 | 365 |
381 TEST_F(WidgetTestInteractive, CaptureAutoReset) { | 366 TEST_F(WidgetTestInteractive, CaptureAutoReset) { |
382 Widget* toplevel = CreateTopLevelFramelessPlatformWidget(); | 367 Widget* toplevel = CreateTopLevelFramelessPlatformWidget(); |
383 View* container = new View; | 368 View* container = new View; |
384 toplevel->SetContentsView(container); | 369 toplevel->SetContentsView(container); |
385 | 370 |
386 EXPECT_FALSE(toplevel->HasCapture()); | 371 EXPECT_FALSE(toplevel->HasCapture()); |
387 toplevel->SetCapture(NULL); | 372 toplevel->SetCapture(NULL); |
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
919 #endif | 904 #endif |
920 | 905 |
921 // Test that touch selection quick menu is not activated when opened. | 906 // Test that touch selection quick menu is not activated when opened. |
922 TEST_F(WidgetTestInteractive, MAYBE_TouchSelectionQuickMenuIsNotActivated) { | 907 TEST_F(WidgetTestInteractive, MAYBE_TouchSelectionQuickMenuIsNotActivated) { |
923 base::CommandLine::ForCurrentProcess()->AppendSwitch( | 908 base::CommandLine::ForCurrentProcess()->AppendSwitch( |
924 switches::kEnableTouchEditing); | 909 switches::kEnableTouchEditing); |
925 #if defined(OS_WIN) | 910 #if defined(OS_WIN) |
926 views_delegate().set_use_desktop_native_widgets(true); | 911 views_delegate().set_use_desktop_native_widgets(true); |
927 #endif // !defined(OS_WIN) | 912 #endif // !defined(OS_WIN) |
928 | 913 |
929 scoped_ptr<Widget> widget(CreateWidget()); | 914 Widget* widget = CreateWidget(); |
930 | 915 |
931 Textfield* textfield = new Textfield; | 916 Textfield* textfield = new Textfield; |
932 textfield->SetBounds(0, 0, 200, 20); | 917 textfield->SetBounds(0, 0, 200, 20); |
933 textfield->SetText(base::ASCIIToUTF16("some text")); | 918 textfield->SetText(base::ASCIIToUTF16("some text")); |
934 widget->GetRootView()->AddChildView(textfield); | 919 widget->GetRootView()->AddChildView(textfield); |
935 | 920 |
936 widget->Show(); | 921 widget->Show(); |
937 textfield->RequestFocus(); | 922 textfield->RequestFocus(); |
938 textfield->SelectAll(true); | 923 textfield->SelectAll(true); |
939 TextfieldTestApi textfield_test_api(textfield); | 924 TextfieldTestApi textfield_test_api(textfield); |
940 | 925 |
941 RunPendingMessages(); | 926 RunPendingMessages(); |
942 | 927 |
943 ui::test::EventGenerator generator(widget->GetNativeWindow()); | 928 ui::test::EventGenerator generator(widget->GetNativeWindow()); |
944 generator.GestureTapAt(gfx::Point(10, 10)); | 929 generator.GestureTapAt(gfx::Point(10, 10)); |
945 ShowQuickMenuImmediately(static_cast<TouchSelectionControllerImpl*>( | 930 ShowQuickMenuImmediately(static_cast<TouchSelectionControllerImpl*>( |
946 textfield_test_api.touch_selection_controller())); | 931 textfield_test_api.touch_selection_controller())); |
947 | 932 |
948 EXPECT_TRUE(textfield->HasFocus()); | 933 EXPECT_TRUE(textfield->HasFocus()); |
949 EXPECT_TRUE(widget->IsActive()); | 934 EXPECT_TRUE(widget->IsActive()); |
950 EXPECT_TRUE(IsQuickMenuVisible(static_cast<TouchSelectionControllerImpl*>( | 935 EXPECT_TRUE(IsQuickMenuVisible(static_cast<TouchSelectionControllerImpl*>( |
951 textfield_test_api.touch_selection_controller()))); | 936 textfield_test_api.touch_selection_controller()))); |
| 937 widget->CloseNow(); |
952 } | 938 } |
953 | 939 |
954 TEST_F(WidgetTestInteractive, DisableViewDoesNotActivateWidget) { | 940 TEST_F(WidgetTestInteractive, DisableViewDoesNotActivateWidget) { |
955 #if defined(OS_WIN) | 941 #if defined(OS_WIN) |
956 views_delegate().set_use_desktop_native_widgets(true); | 942 views_delegate().set_use_desktop_native_widgets(true); |
957 #endif // !defined(OS_WIN) | 943 #endif // !defined(OS_WIN) |
958 | 944 |
959 // Create first widget and view, activate the widget, and focus the view. | 945 // Create first widget and view, activate the widget, and focus the view. |
960 Widget widget1; | 946 Widget widget1; |
961 Widget::InitParams params1 = CreateParams(Widget::InitParams::TYPE_POPUP); | 947 Widget::InitParams params1 = CreateParams(Widget::InitParams::TYPE_POPUP); |
(...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1447 ui::MouseEvent mouse_event(ui::ET_MOUSE_EXITED, gfx::Point(), gfx::Point(), | 1433 ui::MouseEvent mouse_event(ui::ET_MOUSE_EXITED, gfx::Point(), gfx::Point(), |
1448 ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE); | 1434 ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE); |
1449 ui::EventDispatchDetails details = widget1.GetNativeWindow()-> | 1435 ui::EventDispatchDetails details = widget1.GetNativeWindow()-> |
1450 GetHost()->event_processor()->OnEventFromSource(&mouse_event); | 1436 GetHost()->event_processor()->OnEventFromSource(&mouse_event); |
1451 ASSERT_FALSE(details.dispatcher_destroyed); | 1437 ASSERT_FALSE(details.dispatcher_destroyed); |
1452 EXPECT_TRUE(widget1.GetAndClearGotMouseEvent()); | 1438 EXPECT_TRUE(widget1.GetAndClearGotMouseEvent()); |
1453 EXPECT_FALSE(widget2.GetAndClearGotMouseEvent()); | 1439 EXPECT_FALSE(widget2.GetAndClearGotMouseEvent()); |
1454 } | 1440 } |
1455 #endif // defined(OS_WIN) | 1441 #endif // defined(OS_WIN) |
1456 | 1442 |
1457 #if defined(USE_AURA) | 1443 class WidgetInputMethodInteractiveTest : public WidgetTestInteractive { |
| 1444 public: |
| 1445 WidgetInputMethodInteractiveTest() {} |
| 1446 |
| 1447 // testing::Test: |
| 1448 void SetUp() override { |
| 1449 WidgetTestInteractive::SetUp(); |
| 1450 #if defined(OS_WIN) |
| 1451 // On Windows, Widget::Deactivate() works by activating the next topmost |
| 1452 // window on the z-order stack. This only works if there is at least one |
| 1453 // other window, so make sure that is the case. |
| 1454 deactivate_widget_ = CreateWidget(); |
| 1455 deactivate_widget_->Show(); |
| 1456 #endif |
| 1457 } |
| 1458 |
| 1459 void TearDown() override { |
| 1460 if (deactivate_widget_) |
| 1461 deactivate_widget_->CloseNow(); |
| 1462 WidgetTestInteractive::TearDown(); |
| 1463 } |
| 1464 |
| 1465 private: |
| 1466 Widget* deactivate_widget_ = nullptr; |
| 1467 |
| 1468 DISALLOW_COPY_AND_ASSIGN(WidgetInputMethodInteractiveTest); |
| 1469 }; |
| 1470 |
1458 // Test input method focus changes affected by top window activaction. | 1471 // Test input method focus changes affected by top window activaction. |
1459 TEST_F(WidgetTestInteractive, InputMethodFocus_activation) { | 1472 TEST_F(WidgetInputMethodInteractiveTest, Activation) { |
1460 scoped_ptr<Widget> widget(CreateWidget()); | 1473 Widget* widget = CreateWidget(); |
1461 scoped_ptr<Textfield> textfield(new Textfield); | 1474 Textfield* textfield = new Textfield; |
1462 widget->GetRootView()->AddChildView(textfield.get()); | 1475 widget->GetRootView()->AddChildView(textfield); |
1463 widget->Show(); | |
1464 textfield->RequestFocus(); | 1476 textfield->RequestFocus(); |
1465 | 1477 |
1466 ActivatePlatformWindowSync(widget.get()); | 1478 ShowSync(widget); |
1467 | 1479 |
1468 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, | 1480 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, |
1469 widget->GetInputMethod()->GetTextInputType()); | 1481 widget->GetInputMethod()->GetTextInputType()); |
1470 | 1482 |
1471 widget->Deactivate(); | 1483 DeactivateSync(widget); |
1472 | 1484 |
1473 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, | 1485 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, |
1474 widget->GetInputMethod()->GetTextInputType()); | 1486 widget->GetInputMethod()->GetTextInputType()); |
| 1487 widget->CloseNow(); |
1475 } | 1488 } |
1476 | 1489 |
1477 // Test input method focus changes affected by focus changes within 1 window. | 1490 // Test input method focus changes affected by focus changes within 1 window. |
1478 TEST_F(WidgetTestInteractive, InputMethodFocus_1_window) { | 1491 TEST_F(WidgetInputMethodInteractiveTest, OneWindow) { |
1479 scoped_ptr<Widget> widget(CreateWidget()); | 1492 Widget* widget = CreateWidget(); |
1480 scoped_ptr<Textfield> textfield1(new Textfield); | 1493 Textfield* textfield1 = new Textfield; |
1481 scoped_ptr<Textfield> textfield2(new Textfield); | 1494 Textfield* textfield2 = new Textfield; |
1482 textfield2->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); | 1495 textfield2->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); |
1483 widget->GetRootView()->AddChildView(textfield1.get()); | 1496 widget->GetRootView()->AddChildView(textfield1); |
1484 widget->GetRootView()->AddChildView(textfield2.get()); | 1497 widget->GetRootView()->AddChildView(textfield2); |
1485 widget->Show(); | |
1486 | 1498 |
1487 ActivatePlatformWindowSync(widget.get()); | 1499 ShowSync(widget); |
1488 | 1500 |
1489 textfield1->RequestFocus(); | 1501 textfield1->RequestFocus(); |
1490 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, | 1502 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, |
1491 widget->GetInputMethod()->GetTextInputType()); | 1503 widget->GetInputMethod()->GetTextInputType()); |
1492 | 1504 |
1493 textfield2->RequestFocus(); | 1505 textfield2->RequestFocus(); |
1494 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, | 1506 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, |
1495 widget->GetInputMethod()->GetTextInputType()); | 1507 widget->GetInputMethod()->GetTextInputType()); |
1496 | 1508 |
1497 // Window::Blur doesn't work for CrOS, because it uses NWA instead of DNWA and | 1509 // Widget::Deactivate() doesn't work for CrOS, because it uses NWA instead of |
1498 // involves the AuraTestHelper which setup the input method as DummyInputMethod. | 1510 // DNWA (which just activates the last active window) and involves the |
1499 // Please refer to CreateWidget method above. | 1511 // AuraTestHelper which sets the input method as DummyInputMethod. |
1500 #if !defined(OS_CHROMEOS) | 1512 #if !defined(OS_CHROMEOS) |
1501 aura::Window* window = widget->GetNativeWindow(); | 1513 DeactivateSync(widget); |
1502 window->Blur(); | |
1503 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, | 1514 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, |
1504 widget->GetInputMethod()->GetTextInputType()); | 1515 widget->GetInputMethod()->GetTextInputType()); |
1505 | 1516 |
1506 window->Focus(); | 1517 ActivateSync(widget); |
1507 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, | 1518 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, |
1508 widget->GetInputMethod()->GetTextInputType()); | 1519 widget->GetInputMethod()->GetTextInputType()); |
1509 | 1520 |
1510 window->Blur(); | 1521 DeactivateSync(widget); |
1511 textfield1->RequestFocus(); | 1522 textfield1->RequestFocus(); |
1512 window->Focus(); | 1523 ActivateSync(widget); |
1513 EXPECT_TRUE(window->HasFocus()); | 1524 EXPECT_TRUE(widget->IsActive()); |
1514 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, | 1525 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, |
1515 widget->GetInputMethod()->GetTextInputType()); | 1526 widget->GetInputMethod()->GetTextInputType()); |
1516 #endif | 1527 #endif |
| 1528 widget->CloseNow(); |
1517 } | 1529 } |
1518 | 1530 |
1519 // Test input method focus changes affected by focus changes cross 2 windows | 1531 // Test input method focus changes affected by focus changes cross 2 windows |
1520 // which shares the same top window. | 1532 // which shares the same top window. |
1521 TEST_F(WidgetTestInteractive, InputMethodFocus_2_windows) { | 1533 TEST_F(WidgetInputMethodInteractiveTest, TwoWindows) { |
1522 scoped_ptr<Widget> widget(CreateWidget()); | 1534 Widget* parent = CreateWidget(); |
1523 widget->Show(); | 1535 parent->SetBounds(gfx::Rect(100, 100, 100, 100)); |
1524 | 1536 |
1525 views::View* parent_root = new View; | 1537 Widget* child = CreateChildNativeWidgetWithParent(parent); |
1526 scoped_ptr<Widget> parent(new Widget); | |
1527 Widget::InitParams parent_params(Widget::InitParams::TYPE_WINDOW_FRAMELESS); | |
1528 parent_params.ownership = | |
1529 views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
1530 parent_params.context = widget->GetNativeWindow(); | |
1531 parent->Init(parent_params); | |
1532 parent->SetContentsView(parent_root); | |
1533 parent->SetBounds(gfx::Rect(100, 100, 100, 100)); | |
1534 parent->Show(); | |
1535 | |
1536 scoped_ptr<Widget> child(new Widget()); | |
1537 Widget::InitParams child_params(Widget::InitParams::TYPE_CONTROL); | |
1538 child_params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
1539 child_params.parent = parent->GetNativeWindow(); | |
1540 child->Init(child_params); | |
1541 child->SetBounds(gfx::Rect(0, 0, 50, 50)); | 1538 child->SetBounds(gfx::Rect(0, 0, 50, 50)); |
1542 child->Show(); | 1539 child->Show(); |
1543 | 1540 |
1544 scoped_ptr<Textfield> textfield_parent(new Textfield); | 1541 Textfield* textfield_parent = new Textfield; |
1545 scoped_ptr<Textfield> textfield_child(new Textfield); | 1542 Textfield* textfield_child = new Textfield; |
1546 textfield_parent->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); | 1543 textfield_parent->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); |
1547 parent->GetRootView()->AddChildView(textfield_parent.get()); | 1544 parent->GetRootView()->AddChildView(textfield_parent); |
1548 child->GetRootView()->AddChildView(textfield_child.get()); | 1545 child->GetRootView()->AddChildView(textfield_child); |
| 1546 ShowSync(parent); |
1549 | 1547 |
1550 EXPECT_EQ(parent->GetInputMethod(), child->GetInputMethod()); | 1548 EXPECT_EQ(parent->GetInputMethod(), child->GetInputMethod()); |
1551 | 1549 |
1552 textfield_parent->RequestFocus(); | 1550 textfield_parent->RequestFocus(); |
1553 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, | 1551 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, |
1554 parent->GetInputMethod()->GetTextInputType()); | 1552 parent->GetInputMethod()->GetTextInputType()); |
1555 | 1553 |
1556 textfield_child->RequestFocus(); | 1554 textfield_child->RequestFocus(); |
1557 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, | 1555 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, |
1558 parent->GetInputMethod()->GetTextInputType()); | 1556 parent->GetInputMethod()->GetTextInputType()); |
1559 | 1557 |
1560 // Window::Blur doesn't work for CrOS, because it uses NWA instead of DNWA and | 1558 // Widget::Deactivate() doesn't work for CrOS, because it uses NWA instead of |
1561 // involves the AuraTestHelper which setup the input method as DummyInputMethod. | 1559 // DNWA (which just activates the last active window) and involves the |
1562 // Please refer to CreateWidget method above. | 1560 // AuraTestHelper which sets the input method as DummyInputMethod. |
1563 #if !defined(OS_CHROMEOS) | 1561 #if !defined(OS_CHROMEOS) |
1564 child->GetNativeWindow()->Blur(); | 1562 DeactivateSync(parent); |
1565 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, | 1563 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, |
1566 parent->GetInputMethod()->GetTextInputType()); | 1564 parent->GetInputMethod()->GetTextInputType()); |
1567 | 1565 |
1568 child->GetNativeWindow()->Focus(); | 1566 ActivateSync(parent); |
1569 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, | 1567 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, |
1570 parent->GetInputMethod()->GetTextInputType()); | 1568 parent->GetInputMethod()->GetTextInputType()); |
1571 | 1569 |
1572 textfield_parent->RequestFocus(); | 1570 textfield_parent->RequestFocus(); |
1573 parent->GetNativeWindow()->Blur(); | 1571 DeactivateSync(parent); |
1574 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, | 1572 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, |
1575 parent->GetInputMethod()->GetTextInputType()); | 1573 parent->GetInputMethod()->GetTextInputType()); |
1576 | 1574 |
1577 parent->GetNativeWindow()->Focus(); | 1575 ActivateSync(parent); |
1578 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, | 1576 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, |
1579 parent->GetInputMethod()->GetTextInputType()); | 1577 parent->GetInputMethod()->GetTextInputType()); |
1580 #endif | 1578 #endif |
| 1579 |
| 1580 parent->CloseNow(); |
1581 } | 1581 } |
1582 | 1582 |
1583 // Test input method focus changes affected by focus changes cross 2 top | 1583 // Test input method focus changes affected by focus changes cross 2 top |
1584 // windows. | 1584 // windows. |
1585 TEST_F(WidgetTestInteractive, InputMethodFocus_2_top_windows) { | 1585 TEST_F(WidgetInputMethodInteractiveTest, TwoTopWindows) { |
1586 scoped_ptr<Widget> widget1(CreateWidget()); | 1586 Widget* widget1 = CreateWidget(); |
1587 scoped_ptr<Widget> widget2(CreateWidget()); | 1587 Widget* widget2 = CreateWidget(); |
1588 scoped_ptr<Textfield> textfield1(new Textfield); | 1588 Textfield* textfield1 = new Textfield; |
1589 scoped_ptr<Textfield> textfield2(new Textfield); | 1589 Textfield* textfield2 = new Textfield; |
1590 textfield2->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); | 1590 textfield2->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); |
1591 widget1->GetRootView()->AddChildView(textfield1.get()); | 1591 widget1->GetRootView()->AddChildView(textfield1); |
1592 widget2->GetRootView()->AddChildView(textfield2.get()); | 1592 widget2->GetRootView()->AddChildView(textfield2); |
1593 widget1->Show(); | 1593 widget1->Show(); |
1594 widget2->Show(); | 1594 widget2->Show(); |
1595 | 1595 |
1596 textfield1->RequestFocus(); | 1596 textfield1->RequestFocus(); |
1597 textfield2->RequestFocus(); | 1597 textfield2->RequestFocus(); |
1598 | 1598 |
1599 ActivatePlatformWindowSync(widget1.get()); | 1599 ActivateSync(widget1); |
1600 | 1600 |
1601 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, | 1601 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, |
1602 widget1->GetInputMethod()->GetTextInputType()); | 1602 widget1->GetInputMethod()->GetTextInputType()); |
1603 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, | 1603 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, |
1604 widget2->GetInputMethod()->GetTextInputType()); | 1604 widget2->GetInputMethod()->GetTextInputType()); |
1605 | 1605 |
1606 ActivatePlatformWindowSync(widget2.get()); | 1606 ActivateSync(widget2); |
1607 | 1607 |
1608 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, | 1608 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, |
1609 widget1->GetInputMethod()->GetTextInputType()); | 1609 widget1->GetInputMethod()->GetTextInputType()); |
1610 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, | 1610 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, |
1611 widget2->GetInputMethod()->GetTextInputType()); | 1611 widget2->GetInputMethod()->GetTextInputType()); |
| 1612 |
| 1613 widget2->CloseNow(); |
| 1614 widget1->CloseNow(); |
1612 } | 1615 } |
1613 | 1616 |
1614 // Test input method focus changes affected by textfield's state changes. | 1617 // Test input method focus changes affected by textfield's state changes. |
1615 TEST_F(WidgetTestInteractive, InputMethodFocus_textfield) { | 1618 TEST_F(WidgetInputMethodInteractiveTest, TextField) { |
1616 scoped_ptr<Widget> widget(CreateWidget()); | 1619 Widget* widget = CreateWidget(); |
1617 scoped_ptr<Textfield> textfield(new Textfield); | 1620 Textfield* textfield = new Textfield; |
1618 widget->GetRootView()->AddChildView(textfield.get()); | 1621 widget->GetRootView()->AddChildView(textfield); |
1619 widget->Show(); | 1622 ShowSync(widget); |
1620 ActivatePlatformWindowSync(widget.get()); | |
1621 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, | 1623 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, |
1622 widget->GetInputMethod()->GetTextInputType()); | 1624 widget->GetInputMethod()->GetTextInputType()); |
1623 | 1625 |
1624 textfield->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); | 1626 textfield->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); |
1625 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, | 1627 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, |
1626 widget->GetInputMethod()->GetTextInputType()); | 1628 widget->GetInputMethod()->GetTextInputType()); |
1627 | 1629 |
1628 textfield->RequestFocus(); | 1630 textfield->RequestFocus(); |
1629 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, | 1631 EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, |
1630 widget->GetInputMethod()->GetTextInputType()); | 1632 widget->GetInputMethod()->GetTextInputType()); |
1631 | 1633 |
1632 textfield->SetTextInputType(ui::TEXT_INPUT_TYPE_TEXT); | 1634 textfield->SetTextInputType(ui::TEXT_INPUT_TYPE_TEXT); |
1633 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, | 1635 EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, |
1634 widget->GetInputMethod()->GetTextInputType()); | 1636 widget->GetInputMethod()->GetTextInputType()); |
1635 | 1637 |
1636 textfield->SetReadOnly(true); | 1638 textfield->SetReadOnly(true); |
1637 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, | 1639 EXPECT_EQ(ui::TEXT_INPUT_TYPE_NONE, |
1638 widget->GetInputMethod()->GetTextInputType()); | 1640 widget->GetInputMethod()->GetTextInputType()); |
| 1641 widget->CloseNow(); |
1639 } | 1642 } |
1640 #endif // defined(USE_AURA) | |
1641 | 1643 |
1642 } // namespace test | 1644 } // namespace test |
1643 } // namespace views | 1645 } // namespace views |
OLD | NEW |