1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#pragma once
4
5#include "BsCorePrerequisites.h"
6#include <X11/X.h>
7#include <X11/Xlib.h>
8
9namespace bs
10{
11 /** Handles X11 drag and drop functionality. */
12 class LinuxDragAndDrop
13 {
14 /** Possible states of the DND manager. */
15 enum class State
16 {
17 Inactive,
18 Entered,
19 Active
20 };
21
22 /** Type of drag and drop operation. */
23 enum class DragAndDropOpType
24 {
25 Enter,
26 DragOver,
27 Drop,
28 Leave
29 };
30
31 /** Structure describing a drag and drop operation. */
32 struct DragAndDropOp
33 {
34 DragAndDropOp(DragAndDropOpType type, DropTarget* target)
35 :type(type), target(target)
36 { }
37
38 DragAndDropOp(DragAndDropOpType type, DropTarget* target, const Vector2I& pos)
39 :type(type), target(target), position(pos)
40 { }
41
42 DragAndDropOp(DragAndDropOpType type, DropTarget* target, const Vector2I& pos,
43 const Vector<Path>& fileList)
44 :type(type), target(target), position(pos), fileList(fileList)
45 { }
46
47 DragAndDropOpType type;
48 DropTarget* target;
49 Vector2I position;
50 Vector<Path> fileList;
51 };
52
53 /** Represents a single registered drop area. */
54 struct DropArea
55 {
56 DropArea(DropTarget* target, const Rect2I& area)
57 :target(target), area(area)
58 { }
59
60 DropTarget* target;
61 Rect2I area;
62 };
63
64 /** Type of operations that can happen to a DropArea. */
65 enum class DropAreaOpType
66 {
67 Register, /**< New DropArea is being registered. */
68 Unregister, /**< DropArea is being unregistered. */
69 Update /**< DropArea was updated. */
70 };
71
72 /** Operation that in some way modifies a DropArea. */
73 struct DropAreaOp
74 {
75 DropAreaOp(DropTarget* target, DropAreaOpType type, const Rect2I& area = Rect2I::EMPTY)
76 :target(target), area(area), type(type)
77 { }
78
79 DropTarget* target;
80 Rect2I area;
81 DropAreaOpType type;
82 };
83
84 public:
85 /**
86 * Initializes the drag and drop system. Must be called before any other drag and drop methods are called.
87 *
88 * @note Core thread only.
89 */
90 static void startUp(::Display* xDisplay);
91
92 /**
93 * Shuts down the drag and drop system. Should be called after no more calls to the system are expected.
94 *
95 * @note Core thread only.
96 */
97 static void shutDown();
98
99 /**
100 * Triggers any drag and drop events.
101 *
102 * @note Sim thread only.
103 */
104 static void update();
105
106 /**
107 * Marks an X11 window as drag and drop aware (being able to accept and send drag and drop events).
108 *
109 * @note Core thread only.
110 */
111 static void makeDNDAware(::Window xWindow);
112
113 /**
114 * Registers a new drop target Any further events processed will take this target into account, trigger its event
115 * and populate its data if a drop occurs.
116 *
117 * @note Thread safe.
118 */
119 static void registerDropTarget(DropTarget* target);
120
121 /**
122 * Updates information about previous registered DropTarget. Call this when drop target area changes.
123 *
124 * @note Thread safe.
125 */
126 static void updateDropTarget(DropTarget* target);
127
128 /**
129 * Unregisters a drop target. Its events will no longer be triggered.
130 *
131 * @note Thread safe.
132 */
133 static void unregisterDropTarget(DropTarget* target);
134
135 /**
136 * Processes X11 ClientMessage event and handles any messages relating to drag and drop. Returns true if a message
137 * was handled, or false if it needs to be handled by the caller.
138 *
139 * @note Core thread only.
140 */
141 static bool handleClientMessage(XClientMessageEvent& event);
142
143 /**
144 * Processes X11 SelectionNotify event and handles it if it relates to drag and drop. Returns true if the event was
145 * handled, or false otherwise.
146 *
147 * @note Core thread only.
148 */
149 static bool handleSelectionNotify(XSelectionEvent& event);
150
151 private:
152 static ::Display* sXDisplay;
153 static bool sDragActive;
154 static Vector<DropArea> sDropAreas;
155 static Mutex sMutex;
156 static INT32 sDNDVersion;
157 static Atom sDNDType;
158 static ::Window sDNDSource;
159 static Vector2I sDragPosition;
160 static Vector<DragAndDropOp> sQueuedOperations;
161 static Vector<DropAreaOp> sQueuedAreaOperations;
162
163 // Awareness
164 static Atom sXdndAware;
165
166 // Selection handling
167 static Atom sXdndSelection;
168
169 // Client messages
170 static Atom sXdndEnter;
171 static Atom sXdndLeave;
172 static Atom sXdndPosition;
173 static Atom sXdndStatus;
174 static Atom sXdndDrop;
175 static Atom sXdndFinished;
176
177 // Actions
178 static Atom sXdndActionCopy;
179
180 // Type list
181 static Atom sXdndTypeList;
182
183 // Other
184 static Atom sPRIMARY;
185 };
186}
187
188