// Copyright 2020 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef COMPONENTS_EXO_EXTENDED_DRAG_SOURCE_H_ #define COMPONENTS_EXO_EXTENDED_DRAG_SOURCE_H_ #include #include #include "ash/drag_drop/toplevel_window_drag_delegate.h" #include "ash/wm/toplevel_window_event_handler.h" #include "base/observer_list.h" #include "base/optional.h" #include "components/exo/data_source_observer.h" #include "ui/aura/scoped_window_event_targeting_blocker.h" #include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/point_f.h" namespace aura { class Window; } namespace gfx { class Vector2d; } namespace ui { class LocatedEvent; } namespace exo { class DataSource; class Surface; class ExtendedDragSource : public DataSourceObserver, public ash::ToplevelWindowDragDelegate { public: class Delegate { public: virtual bool ShouldAllowDropAnywhere() const = 0; virtual bool ShouldLockCursor() const = 0; virtual void OnSwallowed(const std::string& mime_type) = 0; virtual void OnUnswallowed(const std::string& mime_type, const gfx::Vector2d& offset) = 0; virtual void OnDataSourceDestroying() = 0; protected: virtual ~Delegate() = default; }; class Observer { public: virtual void OnExtendedDragSourceDestroying(ExtendedDragSource* source) = 0; protected: virtual ~Observer() = default; }; static ExtendedDragSource* Get(); ExtendedDragSource(DataSource* source, Delegate* delegate); ExtendedDragSource(const ExtendedDragSource&) = delete; ExtendedDragSource& operator=(const ExtendedDragSource&) = delete; ~ExtendedDragSource() override; void AddObserver(Observer* observer); void RemoveObserver(Observer* observer); void Drag(Surface* surface, const gfx::Vector2d& offset); bool IsActive() const; // ash::ToplevelWindowDragDelegate: void OnToplevelWindowDragStarted(const gfx::PointF& start_location, ui::mojom::DragEventSource source) override; int OnToplevelWindowDragDropped() override; void OnToplevelWindowDragCancelled() override; void OnToplevelWindowDragEvent(ui::LocatedEvent* event) override; // DataSourceObserver: void OnDataSourceDestroying(DataSource* source) override; aura::Window* GetDraggedWindowForTesting(); base::Optional GetDragOffsetForTesting() const; private: class DraggedWindowHolder; void MaybeLockCursor(); void UnlockCursor(); void StartDrag(aura::Window* toplevel, const gfx::PointF& pointer_location_in_screen); void OnDraggedWindowVisibilityChanging(bool visible); gfx::Point CalculateOrigin(aura::Window* target) const; void Cleanup(); static ExtendedDragSource* instance_; DataSource* source_ = nullptr; // Created and destroyed at wayland/zcr_extended_drag.cc and its lifetime is // tied to the zcr_extended_drag_source_v1 object it's attached to. Delegate* const delegate_; gfx::PointF pointer_location_; ui::mojom::DragEventSource drag_event_source_; bool cursor_locked_ = false; std::unique_ptr dragged_window_holder_; std::unique_ptr event_blocker_; base::ObserverList::Unchecked observers_; base::WeakPtrFactory weak_factory_{this}; }; } // namespace exo #endif // COMPONENTS_EXO_EXTENDED_DRAG_SOURCE_H_