// 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.
#ifndef ASH_DRAG_DROP_TAB_DRAG_DROP_DELEGATE_H_
#define ASH_DRAG_DROP_TAB_DRAG_DROP_DELEGATE_H_
#include <memory>
#include "ash/ash_export.h"
#include "ash/drag_drop/drag_drop_capture_delegate.h"
#include "ash/drag_drop/tab_drag_drop_windows_hider.h"
#include "ash/wm/splitview/split_view_controller.h"
#include "ash/wm/splitview/split_view_types.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "ui/aura/window_observer.h"
namespace aura {
class Window;
}
namespace ui {
class OSExchangeData;
class Point;
class PresentationTimeRecorder;
} // namespace ui
namespace ash {
class SplitViewDragIndicators;
class TabDragDropWindowsHider;
// Provides special handling for Chrome tab drags on behalf of
// DragDropController. This must be created at the beginning of a tab drag and
// destroyed at the end.
class ASH_EXPORT TabDragDropDelegate : public DragDropCaptureDelegate,
public aura::WindowObserver {
public:
// Determines whether |drag_data| indicates a tab drag from a WebUI tab strip
// (or simply returns false if the integration is disabled).
static bool IsChromeTabDrag(const ui::OSExchangeData& drag_data);
// Returns whether a tab from |window| is actively being dragged.
static bool IsSourceWindowForDrag(const aura::Window* window);
// |root_window| is the root window from which the drag originated. The drag
// is expected to stay in |root_window|. |source_window| is the Chrome window
// the tab was dragged from. |start_location_in_screen| is the location of
// the touch or click that started the drag.
TabDragDropDelegate(aura::Window* root_window,
aura::Window* source_window,
const gfx::Point& start_location_in_screen);
~TabDragDropDelegate() override;
TabDragDropDelegate(const TabDragDropDelegate&) = delete;
TabDragDropDelegate& operator=(const TabDragDropDelegate&) = delete;
const aura::Window* root_window() const { return root_window_; }
// Must be called on every drag update.
void DragUpdate(const gfx::Point& location_in_screen);
// Must be called on drop if it was not accepted by the drop target. After
// calling this, this delegate must not be used.
void DropAndDeleteSelf(const gfx::Point& location_in_screen,
const ui::OSExchangeData& drop_data);
// Overridden from aura::WindowObserver.
void OnWindowDestroying(aura::Window* window) override;
private:
FRIEND_TEST_ALL_PREFIXES(TabDragDropDelegateTest, DropWithoutNewWindow);
// Scales or transforms the source window if appropriate for this drag.
// |candidate_snap_position| is where the dragged tab will be snapped
// if dropped immediately.
void UpdateSourceWindowBoundsIfNecessary(
SnapPosition candidate_snap_position,
const gfx::Point& location_in_screen);
// Puts the source window back into its original position.
void RestoreSourceWindowBounds();
// Effectively handles the new window creation in DropAndDeleteSelf(). This
// method can be called asynchronously in case of Lacros.
void OnNewBrowserWindowCreated(const gfx::Point& location_in_screen,
aura::Window* new_window);
// This method returns true when all of the conditions below are met
//
// - Not in split view mode
// - In landscape mode
// - The current drag location is inside the WebUI tab strip
//
// When it returns true, we don't allow to enter split view because
// it hinders dragging tabs within the tab strip to trigger auto-scroll.
// This restriction does not apply to split screen mode because either
// the left/right could be non browser window, which may lead to
// confusing behavior.
// It also does not apply to portrait mode because dragging up/down to
// enter split screen does not hinder dragging left/right to move tabs.
//
// https://crbug.com/1316070
bool ShouldPreventSnapToTheEdge(const gfx::Point& location_in_screen);
const raw_ptr<aura::Window> root_window_;
raw_ptr<aura::Window> source_window_;
const gfx::Point start_location_in_screen_;
std::unique_ptr<SplitViewDragIndicators> split_view_drag_indicators_;
std::unique_ptr<TabDragDropWindowsHider> windows_hider_;
// Presentation time recorder for tab dragging in tablet mode with webui
// tab strip enable.
std::unique_ptr<ui::PresentationTimeRecorder> tab_dragging_recorder_;
};
} // namespace ash
#endif // ASH_DRAG_DROP_TAB_DRAG_DROP_DELEGATE_H_