Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(126)

Unified Diff: ui/views/widget/widget_unittest.cc

Issue 851853002: It is time. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Trying to reup because the last upload failed. Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/views/widget/widget_removals_observer.h ('k') | ui/views/widget/window_reorderer.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/views/widget/widget_unittest.cc
diff --git a/ui/views/widget/widget_unittest.cc b/ui/views/widget/widget_unittest.cc
deleted file mode 100644
index 374435f6b038fa0de5b389f73b05e601a26e2f45..0000000000000000000000000000000000000000
--- a/ui/views/widget/widget_unittest.cc
+++ /dev/null
@@ -1,3379 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <algorithm>
-#include <set>
-
-#include "base/basictypes.h"
-#include "base/bind.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/hit_test.h"
-#include "ui/compositor/layer_animation_observer.h"
-#include "ui/compositor/scoped_animation_duration_scale_mode.h"
-#include "ui/compositor/scoped_layer_animation_settings.h"
-#include "ui/events/event_processor.h"
-#include "ui/events/event_utils.h"
-#include "ui/events/test/event_generator.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gfx/point.h"
-#include "ui/views/bubble/bubble_delegate.h"
-#include "ui/views/controls/textfield/textfield.h"
-#include "ui/views/test/test_views_delegate.h"
-#include "ui/views/test/widget_test.h"
-#include "ui/views/views_delegate.h"
-#include "ui/views/widget/native_widget_delegate.h"
-#include "ui/views/widget/root_view.h"
-#include "ui/views/widget/widget_deletion_observer.h"
-#include "ui/views/window/dialog_delegate.h"
-#include "ui/views/window/native_frame_view.h"
-
-#if defined(OS_WIN)
-#include "ui/views/win/hwnd_util.h"
-#endif
-
-namespace views {
-namespace test {
-
-namespace {
-
-// TODO(tdanderson): This utility function is used in different unittest
-// files. Move to a common location to avoid
-// repeated code.
-gfx::Point ConvertPointFromWidgetToView(View* view, const gfx::Point& p) {
- gfx::Point tmp(p);
- View::ConvertPointToTarget(view->GetWidget()->GetRootView(), view, &tmp);
- return tmp;
-}
-
-} // namespace
-
-// A view that keeps track of the events it receives, optionally consuming them.
-class EventCountView : public View {
- public:
- // Whether to call SetHandled() on events as they are received. For some event
- // types, this will allow EventCountView to receives future events in the
- // event sequence, such as a drag.
- enum HandleMode {
- PROPAGATE_EVENTS,
- CONSUME_EVENTS
- };
-
- EventCountView()
- : last_flags_(0),
- handle_mode_(PROPAGATE_EVENTS) {}
-
- virtual ~EventCountView() {}
-
- int GetEventCount(ui::EventType type) {
- return event_count_[type];
- }
-
- void ResetCounts() {
- event_count_.clear();
- }
-
- int last_flags() const {
- return last_flags_;
- }
-
- void set_handle_mode(HandleMode handle_mode) {
- handle_mode_ = handle_mode;
- }
-
- protected:
- // Overridden from View:
- virtual void OnMouseMoved(const ui::MouseEvent& event) override {
- // MouseMove events are not re-dispatched from the RootView.
- ++event_count_[ui::ET_MOUSE_MOVED];
- last_flags_ = 0;
- }
-
- // Overridden from ui::EventHandler:
- virtual void OnKeyEvent(ui::KeyEvent* event) override {
- RecordEvent(event);
- }
- virtual void OnMouseEvent(ui::MouseEvent* event) override {
- RecordEvent(event);
- }
- virtual void OnScrollEvent(ui::ScrollEvent* event) override {
- RecordEvent(event);
- }
- virtual void OnGestureEvent(ui::GestureEvent* event) override {
- RecordEvent(event);
- }
-
- private:
- void RecordEvent(ui::Event* event) {
- ++event_count_[event->type()];
- last_flags_ = event->flags();
- if (handle_mode_ == CONSUME_EVENTS)
- event->SetHandled();
- }
-
- std::map<ui::EventType, int> event_count_;
- int last_flags_;
- HandleMode handle_mode_;
-
- DISALLOW_COPY_AND_ASSIGN(EventCountView);
-};
-
-// A view that keeps track of the events it receives, and consumes all scroll
-// gesture events and ui::ET_SCROLL events.
-class ScrollableEventCountView : public EventCountView {
- public:
- ScrollableEventCountView() {}
- virtual ~ScrollableEventCountView() {}
-
- private:
- // Overridden from ui::EventHandler:
- virtual void OnGestureEvent(ui::GestureEvent* event) override {
- EventCountView::OnGestureEvent(event);
- switch (event->type()) {
- case ui::ET_GESTURE_SCROLL_BEGIN:
- case ui::ET_GESTURE_SCROLL_UPDATE:
- case ui::ET_GESTURE_SCROLL_END:
- case ui::ET_SCROLL_FLING_START:
- event->SetHandled();
- break;
- default:
- break;
- }
- }
-
- virtual void OnScrollEvent(ui::ScrollEvent* event) override {
- EventCountView::OnScrollEvent(event);
- if (event->type() == ui::ET_SCROLL)
- event->SetHandled();
- }
-
- DISALLOW_COPY_AND_ASSIGN(ScrollableEventCountView);
-};
-
-// A view that implements GetMinimumSize.
-class MinimumSizeFrameView : public NativeFrameView {
- public:
- explicit MinimumSizeFrameView(Widget* frame): NativeFrameView(frame) {}
- virtual ~MinimumSizeFrameView() {}
-
- private:
- // Overridden from View:
- virtual gfx::Size GetMinimumSize() const override {
- return gfx::Size(300, 400);
- }
-
- DISALLOW_COPY_AND_ASSIGN(MinimumSizeFrameView);
-};
-
-// An event handler that simply keeps a count of the different types of events
-// it receives.
-class EventCountHandler : public ui::EventHandler {
- public:
- EventCountHandler() {}
- virtual ~EventCountHandler() {}
-
- int GetEventCount(ui::EventType type) {
- return event_count_[type];
- }
-
- void ResetCounts() {
- event_count_.clear();
- }
-
- protected:
- // Overridden from ui::EventHandler:
- virtual void OnEvent(ui::Event* event) override {
- RecordEvent(*event);
- ui::EventHandler::OnEvent(event);
- }
-
- private:
- void RecordEvent(const ui::Event& event) {
- ++event_count_[event.type()];
- }
-
- std::map<ui::EventType, int> event_count_;
-
- DISALLOW_COPY_AND_ASSIGN(EventCountHandler);
-};
-
-// Class that closes the widget (which ends up deleting it immediately) when the
-// appropriate event is received.
-class CloseWidgetView : public View {
- public:
- explicit CloseWidgetView(ui::EventType event_type)
- : event_type_(event_type) {
- }
-
- // ui::EventHandler override:
- virtual void OnEvent(ui::Event* event) override {
- if (event->type() == event_type_) {
- // Go through NativeWidgetPrivate to simulate what happens if the OS
- // deletes the NativeWindow out from under us.
- GetWidget()->native_widget_private()->CloseNow();
- } else {
- View::OnEvent(event);
- if (!event->IsTouchEvent())
- event->SetHandled();
- }
- }
-
- private:
- const ui::EventType event_type_;
-
- DISALLOW_COPY_AND_ASSIGN(CloseWidgetView);
-};
-
-ui::WindowShowState GetWidgetShowState(const Widget* widget) {
- // Use IsMaximized/IsMinimized/IsFullScreen instead of GetWindowPlacement
- // because the former is implemented on all platforms but the latter is not.
- return widget->IsFullscreen() ? ui::SHOW_STATE_FULLSCREEN :
- widget->IsMaximized() ? ui::SHOW_STATE_MAXIMIZED :
- widget->IsMinimized() ? ui::SHOW_STATE_MINIMIZED :
- widget->IsActive() ? ui::SHOW_STATE_NORMAL :
- ui::SHOW_STATE_INACTIVE;
-}
-
-TEST_F(WidgetTest, WidgetInitParams) {
- // Widgets are not transparent by default.
- Widget::InitParams init1;
- EXPECT_EQ(Widget::InitParams::INFER_OPACITY, init1.opacity);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Widget::GetTopLevelWidget tests.
-
-TEST_F(WidgetTest, GetTopLevelWidget_Native) {
- // Create a hierarchy of native widgets.
- Widget* toplevel = CreateTopLevelPlatformWidget();
- gfx::NativeView parent = toplevel->GetNativeView();
- Widget* child = CreateChildPlatformWidget(parent);
-
- EXPECT_EQ(toplevel, toplevel->GetTopLevelWidget());
- EXPECT_EQ(toplevel, child->GetTopLevelWidget());
-
- toplevel->CloseNow();
- // |child| should be automatically destroyed with |toplevel|.
-}
-
-// Test if a focus manager and an inputmethod work without CHECK failure
-// when window activation changes.
-TEST_F(WidgetTest, ChangeActivation) {
- Widget* top1 = CreateTopLevelPlatformWidget();
- // CreateInputMethod before activated
- top1->GetInputMethod();
- top1->Show();
- RunPendingMessages();
-
- Widget* top2 = CreateTopLevelPlatformWidget();
- top2->Show();
- RunPendingMessages();
-
- top1->Activate();
- RunPendingMessages();
-
- // Create InputMethod after deactivated.
- top2->GetInputMethod();
- top2->Activate();
- RunPendingMessages();
-
- top1->Activate();
- RunPendingMessages();
-
- top1->CloseNow();
- top2->CloseNow();
-}
-
-// Tests visibility of child widgets.
-TEST_F(WidgetTest, Visibility) {
- Widget* toplevel = CreateTopLevelPlatformWidget();
- gfx::NativeView parent = toplevel->GetNativeView();
- Widget* child = CreateChildPlatformWidget(parent);
-
- EXPECT_FALSE(toplevel->IsVisible());
- EXPECT_FALSE(child->IsVisible());
-
- child->Show();
-
- EXPECT_FALSE(toplevel->IsVisible());
- EXPECT_FALSE(child->IsVisible());
-
- toplevel->Show();
-
- EXPECT_TRUE(toplevel->IsVisible());
- EXPECT_TRUE(child->IsVisible());
-
- toplevel->CloseNow();
- // |child| should be automatically destroyed with |toplevel|.
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Widget ownership tests.
-//
-// Tests various permutations of Widget ownership specified in the
-// InitParams::Ownership param.
-
-// A WidgetTest that supplies a toplevel widget for NativeWidget to parent to.
-class WidgetOwnershipTest : public WidgetTest {
- public:
- WidgetOwnershipTest() {}
- virtual ~WidgetOwnershipTest() {}
-
- virtual void SetUp() {
- WidgetTest::SetUp();
- desktop_widget_ = CreateTopLevelPlatformWidget();
- }
-
- virtual void TearDown() {
- desktop_widget_->CloseNow();
- WidgetTest::TearDown();
- }
-
- private:
- Widget* desktop_widget_;
-
- DISALLOW_COPY_AND_ASSIGN(WidgetOwnershipTest);
-};
-
-// A bag of state to monitor destructions.
-struct OwnershipTestState {
- OwnershipTestState() : widget_deleted(false), native_widget_deleted(false) {}
-
- bool widget_deleted;
- bool native_widget_deleted;
-};
-
-// A platform NativeWidget subclass that updates a bag of state when it is
-// destroyed.
-class OwnershipTestNativeWidget : public PlatformNativeWidget {
- public:
- OwnershipTestNativeWidget(internal::NativeWidgetDelegate* delegate,
- OwnershipTestState* state)
- : PlatformNativeWidget(delegate),
- state_(state) {
- }
- virtual ~OwnershipTestNativeWidget() {
- state_->native_widget_deleted = true;
- }
-
- private:
- OwnershipTestState* state_;
-
- DISALLOW_COPY_AND_ASSIGN(OwnershipTestNativeWidget);
-};
-
-// A views NativeWidget subclass that updates a bag of state when it is
-// destroyed.
-class OwnershipTestNativeWidgetAura : public NativeWidgetCapture {
- public:
- OwnershipTestNativeWidgetAura(internal::NativeWidgetDelegate* delegate,
- OwnershipTestState* state)
- : NativeWidgetCapture(delegate),
- state_(state) {
- }
- virtual ~OwnershipTestNativeWidgetAura() {
- state_->native_widget_deleted = true;
- }
-
- private:
- OwnershipTestState* state_;
-
- DISALLOW_COPY_AND_ASSIGN(OwnershipTestNativeWidgetAura);
-};
-
-// A Widget subclass that updates a bag of state when it is destroyed.
-class OwnershipTestWidget : public Widget {
- public:
- explicit OwnershipTestWidget(OwnershipTestState* state) : state_(state) {}
- virtual ~OwnershipTestWidget() {
- state_->widget_deleted = true;
- }
-
- private:
- OwnershipTestState* state_;
-
- DISALLOW_COPY_AND_ASSIGN(OwnershipTestWidget);
-};
-
-// Widget owns its NativeWidget, part 1: NativeWidget is a platform-native
-// widget.
-TEST_F(WidgetOwnershipTest, Ownership_WidgetOwnsPlatformNativeWidget) {
- OwnershipTestState state;
-
- scoped_ptr<Widget> widget(new OwnershipTestWidget(&state));
- Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget =
- new OwnershipTestNativeWidgetAura(widget.get(), &state);
- params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- widget->Init(params);
-
- // Now delete the Widget, which should delete the NativeWidget.
- widget.reset();
-
- EXPECT_TRUE(state.widget_deleted);
- EXPECT_TRUE(state.native_widget_deleted);
-
- // TODO(beng): write test for this ownership scenario and the NativeWidget
- // being deleted out from under the Widget.
-}
-
-// Widget owns its NativeWidget, part 2: NativeWidget is a NativeWidget.
-TEST_F(WidgetOwnershipTest, Ownership_WidgetOwnsViewsNativeWidget) {
- OwnershipTestState state;
-
- scoped_ptr<Widget> widget(new OwnershipTestWidget(&state));
- Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget =
- new OwnershipTestNativeWidgetAura(widget.get(), &state);
- params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- widget->Init(params);
-
- // Now delete the Widget, which should delete the NativeWidget.
- widget.reset();
-
- EXPECT_TRUE(state.widget_deleted);
- EXPECT_TRUE(state.native_widget_deleted);
-
- // TODO(beng): write test for this ownership scenario and the NativeWidget
- // being deleted out from under the Widget.
-}
-
-// Widget owns its NativeWidget, part 3: NativeWidget is a NativeWidget,
-// destroy the parent view.
-TEST_F(WidgetOwnershipTest,
- Ownership_WidgetOwnsViewsNativeWidget_DestroyParentView) {
- OwnershipTestState state;
-
- Widget* toplevel = CreateTopLevelPlatformWidget();
-
- scoped_ptr<Widget> widget(new OwnershipTestWidget(&state));
- Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget =
- new OwnershipTestNativeWidgetAura(widget.get(), &state);
- params.parent = toplevel->GetNativeView();
- params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- widget->Init(params);
-
- // Now close the toplevel, which deletes the view hierarchy.
- toplevel->CloseNow();
-
- RunPendingMessages();
-
- // This shouldn't delete the widget because it shouldn't be deleted
- // from the native side.
- EXPECT_FALSE(state.widget_deleted);
- EXPECT_FALSE(state.native_widget_deleted);
-
- // Now delete it explicitly.
- widget.reset();
-
- EXPECT_TRUE(state.widget_deleted);
- EXPECT_TRUE(state.native_widget_deleted);
-}
-
-// NativeWidget owns its Widget, part 1: NativeWidget is a platform-native
-// widget.
-TEST_F(WidgetOwnershipTest, Ownership_PlatformNativeWidgetOwnsWidget) {
- OwnershipTestState state;
-
- Widget* widget = new OwnershipTestWidget(&state);
- Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget =
- new OwnershipTestNativeWidgetAura(widget, &state);
- widget->Init(params);
-
- // Now destroy the native widget.
- widget->CloseNow();
-
- EXPECT_TRUE(state.widget_deleted);
- EXPECT_TRUE(state.native_widget_deleted);
-}
-
-// NativeWidget owns its Widget, part 2: NativeWidget is a NativeWidget.
-TEST_F(WidgetOwnershipTest, Ownership_ViewsNativeWidgetOwnsWidget) {
- OwnershipTestState state;
-
- Widget* toplevel = CreateTopLevelPlatformWidget();
-
- Widget* widget = new OwnershipTestWidget(&state);
- Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget =
- new OwnershipTestNativeWidgetAura(widget, &state);
- params.parent = toplevel->GetNativeView();
- widget->Init(params);
-
- // Now destroy the native widget. This is achieved by closing the toplevel.
- toplevel->CloseNow();
-
- // The NativeWidget won't be deleted until after a return to the message loop
- // so we have to run pending messages before testing the destruction status.
- RunPendingMessages();
-
- EXPECT_TRUE(state.widget_deleted);
- EXPECT_TRUE(state.native_widget_deleted);
-}
-
-// NativeWidget owns its Widget, part 3: NativeWidget is a platform-native
-// widget, destroyed out from under it by the OS.
-TEST_F(WidgetOwnershipTest,
- Ownership_PlatformNativeWidgetOwnsWidget_NativeDestroy) {
- OwnershipTestState state;
-
- Widget* widget = new OwnershipTestWidget(&state);
- Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget =
- new OwnershipTestNativeWidgetAura(widget, &state);
- widget->Init(params);
-
- // Now simulate a destroy of the platform native widget from the OS:
- SimulateNativeDestroy(widget);
-
- EXPECT_TRUE(state.widget_deleted);
- EXPECT_TRUE(state.native_widget_deleted);
-}
-
-// NativeWidget owns its Widget, part 4: NativeWidget is a NativeWidget,
-// destroyed by the view hierarchy that contains it.
-TEST_F(WidgetOwnershipTest,
- Ownership_ViewsNativeWidgetOwnsWidget_NativeDestroy) {
- OwnershipTestState state;
-
- Widget* toplevel = CreateTopLevelPlatformWidget();
-
- Widget* widget = new OwnershipTestWidget(&state);
- Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget =
- new OwnershipTestNativeWidgetAura(widget, &state);
- params.parent = toplevel->GetNativeView();
- widget->Init(params);
-
- // Destroy the widget (achieved by closing the toplevel).
- toplevel->CloseNow();
-
- // The NativeWidget won't be deleted until after a return to the message loop
- // so we have to run pending messages before testing the destruction status.
- RunPendingMessages();
-
- EXPECT_TRUE(state.widget_deleted);
- EXPECT_TRUE(state.native_widget_deleted);
-}
-
-// NativeWidget owns its Widget, part 5: NativeWidget is a NativeWidget,
-// we close it directly.
-TEST_F(WidgetOwnershipTest,
- Ownership_ViewsNativeWidgetOwnsWidget_Close) {
- OwnershipTestState state;
-
- Widget* toplevel = CreateTopLevelPlatformWidget();
-
- Widget* widget = new OwnershipTestWidget(&state);
- Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget =
- new OwnershipTestNativeWidgetAura(widget, &state);
- params.parent = toplevel->GetNativeView();
- widget->Init(params);
-
- // Destroy the widget.
- widget->Close();
- toplevel->CloseNow();
-
- // The NativeWidget won't be deleted until after a return to the message loop
- // so we have to run pending messages before testing the destruction status.
- RunPendingMessages();
-
- EXPECT_TRUE(state.widget_deleted);
- EXPECT_TRUE(state.native_widget_deleted);
-}
-
-// Widget owns its NativeWidget and has a WidgetDelegateView as its contents.
-TEST_F(WidgetOwnershipTest,
- Ownership_WidgetOwnsNativeWidgetWithWithWidgetDelegateView) {
- OwnershipTestState state;
-
- WidgetDelegateView* delegate_view = new WidgetDelegateView;
-
- scoped_ptr<Widget> widget(new OwnershipTestWidget(&state));
- Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget =
- new OwnershipTestNativeWidgetAura(widget.get(), &state);
- params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params.delegate = delegate_view;
- widget->Init(params);
- widget->SetContentsView(delegate_view);
-
- // Now delete the Widget. There should be no crash or use-after-free.
- widget.reset();
-
- EXPECT_TRUE(state.widget_deleted);
- EXPECT_TRUE(state.native_widget_deleted);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Test to verify using various Widget methods doesn't crash when the underlying
-// NativeView is destroyed.
-//
-class WidgetWithDestroyedNativeViewTest : public ViewsTestBase {
- public:
- WidgetWithDestroyedNativeViewTest() {}
- virtual ~WidgetWithDestroyedNativeViewTest() {}
-
- void InvokeWidgetMethods(Widget* widget) {
- widget->GetNativeView();
- widget->GetNativeWindow();
- ui::Accelerator accelerator;
- widget->GetAccelerator(0, &accelerator);
- widget->GetTopLevelWidget();
- widget->GetWindowBoundsInScreen();
- widget->GetClientAreaBoundsInScreen();
- widget->SetBounds(gfx::Rect(0, 0, 100, 80));
- widget->SetSize(gfx::Size(10, 11));
- widget->SetBoundsConstrained(gfx::Rect(0, 0, 120, 140));
- widget->SetVisibilityChangedAnimationsEnabled(false);
- widget->StackAtTop();
- widget->IsClosed();
- widget->Close();
- widget->Hide();
- widget->Activate();
- widget->Deactivate();
- widget->IsActive();
- widget->DisableInactiveRendering();
- widget->SetAlwaysOnTop(true);
- widget->IsAlwaysOnTop();
- widget->Maximize();
- widget->Minimize();
- widget->Restore();
- widget->IsMaximized();
- widget->IsFullscreen();
- widget->SetOpacity(0);
- widget->SetUseDragFrame(true);
- widget->FlashFrame(true);
- widget->IsVisible();
- widget->GetThemeProvider();
- widget->GetNativeTheme();
- widget->GetFocusManager();
- widget->GetInputMethod();
- widget->SchedulePaintInRect(gfx::Rect(0, 0, 1, 2));
- widget->IsMouseEventsEnabled();
- widget->SetNativeWindowProperty("xx", widget);
- widget->GetNativeWindowProperty("xx");
- widget->GetFocusTraversable();
- widget->GetLayer();
- widget->ReorderNativeViews();
- widget->SetCapture(widget->GetRootView());
- widget->ReleaseCapture();
- widget->HasCapture();
- widget->GetWorkAreaBoundsInScreen();
- widget->IsTranslucentWindowOpacitySupported();
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(WidgetWithDestroyedNativeViewTest);
-};
-
-TEST_F(WidgetWithDestroyedNativeViewTest, Test) {
- {
- Widget widget;
- Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- widget.Init(params);
- widget.Show();
-
- widget.native_widget_private()->CloseNow();
- InvokeWidgetMethods(&widget);
- }
-#if !defined(OS_CHROMEOS)
- {
- Widget widget;
- Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget = new PlatformDesktopNativeWidget(&widget);
- params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- widget.Init(params);
- widget.Show();
-
- widget.native_widget_private()->CloseNow();
- InvokeWidgetMethods(&widget);
- }
-#endif
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Widget observer tests.
-//
-
-class WidgetObserverTest : public WidgetTest, public WidgetObserver {
- public:
- WidgetObserverTest()
- : active_(NULL),
- widget_closed_(NULL),
- widget_activated_(NULL),
- widget_shown_(NULL),
- widget_hidden_(NULL),
- widget_bounds_changed_(NULL) {
- }
-
- virtual ~WidgetObserverTest() {}
-
- // Overridden from WidgetObserver:
- virtual void OnWidgetDestroying(Widget* widget) override {
- if (active_ == widget)
- active_ = NULL;
- widget_closed_ = widget;
- }
-
- virtual void OnWidgetActivationChanged(Widget* widget,
- bool active) override {
- if (active) {
- if (widget_activated_)
- widget_activated_->Deactivate();
- widget_activated_ = widget;
- active_ = widget;
- } else {
- if (widget_activated_ == widget)
- widget_activated_ = NULL;
- widget_deactivated_ = widget;
- }
- }
-
- virtual void OnWidgetVisibilityChanged(Widget* widget,
- bool visible) override {
- if (visible)
- widget_shown_ = widget;
- else
- widget_hidden_ = widget;
- }
-
- virtual void OnWidgetBoundsChanged(Widget* widget,
- const gfx::Rect& new_bounds) override {
- widget_bounds_changed_ = widget;
- }
-
- void reset() {
- active_ = NULL;
- widget_closed_ = NULL;
- widget_activated_ = NULL;
- widget_deactivated_ = NULL;
- widget_shown_ = NULL;
- widget_hidden_ = NULL;
- widget_bounds_changed_ = NULL;
- }
-
- Widget* NewWidget() {
- Widget* widget = CreateTopLevelNativeWidget();
- widget->AddObserver(this);
- return widget;
- }
-
- const Widget* active() const { return active_; }
- const Widget* widget_closed() const { return widget_closed_; }
- const Widget* widget_activated() const { return widget_activated_; }
- const Widget* widget_deactivated() const { return widget_deactivated_; }
- const Widget* widget_shown() const { return widget_shown_; }
- const Widget* widget_hidden() const { return widget_hidden_; }
- const Widget* widget_bounds_changed() const { return widget_bounds_changed_; }
-
- private:
- Widget* active_;
-
- Widget* widget_closed_;
- Widget* widget_activated_;
- Widget* widget_deactivated_;
- Widget* widget_shown_;
- Widget* widget_hidden_;
- Widget* widget_bounds_changed_;
-};
-
-TEST_F(WidgetObserverTest, DISABLED_ActivationChange) {
- Widget* toplevel = CreateTopLevelPlatformWidget();
-
- Widget* toplevel1 = NewWidget();
- Widget* toplevel2 = NewWidget();
-
- toplevel1->Show();
- toplevel2->Show();
-
- reset();
-
- toplevel1->Activate();
-
- RunPendingMessages();
- EXPECT_EQ(toplevel1, widget_activated());
-
- toplevel2->Activate();
- RunPendingMessages();
- EXPECT_EQ(toplevel1, widget_deactivated());
- EXPECT_EQ(toplevel2, widget_activated());
- EXPECT_EQ(toplevel2, active());
-
- toplevel->CloseNow();
-}
-
-TEST_F(WidgetObserverTest, DISABLED_VisibilityChange) {
- Widget* toplevel = CreateTopLevelPlatformWidget();
-
- Widget* child1 = NewWidget();
- Widget* child2 = NewWidget();
-
- toplevel->Show();
- child1->Show();
- child2->Show();
-
- reset();
-
- child1->Hide();
- EXPECT_EQ(child1, widget_hidden());
-
- child2->Hide();
- EXPECT_EQ(child2, widget_hidden());
-
- child1->Show();
- EXPECT_EQ(child1, widget_shown());
-
- child2->Show();
- EXPECT_EQ(child2, widget_shown());
-
- toplevel->CloseNow();
-}
-
-TEST_F(WidgetObserverTest, DestroyBubble) {
- Widget* anchor = CreateTopLevelPlatformWidget();
- anchor->Show();
-
- BubbleDelegateView* bubble_delegate =
- new BubbleDelegateView(anchor->client_view(), BubbleBorder::NONE);
- Widget* bubble_widget(BubbleDelegateView::CreateBubble(bubble_delegate));
- bubble_widget->Show();
- bubble_widget->CloseNow();
-
- anchor->Hide();
- anchor->CloseNow();
-}
-
-TEST_F(WidgetObserverTest, WidgetBoundsChanged) {
- Widget* child1 = NewWidget();
- Widget* child2 = NewWidget();
-
- child1->OnNativeWidgetMove();
- EXPECT_EQ(child1, widget_bounds_changed());
-
- child2->OnNativeWidgetMove();
- EXPECT_EQ(child2, widget_bounds_changed());
-
- child1->OnNativeWidgetSizeChanged(gfx::Size());
- EXPECT_EQ(child1, widget_bounds_changed());
-
- child2->OnNativeWidgetSizeChanged(gfx::Size());
- EXPECT_EQ(child2, widget_bounds_changed());
-}
-
-// Tests that SetBounds() and GetWindowBoundsInScreen() is symmetric when the
-// widget is visible and not maximized or fullscreen.
-TEST_F(WidgetTest, GetWindowBoundsInScreen) {
- // Choose test coordinates away from edges and dimensions that are "small"
- // (but not too small) to ensure the OS doesn't try to adjust them.
- const gfx::Rect kTestBounds(150, 150, 400, 300);
- const gfx::Size kTestSize(200, 180);
-
- // First test a toplevel widget.
- Widget* widget = CreateTopLevelPlatformWidget();
- widget->Show();
-
- EXPECT_NE(kTestSize.ToString(),
- widget->GetWindowBoundsInScreen().size().ToString());
- widget->SetSize(kTestSize);
- EXPECT_EQ(kTestSize.ToString(),
- widget->GetWindowBoundsInScreen().size().ToString());
-
- EXPECT_NE(kTestBounds.ToString(),
- widget->GetWindowBoundsInScreen().ToString());
- widget->SetBounds(kTestBounds);
- EXPECT_EQ(kTestBounds.ToString(),
- widget->GetWindowBoundsInScreen().ToString());
-
- // Changing just the size should not change the origin.
- widget->SetSize(kTestSize);
- EXPECT_EQ(kTestBounds.origin().ToString(),
- widget->GetWindowBoundsInScreen().origin().ToString());
-
- widget->CloseNow();
-
- // Same tests with a frameless window.
- widget = CreateTopLevelFramelessPlatformWidget();
- widget->Show();
-
- EXPECT_NE(kTestSize.ToString(),
- widget->GetWindowBoundsInScreen().size().ToString());
- widget->SetSize(kTestSize);
- EXPECT_EQ(kTestSize.ToString(),
- widget->GetWindowBoundsInScreen().size().ToString());
-
- EXPECT_NE(kTestBounds.ToString(),
- widget->GetWindowBoundsInScreen().ToString());
- widget->SetBounds(kTestBounds);
- EXPECT_EQ(kTestBounds.ToString(),
- widget->GetWindowBoundsInScreen().ToString());
-
- // For a frameless widget, the client bounds should also match.
- EXPECT_EQ(kTestBounds.ToString(),
- widget->GetClientAreaBoundsInScreen().ToString());
-
- // Verify origin is stable for a frameless window as well.
- widget->SetSize(kTestSize);
- EXPECT_EQ(kTestBounds.origin().ToString(),
- widget->GetWindowBoundsInScreen().origin().ToString());
-
- widget->CloseNow();
-}
-
-// Before being enabled on Mac, this was #ifdef(false).
-// TODO(tapted): Fix this for DesktopNativeWidgets on other platforms.
-#if defined(OS_MACOSX)
-// Aura needs shell to maximize/fullscreen window.
-// NativeWidgetGtk doesn't implement GetRestoredBounds.
-TEST_F(WidgetTest, GetRestoredBounds) {
- Widget* toplevel = CreateTopLevelPlatformWidget();
- EXPECT_EQ(toplevel->GetWindowBoundsInScreen().ToString(),
- toplevel->GetRestoredBounds().ToString());
- toplevel->Show();
- toplevel->Maximize();
- RunPendingMessages();
-#if defined(OS_MACOSX)
- // Current expectation on Mac is to do nothing on Maximize.
- EXPECT_EQ(toplevel->GetWindowBoundsInScreen().ToString(),
- toplevel->GetRestoredBounds().ToString());
-#else
- EXPECT_NE(toplevel->GetWindowBoundsInScreen().ToString(),
- toplevel->GetRestoredBounds().ToString());
-#endif
- EXPECT_GT(toplevel->GetRestoredBounds().width(), 0);
- EXPECT_GT(toplevel->GetRestoredBounds().height(), 0);
-
- toplevel->Restore();
- RunPendingMessages();
- EXPECT_EQ(toplevel->GetWindowBoundsInScreen().ToString(),
- toplevel->GetRestoredBounds().ToString());
-
- toplevel->SetFullscreen(true);
- RunPendingMessages();
- EXPECT_NE(toplevel->GetWindowBoundsInScreen().ToString(),
- toplevel->GetRestoredBounds().ToString());
- EXPECT_GT(toplevel->GetRestoredBounds().width(), 0);
- EXPECT_GT(toplevel->GetRestoredBounds().height(), 0);
-}
-#endif
-
-// Test that window state is not changed after getting out of full screen.
-TEST_F(WidgetTest, ExitFullscreenRestoreState) {
- Widget* toplevel = CreateTopLevelPlatformWidget();
-
- toplevel->Show();
- RunPendingMessages();
-
- // This should be a normal state window.
- EXPECT_EQ(ui::SHOW_STATE_NORMAL, GetWidgetShowState(toplevel));
-
- toplevel->SetFullscreen(true);
- EXPECT_EQ(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel));
- toplevel->SetFullscreen(false);
- EXPECT_NE(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel));
-
- // And it should still be in normal state after getting out of full screen.
- EXPECT_EQ(ui::SHOW_STATE_NORMAL, GetWidgetShowState(toplevel));
-
-// On Mac, a "maximized" state is indistinguishable from a window that just
-// fills the screen, so nothing to check there.
-#if !defined(OS_MACOSX)
- // Now, make it maximized.
- toplevel->Maximize();
- EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, GetWidgetShowState(toplevel));
-
- toplevel->SetFullscreen(true);
- EXPECT_EQ(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel));
- toplevel->SetFullscreen(false);
- EXPECT_NE(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel));
-
- // And it stays maximized after getting out of full screen.
- EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, GetWidgetShowState(toplevel));
-#endif
-
- // Clean up.
- toplevel->Close();
- RunPendingMessages();
-}
-
-// The key-event propagation from Widget happens differently on aura and
-// non-aura systems because of the difference in IME. So this test works only on
-// aura.
-TEST_F(WidgetTest, KeyboardInputEvent) {
- Widget* toplevel = CreateTopLevelPlatformWidget();
- View* container = toplevel->client_view();
-
- Textfield* textfield = new Textfield();
- textfield->SetText(base::ASCIIToUTF16("some text"));
- container->AddChildView(textfield);
- toplevel->Show();
- textfield->RequestFocus();
-
- // The press gets handled. The release doesn't have an effect.
- ui::KeyEvent backspace_p(ui::ET_KEY_PRESSED, ui::VKEY_DELETE, ui::EF_NONE);
- toplevel->OnKeyEvent(&backspace_p);
- EXPECT_TRUE(backspace_p.stopped_propagation());
- ui::KeyEvent backspace_r(ui::ET_KEY_RELEASED, ui::VKEY_DELETE, ui::EF_NONE);
- toplevel->OnKeyEvent(&backspace_r);
- EXPECT_FALSE(backspace_r.handled());
-
- toplevel->Close();
-}
-
-// Verifies bubbles result in a focus lost when shown.
-// TODO(msw): this tests relies on focus, it needs to be in
-// interactive_ui_tests.
-TEST_F(WidgetTest, DISABLED_FocusChangesOnBubble) {
- // Create a widget, show and activate it and focus the contents view.
- View* contents_view = new View;
- contents_view->SetFocusable(true);
- Widget widget;
- Widget::InitParams init_params =
- CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
- init_params.bounds = gfx::Rect(0, 0, 200, 200);
- init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
-#if !defined(OS_CHROMEOS)
- init_params.native_widget = new PlatformDesktopNativeWidget(&widget);
-#endif
- widget.Init(init_params);
- widget.SetContentsView(contents_view);
- widget.Show();
- widget.Activate();
- contents_view->RequestFocus();
- EXPECT_TRUE(contents_view->HasFocus());
-
- // Show a bubble.
- BubbleDelegateView* bubble_delegate_view =
- new BubbleDelegateView(contents_view, BubbleBorder::TOP_LEFT);
- bubble_delegate_view->SetFocusable(true);
- BubbleDelegateView::CreateBubble(bubble_delegate_view)->Show();
- bubble_delegate_view->RequestFocus();
-
- // |contents_view_| should no longer have focus.
- EXPECT_FALSE(contents_view->HasFocus());
- EXPECT_TRUE(bubble_delegate_view->HasFocus());
-
- bubble_delegate_view->GetWidget()->CloseNow();
-
- // Closing the bubble should result in focus going back to the contents view.
- EXPECT_TRUE(contents_view->HasFocus());
-}
-
-class TestBubbleDelegateView : public BubbleDelegateView {
- public:
- TestBubbleDelegateView(View* anchor)
- : BubbleDelegateView(anchor, BubbleBorder::NONE),
- reset_controls_called_(false) {}
- virtual ~TestBubbleDelegateView() {}
-
- virtual bool ShouldShowCloseButton() const override {
- reset_controls_called_ = true;
- return true;
- }
-
- mutable bool reset_controls_called_;
-};
-
-TEST_F(WidgetTest, BubbleControlsResetOnInit) {
- Widget* anchor = CreateTopLevelPlatformWidget();
- anchor->Show();
-
- TestBubbleDelegateView* bubble_delegate =
- new TestBubbleDelegateView(anchor->client_view());
- Widget* bubble_widget(BubbleDelegateView::CreateBubble(bubble_delegate));
- EXPECT_TRUE(bubble_delegate->reset_controls_called_);
- bubble_widget->Show();
- bubble_widget->CloseNow();
-
- anchor->Hide();
- anchor->CloseNow();
-}
-
-// Desktop native widget Aura tests are for non Chrome OS platforms.
-#if !defined(OS_CHROMEOS)
-// Test to ensure that after minimize, view width is set to zero.
-TEST_F(WidgetTest, TestViewWidthAfterMinimizingWidget) {
- // Create a widget.
- Widget widget;
- Widget::InitParams init_params =
- CreateParams(Widget::InitParams::TYPE_WINDOW);
- init_params.show_state = ui::SHOW_STATE_NORMAL;
- gfx::Rect initial_bounds(0, 0, 300, 400);
- init_params.bounds = initial_bounds;
- init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- init_params.native_widget = new PlatformDesktopNativeWidget(&widget);
- widget.Init(init_params);
- NonClientView* non_client_view = widget.non_client_view();
- NonClientFrameView* frame_view = new MinimumSizeFrameView(&widget);
- non_client_view->SetFrameView(frame_view);
- widget.Show();
- widget.Minimize();
- EXPECT_EQ(0, frame_view->width());
-}
-
-// This class validates whether paints are received for a visible Widget.
-// To achieve this it overrides the Show and Close methods on the Widget class
-// and sets state whether subsequent paints are expected.
-class DesktopAuraTestValidPaintWidget : public views::Widget {
- public:
- DesktopAuraTestValidPaintWidget()
- : received_paint_(false),
- expect_paint_(true),
- received_paint_while_hidden_(false) {}
-
- virtual ~DesktopAuraTestValidPaintWidget() {}
-
- void InitForTest(Widget::InitParams create_params);
-
- virtual void Show() override {
- expect_paint_ = true;
- views::Widget::Show();
- }
-
- virtual void Close() override {
- expect_paint_ = false;
- views::Widget::Close();
- }
-
- void Hide() {
- expect_paint_ = false;
- views::Widget::Hide();
- }
-
- virtual void OnNativeWidgetPaint(gfx::Canvas* canvas) override {
- received_paint_ = true;
- EXPECT_TRUE(expect_paint_);
- if (!expect_paint_)
- received_paint_while_hidden_ = true;
- views::Widget::OnNativeWidgetPaint(canvas);
- }
-
- bool ReadReceivedPaintAndReset() {
- bool result = received_paint_;
- received_paint_ = false;
- return result;
- }
-
- bool received_paint_while_hidden() const {
- return received_paint_while_hidden_;
- }
-
- private:
- bool received_paint_;
- bool expect_paint_;
- bool received_paint_while_hidden_;
-
- DISALLOW_COPY_AND_ASSIGN(DesktopAuraTestValidPaintWidget);
-};
-
-void DesktopAuraTestValidPaintWidget::InitForTest(InitParams init_params) {
- init_params.bounds = gfx::Rect(0, 0, 200, 200);
- init_params.ownership = InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- init_params.native_widget = new PlatformDesktopNativeWidget(this);
- Init(init_params);
-
- View* contents_view = new View;
- contents_view->SetFocusable(true);
- SetContentsView(contents_view);
-
- Show();
- Activate();
-}
-
-TEST_F(WidgetTest, DesktopNativeWidgetNoPaintAfterCloseTest) {
- DesktopAuraTestValidPaintWidget widget;
- widget.InitForTest(CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS));
- RunPendingMessages();
- EXPECT_TRUE(widget.ReadReceivedPaintAndReset());
- widget.SchedulePaintInRect(widget.GetRestoredBounds());
- widget.Close();
- RunPendingMessages();
- EXPECT_FALSE(widget.ReadReceivedPaintAndReset());
- EXPECT_FALSE(widget.received_paint_while_hidden());
-}
-
-TEST_F(WidgetTest, DesktopNativeWidgetNoPaintAfterHideTest) {
- DesktopAuraTestValidPaintWidget widget;
- widget.InitForTest(CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS));
- RunPendingMessages();
- EXPECT_TRUE(widget.ReadReceivedPaintAndReset());
- widget.SchedulePaintInRect(widget.GetRestoredBounds());
- widget.Hide();
- RunPendingMessages();
- EXPECT_FALSE(widget.ReadReceivedPaintAndReset());
- EXPECT_FALSE(widget.received_paint_while_hidden());
- widget.Close();
-}
-
-// Test to ensure that the aura Window's visiblity state is set to visible if
-// the underlying widget is hidden and then shown.
-TEST_F(WidgetTest, TestWindowVisibilityAfterHide) {
- // Create a widget.
- Widget widget;
- Widget::InitParams init_params =
- CreateParams(Widget::InitParams::TYPE_WINDOW);
- init_params.show_state = ui::SHOW_STATE_NORMAL;
- gfx::Rect initial_bounds(0, 0, 300, 400);
- init_params.bounds = initial_bounds;
- init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- init_params.native_widget = new PlatformDesktopNativeWidget(&widget);
- widget.Init(init_params);
- NonClientView* non_client_view = widget.non_client_view();
- NonClientFrameView* frame_view = new MinimumSizeFrameView(&widget);
- non_client_view->SetFrameView(frame_view);
-
- widget.Show();
- EXPECT_TRUE(IsNativeWindowVisible(widget.GetNativeWindow()));
- widget.Hide();
- EXPECT_FALSE(IsNativeWindowVisible(widget.GetNativeWindow()));
- widget.Show();
- EXPECT_TRUE(IsNativeWindowVisible(widget.GetNativeWindow()));
-}
-
-// The following code verifies we can correctly destroy a Widget from a mouse
-// enter/exit. We could test move/drag/enter/exit but in general we don't run
-// nested message loops from such events, nor has the code ever really dealt
-// with this situation.
-
-// Generates two moves (first generates enter, second real move), a press, drag
-// and release stopping at |last_event_type|.
-void GenerateMouseEvents(Widget* widget, ui::EventType last_event_type) {
- const gfx::Rect screen_bounds(widget->GetWindowBoundsInScreen());
- ui::MouseEvent move_event(ui::ET_MOUSE_MOVED, screen_bounds.CenterPoint(),
- screen_bounds.CenterPoint(), 0, 0);
- ui::EventProcessor* dispatcher = WidgetTest::GetEventProcessor(widget);
- ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&move_event);
- if (last_event_type == ui::ET_MOUSE_ENTERED || details.dispatcher_destroyed)
- return;
- details = dispatcher->OnEventFromSource(&move_event);
- if (last_event_type == ui::ET_MOUSE_MOVED || details.dispatcher_destroyed)
- return;
-
- ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, screen_bounds.CenterPoint(),
- screen_bounds.CenterPoint(), 0, 0);
- details = dispatcher->OnEventFromSource(&press_event);
- if (last_event_type == ui::ET_MOUSE_PRESSED || details.dispatcher_destroyed)
- return;
-
- gfx::Point end_point(screen_bounds.CenterPoint());
- end_point.Offset(1, 1);
- ui::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED, end_point, end_point, 0, 0);
- details = dispatcher->OnEventFromSource(&drag_event);
- if (last_event_type == ui::ET_MOUSE_DRAGGED || details.dispatcher_destroyed)
- return;
-
- ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, end_point, end_point, 0,
- 0);
- details = dispatcher->OnEventFromSource(&release_event);
- if (details.dispatcher_destroyed)
- return;
-}
-
-// Creates a widget and invokes GenerateMouseEvents() with |last_event_type|.
-void RunCloseWidgetDuringDispatchTest(WidgetTest* test,
- ui::EventType last_event_type) {
- // |widget| is deleted by CloseWidgetView.
- Widget* widget = new Widget;
- Widget::InitParams params =
- test->CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget = new PlatformDesktopNativeWidget(widget);
- params.bounds = gfx::Rect(0, 0, 50, 100);
- widget->Init(params);
- widget->SetContentsView(new CloseWidgetView(last_event_type));
- widget->Show();
- GenerateMouseEvents(widget, last_event_type);
-}
-
-// Verifies deleting the widget from a mouse pressed event doesn't crash.
-TEST_F(WidgetTest, CloseWidgetDuringMousePress) {
- RunCloseWidgetDuringDispatchTest(this, ui::ET_MOUSE_PRESSED);
-}
-
-// Verifies deleting the widget from a mouse released event doesn't crash.
-TEST_F(WidgetTest, CloseWidgetDuringMouseReleased) {
- RunCloseWidgetDuringDispatchTest(this, ui::ET_MOUSE_RELEASED);
-}
-
-#endif // !defined(OS_CHROMEOS)
-
-// Tests that wheel events generated from scroll events are targetted to the
-// views under the cursor when the focused view does not processed them.
-TEST_F(WidgetTest, WheelEventsFromScrollEventTarget) {
- EventCountView* cursor_view = new EventCountView;
- cursor_view->SetBounds(60, 0, 50, 40);
-
- Widget* widget = CreateTopLevelPlatformWidget();
- widget->GetRootView()->AddChildView(cursor_view);
-
- // Generate a scroll event on the cursor view.
- ui::ScrollEvent scroll(ui::ET_SCROLL,
- gfx::Point(65, 5),
- ui::EventTimeForNow(),
- 0,
- 0, 20,
- 0, 20,
- 2);
- widget->OnScrollEvent(&scroll);
-
- EXPECT_EQ(1, cursor_view->GetEventCount(ui::ET_SCROLL));
- EXPECT_EQ(1, cursor_view->GetEventCount(ui::ET_MOUSEWHEEL));
-
- cursor_view->ResetCounts();
-
- ui::ScrollEvent scroll2(ui::ET_SCROLL,
- gfx::Point(5, 5),
- ui::EventTimeForNow(),
- 0,
- 0, 20,
- 0, 20,
- 2);
- widget->OnScrollEvent(&scroll2);
-
- EXPECT_EQ(0, cursor_view->GetEventCount(ui::ET_SCROLL));
- EXPECT_EQ(0, cursor_view->GetEventCount(ui::ET_MOUSEWHEEL));
-
- widget->CloseNow();
-}
-
-// Tests that if a scroll-begin gesture is not handled, then subsequent scroll
-// events are not dispatched to any view.
-TEST_F(WidgetTest, GestureScrollEventDispatching) {
- EventCountView* noscroll_view = new EventCountView;
- EventCountView* scroll_view = new ScrollableEventCountView;
-
- noscroll_view->SetBounds(0, 0, 50, 40);
- scroll_view->SetBounds(60, 0, 40, 40);
-
- Widget* widget = CreateTopLevelPlatformWidget();
- widget->GetRootView()->AddChildView(noscroll_view);
- widget->GetRootView()->AddChildView(scroll_view);
-
- {
- ui::GestureEvent begin(
- 5,
- 5,
- 0,
- base::TimeDelta(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN));
- widget->OnGestureEvent(&begin);
- ui::GestureEvent update(
- 25,
- 15,
- 0,
- base::TimeDelta(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, 20, 10));
- widget->OnGestureEvent(&update);
- ui::GestureEvent end(25,
- 15,
- 0,
- base::TimeDelta(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END));
- widget->OnGestureEvent(&end);
-
- EXPECT_EQ(1, noscroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN));
- EXPECT_EQ(0, noscroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE));
- EXPECT_EQ(0, noscroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_END));
- }
-
- {
- ui::GestureEvent begin(
- 65,
- 5,
- 0,
- base::TimeDelta(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN));
- widget->OnGestureEvent(&begin);
- ui::GestureEvent update(
- 85,
- 15,
- 0,
- base::TimeDelta(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, 20, 10));
- widget->OnGestureEvent(&update);
- ui::GestureEvent end(85,
- 15,
- 0,
- base::TimeDelta(),
- ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END));
- widget->OnGestureEvent(&end);
-
- EXPECT_EQ(1, scroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN));
- EXPECT_EQ(1, scroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE));
- EXPECT_EQ(1, scroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_END));
- }
-
- widget->CloseNow();
-}
-
-// Tests that event-handlers installed on the RootView get triggered correctly.
-// TODO(tdanderson): Clean up this test as part of crbug.com/355680.
-TEST_F(WidgetTest, EventHandlersOnRootView) {
- Widget* widget = CreateTopLevelNativeWidget();
- View* root_view = widget->GetRootView();
-
- scoped_ptr<EventCountView> view(new EventCountView());
- view->set_owned_by_client();
- view->SetBounds(0, 0, 20, 20);
- root_view->AddChildView(view.get());
-
- EventCountHandler h1;
- root_view->AddPreTargetHandler(&h1);
-
- EventCountHandler h2;
- root_view->AddPostTargetHandler(&h2);
-
- widget->SetBounds(gfx::Rect(0, 0, 100, 100));
- widget->Show();
-
- // Dispatch a ui::ET_SCROLL event. The event remains unhandled and should
- // bubble up the views hierarchy to be re-dispatched on the root view.
- ui::ScrollEvent scroll(ui::ET_SCROLL,
- gfx::Point(5, 5),
- ui::EventTimeForNow(),
- 0,
- 0, 20,
- 0, 20,
- 2);
- widget->OnScrollEvent(&scroll);
- EXPECT_EQ(2, h1.GetEventCount(ui::ET_SCROLL));
- EXPECT_EQ(1, view->GetEventCount(ui::ET_SCROLL));
- EXPECT_EQ(2, h2.GetEventCount(ui::ET_SCROLL));
-
- // Unhandled scroll events are turned into wheel events and re-dispatched.
- EXPECT_EQ(1, h1.GetEventCount(ui::ET_MOUSEWHEEL));
- EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSEWHEEL));
- EXPECT_EQ(1, h2.GetEventCount(ui::ET_MOUSEWHEEL));
-
- h1.ResetCounts();
- view->ResetCounts();
- h2.ResetCounts();
-
- // Dispatch a ui::ET_SCROLL_FLING_START event. The event remains unhandled and
- // should bubble up the views hierarchy to be re-dispatched on the root view.
- ui::ScrollEvent fling(ui::ET_SCROLL_FLING_START,
- gfx::Point(5, 5),
- ui::EventTimeForNow(),
- 0,
- 0, 20,
- 0, 20,
- 2);
- widget->OnScrollEvent(&fling);
- EXPECT_EQ(2, h1.GetEventCount(ui::ET_SCROLL_FLING_START));
- EXPECT_EQ(1, view->GetEventCount(ui::ET_SCROLL_FLING_START));
- EXPECT_EQ(2, h2.GetEventCount(ui::ET_SCROLL_FLING_START));
-
- // Unhandled scroll events which are not of type ui::ET_SCROLL should not
- // be turned into wheel events and re-dispatched.
- EXPECT_EQ(0, h1.GetEventCount(ui::ET_MOUSEWHEEL));
- EXPECT_EQ(0, view->GetEventCount(ui::ET_MOUSEWHEEL));
- EXPECT_EQ(0, h2.GetEventCount(ui::ET_MOUSEWHEEL));
-
- h1.ResetCounts();
- view->ResetCounts();
- h2.ResetCounts();
-
- // Change the handle mode of |view| so that events are marked as handled at
- // the target phase.
- view->set_handle_mode(EventCountView::CONSUME_EVENTS);
-
- // Dispatch a ui::ET_GESTURE_TAP_DOWN and a ui::ET_GESTURE_TAP_CANCEL event.
- // The events are handled at the target phase and should not reach the
- // post-target handler.
- ui::GestureEvent tap_down(5,
- 5,
- 0,
- ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN));
- widget->OnGestureEvent(&tap_down);
- EXPECT_EQ(1, h1.GetEventCount(ui::ET_GESTURE_TAP_DOWN));
- EXPECT_EQ(1, view->GetEventCount(ui::ET_GESTURE_TAP_DOWN));
- EXPECT_EQ(0, h2.GetEventCount(ui::ET_GESTURE_TAP_DOWN));
-
- ui::GestureEvent tap_cancel(
- 5,
- 5,
- 0,
- ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_TAP_CANCEL));
- widget->OnGestureEvent(&tap_cancel);
- EXPECT_EQ(1, h1.GetEventCount(ui::ET_GESTURE_TAP_CANCEL));
- EXPECT_EQ(1, view->GetEventCount(ui::ET_GESTURE_TAP_CANCEL));
- EXPECT_EQ(0, h2.GetEventCount(ui::ET_GESTURE_TAP_CANCEL));
-
- h1.ResetCounts();
- view->ResetCounts();
- h2.ResetCounts();
-
- // Dispatch a ui::ET_SCROLL event. The event is handled at the target phase
- // and should not reach the post-target handler.
- ui::ScrollEvent consumed_scroll(ui::ET_SCROLL,
- gfx::Point(5, 5),
- ui::EventTimeForNow(),
- 0,
- 0, 20,
- 0, 20,
- 2);
- widget->OnScrollEvent(&consumed_scroll);
- EXPECT_EQ(1, h1.GetEventCount(ui::ET_SCROLL));
- EXPECT_EQ(1, view->GetEventCount(ui::ET_SCROLL));
- EXPECT_EQ(0, h2.GetEventCount(ui::ET_SCROLL));
-
- // Handled scroll events are not turned into wheel events and re-dispatched.
- EXPECT_EQ(0, h1.GetEventCount(ui::ET_MOUSEWHEEL));
- EXPECT_EQ(0, view->GetEventCount(ui::ET_MOUSEWHEEL));
- EXPECT_EQ(0, h2.GetEventCount(ui::ET_MOUSEWHEEL));
-
- widget->CloseNow();
-}
-
-TEST_F(WidgetTest, SynthesizeMouseMoveEvent) {
- Widget* widget = CreateTopLevelNativeWidget();
- View* root_view = widget->GetRootView();
-
- EventCountView* v1 = new EventCountView();
- v1->SetBounds(0, 0, 10, 10);
- root_view->AddChildView(v1);
- EventCountView* v2 = new EventCountView();
- v2->SetBounds(0, 10, 10, 10);
- root_view->AddChildView(v2);
-
- gfx::Point cursor_location(5, 5);
- ui::MouseEvent move(ui::ET_MOUSE_MOVED, cursor_location, cursor_location,
- ui::EF_NONE, ui::EF_NONE);
- widget->OnMouseEvent(&move);
-
- EXPECT_EQ(1, v1->GetEventCount(ui::ET_MOUSE_ENTERED));
- EXPECT_EQ(0, v2->GetEventCount(ui::ET_MOUSE_ENTERED));
-
- delete v1;
- v2->SetBounds(0, 0, 10, 10);
- EXPECT_EQ(0, v2->GetEventCount(ui::ET_MOUSE_ENTERED));
-
- widget->SynthesizeMouseMoveEvent();
- EXPECT_EQ(1, v2->GetEventCount(ui::ET_MOUSE_ENTERED));
-}
-
-namespace {
-
-// ui::EventHandler which handles all mouse press events.
-class MousePressEventConsumer : public ui::EventHandler {
- public:
- explicit MousePressEventConsumer() {
- }
-
- virtual ~MousePressEventConsumer() {
- }
-
- private:
- // ui::EventHandler:
- virtual void OnMouseEvent(ui::MouseEvent* event) override {
- if (event->type() == ui::ET_MOUSE_PRESSED)
- event->SetHandled();
- }
-
- DISALLOW_COPY_AND_ASSIGN(MousePressEventConsumer);
-};
-
-} // namespace
-
-// Test that mouse presses and mouse releases are dispatched normally when a
-// touch is down.
-TEST_F(WidgetTest, MouseEventDispatchWhileTouchIsDown) {
- Widget* widget = CreateTopLevelNativeWidget();
- widget->Show();
- widget->SetSize(gfx::Size(300, 300));
-
- EventCountView* event_count_view = new EventCountView();
- event_count_view->SetBounds(0, 0, 300, 300);
- widget->GetRootView()->AddChildView(event_count_view);
-
- MousePressEventConsumer consumer;
- event_count_view->AddPostTargetHandler(&consumer);
-
- ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
- generator.PressTouch();
- generator.ClickLeftButton();
-
- EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSE_PRESSED));
- EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSE_RELEASED));
-
- widget->CloseNow();
-}
-
-// Used by SingleWindowClosing to count number of times WindowClosing() has
-// been invoked.
-class ClosingDelegate : public WidgetDelegate {
- public:
- ClosingDelegate() : count_(0), widget_(NULL) {}
-
- int count() const { return count_; }
-
- void set_widget(views::Widget* widget) { widget_ = widget; }
-
- // WidgetDelegate overrides:
- virtual Widget* GetWidget() override { return widget_; }
- virtual const Widget* GetWidget() const override { return widget_; }
- virtual void WindowClosing() override {
- count_++;
- }
-
- private:
- int count_;
- views::Widget* widget_;
-
- DISALLOW_COPY_AND_ASSIGN(ClosingDelegate);
-};
-
-// Verifies WindowClosing() is invoked correctly on the delegate when a Widget
-// is closed.
-TEST_F(WidgetTest, SingleWindowClosing) {
- scoped_ptr<ClosingDelegate> delegate(new ClosingDelegate());
- Widget* widget = new Widget(); // Destroyed by CloseNow() below.
- Widget::InitParams init_params =
- CreateParams(Widget::InitParams::TYPE_WINDOW);
- init_params.bounds = gfx::Rect(0, 0, 200, 200);
- init_params.delegate = delegate.get();
-#if !defined(OS_CHROMEOS)
- init_params.native_widget = new PlatformDesktopNativeWidget(widget);
-#endif
- widget->Init(init_params);
- EXPECT_EQ(0, delegate->count());
- widget->CloseNow();
- EXPECT_EQ(1, delegate->count());
-}
-
-class WidgetWindowTitleTest : public WidgetTest {
- protected:
- void RunTest(bool desktop_native_widget) {
- Widget* widget = new Widget(); // Destroyed by CloseNow() below.
- Widget::InitParams init_params =
- CreateParams(Widget::InitParams::TYPE_WINDOW);
- widget->Init(init_params);
-
-#if !defined(OS_CHROMEOS)
- if (desktop_native_widget)
- init_params.native_widget = new PlatformDesktopNativeWidget(widget);
-#else
- DCHECK(!desktop_native_widget)
- << "DesktopNativeWidget does not exist on non-Aura or on ChromeOS.";
-#endif
-
- internal::NativeWidgetPrivate* native_widget =
- widget->native_widget_private();
-
- base::string16 empty;
- base::string16 s1(base::UTF8ToUTF16("Title1"));
- base::string16 s2(base::UTF8ToUTF16("Title2"));
- base::string16 s3(base::UTF8ToUTF16("TitleLong"));
-
- // The widget starts with no title, setting empty should not change
- // anything.
- EXPECT_FALSE(native_widget->SetWindowTitle(empty));
- // Setting the title to something non-empty should cause a change.
- EXPECT_TRUE(native_widget->SetWindowTitle(s1));
- // Setting the title to something else with the same length should cause a
- // change.
- EXPECT_TRUE(native_widget->SetWindowTitle(s2));
- // Setting the title to something else with a different length should cause
- // a change.
- EXPECT_TRUE(native_widget->SetWindowTitle(s3));
- // Setting the title to the same thing twice should not cause a change.
- EXPECT_FALSE(native_widget->SetWindowTitle(s3));
-
- widget->CloseNow();
- }
-};
-
-TEST_F(WidgetWindowTitleTest, SetWindowTitleChanged_NativeWidget) {
- // Use the default NativeWidget.
- bool desktop_native_widget = false;
- RunTest(desktop_native_widget);
-}
-
-// DesktopNativeWidget does not exist on non-Aura or on ChromeOS.
-#if !defined(OS_CHROMEOS)
-TEST_F(WidgetWindowTitleTest, SetWindowTitleChanged_DesktopNativeWidget) {
- // Override to use a DesktopNativeWidget.
- bool desktop_native_widget = true;
- RunTest(desktop_native_widget);
-}
-#endif // !OS_CHROMEOS
-
-TEST_F(WidgetTest, WidgetDeleted_InOnMousePressed) {
- Widget* widget = new Widget;
- Widget::InitParams params =
- CreateParams(views::Widget::InitParams::TYPE_POPUP);
- widget->Init(params);
-
- widget->SetContentsView(new CloseWidgetView(ui::ET_MOUSE_PRESSED));
-
- widget->SetSize(gfx::Size(100, 100));
- widget->Show();
-
- ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
-
- WidgetDeletionObserver deletion_observer(widget);
- generator.ClickLeftButton();
- EXPECT_FALSE(deletion_observer.IsWidgetAlive());
-
- // Yay we did not crash!
-}
-
-TEST_F(WidgetTest, WidgetDeleted_InDispatchGestureEvent) {
- Widget* widget = new Widget;
- Widget::InitParams params =
- CreateParams(views::Widget::InitParams::TYPE_POPUP);
- widget->Init(params);
-
- widget->SetContentsView(new CloseWidgetView(ui::ET_GESTURE_TAP_DOWN));
-
- widget->SetSize(gfx::Size(100, 100));
- widget->Show();
-
- ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
-
- WidgetDeletionObserver deletion_observer(widget);
- generator.GestureTapAt(widget->GetWindowBoundsInScreen().CenterPoint());
- EXPECT_FALSE(deletion_observer.IsWidgetAlive());
-
- // Yay we did not crash!
-}
-
-// See description of RunGetNativeThemeFromDestructor() for details.
-class GetNativeThemeFromDestructorView : public WidgetDelegateView {
- public:
- GetNativeThemeFromDestructorView() {}
- virtual ~GetNativeThemeFromDestructorView() {
- VerifyNativeTheme();
- }
-
- virtual View* GetContentsView() override {
- return this;
- }
-
- private:
- void VerifyNativeTheme() {
- ASSERT_TRUE(GetNativeTheme() != NULL);
- }
-
- DISALLOW_COPY_AND_ASSIGN(GetNativeThemeFromDestructorView);
-};
-
-// Verifies GetNativeTheme() from the destructor of a WidgetDelegateView doesn't
-// crash. |is_first_run| is true if this is the first call. A return value of
-// true indicates this should be run again with a value of false.
-// First run uses DesktopNativeWidgetAura (if possible). Second run doesn't.
-bool RunGetNativeThemeFromDestructor(const Widget::InitParams& in_params,
- bool is_first_run) {
- bool needs_second_run = false;
- // Destroyed by CloseNow() below.
- Widget* widget = new Widget;
- Widget::InitParams params(in_params);
- // Deletes itself when the Widget is destroyed.
- params.delegate = new GetNativeThemeFromDestructorView;
-#if !defined(OS_CHROMEOS)
- if (is_first_run) {
- params.native_widget = new PlatformDesktopNativeWidget(widget);
- needs_second_run = true;
- }
-#endif
- widget->Init(params);
- widget->CloseNow();
- return needs_second_run;
-}
-
-// See description of RunGetNativeThemeFromDestructor() for details.
-TEST_F(WidgetTest, GetNativeThemeFromDestructor) {
- Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- if (RunGetNativeThemeFromDestructor(params, true))
- RunGetNativeThemeFromDestructor(params, false);
-}
-
-// Used by HideCloseDestroy. Allows setting a boolean when the widget is
-// destroyed.
-class CloseDestroysWidget : public Widget {
- public:
- explicit CloseDestroysWidget(bool* destroyed)
- : destroyed_(destroyed) {
- }
-
- virtual ~CloseDestroysWidget() {
- if (destroyed_) {
- *destroyed_ = true;
- base::MessageLoop::current()->QuitNow();
- }
- }
-
- void Detach() { destroyed_ = NULL; }
-
- private:
- // If non-null set to true from destructor.
- bool* destroyed_;
-
- DISALLOW_COPY_AND_ASSIGN(CloseDestroysWidget);
-};
-
-// An observer that registers that an animation has ended.
-class AnimationEndObserver : public ui::ImplicitAnimationObserver {
- public:
- AnimationEndObserver() : animation_completed_(false) {}
- virtual ~AnimationEndObserver() {}
-
- bool animation_completed() const { return animation_completed_; }
-
- // ui::ImplicitAnimationObserver:
- virtual void OnImplicitAnimationsCompleted() override {
- animation_completed_ = true;
- }
-
- private:
- bool animation_completed_;
-
- DISALLOW_COPY_AND_ASSIGN(AnimationEndObserver);
-};
-
-// An observer that registers the bounds of a widget on destruction.
-class WidgetBoundsObserver : public WidgetObserver {
- public:
- WidgetBoundsObserver() {}
- virtual ~WidgetBoundsObserver() {}
-
- gfx::Rect bounds() { return bounds_; }
-
- // WidgetObserver:
- virtual void OnWidgetDestroying(Widget* widget) override {
- bounds_ = widget->GetWindowBoundsInScreen();
- }
-
- private:
- gfx::Rect bounds_;
-
- DISALLOW_COPY_AND_ASSIGN(WidgetBoundsObserver);
-};
-
-// Verifies Close() results in destroying.
-TEST_F(WidgetTest, CloseDestroys) {
- bool destroyed = false;
- CloseDestroysWidget* widget = new CloseDestroysWidget(&destroyed);
- Widget::InitParams params =
- CreateParams(views::Widget::InitParams::TYPE_MENU);
- params.opacity = Widget::InitParams::OPAQUE_WINDOW;
-#if !defined(OS_CHROMEOS)
- params.native_widget = new PlatformDesktopNativeWidget(widget);
-#endif
- widget->Init(params);
- widget->Show();
- widget->Hide();
- widget->Close();
- EXPECT_FALSE(destroyed);
- // Run the message loop as Close() asynchronously deletes.
- base::RunLoop().Run();
- EXPECT_TRUE(destroyed);
- // Close() should destroy the widget. If not we'll cleanup to avoid leaks.
- if (!destroyed) {
- widget->Detach();
- widget->CloseNow();
- }
-}
-
-// Tests that killing a widget while animating it does not crash.
-TEST_F(WidgetTest, CloseWidgetWhileAnimating) {
- scoped_ptr<Widget> widget(new Widget);
- Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params.bounds = gfx::Rect(50, 50, 250, 250);
- widget->Init(params);
- AnimationEndObserver animation_observer;
- WidgetBoundsObserver widget_observer;
- gfx::Rect bounds(0, 0, 50, 50);
- {
- // Normal animations for tests have ZERO_DURATION, make sure we are actually
- // animating the movement.
- ui::ScopedAnimationDurationScaleMode animation_scale_mode(
- ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
- ui::ScopedLayerAnimationSettings animation_settings(
- widget->GetLayer()->GetAnimator());
- animation_settings.AddObserver(&animation_observer);
- widget->AddObserver(&widget_observer);
- widget->Show();
-
- // Animate the bounds change.
- widget->SetBounds(bounds);
- widget.reset();
- EXPECT_FALSE(animation_observer.animation_completed());
- }
- EXPECT_TRUE(animation_observer.animation_completed());
- EXPECT_EQ(widget_observer.bounds(), bounds);
-}
-
-// A view that consumes mouse-pressed event and gesture-tap-down events.
-class RootViewTestView : public View {
- public:
- RootViewTestView(): View() {}
-
- private:
- virtual bool OnMousePressed(const ui::MouseEvent& event) override {
- return true;
- }
-
- virtual void OnGestureEvent(ui::GestureEvent* event) override {
- if (event->type() == ui::ET_GESTURE_TAP_DOWN)
- event->SetHandled();
- }
-};
-
-// Checks if RootView::*_handler_ fields are unset when widget is hidden.
-// Fails on chromium.webkit Windows bot, see crbug.com/264872.
-#if defined(OS_WIN)
-#define MAYBE_DisableTestRootViewHandlersWhenHidden\
- DISABLED_TestRootViewHandlersWhenHidden
-#else
-#define MAYBE_DisableTestRootViewHandlersWhenHidden\
- TestRootViewHandlersWhenHidden
-#endif
-TEST_F(WidgetTest, MAYBE_DisableTestRootViewHandlersWhenHidden) {
- Widget* widget = CreateTopLevelNativeWidget();
- widget->SetBounds(gfx::Rect(0, 0, 300, 300));
- View* view = new RootViewTestView();
- view->SetBounds(0, 0, 300, 300);
- internal::RootView* root_view =
- static_cast<internal::RootView*>(widget->GetRootView());
- root_view->AddChildView(view);
-
- // Check RootView::mouse_pressed_handler_.
- widget->Show();
- EXPECT_EQ(NULL, GetMousePressedHandler(root_view));
- gfx::Point click_location(45, 15);
- ui::MouseEvent press(ui::ET_MOUSE_PRESSED, click_location, click_location,
- ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
- widget->OnMouseEvent(&press);
- EXPECT_EQ(view, GetMousePressedHandler(root_view));
- widget->Hide();
- EXPECT_EQ(NULL, GetMousePressedHandler(root_view));
-
- // Check RootView::mouse_move_handler_.
- widget->Show();
- EXPECT_EQ(NULL, GetMouseMoveHandler(root_view));
- gfx::Point move_location(45, 15);
- ui::MouseEvent move(ui::ET_MOUSE_MOVED, move_location, move_location, 0, 0);
- widget->OnMouseEvent(&move);
- EXPECT_EQ(view, GetMouseMoveHandler(root_view));
- widget->Hide();
- EXPECT_EQ(NULL, GetMouseMoveHandler(root_view));
-
- // Check RootView::gesture_handler_.
- widget->Show();
- EXPECT_EQ(NULL, GetGestureHandler(root_view));
- ui::GestureEvent tap_down(15,
- 15,
- 0,
- base::TimeDelta(),
- ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN));
- widget->OnGestureEvent(&tap_down);
- EXPECT_EQ(view, GetGestureHandler(root_view));
- widget->Hide();
- EXPECT_EQ(NULL, GetGestureHandler(root_view));
-
- widget->Close();
-}
-
-// Convenience to make constructing a GestureEvent simpler.
-class GestureEventForTest : public ui::GestureEvent {
- public:
- GestureEventForTest(ui::EventType type, int x, int y)
- : GestureEvent(x,
- y,
- 0,
- base::TimeDelta(),
- ui::GestureEventDetails(type)) {}
-
- GestureEventForTest(ui::GestureEventDetails details, int x, int y)
- : GestureEvent(x, y, 0, base::TimeDelta(), details) {}
-};
-
-// Tests that the |gesture_handler_| member in RootView is always NULL
-// after the dispatch of a ui::ET_GESTURE_END event corresponding to
-// the release of the final touch point on the screen, but that
-// ui::ET_GESTURE_END events corresponding to the removal of any other touch
-// point do not modify |gesture_handler_|.
-TEST_F(WidgetTest, GestureEndEvents) {
- Widget* widget = CreateTopLevelNativeWidget();
- widget->SetBounds(gfx::Rect(0, 0, 300, 300));
- EventCountView* view = new EventCountView();
- view->SetBounds(0, 0, 300, 300);
- internal::RootView* root_view =
- static_cast<internal::RootView*>(widget->GetRootView());
- root_view->AddChildView(view);
- widget->Show();
-
- // If no gesture handler is set, a ui::ET_GESTURE_END event should not set
- // the gesture handler.
- EXPECT_EQ(NULL, GetGestureHandler(root_view));
- GestureEventForTest end(ui::ET_GESTURE_END, 15, 15);
- widget->OnGestureEvent(&end);
- EXPECT_EQ(NULL, GetGestureHandler(root_view));
-
- // Change the handle mode of |view| to indicate that it would like
- // to handle all events, then send a GESTURE_TAP to set the gesture handler.
- view->set_handle_mode(EventCountView::CONSUME_EVENTS);
- GestureEventForTest tap(ui::ET_GESTURE_TAP, 15, 15);
- widget->OnGestureEvent(&tap);
- EXPECT_TRUE(tap.handled());
- EXPECT_EQ(view, GetGestureHandler(root_view));
-
- // The gesture handler should remain unchanged on a ui::ET_GESTURE_END
- // corresponding to a second touch point, but should be reset to NULL by a
- // ui::ET_GESTURE_END corresponding to the final touch point.
- ui::GestureEventDetails details(ui::ET_GESTURE_END);
- details.set_touch_points(2);
- GestureEventForTest end_second_touch_point(details, 15, 15);
- widget->OnGestureEvent(&end_second_touch_point);
- EXPECT_EQ(view, GetGestureHandler(root_view));
-
- end = GestureEventForTest(ui::ET_GESTURE_END, 15, 15);
- widget->OnGestureEvent(&end);
- EXPECT_TRUE(end.handled());
- EXPECT_EQ(NULL, GetGestureHandler(root_view));
-
- // Send a GESTURE_TAP to set the gesture handler, then change the handle
- // mode of |view| to indicate that it does not want to handle any
- // further events.
- tap = GestureEventForTest(ui::ET_GESTURE_TAP, 15, 15);
- widget->OnGestureEvent(&tap);
- EXPECT_TRUE(tap.handled());
- EXPECT_EQ(view, GetGestureHandler(root_view));
- view->set_handle_mode(EventCountView::PROPAGATE_EVENTS);
-
- // The gesture handler should remain unchanged on a ui::ET_GESTURE_END
- // corresponding to a second touch point, but should be reset to NULL by a
- // ui::ET_GESTURE_END corresponding to the final touch point.
- end_second_touch_point = GestureEventForTest(details, 15, 15);
- widget->OnGestureEvent(&end_second_touch_point);
- EXPECT_EQ(view, GetGestureHandler(root_view));
-
- end = GestureEventForTest(ui::ET_GESTURE_END, 15, 15);
- widget->OnGestureEvent(&end);
- EXPECT_FALSE(end.handled());
- EXPECT_EQ(NULL, GetGestureHandler(root_view));
-
- widget->Close();
-}
-
-// Tests that gesture events which should not be processed (because
-// RootView::OnEventProcessingStarted() has marked them as handled) are not
-// dispatched to any views.
-TEST_F(WidgetTest, GestureEventsNotProcessed) {
- Widget* widget = CreateTopLevelNativeWidget();
- widget->SetBounds(gfx::Rect(0, 0, 300, 300));
-
- // Define a hierarchy of four views (coordinates are in
- // their parent coordinate space).
- // v1 (0, 0, 300, 300)
- // v2 (0, 0, 100, 100)
- // v3 (0, 0, 50, 50)
- // v4(0, 0, 10, 10)
- EventCountView* v1 = new EventCountView();
- v1->SetBounds(0, 0, 300, 300);
- EventCountView* v2 = new EventCountView();
- v2->SetBounds(0, 0, 100, 100);
- EventCountView* v3 = new EventCountView();
- v3->SetBounds(0, 0, 50, 50);
- EventCountView* v4 = new EventCountView();
- v4->SetBounds(0, 0, 10, 10);
- internal::RootView* root_view =
- static_cast<internal::RootView*>(widget->GetRootView());
- root_view->AddChildView(v1);
- v1->AddChildView(v2);
- v2->AddChildView(v3);
- v3->AddChildView(v4);
-
- widget->Show();
-
- // ui::ET_GESTURE_BEGIN events should never be seen by any view, but
- // they should be marked as handled by OnEventProcessingStarted().
- GestureEventForTest begin(ui::ET_GESTURE_BEGIN, 5, 5);
- widget->OnGestureEvent(&begin);
- EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_BEGIN));
- EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_BEGIN));
- EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_BEGIN));
- EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_BEGIN));
- EXPECT_EQ(NULL, GetGestureHandler(root_view));
- EXPECT_TRUE(begin.handled());
- v1->ResetCounts();
- v2->ResetCounts();
- v3->ResetCounts();
- v4->ResetCounts();
-
- // ui::ET_GESTURE_END events should not be seen by any view when there is
- // no default gesture handler set, but they should be marked as handled by
- // OnEventProcessingStarted().
- GestureEventForTest end(ui::ET_GESTURE_END, 5, 5);
- widget->OnGestureEvent(&end);
- EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_END));
- EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_END));
- EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_END));
- EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_END));
- EXPECT_EQ(NULL, GetGestureHandler(root_view));
- EXPECT_TRUE(end.handled());
- v1->ResetCounts();
- v2->ResetCounts();
- v3->ResetCounts();
- v4->ResetCounts();
-
- // ui::ET_GESTURE_END events not corresponding to the release of the
- // final touch point should never be seen by any view, but they should
- // be marked as handled by OnEventProcessingStarted().
- ui::GestureEventDetails details(ui::ET_GESTURE_END);
- details.set_touch_points(2);
- GestureEventForTest end_second_touch_point(details, 5, 5);
- widget->OnGestureEvent(&end_second_touch_point);
- EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_END));
- EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_END));
- EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_END));
- EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_END));
- EXPECT_EQ(NULL, GetGestureHandler(root_view));
- EXPECT_TRUE(end_second_touch_point.handled());
- v1->ResetCounts();
- v2->ResetCounts();
- v3->ResetCounts();
- v4->ResetCounts();
-
- // ui::ET_GESTURE_SCROLL_UPDATE events should never be seen by any view when
- // there is no default gesture handler set, but they should be marked as
- // handled by OnEventProcessingStarted().
- GestureEventForTest scroll_update(ui::ET_GESTURE_SCROLL_UPDATE, 5, 5);
- widget->OnGestureEvent(&scroll_update);
- EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE));
- EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE));
- EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE));
- EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE));
- EXPECT_EQ(NULL, GetGestureHandler(root_view));
- EXPECT_TRUE(scroll_update.handled());
- v1->ResetCounts();
- v2->ResetCounts();
- v3->ResetCounts();
- v4->ResetCounts();
-
- // ui::ET_GESTURE_SCROLL_END events should never be seen by any view when
- // there is no default gesture handler set, but they should be marked as
- // handled by OnEventProcessingStarted().
- GestureEventForTest scroll_end(ui::ET_GESTURE_SCROLL_END, 5, 5);
- widget->OnGestureEvent(&scroll_end);
- EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_SCROLL_END));
- EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_SCROLL_END));
- EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_SCROLL_END));
- EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_SCROLL_END));
- EXPECT_EQ(NULL, GetGestureHandler(root_view));
- EXPECT_TRUE(scroll_end.handled());
- v1->ResetCounts();
- v2->ResetCounts();
- v3->ResetCounts();
- v4->ResetCounts();
-
- // ui::ET_SCROLL_FLING_START events should never be seen by any view when
- // there is no default gesture handler set, but they should be marked as
- // handled by OnEventProcessingStarted().
- GestureEventForTest scroll_fling_start(ui::ET_SCROLL_FLING_START, 5, 5);
- widget->OnGestureEvent(&scroll_fling_start);
- EXPECT_EQ(0, v1->GetEventCount(ui::ET_SCROLL_FLING_START));
- EXPECT_EQ(0, v2->GetEventCount(ui::ET_SCROLL_FLING_START));
- EXPECT_EQ(0, v3->GetEventCount(ui::ET_SCROLL_FLING_START));
- EXPECT_EQ(0, v4->GetEventCount(ui::ET_SCROLL_FLING_START));
- EXPECT_EQ(NULL, GetGestureHandler(root_view));
- EXPECT_TRUE(scroll_fling_start.handled());
- v1->ResetCounts();
- v2->ResetCounts();
- v3->ResetCounts();
- v4->ResetCounts();
-
- widget->Close();
-}
-
-// Tests that a (non-scroll) gesture event is dispatched to the correct views
-// in a view hierarchy and that the default gesture handler in RootView is set
-// correctly.
-TEST_F(WidgetTest, GestureEventDispatch) {
- Widget* widget = CreateTopLevelNativeWidget();
- widget->SetBounds(gfx::Rect(0, 0, 300, 300));
-
- // Define a hierarchy of four views (coordinates are in
- // their parent coordinate space).
- // v1 (0, 0, 300, 300)
- // v2 (0, 0, 100, 100)
- // v3 (0, 0, 50, 50)
- // v4(0, 0, 10, 10)
- EventCountView* v1 = new EventCountView();
- v1->SetBounds(0, 0, 300, 300);
- EventCountView* v2 = new EventCountView();
- v2->SetBounds(0, 0, 100, 100);
- EventCountView* v3 = new EventCountView();
- v3->SetBounds(0, 0, 50, 50);
- EventCountView* v4 = new EventCountView();
- v4->SetBounds(0, 0, 10, 10);
- internal::RootView* root_view =
- static_cast<internal::RootView*>(widget->GetRootView());
- root_view->AddChildView(v1);
- v1->AddChildView(v2);
- v2->AddChildView(v3);
- v3->AddChildView(v4);
-
- widget->Show();
-
- // No gesture handler is set in the root view and none of the views in the
- // view hierarchy handle a ui::ET_GESTURE_TAP event. In this case the tap
- // event should be dispatched to all views in the hierarchy, the gesture
- // handler should remain unset, and the event should remain unhandled.
- GestureEventForTest tap(ui::ET_GESTURE_TAP, 5, 5);
- EXPECT_EQ(NULL, GetGestureHandler(root_view));
- widget->OnGestureEvent(&tap);
- EXPECT_EQ(1, v1->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(1, v2->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(1, v3->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(1, v4->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(NULL, GetGestureHandler(root_view));
- EXPECT_FALSE(tap.handled());
-
- // No gesture handler is set in the root view and |v1|, |v2|, and |v3| all
- // handle a ui::ET_GESTURE_TAP event. In this case the tap event should be
- // dispatched to |v4| and |v3|, the gesture handler should be set to |v3|,
- // and the event should be marked as handled.
- v1->ResetCounts();
- v2->ResetCounts();
- v3->ResetCounts();
- v4->ResetCounts();
- v1->set_handle_mode(EventCountView::CONSUME_EVENTS);
- v2->set_handle_mode(EventCountView::CONSUME_EVENTS);
- v3->set_handle_mode(EventCountView::CONSUME_EVENTS);
- tap = GestureEventForTest(ui::ET_GESTURE_TAP, 5, 5);
- widget->OnGestureEvent(&tap);
- EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(1, v3->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(1, v4->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(v3, GetGestureHandler(root_view));
- EXPECT_TRUE(tap.handled());
-
- // The gesture handler is set to |v3| and all views handle all gesture event
- // types. In this case subsequent gesture events should only be dispatched to
- // |v3| and marked as handled. The gesture handler should remain as |v3|.
- v1->ResetCounts();
- v2->ResetCounts();
- v3->ResetCounts();
- v4->ResetCounts();
- v4->set_handle_mode(EventCountView::CONSUME_EVENTS);
- tap = GestureEventForTest(ui::ET_GESTURE_TAP, 5, 5);
- widget->OnGestureEvent(&tap);
- EXPECT_TRUE(tap.handled());
- GestureEventForTest show_press(ui::ET_GESTURE_SHOW_PRESS, 5, 5);
- widget->OnGestureEvent(&show_press);
- tap = GestureEventForTest(ui::ET_GESTURE_TAP, 5, 5);
- widget->OnGestureEvent(&tap);
- EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(2, v3->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_SHOW_PRESS));
- EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_SHOW_PRESS));
- EXPECT_EQ(1, v3->GetEventCount(ui::ET_GESTURE_SHOW_PRESS));
- EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_SHOW_PRESS));
- EXPECT_TRUE(tap.handled());
- EXPECT_TRUE(show_press.handled());
- EXPECT_EQ(v3, GetGestureHandler(root_view));
-
- // The gesture handler is set to |v3|, but |v3| does not handle
- // ui::ET_GESTURE_TAP events. In this case a tap gesture should be dispatched
- // only to |v3|, but the event should remain unhandled. The gesture handler
- // should remain as |v3|.
- v1->ResetCounts();
- v2->ResetCounts();
- v3->ResetCounts();
- v4->ResetCounts();
- v3->set_handle_mode(EventCountView::PROPAGATE_EVENTS);
- tap = GestureEventForTest(ui::ET_GESTURE_TAP, 5, 5);
- widget->OnGestureEvent(&tap);
- EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(1, v3->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_FALSE(tap.handled());
- EXPECT_EQ(v3, GetGestureHandler(root_view));
-
- widget->Close();
-}
-
-// Tests that gesture scroll events will change the default gesture handler in
-// RootView if the current handler to which they are dispatched does not handle
-// gesture scroll events.
-TEST_F(WidgetTest, ScrollGestureEventDispatch) {
- Widget* widget = CreateTopLevelNativeWidget();
- widget->SetBounds(gfx::Rect(0, 0, 300, 300));
-
- // Define a hierarchy of four views (coordinates are in
- // their parent coordinate space).
- // v1 (0, 0, 300, 300)
- // v2 (0, 0, 100, 100)
- // v3 (0, 0, 50, 50)
- // v4(0, 0, 10, 10)
- EventCountView* v1 = new EventCountView();
- v1->SetBounds(0, 0, 300, 300);
- EventCountView* v2 = new EventCountView();
- v2->SetBounds(0, 0, 100, 100);
- EventCountView* v3 = new EventCountView();
- v3->SetBounds(0, 0, 50, 50);
- EventCountView* v4 = new EventCountView();
- v4->SetBounds(0, 0, 10, 10);
- internal::RootView* root_view =
- static_cast<internal::RootView*>(widget->GetRootView());
- root_view->AddChildView(v1);
- v1->AddChildView(v2);
- v2->AddChildView(v3);
- v3->AddChildView(v4);
-
- widget->Show();
-
- // Change the handle mode of |v3| to indicate that it would like to handle
- // gesture events.
- v3->set_handle_mode(EventCountView::CONSUME_EVENTS);
-
- // When no gesture handler is set, dispatching a ui::ET_GESTURE_TAP_DOWN
- // should bubble up the views hierarchy until it reaches the first view
- // that will handle it (|v3|) and then sets the handler to |v3|.
- EXPECT_EQ(NULL, GetGestureHandler(root_view));
- GestureEventForTest tap_down(ui::ET_GESTURE_TAP_DOWN, 5, 5);
- widget->OnGestureEvent(&tap_down);
- EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_TAP_DOWN));
- EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_TAP_DOWN));
- EXPECT_EQ(1, v3->GetEventCount(ui::ET_GESTURE_TAP_DOWN));
- EXPECT_EQ(1, v4->GetEventCount(ui::ET_GESTURE_TAP_DOWN));
- EXPECT_EQ(v3, GetGestureHandler(root_view));
- EXPECT_TRUE(tap_down.handled());
- v1->ResetCounts();
- v2->ResetCounts();
- v3->ResetCounts();
- v4->ResetCounts();
-
- // A ui::ET_GESTURE_TAP_CANCEL event should be dispatched to |v3| directly.
- GestureEventForTest tap_cancel(ui::ET_GESTURE_TAP_CANCEL, 5, 5);
- widget->OnGestureEvent(&tap_cancel);
- EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_TAP_CANCEL));
- EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_TAP_CANCEL));
- EXPECT_EQ(1, v3->GetEventCount(ui::ET_GESTURE_TAP_CANCEL));
- EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_TAP_CANCEL));
- EXPECT_EQ(v3, GetGestureHandler(root_view));
- EXPECT_TRUE(tap_cancel.handled());
- v1->ResetCounts();
- v2->ResetCounts();
- v3->ResetCounts();
- v4->ResetCounts();
-
- // Change the handle mode of |v3| to indicate that it would no longer like
- // to handle events, and change the mode of |v1| to indicate that it would
- // like to handle events.
- v3->set_handle_mode(EventCountView::PROPAGATE_EVENTS);
- v1->set_handle_mode(EventCountView::CONSUME_EVENTS);
-
- // Dispatch a ui::ET_GESTURE_SCROLL_BEGIN event. Because the current gesture
- // handler (|v3|) does not handle scroll events, the event should bubble up
- // the views hierarchy until it reaches the first view that will handle
- // it (|v1|) and then sets the handler to |v1|.
- GestureEventForTest scroll_begin(ui::ET_GESTURE_SCROLL_BEGIN, 5, 5);
- widget->OnGestureEvent(&scroll_begin);
- EXPECT_EQ(1, v1->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN));
- EXPECT_EQ(1, v2->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN));
- EXPECT_EQ(1, v3->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN));
- EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN));
- EXPECT_EQ(v1, GetGestureHandler(root_view));
- EXPECT_TRUE(scroll_begin.handled());
- v1->ResetCounts();
- v2->ResetCounts();
- v3->ResetCounts();
- v4->ResetCounts();
-
- // A ui::ET_GESTURE_SCROLL_UPDATE event should be dispatched to |v1|
- // directly.
- GestureEventForTest scroll_update(ui::ET_GESTURE_SCROLL_UPDATE, 5, 5);
- widget->OnGestureEvent(&scroll_update);
- EXPECT_EQ(1, v1->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE));
- EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE));
- EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE));
- EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE));
- EXPECT_EQ(v1, GetGestureHandler(root_view));
- EXPECT_TRUE(scroll_update.handled());
- v1->ResetCounts();
- v2->ResetCounts();
- v3->ResetCounts();
- v4->ResetCounts();
-
- // A ui::ET_GESTURE_SCROLL_END event should be dispatched to |v1|
- // directly and should not reset the gesture handler.
- GestureEventForTest scroll_end(ui::ET_GESTURE_SCROLL_END, 5, 5);
- widget->OnGestureEvent(&scroll_end);
- EXPECT_EQ(1, v1->GetEventCount(ui::ET_GESTURE_SCROLL_END));
- EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_SCROLL_END));
- EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_SCROLL_END));
- EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_SCROLL_END));
- EXPECT_EQ(v1, GetGestureHandler(root_view));
- EXPECT_TRUE(scroll_end.handled());
- v1->ResetCounts();
- v2->ResetCounts();
- v3->ResetCounts();
- v4->ResetCounts();
-
- // A ui::ET_GESTURE_PINCH_BEGIN event (which is a non-scroll event) should
- // still be dispatched to |v1| directly.
- GestureEventForTest pinch_begin(ui::ET_GESTURE_PINCH_BEGIN, 5, 5);
- widget->OnGestureEvent(&pinch_begin);
- EXPECT_EQ(1, v1->GetEventCount(ui::ET_GESTURE_PINCH_BEGIN));
- EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_PINCH_BEGIN));
- EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_PINCH_BEGIN));
- EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_PINCH_BEGIN));
- EXPECT_EQ(v1, GetGestureHandler(root_view));
- EXPECT_TRUE(pinch_begin.handled());
- v1->ResetCounts();
- v2->ResetCounts();
- v3->ResetCounts();
- v4->ResetCounts();
-
- // A ui::ET_GESTURE_END event should be dispatched to |v1| and should
- // set the gesture handler to NULL.
- GestureEventForTest end(ui::ET_GESTURE_END, 5, 5);
- widget->OnGestureEvent(&end);
- EXPECT_EQ(1, v1->GetEventCount(ui::ET_GESTURE_END));
- EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_END));
- EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_END));
- EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_END));
- EXPECT_EQ(NULL, GetGestureHandler(root_view));
- EXPECT_TRUE(end.handled());
-
- widget->Close();
-}
-
-// A class used in WidgetTest.GestureEventLocationWhileBubbling to verify
-// that when a gesture event bubbles up a View hierarchy, the location
-// of a gesture event seen by each View is in the local coordinate space
-// of that View.
-class GestureLocationView : public EventCountView {
- public:
- GestureLocationView() {}
- virtual ~GestureLocationView() {}
-
- void set_expected_location(gfx::Point expected_location) {
- expected_location_ = expected_location;
- }
-
- // EventCountView:
- virtual void OnGestureEvent(ui::GestureEvent* event) override {
- EventCountView::OnGestureEvent(event);
-
- // Verify that the location of |event| is in the local coordinate
- // space of |this|.
- EXPECT_EQ(expected_location_, event->location());
- }
-
- private:
- // The expected location of a gesture event dispatched to |this|.
- gfx::Point expected_location_;
-
- DISALLOW_COPY_AND_ASSIGN(GestureLocationView);
-};
-
-// Verifies that the location of a gesture event is always in the local
-// coordinate space of the View receiving the event while bubbling.
-TEST_F(WidgetTest, GestureEventLocationWhileBubbling) {
- Widget* widget = CreateTopLevelNativeWidget();
- widget->SetBounds(gfx::Rect(0, 0, 300, 300));
-
- // Define a hierarchy of three views (coordinates shown below are in the
- // coordinate space of the root view, but the coordinates used for
- // SetBounds() are in their parent coordinate space).
- // v1 (50, 50, 150, 150)
- // v2 (100, 70, 50, 80)
- // v3 (120, 100, 10, 10)
- GestureLocationView* v1 = new GestureLocationView();
- v1->SetBounds(50, 50, 150, 150);
- GestureLocationView* v2 = new GestureLocationView();
- v2->SetBounds(50, 20, 50, 80);
- GestureLocationView* v3 = new GestureLocationView();
- v3->SetBounds(20, 30, 10, 10);
- internal::RootView* root_view =
- static_cast<internal::RootView*>(widget->GetRootView());
- root_view->AddChildView(v1);
- v1->AddChildView(v2);
- v2->AddChildView(v3);
-
- widget->Show();
-
- // Define a GESTURE_TAP event located at (125, 105) in root view coordinates.
- // This event is contained within all of |v1|, |v2|, and |v3|.
- gfx::Point location_in_root(125, 105);
- GestureEventForTest tap(
- ui::ET_GESTURE_TAP, location_in_root.x(), location_in_root.y());
-
- // Calculate the location of the event in the local coordinate spaces
- // of each of the views.
- gfx::Point location_in_v1(ConvertPointFromWidgetToView(v1, location_in_root));
- EXPECT_EQ(gfx::Point(75, 55), location_in_v1);
- gfx::Point location_in_v2(ConvertPointFromWidgetToView(v2, location_in_root));
- EXPECT_EQ(gfx::Point(25, 35), location_in_v2);
- gfx::Point location_in_v3(ConvertPointFromWidgetToView(v3, location_in_root));
- EXPECT_EQ(gfx::Point(5, 5), location_in_v3);
-
- // Dispatch the event. When each view receives the event, its location should
- // be in the local coordinate space of that view (see the check made by
- // GestureLocationView). After dispatch is complete the event's location
- // should be in the root coordinate space.
- v1->set_expected_location(location_in_v1);
- v2->set_expected_location(location_in_v2);
- v3->set_expected_location(location_in_v3);
- widget->OnGestureEvent(&tap);
- EXPECT_EQ(location_in_root, tap.location());
-
- // Verify that each view did in fact see the event.
- EventCountView* view1 = v1;
- EventCountView* view2 = v2;
- EventCountView* view3 = v3;
- EXPECT_EQ(1, view1->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(1, view2->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(1, view3->GetEventCount(ui::ET_GESTURE_TAP));
-
- widget->Close();
-}
-
-// Verifies that disabled views are permitted to be set as the default gesture
-// handler in RootView. Also verifies that gesture events targeted to a disabled
-// view are not actually dispatched to the view, but are still marked as
-// handled.
-TEST_F(WidgetTest, DisabledGestureEventTarget) {
- Widget* widget = CreateTopLevelNativeWidget();
- widget->SetBounds(gfx::Rect(0, 0, 300, 300));
-
- // Define a hierarchy of four views (coordinates are in
- // their parent coordinate space).
- // v1 (0, 0, 300, 300)
- // v2 (0, 0, 100, 100)
- // v3 (0, 0, 50, 50)
- // v4(0, 0, 10, 10)
- EventCountView* v1 = new EventCountView();
- v1->SetBounds(0, 0, 300, 300);
- EventCountView* v2 = new EventCountView();
- v2->SetBounds(0, 0, 100, 100);
- EventCountView* v3 = new EventCountView();
- v3->SetBounds(0, 0, 50, 50);
- EventCountView* v4 = new EventCountView();
- v4->SetBounds(0, 0, 10, 10);
- internal::RootView* root_view =
- static_cast<internal::RootView*>(widget->GetRootView());
- root_view->AddChildView(v1);
- v1->AddChildView(v2);
- v2->AddChildView(v3);
- v3->AddChildView(v4);
-
- widget->Show();
-
- // |v1|, |v2|, and |v3| all handle gesture events but |v3| is marked as
- // disabled.
- v1->set_handle_mode(EventCountView::CONSUME_EVENTS);
- v2->set_handle_mode(EventCountView::CONSUME_EVENTS);
- v3->set_handle_mode(EventCountView::CONSUME_EVENTS);
- v3->SetEnabled(false);
-
- // No gesture handler is set in the root view. In this case the tap event
- // should be dispatched only to |v4|, the gesture handler should be set to
- // |v3|, and the event should be marked as handled.
- GestureEventForTest tap(ui::ET_GESTURE_TAP, 5, 5);
- widget->OnGestureEvent(&tap);
- EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(1, v4->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(v3, GetGestureHandler(root_view));
- EXPECT_TRUE(tap.handled());
- v1->ResetCounts();
- v2->ResetCounts();
- v3->ResetCounts();
- v4->ResetCounts();
-
- // A subsequent gesture event should be marked as handled but not dispatched.
- tap = GestureEventForTest(ui::ET_GESTURE_TAP, 5, 5);
- widget->OnGestureEvent(&tap);
- EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(v3, GetGestureHandler(root_view));
- EXPECT_TRUE(tap.handled());
- v1->ResetCounts();
- v2->ResetCounts();
- v3->ResetCounts();
- v4->ResetCounts();
-
- // A GESTURE_END should reset the default gesture handler to NULL. It should
- // also not be dispatched to |v3| but still marked as handled.
- GestureEventForTest end(ui::ET_GESTURE_END, 5, 5);
- widget->OnGestureEvent(&end);
- EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_END));
- EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_END));
- EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_END));
- EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_END));
- EXPECT_EQ(NULL, GetGestureHandler(root_view));
- EXPECT_TRUE(end.handled());
- v1->ResetCounts();
- v2->ResetCounts();
- v3->ResetCounts();
- v4->ResetCounts();
-
- // Change the handle mode of |v3| to indicate that it would no longer like
- // to handle events which are dispatched to it.
- v3->set_handle_mode(EventCountView::PROPAGATE_EVENTS);
-
- // No gesture handler is set in the root view. In this case the tap event
- // should be dispatched only to |v4| and the event should be marked as
- // handled. Furthermore, the gesture handler should be set to
- // |v3|; even though |v3| does not explicitly handle events, it is a
- // valid target for the tap event because it is disabled.
- tap = GestureEventForTest(ui::ET_GESTURE_TAP, 5, 5);
- widget->OnGestureEvent(&tap);
- EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(1, v4->GetEventCount(ui::ET_GESTURE_TAP));
- EXPECT_EQ(v3, GetGestureHandler(root_view));
- EXPECT_TRUE(tap.handled());
- v1->ResetCounts();
- v2->ResetCounts();
- v3->ResetCounts();
- v4->ResetCounts();
-
- // A GESTURE_END should reset the default gesture handler to NULL. It should
- // also not be dispatched to |v3| but still marked as handled.
- end = GestureEventForTest(ui::ET_GESTURE_END, 5, 5);
- widget->OnGestureEvent(&end);
- EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_END));
- EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_END));
- EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_END));
- EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_END));
- EXPECT_EQ(NULL, GetGestureHandler(root_view));
- EXPECT_TRUE(end.handled());
-
- widget->Close();
-}
-
-// Test the result of Widget::GetAllChildWidgets().
-TEST_F(WidgetTest, GetAllChildWidgets) {
- // Create the following widget hierarchy:
- //
- // toplevel
- // +-- w1
- // +-- w11
- // +-- w2
- // +-- w21
- // +-- w22
- Widget* toplevel = CreateTopLevelPlatformWidget();
- Widget* w1 = CreateChildPlatformWidget(toplevel->GetNativeView());
- Widget* w11 = CreateChildPlatformWidget(w1->GetNativeView());
- Widget* w2 = CreateChildPlatformWidget(toplevel->GetNativeView());
- Widget* w21 = CreateChildPlatformWidget(w2->GetNativeView());
- Widget* w22 = CreateChildPlatformWidget(w2->GetNativeView());
-
- std::set<Widget*> expected;
- expected.insert(toplevel);
- expected.insert(w1);
- expected.insert(w11);
- expected.insert(w2);
- expected.insert(w21);
- expected.insert(w22);
-
- std::set<Widget*> widgets;
- Widget::GetAllChildWidgets(toplevel->GetNativeView(), &widgets);
-
- EXPECT_EQ(expected.size(), widgets.size());
- EXPECT_TRUE(std::equal(expected.begin(), expected.end(), widgets.begin()));
-}
-
-// Used by DestroyChildWidgetsInOrder. On destruction adds the supplied name to
-// a vector.
-class DestroyedTrackingView : public View {
- public:
- DestroyedTrackingView(const std::string& name,
- std::vector<std::string>* add_to)
- : name_(name),
- add_to_(add_to) {
- }
-
- virtual ~DestroyedTrackingView() {
- add_to_->push_back(name_);
- }
-
- private:
- const std::string name_;
- std::vector<std::string>* add_to_;
-
- DISALLOW_COPY_AND_ASSIGN(DestroyedTrackingView);
-};
-
-class WidgetChildDestructionTest : public WidgetTest {
- public:
- WidgetChildDestructionTest() {}
-
- // Creates a top level and a child, destroys the child and verifies the views
- // of the child are destroyed before the views of the parent.
- void RunDestroyChildWidgetsTest(bool top_level_has_desktop_native_widget_aura,
- bool child_has_desktop_native_widget_aura) {
- // When a View is destroyed its name is added here.
- std::vector<std::string> destroyed;
-
- Widget* top_level = new Widget;
- Widget::InitParams params =
- CreateParams(views::Widget::InitParams::TYPE_WINDOW);
-#if !defined(OS_CHROMEOS)
- if (top_level_has_desktop_native_widget_aura)
- params.native_widget = new PlatformDesktopNativeWidget(top_level);
-#endif
- top_level->Init(params);
- top_level->GetRootView()->AddChildView(
- new DestroyedTrackingView("parent", &destroyed));
- top_level->Show();
-
- Widget* child = new Widget;
- Widget::InitParams child_params =
- CreateParams(views::Widget::InitParams::TYPE_POPUP);
- child_params.parent = top_level->GetNativeView();
-#if !defined(OS_CHROMEOS)
- if (child_has_desktop_native_widget_aura)
- child_params.native_widget = new PlatformDesktopNativeWidget(child);
-#endif
- child->Init(child_params);
- child->GetRootView()->AddChildView(
- new DestroyedTrackingView("child", &destroyed));
- child->Show();
-
- // Should trigger destruction of the child too.
- top_level->native_widget_private()->CloseNow();
-
- // Child should be destroyed first.
- ASSERT_EQ(2u, destroyed.size());
- EXPECT_EQ("child", destroyed[0]);
- EXPECT_EQ("parent", destroyed[1]);
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(WidgetChildDestructionTest);
-};
-
-#if !defined(OS_CHROMEOS)
-// See description of RunDestroyChildWidgetsTest(). Parent uses
-// DesktopNativeWidgetAura.
-TEST_F(WidgetChildDestructionTest,
- DestroyChildWidgetsInOrderWithDesktopNativeWidget) {
- RunDestroyChildWidgetsTest(true, false);
-}
-
-// See description of RunDestroyChildWidgetsTest(). Both parent and child use
-// DesktopNativeWidgetAura.
-TEST_F(WidgetChildDestructionTest,
- DestroyChildWidgetsInOrderWithDesktopNativeWidgetForBoth) {
- RunDestroyChildWidgetsTest(true, true);
-}
-#endif // !defined(OS_CHROMEOS)
-
-// See description of RunDestroyChildWidgetsTest().
-TEST_F(WidgetChildDestructionTest, DestroyChildWidgetsInOrder) {
- RunDestroyChildWidgetsTest(false, false);
-}
-
-#if !defined(OS_CHROMEOS)
-// Provides functionality to create a window modal dialog.
-class ModalDialogDelegate : public DialogDelegateView {
- public:
- ModalDialogDelegate() {}
- virtual ~ModalDialogDelegate() {}
-
- // WidgetDelegate overrides.
- virtual ui::ModalType GetModalType() const override {
- return ui::MODAL_TYPE_WINDOW;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ModalDialogDelegate);
-};
-
-// This test verifies that whether mouse events when a modal dialog is
-// displayed are eaten or recieved by the dialog.
-TEST_F(WidgetTest, WindowMouseModalityTest) {
- // Create a top level widget.
- Widget top_level_widget;
- Widget::InitParams init_params =
- CreateParams(Widget::InitParams::TYPE_WINDOW);
- init_params.show_state = ui::SHOW_STATE_NORMAL;
- gfx::Rect initial_bounds(0, 0, 500, 500);
- init_params.bounds = initial_bounds;
- init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- init_params.native_widget =
- new PlatformDesktopNativeWidget(&top_level_widget);
- top_level_widget.Init(init_params);
- top_level_widget.Show();
- EXPECT_TRUE(top_level_widget.IsVisible());
-
- // Create a view and validate that a mouse moves makes it to the view.
- EventCountView* widget_view = new EventCountView();
- widget_view->SetBounds(0, 0, 10, 10);
- top_level_widget.GetRootView()->AddChildView(widget_view);
-
- gfx::Point cursor_location_main(5, 5);
- ui::MouseEvent move_main(ui::ET_MOUSE_MOVED,
- cursor_location_main,
- cursor_location_main,
- ui::EF_NONE,
- ui::EF_NONE);
- ui::EventDispatchDetails details =
- GetEventProcessor(&top_level_widget)->OnEventFromSource(&move_main);
- ASSERT_FALSE(details.dispatcher_destroyed);
-
- EXPECT_EQ(1, widget_view->GetEventCount(ui::ET_MOUSE_ENTERED));
- widget_view->ResetCounts();
-
- // Create a modal dialog and validate that a mouse down message makes it to
- // the main view within the dialog.
-
- // This instance will be destroyed when the dialog is destroyed.
- ModalDialogDelegate* dialog_delegate = new ModalDialogDelegate;
-
- Widget* modal_dialog_widget = views::DialogDelegate::CreateDialogWidget(
- dialog_delegate, NULL, top_level_widget.GetNativeView());
- modal_dialog_widget->SetBounds(gfx::Rect(100, 100, 200, 200));
- EventCountView* dialog_widget_view = new EventCountView();
- dialog_widget_view->SetBounds(0, 0, 50, 50);
- modal_dialog_widget->GetRootView()->AddChildView(dialog_widget_view);
- modal_dialog_widget->Show();
- EXPECT_TRUE(modal_dialog_widget->IsVisible());
-
- gfx::Point cursor_location_dialog(100, 100);
- ui::MouseEvent mouse_down_dialog(ui::ET_MOUSE_PRESSED,
- cursor_location_dialog,
- cursor_location_dialog,
- ui::EF_NONE,
- ui::EF_NONE);
- details = GetEventProcessor(&top_level_widget)->OnEventFromSource(
- &mouse_down_dialog);
- ASSERT_FALSE(details.dispatcher_destroyed);
- EXPECT_EQ(1, dialog_widget_view->GetEventCount(ui::ET_MOUSE_PRESSED));
-
- // Send a mouse move message to the main window. It should not be received by
- // the main window as the modal dialog is still active.
- gfx::Point cursor_location_main2(6, 6);
- ui::MouseEvent mouse_down_main(ui::ET_MOUSE_MOVED,
- cursor_location_main2,
- cursor_location_main2,
- ui::EF_NONE,
- ui::EF_NONE);
- details = GetEventProcessor(&top_level_widget)->OnEventFromSource(
- &mouse_down_main);
- ASSERT_FALSE(details.dispatcher_destroyed);
- EXPECT_EQ(0, widget_view->GetEventCount(ui::ET_MOUSE_MOVED));
-
- modal_dialog_widget->CloseNow();
- top_level_widget.CloseNow();
-}
-
-// Verifies nativeview visbility matches that of Widget visibility when
-// SetFullscreen is invoked.
-TEST_F(WidgetTest, FullscreenStatePropagated) {
- Widget::InitParams init_params =
- CreateParams(Widget::InitParams::TYPE_WINDOW);
- init_params.show_state = ui::SHOW_STATE_NORMAL;
- init_params.bounds = gfx::Rect(0, 0, 500, 500);
- init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
-
- {
- Widget top_level_widget;
- top_level_widget.Init(init_params);
- top_level_widget.SetFullscreen(true);
- EXPECT_EQ(top_level_widget.IsVisible(),
- IsNativeWindowVisible(top_level_widget.GetNativeWindow()));
- top_level_widget.CloseNow();
- }
-#if !defined(OS_CHROMEOS)
- {
- Widget top_level_widget;
- init_params.native_widget =
- new PlatformDesktopNativeWidget(&top_level_widget);
- top_level_widget.Init(init_params);
- top_level_widget.SetFullscreen(true);
- EXPECT_EQ(top_level_widget.IsVisible(),
- IsNativeWindowVisible(top_level_widget.GetNativeWindow()));
- top_level_widget.CloseNow();
- }
-#endif
-}
-#if defined(OS_WIN)
-
-// Provides functionality to test widget activation via an activation flag
-// which can be set by an accessor.
-class ModalWindowTestWidgetDelegate : public WidgetDelegate {
- public:
- ModalWindowTestWidgetDelegate()
- : widget_(NULL),
- can_activate_(true) {}
-
- virtual ~ModalWindowTestWidgetDelegate() {}
-
- // Overridden from WidgetDelegate:
- virtual void DeleteDelegate() override {
- delete this;
- }
- virtual Widget* GetWidget() override {
- return widget_;
- }
- virtual const Widget* GetWidget() const override {
- return widget_;
- }
- virtual bool CanActivate() const override {
- return can_activate_;
- }
- virtual bool ShouldAdvanceFocusToTopLevelWidget() const override {
- return true;
- }
-
- void set_can_activate(bool can_activate) {
- can_activate_ = can_activate;
- }
-
- void set_widget(Widget* widget) {
- widget_ = widget;
- }
-
- private:
- Widget* widget_;
- bool can_activate_;
-
- DISALLOW_COPY_AND_ASSIGN(ModalWindowTestWidgetDelegate);
-};
-
-// Tests whether we can activate the top level widget when a modal dialog is
-// active.
-TEST_F(WidgetTest, WindowModalityActivationTest) {
- // Destroyed when the top level widget created below is destroyed.
- ModalWindowTestWidgetDelegate* widget_delegate =
- new ModalWindowTestWidgetDelegate;
- // Create a top level widget.
- Widget top_level_widget;
- Widget::InitParams init_params =
- CreateParams(Widget::InitParams::TYPE_WINDOW);
- init_params.show_state = ui::SHOW_STATE_NORMAL;
- gfx::Rect initial_bounds(0, 0, 500, 500);
- init_params.bounds = initial_bounds;
- init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- init_params.native_widget = new DesktopNativeWidgetAura(&top_level_widget);
- init_params.delegate = widget_delegate;
- top_level_widget.Init(init_params);
- widget_delegate->set_widget(&top_level_widget);
- top_level_widget.Show();
- EXPECT_TRUE(top_level_widget.IsVisible());
-
- HWND win32_window = views::HWNDForWidget(&top_level_widget);
- EXPECT_TRUE(::IsWindow(win32_window));
-
- // This instance will be destroyed when the dialog is destroyed.
- ModalDialogDelegate* dialog_delegate = new ModalDialogDelegate;
-
- // We should be able to activate the window even if the WidgetDelegate
- // says no, when a modal dialog is active.
- widget_delegate->set_can_activate(false);
-
- Widget* modal_dialog_widget = views::DialogDelegate::CreateDialogWidget(
- dialog_delegate, NULL, top_level_widget.GetNativeWindow());
- modal_dialog_widget->SetBounds(gfx::Rect(100, 100, 200, 200));
- modal_dialog_widget->Show();
- EXPECT_TRUE(modal_dialog_widget->IsVisible());
-
- LRESULT activate_result = ::SendMessage(
- win32_window,
- WM_MOUSEACTIVATE,
- reinterpret_cast<WPARAM>(win32_window),
- MAKELPARAM(WM_LBUTTONDOWN, HTCLIENT));
- EXPECT_EQ(activate_result, MA_ACTIVATE);
-
- modal_dialog_widget->CloseNow();
- top_level_widget.CloseNow();
-}
-#endif // defined(OS_WIN)
-#endif // !defined(OS_CHROMEOS)
-
-TEST_F(WidgetTest, ShowCreatesActiveWindow) {
- Widget* widget = CreateTopLevelPlatformWidget();
-
- widget->Show();
- EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL);
-
- widget->CloseNow();
-}
-
-// OSX does not have a per-application "active" window such as provided by
-// ::GetActiveWindow() on Windows. There is only a system-wide "keyWindow" which
-// is updated asynchronously.
-#if defined(OS_MACOSX)
-#define MAYBE_ShowInactive DISABLED_ShowInactive
-#else
-#define MAYBE_ShowInactive ShowInactive
-#endif
-TEST_F(WidgetTest, MAYBE_ShowInactive) {
- Widget* widget = CreateTopLevelPlatformWidget();
-
- widget->ShowInactive();
- EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_INACTIVE);
-
- widget->CloseNow();
-}
-
-TEST_F(WidgetTest, InactiveBeforeShow) {
- Widget* widget = CreateTopLevelPlatformWidget();
-
- EXPECT_FALSE(widget->IsActive());
- EXPECT_FALSE(widget->IsVisible());
-
- widget->Show();
-
- EXPECT_TRUE(widget->IsActive());
- EXPECT_TRUE(widget->IsVisible());
-
- widget->CloseNow();
-}
-
-TEST_F(WidgetTest, ShowInactiveAfterShow) {
- // Create 2 widgets to ensure window layering does not change.
- Widget* widget = CreateTopLevelPlatformWidget();
- Widget* widget2 = CreateTopLevelPlatformWidget();
-
- widget2->Show();
- EXPECT_FALSE(widget->IsActive());
- EXPECT_TRUE(widget2->IsVisible());
- EXPECT_TRUE(widget2->IsActive());
-
- widget->Show();
- EXPECT_TRUE(widget->IsActive());
- EXPECT_FALSE(widget2->IsActive());
- widget->ShowInactive();
- EXPECT_TRUE(widget->IsActive());
- EXPECT_FALSE(widget2->IsActive());
- EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL);
-
- widget2->CloseNow();
- widget->CloseNow();
-}
-
-TEST_F(WidgetTest, ShowAfterShowInactive) {
- Widget* widget = CreateTopLevelPlatformWidget();
-
- widget->ShowInactive();
- widget->Show();
- EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL);
-
- widget->CloseNow();
-}
-
-#if !defined(OS_CHROMEOS)
-TEST_F(WidgetTest, InactiveWidgetDoesNotGrabActivation) {
- Widget* widget = CreateTopLevelPlatformWidget();
- widget->Show();
- EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL);
-
- Widget widget2;
- Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
- params.native_widget = new PlatformDesktopNativeWidget(&widget2);
- params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- widget2.Init(params);
- widget2.Show();
-
- EXPECT_EQ(GetWidgetShowState(&widget2), ui::SHOW_STATE_INACTIVE);
- EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL);
-
- widget->CloseNow();
- widget2.CloseNow();
-}
-#endif // !defined(OS_CHROMEOS)
-
-namespace {
-
-class FullscreenAwareFrame : public views::NonClientFrameView {
- public:
- explicit FullscreenAwareFrame(views::Widget* widget)
- : widget_(widget), fullscreen_layout_called_(false) {}
- virtual ~FullscreenAwareFrame() {}
-
- // views::NonClientFrameView overrides:
- virtual gfx::Rect GetBoundsForClientView() const override {
- return gfx::Rect();
- }
- virtual gfx::Rect GetWindowBoundsForClientBounds(
- const gfx::Rect& client_bounds) const override {
- return gfx::Rect();
- }
- virtual int NonClientHitTest(const gfx::Point& point) override {
- return HTNOWHERE;
- }
- virtual void GetWindowMask(const gfx::Size& size,
- gfx::Path* window_mask) override {}
- virtual void ResetWindowControls() override {}
- virtual void UpdateWindowIcon() override {}
- virtual void UpdateWindowTitle() override {}
- virtual void SizeConstraintsChanged() override {}
-
- // views::View overrides:
- virtual void Layout() override {
- if (widget_->IsFullscreen())
- fullscreen_layout_called_ = true;
- }
-
- bool fullscreen_layout_called() const { return fullscreen_layout_called_; }
-
- private:
- views::Widget* widget_;
- bool fullscreen_layout_called_;
-
- DISALLOW_COPY_AND_ASSIGN(FullscreenAwareFrame);
-};
-
-} // namespace
-
-// Tests that frame Layout is called when a widget goes fullscreen without
-// changing its size or title.
-TEST_F(WidgetTest, FullscreenFrameLayout) {
- Widget* widget = CreateTopLevelPlatformWidget();
- FullscreenAwareFrame* frame = new FullscreenAwareFrame(widget);
- widget->non_client_view()->SetFrameView(frame); // Owns |frame|.
-
- widget->Maximize();
- RunPendingMessages();
-
- EXPECT_FALSE(frame->fullscreen_layout_called());
- widget->SetFullscreen(true);
- widget->Show();
- RunPendingMessages();
- EXPECT_TRUE(frame->fullscreen_layout_called());
-
- widget->CloseNow();
-}
-
-#if !defined(OS_CHROMEOS)
-namespace {
-
-// Trivial WidgetObserverTest that invokes Widget::IsActive() from
-// OnWindowDestroying.
-class IsActiveFromDestroyObserver : public WidgetObserver {
- public:
- IsActiveFromDestroyObserver() {}
- virtual ~IsActiveFromDestroyObserver() {}
- virtual void OnWidgetDestroying(Widget* widget) override {
- widget->IsActive();
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(IsActiveFromDestroyObserver);
-};
-
-} // namespace
-
-// Verifies Widget::IsActive() invoked from
-// WidgetObserver::OnWidgetDestroying() in a child widget doesn't crash.
-TEST_F(WidgetTest, IsActiveFromDestroy) {
- // Create two widgets, one a child of the other.
- IsActiveFromDestroyObserver observer;
- Widget parent_widget;
- Widget::InitParams parent_params =
- CreateParams(Widget::InitParams::TYPE_POPUP);
- parent_params.native_widget = new PlatformDesktopNativeWidget(&parent_widget);
- parent_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- parent_widget.Init(parent_params);
- parent_widget.Show();
-
- Widget child_widget;
- Widget::InitParams child_params =
- CreateParams(Widget::InitParams::TYPE_POPUP);
- child_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- child_params.context = parent_widget.GetNativeWindow();
- child_widget.Init(child_params);
- child_widget.AddObserver(&observer);
- child_widget.Show();
-
- parent_widget.CloseNow();
-}
-#endif // !defined(OS_CHROMEOS)
-
-// Tests that events propagate through from the dispatcher with the correct
-// event type, and that the different platforms behave the same.
-TEST_F(WidgetTest, MouseEventTypesViaGenerator) {
- EventCountView* view = new EventCountView;
- view->set_handle_mode(EventCountView::CONSUME_EVENTS);
- view->SetBounds(10, 10, 50, 40);
-
- Widget* widget = CreateTopLevelFramelessPlatformWidget();
- widget->GetRootView()->AddChildView(view);
-
- widget->SetBounds(gfx::Rect(0, 0, 100, 80));
- widget->Show();
-
- ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
- generator.set_current_location(gfx::Point(20, 20));
-
- generator.ClickLeftButton();
- EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_PRESSED));
- EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_RELEASED));
- EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, view->last_flags());
-
- generator.PressRightButton();
- EXPECT_EQ(2, view->GetEventCount(ui::ET_MOUSE_PRESSED));
- EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_RELEASED));
- EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, view->last_flags());
-
- generator.ReleaseRightButton();
- EXPECT_EQ(2, view->GetEventCount(ui::ET_MOUSE_PRESSED));
- EXPECT_EQ(2, view->GetEventCount(ui::ET_MOUSE_RELEASED));
- EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, view->last_flags());
-
- // Test mouse move events.
- EXPECT_EQ(0, view->GetEventCount(ui::ET_MOUSE_MOVED));
- EXPECT_EQ(0, view->GetEventCount(ui::ET_MOUSE_ENTERED));
-
- // Move the mouse within the view (20, 20) -> (30, 30).
- generator.MoveMouseTo(gfx::Point(30, 30));
- EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_MOVED));
- EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_ENTERED));
- EXPECT_EQ(ui::EF_NONE, view->last_flags());
-
- // Move it again - entered count shouldn't change.
- generator.MoveMouseTo(gfx::Point(31, 31));
- EXPECT_EQ(2, view->GetEventCount(ui::ET_MOUSE_MOVED));
- EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_ENTERED));
- EXPECT_EQ(0, view->GetEventCount(ui::ET_MOUSE_EXITED));
-
- // Move it off the view.
- generator.MoveMouseTo(gfx::Point(5, 5));
- EXPECT_EQ(2, view->GetEventCount(ui::ET_MOUSE_MOVED));
- EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_ENTERED));
- EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_EXITED));
-
- // Move it back on.
- generator.MoveMouseTo(gfx::Point(20, 20));
- EXPECT_EQ(3, view->GetEventCount(ui::ET_MOUSE_MOVED));
- EXPECT_EQ(2, view->GetEventCount(ui::ET_MOUSE_ENTERED));
- EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_EXITED));
-
- // Drargging. Cover HasCapture() and NativeWidgetPrivate::IsMouseButtonDown().
- generator.DragMouseTo(gfx::Point(40, 40));
- EXPECT_EQ(3, view->GetEventCount(ui::ET_MOUSE_PRESSED));
- EXPECT_EQ(3, view->GetEventCount(ui::ET_MOUSE_RELEASED));
- EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_DRAGGED));
- EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, view->last_flags());
-
- widget->CloseNow();
-}
-
-// Tests that a view does not receive entered, dragged, or moved events if
-// a mouse cursor is moved into it while the left mouse button is pressed.
-TEST_F(WidgetTest, DragIntoView) {
- EventCountView* container = new EventCountView;
- container->SetBounds(0, 0, 100, 80);
-
- EventCountView* consume_view = new EventCountView;
- consume_view->set_handle_mode(EventCountView::CONSUME_EVENTS);
- consume_view->SetBounds(10, 10, 50, 40);
-
- Widget* widget = CreateTopLevelFramelessPlatformWidget();
- widget->SetBounds(gfx::Rect(0, 0, 100, 80));
- widget->SetContentsView(container);
- container->AddChildView(consume_view);
-
- widget->Show();
-
- ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
- generator.set_current_location(gfx::Point(75, 15));
-
- generator.PressLeftButton();
- generator.MoveMouseTo(gfx::Point(20, 20));
- EXPECT_EQ(0, consume_view->GetEventCount(ui::ET_MOUSE_ENTERED));
- EXPECT_EQ(0, consume_view->GetEventCount(ui::ET_MOUSE_DRAGGED));
- EXPECT_EQ(0, consume_view->GetEventCount(ui::ET_MOUSE_MOVED));
-
- widget->CloseNow();
-}
-
-// Tests that a view receives the correct mouse events if a mouse cursor
-// is moved out of its bounds while the left mouse button is pressed.
-TEST_F(WidgetTest, DragOutOfView) {
- EventCountView* container = new EventCountView;
- container->SetBounds(0, 0, 100, 80);
-
- EventCountView* consume_view = new EventCountView;
- consume_view->set_handle_mode(EventCountView::CONSUME_EVENTS);
- consume_view->SetBounds(10, 10, 50, 40);
-
- Widget* widget = CreateTopLevelFramelessPlatformWidget();
- widget->SetBounds(gfx::Rect(0, 0, 100, 80));
- widget->SetContentsView(container);
- container->AddChildView(consume_view);
-
- widget->Show();
-
- ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
- generator.set_current_location(gfx::Point(20, 20));
-
- generator.PressLeftButton();
- EXPECT_EQ(1, consume_view->GetEventCount(ui::ET_MOUSE_PRESSED));
- EXPECT_EQ(0, container->GetEventCount(ui::ET_MOUSE_PRESSED));
- consume_view->ResetCounts();
-
- generator.MoveMouseTo(gfx::Point(70, 70));
- EXPECT_EQ(0, consume_view->GetEventCount(ui::ET_MOUSE_EXITED));
- EXPECT_EQ(1, consume_view->GetEventCount(ui::ET_MOUSE_DRAGGED));
- EXPECT_EQ(0, consume_view->GetEventCount(ui::ET_MOUSE_MOVED));
- EXPECT_EQ(0, container->GetEventCount(ui::ET_MOUSE_ENTERED));
- EXPECT_EQ(0, container->GetEventCount(ui::ET_MOUSE_DRAGGED));
- EXPECT_EQ(0, container->GetEventCount(ui::ET_MOUSE_MOVED));
- consume_view->ResetCounts();
-
- generator.MoveMouseTo(gfx::Point(71, 71));
- EXPECT_EQ(1, consume_view->GetEventCount(ui::ET_MOUSE_DRAGGED));
- EXPECT_EQ(0, consume_view->GetEventCount(ui::ET_MOUSE_MOVED));
- EXPECT_EQ(0, container->GetEventCount(ui::ET_MOUSE_DRAGGED));
- EXPECT_EQ(0, container->GetEventCount(ui::ET_MOUSE_MOVED));
- consume_view->ResetCounts();
-
- generator.ReleaseLeftButton();
- EXPECT_EQ(1, consume_view->GetEventCount(ui::ET_MOUSE_RELEASED));
- EXPECT_EQ(0, container->GetEventCount(ui::ET_MOUSE_RELEASED));
- consume_view->ResetCounts();
-
- widget->CloseNow();
-}
-
-// Tests that the root view is correctly set up for Widget types that do not
-// require a non-client view, before any other views are added to the widget.
-// That is, before Widget::ReorderNativeViews() is called which, if called with
-// a root view not set, could cause the root view to get resized to the widget.
-TEST_F(WidgetTest, NonClientWindowValidAfterInit) {
- Widget* widget = CreateTopLevelFramelessPlatformWidget();
- View* root_view = widget->GetRootView();
-
- // Size the root view to exceed the widget bounds.
- const gfx::Rect test_rect(0, 0, 500, 500);
- root_view->SetBoundsRect(test_rect);
-
- EXPECT_NE(test_rect.size(), widget->GetWindowBoundsInScreen().size());
-
- EXPECT_EQ(test_rect, root_view->bounds());
- widget->ReorderNativeViews();
- EXPECT_EQ(test_rect, root_view->bounds());
-
- widget->CloseNow();
-}
-
-} // namespace test
-} // namespace views
« no previous file with comments | « ui/views/widget/widget_removals_observer.h ('k') | ui/views/widget/window_reorderer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698