| // Copyright 2016 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 SERVICES_UI_WS_DRAG_CONTROLLER_H_ |
| #define SERVICES_UI_WS_DRAG_CONTROLLER_H_ |
| |
| #include <map> |
| #include <set> |
| |
| #include "base/memory/weak_ptr.h" |
| #include "services/ui/common/types.h" |
| #include "services/ui/public/interfaces/cursor.mojom.h" |
| #include "services/ui/ws/ids.h" |
| #include "services/ui/ws/server_window_observer.h" |
| |
| namespace ui { |
| namespace ws { |
| |
| namespace test { |
| class DragControllerTestApi; |
| } |
| |
| class DragCursorUpdater; |
| class DragSource; |
| class DragTargetConnection; |
| |
| // A single ui::mojom::kDropEffect operation. |
| using DropEffect = uint32_t; |
| |
| // A bitmask of ui::mojom::kDropEffect operations. |
| using DropEffectBitmask = uint32_t; |
| |
| // Represents all the data around the current ongoing drag operation. |
| // |
| // There should only be one instance of this class per userid. The |
| // WindowManagerState's EventDispatcher creates and owns this instance. |
| class DragController : public ServerWindowObserver { |
| public: |
| DragController( |
| DragCursorUpdater* cursor_updater, |
| DragSource* source, |
| ServerWindow* source_window, |
| DragTargetConnection* source_connection, |
| int32_t drag_pointer, |
| const std::unordered_map<std::string, std::vector<uint8_t>>& mime_data, |
| DropEffectBitmask drag_operations); |
| ~DragController() override; |
| |
| ui::mojom::Cursor current_cursor() const { return current_cursor_; } |
| |
| // Cancels the current drag, ie, due to the user pressing Escape. |
| void Cancel(); |
| |
| // Responds to a pointer move/release event. Returns true if the event was |
| // handled by the drag. |
| bool DispatchPointerEvent(const ui::PointerEvent& event, |
| ServerWindow* current_target); |
| |
| void OnWillDestroyDragTargetConnection(DragTargetConnection* connection); |
| |
| private: |
| friend class test::DragControllerTestApi; |
| enum class OperationType { NONE, ENTER, OVER, LEAVE, DROP }; |
| struct Operation; |
| struct WindowState; |
| |
| // Notifies all windows we messaged that the drag is finished, and then tell |
| // |source| the result. |
| void MessageDragCompleted(bool success, DropEffect action_taken); |
| |
| // Returns the number of events on |window|. A value of 1 means that there's |
| // a single event outstanding that we're waiting for a response from the |
| // client, all values over 1 are queued and will be dispatched when the event |
| // in the front of the queue gets a response. |
| size_t GetSizeOfQueueForWindow(ServerWindow* window); |
| |
| // Sets |current_target_window_| to |current_target|, making sure that we add |
| // and release ServerWindow observers correctly. |
| void SetCurrentTargetWindow(ServerWindow* current_target); |
| |
| // Updates the possible cursor effects for |window|. |bitmask| is a |
| // bitmask of the current valid drag operations. |
| void SetWindowDropOperations(ServerWindow* window, DropEffectBitmask bitmask); |
| |
| // Returns the ui::mojom::Cursor for the window |bitmask|, adjusted for types |
| // that the drag source allows. |
| ui::mojom::Cursor CursorForEffectBitmask(DropEffectBitmask bitmask); |
| |
| // Ensure that |window| has an entry in |window_state_| and that we're an |
| // observer. |
| void EnsureWindowObserved(ServerWindow* window); |
| |
| void QueueOperation(ServerWindow* window, |
| OperationType type, |
| uint32_t event_flags, |
| const gfx::Point& screen_position); |
| void DispatchOperation(ServerWindow* window, WindowState* state); |
| void OnRespondToOperation(ServerWindow* window); |
| |
| // Callback methods. |
| void OnDragStatusCompleted(const WindowId& id, DropEffectBitmask bitmask); |
| void OnDragDropCompleted(const WindowId& id, DropEffect action); |
| |
| // ServerWindowObserver: |
| void OnWindowDestroying(ServerWindow* window) override; |
| |
| // Our owner. |
| DragSource* source_; |
| |
| // Object to notify about all cursor changes. |
| DragCursorUpdater* cursor_updater_; |
| |
| // A bit-field of acceptable drag operations offered by the source. |
| const DropEffectBitmask drag_operations_; |
| |
| // Only act on pointer events that meet this id. |
| const int32_t drag_pointer_id_; |
| |
| // The current mouse cursor during the drag. |
| ui::mojom::Cursor current_cursor_; |
| |
| // Sending OnDragOver() to our |source_| destroys us; there is a period where |
| // we have to continue to exist, but not process any more pointer events. |
| bool waiting_for_final_drop_response_ = false; |
| |
| ServerWindow* source_window_; |
| ServerWindow* current_target_window_ = nullptr; |
| |
| // The target connection that |source_window_| is part of. |
| DragTargetConnection* source_connection_; |
| |
| // A list of the offered mime types. |
| std::unordered_map<std::string, std::vector<uint8_t>> mime_data_; |
| |
| // We need to keep track of state on a per window basis. A window being in |
| // this map means that we're observing it. WindowState also keeps track of |
| // what type of operation we're waiting for a response from the window's |
| // client, along with a queued operation to send when we get a reply. |
| std::map<ServerWindow*, WindowState> window_state_; |
| |
| // A set of DragTargetConnections* which have received the |
| // PerformOnDragMimeTypes() call. |
| std::set<DragTargetConnection*> called_on_drag_mime_types_; |
| |
| base::WeakPtrFactory<DragController> weak_factory_; |
| |
| DISALLOW_COPY_AND_ASSIGN(DragController); |
| }; |
| |
| } // namespace ws |
| } // namespace ui |
| |
| #endif // SERVICES_UI_WS_DRAG_CONTROLLER_H_ |