chromium/ui/views/widget/root_view_unittest.cc

// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/views/widget/root_view.h"

#include <memory>
#include <utility>

#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_forward.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "build/build_config.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/mojom/dialog_button.mojom.h"
#include "ui/events/event_utils.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/context_menu_controller.h"
#include "ui/views/test/test_views.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/test/views_test_utils.h"
#include "ui/views/view_targeter.h"
#include "ui/views/widget/widget_deletion_observer.h"
#include "ui/views/window/dialog_delegate.h"

#if BUILDFLAG(IS_MAC)
#include "base/mac/mac_util.h"
#endif

namespace views::test {
namespace {

struct RootViewTestStateInit {};

class RootViewTestState {};

class DeleteOnKeyEventView : public View {};

BEGIN_METADATA()

}  // namespace

RootViewTest;

// Verifies deleting a View in OnKeyPressed() doesn't crash and that the
// target is marked as destroyed in the returned EventDispatchDetails.
TEST_F(RootViewTest, DeleteViewDuringKeyEventDispatch) {}

// Tracks whether a context menu is shown.
class TestContextMenuController : public ContextMenuController {};

// Tests that context menus are shown for certain key events (Shift+F10
// and VKEY_APPS) by the pre-target handler installed on RootView.
TEST_F(RootViewTest, ContextMenuFromKeyEvent) {}

// View which handles all gesture events.
class GestureHandlingView : public View {};

BEGIN_METADATA()

// View which handles all mouse events.
class MouseHandlingView : public View {};

BEGIN_METADATA()

TEST_F(RootViewTest, EventHandlersResetWhenDeleted) {}

TEST_F(RootViewTest, EventHandlersNotResetWhenReparented) {}

// Verifies that the gesture handler stored in the root view is reset after
// mouse is released. Note that during mouse event handling,
// `RootView::SetMouseAndGestureHandler()` may be called to set the gesture
// handler. Therefore we should reset the gesture handler when mouse is
// released. We may remove this test in the future if the implementation of the
// product code changes.
TEST_F(RootViewTest, GestureHandlerResetAfterMouseReleased) {}

// Tests that context menus are shown for long press by the post-target handler
// installed on the RootView only if the event is targetted at a view which can
// show a context menu.
TEST_F(RootViewTest, ContextMenuFromLongPress) {}

// Tests that context menus are not shown for disabled views on a long press.
TEST_F(RootViewTest, ContextMenuFromLongPressOnDisabledView) {}

namespace {

// View class which destroys itself when it gets an event of type
// |delete_event_type|.
class DeleteViewOnEvent : public View {};

BEGIN_METADATA()

// View class which remove itself when it gets an event of type
// |remove_event_type|.
class RemoveViewOnEvent : public View {};

BEGIN_METADATA()

// View class which generates a nested event the first time it gets an event of
// type |nested_event_type|. This is used to simulate nested event loops which
// can cause |RootView::mouse_event_handler_| to get reset.
class NestedEventOnEvent : public View {};

BEGIN_METADATA()

}  // namespace

// Verifies deleting a View in OnMouseExited() doesn't crash.
TEST_F(RootViewTest, DeleteViewOnMouseExitDispatch) {}

// Verifies deleting a View in OnMouseEntered() doesn't crash.
TEST_F(RootViewTest, DeleteViewOnMouseEnterDispatch) {}

// Verifies removing a View in OnMouseEntered() doesn't crash.
TEST_F(RootViewTest, RemoveViewOnMouseEnterDispatch) {}

// Verifies clearing the root view's |mouse_move_handler_| in OnMouseExited()
// doesn't crash.
TEST_F(RootViewTest, ClearMouseMoveHandlerOnMouseExitDispatch) {}

// Verifies clearing the root view's |mouse_move_handler_| in OnMouseExited()
// doesn't crash, in the case where the root view is targeted, because
// it's the first enabled view encountered walking up the target tree.
TEST_F(RootViewTest,
       ClearMouseMoveHandlerOnMouseExitDispatchWithContentViewDisabled) {}

// Verifies clearing the root view's |mouse_move_handler_| in OnMouseEntered()
// doesn't crash.
TEST_F(RootViewTest, ClearMouseMoveHandlerOnMouseEnterDispatch) {}

namespace {

// View class which deletes its owning Widget when it gets a mouse exit event.
class DeleteWidgetOnMouseExit : public View {};

BEGIN_METADATA()

}  // namespace

// Test that there is no crash if a View deletes its parent Widget in
// View::OnMouseExited().
TEST_F(RootViewTest, DeleteWidgetOnMouseExitDispatch) {}

// Test that there is no crash if a View deletes its parent widget as a result
// of a mouse exited event which was propagated from one of its children.
TEST_F(RootViewTest, DeleteWidgetOnMouseExitDispatchFromChild) {}

namespace {
class RootViewTestDialogDelegate : public DialogDelegateView {};
}  // namespace

// Ensure only one layout happens during Widget initialization, and ensure it
// happens at the ContentView's preferred size.
TEST_F(RootViewTest, SingleLayoutDuringInit) {}

RootViewDesktopNativeWidgetTest;

// Also test Aura desktop Widget codepaths.
TEST_F(RootViewDesktopNativeWidgetTest, SingleLayoutDuringInit) {}

#if !BUILDFLAG(IS_MAC)

// Tests that AnnounceAlert sets up the correct text value on the hidden
// view, and that the resulting hidden view actually stays hidden.
TEST_F(RootViewTest, AnnounceTextAsTest) {}

#endif  // !BUILDFLAG(IS_MAC)

TEST_F(RootViewTest, MouseEventDispatchedToClosestEnabledView) {}

// If RootView::OnMousePressed() receives a double-click event that isn't
// handled by any views, it should still report it as handled if the first click
// was handled. However, it should *not* if the first click was unhandled.
// Regression test for https://crbug.com/1055674.
TEST_F(RootViewTest, DoubleClickHandledIffFirstClickHandled) {}

TEST_F(RootViewTest, AccessibleProperties) {}

}  // namespace views::test