Changeset View
Changeset View
Standalone View
Standalone View
src/server/datadevice_interface.cpp
Show All 13 Lines | |||||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | Lesser General Public License for more details. | 15 | Lesser General Public License for more details. | ||
16 | 16 | | |||
17 | You should have received a copy of the GNU Lesser General Public | 17 | You should have received a copy of the GNU Lesser General Public | ||
18 | License along with this library. If not, see <http://www.gnu.org/licenses/>. | 18 | License along with this library. If not, see <http://www.gnu.org/licenses/>. | ||
19 | *********************************************************************/ | 19 | *********************************************************************/ | ||
20 | #include "datadevice_interface.h" | 20 | #include "datadevice_interface.h" | ||
21 | #include "datadevicemanager_interface.h" | 21 | #include "datadevicemanager_interface.h" | ||
22 | #include "dataoffer_interface.h" | 22 | #include "dataoffer_interface_p.h" | ||
23 | #include "datasource_interface.h" | 23 | #include "datasource_interface.h" | ||
24 | #include "display.h" | 24 | #include "display.h" | ||
25 | #include "resource_p.h" | 25 | #include "resource_p.h" | ||
26 | #include "pointer_interface.h" | 26 | #include "pointer_interface.h" | ||
27 | #include "seat_interface.h" | 27 | #include "seat_interface.h" | ||
28 | #include "surface_interface.h" | 28 | #include "surface_interface.h" | ||
29 | // Wayland | 29 | // Wayland | ||
30 | #include <wayland-server.h> | 30 | #include <wayland-server.h> | ||
Show All 19 Lines | 39 | public: | |||
50 | DataSourceInterface *selection = nullptr; | 50 | DataSourceInterface *selection = nullptr; | ||
51 | QMetaObject::Connection selectionUnboundConnection; | 51 | QMetaObject::Connection selectionUnboundConnection; | ||
52 | QMetaObject::Connection selectionDestroyedConnection; | 52 | QMetaObject::Connection selectionDestroyedConnection; | ||
53 | 53 | | |||
54 | struct Drag { | 54 | struct Drag { | ||
55 | SurfaceInterface *surface = nullptr; | 55 | SurfaceInterface *surface = nullptr; | ||
56 | QMetaObject::Connection destroyConnection; | 56 | QMetaObject::Connection destroyConnection; | ||
57 | QMetaObject::Connection pointerPosConnection; | 57 | QMetaObject::Connection pointerPosConnection; | ||
58 | QMetaObject::Connection sourceActionConnection; | ||||
59 | QMetaObject::Connection targetActionConnection; | ||||
58 | quint32 serial = 0; | 60 | quint32 serial = 0; | ||
59 | }; | 61 | }; | ||
60 | Drag drag; | 62 | Drag drag; | ||
61 | 63 | | |||
62 | private: | 64 | private: | ||
63 | DataDeviceInterface *q_func() { | 65 | DataDeviceInterface *q_func() { | ||
64 | return reinterpret_cast<DataDeviceInterface*>(q); | 66 | return reinterpret_cast<DataDeviceInterface*>(q); | ||
65 | } | 67 | } | ||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Line(s) | 117 | { | |||
116 | Q_UNUSED(client) | 118 | Q_UNUSED(client) | ||
117 | Q_UNUSED(serial) | 119 | Q_UNUSED(serial) | ||
118 | // TODO: verify serial | 120 | // TODO: verify serial | ||
119 | cast<Private>(resource)->setSelection(DataSourceInterface::get(source)); | 121 | cast<Private>(resource)->setSelection(DataSourceInterface::get(source)); | ||
120 | } | 122 | } | ||
121 | 123 | | |||
122 | void DataDeviceInterface::Private::setSelection(DataSourceInterface *dataSource) | 124 | void DataDeviceInterface::Private::setSelection(DataSourceInterface *dataSource) | ||
123 | { | 125 | { | ||
126 | if (dataSource->supportedDragAndDropActions()) { | ||||
127 | wl_resource_post_error(dataSource->resource(), WL_DATA_SOURCE_ERROR_INVALID_SOURCE, "Data source is for drag and drop"); | ||||
128 | return; | ||||
129 | } | ||||
124 | Q_Q(DataDeviceInterface); | 130 | Q_Q(DataDeviceInterface); | ||
125 | QObject::disconnect(selectionUnboundConnection); | 131 | QObject::disconnect(selectionUnboundConnection); | ||
126 | QObject::disconnect(selectionDestroyedConnection); | 132 | QObject::disconnect(selectionDestroyedConnection); | ||
127 | if (selection) { | 133 | if (selection) { | ||
128 | selection->cancel(); | 134 | selection->cancel(); | ||
129 | } | 135 | } | ||
130 | selection = dataSource; | 136 | selection = dataSource; | ||
131 | if (selection) { | 137 | if (selection) { | ||
▲ Show 20 Lines • Show All 95 Lines • ▼ Show 20 Line(s) | |||||
227 | 233 | | |||
228 | void DataDeviceInterface::drop() | 234 | void DataDeviceInterface::drop() | ||
229 | { | 235 | { | ||
230 | Q_D(); | 236 | Q_D(); | ||
231 | if (!d->resource) { | 237 | if (!d->resource) { | ||
232 | return; | 238 | return; | ||
233 | } | 239 | } | ||
234 | wl_data_device_send_drop(d->resource); | 240 | wl_data_device_send_drop(d->resource); | ||
241 | if (d->drag.pointerPosConnection) { | ||||
242 | disconnect(d->drag.pointerPosConnection); | ||||
243 | d->drag.pointerPosConnection = QMetaObject::Connection(); | ||||
244 | } | ||||
245 | disconnect(d->drag.destroyConnection); | ||||
246 | d->drag.destroyConnection = QMetaObject::Connection(); | ||||
247 | d->drag.surface = nullptr; | ||||
235 | client()->flush(); | 248 | client()->flush(); | ||
236 | } | 249 | } | ||
237 | 250 | | |||
238 | void DataDeviceInterface::updateDragTarget(SurfaceInterface *surface, quint32 serial) | 251 | void DataDeviceInterface::updateDragTarget(SurfaceInterface *surface, quint32 serial) | ||
239 | { | 252 | { | ||
240 | Q_D(); | 253 | Q_D(); | ||
241 | if (d->drag.surface) { | 254 | if (d->drag.surface) { | ||
242 | if (d->resource && d->drag.surface->resource()) { | 255 | if (d->resource && d->drag.surface->resource()) { | ||
243 | wl_data_device_send_leave(d->resource); | 256 | wl_data_device_send_leave(d->resource); | ||
244 | } | 257 | } | ||
245 | if (d->drag.pointerPosConnection) { | 258 | if (d->drag.pointerPosConnection) { | ||
246 | disconnect(d->drag.pointerPosConnection); | 259 | disconnect(d->drag.pointerPosConnection); | ||
247 | d->drag.pointerPosConnection = QMetaObject::Connection(); | 260 | d->drag.pointerPosConnection = QMetaObject::Connection(); | ||
248 | } | 261 | } | ||
249 | disconnect(d->drag.destroyConnection); | 262 | disconnect(d->drag.destroyConnection); | ||
250 | d->drag.destroyConnection = QMetaObject::Connection(); | 263 | d->drag.destroyConnection = QMetaObject::Connection(); | ||
251 | d->drag.surface = nullptr; | 264 | d->drag.surface = nullptr; | ||
265 | if (d->drag.sourceActionConnection) { | ||||
266 | disconnect(d->drag.sourceActionConnection); | ||||
267 | d->drag.sourceActionConnection = QMetaObject::Connection(); | ||||
268 | } | ||||
269 | if (d->drag.targetActionConnection) { | ||||
270 | disconnect(d->drag.targetActionConnection); | ||||
271 | d->drag.targetActionConnection = QMetaObject::Connection(); | ||||
272 | } | ||||
252 | // don't update serial, we need it | 273 | // don't update serial, we need it | ||
253 | } | 274 | } | ||
254 | if (!surface) { | 275 | if (!surface) { | ||
276 | d->seat->dragSource()->dragSource()->dndAction(DataDeviceManagerInterface::DnDAction::None); | ||||
255 | return; | 277 | return; | ||
256 | } | 278 | } | ||
257 | DataOfferInterface *offer = d->createDataOffer(d->seat->dragSource()->dragSource()); | 279 | auto *source = d->seat->dragSource()->dragSource(); | ||
280 | DataOfferInterface *offer = d->createDataOffer(source); | ||||
258 | d->drag.surface = surface; | 281 | d->drag.surface = surface; | ||
259 | if (d->seat->isDragPointer()) { | 282 | if (d->seat->isDragPointer()) { | ||
260 | d->drag.pointerPosConnection = connect(d->seat, &SeatInterface::pointerPosChanged, this, | 283 | d->drag.pointerPosConnection = connect(d->seat, &SeatInterface::pointerPosChanged, this, | ||
261 | [this] { | 284 | [this] { | ||
262 | Q_D(); | 285 | Q_D(); | ||
263 | const QPointF pos = d->seat->dragSurfaceTransformation().map(d->seat->pointerPos()); | 286 | const QPointF pos = d->seat->dragSurfaceTransformation().map(d->seat->pointerPos()); | ||
264 | wl_data_device_send_motion(d->resource, d->seat->timestamp(), | 287 | wl_data_device_send_motion(d->resource, d->seat->timestamp(), | ||
265 | wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y())); | 288 | wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y())); | ||
Show All 14 Lines | 295 | [this] { | |||
280 | d->drag = Private::Drag(); | 303 | d->drag = Private::Drag(); | ||
281 | } | 304 | } | ||
282 | ); | 305 | ); | ||
283 | 306 | | |||
284 | // TODO: handle touch position | 307 | // TODO: handle touch position | ||
285 | const QPointF pos = d->seat->dragSurfaceTransformation().map(d->seat->pointerPos()); | 308 | const QPointF pos = d->seat->dragSurfaceTransformation().map(d->seat->pointerPos()); | ||
286 | wl_data_device_send_enter(d->resource, serial, surface->resource(), | 309 | wl_data_device_send_enter(d->resource, serial, surface->resource(), | ||
287 | wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y()), offer ? offer->resource() : nullptr); | 310 | wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y()), offer ? offer->resource() : nullptr); | ||
311 | if (offer) { | ||||
312 | offer->d_func()->sendSourceActions(); | ||||
313 | auto matchOffers = [source, offer] { | ||||
314 | DataDeviceManagerInterface::DnDAction action{DataDeviceManagerInterface::DnDAction::None}; | ||||
315 | if (source->supportedDragAndDropActions().testFlag(offer->preferredDragAndDropAction())) { | ||||
316 | action = offer->preferredDragAndDropAction(); | ||||
317 | } else { | ||||
318 | if (source->supportedDragAndDropActions().testFlag(DataDeviceManagerInterface::DnDAction::Copy) && | ||||
319 | offer->supportedDragAndDropActions().testFlag(DataDeviceManagerInterface::DnDAction::Copy)) { | ||||
320 | action = DataDeviceManagerInterface::DnDAction::Copy; | ||||
321 | } else if (source->supportedDragAndDropActions().testFlag(DataDeviceManagerInterface::DnDAction::Move) && | ||||
322 | offer->supportedDragAndDropActions().testFlag(DataDeviceManagerInterface::DnDAction::Move)) { | ||||
323 | action = DataDeviceManagerInterface::DnDAction::Move; | ||||
324 | } else if (source->supportedDragAndDropActions().testFlag(DataDeviceManagerInterface::DnDAction::Ask) && | ||||
325 | offer->supportedDragAndDropActions().testFlag(DataDeviceManagerInterface::DnDAction::Ask)) { | ||||
326 | action = DataDeviceManagerInterface::DnDAction::Ask; | ||||
327 | } | ||||
328 | } | ||||
329 | offer->dndAction(action); | ||||
330 | source->dndAction(action); | ||||
331 | }; | ||||
332 | d->drag.targetActionConnection = connect(offer, &DataOfferInterface::dragAndDropActionsChanged, offer, matchOffers); | ||||
333 | d->drag.sourceActionConnection = connect(source, &DataSourceInterface::supportedDragAndDropActionsChanged, source, matchOffers); | ||||
334 | } | ||||
288 | d->client->flush(); | 335 | d->client->flush(); | ||
289 | } | 336 | } | ||
290 | 337 | | |||
291 | quint32 DataDeviceInterface::dragImplicitGrabSerial() const | 338 | quint32 DataDeviceInterface::dragImplicitGrabSerial() const | ||
292 | { | 339 | { | ||
293 | Q_D(); | 340 | Q_D(); | ||
294 | return d->drag.serial; | 341 | return d->drag.serial; | ||
295 | } | 342 | } | ||
296 | 343 | | |||
297 | DataDeviceInterface::Private *DataDeviceInterface::d_func() const | 344 | DataDeviceInterface::Private *DataDeviceInterface::d_func() const | ||
298 | { | 345 | { | ||
299 | return reinterpret_cast<DataDeviceInterface::Private*>(d.data()); | 346 | return reinterpret_cast<DataDeviceInterface::Private*>(d.data()); | ||
300 | } | 347 | } | ||
301 | 348 | | |||
302 | } | 349 | } | ||
303 | } | 350 | } |