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();
1700 root_view
->SetBoundsRect(gfx::Rect(0, 0, 500, 500));
1702 EventCountView
* v1
= new EventCountView();
1703 v1
->SetBounds(5, 5, 10, 10);
1704 root_view
->AddChildView(v1
);
1705 EventCountView
* v2
= new EventCountView();
1706 v2
->SetBounds(5, 15, 10, 10);
1707 root_view
->AddChildView(v2
);
1711 // SynthesizeMouseMoveEvent does nothing until the mouse is entered.
1712 widget
->SynthesizeMouseMoveEvent();
1713 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_MOUSE_MOVED
));
1714 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_MOUSE_MOVED
));
1716 gfx::Point
cursor_location(5, 5);
1717 View::ConvertPointToScreen(widget
->GetRootView(), &cursor_location
);
1718 ui::MouseEvent
move(ui::ET_MOUSE_MOVED
, cursor_location
, cursor_location
,
1719 ui::EventTimeForNow(), ui::EF_NONE
, ui::EF_NONE
);
1720 ui::EventDispatchDetails details
=
1721 WidgetTest::GetEventProcessor(widget
)->OnEventFromSource(&move
);
1722 EXPECT_FALSE(details
.dispatcher_destroyed
);
1724 EXPECT_EQ(1, v1
->GetEventCount(ui::ET_MOUSE_MOVED
));
1725 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_MOUSE_MOVED
));
1727 // SynthesizeMouseMoveEvent dispatches an mousemove event.
1728 widget
->SynthesizeMouseMoveEvent();
1729 EXPECT_EQ(2, v1
->GetEventCount(ui::ET_MOUSE_MOVED
));
1732 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_MOUSE_MOVED
));
1733 v2
->SetBounds(5, 5, 10, 10);
1734 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_MOUSE_MOVED
));
1736 widget
->SynthesizeMouseMoveEvent();
1737 EXPECT_EQ(1, v2
->GetEventCount(ui::ET_MOUSE_MOVED
));
1742 // No touch on desktop Mac. Tracked in http://crbug.com/445520.
1743 #if !defined(OS_MACOSX) || defined(USE_AURA)
1747 // ui::EventHandler which handles all mouse press events.
1748 class MousePressEventConsumer
: public ui::EventHandler
{
1750 MousePressEventConsumer() {}
1753 // ui::EventHandler:
1754 void OnMouseEvent(ui::MouseEvent
* event
) override
{
1755 if (event
->type() == ui::ET_MOUSE_PRESSED
)
1756 event
->SetHandled();
1759 DISALLOW_COPY_AND_ASSIGN(MousePressEventConsumer
);
1764 // Test that mouse presses and mouse releases are dispatched normally when a
1766 TEST_F(WidgetTest
, MouseEventDispatchWhileTouchIsDown
) {
1767 Widget
* widget
= CreateTopLevelNativeWidget();
1769 widget
->SetSize(gfx::Size(300, 300));
1771 EventCountView
* event_count_view
= new EventCountView();
1772 event_count_view
->SetBounds(0, 0, 300, 300);
1773 widget
->GetRootView()->AddChildView(event_count_view
);
1775 MousePressEventConsumer consumer
;
1776 event_count_view
->AddPostTargetHandler(&consumer
);
1778 ui::test::EventGenerator
generator(GetContext(), widget
->GetNativeWindow());
1779 generator
.PressTouch();
1780 generator
.ClickLeftButton();
1782 EXPECT_EQ(1, event_count_view
->GetEventCount(ui::ET_MOUSE_PRESSED
));
1783 EXPECT_EQ(1, event_count_view
->GetEventCount(ui::ET_MOUSE_RELEASED
));
1788 #endif // !defined(OS_MACOSX) || defined(USE_AURA)
1790 // Verifies WindowClosing() is invoked correctly on the delegate when a Widget
1792 TEST_F(WidgetTest
, SingleWindowClosing
) {
1793 TestDesktopWidgetDelegate delegate
;
1794 delegate
.InitWidget(CreateParams(Widget::InitParams::TYPE_WINDOW
));
1795 EXPECT_EQ(0, delegate
.window_closing_count());
1796 delegate
.GetWidget()->CloseNow();
1797 EXPECT_EQ(1, delegate
.window_closing_count());
1800 class WidgetWindowTitleTest
: public WidgetTest
{
1802 void RunTest(bool desktop_native_widget
) {
1803 Widget
* widget
= new Widget(); // Destroyed by CloseNow() below.
1804 Widget::InitParams init_params
=
1805 CreateParams(Widget::InitParams::TYPE_WINDOW
);
1806 widget
->Init(init_params
);
1808 #if !defined(OS_CHROMEOS)
1809 if (desktop_native_widget
)
1810 init_params
.native_widget
= new PlatformDesktopNativeWidget(widget
);
1812 DCHECK(!desktop_native_widget
)
1813 << "DesktopNativeWidget does not exist on non-Aura or on ChromeOS.";
1816 internal::NativeWidgetPrivate
* native_widget
=
1817 widget
->native_widget_private();
1819 base::string16 empty
;
1820 base::string16
s1(base::UTF8ToUTF16("Title1"));
1821 base::string16
s2(base::UTF8ToUTF16("Title2"));
1822 base::string16
s3(base::UTF8ToUTF16("TitleLong"));
1824 // The widget starts with no title, setting empty should not change
1826 EXPECT_FALSE(native_widget
->SetWindowTitle(empty
));
1827 // Setting the title to something non-empty should cause a change.
1828 EXPECT_TRUE(native_widget
->SetWindowTitle(s1
));
1829 // Setting the title to something else with the same length should cause a
1831 EXPECT_TRUE(native_widget
->SetWindowTitle(s2
));
1832 // Setting the title to something else with a different length should cause
1834 EXPECT_TRUE(native_widget
->SetWindowTitle(s3
));
1835 // Setting the title to the same thing twice should not cause a change.
1836 EXPECT_FALSE(native_widget
->SetWindowTitle(s3
));
1842 TEST_F(WidgetWindowTitleTest
, SetWindowTitleChanged_NativeWidget
) {
1843 // Use the default NativeWidget.
1844 bool desktop_native_widget
= false;
1845 RunTest(desktop_native_widget
);
1848 // DesktopNativeWidget does not exist on non-Aura or on ChromeOS.
1849 #if !defined(OS_CHROMEOS)
1850 TEST_F(WidgetWindowTitleTest
, SetWindowTitleChanged_DesktopNativeWidget
) {
1851 // Override to use a DesktopNativeWidget.
1852 bool desktop_native_widget
= true;
1853 RunTest(desktop_native_widget
);
1855 #endif // !OS_CHROMEOS
1857 TEST_F(WidgetTest
, WidgetDeleted_InOnMousePressed
) {
1858 Widget
* widget
= new Widget
;
1859 Widget::InitParams params
=
1860 CreateParams(views::Widget::InitParams::TYPE_POPUP
);
1861 widget
->Init(params
);
1863 widget
->SetContentsView(new CloseWidgetView(ui::ET_MOUSE_PRESSED
));
1865 widget
->SetSize(gfx::Size(100, 100));
1868 ui::test::EventGenerator
generator(GetContext(), widget
->GetNativeWindow());
1870 WidgetDeletionObserver
deletion_observer(widget
);
1871 generator
.ClickLeftButton();
1872 EXPECT_FALSE(deletion_observer
.IsWidgetAlive());
1874 // Yay we did not crash!
1877 // No touch on desktop Mac. Tracked in http://crbug.com/445520.
1878 #if !defined(OS_MACOSX) || defined(USE_AURA)
1880 TEST_F(WidgetTest
, WidgetDeleted_InDispatchGestureEvent
) {
1881 Widget
* widget
= new Widget
;
1882 Widget::InitParams params
=
1883 CreateParams(views::Widget::InitParams::TYPE_POPUP
);
1884 widget
->Init(params
);
1886 widget
->SetContentsView(new CloseWidgetView(ui::ET_GESTURE_TAP_DOWN
));
1888 widget
->SetSize(gfx::Size(100, 100));
1891 ui::test::EventGenerator
generator(GetContext(), widget
->GetNativeWindow());
1893 WidgetDeletionObserver
deletion_observer(widget
);
1894 generator
.GestureTapAt(widget
->GetWindowBoundsInScreen().CenterPoint());
1895 EXPECT_FALSE(deletion_observer
.IsWidgetAlive());
1897 // Yay we did not crash!
1900 #endif // !defined(OS_MACOSX) || defined(USE_AURA)
1902 // See description of RunGetNativeThemeFromDestructor() for details.
1903 class GetNativeThemeFromDestructorView
: public WidgetDelegateView
{
1905 GetNativeThemeFromDestructorView() {}
1906 ~GetNativeThemeFromDestructorView() override
{ VerifyNativeTheme(); }
1908 View
* GetContentsView() override
{ return this; }
1911 void VerifyNativeTheme() {
1912 ASSERT_TRUE(GetNativeTheme() != NULL
);
1915 DISALLOW_COPY_AND_ASSIGN(GetNativeThemeFromDestructorView
);
1918 // Verifies GetNativeTheme() from the destructor of a WidgetDelegateView doesn't
1919 // crash. |is_first_run| is true if this is the first call. A return value of
1920 // true indicates this should be run again with a value of false.
1921 // First run uses DesktopNativeWidgetAura (if possible). Second run doesn't.
1922 bool RunGetNativeThemeFromDestructor(const Widget::InitParams
& in_params
,
1923 bool is_first_run
) {
1924 bool needs_second_run
= false;
1925 // Destroyed by CloseNow() below.
1926 Widget
* widget
= new Widget
;
1927 Widget::InitParams
params(in_params
);
1928 // Deletes itself when the Widget is destroyed.
1929 params
.delegate
= new GetNativeThemeFromDestructorView
;
1930 #if !defined(OS_CHROMEOS)
1932 params
.native_widget
= new PlatformDesktopNativeWidget(widget
);
1933 needs_second_run
= true;
1936 widget
->Init(params
);
1938 return needs_second_run
;
1941 // See description of RunGetNativeThemeFromDestructor() for details.
1942 TEST_F(WidgetTest
, GetNativeThemeFromDestructor
) {
1943 Widget::InitParams params
= CreateParams(Widget::InitParams::TYPE_POPUP
);
1944 if (RunGetNativeThemeFromDestructor(params
, true))
1945 RunGetNativeThemeFromDestructor(params
, false);
1948 // Used by HideCloseDestroy. Allows setting a boolean when the widget is
1950 class CloseDestroysWidget
: public Widget
{
1952 explicit CloseDestroysWidget(bool* destroyed
)
1953 : destroyed_(destroyed
) {
1956 ~CloseDestroysWidget() override
{
1959 base::MessageLoop::current()->QuitNow();
1963 void Detach() { destroyed_
= NULL
; }
1966 // If non-null set to true from destructor.
1969 DISALLOW_COPY_AND_ASSIGN(CloseDestroysWidget
);
1972 // An observer that registers that an animation has ended.
1973 class AnimationEndObserver
: public ui::ImplicitAnimationObserver
{
1975 AnimationEndObserver() : animation_completed_(false) {}
1976 ~AnimationEndObserver() override
{}
1978 bool animation_completed() const { return animation_completed_
; }
1980 // ui::ImplicitAnimationObserver:
1981 void OnImplicitAnimationsCompleted() override
{ animation_completed_
= true; }
1984 bool animation_completed_
;
1986 DISALLOW_COPY_AND_ASSIGN(AnimationEndObserver
);
1989 // An observer that registers the bounds of a widget on destruction.
1990 class WidgetBoundsObserver
: public WidgetObserver
{
1992 WidgetBoundsObserver() {}
1993 ~WidgetBoundsObserver() override
{}
1995 gfx::Rect
bounds() { return bounds_
; }
1998 void OnWidgetDestroying(Widget
* widget
) override
{
1999 EXPECT_TRUE(widget
->GetNativeWindow());
2000 bounds_
= widget
->GetWindowBoundsInScreen();
2006 DISALLOW_COPY_AND_ASSIGN(WidgetBoundsObserver
);
2009 // Verifies Close() results in destroying.
2010 TEST_F(WidgetTest
, CloseDestroys
) {
2011 bool destroyed
= false;
2012 CloseDestroysWidget
* widget
= new CloseDestroysWidget(&destroyed
);
2013 Widget::InitParams params
=
2014 CreateParams(views::Widget::InitParams::TYPE_MENU
);
2015 params
.opacity
= Widget::InitParams::OPAQUE_WINDOW
;
2016 #if !defined(OS_CHROMEOS)
2017 params
.native_widget
= new PlatformDesktopNativeWidget(widget
);
2019 widget
->Init(params
);
2023 EXPECT_FALSE(destroyed
);
2024 // Run the message loop as Close() asynchronously deletes.
2025 base::RunLoop().Run();
2026 EXPECT_TRUE(destroyed
);
2027 // Close() should destroy the widget. If not we'll cleanup to avoid leaks.
2034 // Tests that killing a widget while animating it does not crash.
2035 TEST_F(WidgetTest
, CloseWidgetWhileAnimating
) {
2036 scoped_ptr
<Widget
> widget(new Widget
);
2037 Widget::InitParams params
= CreateParams(Widget::InitParams::TYPE_POPUP
);
2038 params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
2039 params
.bounds
= gfx::Rect(50, 50, 250, 250);
2040 widget
->Init(params
);
2041 AnimationEndObserver animation_observer
;
2042 WidgetBoundsObserver widget_observer
;
2043 gfx::Rect
bounds(100, 100, 50, 50);
2045 // Normal animations for tests have ZERO_DURATION, make sure we are actually
2046 // animating the movement.
2047 ui::ScopedAnimationDurationScaleMode
animation_scale_mode(
2048 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION
);
2049 ui::ScopedLayerAnimationSettings
animation_settings(
2050 widget
->GetLayer()->GetAnimator());
2051 animation_settings
.AddObserver(&animation_observer
);
2052 widget
->AddObserver(&widget_observer
);
2055 // Animate the bounds change.
2056 widget
->SetBounds(bounds
);
2058 EXPECT_FALSE(animation_observer
.animation_completed());
2060 EXPECT_TRUE(animation_observer
.animation_completed());
2061 EXPECT_EQ(widget_observer
.bounds(), bounds
);
2064 // Test that the NativeWidget is still valid during OnNativeWidgetDestroying(),
2065 // and properties that depend on it are valid, when closed via CloseNow().
2066 TEST_F(WidgetTest
, ValidDuringOnNativeWidgetDestroyingFromCloseNow
) {
2067 Widget
* widget
= CreateNativeDesktopWidget();
2069 gfx::Rect
screen_rect(50, 50, 100, 100);
2070 widget
->SetBounds(screen_rect
);
2071 WidgetBoundsObserver observer
;
2072 widget
->AddObserver(&observer
);
2074 EXPECT_EQ(screen_rect
, observer
.bounds());
2077 // Test that the NativeWidget is still valid during OnNativeWidgetDestroying(),
2078 // and properties that depend on it are valid, when closed via Close().
2079 TEST_F(WidgetTest
, ValidDuringOnNativeWidgetDestroyingFromClose
) {
2080 Widget
* widget
= CreateNativeDesktopWidget();
2082 gfx::Rect
screen_rect(50, 50, 100, 100);
2083 widget
->SetBounds(screen_rect
);
2084 WidgetBoundsObserver observer
;
2085 widget
->AddObserver(&observer
);
2087 EXPECT_EQ(gfx::Rect(), observer
.bounds());
2088 base::RunLoop().RunUntilIdle();
2089 // Broken on Linux. See http://crbug.com/515379.
2090 #if !defined(OS_LINUX) || defined(OS_CHROMEOS)
2091 EXPECT_EQ(screen_rect
, observer
.bounds());
2095 // Tests that we do not crash when a Widget is destroyed by going out of
2096 // scope (as opposed to being explicitly deleted by its NativeWidget).
2097 TEST_F(WidgetTest
, NoCrashOnWidgetDelete
) {
2098 scoped_ptr
<Widget
> widget(new Widget
);
2099 Widget::InitParams params
= CreateParams(Widget::InitParams::TYPE_POPUP
);
2100 params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
2101 widget
->Init(params
);
2104 // Tests that we do not crash when a Widget is destroyed before it finishes
2105 // processing of pending input events in the message loop.
2106 TEST_F(WidgetTest
, NoCrashOnWidgetDeleteWithPendingEvents
) {
2107 scoped_ptr
<Widget
> widget(new Widget
);
2108 Widget::InitParams params
= CreateParams(Widget::InitParams::TYPE_WINDOW
);
2109 params
.bounds
= gfx::Rect(0, 0, 200, 200);
2110 params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
2111 widget
->Init(params
);
2114 ui::test::EventGenerator
generator(GetContext(), widget
->GetNativeWindow());
2115 generator
.MoveMouseTo(10, 10);
2117 // No touch on desktop Mac. Tracked in http://crbug.com/445520.
2118 #if defined(OS_MACOSX) && !defined(USE_AURA)
2119 generator
.ClickLeftButton();
2121 generator
.PressTouch();
2126 // A view that consumes mouse-pressed event and gesture-tap-down events.
2127 class RootViewTestView
: public View
{
2129 RootViewTestView(): View() {}
2132 bool OnMousePressed(const ui::MouseEvent
& event
) override
{ return true; }
2134 void OnGestureEvent(ui::GestureEvent
* event
) override
{
2135 if (event
->type() == ui::ET_GESTURE_TAP_DOWN
)
2136 event
->SetHandled();
2140 // Checks if RootView::*_handler_ fields are unset when widget is hidden.
2141 // Fails on chromium.webkit Windows bot, see crbug.com/264872.
2143 #define MAYBE_DisableTestRootViewHandlersWhenHidden\
2144 DISABLED_TestRootViewHandlersWhenHidden
2146 #define MAYBE_DisableTestRootViewHandlersWhenHidden\
2147 TestRootViewHandlersWhenHidden
2149 TEST_F(WidgetTest
, MAYBE_DisableTestRootViewHandlersWhenHidden
) {
2150 Widget
* widget
= CreateTopLevelNativeWidget();
2151 widget
->SetBounds(gfx::Rect(0, 0, 300, 300));
2152 View
* view
= new RootViewTestView();
2153 view
->SetBounds(0, 0, 300, 300);
2154 internal::RootView
* root_view
=
2155 static_cast<internal::RootView
*>(widget
->GetRootView());
2156 root_view
->AddChildView(view
);
2158 // Check RootView::mouse_pressed_handler_.
2160 EXPECT_EQ(NULL
, GetMousePressedHandler(root_view
));
2161 gfx::Point
click_location(45, 15);
2162 ui::MouseEvent
press(ui::ET_MOUSE_PRESSED
, click_location
, click_location
,
2163 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON
,
2164 ui::EF_LEFT_MOUSE_BUTTON
);
2165 widget
->OnMouseEvent(&press
);
2166 EXPECT_EQ(view
, GetMousePressedHandler(root_view
));
2168 EXPECT_EQ(NULL
, GetMousePressedHandler(root_view
));
2170 // Check RootView::mouse_move_handler_.
2172 EXPECT_EQ(NULL
, GetMouseMoveHandler(root_view
));
2173 gfx::Point
move_location(45, 15);
2174 ui::MouseEvent
move(ui::ET_MOUSE_MOVED
, move_location
, move_location
,
2175 ui::EventTimeForNow(), 0, 0);
2176 widget
->OnMouseEvent(&move
);
2177 EXPECT_EQ(view
, GetMouseMoveHandler(root_view
));
2179 EXPECT_EQ(NULL
, GetMouseMoveHandler(root_view
));
2181 // Check RootView::gesture_handler_.
2183 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2184 ui::GestureEvent
tap_down(15,
2188 ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN
));
2189 widget
->OnGestureEvent(&tap_down
);
2190 EXPECT_EQ(view
, GetGestureHandler(root_view
));
2192 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2197 // Convenience to make constructing a GestureEvent simpler.
2198 class GestureEventForTest
: public ui::GestureEvent
{
2200 GestureEventForTest(ui::EventType type
, int x
, int y
)
2205 ui::GestureEventDetails(type
)) {}
2207 GestureEventForTest(ui::GestureEventDetails details
, int x
, int y
)
2208 : GestureEvent(x
, y
, 0, base::TimeDelta(), details
) {}
2211 // Tests that the |gesture_handler_| member in RootView is always NULL
2212 // after the dispatch of a ui::ET_GESTURE_END event corresponding to
2213 // the release of the final touch point on the screen, but that
2214 // ui::ET_GESTURE_END events corresponding to the removal of any other touch
2215 // point do not modify |gesture_handler_|.
2216 TEST_F(WidgetTest
, GestureEndEvents
) {
2217 Widget
* widget
= CreateTopLevelNativeWidget();
2218 widget
->SetBounds(gfx::Rect(0, 0, 300, 300));
2219 EventCountView
* view
= new EventCountView();
2220 view
->SetBounds(0, 0, 300, 300);
2221 internal::RootView
* root_view
=
2222 static_cast<internal::RootView
*>(widget
->GetRootView());
2223 root_view
->AddChildView(view
);
2226 // If no gesture handler is set, a ui::ET_GESTURE_END event should not set
2227 // the gesture handler.
2228 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2229 GestureEventForTest
end(ui::ET_GESTURE_END
, 15, 15);
2230 widget
->OnGestureEvent(&end
);
2231 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2233 // Change the handle mode of |view| to indicate that it would like
2234 // to handle all events, then send a GESTURE_TAP to set the gesture handler.
2235 view
->set_handle_mode(EventCountView::CONSUME_EVENTS
);
2236 GestureEventForTest
tap(ui::ET_GESTURE_TAP
, 15, 15);
2237 widget
->OnGestureEvent(&tap
);
2238 EXPECT_TRUE(tap
.handled());
2239 EXPECT_EQ(view
, GetGestureHandler(root_view
));
2241 // The gesture handler should remain unchanged on a ui::ET_GESTURE_END
2242 // corresponding to a second touch point, but should be reset to NULL by a
2243 // ui::ET_GESTURE_END corresponding to the final touch point.
2244 ui::GestureEventDetails
details(ui::ET_GESTURE_END
);
2245 details
.set_touch_points(2);
2246 GestureEventForTest
end_second_touch_point(details
, 15, 15);
2247 widget
->OnGestureEvent(&end_second_touch_point
);
2248 EXPECT_EQ(view
, GetGestureHandler(root_view
));
2250 end
= GestureEventForTest(ui::ET_GESTURE_END
, 15, 15);
2251 widget
->OnGestureEvent(&end
);
2252 EXPECT_TRUE(end
.handled());
2253 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2255 // Send a GESTURE_TAP to set the gesture handler, then change the handle
2256 // mode of |view| to indicate that it does not want to handle any
2258 tap
= GestureEventForTest(ui::ET_GESTURE_TAP
, 15, 15);
2259 widget
->OnGestureEvent(&tap
);
2260 EXPECT_TRUE(tap
.handled());
2261 EXPECT_EQ(view
, GetGestureHandler(root_view
));
2262 view
->set_handle_mode(EventCountView::PROPAGATE_EVENTS
);
2264 // The gesture handler should remain unchanged on a ui::ET_GESTURE_END
2265 // corresponding to a second touch point, but should be reset to NULL by a
2266 // ui::ET_GESTURE_END corresponding to the final touch point.
2267 end_second_touch_point
= GestureEventForTest(details
, 15, 15);
2268 widget
->OnGestureEvent(&end_second_touch_point
);
2269 EXPECT_EQ(view
, GetGestureHandler(root_view
));
2271 end
= GestureEventForTest(ui::ET_GESTURE_END
, 15, 15);
2272 widget
->OnGestureEvent(&end
);
2273 EXPECT_FALSE(end
.handled());
2274 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2279 // Tests that gesture events which should not be processed (because
2280 // RootView::OnEventProcessingStarted() has marked them as handled) are not
2281 // dispatched to any views.
2282 TEST_F(WidgetTest
, GestureEventsNotProcessed
) {
2283 Widget
* widget
= CreateTopLevelNativeWidget();
2284 widget
->SetBounds(gfx::Rect(0, 0, 300, 300));
2286 // Define a hierarchy of four views (coordinates are in
2287 // their parent coordinate space).
2288 // v1 (0, 0, 300, 300)
2289 // v2 (0, 0, 100, 100)
2290 // v3 (0, 0, 50, 50)
2292 EventCountView
* v1
= new EventCountView();
2293 v1
->SetBounds(0, 0, 300, 300);
2294 EventCountView
* v2
= new EventCountView();
2295 v2
->SetBounds(0, 0, 100, 100);
2296 EventCountView
* v3
= new EventCountView();
2297 v3
->SetBounds(0, 0, 50, 50);
2298 EventCountView
* v4
= new EventCountView();
2299 v4
->SetBounds(0, 0, 10, 10);
2300 internal::RootView
* root_view
=
2301 static_cast<internal::RootView
*>(widget
->GetRootView());
2302 root_view
->AddChildView(v1
);
2303 v1
->AddChildView(v2
);
2304 v2
->AddChildView(v3
);
2305 v3
->AddChildView(v4
);
2309 // ui::ET_GESTURE_BEGIN events should never be seen by any view, but
2310 // they should be marked as handled by OnEventProcessingStarted().
2311 GestureEventForTest
begin(ui::ET_GESTURE_BEGIN
, 5, 5);
2312 widget
->OnGestureEvent(&begin
);
2313 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_BEGIN
));
2314 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_BEGIN
));
2315 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_BEGIN
));
2316 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_BEGIN
));
2317 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2318 EXPECT_TRUE(begin
.handled());
2324 // ui::ET_GESTURE_END events should not be seen by any view when there is
2325 // no default gesture handler set, but they should be marked as handled by
2326 // OnEventProcessingStarted().
2327 GestureEventForTest
end(ui::ET_GESTURE_END
, 5, 5);
2328 widget
->OnGestureEvent(&end
);
2329 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_END
));
2330 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_END
));
2331 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_END
));
2332 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_END
));
2333 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2334 EXPECT_TRUE(end
.handled());
2340 // ui::ET_GESTURE_END events not corresponding to the release of the
2341 // final touch point should never be seen by any view, but they should
2342 // be marked as handled by OnEventProcessingStarted().
2343 ui::GestureEventDetails
details(ui::ET_GESTURE_END
);
2344 details
.set_touch_points(2);
2345 GestureEventForTest
end_second_touch_point(details
, 5, 5);
2346 widget
->OnGestureEvent(&end_second_touch_point
);
2347 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_END
));
2348 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_END
));
2349 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_END
));
2350 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_END
));
2351 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2352 EXPECT_TRUE(end_second_touch_point
.handled());
2358 // ui::ET_GESTURE_SCROLL_UPDATE 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_update(ui::ET_GESTURE_SCROLL_UPDATE
, 5, 5);
2362 widget
->OnGestureEvent(&scroll_update
);
2363 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE
));
2364 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE
));
2365 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE
));
2366 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE
));
2367 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2368 EXPECT_TRUE(scroll_update
.handled());
2374 // ui::ET_GESTURE_SCROLL_END 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_end(ui::ET_GESTURE_SCROLL_END
, 5, 5);
2378 widget
->OnGestureEvent(&scroll_end
);
2379 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_SCROLL_END
));
2380 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_SCROLL_END
));
2381 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_SCROLL_END
));
2382 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_SCROLL_END
));
2383 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2384 EXPECT_TRUE(scroll_end
.handled());
2390 // ui::ET_SCROLL_FLING_START events should never be seen by any view when
2391 // there is no default gesture handler set, but they should be marked as
2392 // handled by OnEventProcessingStarted().
2393 GestureEventForTest
scroll_fling_start(ui::ET_SCROLL_FLING_START
, 5, 5);
2394 widget
->OnGestureEvent(&scroll_fling_start
);
2395 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_SCROLL_FLING_START
));
2396 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_SCROLL_FLING_START
));
2397 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_SCROLL_FLING_START
));
2398 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_SCROLL_FLING_START
));
2399 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2400 EXPECT_TRUE(scroll_fling_start
.handled());
2409 // Tests that a (non-scroll) gesture event is dispatched to the correct views
2410 // in a view hierarchy and that the default gesture handler in RootView is set
2412 TEST_F(WidgetTest
, GestureEventDispatch
) {
2413 Widget
* widget
= CreateTopLevelNativeWidget();
2414 widget
->SetBounds(gfx::Rect(0, 0, 300, 300));
2416 // Define a hierarchy of four views (coordinates are in
2417 // their parent coordinate space).
2418 // v1 (0, 0, 300, 300)
2419 // v2 (0, 0, 100, 100)
2420 // v3 (0, 0, 50, 50)
2422 EventCountView
* v1
= new EventCountView();
2423 v1
->SetBounds(0, 0, 300, 300);
2424 EventCountView
* v2
= new EventCountView();
2425 v2
->SetBounds(0, 0, 100, 100);
2426 EventCountView
* v3
= new EventCountView();
2427 v3
->SetBounds(0, 0, 50, 50);
2428 EventCountView
* v4
= new EventCountView();
2429 v4
->SetBounds(0, 0, 10, 10);
2430 internal::RootView
* root_view
=
2431 static_cast<internal::RootView
*>(widget
->GetRootView());
2432 root_view
->AddChildView(v1
);
2433 v1
->AddChildView(v2
);
2434 v2
->AddChildView(v3
);
2435 v3
->AddChildView(v4
);
2439 // No gesture handler is set in the root view and none of the views in the
2440 // view hierarchy handle a ui::ET_GESTURE_TAP event. In this case the tap
2441 // event should be dispatched to all views in the hierarchy, the gesture
2442 // handler should remain unset, and the event should remain unhandled.
2443 GestureEventForTest
tap(ui::ET_GESTURE_TAP
, 5, 5);
2444 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2445 widget
->OnGestureEvent(&tap
);
2446 EXPECT_EQ(1, v1
->GetEventCount(ui::ET_GESTURE_TAP
));
2447 EXPECT_EQ(1, v2
->GetEventCount(ui::ET_GESTURE_TAP
));
2448 EXPECT_EQ(1, v3
->GetEventCount(ui::ET_GESTURE_TAP
));
2449 EXPECT_EQ(1, v4
->GetEventCount(ui::ET_GESTURE_TAP
));
2450 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2451 EXPECT_FALSE(tap
.handled());
2453 // No gesture handler is set in the root view and |v1|, |v2|, and |v3| all
2454 // handle a ui::ET_GESTURE_TAP event. In this case the tap event should be
2455 // dispatched to |v4| and |v3|, the gesture handler should be set to |v3|,
2456 // and the event should be marked as handled.
2461 v1
->set_handle_mode(EventCountView::CONSUME_EVENTS
);
2462 v2
->set_handle_mode(EventCountView::CONSUME_EVENTS
);
2463 v3
->set_handle_mode(EventCountView::CONSUME_EVENTS
);
2464 tap
= GestureEventForTest(ui::ET_GESTURE_TAP
, 5, 5);
2465 widget
->OnGestureEvent(&tap
);
2466 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_TAP
));
2467 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_TAP
));
2468 EXPECT_EQ(1, v3
->GetEventCount(ui::ET_GESTURE_TAP
));
2469 EXPECT_EQ(1, v4
->GetEventCount(ui::ET_GESTURE_TAP
));
2470 EXPECT_EQ(v3
, GetGestureHandler(root_view
));
2471 EXPECT_TRUE(tap
.handled());
2473 // The gesture handler is set to |v3| and all views handle all gesture event
2474 // types. In this case subsequent gesture events should only be dispatched to
2475 // |v3| and marked as handled. The gesture handler should remain as |v3|.
2480 v4
->set_handle_mode(EventCountView::CONSUME_EVENTS
);
2481 tap
= GestureEventForTest(ui::ET_GESTURE_TAP
, 5, 5);
2482 widget
->OnGestureEvent(&tap
);
2483 EXPECT_TRUE(tap
.handled());
2484 GestureEventForTest
show_press(ui::ET_GESTURE_SHOW_PRESS
, 5, 5);
2485 widget
->OnGestureEvent(&show_press
);
2486 tap
= GestureEventForTest(ui::ET_GESTURE_TAP
, 5, 5);
2487 widget
->OnGestureEvent(&tap
);
2488 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_TAP
));
2489 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_TAP
));
2490 EXPECT_EQ(2, v3
->GetEventCount(ui::ET_GESTURE_TAP
));
2491 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_TAP
));
2492 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_SHOW_PRESS
));
2493 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_SHOW_PRESS
));
2494 EXPECT_EQ(1, v3
->GetEventCount(ui::ET_GESTURE_SHOW_PRESS
));
2495 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_SHOW_PRESS
));
2496 EXPECT_TRUE(tap
.handled());
2497 EXPECT_TRUE(show_press
.handled());
2498 EXPECT_EQ(v3
, GetGestureHandler(root_view
));
2500 // The gesture handler is set to |v3|, but |v3| does not handle
2501 // ui::ET_GESTURE_TAP events. In this case a tap gesture should be dispatched
2502 // only to |v3|, but the event should remain unhandled. The gesture handler
2503 // should remain as |v3|.
2508 v3
->set_handle_mode(EventCountView::PROPAGATE_EVENTS
);
2509 tap
= GestureEventForTest(ui::ET_GESTURE_TAP
, 5, 5);
2510 widget
->OnGestureEvent(&tap
);
2511 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_TAP
));
2512 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_TAP
));
2513 EXPECT_EQ(1, v3
->GetEventCount(ui::ET_GESTURE_TAP
));
2514 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_TAP
));
2515 EXPECT_FALSE(tap
.handled());
2516 EXPECT_EQ(v3
, GetGestureHandler(root_view
));
2521 // Tests that gesture scroll events will change the default gesture handler in
2522 // RootView if the current handler to which they are dispatched does not handle
2523 // gesture scroll events.
2524 TEST_F(WidgetTest
, ScrollGestureEventDispatch
) {
2525 Widget
* widget
= CreateTopLevelNativeWidget();
2526 widget
->SetBounds(gfx::Rect(0, 0, 300, 300));
2528 // Define a hierarchy of four views (coordinates are in
2529 // their parent coordinate space).
2530 // v1 (0, 0, 300, 300)
2531 // v2 (0, 0, 100, 100)
2532 // v3 (0, 0, 50, 50)
2534 EventCountView
* v1
= new EventCountView();
2535 v1
->SetBounds(0, 0, 300, 300);
2536 EventCountView
* v2
= new EventCountView();
2537 v2
->SetBounds(0, 0, 100, 100);
2538 EventCountView
* v3
= new EventCountView();
2539 v3
->SetBounds(0, 0, 50, 50);
2540 EventCountView
* v4
= new EventCountView();
2541 v4
->SetBounds(0, 0, 10, 10);
2542 internal::RootView
* root_view
=
2543 static_cast<internal::RootView
*>(widget
->GetRootView());
2544 root_view
->AddChildView(v1
);
2545 v1
->AddChildView(v2
);
2546 v2
->AddChildView(v3
);
2547 v3
->AddChildView(v4
);
2551 // Change the handle mode of |v3| to indicate that it would like to handle
2553 v3
->set_handle_mode(EventCountView::CONSUME_EVENTS
);
2555 // When no gesture handler is set, dispatching a ui::ET_GESTURE_TAP_DOWN
2556 // should bubble up the views hierarchy until it reaches the first view
2557 // that will handle it (|v3|) and then sets the handler to |v3|.
2558 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2559 GestureEventForTest
tap_down(ui::ET_GESTURE_TAP_DOWN
, 5, 5);
2560 widget
->OnGestureEvent(&tap_down
);
2561 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_TAP_DOWN
));
2562 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_TAP_DOWN
));
2563 EXPECT_EQ(1, v3
->GetEventCount(ui::ET_GESTURE_TAP_DOWN
));
2564 EXPECT_EQ(1, v4
->GetEventCount(ui::ET_GESTURE_TAP_DOWN
));
2565 EXPECT_EQ(v3
, GetGestureHandler(root_view
));
2566 EXPECT_TRUE(tap_down
.handled());
2572 // A ui::ET_GESTURE_TAP_CANCEL event should be dispatched to |v3| directly.
2573 GestureEventForTest
tap_cancel(ui::ET_GESTURE_TAP_CANCEL
, 5, 5);
2574 widget
->OnGestureEvent(&tap_cancel
);
2575 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_TAP_CANCEL
));
2576 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_TAP_CANCEL
));
2577 EXPECT_EQ(1, v3
->GetEventCount(ui::ET_GESTURE_TAP_CANCEL
));
2578 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_TAP_CANCEL
));
2579 EXPECT_EQ(v3
, GetGestureHandler(root_view
));
2580 EXPECT_TRUE(tap_cancel
.handled());
2586 // Change the handle mode of |v3| to indicate that it would no longer like
2587 // to handle events, and change the mode of |v1| to indicate that it would
2588 // like to handle events.
2589 v3
->set_handle_mode(EventCountView::PROPAGATE_EVENTS
);
2590 v1
->set_handle_mode(EventCountView::CONSUME_EVENTS
);
2592 // Dispatch a ui::ET_GESTURE_SCROLL_BEGIN event. Because the current gesture
2593 // handler (|v3|) does not handle scroll events, the event should bubble up
2594 // the views hierarchy until it reaches the first view that will handle
2595 // it (|v1|) and then sets the handler to |v1|.
2596 GestureEventForTest
scroll_begin(ui::ET_GESTURE_SCROLL_BEGIN
, 5, 5);
2597 widget
->OnGestureEvent(&scroll_begin
);
2598 EXPECT_EQ(1, v1
->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN
));
2599 EXPECT_EQ(1, v2
->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN
));
2600 EXPECT_EQ(1, v3
->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN
));
2601 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN
));
2602 EXPECT_EQ(v1
, GetGestureHandler(root_view
));
2603 EXPECT_TRUE(scroll_begin
.handled());
2609 // A ui::ET_GESTURE_SCROLL_UPDATE event should be dispatched to |v1|
2611 GestureEventForTest
scroll_update(ui::ET_GESTURE_SCROLL_UPDATE
, 5, 5);
2612 widget
->OnGestureEvent(&scroll_update
);
2613 EXPECT_EQ(1, v1
->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE
));
2614 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE
));
2615 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE
));
2616 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE
));
2617 EXPECT_EQ(v1
, GetGestureHandler(root_view
));
2618 EXPECT_TRUE(scroll_update
.handled());
2624 // A ui::ET_GESTURE_SCROLL_END event should be dispatched to |v1|
2625 // directly and should not reset the gesture handler.
2626 GestureEventForTest
scroll_end(ui::ET_GESTURE_SCROLL_END
, 5, 5);
2627 widget
->OnGestureEvent(&scroll_end
);
2628 EXPECT_EQ(1, v1
->GetEventCount(ui::ET_GESTURE_SCROLL_END
));
2629 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_SCROLL_END
));
2630 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_SCROLL_END
));
2631 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_SCROLL_END
));
2632 EXPECT_EQ(v1
, GetGestureHandler(root_view
));
2633 EXPECT_TRUE(scroll_end
.handled());
2639 // A ui::ET_GESTURE_PINCH_BEGIN event (which is a non-scroll event) should
2640 // still be dispatched to |v1| directly.
2641 GestureEventForTest
pinch_begin(ui::ET_GESTURE_PINCH_BEGIN
, 5, 5);
2642 widget
->OnGestureEvent(&pinch_begin
);
2643 EXPECT_EQ(1, v1
->GetEventCount(ui::ET_GESTURE_PINCH_BEGIN
));
2644 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_PINCH_BEGIN
));
2645 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_PINCH_BEGIN
));
2646 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_PINCH_BEGIN
));
2647 EXPECT_EQ(v1
, GetGestureHandler(root_view
));
2648 EXPECT_TRUE(pinch_begin
.handled());
2654 // A ui::ET_GESTURE_END event should be dispatched to |v1| and should
2655 // set the gesture handler to NULL.
2656 GestureEventForTest
end(ui::ET_GESTURE_END
, 5, 5);
2657 widget
->OnGestureEvent(&end
);
2658 EXPECT_EQ(1, v1
->GetEventCount(ui::ET_GESTURE_END
));
2659 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_END
));
2660 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_END
));
2661 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_END
));
2662 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2663 EXPECT_TRUE(end
.handled());
2668 // A class used in WidgetTest.GestureEventLocationWhileBubbling to verify
2669 // that when a gesture event bubbles up a View hierarchy, the location
2670 // of a gesture event seen by each View is in the local coordinate space
2672 class GestureLocationView
: public EventCountView
{
2674 GestureLocationView() {}
2675 ~GestureLocationView() override
{}
2677 void set_expected_location(gfx::Point expected_location
) {
2678 expected_location_
= expected_location
;
2682 void OnGestureEvent(ui::GestureEvent
* event
) override
{
2683 EventCountView::OnGestureEvent(event
);
2685 // Verify that the location of |event| is in the local coordinate
2687 EXPECT_EQ(expected_location_
, event
->location());
2691 // The expected location of a gesture event dispatched to |this|.
2692 gfx::Point expected_location_
;
2694 DISALLOW_COPY_AND_ASSIGN(GestureLocationView
);
2697 // Verifies that the location of a gesture event is always in the local
2698 // coordinate space of the View receiving the event while bubbling.
2699 TEST_F(WidgetTest
, GestureEventLocationWhileBubbling
) {
2700 Widget
* widget
= CreateTopLevelNativeWidget();
2701 widget
->SetBounds(gfx::Rect(0, 0, 300, 300));
2703 // Define a hierarchy of three views (coordinates shown below are in the
2704 // coordinate space of the root view, but the coordinates used for
2705 // SetBounds() are in their parent coordinate space).
2706 // v1 (50, 50, 150, 150)
2707 // v2 (100, 70, 50, 80)
2708 // v3 (120, 100, 10, 10)
2709 GestureLocationView
* v1
= new GestureLocationView();
2710 v1
->SetBounds(50, 50, 150, 150);
2711 GestureLocationView
* v2
= new GestureLocationView();
2712 v2
->SetBounds(50, 20, 50, 80);
2713 GestureLocationView
* v3
= new GestureLocationView();
2714 v3
->SetBounds(20, 30, 10, 10);
2715 internal::RootView
* root_view
=
2716 static_cast<internal::RootView
*>(widget
->GetRootView());
2717 root_view
->AddChildView(v1
);
2718 v1
->AddChildView(v2
);
2719 v2
->AddChildView(v3
);
2723 // Define a GESTURE_TAP event located at (125, 105) in root view coordinates.
2724 // This event is contained within all of |v1|, |v2|, and |v3|.
2725 gfx::Point
location_in_root(125, 105);
2726 GestureEventForTest
tap(
2727 ui::ET_GESTURE_TAP
, location_in_root
.x(), location_in_root
.y());
2729 // Calculate the location of the event in the local coordinate spaces
2730 // of each of the views.
2731 gfx::Point
location_in_v1(ConvertPointFromWidgetToView(v1
, location_in_root
));
2732 EXPECT_EQ(gfx::Point(75, 55), location_in_v1
);
2733 gfx::Point
location_in_v2(ConvertPointFromWidgetToView(v2
, location_in_root
));
2734 EXPECT_EQ(gfx::Point(25, 35), location_in_v2
);
2735 gfx::Point
location_in_v3(ConvertPointFromWidgetToView(v3
, location_in_root
));
2736 EXPECT_EQ(gfx::Point(5, 5), location_in_v3
);
2738 // Dispatch the event. When each view receives the event, its location should
2739 // be in the local coordinate space of that view (see the check made by
2740 // GestureLocationView). After dispatch is complete the event's location
2741 // should be in the root coordinate space.
2742 v1
->set_expected_location(location_in_v1
);
2743 v2
->set_expected_location(location_in_v2
);
2744 v3
->set_expected_location(location_in_v3
);
2745 widget
->OnGestureEvent(&tap
);
2746 EXPECT_EQ(location_in_root
, tap
.location());
2748 // Verify that each view did in fact see the event.
2749 EventCountView
* view1
= v1
;
2750 EventCountView
* view2
= v2
;
2751 EventCountView
* view3
= v3
;
2752 EXPECT_EQ(1, view1
->GetEventCount(ui::ET_GESTURE_TAP
));
2753 EXPECT_EQ(1, view2
->GetEventCount(ui::ET_GESTURE_TAP
));
2754 EXPECT_EQ(1, view3
->GetEventCount(ui::ET_GESTURE_TAP
));
2759 // Verifies that disabled views are permitted to be set as the default gesture
2760 // handler in RootView. Also verifies that gesture events targeted to a disabled
2761 // view are not actually dispatched to the view, but are still marked as
2763 TEST_F(WidgetTest
, DisabledGestureEventTarget
) {
2764 Widget
* widget
= CreateTopLevelNativeWidget();
2765 widget
->SetBounds(gfx::Rect(0, 0, 300, 300));
2767 // Define a hierarchy of four views (coordinates are in
2768 // their parent coordinate space).
2769 // v1 (0, 0, 300, 300)
2770 // v2 (0, 0, 100, 100)
2771 // v3 (0, 0, 50, 50)
2773 EventCountView
* v1
= new EventCountView();
2774 v1
->SetBounds(0, 0, 300, 300);
2775 EventCountView
* v2
= new EventCountView();
2776 v2
->SetBounds(0, 0, 100, 100);
2777 EventCountView
* v3
= new EventCountView();
2778 v3
->SetBounds(0, 0, 50, 50);
2779 EventCountView
* v4
= new EventCountView();
2780 v4
->SetBounds(0, 0, 10, 10);
2781 internal::RootView
* root_view
=
2782 static_cast<internal::RootView
*>(widget
->GetRootView());
2783 root_view
->AddChildView(v1
);
2784 v1
->AddChildView(v2
);
2785 v2
->AddChildView(v3
);
2786 v3
->AddChildView(v4
);
2790 // |v1|, |v2|, and |v3| all handle gesture events but |v3| is marked as
2792 v1
->set_handle_mode(EventCountView::CONSUME_EVENTS
);
2793 v2
->set_handle_mode(EventCountView::CONSUME_EVENTS
);
2794 v3
->set_handle_mode(EventCountView::CONSUME_EVENTS
);
2795 v3
->SetEnabled(false);
2797 // No gesture handler is set in the root view. In this case the tap event
2798 // should be dispatched only to |v4|, the gesture handler should be set to
2799 // |v3|, and the event should be marked as handled.
2800 GestureEventForTest
tap(ui::ET_GESTURE_TAP
, 5, 5);
2801 widget
->OnGestureEvent(&tap
);
2802 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_TAP
));
2803 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_TAP
));
2804 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_TAP
));
2805 EXPECT_EQ(1, v4
->GetEventCount(ui::ET_GESTURE_TAP
));
2806 EXPECT_EQ(v3
, GetGestureHandler(root_view
));
2807 EXPECT_TRUE(tap
.handled());
2813 // A subsequent gesture event should be marked as handled but not dispatched.
2814 tap
= GestureEventForTest(ui::ET_GESTURE_TAP
, 5, 5);
2815 widget
->OnGestureEvent(&tap
);
2816 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_TAP
));
2817 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_TAP
));
2818 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_TAP
));
2819 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_TAP
));
2820 EXPECT_EQ(v3
, GetGestureHandler(root_view
));
2821 EXPECT_TRUE(tap
.handled());
2827 // A GESTURE_END should reset the default gesture handler to NULL. It should
2828 // also not be dispatched to |v3| but still marked as handled.
2829 GestureEventForTest
end(ui::ET_GESTURE_END
, 5, 5);
2830 widget
->OnGestureEvent(&end
);
2831 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_END
));
2832 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_END
));
2833 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_END
));
2834 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_END
));
2835 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2836 EXPECT_TRUE(end
.handled());
2842 // Change the handle mode of |v3| to indicate that it would no longer like
2843 // to handle events which are dispatched to it.
2844 v3
->set_handle_mode(EventCountView::PROPAGATE_EVENTS
);
2846 // No gesture handler is set in the root view. In this case the tap event
2847 // should be dispatched only to |v4| and the event should be marked as
2848 // handled. Furthermore, the gesture handler should be set to
2849 // |v3|; even though |v3| does not explicitly handle events, it is a
2850 // valid target for the tap event because it is disabled.
2851 tap
= GestureEventForTest(ui::ET_GESTURE_TAP
, 5, 5);
2852 widget
->OnGestureEvent(&tap
);
2853 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_TAP
));
2854 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_TAP
));
2855 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_TAP
));
2856 EXPECT_EQ(1, v4
->GetEventCount(ui::ET_GESTURE_TAP
));
2857 EXPECT_EQ(v3
, GetGestureHandler(root_view
));
2858 EXPECT_TRUE(tap
.handled());
2864 // A GESTURE_END should reset the default gesture handler to NULL. It should
2865 // also not be dispatched to |v3| but still marked as handled.
2866 end
= GestureEventForTest(ui::ET_GESTURE_END
, 5, 5);
2867 widget
->OnGestureEvent(&end
);
2868 EXPECT_EQ(0, v1
->GetEventCount(ui::ET_GESTURE_END
));
2869 EXPECT_EQ(0, v2
->GetEventCount(ui::ET_GESTURE_END
));
2870 EXPECT_EQ(0, v3
->GetEventCount(ui::ET_GESTURE_END
));
2871 EXPECT_EQ(0, v4
->GetEventCount(ui::ET_GESTURE_END
));
2872 EXPECT_EQ(NULL
, GetGestureHandler(root_view
));
2873 EXPECT_TRUE(end
.handled());
2878 // Test the result of Widget::GetAllChildWidgets().
2879 TEST_F(WidgetTest
, GetAllChildWidgets
) {
2880 // Create the following widget hierarchy:
2888 Widget
* toplevel
= CreateTopLevelPlatformWidget();
2889 Widget
* w1
= CreateChildPlatformWidget(toplevel
->GetNativeView());
2890 Widget
* w11
= CreateChildPlatformWidget(w1
->GetNativeView());
2891 Widget
* w2
= CreateChildPlatformWidget(toplevel
->GetNativeView());
2892 Widget
* w21
= CreateChildPlatformWidget(w2
->GetNativeView());
2893 Widget
* w22
= CreateChildPlatformWidget(w2
->GetNativeView());
2895 std::set
<Widget
*> expected
;
2896 expected
.insert(toplevel
);
2897 expected
.insert(w1
);
2898 expected
.insert(w11
);
2899 expected
.insert(w2
);
2900 expected
.insert(w21
);
2901 expected
.insert(w22
);
2903 std::set
<Widget
*> widgets
;
2904 Widget::GetAllChildWidgets(toplevel
->GetNativeView(), &widgets
);
2906 EXPECT_EQ(expected
.size(), widgets
.size());
2907 EXPECT_TRUE(std::equal(expected
.begin(), expected
.end(), widgets
.begin()));
2908 toplevel
->CloseNow();
2911 // Used by DestroyChildWidgetsInOrder. On destruction adds the supplied name to
2913 class DestroyedTrackingView
: public View
{
2915 DestroyedTrackingView(const std::string
& name
,
2916 std::vector
<std::string
>* add_to
)
2921 ~DestroyedTrackingView() override
{ add_to_
->push_back(name_
); }
2924 const std::string name_
;
2925 std::vector
<std::string
>* add_to_
;
2927 DISALLOW_COPY_AND_ASSIGN(DestroyedTrackingView
);
2930 class WidgetChildDestructionTest
: public WidgetTest
{
2932 WidgetChildDestructionTest() {}
2934 // Creates a top level and a child, destroys the child and verifies the views
2935 // of the child are destroyed before the views of the parent.
2936 void RunDestroyChildWidgetsTest(bool top_level_has_desktop_native_widget_aura
,
2937 bool child_has_desktop_native_widget_aura
) {
2938 // When a View is destroyed its name is added here.
2939 std::vector
<std::string
> destroyed
;
2941 Widget
* top_level
= new Widget
;
2942 Widget::InitParams params
=
2943 CreateParams(views::Widget::InitParams::TYPE_WINDOW
);
2944 #if !defined(OS_CHROMEOS)
2945 if (top_level_has_desktop_native_widget_aura
)
2946 params
.native_widget
= new PlatformDesktopNativeWidget(top_level
);
2948 top_level
->Init(params
);
2949 top_level
->GetRootView()->AddChildView(
2950 new DestroyedTrackingView("parent", &destroyed
));
2953 Widget
* child
= new Widget
;
2954 Widget::InitParams child_params
=
2955 CreateParams(views::Widget::InitParams::TYPE_POPUP
);
2956 child_params
.parent
= top_level
->GetNativeView();
2957 #if !defined(OS_CHROMEOS)
2958 if (child_has_desktop_native_widget_aura
)
2959 child_params
.native_widget
= new PlatformDesktopNativeWidget(child
);
2961 child
->Init(child_params
);
2962 child
->GetRootView()->AddChildView(
2963 new DestroyedTrackingView("child", &destroyed
));
2966 // Should trigger destruction of the child too.
2967 top_level
->native_widget_private()->CloseNow();
2969 // Child should be destroyed first.
2970 ASSERT_EQ(2u, destroyed
.size());
2971 EXPECT_EQ("child", destroyed
[0]);
2972 EXPECT_EQ("parent", destroyed
[1]);
2976 DISALLOW_COPY_AND_ASSIGN(WidgetChildDestructionTest
);
2979 #if !defined(OS_CHROMEOS)
2980 // See description of RunDestroyChildWidgetsTest(). Parent uses
2981 // DesktopNativeWidgetAura.
2982 TEST_F(WidgetChildDestructionTest
,
2983 DestroyChildWidgetsInOrderWithDesktopNativeWidget
) {
2984 RunDestroyChildWidgetsTest(true, false);
2987 // See description of RunDestroyChildWidgetsTest(). Both parent and child use
2988 // DesktopNativeWidgetAura.
2989 TEST_F(WidgetChildDestructionTest
,
2990 DestroyChildWidgetsInOrderWithDesktopNativeWidgetForBoth
) {
2991 RunDestroyChildWidgetsTest(true, true);
2993 #endif // !defined(OS_CHROMEOS)
2995 // See description of RunDestroyChildWidgetsTest().
2996 TEST_F(WidgetChildDestructionTest
, DestroyChildWidgetsInOrder
) {
2997 RunDestroyChildWidgetsTest(false, false);
3000 // Verifies nativeview visbility matches that of Widget visibility when
3001 // SetFullscreen is invoked.
3002 TEST_F(WidgetTest
, FullscreenStatePropagated
) {
3003 Widget::InitParams init_params
=
3004 CreateParams(Widget::InitParams::TYPE_WINDOW
);
3005 init_params
.show_state
= ui::SHOW_STATE_NORMAL
;
3006 init_params
.bounds
= gfx::Rect(0, 0, 500, 500);
3007 init_params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
3010 Widget top_level_widget
;
3011 top_level_widget
.Init(init_params
);
3012 top_level_widget
.SetFullscreen(true);
3013 EXPECT_EQ(top_level_widget
.IsVisible(),
3014 IsNativeWindowVisible(top_level_widget
.GetNativeWindow()));
3015 top_level_widget
.CloseNow();
3017 #if !defined(OS_CHROMEOS)
3019 Widget top_level_widget
;
3020 init_params
.native_widget
=
3021 new PlatformDesktopNativeWidget(&top_level_widget
);
3022 top_level_widget
.Init(init_params
);
3023 top_level_widget
.SetFullscreen(true);
3024 EXPECT_EQ(top_level_widget
.IsVisible(),
3025 IsNativeWindowVisible(top_level_widget
.GetNativeWindow()));
3026 top_level_widget
.CloseNow();
3033 class FullscreenAwareFrame
: public views::NonClientFrameView
{
3035 explicit FullscreenAwareFrame(views::Widget
* widget
)
3036 : widget_(widget
), fullscreen_layout_called_(false) {}
3037 ~FullscreenAwareFrame() override
{}
3039 // views::NonClientFrameView overrides:
3040 gfx::Rect
GetBoundsForClientView() const override
{ return gfx::Rect(); }
3041 gfx::Rect
GetWindowBoundsForClientBounds(
3042 const gfx::Rect
& client_bounds
) const override
{
3045 int NonClientHitTest(const gfx::Point
& point
) override
{ return HTNOWHERE
; }
3046 void GetWindowMask(const gfx::Size
& size
, gfx::Path
* window_mask
) override
{}
3047 void ResetWindowControls() override
{}
3048 void UpdateWindowIcon() override
{}
3049 void UpdateWindowTitle() override
{}
3050 void SizeConstraintsChanged() override
{}
3052 // views::View overrides:
3053 void Layout() override
{
3054 if (widget_
->IsFullscreen())
3055 fullscreen_layout_called_
= true;
3058 bool fullscreen_layout_called() const { return fullscreen_layout_called_
; }
3061 views::Widget
* widget_
;
3062 bool fullscreen_layout_called_
;
3064 DISALLOW_COPY_AND_ASSIGN(FullscreenAwareFrame
);
3069 // Tests that frame Layout is called when a widget goes fullscreen without
3070 // changing its size or title.
3071 TEST_F(WidgetTest
, FullscreenFrameLayout
) {
3072 Widget
* widget
= CreateTopLevelPlatformWidget();
3073 FullscreenAwareFrame
* frame
= new FullscreenAwareFrame(widget
);
3074 widget
->non_client_view()->SetFrameView(frame
); // Owns |frame|.
3077 RunPendingMessages();
3079 EXPECT_FALSE(frame
->fullscreen_layout_called());
3080 widget
->SetFullscreen(true);
3082 RunPendingMessages();
3084 if (IsTestingSnowLeopard()) {
3085 // Fullscreen is currently ignored on Snow Leopard.
3086 EXPECT_FALSE(frame
->fullscreen_layout_called());
3088 EXPECT_TRUE(frame
->fullscreen_layout_called());
3094 #if !defined(OS_CHROMEOS)
3097 // Trivial WidgetObserverTest that invokes Widget::IsActive() from
3098 // OnWindowDestroying.
3099 class IsActiveFromDestroyObserver
: public WidgetObserver
{
3101 IsActiveFromDestroyObserver() {}
3102 ~IsActiveFromDestroyObserver() override
{}
3103 void OnWidgetDestroying(Widget
* widget
) override
{ widget
->IsActive(); }
3106 DISALLOW_COPY_AND_ASSIGN(IsActiveFromDestroyObserver
);
3111 // Verifies Widget::IsActive() invoked from
3112 // WidgetObserver::OnWidgetDestroying() in a child widget doesn't crash.
3113 TEST_F(WidgetTest
, IsActiveFromDestroy
) {
3114 // Create two widgets, one a child of the other.
3115 IsActiveFromDestroyObserver observer
;
3116 Widget parent_widget
;
3117 Widget::InitParams parent_params
=
3118 CreateParams(Widget::InitParams::TYPE_POPUP
);
3119 parent_params
.native_widget
= new PlatformDesktopNativeWidget(&parent_widget
);
3120 parent_params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
3121 parent_widget
.Init(parent_params
);
3122 parent_widget
.Show();
3124 Widget child_widget
;
3125 Widget::InitParams child_params
=
3126 CreateParams(Widget::InitParams::TYPE_POPUP
);
3127 child_params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
3128 child_params
.context
= parent_widget
.GetNativeWindow();
3129 child_widget
.Init(child_params
);
3130 child_widget
.AddObserver(&observer
);
3131 child_widget
.Show();
3133 parent_widget
.CloseNow();
3135 #endif // !defined(OS_CHROMEOS)
3137 // Tests that events propagate through from the dispatcher with the correct
3138 // event type, and that the different platforms behave the same.
3139 TEST_F(WidgetTest
, MouseEventTypesViaGenerator
) {
3140 EventCountView
* view
= new EventCountView
;
3141 view
->set_handle_mode(EventCountView::CONSUME_EVENTS
);
3142 view
->SetBounds(10, 10, 50, 40);
3144 Widget
* widget
= CreateTopLevelFramelessPlatformWidget();
3145 widget
->GetRootView()->AddChildView(view
);
3147 widget
->SetBounds(gfx::Rect(0, 0, 100, 80));
3150 ui::test::EventGenerator
generator(GetContext(), widget
->GetNativeWindow());
3151 generator
.set_current_location(gfx::Point(20, 20));
3153 generator
.ClickLeftButton();
3154 EXPECT_EQ(1, view
->GetEventCount(ui::ET_MOUSE_PRESSED
));
3155 EXPECT_EQ(1, view
->GetEventCount(ui::ET_MOUSE_RELEASED
));
3156 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON
, view
->last_flags());
3158 generator
.PressRightButton();
3159 EXPECT_EQ(2, view
->GetEventCount(ui::ET_MOUSE_PRESSED
));
3160 EXPECT_EQ(1, view
->GetEventCount(ui::ET_MOUSE_RELEASED
));
3161 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON
, view
->last_flags());
3163 generator
.ReleaseRightButton();
3164 EXPECT_EQ(2, view
->GetEventCount(ui::ET_MOUSE_PRESSED
));
3165 EXPECT_EQ(2, view
->GetEventCount(ui::ET_MOUSE_RELEASED
));
3166 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON
, view
->last_flags());
3168 // Test mouse move events.
3169 EXPECT_EQ(0, view
->GetEventCount(ui::ET_MOUSE_MOVED
));
3170 EXPECT_EQ(0, view
->GetEventCount(ui::ET_MOUSE_ENTERED
));
3172 // Move the mouse within the view (20, 20) -> (30, 30).
3173 generator
.MoveMouseTo(gfx::Point(30, 30));
3174 EXPECT_EQ(1, view
->GetEventCount(ui::ET_MOUSE_MOVED
));
3175 EXPECT_EQ(1, view
->GetEventCount(ui::ET_MOUSE_ENTERED
));
3176 EXPECT_EQ(ui::EF_NONE
, view
->last_flags());
3178 // Move it again - entered count shouldn't change.
3179 generator
.MoveMouseTo(gfx::Point(31, 31));
3180 EXPECT_EQ(2, view
->GetEventCount(ui::ET_MOUSE_MOVED
));
3181 EXPECT_EQ(1, view
->GetEventCount(ui::ET_MOUSE_ENTERED
));
3182 EXPECT_EQ(0, view
->GetEventCount(ui::ET_MOUSE_EXITED
));
3184 // Move it off the view.
3185 generator
.MoveMouseTo(gfx::Point(5, 5));
3186 EXPECT_EQ(2, view
->GetEventCount(ui::ET_MOUSE_MOVED
));
3187 EXPECT_EQ(1, view
->GetEventCount(ui::ET_MOUSE_ENTERED
));
3188 EXPECT_EQ(1, view
->GetEventCount(ui::ET_MOUSE_EXITED
));
3191 generator
.MoveMouseTo(gfx::Point(20, 20));
3192 EXPECT_EQ(3, view
->GetEventCount(ui::ET_MOUSE_MOVED
));
3193 EXPECT_EQ(2, view
->GetEventCount(ui::ET_MOUSE_ENTERED
));
3194 EXPECT_EQ(1, view
->GetEventCount(ui::ET_MOUSE_EXITED
));
3196 // Drargging. Cover HasCapture() and NativeWidgetPrivate::IsMouseButtonDown().
3197 generator
.DragMouseTo(gfx::Point(40, 40));
3198 EXPECT_EQ(3, view
->GetEventCount(ui::ET_MOUSE_PRESSED
));
3199 EXPECT_EQ(3, view
->GetEventCount(ui::ET_MOUSE_RELEASED
));
3200 EXPECT_EQ(1, view
->GetEventCount(ui::ET_MOUSE_DRAGGED
));
3201 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON
, view
->last_flags());
3206 // Tests that the root view is correctly set up for Widget types that do not
3207 // require a non-client view, before any other views are added to the widget.
3208 // That is, before Widget::ReorderNativeViews() is called which, if called with
3209 // a root view not set, could cause the root view to get resized to the widget.
3210 TEST_F(WidgetTest
, NonClientWindowValidAfterInit
) {
3211 Widget
* widget
= CreateTopLevelFramelessPlatformWidget();
3212 View
* root_view
= widget
->GetRootView();
3214 // Size the root view to exceed the widget bounds.
3215 const gfx::Rect
test_rect(0, 0, 500, 500);
3216 root_view
->SetBoundsRect(test_rect
);
3218 EXPECT_NE(test_rect
.size(), widget
->GetWindowBoundsInScreen().size());
3220 EXPECT_EQ(test_rect
, root_view
->bounds());
3221 widget
->ReorderNativeViews();
3222 EXPECT_EQ(test_rect
, root_view
->bounds());
3228 // This test validates that sending WM_CHAR/WM_SYSCHAR/WM_SYSDEADCHAR
3229 // messages via the WindowEventTarget interface implemented by the
3230 // HWNDMessageHandler class does not cause a crash due to an unprocessed
3232 TEST_F(WidgetTest
, CharMessagesAsKeyboardMessagesDoesNotCrash
) {
3234 Widget::InitParams params
=
3235 CreateParams(Widget::InitParams::TYPE_WINDOW
);
3236 params
.native_widget
= new PlatformDesktopNativeWidget(&widget
);
3237 params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
3238 widget
.Init(params
);
3241 ui::WindowEventTarget
* target
=
3242 reinterpret_cast<ui::WindowEventTarget
*>(ui::ViewProp::GetValue(
3243 widget
.GetNativeWindow()->GetHost()->GetAcceleratedWidget(),
3244 ui::WindowEventTarget::kWin32InputEventTarget
));
3245 EXPECT_NE(nullptr, target
);
3246 bool handled
= false;
3247 target
->HandleKeyboardMessage(WM_CHAR
, 0, 0, &handled
);
3248 target
->HandleKeyboardMessage(WM_SYSCHAR
, 0, 0, &handled
);
3249 target
->HandleKeyboardMessage(WM_SYSDEADCHAR
, 0, 0, &handled
);
3254 // Test that SetAlwaysOnTop and IsAlwaysOnTop are consistent.
3255 TEST_F(WidgetTest
, AlwaysOnTop
) {
3256 Widget
* widget
= CreateTopLevelNativeWidget();
3257 EXPECT_FALSE(widget
->IsAlwaysOnTop());
3258 widget
->SetAlwaysOnTop(true);
3259 EXPECT_TRUE(widget
->IsAlwaysOnTop());
3260 widget
->SetAlwaysOnTop(false);
3261 EXPECT_FALSE(widget
->IsAlwaysOnTop());
3266 } // namespace views