chromium/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc

// Copyright 2020 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/ozone/platform/wayland/host/wayland_window_drag_controller.h"

#include <linux/input-event-codes.h>
#include <wayland-server-protocol.h>
#include <wayland-server.h>
#include <wayland-util.h>
#include <xdg-shell-server-protocol.h>

#include <cstdint>

#include "base/functional/bind.h"
#include "base/notreached.h"
#include "base/test/bind.h"
#include "base/test/mock_callback.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/event.h"
#include "ui/events/types/event_type.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/ozone/platform/wayland/host/wayland_cursor_position.h"
#include "ui/ozone/platform/wayland/host/wayland_data_device.h"
#include "ui/ozone/platform/wayland/host/wayland_event_source.h"
#include "ui/ozone/platform/wayland/host/wayland_output.h"
#include "ui/ozone/platform/wayland/host/wayland_output_manager.h"
#include "ui/ozone/platform/wayland/host/wayland_screen.h"
#include "ui/ozone/platform/wayland/host/wayland_serial_tracker.h"
#include "ui/ozone/platform/wayland/host/wayland_toplevel_window.h"
#include "ui/ozone/platform/wayland/host/wayland_window.h"
#include "ui/ozone/platform/wayland/host/wayland_window_manager.h"
#include "ui/ozone/platform/wayland/test/mock_pointer.h"
#include "ui/ozone/platform/wayland/test/mock_surface.h"
#include "ui/ozone/platform/wayland/test/mock_wayland_platform_window_delegate.h"
#include "ui/ozone/platform/wayland/test/scoped_wl_array.h"
#include "ui/ozone/platform/wayland/test/test_data_device.h"
#include "ui/ozone/platform/wayland/test/test_data_device_manager.h"
#include "ui/ozone/platform/wayland/test/test_data_offer.h"
#include "ui/ozone/platform/wayland/test/test_data_source.h"
#include "ui/ozone/platform/wayland/test/test_output.h"
#include "ui/ozone/platform/wayland/test/test_wayland_server_thread.h"
#include "ui/ozone/platform/wayland/test/test_zaura_toplevel.h"
#include "ui/ozone/platform/wayland/test/wayland_drag_drop_test.h"
#include "ui/ozone/platform/wayland/test/wayland_test.h"
#include "ui/platform_window/extensions/wayland_extension.h"
#include "ui/platform_window/platform_window_delegate.h"
#include "ui/platform_window/wm/wm_move_loop_handler.h"

_;
Mock;
Values;

namespace ui {

DragEventSource;

class WaylandWindowDragControllerTest : public WaylandDragDropTest {};

// Check the following flow works as expected:
// 1. With a single 1 window open,
// 2. Move pointer into it, press left button, move cursor a bit (drag),
// 3. Run move loop, drag it within the window bounds and drop.
TEST_P(WaylandWindowDragControllerTest, DragInsideWindowAndDrop) {}

// Check the following flow works as expected:
// 1. With a single window open,
// 2. Touch down and move the touch point a bit (drag),
// 3. Run move loop, drag it within the window bounds and drop.
TEST_P(WaylandWindowDragControllerTest, DragInsideWindowAndDrop_TOUCH) {}

// Similar to DragInsideWindowAndDrop_TOUCH but with two fingers.
TEST_P(WaylandWindowDragControllerTest, DragInsideWindowAndDropTwoFingerTouch) {}

// Check the following flow works as expected:
// 1. Start dragging  window_2 with touch.
// 2. Emulate |window_2| being closed manually by the user (eg control+w).
// 3. No crash observed.
TEST_P(WaylandWindowDragControllerTest, DestroyWindowDuringDragAndDrop_TOUCH) {}

// Check the following flow works as expected:
// 1. With two windows open,
// 2. Touch down and start drag a window,
// 3. Emulate the compositor sending an unexpected `pointer enter` event
//   to another window, when the drag is ongoing.
//
// NOTE: This bug isn't noticed on DUT, but seems to be frequent on ash/chrome
// linux desktop builds (with ozone/x11 underneath).
TEST_P(WaylandWindowDragControllerTest,
       DragAndDropWithExtraneousPointerEnterEvent_TOUCH) {}

// Check the following flow works as expected:
// 1. With only 1 window open;
// 2. Move pointer into it, press left button, move cursor a bit (drag);
// 3. Run move loop,
// 4. Drag pointer to outside the window and release the mouse button, and make
//    sure RELEASE and EXIT mouse events are delivered even when the drop
//    happens outside the bounds of any surface.
TEST_P(WaylandWindowDragControllerTest, DragExitWindowAndDrop) {}

// Check the following flow works as expected:
// 1. With 2 windows open,
// 2. Focus window 1, starts dragging,
// 3. Run move loop,
// 4. Drag the pointer out of window 1 and then into window 2,
// 5. Drag it a bit more (within window 2) and then calls EndMoveLoop(),
//    emulating a window snap), and then
// 6. With the window in "snapped" state, drag it further and then drop.
// TODO(crbug.com/40886646): Test needs to be updated for 112.0.5570.0 to remove
// special handling logic in wayland_pointer.cc.
TEST_P(WaylandWindowDragControllerTest, DragToOtherWindowSnapDragDrop) {}

// Check the following flow works as expected:
// 1. With 2 windows open,
// 2. Focus window 1, starts dragging,
// 3. Run move loop,
// 4. Drag the pointer out of window 1 and then into window 2,
// 5. Drag it a bit more (within window 2) and then calls EndMoveLoop(),
//    emulating a window snap), and then
// 6. With the window in "snapped" state, drag it further and then drop.
TEST_P(WaylandWindowDragControllerTest, DragToOtherWindowSnapDragDrop_TOUCH) {}

// Check the following flow works as expected:
// 1. With 2 windows open,
// 2. Focus window 1, starts dragging,
// 3. Run move loop,
// 4. Drag the pointer out of window 1 and then into window 2,
// 5. Simulate a spurious `wl_pointer.enter` event from the server
//    during the dnd operation. It should be ignored...
// 6. Drag it a bit more (within window 2) and then calls EndMoveLoop(),
//    emulating a window snap), and then drop.
// TODO(crbug.com/40886646): Test needs to be updated for 112.0.5570.0 to remove
// special handling logic in wayland_pointer.cc.
TEST_P(WaylandWindowDragControllerTest,
       DragToOtherWindowIgnoringSpuriousPointerEnterEvent) {}

// Verifies wl_data_device::leave events are properly handled and propagated
// while in window dragging "attached" mode.
TEST_P(WaylandWindowDragControllerTest, DragExitAttached) {}

// Verifies wl_data_device::leave events are properly handled and propagated
// while in window dragging "attached" mode.
TEST_P(WaylandWindowDragControllerTest, DragExitAttached_TOUCH) {}

BoundsChange;

TEST_P(WaylandWindowDragControllerTest, RestoreDuringWindowDragSession) {}

// Check the following flow works as expected:
//
// 1. With a single 1 window open,
// 2. Move pointer into it, press left button, move cursor a bit (drag),
// 3. Run move loop, drag it from 200,200 location to 100,100
// 4. Send a few wl_pointer::motion events targeting 20,20 location and ensure
//    they are ignored (i.e: window bounds keep unchanged) until drop happens.
//
// Verifies window drag controller is resistant to issues such as
// https://crbug.com/1148021.
TEST_P(WaylandWindowDragControllerTest, IgnorePointerEventsUntilDrop) {}

// Regression test for https://crbug.com/1169446.
TEST_P(WaylandWindowDragControllerTest, MotionEventsSkippedWhileReattaching) {}

// Test that cursor position is using DIP coordinates and is updated correctly
// on DragMotion event.
TEST_P(WaylandWindowDragControllerTest, CursorPositionIsUpdatedOnMotion) {}

// Ensure no memory issues happen when the dragged window is destroyed just
// after quitting the move loop. Regression test for crbug.com/1267791 and
// should be caught in both regular and ASAN builds, where more details about
// the actual memory issue is provided.
TEST_P(WaylandWindowDragControllerTest,
       HandleDraggedWindowDestructionAfterMoveLoop) {}

// Ensure no memory issues happen when the dragged and/or events grabber windows
// get destroyed while the move loop is running.
TEST_P(WaylandWindowDragControllerTest,
       HandleWindowsDestructionDuringMoveLoop) {}

// Ensures correct behavior when ext-drag protocol is not available, such as:
//
// 1. Returns 'success' even when wl_data_source.cancelled is sent by the
//    Wayland Compositor.
//
//  Regression test for https://crbug.com/1366504.
TEST_P(WaylandWindowDragControllerTest, ExtendedDragUnavailable) {}

TEST_P(WaylandWindowDragControllerTest, GetSerial) {}

TEST_P(WaylandWindowDragControllerTest, NoopUnlessPointerOrTouchPressed) {}

// Ensure events are handled appropriately when the target window is destroyed
// while the move loop is running (i.e. dragging in the detached state).
// Regression test for crbug.com/1433577.
TEST_P(WaylandWindowDragControllerTest,
       HandleTargetWindowDestruction_DetachedState) {}

// Ensure events are handled appropriately when the target window is destroyed
// while dragging a tab attached to the window (i.e. dragging in the attached
// state).
// Regression test for crbug.com/1433577.
TEST_P(WaylandWindowDragControllerTest,
       HandleTargetWindowDestruction_AttachedState) {}

TEST_P(WaylandWindowDragControllerTest,
       PointerReleaseBeforeServerAckCancellsDrag) {}

TEST_P(WaylandWindowDragControllerTest,
       TouchReleaseBeforeServerAckCancellsDrag) {}

// Regression test for b/336321329. Ensures all pressed mouse buttons are
// released when the window drag ends.
TEST_P(WaylandWindowDragControllerTest, AllPointersReleasedAfterDragEnd) {}

// Regression test for crbug.com/330274075. There are circumstances under which
// compositors will not send a send data_source.dnd_finish|cancelled for a
// wayland drag session. This can result in a data drag leaving the shared state
// in the data device in an inconsistent state. If a window drag session is
// requested while in such an inconsistent state this shared state must first be
// reset.
TEST_P(WaylandWindowDragControllerTest, OutgoingSessionWithoutDndFinished) {}

#if !BUILDFLAG(IS_CHROMEOS_LACROS)
// Lacros requires aura shell.
INSTANTIATE_TEST_SUITE_P();
#else
// Linux shouldn't use aura shell.
INSTANTIATE_TEST_SUITE_P(
    XdgVersionStableTestWithAuraShell,
    WaylandWindowDragControllerTest,
    Values(wl::ServerConfig{
        .enable_aura_shell = wl::EnableAuraShellProtocol::kEnabled}));
#endif

}  // namespace ui