qxcbdrag.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/plugins/platforms/xcb/qxcbdrag.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the QtGui module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://www.qt.io/contact-us.-
16**-
17** GNU Lesser General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU Lesser-
19** General Public License version 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39-
40#include "qxcbdrag.h"-
41#include <xcb/xcb.h>-
42#include "qxcbconnection.h"-
43#include "qxcbclipboard.h"-
44#include "qxcbmime.h"-
45#include "qxcbwindow.h"-
46#include "qxcbscreen.h"-
47#include "qwindow.h"-
48#include "qxcbcursor.h"-
49#include <private/qdnd_p.h>-
50#include <qdebug.h>-
51#include <qevent.h>-
52#include <qguiapplication.h>-
53#include <qrect.h>-
54#include <qpainter.h>-
55#include <qtimer.h>-
56-
57#include <qpa/qwindowsysteminterface.h>-
58-
59#include <private/qguiapplication_p.h>-
60#include <private/qshapedpixmapdndwindow_p.h>-
61#include <private/qsimpledrag_p.h>-
62#include <private/qhighdpiscaling_p.h>-
63-
64QT_BEGIN_NAMESPACE-
65-
66#ifndef QT_NO_DRAGANDDROP-
67-
68//#define DND_DEBUG-
69#ifdef DND_DEBUG-
70#define DEBUG qDebug-
71#else-
72#define DEBUG if(0) qDebug-
73#endif-
74-
75#ifdef DND_DEBUG-
76#define DNDDEBUG qDebug()-
77#else-
78#define DNDDEBUG if(0) qDebug()-
79#endif-
80-
81const int xdnd_version = 5;-
82-
83static inline xcb_window_t xcb_window(QPlatformWindow *w)-
84{-
85 return static_cast<QXcbWindow *>(w)->xcb_window();-
86}-
87-
88static inline xcb_window_t xcb_window(QWindow *w)-
89{-
90 return static_cast<QXcbWindow *>(w->handle())->xcb_window();-
91}-
92-
93static xcb_window_t xdndProxy(QXcbConnection *c, xcb_window_t w)-
94{-
95 xcb_window_t proxy = XCB_NONE;-
96-
97 xcb_get_property_cookie_t cookie = Q_XCB_CALL2(xcb_get_property(c->xcb_connection(), false, w, c->atom(QXcbAtom::XdndProxy),-
98 XCB_ATOM_WINDOW, 0, 1), c);-
99 xcb_get_property_reply_t *reply = xcb_get_property_reply(c->xcb_connection(), cookie, 0);-
100-
101 if (reply && reply->type == XCB_ATOM_WINDOW)-
102 proxy = *((xcb_window_t *)xcb_get_property_value(reply));-
103 free(reply);-
104-
105 if (proxy == XCB_NONE)-
106 return proxy;-
107-
108 // exists and is real?-
109 cookie = Q_XCB_CALL2(xcb_get_property(c->xcb_connection(), false, proxy, c->atom(QXcbAtom::XdndProxy),-
110 XCB_ATOM_WINDOW, 0, 1), c);-
111 reply = xcb_get_property_reply(c->xcb_connection(), cookie, 0);-
112-
113 if (reply && reply->type == XCB_ATOM_WINDOW) {-
114 xcb_window_t p = *((xcb_window_t *)xcb_get_property_value(reply));-
115 if (proxy != p)-
116 proxy = 0;-
117 } else {-
118 proxy = 0;-
119 }-
120-
121 free(reply);-
122-
123 return proxy;-
124}-
125-
126class QXcbDropData : public QXcbMime-
127{-
128public:-
129 QXcbDropData(QXcbDrag *d);-
130 ~QXcbDropData();-
131-
132protected:-
133 bool hasFormat_sys(const QString &mimeType) const Q_DECL_OVERRIDE;-
134 QStringList formats_sys() const Q_DECL_OVERRIDE;-
135 QVariant retrieveData_sys(const QString &mimeType, QVariant::Type type) const Q_DECL_OVERRIDE;-
136-
137 QVariant xdndObtainData(const QByteArray &format, QVariant::Type requestedType) const;-
138-
139 QXcbDrag *drag;-
140};-
141-
142-
143QXcbDrag::QXcbDrag(QXcbConnection *c) : QXcbObject(c)-
144{-
145 dropData = new QXcbDropData(this);-
146-
147 init();-
148 cleanup_timer = -1;-
149}-
150-
151QXcbDrag::~QXcbDrag()-
152{-
153 delete dropData;-
154}-
155-
156void QXcbDrag::init()-
157{-
158 currentWindow.clear();-
159-
160 accepted_drop_action = Qt::IgnoreAction;-
161-
162 xdnd_dragsource = XCB_NONE;-
163-
164 waiting_for_status = false;-
165 current_target = XCB_NONE;-
166 current_proxy_target = XCB_NONE;-
167-
168 source_time = XCB_CURRENT_TIME;-
169 target_time = XCB_CURRENT_TIME;-
170-
171 QXcbCursor::queryPointer(connection(), &current_virtual_desktop, 0);-
172 drag_types.clear();-
173}-
174-
175QMimeData *QXcbDrag::platformDropData()-
176{-
177 return dropData;-
178}-
179-
180bool QXcbDrag::eventFilter(QObject *o, QEvent *e)-
181{-
182 /* We are setting a mouse grab on the QShapedPixmapWindow in order not to-
183 * lose the grab when the virtual desktop changes, but-
184 * QBasicDrag::eventFilter() expects the events to be coming from the-
185 * window where the drag was started. */-
186 if (initiatorWindow && o == shapedPixmapWindow())-
187 o = initiatorWindow.data();-
188 return QBasicDrag::eventFilter(o, e);-
189}-
190-
191void QXcbDrag::startDrag()-
192{-
193 // #fixme enableEventFilter();-
194-
195 init();-
196-
197 xcb_set_selection_owner(xcb_connection(), connection()->clipboard()->owner(),-
198 atom(QXcbAtom::XdndSelection), connection()->time());-
199-
200 QStringList fmts = QXcbMime::formatsHelper(drag()->mimeData());-
201 for (int i = 0; i < fmts.size(); ++i) {-
202 QVector<xcb_atom_t> atoms = QXcbMime::mimeAtomsForFormat(connection(), fmts.at(i));-
203 for (int j = 0; j < atoms.size(); ++j) {-
204 if (!drag_types.contains(atoms.at(j)))-
205 drag_types.append(atoms.at(j));-
206 }-
207 }-
208 if (drag_types.size() > 3)-
209 xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, connection()->clipboard()->owner(),-
210 atom(QXcbAtom::XdndTypelist),-
211 XCB_ATOM_ATOM, 32, drag_types.size(), (const void *)drag_types.constData());-
212-
213 setUseCompositing(current_virtual_desktop->compositingActive());-
214 setScreen(current_virtual_desktop->screens().constFirst()->screen());-
215 initiatorWindow = QGuiApplicationPrivate::currentMouseWindow;-
216 QBasicDrag::startDrag();-
217 if (connection()->mouseGrabber() == Q_NULLPTR)-
218 shapedPixmapWindow()->setMouseGrabEnabled(true);-
219}-
220-
221void QXcbDrag::endDrag()-
222{-
223 QBasicDrag::endDrag();-
224 initiatorWindow.clear();-
225}-
226-
227static xcb_translate_coordinates_reply_t *-
228translateCoordinates(QXcbConnection *c, xcb_window_t from, xcb_window_t to, int x, int y)-
229{-
230 xcb_translate_coordinates_cookie_t cookie =-
231 xcb_translate_coordinates(c->xcb_connection(), from, to, x, y);-
232 return xcb_translate_coordinates_reply(c->xcb_connection(), cookie, 0);-
233}-
234-
235static-
236bool windowInteractsWithPosition(xcb_connection_t *connection, const QPoint & pos, xcb_window_t w, xcb_shape_sk_t shapeType)-
237{-
238 bool interacts = false;-
239 xcb_shape_get_rectangles_reply_t *reply = xcb_shape_get_rectangles_reply(connection, xcb_shape_get_rectangles(connection, w, shapeType), NULL);-
240 if (reply) {-
241 xcb_rectangle_t *rectangles = xcb_shape_get_rectangles_rectangles(reply);-
242 if (rectangles) {-
243 const int nRectangles = xcb_shape_get_rectangles_rectangles_length(reply);-
244 for (int i = 0; !interacts && i < nRectangles; ++i) {-
245 interacts = QRect(rectangles[i].x, rectangles[i].y, rectangles[i].width, rectangles[i].height).contains(pos);-
246 }-
247 }-
248 free(reply);-
249 }-
250-
251 return interacts;-
252}-
253-
254xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md, bool ignoreNonXdndAwareWindows)-
255{-
256 if (w == shapedPixmapWindow()->handle()->winId())-
257 return 0;-
258-
259 if (md) {-
260 xcb_get_window_attributes_cookie_t cookie = xcb_get_window_attributes(xcb_connection(), w);-
261 xcb_get_window_attributes_reply_t *reply = xcb_get_window_attributes_reply(xcb_connection(), cookie, 0);-
262 if (!reply)-
263 return 0;-
264-
265 if (reply->map_state != XCB_MAP_STATE_VIEWABLE)-
266 return 0;-
267-
268 free(reply);-
269-
270 xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(xcb_connection(), w);-
271 xcb_get_geometry_reply_t *greply = xcb_get_geometry_reply(xcb_connection(), gcookie, 0);-
272 if (!greply)-
273 return 0;-
274-
275 QRect windowRect(greply->x, greply->y, greply->width, greply->height);-
276 free(greply);-
277 if (windowRect.contains(pos)) {-
278 bool windowContainsMouse = !ignoreNonXdndAwareWindows;-
279 {-
280 xcb_get_property_cookie_t cookie =-
281 Q_XCB_CALL(xcb_get_property(xcb_connection(), false, w, connection()->atom(QXcbAtom::XdndAware),-
282 XCB_GET_PROPERTY_TYPE_ANY, 0, 0));-
283 xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0);-
284-
285 bool isAware = reply && reply->type != XCB_NONE;-
286 free(reply);-
287 if (isAware) {-
288 const QPoint relPos = pos - windowRect.topLeft();-
289 // When ShapeInput and ShapeBounding are not set they return a single rectangle with the geometry of the window, this is why we-
290 // need to check both here so that in the case one is set and the other is not we still get the correct result.-
291 if (connection()->hasInputShape())-
292 windowContainsMouse = windowInteractsWithPosition(xcb_connection(), relPos, w, XCB_SHAPE_SK_INPUT);-
293 if (windowContainsMouse && connection()->hasXShape())-
294 windowContainsMouse = windowInteractsWithPosition(xcb_connection(), relPos, w, XCB_SHAPE_SK_BOUNDING);-
295 if (!connection()->hasInputShape() && !connection()->hasXShape())-
296 windowContainsMouse = true;-
297 if (windowContainsMouse)-
298 return w;-
299 }-
300 }-
301-
302 xcb_query_tree_cookie_t cookie = xcb_query_tree (xcb_connection(), w);-
303 xcb_query_tree_reply_t *reply = xcb_query_tree_reply(xcb_connection(), cookie, 0);-
304-
305 if (!reply)-
306 return 0;-
307 int nc = xcb_query_tree_children_length(reply);-
308 xcb_window_t *c = xcb_query_tree_children(reply);-
309-
310 xcb_window_t r = 0;-
311 for (uint i = nc; !r && i--;)-
312 r = findRealWindow(pos - windowRect.topLeft(), c[i], md-1, ignoreNonXdndAwareWindows);-
313-
314 free(reply);-
315 if (r)-
316 return r;-
317-
318 // We didn't find a client window! Just use the-
319 // innermost window.-
320-
321 // No children!-
322 if (!windowContainsMouse)-
323 return 0;-
324 else-
325 return w;-
326 }-
327 }-
328 return 0;-
329}-
330-
331void QXcbDrag::move(const QPoint &globalPos)-
332{-
333-
334 if (source_sameanswer.contains(globalPos) && source_sameanswer.isValid())-
335 return;-
336-
337 QXcbVirtualDesktop *virtualDesktop = Q_NULLPTR;-
338 QPoint cursorPos;-
339 QXcbCursor::queryPointer(connection(), &virtualDesktop, &cursorPos);-
340 QXcbScreen *screen = virtualDesktop->screenAt(cursorPos);-
341 QPoint deviceIndependentPos = QHighDpiScaling::mapPositionFromNative(globalPos, screen);-
342-
343 if (virtualDesktop != current_virtual_desktop) {-
344 setUseCompositing(virtualDesktop->compositingActive());-
345 recreateShapedPixmapWindow(static_cast<QPlatformScreen*>(screen)->screen(), deviceIndependentPos);-
346 if (connection()->mouseGrabber() == Q_NULLPTR)-
347 shapedPixmapWindow()->setMouseGrabEnabled(true);-
348-
349 current_virtual_desktop = virtualDesktop;-
350 } else {-
351 QBasicDrag::moveShapedPixmapWindow(deviceIndependentPos);-
352 }-
353-
354 xcb_window_t rootwin = current_virtual_desktop->root();-
355 xcb_translate_coordinates_reply_t *translate =-
356 ::translateCoordinates(connection(), rootwin, rootwin, globalPos.x(), globalPos.y());-
357 if (!translate)-
358 return;-
359-
360 xcb_window_t target = translate->child;-
361 int lx = translate->dst_x;-
362 int ly = translate->dst_y;-
363 free (translate);-
364-
365 if (target && target != rootwin) {-
366 xcb_window_t src = rootwin;-
367 while (target != 0) {-
368 DNDDEBUG << "checking target for XdndAware" << target << lx << ly;
dead code: QMessageLogger(__FILE__, 368, __PRETTY_FUNCTION__).debug() << "checking target for XdndAware" << target << lx << ly;
-
369-
370 // translate coordinates-
371 translate = ::translateCoordinates(connection(), src, target, lx, ly);-
372 if (!translate) {-
373 target = 0;-
374 break;-
375 }-
376 lx = translate->dst_x;-
377 ly = translate->dst_y;-
378 src = target;-
379 xcb_window_t child = translate->child;-
380 free(translate);-
381-
382 // check if it has XdndAware-
383 xcb_get_property_cookie_t cookie = Q_XCB_CALL(xcb_get_property(xcb_connection(), false, target,-
384 atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0));-
385 xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0);-
386 bool aware = reply && reply->type != XCB_NONE;-
387 free(reply);-
388 if (aware) {-
389 DNDDEBUG << "Found XdndAware on " << target;
dead code: QMessageLogger(__FILE__, 389, __PRETTY_FUNCTION__).debug() << "Found XdndAware on " << target;
-
390 break;-
391 }-
392-
393 target = child;-
394 }-
395-
396 if (!target || target == shapedPixmapWindow()->handle()->winId()) {-
397 DNDDEBUG << "need to find real window";
dead code: QMessageLogger(__FILE__, 397, __PRETTY_FUNCTION__).debug() << "need to find real window";
-
398 target = findRealWindow(globalPos, rootwin, 6, true);-
399 if (target == 0)-
400 target = findRealWindow(globalPos, rootwin, 6, false);-
401 DNDDEBUG << "real window found" << target;
dead code: QMessageLogger(__FILE__, 401, __PRETTY_FUNCTION__).debug() << "real window found" << target;
-
402 }-
403 }-
404-
405 QXcbWindow *w = 0;-
406 if (target) {-
407 w = connection()->platformWindowFromId(target);-
408 if (w && (w->window()->type() == Qt::Desktop) /*&& !w->acceptDrops()*/)-
409 w = 0;-
410 } else {-
411 w = 0;-
412 target = rootwin;-
413 }-
414-
415 xcb_window_t proxy_target = xdndProxy(connection(), target);-
416 if (!proxy_target)-
417 proxy_target = target;-
418 int target_version = 1;-
419-
420 if (proxy_target) {-
421 xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, proxy_target,-
422 atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 1);-
423 xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0);-
424 if (!reply || reply->type == XCB_NONE)-
425 target = 0;-
426-
427 target_version = *(uint32_t *)xcb_get_property_value(reply);-
428 target_version = qMin(xdnd_version, target_version ? target_version : 1);-
429-
430 free(reply);-
431 }-
432-
433 if (target != current_target) {-
434 if (current_target)-
435 send_leave();-
436-
437 current_target = target;-
438 current_proxy_target = proxy_target;-
439 if (target) {-
440 int flags = target_version << 24;-
441 if (drag_types.size() > 3)-
442 flags |= 0x0001;-
443-
444 xcb_client_message_event_t enter;-
445 enter.response_type = XCB_CLIENT_MESSAGE;-
446 enter.sequence = 0;-
447 enter.window = target;-
448 enter.format = 32;-
449 enter.type = atom(QXcbAtom::XdndEnter);-
450 enter.data.data32[0] = connection()->clipboard()->owner();-
451 enter.data.data32[1] = flags;-
452 enter.data.data32[2] = drag_types.size()>0 ? drag_types.at(0) : 0;-
453 enter.data.data32[3] = drag_types.size()>1 ? drag_types.at(1) : 0;-
454 enter.data.data32[4] = drag_types.size()>2 ? drag_types.at(2) : 0;-
455 // provisionally set the rectangle to 5x5 pixels...-
456 source_sameanswer = QRect(globalPos.x() - 2, globalPos.y() -2 , 5, 5);-
457-
458 DEBUG() << "sending Xdnd enter source=" << enter.data.data32[0];
dead code: QMessageLogger(__FILE__, 458, __PRETTY_FUNCTION__).debug() << "sending Xdnd enter source=" << enter.data.data32[0];
-
459 if (w)-
460 handleEnter(w, &enter, current_proxy_target);-
461 else if (target)-
462 xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&enter);-
463 waiting_for_status = false;-
464 }-
465 }-
466-
467 if (waiting_for_status)-
468 return;-
469-
470 if (target) {-
471 waiting_for_status = true;-
472-
473 xcb_client_message_event_t move;-
474 move.response_type = XCB_CLIENT_MESSAGE;-
475 move.sequence = 0;-
476 move.window = target;-
477 move.format = 32;-
478 move.type = atom(QXcbAtom::XdndPosition);-
479 move.data.data32[0] = connection()->clipboard()->owner();-
480 move.data.data32[1] = 0; // flags-
481 move.data.data32[2] = (globalPos.x() << 16) + globalPos.y();-
482 move.data.data32[3] = connection()->time();-
483 move.data.data32[4] = toXdndAction(defaultAction(currentDrag()->supportedActions(), QGuiApplication::keyboardModifiers()));-
484 DEBUG() << "sending Xdnd position source=" << move.data.data32[0] << "target=" << move.window;
dead code: QMessageLogger(__FILE__, 484, __PRETTY_FUNCTION__).debug() << "sending Xdnd position source=" << move.data.data32[0] << "target=" << move.window;
-
485-
486 source_time = connection()->time();-
487-
488 if (w)-
489 handle_xdnd_position(w, &move);-
490 else-
491 xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&move);-
492 }-
493}-
494-
495void QXcbDrag::drop(const QPoint &globalPos)-
496{-
497 QBasicDrag::drop(globalPos);-
498-
499 if (!current_target)-
500 return;-
501-
502 xcb_client_message_event_t drop;-
503 drop.response_type = XCB_CLIENT_MESSAGE;-
504 drop.sequence = 0;-
505 drop.window = current_target;-
506 drop.format = 32;-
507 drop.type = atom(QXcbAtom::XdndDrop);-
508 drop.data.data32[0] = connection()->clipboard()->owner();-
509 drop.data.data32[1] = 0; // flags-
510 drop.data.data32[2] = connection()->time();-
511-
512 drop.data.data32[3] = 0;-
513 drop.data.data32[4] = currentDrag()->supportedActions();-
514-
515 QXcbWindow *w = connection()->platformWindowFromId(current_proxy_target);-
516-
517 if (w && (w->window()->type() == Qt::Desktop) /*&& !w->acceptDrops()*/)-
518 w = 0;-
519-
520 Transaction t = {-
521 connection()->time(),-
522 current_target,-
523 current_proxy_target,-
524 w,-
525// current_embeddig_widget,-
526 currentDrag(),-
527 QTime::currentTime()-
528 };-
529 transactions.append(t);-
530-
531 // timer is needed only for drops that came from other processes.-
532 if (!t.targetWindow && cleanup_timer == -1) {-
533 cleanup_timer = startTimer(XdndDropTransactionTimeout);-
534 }-
535-
536 if (w) {-
537 handleDrop(w, &drop);-
538 } else {-
539 xcb_send_event(xcb_connection(), false, current_proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&drop);-
540 }-
541-
542 current_target = 0;-
543 current_proxy_target = 0;-
544 source_time = 0;-
545// current_embedding_widget = 0;-
546}-
547-
548Qt::DropAction QXcbDrag::toDropAction(xcb_atom_t a) const-
549{-
550 if (a == atom(QXcbAtom::XdndActionCopy) || a == 0)-
551 return Qt::CopyAction;-
552 if (a == atom(QXcbAtom::XdndActionLink))-
553 return Qt::LinkAction;-
554 if (a == atom(QXcbAtom::XdndActionMove))-
555 return Qt::MoveAction;-
556 return Qt::CopyAction;-
557}-
558-
559xcb_atom_t QXcbDrag::toXdndAction(Qt::DropAction a) const-
560{-
561 switch (a) {-
562 case Qt::CopyAction:-
563 return atom(QXcbAtom::XdndActionCopy);-
564 case Qt::LinkAction:-
565 return atom(QXcbAtom::XdndActionLink);-
566 case Qt::MoveAction:-
567 case Qt::TargetMoveAction:-
568 return atom(QXcbAtom::XdndActionMove);-
569 case Qt::IgnoreAction:-
570 return XCB_NONE;-
571 default:-
572 return atom(QXcbAtom::XdndActionCopy);-
573 }-
574}-
575-
576int QXcbDrag::findTransactionByWindow(xcb_window_t window)-
577{-
578 int at = -1;-
579 for (int i = 0; i < transactions.count(); ++i) {-
580 const Transaction &t = transactions.at(i);-
581 if (t.target == window || t.proxy_target == window) {-
582 at = i;-
583 break;-
584 }-
585 }-
586 return at;-
587}-
588-
589int QXcbDrag::findTransactionByTime(xcb_timestamp_t timestamp)-
590{-
591 int at = -1;-
592 for (int i = 0; i < transactions.count(); ++i) {-
593 const Transaction &t = transactions.at(i);-
594 if (t.timestamp == timestamp) {-
595 at = i;-
596 break;-
597 }-
598 }-
599 return at;-
600}-
601-
602#if 0-
603-
604// find an ancestor with XdndAware on it-
605static Window findXdndAwareParent(Window window)-
606{-
607 Window target = 0;-
608 forever {-
609 // check if window has XdndAware-
610 Atom type = 0;-
611 int f;-
612 unsigned long n, a;-
613 unsigned char *data = 0;-
614 if (XGetWindowProperty(X11->display, window, ATOM(XdndAware), 0, 0, False,-
615 AnyPropertyType, &type, &f,&n,&a,&data) == Success) {-
616 if (data)-
617 XFree(data);-
618 if (type) {-
619 target = window;-
620 break;-
621 }-
622 }-
623-
624 // try window's parent-
625 Window root;-
626 Window parent;-
627 Window *children;-
628 uint unused;-
629 if (!XQueryTree(X11->display, window, &root, &parent, &children, &unused))-
630 break;-
631 if (children)-
632 XFree(children);-
633 if (window == root)-
634 break;-
635 window = parent;-
636 }-
637 return target;-
638}-
639-
640-
641// for embedding only-
642static QWidget* current_embedding_widget = 0;-
643static xcb_client_message_event_t last_enter_event;-
644-
645-
646static bool checkEmbedded(QWidget* w, const XEvent* xe)-
647{-
648 if (!w)-
649 return false;-
650-
651 if (current_embedding_widget != 0 && current_embedding_widget != w) {-
652 current_target = ((QExtraWidget*)current_embedding_widget)->extraData()->xDndProxy;-
653 current_proxy_target = current_target;-
654 qt_xdnd_send_leave();-
655 current_target = 0;-
656 current_proxy_target = 0;-
657 current_embedding_widget = 0;-
658 }-
659-
660 QWExtra* extra = ((QExtraWidget*)w)->extraData();-
661 if (extra && extra->xDndProxy != 0) {-
662-
663 if (current_embedding_widget != w) {-
664-
665 last_enter_event.xany.window = extra->xDndProxy;-
666 XSendEvent(X11->display, extra->xDndProxy, False, NoEventMask, &last_enter_event);-
667 current_embedding_widget = w;-
668 }-
669-
670 ((XEvent*)xe)->xany.window = extra->xDndProxy;-
671 XSendEvent(X11->display, extra->xDndProxy, False, NoEventMask, (XEvent*)xe);-
672 if (currentWindow != w) {-
673 currentWindow = w;-
674 }-
675 return true;-
676 }-
677 current_embedding_widget = 0;-
678 return false;-
679}-
680#endif-
681-
682-
683void QXcbDrag::handleEnter(QPlatformWindow *window, const xcb_client_message_event_t *event, xcb_window_t proxy)-
684{-
685 Q_UNUSED(window);-
686 DEBUG() << "handleEnter" << window;
dead code: QMessageLogger(__FILE__, 686, __PRETTY_FUNCTION__).debug() << "handleEnter" << window;
-
687-
688 xdnd_types.clear();-
689-
690 int version = (int)(event->data.data32[1] >> 24);-
691 if (version > xdnd_version)-
692 return;-
693-
694 xdnd_dragsource = event->data.data32[0];-
695 if (!proxy)-
696 proxy = xdndProxy(connection(), xdnd_dragsource);-
697 current_proxy_target = proxy ? proxy : xdnd_dragsource;-
698-
699 if (event->data.data32[1] & 1) {-
700 // get the types from XdndTypeList-
701 xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, xdnd_dragsource,-
702 atom(QXcbAtom::XdndTypelist), XCB_ATOM_ATOM,-
703 0, xdnd_max_type);-
704 xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0);-
705 if (reply && reply->type != XCB_NONE && reply->format == 32) {-
706 int length = xcb_get_property_value_length(reply) / 4;-
707 if (length > xdnd_max_type)-
708 length = xdnd_max_type;-
709-
710 xcb_atom_t *atoms = (xcb_atom_t *)xcb_get_property_value(reply);-
711 xdnd_types.reserve(length);-
712 for (int i = 0; i < length; ++i)-
713 xdnd_types.append(atoms[i]);-
714 }-
715 free(reply);-
716 } else {-
717 // get the types from the message-
718 for(int i = 2; i < 5; i++) {-
719 if (event->data.data32[i])-
720 xdnd_types.append(event->data.data32[i]);-
721 }-
722 }-
723 for(int i = 0; i < xdnd_types.length(); ++i)-
724 DEBUG() << " " << connection()->atomName(xdnd_types.at(i));
dead code: QMessageLogger(__FILE__, 724, __PRETTY_FUNCTION__).debug() << " " << connection()->atomName(xdnd_types.at(i));
-
725}-
726-
727void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message_event_t *e)-
728{-
729 QPoint p((e->data.data32[2] & 0xffff0000) >> 16, e->data.data32[2] & 0x0000ffff);-
730 Q_ASSERT(w);-
731 QRect geometry = w->geometry();-
732 p -= geometry.topLeft();-
733-
734 if (!w || !w->window() || (w->window()->type() == Qt::Desktop))-
735 return;-
736-
737 if (e->data.data32[0] != xdnd_dragsource) {-
738 DEBUG("xdnd drag position from unexpected source (%x not %x)", e->data.data32[0], xdnd_dragsource);
dead code: QMessageLogger(__FILE__, 738, __PRETTY_FUNCTION__).debug("xdnd drag position from unexpected source (%x not %x)", e->data.data32[0], xdnd_dragsource);
-
739 return;-
740 }-
741-
742 currentPosition = p;-
743 currentWindow = w->window();-
744-
745 // timestamp from the source-
746 if (e->data.data32[3] != XCB_NONE) {-
747 target_time = e->data.data32[3];-
748 }-
749-
750 QMimeData *dropData = 0;-
751 Qt::DropActions supported_actions = Qt::IgnoreAction;-
752 if (currentDrag()) {-
753 dropData = currentDrag()->mimeData();-
754 supported_actions = currentDrag()->supportedActions();-
755 } else {-
756 dropData = platformDropData();-
757 supported_actions = Qt::DropActions(toDropAction(e->data.data32[4]));-
758 }-
759-
760 QPlatformDragQtResponse qt_response = QWindowSystemInterface::handleDrag(w->window(),dropData,p,supported_actions);-
761 QRect answerRect(p + geometry.topLeft(), QSize(1,1));-
762 answerRect = qt_response.answerRect().translated(geometry.topLeft()).intersected(geometry);-
763-
764 xcb_client_message_event_t response;-
765 response.response_type = XCB_CLIENT_MESSAGE;-
766 response.sequence = 0;-
767 response.window = xdnd_dragsource;-
768 response.format = 32;-
769 response.type = atom(QXcbAtom::XdndStatus);-
770 response.data.data32[0] = xcb_window(w);-
771 response.data.data32[1] = qt_response.isAccepted(); // flags-
772 response.data.data32[2] = 0; // x, y-
773 response.data.data32[3] = 0; // w, h-
774 response.data.data32[4] = toXdndAction(qt_response.acceptedAction()); // action-
775-
776 accepted_drop_action = qt_response.acceptedAction();-
777-
778 if (answerRect.left() < 0)-
779 answerRect.setLeft(0);-
780 if (answerRect.right() > 4096)-
781 answerRect.setRight(4096);-
782 if (answerRect.top() < 0)-
783 answerRect.setTop(0);-
784 if (answerRect.bottom() > 4096)-
785 answerRect.setBottom(4096);-
786 if (answerRect.width() < 0)-
787 answerRect.setWidth(0);-
788 if (answerRect.height() < 0)-
789 answerRect.setHeight(0);-
790-
791 // reset-
792 target_time = XCB_CURRENT_TIME;-
793-
794 if (xdnd_dragsource == connection()->clipboard()->owner())-
795 handle_xdnd_status(&response);-
796 else-
797 Q_XCB_CALL(xcb_send_event(xcb_connection(), false, current_proxy_target,-
798 XCB_EVENT_MASK_NO_EVENT, (const char *)&response));-
799}-
800-
801namespace-
802{-
803 class ClientMessageScanner {-
804 public:-
805 ClientMessageScanner(xcb_atom_t a) : atom(a) {}-
806 xcb_atom_t atom;-
807 bool checkEvent(xcb_generic_event_t *event) const {-
808 if (!event)-
809 return false;-
810 if ((event->response_type & 0x7f) != XCB_CLIENT_MESSAGE)-
811 return false;-
812 return ((xcb_client_message_event_t *)event)->type == atom;-
813 }-
814 };-
815}-
816-
817void QXcbDrag::handlePosition(QPlatformWindow * w, const xcb_client_message_event_t *event)-
818{-
819 xcb_client_message_event_t *lastEvent = const_cast<xcb_client_message_event_t *>(event);-
820 xcb_generic_event_t *nextEvent;-
821 ClientMessageScanner scanner(atom(QXcbAtom::XdndPosition));-
822 while ((nextEvent = connection()->checkEvent(scanner))) {-
823 if (lastEvent != event)-
824 free(lastEvent);-
825 lastEvent = (xcb_client_message_event_t *)nextEvent;-
826 }-
827-
828 handle_xdnd_position(w, lastEvent);-
829 if (lastEvent != event)-
830 free(lastEvent);-
831}-
832-
833void QXcbDrag::handle_xdnd_status(const xcb_client_message_event_t *event)-
834{-
835 DEBUG("xdndHandleStatus");
dead code: QMessageLogger(__FILE__, 835, __PRETTY_FUNCTION__).debug("xdndHandleStatus");
-
836 waiting_for_status = false;-
837 // ignore late status messages-
838 if (event->data.data32[0] && event->data.data32[0] != current_target)-
839 return;-
840-
841 const bool dropPossible = event->data.data32[1];-
842 setCanDrop(dropPossible);-
843-
844 if (dropPossible) {-
845 accepted_drop_action = toDropAction(event->data.data32[4]);-
846 updateCursor(accepted_drop_action);-
847 } else {-
848 updateCursor(Qt::IgnoreAction);-
849 }-
850-
851 if ((event->data.data32[1] & 2) == 0) {-
852 QPoint p((event->data.data32[2] & 0xffff0000) >> 16, event->data.data32[2] & 0x0000ffff);-
853 QSize s((event->data.data32[3] & 0xffff0000) >> 16, event->data.data32[3] & 0x0000ffff);-
854 source_sameanswer = QRect(p, s);-
855 } else {-
856 source_sameanswer = QRect();-
857 }-
858}-
859-
860void QXcbDrag::handleStatus(const xcb_client_message_event_t *event)-
861{-
862 if (event->window != connection()->clipboard()->owner() || !drag())-
863 return;-
864-
865 xcb_client_message_event_t *lastEvent = const_cast<xcb_client_message_event_t *>(event);-
866 xcb_generic_event_t *nextEvent;-
867 ClientMessageScanner scanner(atom(QXcbAtom::XdndStatus));-
868 while ((nextEvent = connection()->checkEvent(scanner))) {-
869 if (lastEvent != event)-
870 free(lastEvent);-
871 lastEvent = (xcb_client_message_event_t *)nextEvent;-
872 }-
873-
874 handle_xdnd_status(lastEvent);-
875 if (lastEvent != event)-
876 free(lastEvent);-
877 DEBUG("xdndHandleStatus end");
dead code: QMessageLogger(__FILE__, 877, __PRETTY_FUNCTION__).debug("xdndHandleStatus end");
-
878}-
879-
880void QXcbDrag::handleLeave(QPlatformWindow *w, const xcb_client_message_event_t *event)-
881{-
882 DEBUG("xdnd leave");
dead code: QMessageLogger(__FILE__, 882, __PRETTY_FUNCTION__).debug("xdnd leave");
-
883 if (!currentWindow || w != currentWindow.data()->handle())-
884 return; // sanity-
885-
886 // ###-
887// if (checkEmbedded(current_embedding_widget, event)) {-
888// current_embedding_widget = 0;-
889// currentWindow.clear();-
890// return;-
891// }-
892-
893 if (event->data.data32[0] != xdnd_dragsource) {-
894 // This often happens - leave other-process window quickly-
895 DEBUG("xdnd drag leave from unexpected source (%x not %x", event->data.data32[0], xdnd_dragsource);
dead code: QMessageLogger(__FILE__, 895, __PRETTY_FUNCTION__).debug("xdnd drag leave from unexpected source (%x not %x", event->data.data32[0], xdnd_dragsource);
-
896 }-
897-
898 QWindowSystemInterface::handleDrag(w->window(),0,QPoint(),Qt::IgnoreAction);-
899-
900 xdnd_dragsource = 0;-
901 xdnd_types.clear();-
902 currentWindow.clear();-
903}-
904-
905void QXcbDrag::send_leave()-
906{-
907 if (!current_target)-
908 return;-
909-
910-
911 xcb_client_message_event_t leave;-
912 leave.response_type = XCB_CLIENT_MESSAGE;-
913 leave.sequence = 0;-
914 leave.window = current_target;-
915 leave.format = 32;-
916 leave.type = atom(QXcbAtom::XdndLeave);-
917 leave.data.data32[0] = connection()->clipboard()->owner();-
918 leave.data.data32[1] = 0; // flags-
919 leave.data.data32[2] = 0; // x, y-
920 leave.data.data32[3] = 0; // w, h-
921 leave.data.data32[4] = 0; // just null-
922-
923 QXcbWindow *w = connection()->platformWindowFromId(current_proxy_target);-
924-
925 if (w && (w->window()->type() == Qt::Desktop) /*&& !w->acceptDrops()*/)-
926 w = 0;-
927-
928 if (w)-
929 handleLeave(w, (const xcb_client_message_event_t *)&leave);-
930 else-
931 xcb_send_event(xcb_connection(), false,current_proxy_target,-
932 XCB_EVENT_MASK_NO_EVENT, (const char *)&leave);-
933-
934 current_target = 0;-
935 current_proxy_target = 0;-
936 source_time = XCB_CURRENT_TIME;-
937 waiting_for_status = false;-
938}-
939-
940void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *event)-
941{-
942 DEBUG("xdndHandleDrop");
dead code: QMessageLogger(__FILE__, 942, __PRETTY_FUNCTION__).debug("xdndHandleDrop");
-
943 if (!currentWindow) {-
944 xdnd_dragsource = 0;-
945 return; // sanity-
946 }-
947-
948 const uint32_t *l = event->data.data32;-
949-
950 DEBUG("xdnd drop");
dead code: QMessageLogger(__FILE__, 950, __PRETTY_FUNCTION__).debug("xdnd drop");
-
951-
952 if (l[0] != xdnd_dragsource) {-
953 DEBUG("xdnd drop from unexpected source (%x not %x", l[0], xdnd_dragsource);
dead code: QMessageLogger(__FILE__, 953, __PRETTY_FUNCTION__).debug("xdnd drop from unexpected source (%x not %x", l[0], xdnd_dragsource);
-
954 return;-
955 }-
956-
957 // update the "user time" from the timestamp in the event.-
958 if (l[2] != 0)-
959 target_time = /*X11->userTime =*/ l[2];-
960-
961 Qt::DropActions supported_drop_actions;-
962 QMimeData *dropData = 0;-
963 if (currentDrag()) {-
964 dropData = currentDrag()->mimeData();-
965 supported_drop_actions = Qt::DropActions(l[4]);-
966 } else {-
967 dropData = platformDropData();-
968 supported_drop_actions = accepted_drop_action;-
969-
970 // Drop coming from another app? Update keyboard modifiers.-
971 QGuiApplicationPrivate::modifier_buttons = QGuiApplication::queryKeyboardModifiers();-
972 }-
973-
974 if (!dropData)-
975 return;-
976 // ###-
977 // int at = findXdndDropTransactionByTime(target_time);-
978 // if (at != -1)-
979 // dropData = QDragManager::dragPrivate(X11->dndDropTransactions.at(at).object)->data;-
980 // if we can't find it, then use the data in the drag manager-
981-
982 QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(currentWindow.data(),dropData,currentPosition,supported_drop_actions);-
983 setExecutedDropAction(response.acceptedAction());-
984-
985 xcb_client_message_event_t finished;-
986 finished.response_type = XCB_CLIENT_MESSAGE;-
987 finished.sequence = 0;-
988 finished.window = xdnd_dragsource;-
989 finished.format = 32;-
990 finished.type = atom(QXcbAtom::XdndFinished);-
991 finished.data.data32[0] = currentWindow ? xcb_window(currentWindow.data()) : XCB_NONE;-
992 finished.data.data32[1] = response.isAccepted(); // flags-
993 finished.data.data32[2] = toXdndAction(response.acceptedAction());-
994 Q_XCB_CALL(xcb_send_event(xcb_connection(), false, current_proxy_target,-
995 XCB_EVENT_MASK_NO_EVENT, (char *)&finished));-
996-
997 xdnd_dragsource = 0;-
998 currentWindow.clear();-
999 waiting_for_status = false;-
1000-
1001 // reset-
1002 target_time = XCB_CURRENT_TIME;-
1003}-
1004-
1005-
1006void QXcbDrag::handleFinished(const xcb_client_message_event_t *event)-
1007{-
1008 DEBUG("xdndHandleFinished");
dead code: QMessageLogger(__FILE__, 1008, __PRETTY_FUNCTION__).debug("xdndHandleFinished");
-
1009 if (event->window != connection()->clipboard()->owner())-
1010 return;-
1011-
1012 const unsigned long *l = (const unsigned long *)event->data.data32;-
1013-
1014 DNDDEBUG << "xdndHandleFinished, l[0]" << l[0]
dead code: QMessageLogger(__FILE__, 1014, __PRETTY_FUNCTION__).debug() << "xdndHandleFinished, l[0]" << l[0] << "current_target" << current_target << "qt_xdnd_current_proxy_targe" << current_proxy_target;
-
1015 << "current_target" << current_target
dead code: QMessageLogger(__FILE__, 1014, __PRETTY_FUNCTION__).debug() << "xdndHandleFinished, l[0]" << l[0] << "current_target" << current_target << "qt_xdnd_current_proxy_targe" << current_proxy_target;
-
1016 << "qt_xdnd_current_proxy_targe" << current_proxy_target;
dead code: QMessageLogger(__FILE__, 1014, __PRETTY_FUNCTION__).debug() << "xdndHandleFinished, l[0]" << l[0] << "current_target" << current_target << "qt_xdnd_current_proxy_targe" << current_proxy_target;
-
1017-
1018 if (l[0]) {-
1019 int at = findTransactionByWindow(l[0]);-
1020 if (at != -1) {-
1021-
1022 Transaction t = transactions.takeAt(at);-
1023 if (t.drag)-
1024 t.drag->deleteLater();-
1025// QDragManager *manager = QDragManager::self();-
1026-
1027// Window target = current_target;-
1028// Window proxy_target = current_proxy_target;-
1029// QWidget *embedding_widget = current_embedding_widget;-
1030// QDrag *currentObject = manager->object;-
1031-
1032// current_target = t.target;-
1033// current_proxy_target = t.proxy_target;-
1034// current_embedding_widget = t.embedding_widget;-
1035// manager->object = t.object;-
1036-
1037// if (!passive)-
1038// (void) checkEmbedded(currentWindow, xe);-
1039-
1040// current_embedding_widget = 0;-
1041// current_target = 0;-
1042// current_proxy_target = 0;-
1043-
1044// current_target = target;-
1045// current_proxy_target = proxy_target;-
1046// current_embedding_widget = embedding_widget;-
1047// manager->object = currentObject;-
1048 } else {-
1049 qWarning("QXcbDrag::handleFinished - drop data has expired");-
1050 }-
1051 }-
1052 waiting_for_status = false;-
1053}-
1054-
1055void QXcbDrag::timerEvent(QTimerEvent* e)-
1056{-
1057 if (e->timerId() == cleanup_timer) {-
1058 bool stopTimer = true;-
1059 for (int i = 0; i < transactions.count(); ++i) {-
1060 const Transaction &t = transactions.at(i);-
1061 if (t.targetWindow) {-
1062 // dnd within the same process, don't delete, these are taken care of-
1063 // in handleFinished()-
1064 continue;-
1065 }-
1066 QTime currentTime = QTime::currentTime();-
1067 int delta = t.time.msecsTo(currentTime);-
1068 if (delta > XdndDropTransactionTimeout) {-
1069 /* delete transactions which are older than XdndDropTransactionTimeout. It could mean-
1070 one of these:-
1071 - client has crashed and as a result we have never received XdndFinished-
1072 - showing dialog box on drop event where user's response takes more time than XdndDropTransactionTimeout (QTBUG-14493)-
1073 - dnd takes unusually long time to process data-
1074 */-
1075 if (t.drag)-
1076 t.drag->deleteLater();-
1077 transactions.removeAt(i--);-
1078 } else {-
1079 stopTimer = false;-
1080 }-
1081-
1082 }-
1083 if (stopTimer && cleanup_timer != -1) {-
1084 killTimer(cleanup_timer);-
1085 cleanup_timer = -1;-
1086 }-
1087 }-
1088}-
1089-
1090void QXcbDrag::cancel()-
1091{-
1092 DEBUG("QXcbDrag::cancel");
dead code: QMessageLogger(__FILE__, 1092, __PRETTY_FUNCTION__).debug("QXcbDrag::cancel");
-
1093 QBasicDrag::cancel();-
1094 if (current_target)-
1095 send_leave();-
1096}-
1097-
1098// find an ancestor with XdndAware on it-
1099static xcb_window_t findXdndAwareParent(QXcbConnection *c, xcb_window_t window)-
1100{-
1101 xcb_window_t target = 0;-
1102 forever {-
1103 // check if window has XdndAware-
1104 xcb_get_property_cookie_t gpCookie = Q_XCB_CALL(-
1105 xcb_get_property(c->xcb_connection(), false, window,-
1106 c->atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0));-
1107 xcb_get_property_reply_t *gpReply = xcb_get_property_reply(-
1108 c->xcb_connection(), gpCookie, 0);-
1109 bool aware = gpReply && gpReply->type != XCB_NONE;-
1110 free(gpReply);-
1111 if (aware) {-
1112 target = window;-
1113 break;-
1114 }-
1115-
1116 // try window's parent-
1117 xcb_query_tree_cookie_t qtCookie = Q_XCB_CALL(-
1118 xcb_query_tree_unchecked(c->xcb_connection(), window));-
1119 xcb_query_tree_reply_t *qtReply = xcb_query_tree_reply(-
1120 c->xcb_connection(), qtCookie, NULL);-
1121 if (!qtReply)-
1122 break;-
1123 xcb_window_t root = qtReply->root;-
1124 xcb_window_t parent = qtReply->parent;-
1125 free(qtReply);-
1126 if (window == root)-
1127 break;-
1128 window = parent;-
1129 }-
1130 return target;-
1131}-
1132-
1133void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event)-
1134{-
1135 Q_DECLARE_XCB_EVENT(notify,xcb_selection_notify_event_t );notify;-
1136 notify.response_type = XCB_SELECTION_NOTIFY;-
1137 notify.requestor = event->requestor;-
1138 notify.selection = event->selection;-
1139 notify.target = XCB_NONE;-
1140 notify.property = XCB_NONE;-
1141 notify.time = event->time;-
1142-
1143 // which transaction do we use? (note: -2 means use current currentDrag())-
1144 int at = -1;-
1145-
1146 // figure out which data the requestor is really interested in-
1147 if (currentDrag() && event->time == source_time) {
currentDrag()Description
TRUEnever evaluated
FALSEnever evaluated
event->time == source_timeDescription
TRUEnever evaluated
FALSEnever evaluated
0
1148 // requestor wants the current drag data-
1149 at = -2;-
1150 } else {
never executed: end of block
0
1151 // if someone has requested data in response to XdndDrop, find the corresponding transaction. the-
1152 // spec says to call xcb_convert_selection() using the timestamp from the XdndDrop-
1153 at = findTransactionByTime(event->time);-
1154 if (at == -1) {
at == -1Description
TRUEnever evaluated
FALSEnever evaluated
0
1155 // no dice, perhaps the client was nice enough to use the same window id in-
1156 // xcb_convert_selection() that we sent the XdndDrop event to.-
1157 at = findTransactionByWindow(event->requestor);-
1158 }
never executed: end of block
0
1159-
1160 if (at == -1) {
at == -1Description
TRUEnever evaluated
FALSEnever evaluated
0
1161 xcb_window_t target = findXdndAwareParent(connection(), event->requestor);-
1162 if (target) {
targetDescription
TRUEnever evaluated
FALSEnever evaluated
0
1163 if (event->time == XCB_CURRENT_TIME && current_target == target)
event->time == 0LDescription
TRUEnever evaluated
FALSEnever evaluated
current_target == targetDescription
TRUEnever evaluated
FALSEnever evaluated
0
1164 at = -2;
never executed: at = -2;
0
1165 else-
1166 at = findTransactionByWindow(target);
never executed: at = findTransactionByWindow(target);
0
1167 }-
1168 }
never executed: end of block
0
1169 }
never executed: end of block
0
1170-
1171 QDrag *transactionDrag = 0;-
1172 if (at >= 0) {
at >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1173 transactionDrag = transactions.at(at).drag;-
1174 } else if (at == -2) {
never executed: end of block
at == -2Description
TRUEnever evaluated
FALSEnever evaluated
0
1175 transactionDrag = currentDrag();-
1176 }
never executed: end of block
0
1177-
1178 if (transactionDrag) {
transactionDragDescription
TRUEnever evaluated
FALSEnever evaluated
0
1179 xcb_atom_t atomFormat = event->target;-
1180 int dataFormat = 0;-
1181 QByteArray data;-
1182 if (QXcbMime::mimeDataForAtom(connection(), event->target, transactionDrag->mimeData(),
QXcbMime::mime..., &dataFormat)Description
TRUEnever evaluated
FALSEnever evaluated
0
1183 &data, &atomFormat, &dataFormat)) {
QXcbMime::mime..., &dataFormat)Description
TRUEnever evaluated
FALSEnever evaluated
0
1184 int dataSize = data.size() / (dataFormat / 8);-
1185 xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, event->requestor, event->property,-
1186 atomFormat, dataFormat, dataSize, (const void *)data.constData());-
1187 notify.property = event->property;-
1188 notify.target = atomFormat;-
1189 }
never executed: end of block
0
1190 }
never executed: end of block
0
1191-
1192 xcb_window_t proxy_target = xdndProxy(connection(), event->requestor);-
1193 if (!proxy_target)
!proxy_targetDescription
TRUEnever evaluated
FALSEnever evaluated
0
1194 proxy_target = event->requestor;
never executed: proxy_target = event->requestor;
0
1195-
1196 xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&notify);-
1197}
never executed: end of block
0
1198-
1199-
1200bool QXcbDrag::dndEnable(QXcbWindow *w, bool on)-
1201{-
1202 DNDDEBUG << "xdndEnable" << w << on;
dead code: QMessageLogger(__FILE__, 1202, __PRETTY_FUNCTION__).debug() << "xdndEnable" << w << on;
-
1203 if (on) {-
1204 QXcbWindow *xdnd_widget = 0;-
1205 if ((w->window()->type() == Qt::Desktop)) {-
1206 if (desktop_proxy) // *WE* already have one.-
1207 return false;-
1208-
1209 QXcbConnectionGrabber grabber(connection());-
1210-
1211 // As per Xdnd4, use XdndProxy-
1212 xcb_window_t proxy_id = xdndProxy(connection(), w->xcb_window());-
1213-
1214 if (!proxy_id) {-
1215 desktop_proxy = new QWindow;-
1216 xdnd_widget = static_cast<QXcbWindow *>(desktop_proxy->handle());-
1217 proxy_id = xdnd_widget->xcb_window();-
1218 xcb_atom_t xdnd_proxy = atom(QXcbAtom::XdndProxy);-
1219 xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, w->xcb_window(), xdnd_proxy,-
1220 XCB_ATOM_WINDOW, 32, 1, &proxy_id);-
1221 xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, proxy_id, xdnd_proxy,-
1222 XCB_ATOM_WINDOW, 32, 1, &proxy_id);-
1223 }-
1224-
1225 } else {-
1226 xdnd_widget = w;-
1227 }-
1228 if (xdnd_widget) {-
1229 DNDDEBUG << "setting XdndAware for" << xdnd_widget << xdnd_widget->xcb_window();
dead code: QMessageLogger(__FILE__, 1229, __PRETTY_FUNCTION__).debug() << "setting XdndAware for" << xdnd_widget << xdnd_widget->xcb_window();
-
1230 xcb_atom_t atm = xdnd_version;-
1231 xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, xdnd_widget->xcb_window(),-
1232 atom(QXcbAtom::XdndAware), XCB_ATOM_ATOM, 32, 1, &atm);-
1233 return true;-
1234 } else {-
1235 return false;-
1236 }-
1237 } else {-
1238 if ((w->window()->type() == Qt::Desktop)) {-
1239 xcb_delete_property(xcb_connection(), w->xcb_window(), atom(QXcbAtom::XdndProxy));-
1240 delete desktop_proxy;-
1241 desktop_proxy = 0;-
1242 } else {-
1243 DNDDEBUG << "not deleting XDndAware";
dead code: QMessageLogger(__FILE__, 1243, __PRETTY_FUNCTION__).debug() << "not deleting XDndAware";
-
1244 }-
1245 return true;-
1246 }-
1247}-
1248-
1249bool QXcbDrag::ownsDragObject() const-
1250{-
1251 return true;-
1252}-
1253-
1254QXcbDropData::QXcbDropData(QXcbDrag *d)-
1255 : QXcbMime(),-
1256 drag(d)-
1257{-
1258}-
1259-
1260QXcbDropData::~QXcbDropData()-
1261{-
1262}-
1263-
1264QVariant QXcbDropData::retrieveData_sys(const QString &mimetype, QVariant::Type requestedType) const-
1265{-
1266 QByteArray mime = mimetype.toLatin1();-
1267 QVariant data = xdndObtainData(mime, requestedType);-
1268 return data;-
1269}-
1270-
1271QVariant QXcbDropData::xdndObtainData(const QByteArray &format, QVariant::Type requestedType) const-
1272{-
1273 QByteArray result;-
1274-
1275 QXcbConnection *c = drag->connection();-
1276 QXcbWindow *xcb_window = c->platformWindowFromId(drag->xdnd_dragsource);-
1277 if (xcb_window && drag->currentDrag() && xcb_window->window()->type() != Qt::Desktop) {-
1278 QMimeData *data = drag->currentDrag()->mimeData();-
1279 if (data->hasFormat(QLatin1String(format)))-
1280 result = data->data(QLatin1String(format));-
1281 return result;-
1282 }-
1283-
1284 QVector<xcb_atom_t> atoms = drag->xdnd_types;-
1285 QByteArray encoding;-
1286 xcb_atom_t a = mimeAtomForFormat(c, QLatin1String(format), requestedType, atoms, &encoding);-
1287 if (a == XCB_NONE)-
1288 return result;-
1289-
1290 if (c->clipboard()->getSelectionOwner(drag->atom(QXcbAtom::XdndSelection)) == XCB_NONE)-
1291 return result; // should never happen?-
1292-
1293 xcb_atom_t xdnd_selection = c->atom(QXcbAtom::XdndSelection);-
1294 result = c->clipboard()->getSelection(xdnd_selection, a, xdnd_selection, drag->targetTime());-
1295-
1296 return mimeConvertToFormat(c, a, result, QLatin1String(format), requestedType, encoding);-
1297}-
1298-
1299-
1300bool QXcbDropData::hasFormat_sys(const QString &format) const-
1301{-
1302 return formats().contains(format);-
1303}-
1304-
1305QStringList QXcbDropData::formats_sys() const-
1306{-
1307 QStringList formats;-
1308 for (int i = 0; i < drag->xdnd_types.size(); ++i) {-
1309 QString f = mimeAtomToString(drag->connection(), drag->xdnd_types.at(i));-
1310 if (!formats.contains(f))-
1311 formats.append(f);-
1312 }-
1313 return formats;-
1314}-
1315-
1316#endif // QT_NO_DRAGANDDROP-
1317-
1318QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9