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.
8 #include "base/basictypes.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/run_loop.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "ui/base/hit_test.h"
16 #include "ui/compositor/layer_animation_observer.h"
17 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
18 #include "ui/compositor/scoped_layer_animation_settings.h"
19 #include "ui/events/event_utils.h"
20 #include "ui/events/test/event_generator.h"
21 #include "ui/gfx/geometry/point.h"
22 #include "ui/gfx/native_widget_types.h"
23 #include "ui/views/bubble/bubble_delegate.h"
24 #include "ui/views/controls/textfield/textfield.h"
25 #include "ui/views/test/test_views.h"
26 #include "ui/views/test/test_widget_observer.h"
27 #include "ui/views/test/widget_test.h"
28 #include "ui/views/widget/native_widget_delegate.h"
29 #include "ui/views/widget/root_view.h"
30 #include "ui/views/widget/widget_deletion_observer.h"
31 #include "ui/views/window/dialog_delegate.h"
32 #include "ui/views/window/native_frame_view.h"
35 #include "ui/aura/window.h"
36 #include "ui/aura/window_tree_host.h"
37 #include "ui/base/view_prop.h"
38 #include "ui/base/win/window_event_target.h"
39 #include "ui/views/win/hwnd_util.h"
42 #if defined(OS_MACOSX)
43 #include "base/mac/mac_util.h"
44 #include "ui/base/test/scoped_fake_nswindow_fullscreen.h"
52 // TODO(tdanderson): This utility function is used in different unittest
53 // files. Move to a common location to avoid
55 gfx::Point
ConvertPointFromWidgetToView(View
* view
, const gfx::Point
& p
) {
57 View::ConvertPointToTarget(view
->GetWidget()->GetRootView(), view
, &tmp
);
61 // Helper function for Snow Leopard special cases to avoid #ifdef litter.
62 bool IsTestingSnowLeopard() {
63 #if defined(OS_MACOSX)
64 return base::mac::IsOSSnowLeopard();
72 // A view that keeps track of the events it receives, and consumes all scroll
73 // gesture events and ui::ET_SCROLL events.
74 class ScrollableEventCountView
: public EventCountView
{
76 ScrollableEventCountView() {}
77 ~ScrollableEventCountView() override
{}
80 // Overridden from ui::EventHandler:
81 void OnGestureEvent(ui::GestureEvent
* event
) override
{
82 EventCountView::OnGestureEvent(event
);
83 switch (event
->type()) {
84 case ui::ET_GESTURE_SCROLL_BEGIN
:
85 case ui::ET_GESTURE_SCROLL_UPDATE
:
86 case ui::ET_GESTURE_SCROLL_END
:
87 case ui::ET_SCROLL_FLING_START
:
95 void OnScrollEvent(ui::ScrollEvent
* event
) override
{
96 EventCountView::OnScrollEvent(event
);
97 if (event
->type() == ui::ET_SCROLL
)
101 DISALLOW_COPY_AND_ASSIGN(ScrollableEventCountView
);
104 // A view that implements GetMinimumSize.
105 class MinimumSizeFrameView
: public NativeFrameView
{
107 explicit MinimumSizeFrameView(Widget
* frame
): NativeFrameView(frame
) {}
108 ~MinimumSizeFrameView() override
{}
111 // Overridden from View:
112 gfx::Size
GetMinimumSize() const override
{ return gfx::Size(300, 400); }
114 DISALLOW_COPY_AND_ASSIGN(MinimumSizeFrameView
);
117 // An event handler that simply keeps a count of the different types of events
119 class EventCountHandler
: public ui::EventHandler
{
121 EventCountHandler() {}
122 ~EventCountHandler() override
{}
124 int GetEventCount(ui::EventType type
) {
125 return event_count_
[type
];
129 event_count_
.clear();
133 // Overridden from ui::EventHandler:
134 void OnEvent(ui::Event
* event
) override
{
136 ui::EventHandler::OnEvent(event
);
140 void RecordEvent(const ui::Event
& event
) {
141 ++event_count_
[event
.type()];
144 std::map
<ui::EventType
, int> event_count_
;
146 DISALLOW_COPY_AND_ASSIGN(EventCountHandler
);
149 TEST_F(WidgetTest
, WidgetInitParams
) {
150 // Widgets are not transparent by default.
151 Widget::InitParams init1
;
152 EXPECT_EQ(Widget::InitParams::INFER_OPACITY
, init1
.opacity
);
155 TEST_F(WidgetTest
, NativeWindowProperty
) {
156 const char* key
= "foo";
159 Widget
* widget
= CreateTopLevelPlatformWidget();
160 EXPECT_EQ(nullptr, widget
->GetNativeWindowProperty(key
));
162 widget
->SetNativeWindowProperty(key
, &value
);
163 EXPECT_EQ(&value
, widget
->GetNativeWindowProperty(key
));
165 widget
->SetNativeWindowProperty(key
, nullptr);
166 EXPECT_EQ(nullptr, widget
->GetNativeWindowProperty(key
));
171 ////////////////////////////////////////////////////////////////////////////////
172 // Widget::GetTopLevelWidget tests.
174 TEST_F(WidgetTest
, GetTopLevelWidget_Native
) {
175 // Create a hierarchy of native widgets.
176 Widget
* toplevel
= CreateTopLevelPlatformWidget();
177 gfx::NativeView parent
= toplevel
->GetNativeView();
178 Widget
* child
= CreateChildPlatformWidget(parent
);
180 EXPECT_EQ(toplevel
, toplevel
->GetTopLevelWidget());
181 EXPECT_EQ(toplevel
, child
->GetTopLevelWidget());
183 toplevel
->CloseNow();
184 // |child| should be automatically destroyed with |toplevel|.
187 // Test if a focus manager and an inputmethod work without CHECK failure
188 // when window activation changes.
189 TEST_F(WidgetTest
, ChangeActivation
) {
190 Widget
* top1
= CreateTopLevelPlatformWidget();
192 RunPendingMessages();
194 Widget
* top2
= CreateTopLevelPlatformWidget();
196 RunPendingMessages();
199 RunPendingMessages();
202 RunPendingMessages();
205 RunPendingMessages();
211 // Tests visibility of child widgets.
212 TEST_F(WidgetTest
, Visibility
) {
213 Widget
* toplevel
= CreateTopLevelPlatformWidget();
214 gfx::NativeView parent
= toplevel
->GetNativeView();
215 Widget
* child
= CreateChildPlatformWidget(parent
);
217 EXPECT_FALSE(toplevel
->IsVisible());
218 EXPECT_FALSE(child
->IsVisible());
220 // Showing a child with a hidden parent keeps the child hidden.
222 EXPECT_FALSE(toplevel
->IsVisible());
223 EXPECT_FALSE(child
->IsVisible());
225 // Showing a hidden parent with a visible child shows both.
227 EXPECT_TRUE(toplevel
->IsVisible());
228 EXPECT_TRUE(child
->IsVisible());
230 // Hiding a parent hides both parent and child.
232 EXPECT_FALSE(toplevel
->IsVisible());
233 EXPECT_FALSE(child
->IsVisible());
235 // Hiding a child while the parent is hidden keeps the child hidden when the
239 EXPECT_TRUE(toplevel
->IsVisible());
240 EXPECT_FALSE(child
->IsVisible());
242 toplevel
->CloseNow();
243 // |child| should be automatically destroyed with |toplevel|.
246 // Test that child widgets are positioned relative to their parent.
247 TEST_F(WidgetTest
, ChildBoundsRelativeToParent
) {
248 Widget
* toplevel
= CreateTopLevelPlatformWidget();
249 Widget
* child
= CreateChildPlatformWidget(toplevel
->GetNativeView());
251 toplevel
->SetBounds(gfx::Rect(160, 100, 320, 200));
252 child
->SetBounds(gfx::Rect(0, 0, 320, 200));
257 gfx::Rect toplevel_bounds
= toplevel
->GetWindowBoundsInScreen();
259 // Check the parent origin. If it was (0, 0) the test wouldn't be interesting.
260 EXPECT_NE(gfx::Vector2d(0, 0), toplevel_bounds
.OffsetFromOrigin());
262 // The child's origin is at (0, 0), but the same size, so bounds should match.
263 EXPECT_EQ(toplevel_bounds
, child
->GetWindowBoundsInScreen());
265 toplevel
->CloseNow();
268 // Test z-order of child widgets relative to their parent.
269 TEST_F(WidgetTest
, ChildStackedRelativeToParent
) {
270 Widget
* parent
= CreateTopLevelPlatformWidget();
271 Widget
* child
= CreateChildPlatformWidget(parent
->GetNativeView());
273 parent
->SetBounds(gfx::Rect(160, 100, 320, 200));
274 child
->SetBounds(gfx::Rect(50, 50, 30, 20));
276 // Child shown first. Initially not visible, but on top of parent when shown.
277 // Use ShowInactive whenever showing the child, otherwise the usual activation
278 // logic will just put it on top anyway. Here, we want to ensure it is on top
279 // of its parent regardless.
280 child
->ShowInactive();
281 EXPECT_FALSE(child
->IsVisible());
284 EXPECT_TRUE(child
->IsVisible());
285 EXPECT_TRUE(IsWindowStackedAbove(child
, parent
));
286 EXPECT_FALSE(IsWindowStackedAbove(parent
, child
)); // Sanity check.
288 Widget
* popover
= CreateTopLevelPlatformWidget();
289 popover
->SetBounds(gfx::Rect(150, 90, 340, 240));
292 EXPECT_TRUE(IsWindowStackedAbove(popover
, child
));
293 EXPECT_TRUE(IsWindowStackedAbove(child
, parent
));
295 // Showing the parent again should raise it and its child above the popover.
297 EXPECT_TRUE(IsWindowStackedAbove(child
, parent
));
298 EXPECT_TRUE(IsWindowStackedAbove(parent
, popover
));
300 // Test grandchildren.
301 Widget
* grandchild
= CreateChildPlatformWidget(child
->GetNativeView());
302 grandchild
->SetBounds(gfx::Rect(5, 5, 15, 10));
303 grandchild
->ShowInactive();
304 EXPECT_TRUE(IsWindowStackedAbove(grandchild
, child
));
305 EXPECT_TRUE(IsWindowStackedAbove(child
, parent
));
306 EXPECT_TRUE(IsWindowStackedAbove(parent
, popover
));
309 EXPECT_TRUE(IsWindowStackedAbove(popover
, grandchild
));
310 EXPECT_TRUE(IsWindowStackedAbove(grandchild
, child
));
313 EXPECT_TRUE(IsWindowStackedAbove(grandchild
, child
));
314 EXPECT_TRUE(IsWindowStackedAbove(child
, popover
));
316 // Test hiding and reshowing.
318 EXPECT_FALSE(grandchild
->IsVisible());
321 EXPECT_TRUE(IsWindowStackedAbove(grandchild
, child
));
322 EXPECT_TRUE(IsWindowStackedAbove(child
, parent
));
323 EXPECT_TRUE(IsWindowStackedAbove(parent
, popover
));
326 EXPECT_FALSE(grandchild
->IsVisible());
327 grandchild
->ShowInactive();
329 EXPECT_TRUE(IsWindowStackedAbove(grandchild
, child
));
330 EXPECT_TRUE(IsWindowStackedAbove(child
, parent
));
331 EXPECT_TRUE(IsWindowStackedAbove(parent
, popover
));
337 ////////////////////////////////////////////////////////////////////////////////
338 // Widget ownership tests.
340 // Tests various permutations of Widget ownership specified in the
341 // InitParams::Ownership param.
343 // A WidgetTest that supplies a toplevel widget for NativeWidget to parent to.
344 class WidgetOwnershipTest
: public WidgetTest
{
346 WidgetOwnershipTest() {}
347 ~WidgetOwnershipTest() override
{}
349 void SetUp() override
{
351 desktop_widget_
= CreateTopLevelPlatformWidget();
354 void TearDown() override
{
355 desktop_widget_
->CloseNow();
356 WidgetTest::TearDown();
360 Widget
* desktop_widget_
;
362 DISALLOW_COPY_AND_ASSIGN(WidgetOwnershipTest
);
365 // A bag of state to monitor destructions.
366 struct OwnershipTestState
{
367 OwnershipTestState() : widget_deleted(false), native_widget_deleted(false) {}
370 bool native_widget_deleted
;
373 // A platform NativeWidget subclass that updates a bag of state when it is
375 class OwnershipTestNativeWidget
: public PlatformNativeWidget
{
377 OwnershipTestNativeWidget(internal::NativeWidgetDelegate
* delegate
,
378 OwnershipTestState
* state
)
379 : PlatformNativeWidget(delegate
),
382 ~OwnershipTestNativeWidget() override
{
383 state_
->native_widget_deleted
= true;
387 OwnershipTestState
* state_
;
389 DISALLOW_COPY_AND_ASSIGN(OwnershipTestNativeWidget
);
392 // A views NativeWidget subclass that updates a bag of state when it is
394 class OwnershipTestNativeWidgetAura
: public NativeWidgetCapture
{
396 OwnershipTestNativeWidgetAura(internal::NativeWidgetDelegate
* delegate
,
397 OwnershipTestState
* state
)
398 : NativeWidgetCapture(delegate
),
401 ~OwnershipTestNativeWidgetAura() override
{
402 state_
->native_widget_deleted
= true;
406 OwnershipTestState
* state_
;
408 DISALLOW_COPY_AND_ASSIGN(OwnershipTestNativeWidgetAura
);
411 // A Widget subclass that updates a bag of state when it is destroyed.
412 class OwnershipTestWidget
: public Widget
{
414 explicit OwnershipTestWidget(OwnershipTestState
* state
) : state_(state
) {}
415 ~OwnershipTestWidget() override
{ state_
->widget_deleted
= true; }
418 OwnershipTestState
* state_
;
420 DISALLOW_COPY_AND_ASSIGN(OwnershipTestWidget
);
423 // Widget owns its NativeWidget, part 1: NativeWidget is a platform-native
425 TEST_F(WidgetOwnershipTest
, Ownership_WidgetOwnsPlatformNativeWidget
) {
426 OwnershipTestState state
;
428 scoped_ptr
<Widget
> widget(new OwnershipTestWidget(&state
));
429 Widget::InitParams params
= CreateParams(Widget::InitParams::TYPE_POPUP
);
430 params
.native_widget
=
431 new OwnershipTestNativeWidgetAura(widget
.get(), &state
);
432 params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
433 widget
->Init(params
);
435 // Now delete the Widget, which should delete the NativeWidget.
438 EXPECT_TRUE(state
.widget_deleted
);
439 EXPECT_TRUE(state
.native_widget_deleted
);
441 // TODO(beng): write test for this ownership scenario and the NativeWidget
442 // being deleted out from under the Widget.
445 // Widget owns its NativeWidget, part 2: NativeWidget is a NativeWidget.
446 TEST_F(WidgetOwnershipTest
, Ownership_WidgetOwnsViewsNativeWidget
) {
447 OwnershipTestState state
;
449 scoped_ptr
<Widget
> widget(new OwnershipTestWidget(&state
));
450 Widget::InitParams params
= CreateParams(Widget::InitParams::TYPE_POPUP
);
451 params
.native_widget
=
452 new OwnershipTestNativeWidgetAura(widget
.get(), &state
);
453 params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
454 widget
->Init(params
);
456 // Now delete the Widget, which should delete the NativeWidget.
459 EXPECT_TRUE(state
.widget_deleted
);
460 EXPECT_TRUE(state
.native_widget_deleted
);
462 // TODO(beng): write test for this ownership scenario and the NativeWidget
463 // being deleted out from under the Widget.
466 // Widget owns its NativeWidget, part 3: NativeWidget is a NativeWidget,
467 // destroy the parent view.
468 TEST_F(WidgetOwnershipTest
,
469 Ownership_WidgetOwnsViewsNativeWidget_DestroyParentView
) {
470 OwnershipTestState state
;
472 Widget
* toplevel
= CreateTopLevelPlatformWidget();
474 scoped_ptr
<Widget
> widget(new OwnershipTestWidget(&state
));
475 Widget::InitParams params
= CreateParams(Widget::InitParams::TYPE_POPUP
);
476 params
.native_widget
=
477 new OwnershipTestNativeWidgetAura(widget
.get(), &state
);
478 params
.parent
= toplevel
->GetNativeView();
479 params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
480 widget
->Init(params
);
482 // Now close the toplevel, which deletes the view hierarchy.
483 toplevel
->CloseNow();
485 RunPendingMessages();
487 // This shouldn't delete the widget because it shouldn't be deleted
488 // from the native side.
489 EXPECT_FALSE(state
.widget_deleted
);
490 EXPECT_FALSE(state
.native_widget_deleted
);
492 // Now delete it explicitly.
495 EXPECT_TRUE(state
.widget_deleted
);
496 EXPECT_TRUE(state
.native_widget_deleted
);
499 // NativeWidget owns its Widget, part 1: NativeWidget is a platform-native
501 TEST_F(WidgetOwnershipTest
, Ownership_PlatformNativeWidgetOwnsWidget
) {
502 OwnershipTestState state
;
504 Widget
* widget
= new OwnershipTestWidget(&state
);
505 Widget::InitParams params
= CreateParams(Widget::InitParams::TYPE_POPUP
);
506 params
.native_widget
=
507 new OwnershipTestNativeWidgetAura(widget
, &state
);
508 widget
->Init(params
);
510 // Now destroy the native widget.
513 EXPECT_TRUE(state
.widget_deleted
);
514 EXPECT_TRUE(state
.native_widget_deleted
);
517 // NativeWidget owns its Widget, part 2: NativeWidget is a NativeWidget.
518 TEST_F(WidgetOwnershipTest
, Ownership_ViewsNativeWidgetOwnsWidget
) {
519 OwnershipTestState state
;
521 Widget
* toplevel
= CreateTopLevelPlatformWidget();
523 Widget
* widget
= new OwnershipTestWidget(&state
);
524 Widget::InitParams params
= CreateParams(Widget::InitParams::TYPE_POPUP
);
525 params
.native_widget
=
526 new OwnershipTestNativeWidgetAura(widget
, &state
);
527 params
.parent
= toplevel
->GetNativeView();
528 widget
->Init(params
);
530 // Now destroy the native widget. This is achieved by closing the toplevel.
531 toplevel
->CloseNow();
533 // The NativeWidget won't be deleted until after a return to the message loop
534 // so we have to run pending messages before testing the destruction status.
535 RunPendingMessages();
537 EXPECT_TRUE(state
.widget_deleted
);
538 EXPECT_TRUE(state
.native_widget_deleted
);
541 // NativeWidget owns its Widget, part 3: NativeWidget is a platform-native
542 // widget, destroyed out from under it by the OS.
543 TEST_F(WidgetOwnershipTest
,
544 Ownership_PlatformNativeWidgetOwnsWidget_NativeDestroy
) {
545 OwnershipTestState state
;
547 Widget
* widget
= new OwnershipTestWidget(&state
);
548 Widget::InitParams params
= CreateParams(Widget::InitParams::TYPE_POPUP
);
549 params
.native_widget
=
550 new OwnershipTestNativeWidgetAura(widget
, &state
);
551 widget
->Init(params
);
553 // Now simulate a destroy of the platform native widget from the OS:
554 SimulateNativeDestroy(widget
);
556 EXPECT_TRUE(state
.widget_deleted
);
557 EXPECT_TRUE(state
.native_widget_deleted
);
560 // NativeWidget owns its Widget, part 4: NativeWidget is a NativeWidget,
561 // destroyed by the view hierarchy that contains it.
562 TEST_F(WidgetOwnershipTest
,
563 Ownership_ViewsNativeWidgetOwnsWidget_NativeDestroy
) {
564 OwnershipTestState state
;
566 Widget
* toplevel
= CreateTopLevelPlatformWidget();
568 Widget
* widget
= new OwnershipTestWidget(&state
);
569 Widget::InitParams params
= CreateParams(Widget::InitParams::TYPE_POPUP
);
570 params
.native_widget
=
571 new OwnershipTestNativeWidgetAura(widget
, &state
);
572 params
.parent
= toplevel
->GetNativeView();
573 widget
->Init(params
);
575 // Destroy the widget (achieved by closing the toplevel).
576 toplevel
->CloseNow();
578 // The NativeWidget won't be deleted until after a return to the message loop
579 // so we have to run pending messages before testing the destruction status.
580 RunPendingMessages();
582 EXPECT_TRUE(state
.widget_deleted
);
583 EXPECT_TRUE(state
.native_widget_deleted
);
586 // NativeWidget owns its Widget, part 5: NativeWidget is a NativeWidget,
587 // we close it directly.
588 TEST_F(WidgetOwnershipTest
,
589 Ownership_ViewsNativeWidgetOwnsWidget_Close
) {
590 OwnershipTestState state
;
592 Widget
* toplevel
= CreateTopLevelPlatformWidget();
594 Widget
* widget
= new OwnershipTestWidget(&state
);
595 Widget::InitParams params
= CreateParams(Widget::InitParams::TYPE_POPUP
);
596 params
.native_widget
=
597 new OwnershipTestNativeWidgetAura(widget
, &state
);
598 params
.parent
= toplevel
->GetNativeView();
599 widget
->Init(params
);
601 // Destroy the widget.
603 toplevel
->CloseNow();
605 // The NativeWidget won't be deleted until after a return to the message loop
606 // so we have to run pending messages before testing the destruction status.
607 RunPendingMessages();
609 EXPECT_TRUE(state
.widget_deleted
);
610 EXPECT_TRUE(state
.native_widget_deleted
);
613 // Widget owns its NativeWidget and has a WidgetDelegateView as its contents.
614 TEST_F(WidgetOwnershipTest
,
615 Ownership_WidgetOwnsNativeWidgetWithWithWidgetDelegateView
) {
616 OwnershipTestState state
;
618 WidgetDelegateView
* delegate_view
= new WidgetDelegateView
;
620 scoped_ptr
<Widget
> widget(new OwnershipTestWidget(&state
));
621 Widget::InitParams params
= CreateParams(Widget::InitParams::TYPE_POPUP
);
622 params
.native_widget
=
623 new OwnershipTestNativeWidgetAura(widget
.get(), &state
);
624 params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
625 params
.delegate
= delegate_view
;
626 widget
->Init(params
);
627 widget
->SetContentsView(delegate_view
);
629 // Now delete the Widget. There should be no crash or use-after-free.
632 EXPECT_TRUE(state
.widget_deleted
);
633 EXPECT_TRUE(state
.native_widget_deleted
);
636 ////////////////////////////////////////////////////////////////////////////////
637 // Test to verify using various Widget methods doesn't crash when the underlying
638 // NativeView is destroyed.
640 class WidgetWithDestroyedNativeViewTest
: public ViewsTestBase
{
642 WidgetWithDestroyedNativeViewTest() {}
643 ~WidgetWithDestroyedNativeViewTest() override
{}
645 void InvokeWidgetMethods(Widget
* widget
) {
646 widget
->GetNativeView();
647 widget
->GetNativeWindow();
648 ui::Accelerator accelerator
;
649 widget
->GetAccelerator(0, &accelerator
);
650 widget
->GetTopLevelWidget();
651 widget
->GetWindowBoundsInScreen();
652 widget
->GetClientAreaBoundsInScreen();
653 widget
->SetBounds(gfx::Rect(0, 0, 100, 80));
654 widget
->SetSize(gfx::Size(10, 11));
655 widget
->SetBoundsConstrained(gfx::Rect(0, 0, 120, 140));
656 widget
->SetVisibilityChangedAnimationsEnabled(false);
657 widget
->StackAtTop();
662 widget
->Deactivate();
664 widget
->DisableInactiveRendering();
665 widget
->SetAlwaysOnTop(true);
666 widget
->IsAlwaysOnTop();
670 widget
->IsMaximized();
671 widget
->IsFullscreen();
672 widget
->SetOpacity(0);
673 widget
->SetUseDragFrame(true);
674 widget
->FlashFrame(true);
676 widget
->GetThemeProvider();
677 widget
->GetNativeTheme();
678 widget
->GetFocusManager();
679 widget
->SchedulePaintInRect(gfx::Rect(0, 0, 1, 2));
680 widget
->IsMouseEventsEnabled();
681 widget
->SetNativeWindowProperty("xx", widget
);
682 widget
->GetNativeWindowProperty("xx");
683 widget
->GetFocusTraversable();
685 widget
->ReorderNativeViews();
686 widget
->SetCapture(widget
->GetRootView());
687 widget
->ReleaseCapture();
688 widget
->HasCapture();
689 widget
->GetWorkAreaBoundsInScreen();
690 widget
->IsTranslucentWindowOpacitySupported();
694 DISALLOW_COPY_AND_ASSIGN(WidgetWithDestroyedNativeViewTest
);
697 TEST_F(WidgetWithDestroyedNativeViewTest
, Test
) {
700 Widget::InitParams params
= CreateParams(Widget::InitParams::TYPE_POPUP
);
701 params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
705 widget
.native_widget_private()->CloseNow();
706 InvokeWidgetMethods(&widget
);
708 #if !defined(OS_CHROMEOS)
711 Widget::InitParams params
= CreateParams(Widget::InitParams::TYPE_POPUP
);
712 params
.native_widget
= new PlatformDesktopNativeWidget(&widget
);
713 params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
717 widget
.native_widget_private()->CloseNow();
718 InvokeWidgetMethods(&widget
);
723 ////////////////////////////////////////////////////////////////////////////////
724 // Widget observer tests.
727 class WidgetObserverTest
: public WidgetTest
, public WidgetObserver
{
731 widget_closed_(nullptr),
732 widget_activated_(nullptr),
733 widget_shown_(nullptr),
734 widget_hidden_(nullptr),
735 widget_bounds_changed_(nullptr),
736 widget_to_close_on_hide_(nullptr) {
739 ~WidgetObserverTest() override
{}
741 // Set a widget to Close() the next time the Widget being observed is hidden.
742 void CloseOnNextHide(Widget
* widget
) {
743 widget_to_close_on_hide_
= widget
;
746 // Overridden from WidgetObserver:
747 void OnWidgetDestroying(Widget
* widget
) override
{
748 if (active_
== widget
)
750 widget_closed_
= widget
;
753 void OnWidgetActivationChanged(Widget
* widget
, bool active
) override
{
755 if (widget_activated_
)
756 widget_activated_
->Deactivate();
757 widget_activated_
= widget
;
760 if (widget_activated_
== widget
)
761 widget_activated_
= nullptr;
762 widget_deactivated_
= widget
;
766 void OnWidgetVisibilityChanged(Widget
* widget
, bool visible
) override
{
768 widget_shown_
= widget
;
771 widget_hidden_
= widget
;
772 if (widget_to_close_on_hide_
) {
773 widget_to_close_on_hide_
->Close();
774 widget_to_close_on_hide_
= nullptr;
778 void OnWidgetBoundsChanged(Widget
* widget
,
779 const gfx::Rect
& new_bounds
) override
{
780 widget_bounds_changed_
= widget
;
785 widget_closed_
= nullptr;
786 widget_activated_
= nullptr;
787 widget_deactivated_
= nullptr;
788 widget_shown_
= nullptr;
789 widget_hidden_
= nullptr;
790 widget_bounds_changed_
= nullptr;
793 Widget
* NewWidget() {
794 Widget
* widget
= CreateTopLevelNativeWidget();
795 widget
->AddObserver(this);
799 const Widget
* active() const { return active_
; }
800 const Widget
* widget_closed() const { return widget_closed_
; }
801 const Widget
* widget_activated() const { return widget_activated_
; }
802 const Widget
* widget_deactivated() const { return widget_deactivated_
; }
803 const Widget
* widget_shown() const { return widget_shown_
; }
804 const Widget
* widget_hidden() const { return widget_hidden_
; }
805 const Widget
* widget_bounds_changed() const { return widget_bounds_changed_
; }
810 Widget
* widget_closed_
;
811 Widget
* widget_activated_
;
812 Widget
* widget_deactivated_
;
813 Widget
* widget_shown_
;
814 Widget
* widget_hidden_
;
815 Widget
* widget_bounds_changed_
;
817 Widget
* widget_to_close_on_hide_
;
820 TEST_F(WidgetObserverTest
, DISABLED_ActivationChange
) {
821 Widget
* toplevel
= CreateTopLevelPlatformWidget();
823 Widget
* toplevel1
= NewWidget();
824 Widget
* toplevel2
= NewWidget();
831 toplevel1
->Activate();
833 RunPendingMessages();
834 EXPECT_EQ(toplevel1
, widget_activated());
836 toplevel2
->Activate();
837 RunPendingMessages();
838 EXPECT_EQ(toplevel1
, widget_deactivated());
839 EXPECT_EQ(toplevel2
, widget_activated());
840 EXPECT_EQ(toplevel2
, active());
842 toplevel
->CloseNow();
845 TEST_F(WidgetObserverTest
, DISABLED_VisibilityChange
) {
846 Widget
* toplevel
= CreateTopLevelPlatformWidget();
848 Widget
* child1
= NewWidget();
849 Widget
* child2
= NewWidget();
858 EXPECT_EQ(child1
, widget_hidden());
861 EXPECT_EQ(child2
, widget_hidden());
864 EXPECT_EQ(child1
, widget_shown());
867 EXPECT_EQ(child2
, widget_shown());
869 toplevel
->CloseNow();
872 TEST_F(WidgetObserverTest
, DestroyBubble
) {
873 Widget
* anchor
= CreateTopLevelPlatformWidget();
876 BubbleDelegateView
* bubble_delegate
=
877 new BubbleDelegateView(anchor
->client_view(), BubbleBorder::NONE
);
878 Widget
* bubble_widget(BubbleDelegateView::CreateBubble(bubble_delegate
));
879 bubble_widget
->Show();
880 bubble_widget
->CloseNow();
886 TEST_F(WidgetObserverTest
, WidgetBoundsChanged
) {
887 Widget
* child1
= NewWidget();
888 Widget
* child2
= NewWidget();
890 child1
->OnNativeWidgetMove();
891 EXPECT_EQ(child1
, widget_bounds_changed());
893 child2
->OnNativeWidgetMove();
894 EXPECT_EQ(child2
, widget_bounds_changed());
896 child1
->OnNativeWidgetSizeChanged(gfx::Size());
897 EXPECT_EQ(child1
, widget_bounds_changed());
899 child2
->OnNativeWidgetSizeChanged(gfx::Size());
900 EXPECT_EQ(child2
, widget_bounds_changed());
906 // An extension to WidgetBoundsChanged to ensure notifications are forwarded
907 // by the NativeWidget implementation.
908 TEST_F(WidgetObserverTest
, WidgetBoundsChangedNative
) {
909 // Don't use NewWidget(), so that the Init() flow can be observed to ensure
910 // consistency across platforms.
911 Widget
* widget
= new Widget(); // Note: owned by NativeWidget.
912 widget
->AddObserver(this);
914 EXPECT_FALSE(widget_bounds_changed());
916 // Init causes a bounds change, even while not showing. Note some platforms
917 // cause a bounds change even when the bounds are empty. Mac does not.
918 Widget::InitParams params
= CreateParams(Widget::InitParams::TYPE_WINDOW
);
919 params
.bounds
= gfx::Rect(0, 0, 100, 100);
920 widget
->Init(params
);
921 EXPECT_TRUE(widget_bounds_changed());
924 // Resizing while hidden, triggers a change.
925 widget
->SetSize(gfx::Size(160, 100));
926 EXPECT_FALSE(widget
->IsVisible());
927 EXPECT_TRUE(widget_bounds_changed());
930 // Setting the same size does nothing.
931 widget
->SetSize(gfx::Size(160, 100));
932 EXPECT_FALSE(widget_bounds_changed());
935 // Showing does nothing to the bounds.
937 EXPECT_TRUE(widget
->IsVisible());
938 EXPECT_FALSE(widget_bounds_changed());
941 // Resizing while shown.
942 widget
->SetSize(gfx::Size(170, 100));
943 EXPECT_TRUE(widget_bounds_changed());
946 // Resize to the same thing while shown does nothing.
947 widget
->SetSize(gfx::Size(170, 100));
948 EXPECT_FALSE(widget_bounds_changed());
951 // No bounds change when closing.
953 EXPECT_FALSE(widget_bounds_changed());
956 // Test correct behavior when widgets close themselves in response to visibility
958 TEST_F(WidgetObserverTest
, ClosingOnHiddenParent
) {
959 Widget
* parent
= NewWidget();
960 Widget
* child
= CreateChildPlatformWidget(parent
->GetNativeView());
962 TestWidgetObserver
child_observer(child
);
964 EXPECT_FALSE(parent
->IsVisible());
965 EXPECT_FALSE(child
->IsVisible());
967 // Note |child| is TYPE_CONTROL, which start shown. So no need to show the
970 EXPECT_TRUE(parent
->IsVisible());
971 EXPECT_TRUE(child
->IsVisible());
973 // Simulate a child widget that closes itself when the parent is hidden.
974 CloseOnNextHide(child
);
975 EXPECT_FALSE(child_observer
.widget_closed());
977 RunPendingMessages();
978 EXPECT_TRUE(child_observer
.widget_closed());
983 // Test behavior of NativeWidget*::GetWindowPlacement on the native desktop.
984 TEST_F(WidgetTest
, GetWindowPlacement
) {
986 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
987 // On desktop-Linux cheat and use non-desktop widgets. On X11, minimize is
988 // asynchronous. Also (harder) showing a window doesn't activate it without
989 // user interaction (or extra steps only done for interactive ui tests).
990 // Without that, show_state remains in ui::SHOW_STATE_INACTIVE throughout.
991 // TODO(tapted): Find a nice way to run this with desktop widgets on Linux.
992 widget
= CreateTopLevelPlatformWidget();
994 widget
= CreateNativeDesktopWidget();
997 gfx::Rect
expected_bounds(100, 110, 200, 220);
998 widget
->SetBounds(expected_bounds
);
1001 // Start with something invalid to ensure it changes.
1002 ui::WindowShowState show_state
= ui::SHOW_STATE_END
;
1003 gfx::Rect restored_bounds
;
1005 internal::NativeWidgetPrivate
* native_widget
=
1006 widget
->native_widget_private();
1008 native_widget
->GetWindowPlacement(&restored_bounds
, &show_state
);
1009 EXPECT_EQ(expected_bounds
, restored_bounds
);
1010 #if defined(OS_LINUX)
1011 // Non-desktop/Ash widgets start off in "default" until a Restore().
1012 EXPECT_EQ(ui::SHOW_STATE_DEFAULT
, show_state
);
1014 native_widget
->GetWindowPlacement(&restored_bounds
, &show_state
);
1016 EXPECT_EQ(ui::SHOW_STATE_NORMAL
, show_state
);
1019 native_widget
->GetWindowPlacement(&restored_bounds
, &show_state
);
1020 EXPECT_EQ(ui::SHOW_STATE_MINIMIZED
, show_state
);
1021 EXPECT_EQ(expected_bounds
, restored_bounds
);
1024 native_widget
->GetWindowPlacement(&restored_bounds
, &show_state
);
1025 EXPECT_EQ(ui::SHOW_STATE_NORMAL
, show_state
);
1026 EXPECT_EQ(expected_bounds
, restored_bounds
);
1028 expected_bounds
= gfx::Rect(130, 140, 230, 250);
1029 widget
->SetBounds(expected_bounds
);
1030 native_widget
->GetWindowPlacement(&restored_bounds
, &show_state
);
1031 EXPECT_EQ(ui::SHOW_STATE_NORMAL
, show_state
);
1032 EXPECT_EQ(expected_bounds
, restored_bounds
);
1034 widget
->SetFullscreen(true);
1035 native_widget
->GetWindowPlacement(&restored_bounds
, &show_state
);
1038 // Desktop Aura widgets on Windows currently don't update show_state when
1039 // going fullscreen, and report restored_bounds as the full screen size.
1040 // See http://crbug.com/475813.
1041 EXPECT_EQ(ui::SHOW_STATE_NORMAL
, show_state
);
1043 EXPECT_EQ(ui::SHOW_STATE_FULLSCREEN
, show_state
);
1044 EXPECT_EQ(expected_bounds
, restored_bounds
);
1047 widget
->SetFullscreen(false);
1048 native_widget
->GetWindowPlacement(&restored_bounds
, &show_state
);
1049 EXPECT_EQ(ui::SHOW_STATE_NORMAL
, show_state
);
1050 EXPECT_EQ(expected_bounds
, restored_bounds
);
1055 // Test that widget size constraints are properly applied immediately after
1056 // Init(), and that SetBounds() calls are appropriately clamped.
1057 TEST_F(WidgetTest
, MinimumSizeConstraints
) {
1058 TestDesktopWidgetDelegate delegate
;
1059 gfx::Size
minimum_size(100, 100);
1060 const gfx::Size
smaller_size(90, 90);
1062 delegate
.set_contents_view(new StaticSizedView(minimum_size
));
1063 delegate
.InitWidget(CreateParams(Widget::InitParams::TYPE_WINDOW
));
1064 Widget
* widget
= delegate
.GetWidget();
1066 // On desktop Linux, the Widget must be shown to ensure the window is mapped.
1067 // On other platforms this line is optional.
1071 EXPECT_GT(delegate
.initial_bounds().width(), minimum_size
.width());
1072 EXPECT_GT(delegate
.initial_bounds().height(), minimum_size
.height());
1073 EXPECT_EQ(delegate
.initial_bounds().size(),
1074 widget
->GetWindowBoundsInScreen().size());
1075 // Note: StaticSizedView doesn't currently provide a maximum size.
1076 EXPECT_EQ(gfx::Size(), widget
->GetMaximumSize());
1078 if (!widget
->ShouldUseNativeFrame()) {
1079 // The test environment may have dwm disabled on Windows. In this case,
1080 // CustomFrameView is used instead of the NativeFrameView, which will
1081 // provide a minimum size that includes frame decorations.
1082 minimum_size
= widget
->non_client_view()->GetWindowBoundsForClientBounds(
1083 gfx::Rect(minimum_size
)).size();
1086 EXPECT_EQ(minimum_size
, widget
->GetMinimumSize());
1087 EXPECT_EQ(minimum_size
, GetNativeWidgetMinimumContentSize(widget
));
1089 // Trying to resize smaller than the minimum size should restrict the content
1090 // size to the minimum size.
1091 widget
->SetBounds(gfx::Rect(smaller_size
));
1092 EXPECT_EQ(minimum_size
, widget
->GetClientAreaBoundsInScreen().size());
1094 widget
->SetSize(smaller_size
);
1095 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
1096 // TODO(tapted): Desktop Linux ignores size constraints for SetSize. Fix it.
1097 EXPECT_EQ(smaller_size
, widget
->GetClientAreaBoundsInScreen().size());
1099 EXPECT_EQ(minimum_size
, widget
->GetClientAreaBoundsInScreen().size());
1103 // Tests that SetBounds() and GetWindowBoundsInScreen() is symmetric when the
1104 // widget is visible and not maximized or fullscreen.
1105 TEST_F(WidgetTest
, GetWindowBoundsInScreen
) {
1106 // Choose test coordinates away from edges and dimensions that are "small"
1107 // (but not too small) to ensure the OS doesn't try to adjust them.
1108 const gfx::Rect
kTestBounds(150, 150, 400, 300);
1109 const gfx::Size
kTestSize(200, 180);
1111 // First test a toplevel widget.
1112 Widget
* widget
= CreateTopLevelPlatformWidget();
1115 EXPECT_NE(kTestSize
.ToString(),
1116 widget
->GetWindowBoundsInScreen().size().ToString());
1117 widget
->SetSize(kTestSize
);
1118 EXPECT_EQ(kTestSize
.ToString(),
1119 widget
->GetWindowBoundsInScreen().size().ToString());
1121 EXPECT_NE(kTestBounds
.ToString(),
1122 widget
->GetWindowBoundsInScreen().ToString());
1123 widget
->SetBounds(kTestBounds
);
1124 EXPECT_EQ(kTestBounds
.ToString(),
1125 widget
->GetWindowBoundsInScreen().ToString());
1127 // Changing just the size should not change the origin.
1128 widget
->SetSize(kTestSize
);
1129 EXPECT_EQ(kTestBounds
.origin().ToString(),
1130 widget
->GetWindowBoundsInScreen().origin().ToString());
1134 // Same tests with a frameless window.
1135 widget
= CreateTopLevelFramelessPlatformWidget();
1138 EXPECT_NE(kTestSize
.ToString(),
1139 widget
->GetWindowBoundsInScreen().size().ToString());
1140 widget
->SetSize(kTestSize
);
1141 EXPECT_EQ(kTestSize
.ToString(),
1142 widget
->GetWindowBoundsInScreen().size().ToString());
1144 EXPECT_NE(kTestBounds
.ToString(),
1145 widget
->GetWindowBoundsInScreen().ToString());
1146 widget
->SetBounds(kTestBounds
);
1147 EXPECT_EQ(kTestBounds
.ToString(),
1148 widget
->GetWindowBoundsInScreen().ToString());
1150 // For a frameless widget, the client bounds should also match.
1151 EXPECT_EQ(kTestBounds
.ToString(),
1152 widget
->GetClientAreaBoundsInScreen().ToString());
1154 // Verify origin is stable for a frameless window as well.
1155 widget
->SetSize(kTestSize
);
1156 EXPECT_EQ(kTestBounds
.origin().ToString(),
1157 widget
->GetWindowBoundsInScreen().origin().ToString());
1162 // Non-Desktop widgets need the shell to maximize/fullscreen window.
1163 // Disable on Linux because windows restore to the wrong bounds.
1164 // See http://crbug.com/515369.
1165 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
1166 #define MAYBE_GetRestoredBounds DISABLED_GetRestoredBounds
1168 #define MAYBE_GetRestoredBounds GetRestoredBounds
1171 // Test that GetRestoredBounds() returns the original bounds of the window.
1172 TEST_F(WidgetTest
, MAYBE_GetRestoredBounds
) {
1173 #if defined(OS_MACOSX)
1174 // Fullscreen on Mac requires an interactive UI test, fake them here.
1175 ui::test::ScopedFakeNSWindowFullscreen fake_fullscreen
;
1178 Widget
* toplevel
= CreateNativeDesktopWidget();
1180 // Initial restored bounds have non-zero size.
1181 EXPECT_FALSE(toplevel
->GetRestoredBounds().IsEmpty());
1183 const gfx::Rect
bounds(100, 100, 200, 200);
1184 toplevel
->SetBounds(bounds
);
1185 EXPECT_EQ(bounds
, toplevel
->GetWindowBoundsInScreen());
1186 EXPECT_EQ(bounds
, toplevel
->GetRestoredBounds());
1188 toplevel
->Maximize();
1189 RunPendingMessages();
1190 #if defined(OS_MACOSX)
1191 // Current expectation on Mac is to do nothing on Maximize.
1192 EXPECT_EQ(toplevel
->GetWindowBoundsInScreen(), toplevel
->GetRestoredBounds());
1194 EXPECT_NE(toplevel
->GetWindowBoundsInScreen(), toplevel
->GetRestoredBounds());
1196 EXPECT_EQ(bounds
, toplevel
->GetRestoredBounds());
1198 toplevel
->Restore();
1199 RunPendingMessages();
1200 EXPECT_EQ(bounds
, toplevel
->GetWindowBoundsInScreen());
1201 EXPECT_EQ(bounds
, toplevel
->GetRestoredBounds());
1203 toplevel
->SetFullscreen(true);
1204 RunPendingMessages();
1206 if (IsTestingSnowLeopard()) {
1207 // Fullscreen not implemented for Snow Leopard.
1208 EXPECT_EQ(toplevel
->GetWindowBoundsInScreen(),
1209 toplevel
->GetRestoredBounds());
1211 EXPECT_NE(toplevel
->GetWindowBoundsInScreen(),
1212 toplevel
->GetRestoredBounds());
1214 EXPECT_EQ(bounds
, toplevel
->GetRestoredBounds());
1216 toplevel
->SetFullscreen(false);
1217 RunPendingMessages();
1218 EXPECT_EQ(bounds
, toplevel
->GetWindowBoundsInScreen());
1219 EXPECT_EQ(bounds
, toplevel
->GetRestoredBounds());
1221 toplevel
->CloseNow();
1224 // The key-event propagation from Widget happens differently on aura and
1225 // non-aura systems because of the difference in IME. So this test works only on
1227 TEST_F(WidgetTest
, KeyboardInputEvent
) {
1228 Widget
* toplevel
= CreateTopLevelPlatformWidget();
1229 View
* container
= toplevel
->client_view();
1231 Textfield
* textfield
= new Textfield();
1232 textfield
->SetText(base::ASCIIToUTF16("some text"));
1233 container
->AddChildView(textfield
);
1235 textfield
->RequestFocus();
1237 // The press gets handled. The release doesn't have an effect.
1238 ui::KeyEvent
backspace_p(ui::ET_KEY_PRESSED
, ui::VKEY_DELETE
, ui::EF_NONE
);
1239 toplevel
->OnKeyEvent(&backspace_p
);
1240 EXPECT_TRUE(backspace_p
.stopped_propagation());
1241 ui::KeyEvent
backspace_r(ui::ET_KEY_RELEASED
, ui::VKEY_DELETE
, ui::EF_NONE
);
1242 toplevel
->OnKeyEvent(&backspace_r
);
1243 EXPECT_FALSE(backspace_r
.handled());
1248 // Verifies bubbles result in a focus lost when shown.
1249 // TODO(msw): this tests relies on focus, it needs to be in
1250 // interactive_ui_tests.
1251 TEST_F(WidgetTest
, DISABLED_FocusChangesOnBubble
) {
1252 // Create a widget, show and activate it and focus the contents view.
1253 View
* contents_view
= new View
;
1254 contents_view
->SetFocusable(true);
1256 Widget::InitParams init_params
=
1257 CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS
);
1258 init_params
.bounds
= gfx::Rect(0, 0, 200, 200);
1259 init_params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
1260 #if !defined(OS_CHROMEOS)
1261 init_params
.native_widget
= new PlatformDesktopNativeWidget(&widget
);
1263 widget
.Init(init_params
);
1264 widget
.SetContentsView(contents_view
);
1267 contents_view
->RequestFocus();
1268 EXPECT_TRUE(contents_view
->HasFocus());
1271 BubbleDelegateView
* bubble_delegate_view
=
1272 new BubbleDelegateView(contents_view
, BubbleBorder::TOP_LEFT
);
1273 bubble_delegate_view
->SetFocusable(true);
1274 BubbleDelegateView::CreateBubble(bubble_delegate_view
)->Show();
1275 bubble_delegate_view
->RequestFocus();
1277 // |contents_view_| should no longer have focus.
1278 EXPECT_FALSE(contents_view
->HasFocus());
1279 EXPECT_TRUE(bubble_delegate_view
->HasFocus());
1281 bubble_delegate_view
->GetWidget()->CloseNow();
1283 // Closing the bubble should result in focus going back to the contents view.
1284 EXPECT_TRUE(contents_view
->HasFocus());
1287 class TestBubbleDelegateView
: public BubbleDelegateView
{
1289 TestBubbleDelegateView(View
* anchor
)
1290 : BubbleDelegateView(anchor
, BubbleBorder::NONE
),
1291 reset_controls_called_(false) {}
1292 ~TestBubbleDelegateView() override
{}
1294 bool ShouldShowCloseButton() const override
{
1295 reset_controls_called_
= true;
1299 mutable bool reset_controls_called_
;
1302 TEST_F(WidgetTest
, BubbleControlsResetOnInit
) {
1303 Widget
* anchor
= CreateTopLevelPlatformWidget();
1306 TestBubbleDelegateView
* bubble_delegate
=
1307 new TestBubbleDelegateView(anchor
->client_view());
1308 Widget
* bubble_widget(BubbleDelegateView::CreateBubble(bubble_delegate
));
1309 EXPECT_TRUE(bubble_delegate
->reset_controls_called_
);
1310 bubble_widget
->Show();
1311 bubble_widget
->CloseNow();
1318 // Test to ensure that after minimize, view width is set to zero. This is only
1319 // the case for desktop widgets on Windows. Other platforms retain the window
1320 // size while minimized.
1321 TEST_F(WidgetTest
, TestViewWidthAfterMinimizingWidget
) {
1324 Widget::InitParams init_params
=
1325 CreateParams(Widget::InitParams::TYPE_WINDOW
);
1326 init_params
.show_state
= ui::SHOW_STATE_NORMAL
;
1327 gfx::Rect
initial_bounds(0, 0, 300, 400);
1328 init_params
.bounds
= initial_bounds
;
1329 init_params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
1330 init_params
.native_widget
= new PlatformDesktopNativeWidget(&widget
);
1331 widget
.Init(init_params
);
1332 NonClientView
* non_client_view
= widget
.non_client_view();
1333 NonClientFrameView
* frame_view
= new MinimumSizeFrameView(&widget
);
1334 non_client_view
->SetFrameView(frame_view
);
1335 // Setting the frame view doesn't do a layout, so force one.
1336 non_client_view
->Layout();
1338 EXPECT_NE(0, frame_view
->width());
1340 EXPECT_EQ(0, frame_view
->width());
1344 // Desktop native widget Aura tests are for non Chrome OS platforms.
1345 #if !defined(OS_CHROMEOS)
1346 // This class validates whether paints are received for a visible Widget.
1347 // To achieve this it overrides the Show and Close methods on the Widget class
1348 // and sets state whether subsequent paints are expected.
1349 class DesktopAuraTestValidPaintWidget
: public views::Widget
{
1351 DesktopAuraTestValidPaintWidget()
1352 : received_paint_(false),
1353 expect_paint_(true),
1354 received_paint_while_hidden_(false) {}
1356 ~DesktopAuraTestValidPaintWidget() override
{}
1358 void InitForTest(Widget::InitParams create_params
);
1360 void Show() override
{
1361 expect_paint_
= true;
1362 views::Widget::Show();
1365 void Close() override
{
1366 expect_paint_
= false;
1367 views::Widget::Close();
1371 expect_paint_
= false;
1372 views::Widget::Hide();
1375 void OnNativeWidgetPaint(const ui::PaintContext
& context
) override
{
1376 received_paint_
= true;
1377 EXPECT_TRUE(expect_paint_
);
1379 received_paint_while_hidden_
= true;
1380 views::Widget::OnNativeWidgetPaint(context
);
1383 bool ReadReceivedPaintAndReset() {
1384 bool result
= received_paint_
;
1385 received_paint_
= false;
1389 bool received_paint_while_hidden() const {
1390 return received_paint_while_hidden_
;
1394 bool received_paint_
;
1396 bool received_paint_while_hidden_
;
1398 DISALLOW_COPY_AND_ASSIGN(DesktopAuraTestValidPaintWidget
);
1401 void DesktopAuraTestValidPaintWidget::InitForTest(InitParams init_params
) {
1402 init_params
.bounds
= gfx::Rect(0, 0, 200, 200);
1403 init_params
.ownership
= InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
1404 init_params
.native_widget
= new PlatformDesktopNativeWidget(this);
1407 View
* contents_view
= new View
;
1408 contents_view
->SetFocusable(true);
1409 SetContentsView(contents_view
);
1415 TEST_F(WidgetTest
, DesktopNativeWidgetNoPaintAfterCloseTest
) {
1416 DesktopAuraTestValidPaintWidget widget
;
1417 widget
.InitForTest(CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS
));
1418 RunPendingMessages();
1419 EXPECT_TRUE(widget
.ReadReceivedPaintAndReset());
1420 widget
.SchedulePaintInRect(widget
.GetRestoredBounds());
1422 RunPendingMessages();
1423 EXPECT_FALSE(widget
.ReadReceivedPaintAndReset());
1424 EXPECT_FALSE(widget
.received_paint_while_hidden());
1427 TEST_F(WidgetTest
, DesktopNativeWidgetNoPaintAfterHideTest
) {
1428 DesktopAuraTestValidPaintWidget widget
;
1429 widget
.InitForTest(CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS
));
1430 RunPendingMessages();
1431 EXPECT_TRUE(widget
.ReadReceivedPaintAndReset());
1432 widget
.SchedulePaintInRect(widget
.GetRestoredBounds());
1434 RunPendingMessages();
1435 EXPECT_FALSE(widget
.ReadReceivedPaintAndReset());
1436 EXPECT_FALSE(widget
.received_paint_while_hidden());
1440 // Test to ensure that the aura Window's visiblity state is set to visible if
1441 // the underlying widget is hidden and then shown.
1442 TEST_F(WidgetTest
, TestWindowVisibilityAfterHide
) {
1445 Widget::InitParams init_params
=
1446 CreateParams(Widget::InitParams::TYPE_WINDOW
);
1447 init_params
.show_state
= ui::SHOW_STATE_NORMAL
;
1448 gfx::Rect
initial_bounds(0, 0, 300, 400);
1449 init_params
.bounds
= initial_bounds
;
1450 init_params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
1451 init_params
.native_widget
= new PlatformDesktopNativeWidget(&widget
);
1452 widget
.Init(init_params
);
1453 NonClientView
* non_client_view
= widget
.non_client_view();
1454 NonClientFrameView
* frame_view
= new MinimumSizeFrameView(&widget
);
1455 non_client_view
->SetFrameView(frame_view
);
1458 EXPECT_TRUE(IsNativeWindowVisible(widget
.GetNativeWindow()));
1460 EXPECT_FALSE(IsNativeWindowVisible(widget
.GetNativeWindow()));
1462 EXPECT_TRUE(IsNativeWindowVisible(widget
.GetNativeWindow()));
1465 #endif // !defined(OS_CHROMEOS)
1467 // Tests that wheel events generated from scroll events are targetted to the
1468 // views under the cursor when the focused view does not processed them.
1469 TEST_F(WidgetTest
, WheelEventsFromScrollEventTarget
) {
1470 EventCountView
* cursor_view
= new EventCountView
;
1471 cursor_view
->SetBounds(60, 0, 50, 40);
1473 Widget
* widget
= CreateTopLevelPlatformWidget();
1474 widget
->GetRootView()->AddChildView(cursor_view
);
1476 // Generate a scroll event on the cursor view.
1477 ui::ScrollEvent
scroll(ui::ET_SCROLL
,
1479 ui::EventTimeForNow(),
1484 widget
->OnScrollEvent(&scroll
);
1486 EXPECT_EQ(1, cursor_view
->GetEventCount(ui::ET_SCROLL
));
1487 EXPECT_EQ(1, cursor_view
->GetEventCount(ui::ET_MOUSEWHEEL
));
1489 cursor_view
->ResetCounts();
1491 ui::ScrollEvent
scroll2(ui::ET_SCROLL
,
1493 ui::EventTimeForNow(),
1498 widget
->OnScrollEvent(&scroll2
);
1500 EXPECT_EQ(0, cursor_view
->GetEventCount(ui::ET_SCROLL
));
1501 EXPECT_EQ(0, cursor_view
->GetEventCount(ui::ET_MOUSEWHEEL
));
1506 // Tests that if a scroll-begin gesture is not handled, then subsequent scroll
1507 // events are not dispatched to any view.
1508 TEST_F(WidgetTest
, GestureScrollEventDispatching
) {
1509 EventCountView
* noscroll_view
= new EventCountView
;
1510 EventCountView
* scroll_view
= new ScrollableEventCountView
;
1512 noscroll_view
->SetBounds(0, 0, 50, 40);
1513 scroll_view
->SetBounds(60, 0, 40, 40);
1515 Widget
* widget
= CreateTopLevelPlatformWidget();
1516 widget
->GetRootView()->AddChildView(noscroll_view
);
1517 widget
->GetRootView()->AddChildView(scroll_view
);
1520 ui::GestureEvent
begin(
1525 ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN
));
1526 widget
->OnGestureEvent(&begin
);
1527 ui::GestureEvent
update(
1532 ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE
, 20, 10));
1533 widget
->OnGestureEvent(&update
);
1534 ui::GestureEvent
end(25,
1538 ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END
));
1539 widget
->OnGestureEvent(&end
);
1541 EXPECT_EQ(1, noscroll_view
->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN
));
1542 EXPECT_EQ(0, noscroll_view
->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE
));
1543 EXPECT_EQ(0, noscroll_view
->GetEventCount(ui::ET_GESTURE_SCROLL_END
));
1547 ui::GestureEvent
begin(
1552 ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN
));
1553 widget
->OnGestureEvent(&begin
);
1554 ui::GestureEvent
update(
1559 ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE
, 20, 10));
1560 widget
->OnGestureEvent(&update
);
1561 ui::GestureEvent
end(85,
1565 ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END
));
1566 widget
->OnGestureEvent(&end
);
1568 EXPECT_EQ(1, scroll_view
->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN
));
1569 EXPECT_EQ(1, scroll_view
->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE
));
1570 EXPECT_EQ(1, scroll_view
->GetEventCount(ui::ET_GESTURE_SCROLL_END
));
1576 // Tests that event-handlers installed on the RootView get triggered correctly.
1577 // TODO(tdanderson): Clean up this test as part of crbug.com/355680.
1578 TEST_F(WidgetTest
, EventHandlersOnRootView
) {
1579 Widget
* widget
= CreateTopLevelNativeWidget();
1580 View
* root_view
= widget
->GetRootView();
1582 scoped_ptr
<EventCountView
> view(new EventCountView());
1583 view
->set_owned_by_client();
1584 view
->SetBounds(0, 0, 20, 20);
1585 root_view
->AddChildView(view
.get());
1587 EventCountHandler h1
;
1588 root_view
->AddPreTargetHandler(&h1
);
1590 EventCountHandler h2
;
1591 root_view
->AddPostTargetHandler(&h2
);
1593 widget
->SetBounds(gfx::Rect(0, 0, 100, 100));
1596 // Dispatch a ui::ET_SCROLL event. The event remains unhandled and should
1597 // bubble up the views hierarchy to be re-dispatched on the root view.
1598 ui::ScrollEvent
scroll(ui::ET_SCROLL
,
1600 ui::EventTimeForNow(),
1605 widget
->OnScrollEvent(&scroll
);
1606 EXPECT_EQ(2, h1
.GetEventCount(ui::ET_SCROLL
));
1607 EXPECT_EQ(1, view
->GetEventCount(ui::ET_SCROLL
));
1608 EXPECT_EQ(2, h2
.GetEventCount(ui::ET_SCROLL
));
1610 // Unhandled scroll events are turned into wheel events and re-dispatched.
1611 EXPECT_EQ(1, h1
.GetEventCount(ui::ET_MOUSEWHEEL
));
1612 EXPECT_EQ(1, view
->GetEventCount(ui::ET_MOUSEWHEEL
));
1613 EXPECT_EQ(1, h2
.GetEventCount(ui::ET_MOUSEWHEEL
));
1616 view
->ResetCounts();
1619 // Dispatch a ui::ET_SCROLL_FLING_START event. The event remains unhandled and
1620 // should bubble up the views hierarchy to be re-dispatched on the root view.
1621 ui::ScrollEvent
fling(ui::ET_SCROLL_FLING_START
,
1623 ui::EventTimeForNow(),
1628 widget
->OnScrollEvent(&fling
);
1629 EXPECT_EQ(2, h1
.GetEventCount(ui::ET_SCROLL_FLING_START
));
1630 EXPECT_EQ(1, view
->GetEventCount(ui::ET_SCROLL_FLING_START
));
1631 EXPECT_EQ(2, h2
.GetEventCount(ui::ET_SCROLL_FLING_START
));
1633 // Unhandled scroll events which are not of type ui::ET_SCROLL should not
1634 // be turned into wheel events and re-dispatched.
1635 EXPECT_EQ(0, h1
.GetEventCount(ui::ET_MOUSEWHEEL
));
1636 EXPECT_EQ(0, view
->GetEventCount(ui::ET_MOUSEWHEEL
));
1637 EXPECT_EQ(0, h2
.GetEventCount(ui::ET_MOUSEWHEEL
));
1640 view
->ResetCounts();
1643 // Change the handle mode of |view| so that events are marked as handled at
1644 // the target phase.
1645 view
->set_handle_mode(EventCountView::CONSUME_EVENTS
);
1647 // Dispatch a ui::ET_GESTURE_TAP_DOWN and a ui::ET_GESTURE_TAP_CANCEL event.
1648 // The events are handled at the target phase and should not reach the
1649 // post-target handler.
1650 ui::GestureEvent
tap_down(5,
1653 ui::EventTimeForNow(),
1654 ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN
));
1655 widget
->OnGestureEvent(&tap_down
);
1656 EXPECT_EQ(1, h1
.GetEventCount(ui::ET_GESTURE_TAP_DOWN
));
1657 EXPECT_EQ(1, view
->GetEventCount(ui::ET_GESTURE_TAP_DOWN
));
1658 EXPECT_EQ(0, h2
.GetEventCount(ui::ET_GESTURE_TAP_DOWN
));
1660 ui::GestureEvent
tap_cancel(
1664 ui::EventTimeForNow(),
1665 ui::GestureEventDetails(ui::ET_GESTURE_TAP_CANCEL
));
1666 widget
->OnGestureEvent(&tap_cancel
);
1667 EXPECT_EQ(1, h1
.GetEventCount(ui::ET_GESTURE_TAP_CANCEL
));
1668 EXPECT_EQ(1, view
->GetEventCount(ui::ET_GESTURE_TAP_CANCEL
));
1669 EXPECT_EQ(0, h2
.GetEventCount(ui::ET_GESTURE_TAP_CANCEL
));
1672 view
->ResetCounts();
1675 // Dispatch a ui::ET_SCROLL event. The event is handled at the target phase
1676 // and should not reach the post-target handler.
1677 ui::ScrollEvent
consumed_scroll(ui::ET_SCROLL
,
1679 ui::EventTimeForNow(),
1684 widget
->OnScrollEvent(&consumed_scroll
);
1685 EXPECT_EQ(1, h1
.GetEventCount(ui::ET_SCROLL
));
1686 EXPECT_EQ(1, view
->GetEventCount(ui::ET_SCROLL
));
1687 EXPECT_EQ(0, h2
.GetEventCount(ui::ET_SCROLL
));
1689 // Handled scroll events are not turned into wheel events and re-dispatched.
1690 EXPECT_EQ(0, h1
.GetEventCount(ui::ET_MOUSEWHEEL
));
1691 EXPECT_EQ(0, view
->GetEventCount(ui::ET_MOUSEWHEEL
));
1692 EXPECT_EQ(0, h2
.GetEventCount(ui::ET_MOUSEWHEEL
));
1697 TEST_F(WidgetTest
, SynthesizeMouseMoveEvent
) {
1698 Widget
* widget
= CreateTopLevelNativeWidget();
1699 View
* root_view
= widget
->GetRootView();
1701 EventCountView
* v1
= new EventCountView();
1702 v1
->SetBounds(0, 0, 10, 10);
1703 root_view
->AddChildView(v1
);
1704 EventCountView
* v2
= new EventCountView();
1705 v2
->SetBounds(0, 10, 10, 10);
1706 root_view
->AddChildView(v2
);
1708 gfx::Point
cursor_location(5, 5);
1709 ui::MouseEvent
move(ui::ET_MOUSE_MOVED
, cursor_location
, cursor_location
,
1710 ui::EventTimeForNow(), ui::EF_NONE
, ui::EF_NONE
);
1711 widget
->OnMouseEvent(&move
);
1713 EXPECT_EQ(1, v1
->GetEventCount(ui::ET_MOUSE_ENTERED
));
1714 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_MOUSE_ENTERED
));
1717 v2
->SetBounds(0, 0, 10, 10);
1718 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_MOUSE_ENTERED
));
1720 widget
->SynthesizeMouseMoveEvent();
1721 EXPECT_EQ(1, v2
->GetEventCount(ui::ET_MOUSE_ENTERED
));
1726 // No touch on desktop Mac. Tracked in http://crbug.com/445520.
1727 #if !defined(OS_MACOSX) || defined(USE_AURA)
1731 // ui::EventHandler which handles all mouse press events.
1732 class MousePressEventConsumer
: public ui::EventHandler
{
1734 MousePressEventConsumer() {}
1737 // ui::EventHandler:
1738 void OnMouseEvent(ui::MouseEvent
* event
) override
{
1739 if (event
->type() == ui::ET_MOUSE_PRESSED
)
1740 event
->SetHandled();
1743 DISALLOW_COPY_AND_ASSIGN(MousePressEventConsumer
);
1748 // Test that mouse presses and mouse releases are dispatched normally when a
1750 TEST_F(WidgetTest
, MouseEventDispatchWhileTouchIsDown
) {
1751 Widget
* widget
= CreateTopLevelNativeWidget();
1753 widget
->SetSize(gfx::Size(300, 300));
1755 EventCountView
* event_count_view
= new EventCountView();
1756 event_count_view
->SetBounds(0, 0, 300, 300);
1757 widget
->GetRootView()->AddChildView(event_count_view
);
1759 MousePressEventConsumer consumer
;
1760 event_count_view
->AddPostTargetHandler(&consumer
);
1762 ui::test::EventGenerator
generator(GetContext(), widget
->GetNativeWindow());
1763 generator
.PressTouch();
1764 generator
.ClickLeftButton();
1766 EXPECT_EQ(1, event_count_view
->GetEventCount(ui::ET_MOUSE_PRESSED
));
1767 EXPECT_EQ(1, event_count_view
->GetEventCount(ui::ET_MOUSE_RELEASED
));
1772 #endif // !defined(OS_MACOSX) || defined(USE_AURA)
1774 // Verifies WindowClosing() is invoked correctly on the delegate when a Widget
1776 TEST_F(WidgetTest
, SingleWindowClosing
) {
1777 TestDesktopWidgetDelegate delegate
;
1778 delegate
.InitWidget(CreateParams(Widget::InitParams::TYPE_WINDOW
));
1779 EXPECT_EQ(0, delegate
.window_closing_count());
1780 delegate
.GetWidget()->CloseNow();
1781 EXPECT_EQ(1, delegate
.window_closing_count());
1784 class WidgetWindowTitleTest
: public WidgetTest
{
1786 void RunTest(bool desktop_native_widget
) {
1787 Widget
* widget
= new Widget(); // Destroyed by CloseNow() below.
1788 Widget::InitParams init_params
=
1789 CreateParams(Widget::InitParams::TYPE_WINDOW
);
1790 widget
->Init(init_params
);
1792 #if !defined(OS_CHROMEOS)
1793 if (desktop_native_widget
)
1794 init_params
.native_widget
= new PlatformDesktopNativeWidget(widget
);
1796 DCHECK(!desktop_native_widget
)
1797 << "DesktopNativeWidget does not exist on non-Aura or on ChromeOS.";
1800 internal::NativeWidgetPrivate
* native_widget
=
1801 widget
->native_widget_private();
1803 base::string16 empty
;
1804 base::string16
s1(base::UTF8ToUTF16("Title1"));
1805 base::string16
s2(base::UTF8ToUTF16("Title2"));
1806 base::string16
s3(base::UTF8ToUTF16("TitleLong"));
1808 // The widget starts with no title, setting empty should not change
1810 EXPECT_FALSE(native_widget
->SetWindowTitle(empty
));
1811 // Setting the title to something non-empty should cause a change.
1812 EXPECT_TRUE(native_widget
->SetWindowTitle(s1
));
1813 // Setting the title to something else with the same length should cause a
1815 EXPECT_TRUE(native_widget
->SetWindowTitle(s2
));
1816 // Setting the title to something else with a different length should cause
1818 EXPECT_TRUE(native_widget
->SetWindowTitle(s3
));
1819 // Setting the title to the same thing twice should not cause a change.
1820 EXPECT_FALSE(native_widget
->SetWindowTitle(s3
));
1826 TEST_F(WidgetWindowTitleTest
, SetWindowTitleChanged_NativeWidget
) {
1827 // Use the default NativeWidget.
1828 bool desktop_native_widget
= false;
1829 RunTest(desktop_native_widget
);
1832 // DesktopNativeWidget does not exist on non-Aura or on ChromeOS.
1833 #if !defined(OS_CHROMEOS)
1834 TEST_F(WidgetWindowTitleTest
, SetWindowTitleChanged_DesktopNativeWidget
) {
1835 // Override to use a DesktopNativeWidget.
1836 bool desktop_native_widget
= true;
1837 RunTest(desktop_native_widget
);
1839 #endif // !OS_CHROMEOS
1841 TEST_F(WidgetTest
, WidgetDeleted_InOnMousePressed
) {
1842 Widget
* widget
= new Widget
;
1843 Widget::InitParams params
=
1844 CreateParams(views::Widget::InitParams::TYPE_POPUP
);
1845 widget
->Init(params
);
1847 widget
->SetContentsView(new CloseWidgetView(ui::ET_MOUSE_PRESSED
));
1849 widget
->SetSize(gfx::Size(100, 100));
1852 ui::test::EventGenerator
generator(GetContext(), widget
->GetNativeWindow());
1854 WidgetDeletionObserver
deletion_observer(widget
);
1855 generator
.ClickLeftButton();
1856 EXPECT_FALSE(deletion_observer
.IsWidgetAlive());
1858 // Yay we did not crash!
1861 // No touch on desktop Mac. Tracked in http://crbug.com/445520.
1862 #if !defined(OS_MACOSX) || defined(USE_AURA)
1864 TEST_F(WidgetTest
, WidgetDeleted_InDispatchGestureEvent
) {
1865 Widget
* widget
= new Widget
;
1866 Widget::InitParams params
=
1867 CreateParams(views::Widget::InitParams::TYPE_POPUP
);
1868 widget
->Init(params
);
1870 widget
->SetContentsView(new CloseWidgetView(ui::ET_GESTURE_TAP_DOWN
));
1872 widget
->SetSize(gfx::Size(100, 100));
1875 ui::test::EventGenerator
generator(GetContext(), widget
->GetNativeWindow());
1877 WidgetDeletionObserver
deletion_observer(widget
);
1878 generator
.GestureTapAt(widget
->GetWindowBoundsInScreen().CenterPoint());
1879 EXPECT_FALSE(deletion_observer
.IsWidgetAlive());
1881 // Yay we did not crash!
1884 #endif // !defined(OS_MACOSX) || defined(USE_AURA)
1886 // See description of RunGetNativeThemeFromDestructor() for details.
1887 class GetNativeThemeFromDestructorView
: public WidgetDelegateView
{
1889 GetNativeThemeFromDestructorView() {}
1890 ~GetNativeThemeFromDestructorView() override
{ VerifyNativeTheme(); }
1892 View
* GetContentsView() override
{ return this; }
1895 void VerifyNativeTheme() {
1896 ASSERT_TRUE(GetNativeTheme() != NULL
);
1899 DISALLOW_COPY_AND_ASSIGN(GetNativeThemeFromDestructorView
);
1902 // Verifies GetNativeTheme() from the destructor of a WidgetDelegateView doesn't
1903 // crash. |is_first_run| is true if this is the first call. A return value of
1904 // true indicates this should be run again with a value of false.
1905 // First run uses DesktopNativeWidgetAura (if possible). Second run doesn't.
1906 bool RunGetNativeThemeFromDestructor(const Widget::InitParams
& in_params
,
1907 bool is_first_run
) {
1908 bool needs_second_run
= false;
1909 // Destroyed by CloseNow() below.
1910 Widget
* widget
= new Widget
;
1911 Widget::InitParams
params(in_params
);
1912 // Deletes itself when the Widget is destroyed.
1913 params
.delegate
= new GetNativeThemeFromDestructorView
;
1914 #if !defined(OS_CHROMEOS)
1916 params
.native_widget
= new PlatformDesktopNativeWidget(widget
);
1917 needs_second_run
= true;
1920 widget
->Init(params
);
1922 return needs_second_run
;
1925 // See description of RunGetNativeThemeFromDestructor() for details.
1926 TEST_F(WidgetTest
, GetNativeThemeFromDestructor
) {
1927 Widget::InitParams params
= CreateParams(Widget::InitParams::TYPE_POPUP
);
1928 if (RunGetNativeThemeFromDestructor(params
, true))
1929 RunGetNativeThemeFromDestructor(params
, false);
1932 // Used by HideCloseDestroy. Allows setting a boolean when the widget is
1934 class CloseDestroysWidget
: public Widget
{
1936 explicit CloseDestroysWidget(bool* destroyed
)
1937 : destroyed_(destroyed
) {
1940 ~CloseDestroysWidget() override
{
1943 base::MessageLoop::current()->QuitNow();
1947 void Detach() { destroyed_
= NULL
; }
1950 // If non-null set to true from destructor.
1953 DISALLOW_COPY_AND_ASSIGN(CloseDestroysWidget
);
1956 // An observer that registers that an animation has ended.
1957 class AnimationEndObserver
: public ui::ImplicitAnimationObserver
{
1959 AnimationEndObserver() : animation_completed_(false) {}
1960 ~AnimationEndObserver() override
{}
1962 bool animation_completed() const { return animation_completed_
; }
1964 // ui::ImplicitAnimationObserver:
1965 void OnImplicitAnimationsCompleted() override
{ animation_completed_
= true; }
1968 bool animation_completed_
;
1970 DISALLOW_COPY_AND_ASSIGN(AnimationEndObserver
);
1973 // An observer that registers the bounds of a widget on destruction.
1974 class WidgetBoundsObserver
: public WidgetObserver
{
1976 WidgetBoundsObserver() {}
1977 ~WidgetBoundsObserver() override
{}
1979 gfx::Rect
bounds() { return bounds_
; }
1982 void OnWidgetDestroying(Widget
* widget
) override
{
1983 EXPECT_TRUE(widget
->GetNativeWindow());
1984 bounds_
= widget
->GetWindowBoundsInScreen();
1990 DISALLOW_COPY_AND_ASSIGN(WidgetBoundsObserver
);
1993 // Verifies Close() results in destroying.
1994 TEST_F(WidgetTest
, CloseDestroys
) {
1995 bool destroyed
= false;
1996 CloseDestroysWidget
* widget
= new CloseDestroysWidget(&destroyed
);
1997 Widget::InitParams params
=
1998 CreateParams(views::Widget::InitParams::TYPE_MENU
);
1999 params
.opacity
= Widget::InitParams::OPAQUE_WINDOW
;
2000 #if !defined(OS_CHROMEOS)
2001 params
.native_widget
= new PlatformDesktopNativeWidget(widget
);
2003 widget
->Init(params
);
2007 EXPECT_FALSE(destroyed
);
2008 // Run the message loop as Close() asynchronously deletes.
2009 base::RunLoop().Run();
2010 EXPECT_TRUE(destroyed
);
2011 // Close() should destroy the widget. If not we'll cleanup to avoid leaks.
2018 // Tests that killing a widget while animating it does not crash.
2019 TEST_F(WidgetTest
, CloseWidgetWhileAnimating
) {
2020 scoped_ptr
<Widget
> widget(new Widget
);
2021 Widget::InitParams params
= CreateParams(Widget::InitParams::TYPE_POPUP
);
2022 params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
2023 params
.bounds
= gfx::Rect(50, 50, 250, 250);
2024 widget
->Init(params
);
2025 AnimationEndObserver animation_observer
;
2026 WidgetBoundsObserver widget_observer
;
2027 gfx::Rect
bounds(0, 0, 50, 50);
2029 // Normal animations for tests have ZERO_DURATION, make sure we are actually
2030 // animating the movement.
2031 ui::ScopedAnimationDurationScaleMode
animation_scale_mode(
2032 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION
);
2033 ui::ScopedLayerAnimationSettings
animation_settings(
2034 widget
->GetLayer()->GetAnimator());
2035 animation_settings
.AddObserver(&animation_observer
);
2036 widget
->AddObserver(&widget_observer
);
2039 // Animate the bounds change.
2040 widget
->SetBounds(bounds
);
2042 EXPECT_FALSE(animation_observer
.animation_completed());
2044 EXPECT_TRUE(animation_observer
.animation_completed());
2045 EXPECT_EQ(widget_observer
.bounds(), bounds
);
2048 // Test that the NativeWidget is still valid during OnNativeWidgetDestroying(),
2049 // and properties that depend on it are valid, when closed via CloseNow().
2050 TEST_F(WidgetTest
, ValidDuringOnNativeWidgetDestroyingFromCloseNow
) {
2051 Widget
* widget
= CreateNativeDesktopWidget();
2053 gfx::Rect
screen_rect(50, 50, 100, 100);
2054 widget
->SetBounds(screen_rect
);
2055 WidgetBoundsObserver observer
;
2056 widget
->AddObserver(&observer
);
2058 EXPECT_EQ(screen_rect
, observer
.bounds());
2061 // Test that the NativeWidget is still valid during OnNativeWidgetDestroying(),
2062 // and properties that depend on it are valid, when closed via Close().
2063 TEST_F(WidgetTest
, ValidDuringOnNativeWidgetDestroyingFromClose
) {
2064 Widget
* widget
= CreateNativeDesktopWidget();
2066 gfx::Rect
screen_rect(50, 50, 100, 100);
2067 widget
->SetBounds(screen_rect
);
2068 WidgetBoundsObserver observer
;
2069 widget
->AddObserver(&observer
);
2071 EXPECT_EQ(gfx::Rect(), observer
.bounds());
2072 base::RunLoop().RunUntilIdle();
2073 // Broken on Linux. See http://crbug.com/515379.
2074 #if !defined(OS_LINUX) || defined(OS_CHROMEOS)
2075 EXPECT_EQ(screen_rect
, observer
.bounds());
2079 // Tests that we do not crash when a Widget is destroyed by going out of
2080 // scope (as opposed to being explicitly deleted by its NativeWidget).
2081 TEST_F(WidgetTest
, NoCrashOnWidgetDelete
) {
2082 scoped_ptr
<Widget
> widget(new Widget
);
2083 Widget::InitParams params
= CreateParams(Widget::InitParams::TYPE_POPUP
);
2084 params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
2085 widget
->Init(params
);
2088 // Tests that we do not crash when a Widget is destroyed before it finishes
2089 // processing of pending input events in the message loop.
2090 TEST_F(WidgetTest
, NoCrashOnWidgetDeleteWithPendingEvents
) {
2091 scoped_ptr
<Widget
> widget(new Widget
);
2092 Widget::InitParams params
= CreateParams(Widget::InitParams::TYPE_WINDOW
);
2093 params
.bounds
= gfx::Rect(0, 0, 200, 200);
2094 params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
2095 widget
->Init(params
);
2098 ui::test::EventGenerator
generator(GetContext(), widget
->GetNativeWindow());
2099 generator
.MoveMouseTo(10, 10);
2101 // No touch on desktop Mac. Tracked in http://crbug.com/445520.
2102 #if defined(OS_MACOSX) && !defined(USE_AURA)
2103 generator
.ClickLeftButton();
2105 generator
.PressTouch();
2110 // A view that consumes mouse-pressed event and gesture-tap-down events.
2111 class RootViewTestView
: public View
{
2113 RootViewTestView(): View() {}
2116 bool OnMousePressed(const ui::MouseEvent
& event
) override
{ return true; }
2118 void OnGestureEvent(ui::GestureEvent
* event
) override
{
2119 if (event
->type() == ui::ET_GESTURE_TAP_DOWN
)
2120 event
->SetHandled();
2124 // Checks if RootView::*_handler_ fields are unset when widget is hidden.
2125 // Fails on chromium.webkit Windows bot, see crbug.com/264872.
2127 #define MAYBE_DisableTestRootViewHandlersWhenHidden\
2128 DISABLED_TestRootViewHandlersWhenHidden
2130 #define MAYBE_DisableTestRootViewHandlersWhenHidden\
2131 TestRootViewHandlersWhenHidden
2133 TEST_F(WidgetTest
, MAYBE_DisableTestRootViewHandlersWhenHidden
) {
2134 Widget
* widget
= CreateTopLevelNativeWidget();
2135 widget
->SetBounds(gfx::Rect(0, 0, 300, 300));
2136 View
* view
= new RootViewTestView();
2137 view
->SetBounds(0, 0, 300, 300);
2138 internal::RootView
* root_view
=
2139 static_cast<internal::RootView
*>(widget
->GetRootView());
2140 root_view
->AddChildView(view
);
2142 // Check RootView::mouse_pressed_handler_.
2144 EXPECT_EQ(NULL
, GetMousePressedHandler(root_view
));
2145 gfx::Point
click_location(45, 15);
2146 ui::MouseEvent
press(ui::ET_MOUSE_PRESSED
, click_location
, click_location
,
2147 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2148 ui::EF_LEFT_MOUSE_BUTTON
);
2149 widget
->OnMouseEvent(&press
);
2150 EXPECT_EQ(view
, GetMousePressedHandler(root_view
));
2152 EXPECT_EQ(NULL
, GetMousePressedHandler(root_view
));
2154 // Check RootView::mouse_move_handler_.
2156 EXPECT_EQ(NULL
, GetMouseMoveHandler(root_view
));
2157 gfx::Point
move_location(45, 15);
2158 ui::MouseEvent
move(ui::ET_MOUSE_MOVED
, move_location
, move_location
,
2159 ui::EventTimeForNow(), 0, 0);
2160 widget
->OnMouseEvent(&move
);
2161 EXPECT_EQ(view
, GetMouseMoveHandler(root_view
));
2163 EXPECT_EQ(NULL
, GetMouseMoveHandler(root_view
));
2165 // Check RootView::gesture_handler_.
2167 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2168 ui::GestureEvent
tap_down(15,
2172 ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN
));
2173 widget
->OnGestureEvent(&tap_down
);
2174 EXPECT_EQ(view
, GetGestureHandler(root_view
));
2176 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2181 // Convenience to make constructing a GestureEvent simpler.
2182 class GestureEventForTest
: public ui::GestureEvent
{
2184 GestureEventForTest(ui::EventType type
, int x
, int y
)
2189 ui::GestureEventDetails(type
)) {}
2191 GestureEventForTest(ui::GestureEventDetails details
, int x
, int y
)
2192 : GestureEvent(x
, y
, 0, base::TimeDelta(), details
) {}
2195 // Tests that the |gesture_handler_| member in RootView is always NULL
2196 // after the dispatch of a ui::ET_GESTURE_END event corresponding to
2197 // the release of the final touch point on the screen, but that
2198 // ui::ET_GESTURE_END events corresponding to the removal of any other touch
2199 // point do not modify |gesture_handler_|.
2200 TEST_F(WidgetTest
, GestureEndEvents
) {
2201 Widget
* widget
= CreateTopLevelNativeWidget();
2202 widget
->SetBounds(gfx::Rect(0, 0, 300, 300));
2203 EventCountView
* view
= new EventCountView();
2204 view
->SetBounds(0, 0, 300, 300);
2205 internal::RootView
* root_view
=
2206 static_cast<internal::RootView
*>(widget
->GetRootView());
2207 root_view
->AddChildView(view
);
2210 // If no gesture handler is set, a ui::ET_GESTURE_END event should not set
2211 // the gesture handler.
2212 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2213 GestureEventForTest
end(ui::ET_GESTURE_END
, 15, 15);
2214 widget
->OnGestureEvent(&end
);
2215 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2217 // Change the handle mode of |view| to indicate that it would like
2218 // to handle all events, then send a GESTURE_TAP to set the gesture handler.
2219 view
->set_handle_mode(EventCountView::CONSUME_EVENTS
);
2220 GestureEventForTest
tap(ui::ET_GESTURE_TAP
, 15, 15);
2221 widget
->OnGestureEvent(&tap
);
2222 EXPECT_TRUE(tap
.handled());
2223 EXPECT_EQ(view
, GetGestureHandler(root_view
));
2225 // The gesture handler should remain unchanged on a ui::ET_GESTURE_END
2226 // corresponding to a second touch point, but should be reset to NULL by a
2227 // ui::ET_GESTURE_END corresponding to the final touch point.
2228 ui::GestureEventDetails
details(ui::ET_GESTURE_END
);
2229 details
.set_touch_points(2);
2230 GestureEventForTest
end_second_touch_point(details
, 15, 15);
2231 widget
->OnGestureEvent(&end_second_touch_point
);
2232 EXPECT_EQ(view
, GetGestureHandler(root_view
));
2234 end
= GestureEventForTest(ui::ET_GESTURE_END
, 15, 15);
2235 widget
->OnGestureEvent(&end
);
2236 EXPECT_TRUE(end
.handled());
2237 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2239 // Send a GESTURE_TAP to set the gesture handler, then change the handle
2240 // mode of |view| to indicate that it does not want to handle any
2242 tap
= GestureEventForTest(ui::ET_GESTURE_TAP
, 15, 15);
2243 widget
->OnGestureEvent(&tap
);
2244 EXPECT_TRUE(tap
.handled());
2245 EXPECT_EQ(view
, GetGestureHandler(root_view
));
2246 view
->set_handle_mode(EventCountView::PROPAGATE_EVENTS
);
2248 // The gesture handler should remain unchanged on a ui::ET_GESTURE_END
2249 // corresponding to a second touch point, but should be reset to NULL by a
2250 // ui::ET_GESTURE_END corresponding to the final touch point.
2251 end_second_touch_point
= GestureEventForTest(details
, 15, 15);
2252 widget
->OnGestureEvent(&end_second_touch_point
);
2253 EXPECT_EQ(view
, GetGestureHandler(root_view
));
2255 end
= GestureEventForTest(ui::ET_GESTURE_END
, 15, 15);
2256 widget
->OnGestureEvent(&end
);
2257 EXPECT_FALSE(end
.handled());
2258 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2263 // Tests that gesture events which should not be processed (because
2264 // RootView::OnEventProcessingStarted() has marked them as handled) are not
2265 // dispatched to any views.
2266 TEST_F(WidgetTest
, GestureEventsNotProcessed
) {
2267 Widget
* widget
= CreateTopLevelNativeWidget();
2268 widget
->SetBounds(gfx::Rect(0, 0, 300, 300));
2270 // Define a hierarchy of four views (coordinates are in
2271 // their parent coordinate space).
2272 // v1 (0, 0, 300, 300)
2273 // v2 (0, 0, 100, 100)
2274 // v3 (0, 0, 50, 50)
2276 EventCountView
* v1
= new EventCountView();
2277 v1
->SetBounds(0, 0, 300, 300);
2278 EventCountView
* v2
= new EventCountView();
2279 v2
->SetBounds(0, 0, 100, 100);
2280 EventCountView
* v3
= new EventCountView();
2281 v3
->SetBounds(0, 0, 50, 50);
2282 EventCountView
* v4
= new EventCountView();
2283 v4
->SetBounds(0, 0, 10, 10);
2284 internal::RootView
* root_view
=
2285 static_cast<internal::RootView
*>(widget
->GetRootView());
2286 root_view
->AddChildView(v1
);
2287 v1
->AddChildView(v2
);
2288 v2
->AddChildView(v3
);
2289 v3
->AddChildView(v4
);
2293 // ui::ET_GESTURE_BEGIN events should never be seen by any view, but
2294 // they should be marked as handled by OnEventProcessingStarted().
2295 GestureEventForTest
begin(ui::ET_GESTURE_BEGIN
, 5, 5);
2296 widget
->OnGestureEvent(&begin
);
2297 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_BEGIN
));
2298 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_BEGIN
));
2299 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_BEGIN
));
2300 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_BEGIN
));
2301 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2302 EXPECT_TRUE(begin
.handled());
2308 // ui::ET_GESTURE_END events should not be seen by any view when there is
2309 // no default gesture handler set, but they should be marked as handled by
2310 // OnEventProcessingStarted().
2311 GestureEventForTest
end(ui::ET_GESTURE_END
, 5, 5);
2312 widget
->OnGestureEvent(&end
);
2313 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_END
));
2314 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_END
));
2315 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_END
));
2316 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_END
));
2317 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2318 EXPECT_TRUE(end
.handled());
2324 // ui::ET_GESTURE_END events not corresponding to the release of the
2325 // final touch point should never be seen by any view, but they should
2326 // be marked as handled by OnEventProcessingStarted().
2327 ui::GestureEventDetails
details(ui::ET_GESTURE_END
);
2328 details
.set_touch_points(2);
2329 GestureEventForTest
end_second_touch_point(details
, 5, 5);
2330 widget
->OnGestureEvent(&end_second_touch_point
);
2331 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_END
));
2332 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_END
));
2333 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_END
));
2334 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_END
));
2335 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2336 EXPECT_TRUE(end_second_touch_point
.handled());
2342 // ui::ET_GESTURE_SCROLL_UPDATE events should never be seen by any view when
2343 // there is no default gesture handler set, but they should be marked as
2344 // handled by OnEventProcessingStarted().
2345 GestureEventForTest
scroll_update(ui::ET_GESTURE_SCROLL_UPDATE
, 5, 5);
2346 widget
->OnGestureEvent(&scroll_update
);
2347 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE
));
2348 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE
));
2349 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE
));
2350 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE
));
2351 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2352 EXPECT_TRUE(scroll_update
.handled());
2358 // ui::ET_GESTURE_SCROLL_END events should never be seen by any view when
2359 // there is no default gesture handler set, but they should be marked as
2360 // handled by OnEventProcessingStarted().
2361 GestureEventForTest
scroll_end(ui::ET_GESTURE_SCROLL_END
, 5, 5);
2362 widget
->OnGestureEvent(&scroll_end
);
2363 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_SCROLL_END
));
2364 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_SCROLL_END
));
2365 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_SCROLL_END
));
2366 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_SCROLL_END
));
2367 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2368 EXPECT_TRUE(scroll_end
.handled());
2374 // ui::ET_SCROLL_FLING_START events should never be seen by any view when
2375 // there is no default gesture handler set, but they should be marked as
2376 // handled by OnEventProcessingStarted().
2377 GestureEventForTest
scroll_fling_start(ui::ET_SCROLL_FLING_START
, 5, 5);
2378 widget
->OnGestureEvent(&scroll_fling_start
);
2379 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_SCROLL_FLING_START
));
2380 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_SCROLL_FLING_START
));
2381 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_SCROLL_FLING_START
));
2382 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_SCROLL_FLING_START
));
2383 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2384 EXPECT_TRUE(scroll_fling_start
.handled());
2393 // Tests that a (non-scroll) gesture event is dispatched to the correct views
2394 // in a view hierarchy and that the default gesture handler in RootView is set
2396 TEST_F(WidgetTest
, GestureEventDispatch
) {
2397 Widget
* widget
= CreateTopLevelNativeWidget();
2398 widget
->SetBounds(gfx::Rect(0, 0, 300, 300));
2400 // Define a hierarchy of four views (coordinates are in
2401 // their parent coordinate space).
2402 // v1 (0, 0, 300, 300)
2403 // v2 (0, 0, 100, 100)
2404 // v3 (0, 0, 50, 50)
2406 EventCountView
* v1
= new EventCountView();
2407 v1
->SetBounds(0, 0, 300, 300);
2408 EventCountView
* v2
= new EventCountView();
2409 v2
->SetBounds(0, 0, 100, 100);
2410 EventCountView
* v3
= new EventCountView();
2411 v3
->SetBounds(0, 0, 50, 50);
2412 EventCountView
* v4
= new EventCountView();
2413 v4
->SetBounds(0, 0, 10, 10);
2414 internal::RootView
* root_view
=
2415 static_cast<internal::RootView
*>(widget
->GetRootView());
2416 root_view
->AddChildView(v1
);
2417 v1
->AddChildView(v2
);
2418 v2
->AddChildView(v3
);
2419 v3
->AddChildView(v4
);
2423 // No gesture handler is set in the root view and none of the views in the
2424 // view hierarchy handle a ui::ET_GESTURE_TAP event. In this case the tap
2425 // event should be dispatched to all views in the hierarchy, the gesture
2426 // handler should remain unset, and the event should remain unhandled.
2427 GestureEventForTest
tap(ui::ET_GESTURE_TAP
, 5, 5);
2428 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2429 widget
->OnGestureEvent(&tap
);
2430 EXPECT_EQ(1, v1
->GetEventCount(ui::ET_GESTURE_TAP
));
2431 EXPECT_EQ(1, v2
->GetEventCount(ui::ET_GESTURE_TAP
));
2432 EXPECT_EQ(1, v3
->GetEventCount(ui::ET_GESTURE_TAP
));
2433 EXPECT_EQ(1, v4
->GetEventCount(ui::ET_GESTURE_TAP
));
2434 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2435 EXPECT_FALSE(tap
.handled());
2437 // No gesture handler is set in the root view and |v1|, |v2|, and |v3| all
2438 // handle a ui::ET_GESTURE_TAP event. In this case the tap event should be
2439 // dispatched to |v4| and |v3|, the gesture handler should be set to |v3|,
2440 // and the event should be marked as handled.
2445 v1
->set_handle_mode(EventCountView::CONSUME_EVENTS
);
2446 v2
->set_handle_mode(EventCountView::CONSUME_EVENTS
);
2447 v3
->set_handle_mode(EventCountView::CONSUME_EVENTS
);
2448 tap
= GestureEventForTest(ui::ET_GESTURE_TAP
, 5, 5);
2449 widget
->OnGestureEvent(&tap
);
2450 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_TAP
));
2451 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_TAP
));
2452 EXPECT_EQ(1, v3
->GetEventCount(ui::ET_GESTURE_TAP
));
2453 EXPECT_EQ(1, v4
->GetEventCount(ui::ET_GESTURE_TAP
));
2454 EXPECT_EQ(v3
, GetGestureHandler(root_view
));
2455 EXPECT_TRUE(tap
.handled());
2457 // The gesture handler is set to |v3| and all views handle all gesture event
2458 // types. In this case subsequent gesture events should only be dispatched to
2459 // |v3| and marked as handled. The gesture handler should remain as |v3|.
2464 v4
->set_handle_mode(EventCountView::CONSUME_EVENTS
);
2465 tap
= GestureEventForTest(ui::ET_GESTURE_TAP
, 5, 5);
2466 widget
->OnGestureEvent(&tap
);
2467 EXPECT_TRUE(tap
.handled());
2468 GestureEventForTest
show_press(ui::ET_GESTURE_SHOW_PRESS
, 5, 5);
2469 widget
->OnGestureEvent(&show_press
);
2470 tap
= GestureEventForTest(ui::ET_GESTURE_TAP
, 5, 5);
2471 widget
->OnGestureEvent(&tap
);
2472 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_TAP
));
2473 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_TAP
));
2474 EXPECT_EQ(2, v3
->GetEventCount(ui::ET_GESTURE_TAP
));
2475 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_TAP
));
2476 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_SHOW_PRESS
));
2477 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_SHOW_PRESS
));
2478 EXPECT_EQ(1, v3
->GetEventCount(ui::ET_GESTURE_SHOW_PRESS
));
2479 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_SHOW_PRESS
));
2480 EXPECT_TRUE(tap
.handled());
2481 EXPECT_TRUE(show_press
.handled());
2482 EXPECT_EQ(v3
, GetGestureHandler(root_view
));
2484 // The gesture handler is set to |v3|, but |v3| does not handle
2485 // ui::ET_GESTURE_TAP events. In this case a tap gesture should be dispatched
2486 // only to |v3|, but the event should remain unhandled. The gesture handler
2487 // should remain as |v3|.
2492 v3
->set_handle_mode(EventCountView::PROPAGATE_EVENTS
);
2493 tap
= GestureEventForTest(ui::ET_GESTURE_TAP
, 5, 5);
2494 widget
->OnGestureEvent(&tap
);
2495 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_TAP
));
2496 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_TAP
));
2497 EXPECT_EQ(1, v3
->GetEventCount(ui::ET_GESTURE_TAP
));
2498 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_TAP
));
2499 EXPECT_FALSE(tap
.handled());
2500 EXPECT_EQ(v3
, GetGestureHandler(root_view
));
2505 // Tests that gesture scroll events will change the default gesture handler in
2506 // RootView if the current handler to which they are dispatched does not handle
2507 // gesture scroll events.
2508 TEST_F(WidgetTest
, ScrollGestureEventDispatch
) {
2509 Widget
* widget
= CreateTopLevelNativeWidget();
2510 widget
->SetBounds(gfx::Rect(0, 0, 300, 300));
2512 // Define a hierarchy of four views (coordinates are in
2513 // their parent coordinate space).
2514 // v1 (0, 0, 300, 300)
2515 // v2 (0, 0, 100, 100)
2516 // v3 (0, 0, 50, 50)
2518 EventCountView
* v1
= new EventCountView();
2519 v1
->SetBounds(0, 0, 300, 300);
2520 EventCountView
* v2
= new EventCountView();
2521 v2
->SetBounds(0, 0, 100, 100);
2522 EventCountView
* v3
= new EventCountView();
2523 v3
->SetBounds(0, 0, 50, 50);
2524 EventCountView
* v4
= new EventCountView();
2525 v4
->SetBounds(0, 0, 10, 10);
2526 internal::RootView
* root_view
=
2527 static_cast<internal::RootView
*>(widget
->GetRootView());
2528 root_view
->AddChildView(v1
);
2529 v1
->AddChildView(v2
);
2530 v2
->AddChildView(v3
);
2531 v3
->AddChildView(v4
);
2535 // Change the handle mode of |v3| to indicate that it would like to handle
2537 v3
->set_handle_mode(EventCountView::CONSUME_EVENTS
);
2539 // When no gesture handler is set, dispatching a ui::ET_GESTURE_TAP_DOWN
2540 // should bubble up the views hierarchy until it reaches the first view
2541 // that will handle it (|v3|) and then sets the handler to |v3|.
2542 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2543 GestureEventForTest
tap_down(ui::ET_GESTURE_TAP_DOWN
, 5, 5);
2544 widget
->OnGestureEvent(&tap_down
);
2545 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_TAP_DOWN
));
2546 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_TAP_DOWN
));
2547 EXPECT_EQ(1, v3
->GetEventCount(ui::ET_GESTURE_TAP_DOWN
));
2548 EXPECT_EQ(1, v4
->GetEventCount(ui::ET_GESTURE_TAP_DOWN
));
2549 EXPECT_EQ(v3
, GetGestureHandler(root_view
));
2550 EXPECT_TRUE(tap_down
.handled());
2556 // A ui::ET_GESTURE_TAP_CANCEL event should be dispatched to |v3| directly.
2557 GestureEventForTest
tap_cancel(ui::ET_GESTURE_TAP_CANCEL
, 5, 5);
2558 widget
->OnGestureEvent(&tap_cancel
);
2559 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_TAP_CANCEL
));
2560 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_TAP_CANCEL
));
2561 EXPECT_EQ(1, v3
->GetEventCount(ui::ET_GESTURE_TAP_CANCEL
));
2562 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_TAP_CANCEL
));
2563 EXPECT_EQ(v3
, GetGestureHandler(root_view
));
2564 EXPECT_TRUE(tap_cancel
.handled());
2570 // Change the handle mode of |v3| to indicate that it would no longer like
2571 // to handle events, and change the mode of |v1| to indicate that it would
2572 // like to handle events.
2573 v3
->set_handle_mode(EventCountView::PROPAGATE_EVENTS
);
2574 v1
->set_handle_mode(EventCountView::CONSUME_EVENTS
);
2576 // Dispatch a ui::ET_GESTURE_SCROLL_BEGIN event. Because the current gesture
2577 // handler (|v3|) does not handle scroll events, the event should bubble up
2578 // the views hierarchy until it reaches the first view that will handle
2579 // it (|v1|) and then sets the handler to |v1|.
2580 GestureEventForTest
scroll_begin(ui::ET_GESTURE_SCROLL_BEGIN
, 5, 5);
2581 widget
->OnGestureEvent(&scroll_begin
);
2582 EXPECT_EQ(1, v1
->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN
));
2583 EXPECT_EQ(1, v2
->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN
));
2584 EXPECT_EQ(1, v3
->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN
));
2585 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN
));
2586 EXPECT_EQ(v1
, GetGestureHandler(root_view
));
2587 EXPECT_TRUE(scroll_begin
.handled());
2593 // A ui::ET_GESTURE_SCROLL_UPDATE event should be dispatched to |v1|
2595 GestureEventForTest
scroll_update(ui::ET_GESTURE_SCROLL_UPDATE
, 5, 5);
2596 widget
->OnGestureEvent(&scroll_update
);
2597 EXPECT_EQ(1, v1
->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE
));
2598 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE
));
2599 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE
));
2600 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE
));
2601 EXPECT_EQ(v1
, GetGestureHandler(root_view
));
2602 EXPECT_TRUE(scroll_update
.handled());
2608 // A ui::ET_GESTURE_SCROLL_END event should be dispatched to |v1|
2609 // directly and should not reset the gesture handler.
2610 GestureEventForTest
scroll_end(ui::ET_GESTURE_SCROLL_END
, 5, 5);
2611 widget
->OnGestureEvent(&scroll_end
);
2612 EXPECT_EQ(1, v1
->GetEventCount(ui::ET_GESTURE_SCROLL_END
));
2613 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_SCROLL_END
));
2614 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_SCROLL_END
));
2615 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_SCROLL_END
));
2616 EXPECT_EQ(v1
, GetGestureHandler(root_view
));
2617 EXPECT_TRUE(scroll_end
.handled());
2623 // A ui::ET_GESTURE_PINCH_BEGIN event (which is a non-scroll event) should
2624 // still be dispatched to |v1| directly.
2625 GestureEventForTest
pinch_begin(ui::ET_GESTURE_PINCH_BEGIN
, 5, 5);
2626 widget
->OnGestureEvent(&pinch_begin
);
2627 EXPECT_EQ(1, v1
->GetEventCount(ui::ET_GESTURE_PINCH_BEGIN
));
2628 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_PINCH_BEGIN
));
2629 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_PINCH_BEGIN
));
2630 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_PINCH_BEGIN
));
2631 EXPECT_EQ(v1
, GetGestureHandler(root_view
));
2632 EXPECT_TRUE(pinch_begin
.handled());
2638 // A ui::ET_GESTURE_END event should be dispatched to |v1| and should
2639 // set the gesture handler to NULL.
2640 GestureEventForTest
end(ui::ET_GESTURE_END
, 5, 5);
2641 widget
->OnGestureEvent(&end
);
2642 EXPECT_EQ(1, v1
->GetEventCount(ui::ET_GESTURE_END
));
2643 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_END
));
2644 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_END
));
2645 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_END
));
2646 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2647 EXPECT_TRUE(end
.handled());
2652 // A class used in WidgetTest.GestureEventLocationWhileBubbling to verify
2653 // that when a gesture event bubbles up a View hierarchy, the location
2654 // of a gesture event seen by each View is in the local coordinate space
2656 class GestureLocationView
: public EventCountView
{
2658 GestureLocationView() {}
2659 ~GestureLocationView() override
{}
2661 void set_expected_location(gfx::Point expected_location
) {
2662 expected_location_
= expected_location
;
2666 void OnGestureEvent(ui::GestureEvent
* event
) override
{
2667 EventCountView::OnGestureEvent(event
);
2669 // Verify that the location of |event| is in the local coordinate
2671 EXPECT_EQ(expected_location_
, event
->location());
2675 // The expected location of a gesture event dispatched to |this|.
2676 gfx::Point expected_location_
;
2678 DISALLOW_COPY_AND_ASSIGN(GestureLocationView
);
2681 // Verifies that the location of a gesture event is always in the local
2682 // coordinate space of the View receiving the event while bubbling.
2683 TEST_F(WidgetTest
, GestureEventLocationWhileBubbling
) {
2684 Widget
* widget
= CreateTopLevelNativeWidget();
2685 widget
->SetBounds(gfx::Rect(0, 0, 300, 300));
2687 // Define a hierarchy of three views (coordinates shown below are in the
2688 // coordinate space of the root view, but the coordinates used for
2689 // SetBounds() are in their parent coordinate space).
2690 // v1 (50, 50, 150, 150)
2691 // v2 (100, 70, 50, 80)
2692 // v3 (120, 100, 10, 10)
2693 GestureLocationView
* v1
= new GestureLocationView();
2694 v1
->SetBounds(50, 50, 150, 150);
2695 GestureLocationView
* v2
= new GestureLocationView();
2696 v2
->SetBounds(50, 20, 50, 80);
2697 GestureLocationView
* v3
= new GestureLocationView();
2698 v3
->SetBounds(20, 30, 10, 10);
2699 internal::RootView
* root_view
=
2700 static_cast<internal::RootView
*>(widget
->GetRootView());
2701 root_view
->AddChildView(v1
);
2702 v1
->AddChildView(v2
);
2703 v2
->AddChildView(v3
);
2707 // Define a GESTURE_TAP event located at (125, 105) in root view coordinates.
2708 // This event is contained within all of |v1|, |v2|, and |v3|.
2709 gfx::Point
location_in_root(125, 105);
2710 GestureEventForTest
tap(
2711 ui::ET_GESTURE_TAP
, location_in_root
.x(), location_in_root
.y());
2713 // Calculate the location of the event in the local coordinate spaces
2714 // of each of the views.
2715 gfx::Point
location_in_v1(ConvertPointFromWidgetToView(v1
, location_in_root
));
2716 EXPECT_EQ(gfx::Point(75, 55), location_in_v1
);
2717 gfx::Point
location_in_v2(ConvertPointFromWidgetToView(v2
, location_in_root
));
2718 EXPECT_EQ(gfx::Point(25, 35), location_in_v2
);
2719 gfx::Point
location_in_v3(ConvertPointFromWidgetToView(v3
, location_in_root
));
2720 EXPECT_EQ(gfx::Point(5, 5), location_in_v3
);
2722 // Dispatch the event. When each view receives the event, its location should
2723 // be in the local coordinate space of that view (see the check made by
2724 // GestureLocationView). After dispatch is complete the event's location
2725 // should be in the root coordinate space.
2726 v1
->set_expected_location(location_in_v1
);
2727 v2
->set_expected_location(location_in_v2
);
2728 v3
->set_expected_location(location_in_v3
);
2729 widget
->OnGestureEvent(&tap
);
2730 EXPECT_EQ(location_in_root
, tap
.location());
2732 // Verify that each view did in fact see the event.
2733 EventCountView
* view1
= v1
;
2734 EventCountView
* view2
= v2
;
2735 EventCountView
* view3
= v3
;
2736 EXPECT_EQ(1, view1
->GetEventCount(ui::ET_GESTURE_TAP
));
2737 EXPECT_EQ(1, view2
->GetEventCount(ui::ET_GESTURE_TAP
));
2738 EXPECT_EQ(1, view3
->GetEventCount(ui::ET_GESTURE_TAP
));
2743 // Verifies that disabled views are permitted to be set as the default gesture
2744 // handler in RootView. Also verifies that gesture events targeted to a disabled
2745 // view are not actually dispatched to the view, but are still marked as
2747 TEST_F(WidgetTest
, DisabledGestureEventTarget
) {
2748 Widget
* widget
= CreateTopLevelNativeWidget();
2749 widget
->SetBounds(gfx::Rect(0, 0, 300, 300));
2751 // Define a hierarchy of four views (coordinates are in
2752 // their parent coordinate space).
2753 // v1 (0, 0, 300, 300)
2754 // v2 (0, 0, 100, 100)
2755 // v3 (0, 0, 50, 50)
2757 EventCountView
* v1
= new EventCountView();
2758 v1
->SetBounds(0, 0, 300, 300);
2759 EventCountView
* v2
= new EventCountView();
2760 v2
->SetBounds(0, 0, 100, 100);
2761 EventCountView
* v3
= new EventCountView();
2762 v3
->SetBounds(0, 0, 50, 50);
2763 EventCountView
* v4
= new EventCountView();
2764 v4
->SetBounds(0, 0, 10, 10);
2765 internal::RootView
* root_view
=
2766 static_cast<internal::RootView
*>(widget
->GetRootView());
2767 root_view
->AddChildView(v1
);
2768 v1
->AddChildView(v2
);
2769 v2
->AddChildView(v3
);
2770 v3
->AddChildView(v4
);
2774 // |v1|, |v2|, and |v3| all handle gesture events but |v3| is marked as
2776 v1
->set_handle_mode(EventCountView::CONSUME_EVENTS
);
2777 v2
->set_handle_mode(EventCountView::CONSUME_EVENTS
);
2778 v3
->set_handle_mode(EventCountView::CONSUME_EVENTS
);
2779 v3
->SetEnabled(false);
2781 // No gesture handler is set in the root view. In this case the tap event
2782 // should be dispatched only to |v4|, the gesture handler should be set to
2783 // |v3|, and the event should be marked as handled.
2784 GestureEventForTest
tap(ui::ET_GESTURE_TAP
, 5, 5);
2785 widget
->OnGestureEvent(&tap
);
2786 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_TAP
));
2787 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_TAP
));
2788 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_TAP
));
2789 EXPECT_EQ(1, v4
->GetEventCount(ui::ET_GESTURE_TAP
));
2790 EXPECT_EQ(v3
, GetGestureHandler(root_view
));
2791 EXPECT_TRUE(tap
.handled());
2797 // A subsequent gesture event should be marked as handled but not dispatched.
2798 tap
= GestureEventForTest(ui::ET_GESTURE_TAP
, 5, 5);
2799 widget
->OnGestureEvent(&tap
);
2800 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_TAP
));
2801 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_TAP
));
2802 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_TAP
));
2803 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_TAP
));
2804 EXPECT_EQ(v3
, GetGestureHandler(root_view
));
2805 EXPECT_TRUE(tap
.handled());
2811 // A GESTURE_END should reset the default gesture handler to NULL. It should
2812 // also not be dispatched to |v3| but still marked as handled.
2813 GestureEventForTest
end(ui::ET_GESTURE_END
, 5, 5);
2814 widget
->OnGestureEvent(&end
);
2815 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_END
));
2816 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_END
));
2817 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_END
));
2818 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_END
));
2819 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2820 EXPECT_TRUE(end
.handled());
2826 // Change the handle mode of |v3| to indicate that it would no longer like
2827 // to handle events which are dispatched to it.
2828 v3
->set_handle_mode(EventCountView::PROPAGATE_EVENTS
);
2830 // No gesture handler is set in the root view. In this case the tap event
2831 // should be dispatched only to |v4| and the event should be marked as
2832 // handled. Furthermore, the gesture handler should be set to
2833 // |v3|; even though |v3| does not explicitly handle events, it is a
2834 // valid target for the tap event because it is disabled.
2835 tap
= GestureEventForTest(ui::ET_GESTURE_TAP
, 5, 5);
2836 widget
->OnGestureEvent(&tap
);
2837 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_TAP
));
2838 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_TAP
));
2839 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_TAP
));
2840 EXPECT_EQ(1, v4
->GetEventCount(ui::ET_GESTURE_TAP
));
2841 EXPECT_EQ(v3
, GetGestureHandler(root_view
));
2842 EXPECT_TRUE(tap
.handled());
2848 // A GESTURE_END should reset the default gesture handler to NULL. It should
2849 // also not be dispatched to |v3| but still marked as handled.
2850 end
= GestureEventForTest(ui::ET_GESTURE_END
, 5, 5);
2851 widget
->OnGestureEvent(&end
);
2852 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_END
));
2853 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_END
));
2854 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_END
));
2855 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_END
));
2856 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2857 EXPECT_TRUE(end
.handled());
2862 // Test the result of Widget::GetAllChildWidgets().
2863 TEST_F(WidgetTest
, GetAllChildWidgets
) {
2864 // Create the following widget hierarchy:
2872 Widget
* toplevel
= CreateTopLevelPlatformWidget();
2873 Widget
* w1
= CreateChildPlatformWidget(toplevel
->GetNativeView());
2874 Widget
* w11
= CreateChildPlatformWidget(w1
->GetNativeView());
2875 Widget
* w2
= CreateChildPlatformWidget(toplevel
->GetNativeView());
2876 Widget
* w21
= CreateChildPlatformWidget(w2
->GetNativeView());
2877 Widget
* w22
= CreateChildPlatformWidget(w2
->GetNativeView());
2879 std::set
<Widget
*> expected
;
2880 expected
.insert(toplevel
);
2881 expected
.insert(w1
);
2882 expected
.insert(w11
);
2883 expected
.insert(w2
);
2884 expected
.insert(w21
);
2885 expected
.insert(w22
);
2887 std::set
<Widget
*> widgets
;
2888 Widget::GetAllChildWidgets(toplevel
->GetNativeView(), &widgets
);
2890 EXPECT_EQ(expected
.size(), widgets
.size());
2891 EXPECT_TRUE(std::equal(expected
.begin(), expected
.end(), widgets
.begin()));
2892 toplevel
->CloseNow();
2895 // Used by DestroyChildWidgetsInOrder. On destruction adds the supplied name to
2897 class DestroyedTrackingView
: public View
{
2899 DestroyedTrackingView(const std::string
& name
,
2900 std::vector
<std::string
>* add_to
)
2905 ~DestroyedTrackingView() override
{ add_to_
->push_back(name_
); }
2908 const std::string name_
;
2909 std::vector
<std::string
>* add_to_
;
2911 DISALLOW_COPY_AND_ASSIGN(DestroyedTrackingView
);
2914 class WidgetChildDestructionTest
: public WidgetTest
{
2916 WidgetChildDestructionTest() {}
2918 // Creates a top level and a child, destroys the child and verifies the views
2919 // of the child are destroyed before the views of the parent.
2920 void RunDestroyChildWidgetsTest(bool top_level_has_desktop_native_widget_aura
,
2921 bool child_has_desktop_native_widget_aura
) {
2922 // When a View is destroyed its name is added here.
2923 std::vector
<std::string
> destroyed
;
2925 Widget
* top_level
= new Widget
;
2926 Widget::InitParams params
=
2927 CreateParams(views::Widget::InitParams::TYPE_WINDOW
);
2928 #if !defined(OS_CHROMEOS)
2929 if (top_level_has_desktop_native_widget_aura
)
2930 params
.native_widget
= new PlatformDesktopNativeWidget(top_level
);
2932 top_level
->Init(params
);
2933 top_level
->GetRootView()->AddChildView(
2934 new DestroyedTrackingView("parent", &destroyed
));
2937 Widget
* child
= new Widget
;
2938 Widget::InitParams child_params
=
2939 CreateParams(views::Widget::InitParams::TYPE_POPUP
);
2940 child_params
.parent
= top_level
->GetNativeView();
2941 #if !defined(OS_CHROMEOS)
2942 if (child_has_desktop_native_widget_aura
)
2943 child_params
.native_widget
= new PlatformDesktopNativeWidget(child
);
2945 child
->Init(child_params
);
2946 child
->GetRootView()->AddChildView(
2947 new DestroyedTrackingView("child", &destroyed
));
2950 // Should trigger destruction of the child too.
2951 top_level
->native_widget_private()->CloseNow();
2953 // Child should be destroyed first.
2954 ASSERT_EQ(2u, destroyed
.size());
2955 EXPECT_EQ("child", destroyed
[0]);
2956 EXPECT_EQ("parent", destroyed
[1]);
2960 DISALLOW_COPY_AND_ASSIGN(WidgetChildDestructionTest
);
2963 #if !defined(OS_CHROMEOS)
2964 // See description of RunDestroyChildWidgetsTest(). Parent uses
2965 // DesktopNativeWidgetAura.
2966 TEST_F(WidgetChildDestructionTest
,
2967 DestroyChildWidgetsInOrderWithDesktopNativeWidget
) {
2968 RunDestroyChildWidgetsTest(true, false);
2971 // See description of RunDestroyChildWidgetsTest(). Both parent and child use
2972 // DesktopNativeWidgetAura.
2973 TEST_F(WidgetChildDestructionTest
,
2974 DestroyChildWidgetsInOrderWithDesktopNativeWidgetForBoth
) {
2975 RunDestroyChildWidgetsTest(true, true);
2977 #endif // !defined(OS_CHROMEOS)
2979 // See description of RunDestroyChildWidgetsTest().
2980 TEST_F(WidgetChildDestructionTest
, DestroyChildWidgetsInOrder
) {
2981 RunDestroyChildWidgetsTest(false, false);
2984 // Verifies nativeview visbility matches that of Widget visibility when
2985 // SetFullscreen is invoked.
2986 TEST_F(WidgetTest
, FullscreenStatePropagated
) {
2987 Widget::InitParams init_params
=
2988 CreateParams(Widget::InitParams::TYPE_WINDOW
);
2989 init_params
.show_state
= ui::SHOW_STATE_NORMAL
;
2990 init_params
.bounds
= gfx::Rect(0, 0, 500, 500);
2991 init_params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
2994 Widget top_level_widget
;
2995 top_level_widget
.Init(init_params
);
2996 top_level_widget
.SetFullscreen(true);
2997 EXPECT_EQ(top_level_widget
.IsVisible(),
2998 IsNativeWindowVisible(top_level_widget
.GetNativeWindow()));
2999 top_level_widget
.CloseNow();
3001 #if !defined(OS_CHROMEOS)
3003 Widget top_level_widget
;
3004 init_params
.native_widget
=
3005 new PlatformDesktopNativeWidget(&top_level_widget
);
3006 top_level_widget
.Init(init_params
);
3007 top_level_widget
.SetFullscreen(true);
3008 EXPECT_EQ(top_level_widget
.IsVisible(),
3009 IsNativeWindowVisible(top_level_widget
.GetNativeWindow()));
3010 top_level_widget
.CloseNow();
3017 class FullscreenAwareFrame
: public views::NonClientFrameView
{
3019 explicit FullscreenAwareFrame(views::Widget
* widget
)
3020 : widget_(widget
), fullscreen_layout_called_(false) {}
3021 ~FullscreenAwareFrame() override
{}
3023 // views::NonClientFrameView overrides:
3024 gfx::Rect
GetBoundsForClientView() const override
{ return gfx::Rect(); }
3025 gfx::Rect
GetWindowBoundsForClientBounds(
3026 const gfx::Rect
& client_bounds
) const override
{
3029 int NonClientHitTest(const gfx::Point
& point
) override
{ return HTNOWHERE
; }
3030 void GetWindowMask(const gfx::Size
& size
, gfx::Path
* window_mask
) override
{}
3031 void ResetWindowControls() override
{}
3032 void UpdateWindowIcon() override
{}
3033 void UpdateWindowTitle() override
{}
3034 void SizeConstraintsChanged() override
{}
3036 // views::View overrides:
3037 void Layout() override
{
3038 if (widget_
->IsFullscreen())
3039 fullscreen_layout_called_
= true;
3042 bool fullscreen_layout_called() const { return fullscreen_layout_called_
; }
3045 views::Widget
* widget_
;
3046 bool fullscreen_layout_called_
;
3048 DISALLOW_COPY_AND_ASSIGN(FullscreenAwareFrame
);
3053 // Tests that frame Layout is called when a widget goes fullscreen without
3054 // changing its size or title.
3055 TEST_F(WidgetTest
, FullscreenFrameLayout
) {
3056 Widget
* widget
= CreateTopLevelPlatformWidget();
3057 FullscreenAwareFrame
* frame
= new FullscreenAwareFrame(widget
);
3058 widget
->non_client_view()->SetFrameView(frame
); // Owns |frame|.
3061 RunPendingMessages();
3063 EXPECT_FALSE(frame
->fullscreen_layout_called());
3064 widget
->SetFullscreen(true);
3066 RunPendingMessages();
3068 if (IsTestingSnowLeopard()) {
3069 // Fullscreen is currently ignored on Snow Leopard.
3070 EXPECT_FALSE(frame
->fullscreen_layout_called());
3072 EXPECT_TRUE(frame
->fullscreen_layout_called());
3078 #if !defined(OS_CHROMEOS)
3081 // Trivial WidgetObserverTest that invokes Widget::IsActive() from
3082 // OnWindowDestroying.
3083 class IsActiveFromDestroyObserver
: public WidgetObserver
{
3085 IsActiveFromDestroyObserver() {}
3086 ~IsActiveFromDestroyObserver() override
{}
3087 void OnWidgetDestroying(Widget
* widget
) override
{ widget
->IsActive(); }
3090 DISALLOW_COPY_AND_ASSIGN(IsActiveFromDestroyObserver
);
3095 // Verifies Widget::IsActive() invoked from
3096 // WidgetObserver::OnWidgetDestroying() in a child widget doesn't crash.
3097 TEST_F(WidgetTest
, IsActiveFromDestroy
) {
3098 // Create two widgets, one a child of the other.
3099 IsActiveFromDestroyObserver observer
;
3100 Widget parent_widget
;
3101 Widget::InitParams parent_params
=
3102 CreateParams(Widget::InitParams::TYPE_POPUP
);
3103 parent_params
.native_widget
= new PlatformDesktopNativeWidget(&parent_widget
);
3104 parent_params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
3105 parent_widget
.Init(parent_params
);
3106 parent_widget
.Show();
3108 Widget child_widget
;
3109 Widget::InitParams child_params
=
3110 CreateParams(Widget::InitParams::TYPE_POPUP
);
3111 child_params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
3112 child_params
.context
= parent_widget
.GetNativeWindow();
3113 child_widget
.Init(child_params
);
3114 child_widget
.AddObserver(&observer
);
3115 child_widget
.Show();
3117 parent_widget
.CloseNow();
3119 #endif // !defined(OS_CHROMEOS)
3121 // Tests that events propagate through from the dispatcher with the correct
3122 // event type, and that the different platforms behave the same.
3123 TEST_F(WidgetTest
, MouseEventTypesViaGenerator
) {
3124 EventCountView
* view
= new EventCountView
;
3125 view
->set_handle_mode(EventCountView::CONSUME_EVENTS
);
3126 view
->SetBounds(10, 10, 50, 40);
3128 Widget
* widget
= CreateTopLevelFramelessPlatformWidget();
3129 widget
->GetRootView()->AddChildView(view
);
3131 widget
->SetBounds(gfx::Rect(0, 0, 100, 80));
3134 ui::test::EventGenerator
generator(GetContext(), widget
->GetNativeWindow());
3135 generator
.set_current_location(gfx::Point(20, 20));
3137 generator
.ClickLeftButton();
3138 EXPECT_EQ(1, view
->GetEventCount(ui::ET_MOUSE_PRESSED
));
3139 EXPECT_EQ(1, view
->GetEventCount(ui::ET_MOUSE_RELEASED
));
3140 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON
, view
->last_flags());
3142 generator
.PressRightButton();
3143 EXPECT_EQ(2, view
->GetEventCount(ui::ET_MOUSE_PRESSED
));
3144 EXPECT_EQ(1, view
->GetEventCount(ui::ET_MOUSE_RELEASED
));
3145 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON
, view
->last_flags());
3147 generator
.ReleaseRightButton();
3148 EXPECT_EQ(2, view
->GetEventCount(ui::ET_MOUSE_PRESSED
));
3149 EXPECT_EQ(2, view
->GetEventCount(ui::ET_MOUSE_RELEASED
));
3150 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON
, view
->last_flags());
3152 // Test mouse move events.
3153 EXPECT_EQ(0, view
->GetEventCount(ui::ET_MOUSE_MOVED
));
3154 EXPECT_EQ(0, view
->GetEventCount(ui::ET_MOUSE_ENTERED
));
3156 // Move the mouse within the view (20, 20) -> (30, 30).
3157 generator
.MoveMouseTo(gfx::Point(30, 30));
3158 EXPECT_EQ(1, view
->GetEventCount(ui::ET_MOUSE_MOVED
));
3159 EXPECT_EQ(1, view
->GetEventCount(ui::ET_MOUSE_ENTERED
));
3160 EXPECT_EQ(ui::EF_NONE
, view
->last_flags());
3162 // Move it again - entered count shouldn't change.
3163 generator
.MoveMouseTo(gfx::Point(31, 31));
3164 EXPECT_EQ(2, view
->GetEventCount(ui::ET_MOUSE_MOVED
));
3165 EXPECT_EQ(1, view
->GetEventCount(ui::ET_MOUSE_ENTERED
));
3166 EXPECT_EQ(0, view
->GetEventCount(ui::ET_MOUSE_EXITED
));
3168 // Move it off the view.
3169 generator
.MoveMouseTo(gfx::Point(5, 5));
3170 EXPECT_EQ(2, view
->GetEventCount(ui::ET_MOUSE_MOVED
));
3171 EXPECT_EQ(1, view
->GetEventCount(ui::ET_MOUSE_ENTERED
));
3172 EXPECT_EQ(1, view
->GetEventCount(ui::ET_MOUSE_EXITED
));
3175 generator
.MoveMouseTo(gfx::Point(20, 20));
3176 EXPECT_EQ(3, view
->GetEventCount(ui::ET_MOUSE_MOVED
));
3177 EXPECT_EQ(2, view
->GetEventCount(ui::ET_MOUSE_ENTERED
));
3178 EXPECT_EQ(1, view
->GetEventCount(ui::ET_MOUSE_EXITED
));
3180 // Drargging. Cover HasCapture() and NativeWidgetPrivate::IsMouseButtonDown().
3181 generator
.DragMouseTo(gfx::Point(40, 40));
3182 EXPECT_EQ(3, view
->GetEventCount(ui::ET_MOUSE_PRESSED
));
3183 EXPECT_EQ(3, view
->GetEventCount(ui::ET_MOUSE_RELEASED
));
3184 EXPECT_EQ(1, view
->GetEventCount(ui::ET_MOUSE_DRAGGED
));
3185 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON
, view
->last_flags());
3190 // Tests that the root view is correctly set up for Widget types that do not
3191 // require a non-client view, before any other views are added to the widget.
3192 // That is, before Widget::ReorderNativeViews() is called which, if called with
3193 // a root view not set, could cause the root view to get resized to the widget.
3194 TEST_F(WidgetTest
, NonClientWindowValidAfterInit
) {
3195 Widget
* widget
= CreateTopLevelFramelessPlatformWidget();
3196 View
* root_view
= widget
->GetRootView();
3198 // Size the root view to exceed the widget bounds.
3199 const gfx::Rect
test_rect(0, 0, 500, 500);
3200 root_view
->SetBoundsRect(test_rect
);
3202 EXPECT_NE(test_rect
.size(), widget
->GetWindowBoundsInScreen().size());
3204 EXPECT_EQ(test_rect
, root_view
->bounds());
3205 widget
->ReorderNativeViews();
3206 EXPECT_EQ(test_rect
, root_view
->bounds());
3212 // This test validates that sending WM_CHAR/WM_SYSCHAR/WM_SYSDEADCHAR
3213 // messages via the WindowEventTarget interface implemented by the
3214 // HWNDMessageHandler class does not cause a crash due to an unprocessed
3216 TEST_F(WidgetTest
, CharMessagesAsKeyboardMessagesDoesNotCrash
) {
3218 Widget::InitParams params
=
3219 CreateParams(Widget::InitParams::TYPE_WINDOW
);
3220 params
.native_widget
= new PlatformDesktopNativeWidget(&widget
);
3221 params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
3222 widget
.Init(params
);
3225 ui::WindowEventTarget
* target
=
3226 reinterpret_cast<ui::WindowEventTarget
*>(ui::ViewProp::GetValue(
3227 widget
.GetNativeWindow()->GetHost()->GetAcceleratedWidget(),
3228 ui::WindowEventTarget::kWin32InputEventTarget
));
3229 EXPECT_NE(nullptr, target
);
3230 bool handled
= false;
3231 target
->HandleKeyboardMessage(WM_CHAR
, 0, 0, &handled
);
3232 target
->HandleKeyboardMessage(WM_SYSCHAR
, 0, 0, &handled
);
3233 target
->HandleKeyboardMessage(WM_SYSDEADCHAR
, 0, 0, &handled
);
3238 // Test that SetAlwaysOnTop and IsAlwaysOnTop are consistent.
3239 TEST_F(WidgetTest
, AlwaysOnTop
) {
3240 Widget
* widget
= CreateTopLevelNativeWidget();
3241 EXPECT_FALSE(widget
->IsAlwaysOnTop());
3242 widget
->SetAlwaysOnTop(true);
3243 EXPECT_TRUE(widget
->IsAlwaysOnTop());
3244 widget
->SetAlwaysOnTop(false);
3245 EXPECT_FALSE(widget
->IsAlwaysOnTop());
3250 } // namespace views