#include <stddef.h>
#include <memory>
#include <utility>
#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/location.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/mojom/ui_base_types.mojom-shared.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/test/ui_controls.h"
#include "ui/base/ui_base_features.h"
#include "ui/base/ui_base_switches.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/views/bubble/bubble_dialog_delegate_view.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/controls/textfield/textfield_test_api.h"
#include "ui/views/focus/focus_manager.h"
#include "ui/views/test/focus_manager_test.h"
#include "ui/views/test/native_widget_factory.h"
#include "ui/views/test/widget_activation_waiter.h"
#include "ui/views/test/widget_test.h"
#include "ui/views/touchui/touch_selection_controller_impl.h"
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/unique_widget_ptr.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_interactive_uitest_utils.h"
#include "ui/views/widget/widget_utils.h"
#include "ui/views/window/dialog_delegate.h"
#include "ui/wm/public/activation_client.h"
#if BUILDFLAG(ENABLE_DESKTOP_AURA)
#include "ui/aura/env.h"
#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
#endif
#if BUILDFLAG(IS_WIN)
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/views/win/hwnd_util.h"
#endif
namespace views::test {
namespace {
template <class T>
class UniqueWidgetPtrT : public views::UniqueWidgetPtr { … };
class ExitLoopOnRelease : public View { … };
BEGIN_METADATA(…)
class GestureCaptureView : public View { … };
BEGIN_METADATA(…)
class MouseView : public View { … };
BEGIN_METADATA(…)
class NestedLoopCaptureView : public View { … };
BEGIN_METADATA(…)
#if BUILDFLAG(ENABLE_DESKTOP_AURA)
class DragView : public View, public DragController { … };
BEGIN_METADATA(…)
#endif
ui::WindowShowState GetWidgetShowState(const Widget* widget) { … }
void RunPendingMessagesForActiveStatusChange() { … }
void ActivateSync(Widget* widget) { … }
void ShowSync(Widget* widget) { … }
void DeactivateSync(Widget* widget) { … }
#if BUILDFLAG(IS_WIN)
void ActivatePlatformWindow(Widget* widget) {
::SetActiveWindow(
widget->GetNativeWindow()->GetHost()->GetAcceleratedWidget());
}
#endif
void ShowInactiveSync(Widget* widget) { … }
std::unique_ptr<Textfield> CreateTextfield() { … }
}
class WidgetTestInteractive : public WidgetTest { … };
#if BUILDFLAG(IS_WIN)
TEST_F(DesktopWidgetTestInteractive,
DesktopNativeWidgetAuraActivationAndFocusTest) {
View* focusable_view1 = new View;
focusable_view1->SetFocusBehavior(View::FocusBehavior::ALWAYS);
WidgetAutoclosePtr widget1(CreateTopLevelNativeWidget());
widget1->GetContentsView()->AddChildView(focusable_view1);
widget1->Show();
aura::Window* root_window1 = GetRootWindow(widget1.get());
focusable_view1->RequestFocus();
EXPECT_TRUE(root_window1 != nullptr);
wm::ActivationClient* activation_client1 =
wm::GetActivationClient(root_window1);
EXPECT_TRUE(activation_client1 != nullptr);
EXPECT_EQ(activation_client1->GetActiveWindow(), widget1->GetNativeView());
View* focusable_view2 = new View;
WidgetAutoclosePtr widget2(CreateTopLevelNativeWidget());
widget1->GetContentsView()->AddChildView(focusable_view2);
widget2->Show();
aura::Window* root_window2 = GetRootWindow(widget2.get());
focusable_view2->RequestFocus();
ActivatePlatformWindow(widget2.get());
wm::ActivationClient* activation_client2 =
wm::GetActivationClient(root_window2);
EXPECT_TRUE(activation_client2 != nullptr);
EXPECT_EQ(activation_client2->GetActiveWindow(), widget2->GetNativeView());
EXPECT_EQ(activation_client1->GetActiveWindow(),
reinterpret_cast<aura::Window*>(NULL));
focusable_view1->RequestFocus();
ActivatePlatformWindow(widget1.get());
EXPECT_EQ(activation_client2->GetActiveWindow(),
reinterpret_cast<aura::Window*>(NULL));
EXPECT_EQ(activation_client1->GetActiveWindow(), widget1->GetNativeView());
}
TEST_F(DesktopWidgetTestInteractive, FocusChangesOnBubble) {
WidgetAutoclosePtr widget(CreateTopLevelNativeWidget());
View* focusable_view =
widget->GetContentsView()->AddChildView(std::make_unique<View>());
focusable_view->SetFocusBehavior(View::FocusBehavior::ALWAYS);
widget->Show();
focusable_view->RequestFocus();
EXPECT_TRUE(focusable_view->HasFocus());
auto owned_bubble_delegate_view =
std::make_unique<views::BubbleDialogDelegateView>(focusable_view,
BubbleBorder::NONE);
owned_bubble_delegate_view->SetFocusBehavior(View::FocusBehavior::ALWAYS);
BubbleDialogDelegateView* bubble_delegate_view =
owned_bubble_delegate_view.get();
BubbleDialogDelegateView::CreateBubble(std::move(owned_bubble_delegate_view))
->Show();
bubble_delegate_view->RequestFocus();
EXPECT_FALSE(focusable_view->HasFocus());
EXPECT_TRUE(bubble_delegate_view->HasFocus());
bubble_delegate_view->GetWidget()->CloseNow();
EXPECT_TRUE(focusable_view->HasFocus());
}
class TouchEventHandler : public ui::EventHandler {
public:
explicit TouchEventHandler(Widget* widget) : widget_(widget) {
widget_->GetNativeWindow()->GetHost()->window()->AddPreTargetHandler(this);
}
TouchEventHandler(const TouchEventHandler&) = delete;
TouchEventHandler& operator=(const TouchEventHandler&) = delete;
~TouchEventHandler() override {
widget_->GetNativeWindow()->GetHost()->window()->RemovePreTargetHandler(
this);
}
void WaitForEvents() {
base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
quit_closure_ = run_loop.QuitClosure();
run_loop.Run();
}
static void __stdcall AsyncActivateMouse(HWND hwnd,
UINT msg,
ULONG_PTR data,
LRESULT result) {
EXPECT_EQ(MA_NOACTIVATE, result);
std::move(reinterpret_cast<TouchEventHandler*>(data)->quit_closure_).Run();
}
void ActivateViaMouse() {
SendMessageCallback(
widget_->GetNativeWindow()->GetHost()->GetAcceleratedWidget(),
WM_MOUSEACTIVATE, 0, 0, AsyncActivateMouse,
reinterpret_cast<ULONG_PTR>(this));
}
private:
void OnTouchEvent(ui::TouchEvent* event) override {
if (event->type() == ui::EventType::kTouchPressed) {
ActivateViaMouse();
}
}
raw_ptr<Widget> widget_;
base::OnceClosure quit_closure_;
};
TEST_F(DesktopWidgetTestInteractive, DISABLED_TouchNoActivateWindow) {
View* focusable_view = new View;
focusable_view->SetFocusBehavior(View::FocusBehavior::ALWAYS);
WidgetAutoclosePtr widget(CreateTopLevelNativeWidget());
widget->GetContentsView()->AddChildView(focusable_view);
widget->Show();
{
TouchEventHandler touch_event_handler(widget.get());
ASSERT_TRUE(
ui_controls::SendTouchEvents(ui_controls::kTouchPress, 1, 100, 100));
touch_event_handler.WaitForEvents();
}
}
#endif
TEST_F(WidgetTestInteractive, CheckResizeControllerEvents) { … }
TEST_F(WidgetTestInteractive, ViewFocusOnWidgetActivationChanges) { … }
TEST_F(WidgetTestInteractive, ZOrderCheckBetweenTopWindows) { … }
#if BUILDFLAG(IS_MAC)
#define MAYBE_ChildStackedRelativeToParent …
#else
#define MAYBE_ChildStackedRelativeToParent …
#endif
TEST_F(WidgetTestInteractive, MAYBE_ChildStackedRelativeToParent) { … }
TEST_F(WidgetTestInteractive, ChildWidgetStackAbove) { … }
TEST_F(WidgetTestInteractive, ChildWidgetStackAtTop) { … }
#if BUILDFLAG(IS_WIN)
TEST_F(WidgetTestInteractive, ViewFocusOnHWNDEnabledChanges) {
WidgetAutoclosePtr widget(CreateTopLevelFramelessPlatformWidget());
widget->SetContentsView(std::make_unique<View>());
for (size_t i = 0; i < 2; ++i) {
auto child = std::make_unique<View>();
child->SetFocusBehavior(View::FocusBehavior::ALWAYS);
widget->GetContentsView()->AddChildView(std::move(child));
}
widget->Show();
widget->GetNativeWindow()->GetHost()->Show();
const HWND hwnd = HWNDForWidget(widget.get());
EXPECT_TRUE(::IsWindow(hwnd));
EXPECT_TRUE(::IsWindowEnabled(hwnd));
EXPECT_EQ(hwnd, ::GetActiveWindow());
for (View* view : widget->GetContentsView()->children()) {
SCOPED_TRACE("Child view " +
base::NumberToString(
widget->GetContentsView()->GetIndexOf(view).value()));
view->RequestFocus();
EXPECT_EQ(view, widget->GetFocusManager()->GetFocusedView());
EXPECT_FALSE(::EnableWindow(hwnd, FALSE));
EXPECT_FALSE(::IsWindowEnabled(hwnd));
EXPECT_EQ(hwnd, ::GetActiveWindow());
EXPECT_TRUE(widget->IsActive());
EXPECT_EQ(view, widget->GetFocusManager()->GetFocusedView());
EXPECT_TRUE(::EnableWindow(hwnd, TRUE));
EXPECT_TRUE(::IsWindowEnabled(hwnd));
EXPECT_EQ(hwnd, ::GetActiveWindow());
EXPECT_TRUE(widget->IsActive());
EXPECT_EQ(view, widget->GetFocusManager()->GetFocusedView());
}
}
class WidgetActivationTest : public Widget {
public:
WidgetActivationTest() = default;
WidgetActivationTest(const WidgetActivationTest&) = delete;
WidgetActivationTest& operator=(const WidgetActivationTest&) = delete;
~WidgetActivationTest() override = default;
bool OnNativeWidgetActivationChanged(bool active) override {
active_ = active;
return true;
}
bool active() const { return active_; }
private:
bool active_ = false;
};
TEST_F(WidgetTestInteractive, WidgetNotActivatedOnFakeActivationMessages) {
UniqueWidgetPtrT widget1 = std::make_unique<WidgetActivationTest>();
Widget::InitParams init_params =
CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
init_params.native_widget = new DesktopNativeWidgetAura(widget1.get());
init_params.bounds = gfx::Rect(0, 0, 200, 200);
widget1->Init(std::move(init_params));
widget1->Show();
EXPECT_EQ(true, widget1->active());
UniqueWidgetPtrT widget2 = std::make_unique<WidgetActivationTest>();
init_params = CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
init_params.native_widget = new DesktopNativeWidgetAura(widget2.get());
widget2->Init(std::move(init_params));
widget2->Show();
EXPECT_EQ(true, widget2->active());
EXPECT_EQ(false, widget1->active());
HWND win32_native_window1 = HWNDForWidget(widget1.get());
EXPECT_TRUE(::IsWindow(win32_native_window1));
::SendMessage(win32_native_window1, WM_NCACTIVATE, 1, 0);
EXPECT_EQ(false, widget1->active());
EXPECT_EQ(true, widget2->active());
::SetActiveWindow(win32_native_window1);
EXPECT_EQ(true, widget1->active());
EXPECT_EQ(false, widget2->active());
}
TEST_F(WidgetTestInteractive, FullscreenBoundsReducedOnActivationLoss) {
UniqueWidgetPtr widget1 = std::make_unique<Widget>();
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
params.native_widget = new DesktopNativeWidgetAura(widget1.get());
widget1->Init(std::move(params));
widget1->SetBounds(gfx::Rect(0, 0, 200, 200));
widget1->Show();
widget1->Activate();
RunPendingMessages();
EXPECT_EQ(::GetActiveWindow(),
widget1->GetNativeWindow()->GetHost()->GetAcceleratedWidget());
widget1->SetFullscreen(true);
EXPECT_TRUE(widget1->IsFullscreen());
RunPendingMessages();
EXPECT_EQ(::GetActiveWindow(),
widget1->GetNativeWindow()->GetHost()->GetAcceleratedWidget());
gfx::Rect fullscreen_bounds = widget1->GetWindowBoundsInScreen();
UniqueWidgetPtr widget2 = std::make_unique<Widget>();
params = CreateParams(Widget::InitParams::TYPE_WINDOW);
params.native_widget = new DesktopNativeWidgetAura(widget2.get());
widget2->Init(std::move(params));
widget2->SetBounds(gfx::Rect(0, 0, 200, 200));
widget2->Show();
widget2->Activate();
RunPendingMessages();
EXPECT_EQ(::GetActiveWindow(),
widget2->GetNativeWindow()->GetHost()->GetAcceleratedWidget());
gfx::Rect fullscreen_bounds_after_activation_loss =
widget1->GetWindowBoundsInScreen();
EXPECT_EQ(fullscreen_bounds.height() -
fullscreen_bounds_after_activation_loss.height(),
1);
widget1->Activate();
RunPendingMessages();
EXPECT_EQ(::GetActiveWindow(),
widget1->GetNativeWindow()->GetHost()->GetAcceleratedWidget());
gfx::Rect fullscreen_bounds_after_activate =
widget1->GetWindowBoundsInScreen();
EXPECT_EQ(fullscreen_bounds, fullscreen_bounds_after_activate);
}
TEST_F(WidgetTestInteractive, FullscreenMaximizedWindowBounds) {
UniqueWidgetPtr widget = std::make_unique<Widget>();
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
params.native_widget = new DesktopNativeWidgetAura(widget.get());
widget->set_frame_type(Widget::FrameType::kForceCustom);
widget->Init(std::move(params));
widget->SetBounds(gfx::Rect(0, 0, 200, 200));
widget->Show();
widget->Maximize();
EXPECT_TRUE(widget->IsMaximized());
widget->SetFullscreen(true);
EXPECT_TRUE(widget->IsFullscreen());
EXPECT_FALSE(widget->IsMaximized());
RunPendingMessages();
aura::WindowTreeHost* host = widget->GetNativeWindow()->GetHost();
HWND hwnd = host->GetAcceleratedWidget();
HMONITOR monitor = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
ASSERT_TRUE(!!monitor);
MONITORINFO monitor_info;
monitor_info.cbSize = sizeof(monitor_info);
ASSERT_TRUE(::GetMonitorInfo(monitor, &monitor_info));
gfx::Rect monitor_bounds(monitor_info.rcMonitor);
gfx::Rect window_bounds = widget->GetWindowBoundsInScreen();
gfx::Rect client_area_bounds = host->GetBoundsInPixels();
EXPECT_EQ(window_bounds, monitor_bounds);
EXPECT_EQ(monitor_bounds, client_area_bounds);
widget->SetFullscreen(false);
EXPECT_FALSE(widget->IsFullscreen());
EXPECT_TRUE(widget->IsMaximized());
client_area_bounds = host->GetBoundsInPixels();
EXPECT_TRUE(monitor_bounds.Contains(client_area_bounds));
EXPECT_NE(monitor_bounds, client_area_bounds);
}
#endif
#if BUILDFLAG(ENABLE_DESKTOP_AURA) || BUILDFLAG(IS_MAC)
TEST_F(DesktopWidgetTestInteractive, WindowModalWindowDestroyedActivationTest) { … }
#endif
TEST_F(DesktopWidgetTestInteractive, CanActivateFlagIsHonored) { … }
#if defined(USE_AURA)
TEST_F(DesktopWidgetTestInteractive, TouchSelectionQuickMenuIsNotActivated) { … }
#endif
#if BUILDFLAG(IS_WIN)
TEST_F(DesktopWidgetTestInteractive, DisableViewDoesNotActivateWidget) {
#else
TEST_F(WidgetTestInteractive, DisableViewDoesNotActivateWidget) { … }
TEST_F(WidgetTestInteractive, ShowCreatesActiveWindow) { … }
TEST_F(WidgetTestInteractive, ShowInactive) { … }
TEST_F(WidgetTestInteractive, InactiveBeforeShow) { … }
TEST_F(WidgetTestInteractive, ShowInactiveAfterShow) { … }
TEST_F(WidgetTestInteractive, ShowAfterShowInactive) { … }
TEST_F(WidgetTestInteractive, WidgetShouldBeActiveWhenShow) { … }
#if BUILDFLAG(ENABLE_DESKTOP_AURA) || BUILDFLAG(IS_MAC)
TEST_F(WidgetTestInteractive, InactiveWidgetDoesNotGrabActivation) { … }
#endif
#if BUILDFLAG(IS_MAC)
#define MAYBE_ExitFullscreenRestoreState …
#else
#define MAYBE_ExitFullscreenRestoreState …
#endif
TEST_F(WidgetTestInteractive, MAYBE_ExitFullscreenRestoreState) { … }
TEST_F(WidgetTestInteractive, InitialFocus) { … }
TEST_F(DesktopWidgetTestInteractive, RestoreAfterMinimize) { … }
#if !BUILDFLAG(IS_MAC)
TEST_F(DesktopWidgetTestInteractive, ShowAfterMaximize) { … }
#endif
#if BUILDFLAG(IS_WIN)
TEST_F(DesktopWidgetTestInteractive, RestoreAndMinimizeVisibility) {
WidgetAutoclosePtr widget(CreateTopLevelNativeWidget());
aura::Window* root_window = GetRootWindow(widget.get());
ShowSync(widget.get());
ASSERT_FALSE(widget->IsMinimized());
EXPECT_TRUE(root_window->IsVisible());
PropertyWaiter minimize_widget_waiter(
base::BindRepeating(&Widget::IsMinimized, base::Unretained(widget.get())),
true);
widget->Minimize();
EXPECT_TRUE(minimize_widget_waiter.Wait());
EXPECT_TRUE(widget->IsVisible());
EXPECT_FALSE(root_window->IsVisible());
PropertyWaiter restore_widget_waiter(
base::BindRepeating(&Widget::IsMinimized, base::Unretained(widget.get())),
false);
widget->Restore();
EXPECT_TRUE(restore_widget_waiter.Wait());
EXPECT_TRUE(widget->IsVisible());
EXPECT_TRUE(root_window->IsVisible());
}
TEST_F(DesktopWidgetTestInteractive, MinimizeAndActivateFocus) {
WidgetAutoclosePtr widget(CreateTopLevelNativeWidget());
aura::Window* root_window = GetRootWindow(widget.get());
auto* widget_window = widget->GetNativeWindow();
ShowSync(widget.get());
ASSERT_FALSE(widget->IsMinimized());
EXPECT_TRUE(root_window->IsVisible());
widget_window->Focus();
EXPECT_TRUE(widget_window->HasFocus());
widget->GetContentsView()->SetFocusBehavior(View::FocusBehavior::ALWAYS);
widget->GetContentsView()->RequestFocus();
EXPECT_TRUE(widget->GetContentsView()->HasFocus());
PropertyWaiter minimize_widget_waiter(
base::BindRepeating(&Widget::IsMinimized, base::Unretained(widget.get())),
true);
widget->Minimize();
EXPECT_TRUE(minimize_widget_waiter.Wait());
EXPECT_TRUE(widget->IsVisible());
EXPECT_FALSE(root_window->IsVisible());
PropertyWaiter restore_widget_waiter(
base::BindRepeating(&Widget::IsMinimized, base::Unretained(widget.get())),
false);
widget->Activate();
EXPECT_TRUE(widget->GetContentsView()->HasFocus());
EXPECT_TRUE(restore_widget_waiter.Wait());
EXPECT_TRUE(widget->IsVisible());
EXPECT_TRUE(root_window->IsVisible());
EXPECT_TRUE(widget_window->CanFocus());
}
class SyntheticMouseMoveCounter : public ui::EventHandler {
public:
explicit SyntheticMouseMoveCounter(Widget* widget) : widget_(widget) {
widget_->GetNativeWindow()->AddPreTargetHandler(this);
}
SyntheticMouseMoveCounter(const SyntheticMouseMoveCounter&) = delete;
SyntheticMouseMoveCounter& operator=(const SyntheticMouseMoveCounter&) =
delete;
~SyntheticMouseMoveCounter() override {
widget_->GetNativeWindow()->RemovePreTargetHandler(this);
}
void OnMouseEvent(ui::MouseEvent* event) override {
if (event->type() == ui::EventType::kMouseMoved && event->IsSynthesized()) {
++count_;
}
}
int num_synthetic_mouse_moves() const { return count_; }
private:
int count_ = 0;
raw_ptr<Widget> widget_;
};
#if BUILDFLAG(ENABLE_DESKTOP_AURA)
TEST_F(DesktopWidgetTestInteractive,
DISABLED_DoNotSynthesizeMouseMoveOnVisibilityChangeIfOccluded) {
WidgetAutoclosePtr widget_below(CreateTopLevelPlatformDesktopWidget());
widget_below->SetBounds(gfx::Rect(300, 300));
widget_below->Show();
base::RunLoop run_loop;
ui_controls::SendMouseMoveNotifyWhenDone(150, 150, run_loop.QuitClosure());
run_loop.Run();
UniqueWidgetPtr child = std::make_unique<Widget>();
Widget::InitParams child_params =
CreateParams(Widget::InitParams::TYPE_WINDOW);
child_params.parent = widget_below->GetNativeView();
child_params.context = widget_below->GetNativeWindow();
child->Init(std::move(child_params));
child->SetBounds(gfx::Rect(300, 300));
child->Show();
base::RunLoop().RunUntilIdle();
SyntheticMouseMoveCounter counter_below(widget_below.get());
EXPECT_EQ(0, counter_below.num_synthetic_mouse_moves());
child->Hide();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, counter_below.num_synthetic_mouse_moves());
WidgetAutoclosePtr widget_above(CreateTopLevelPlatformDesktopWidget());
widget_above->SetBounds(gfx::Rect(300, 300));
widget_above->Show();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(widget_above->AsWidget()->IsStackedAbove(
widget_below->AsWidget()->GetNativeView()));
child->Show();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, counter_below.num_synthetic_mouse_moves());
}
#endif
#endif
#if BUILDFLAG(ENABLE_DESKTOP_AURA) || BUILDFLAG(IS_MAC)
TEST_F(DesktopWidgetTestInteractive, EventHandlersClearedOnWidgetMinimize) { … }
#endif
#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && \
BUILDFLAG(ENABLE_DESKTOP_AURA)
TEST_F(DesktopWidgetTestInteractive,
DesktopNativeWidgetWithModalTransientChild) { … }
#endif
namespace {
class CaptureLostState { … };
class CaptureLostTrackingWidget : public Widget { … };
}
class WidgetCaptureTest : public DesktopWidgetTestInteractive { … };
TEST_F(WidgetCaptureTest, Capture) { … }
#if BUILDFLAG(ENABLE_DESKTOP_AURA) || BUILDFLAG(IS_MAC)
TEST_F(WidgetCaptureTest, CaptureDesktopNativeWidget) { … }
#endif
TEST_F(WidgetCaptureTest, DestroyWithCapture_CloseNow) { … }
TEST_F(WidgetCaptureTest, DestroyWithCapture_Close) { … }
TEST_F(WidgetCaptureTest, DestroyWithCapture_WidgetOwnsNativeWidget) { … }
TEST_F(WidgetCaptureTest, FailedCaptureRequestIsNoop) { … }
TEST_F(WidgetCaptureTest, CaptureAutoReset) { … }
TEST_F(WidgetCaptureTest, ResetCaptureOnGestureEnd) { … }
TEST_F(WidgetCaptureTest, DisableCaptureWidgetFromMousePress) { … }
TEST_F(WidgetCaptureTest, GrabUngrab) { … }
#if BUILDFLAG(IS_MAC)
#define MAYBE_SystemModalWindowReleasesCapture …
#elif BUILDFLAG(IS_CHROMEOS_ASH)
#define MAYBE_SystemModalWindowReleasesCapture …
#else
#define MAYBE_SystemModalWindowReleasesCapture …
#endif
TEST_F(WidgetCaptureTest, MAYBE_SystemModalWindowReleasesCapture) { … }
#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_MAC)
#define MAYBE_MouseExitOnCaptureGrab …
#else
#define MAYBE_MouseExitOnCaptureGrab …
#endif
TEST_F(WidgetCaptureTest, MAYBE_MouseExitOnCaptureGrab) { … }
namespace {
class CaptureOnActivationObserver : public WidgetObserver { … };
}
TEST_F(WidgetCaptureTest, SetCaptureToNonToplevel) { … }
#if BUILDFLAG(IS_WIN)
namespace {
class MouseEventTrackingWidget : public Widget {
public:
MouseEventTrackingWidget() = default;
MouseEventTrackingWidget(const MouseEventTrackingWidget&) = delete;
MouseEventTrackingWidget& operator=(const MouseEventTrackingWidget&) = delete;
~MouseEventTrackingWidget() override = default;
bool GetAndClearGotMouseEvent() {
bool value = got_mouse_event_;
got_mouse_event_ = false;
return value;
}
void OnMouseEvent(ui::MouseEvent* event) override {
got_mouse_event_ = true;
Widget::OnMouseEvent(event);
}
private:
bool got_mouse_event_ = false;
};
}
TEST_F(WidgetCaptureTest, MouseEventDispatchedToRightWindow) {
UniqueWidgetPtrT widget1 = std::make_unique<MouseEventTrackingWidget>();
Widget::InitParams params1 =
CreateParams(views::Widget::InitParams::TYPE_WINDOW);
params1.bounds = gfx::Rect(0, 0, 200, 200);
params1.native_widget = new DesktopNativeWidgetAura(widget1.get());
widget1->Init(std::move(params1));
widget1->Show();
UniqueWidgetPtrT widget2 = std::make_unique<MouseEventTrackingWidget>();
Widget::InitParams params2 =
CreateParams(views::Widget::InitParams::TYPE_WINDOW);
params2.bounds = gfx::Rect(0, 0, 200, 200);
params2.native_widget = new DesktopNativeWidgetAura(widget2.get());
widget2->Init(std::move(params2));
widget2->Show();
widget2->SetCapture(widget2->GetRootView());
EXPECT_FALSE(widget1->HasCapture());
EXPECT_TRUE(widget2->HasCapture());
widget1->GetAndClearGotMouseEvent();
widget2->GetAndClearGotMouseEvent();
ui::MouseEvent mouse_event(ui::EventType::kMouseExited, gfx::Point(),
gfx::Point(), ui::EventTimeForNow(), ui::EF_NONE,
ui::EF_NONE);
ui::EventDispatchDetails details =
widget1->GetNativeWindow()->GetHost()->GetEventSink()->OnEventFromSource(
&mouse_event);
ASSERT_FALSE(details.dispatcher_destroyed);
EXPECT_TRUE(widget1->GetAndClearGotMouseEvent());
EXPECT_FALSE(widget2->GetAndClearGotMouseEvent());
}
#endif
class WidgetInputMethodInteractiveTest : public DesktopWidgetTestInteractive { … };
#if BUILDFLAG(IS_MAC)
#define MAYBE_Activation …
#else
#define MAYBE_Activation …
#endif
TEST_F(WidgetInputMethodInteractiveTest, MAYBE_Activation) { … }
TEST_F(WidgetInputMethodInteractiveTest, OneWindow) { … }
TEST_F(WidgetInputMethodInteractiveTest, TwoWindows) { … }
TEST_F(WidgetInputMethodInteractiveTest, TextField) { … }
TEST_F(WidgetInputMethodInteractiveTest, AcceleratorInTextfield) { … }
#if BUILDFLAG(ENABLE_DESKTOP_AURA)
class DesktopWidgetDragTestInteractive : public DesktopWidgetTestInteractive,
public WidgetObserver { … };
TEST_F(DesktopWidgetDragTestInteractive, CancelShellDrag) { … }
#endif
}