// 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