qsimpledrag.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/kernel/qsimpledrag.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 "qsimpledrag_p.h"-
41-
42#include "qbitmap.h"-
43#include "qdrag.h"-
44#include "qpixmap.h"-
45#include "qevent.h"-
46#include "qfile.h"-
47#include "qtextcodec.h"-
48#include "qguiapplication.h"-
49#include "qpoint.h"-
50#include "qbuffer.h"-
51#include "qimage.h"-
52#include "qregexp.h"-
53#include "qdir.h"-
54#include "qimagereader.h"-
55#include "qimagewriter.h"-
56-
57#include <QtCore/QEventLoop>-
58#include <QtCore/QDebug>-
59-
60#include <private/qguiapplication_p.h>-
61#include <private/qdnd_p.h>-
62-
63#include <private/qshapedpixmapdndwindow_p.h>-
64#include <private/qhighdpiscaling_p.h>-
65-
66QT_BEGIN_NAMESPACE-
67-
68#ifndef QT_NO_DRAGANDDROP-
69-
70static QWindow* topLevelAt(const QPoint &pos)-
71{-
72 QWindowList list = QGuiApplication::topLevelWindows();-
73 for (int i = list.count()-1; i >= 0; --i) {
i >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
74 QWindow *w = list.at(i);-
75 if (w->isVisible() && w->geometry().contains(pos) && !qobject_cast<QShapedPixmapWindow*>(w))
w->isVisible()Description
TRUEnever evaluated
FALSEnever evaluated
w->geometry().contains(pos)Description
TRUEnever evaluated
FALSEnever evaluated
!qobject_cast<...mapWindow*>(w)Description
TRUEnever evaluated
FALSEnever evaluated
0
76 return w;
never executed: return w;
0
77 }
never executed: end of block
0
78 return 0;
never executed: return 0;
0
79}-
80-
81/*!-
82 \class QBasicDrag-
83 \brief QBasicDrag is a base class for implementing platform drag and drop.-
84 \since 5.0-
85 \internal-
86 \ingroup qpa-
87-
88 QBasicDrag implements QPlatformDrag::drag() by running a local event loop in which-
89 it tracks mouse movements and moves the drag icon (QShapedPixmapWindow) accordingly.-
90 It provides new virtuals allowing for querying whether the receiving window-
91 (within the Qt application or outside) accepts the drag and sets the state accordingly.-
92*/-
93-
94QBasicDrag::QBasicDrag() :-
95 m_restoreCursor(false), m_eventLoop(0),-
96 m_executed_drop_action(Qt::IgnoreAction), m_can_drop(false),-
97 m_drag(0), m_drag_icon_window(0), m_useCompositing(true),-
98 m_screen(Q_NULLPTR)-
99{-
100}
never executed: end of block
0
101-
102QBasicDrag::~QBasicDrag()-
103{-
104 delete m_drag_icon_window;-
105}
never executed: end of block
0
106-
107void QBasicDrag::enableEventFilter()-
108{-
109 qApp->installEventFilter(this);-
110}
never executed: end of block
0
111-
112void QBasicDrag::disableEventFilter()-
113{-
114 qApp->removeEventFilter(this);-
115}
never executed: end of block
0
116-
117-
118static inline QPoint getNativeMousePos(QEvent *e, QObject *o)-
119{-
120 return QHighDpi::toNativePixels(static_cast<QMouseEvent *>(e)->globalPos(), qobject_cast<QWindow*>(o));
never executed: return QHighDpi::toNativePixels(static_cast<QMouseEvent *>(e)->globalPos(), qobject_cast<QWindow*>(o));
0
121}-
122-
123bool QBasicDrag::eventFilter(QObject *o, QEvent *e)-
124{-
125 Q_UNUSED(o);-
126-
127 if (!m_drag) {
!m_dragDescription
TRUEnever evaluated
FALSEnever evaluated
0
128 if (e->type() == QEvent::KeyRelease && static_cast<QKeyEvent*>(e)->key() == Qt::Key_Escape) {
e->type() == Q...nt::KeyReleaseDescription
TRUEnever evaluated
FALSEnever evaluated
static_cast<QK...Qt::Key_EscapeDescription
TRUEnever evaluated
FALSEnever evaluated
0
129 disableEventFilter();-
130 exitDndEventLoop();-
131 return true; // block the key release
never executed: return true;
0
132 }-
133 return false;
never executed: return false;
0
134 }-
135-
136 switch (e->type()) {-
137 case QEvent::ShortcutOverride:
never executed: case QEvent::ShortcutOverride:
0
138 // prevent accelerators from firing while dragging-
139 e->accept();-
140 return true;
never executed: return true;
0
141-
142 case QEvent::KeyPress:
never executed: case QEvent::KeyPress:
0
143 case QEvent::KeyRelease:
never executed: case QEvent::KeyRelease:
0
144 {-
145 QKeyEvent *ke = static_cast<QKeyEvent *>(e);-
146 if (ke->key() == Qt::Key_Escape && e->type() == QEvent::KeyPress) {
ke->key() == Qt::Key_EscapeDescription
TRUEnever evaluated
FALSEnever evaluated
e->type() == QEvent::KeyPressDescription
TRUEnever evaluated
FALSEnever evaluated
0
147 cancel();-
148 disableEventFilter();-
149 exitDndEventLoop();-
150-
151 }
never executed: end of block
0
152 return true; // Eat all key events
never executed: return true;
0
153 }-
154-
155 case QEvent::MouseMove:
never executed: case QEvent::MouseMove:
0
156 {-
157 QPoint nativePosition = getNativeMousePos(e, o);-
158 move(nativePosition);-
159 return true; // Eat all mouse move events
never executed: return true;
0
160 }-
161 case QEvent::MouseButtonRelease:
never executed: case QEvent::MouseButtonRelease:
0
162 disableEventFilter();-
163 if (canDrop()) {
canDrop()Description
TRUEnever evaluated
FALSEnever evaluated
0
164 QPoint nativePosition = getNativeMousePos(e, o);-
165 drop(nativePosition);-
166 } else {
never executed: end of block
0
167 cancel();-
168 }
never executed: end of block
0
169 exitDndEventLoop();-
170 QCoreApplication::postEvent(o, new QMouseEvent(*static_cast<QMouseEvent *>(e)));-
171 return true; // defer mouse release events until drag event loop has returned
never executed: return true;
0
172 case QEvent::MouseButtonDblClick:
never executed: case QEvent::MouseButtonDblClick:
0
173 case QEvent::Wheel:
never executed: case QEvent::Wheel:
0
174 return true;
never executed: return true;
0
175 default:
never executed: default:
0
176 break;
never executed: break;
0
177 }-
178 return false;
never executed: return false;
0
179}-
180-
181Qt::DropAction QBasicDrag::drag(QDrag *o)-
182{-
183 m_drag = o;-
184 m_executed_drop_action = Qt::IgnoreAction;-
185 m_can_drop = false;-
186 m_restoreCursor = true;-
187#ifndef QT_NO_CURSOR-
188 qApp->setOverrideCursor(Qt::DragCopyCursor);-
189 updateCursor(m_executed_drop_action);-
190#endif-
191 startDrag();-
192 m_eventLoop = new QEventLoop;-
193 m_eventLoop->exec();-
194 delete m_eventLoop;-
195 m_eventLoop = 0;-
196 m_drag = 0;-
197 endDrag();-
198 return m_executed_drop_action;
never executed: return m_executed_drop_action;
0
199}-
200-
201void QBasicDrag::cancelDrag()-
202{-
203 if (m_eventLoop) {
m_eventLoopDescription
TRUEnever evaluated
FALSEnever evaluated
0
204 cancel();-
205 m_eventLoop->quit();-
206 }
never executed: end of block
0
207}
never executed: end of block
0
208-
209void QBasicDrag::restoreCursor()-
210{-
211 if (m_restoreCursor) {
m_restoreCursorDescription
TRUEnever evaluated
FALSEnever evaluated
0
212#ifndef QT_NO_CURSOR-
213 QGuiApplication::restoreOverrideCursor();-
214#endif-
215 m_restoreCursor = false;-
216 }
never executed: end of block
0
217}
never executed: end of block
0
218-
219void QBasicDrag::startDrag()-
220{-
221 QPoint pos;-
222#ifndef QT_NO_CURSOR-
223 pos = QCursor::pos();-
224 if (pos.x() == int(qInf())) {
pos.x() == int(qInf())Description
TRUEnever evaluated
FALSEnever evaluated
0
225 // ### fixme: no mouse pos registered. Get pos from touch...-
226 pos = QPoint();-
227 }
never executed: end of block
0
228#endif-
229 recreateShapedPixmapWindow(m_screen, pos);-
230 enableEventFilter();-
231}
never executed: end of block
0
232-
233void QBasicDrag::endDrag()-
234{-
235}-
236-
237void QBasicDrag::recreateShapedPixmapWindow(QScreen *screen, const QPoint &pos)-
238{-
239 delete m_drag_icon_window;-
240 // ### TODO Check if its really necessary to have m_drag_icon_window-
241 // when QDrag is used without a pixmap - QDrag::setPixmap()-
242 m_drag_icon_window = new QShapedPixmapWindow(screen);-
243-
244 m_drag_icon_window->setUseCompositing(m_useCompositing);-
245 m_drag_icon_window->setPixmap(m_drag->pixmap());-
246 m_drag_icon_window->setHotspot(m_drag->hotSpot());-
247 m_drag_icon_window->updateGeometry(pos);-
248 m_drag_icon_window->setVisible(true);-
249}
never executed: end of block
0
250-
251void QBasicDrag::cancel()-
252{-
253 disableEventFilter();-
254 restoreCursor();-
255 m_drag_icon_window->setVisible(false);-
256}
never executed: end of block
0
257-
258/*!-
259 Move the drag label to \a globalPos, which is-
260 interpreted in device independent coordinates. Typically called from reimplementations of move().-
261 */-
262-
263void QBasicDrag::moveShapedPixmapWindow(const QPoint &globalPos)-
264{-
265 if (m_drag)
m_dragDescription
TRUEnever evaluated
FALSEnever evaluated
0
266 m_drag_icon_window->updateGeometry(globalPos);
never executed: m_drag_icon_window->updateGeometry(globalPos);
0
267}
never executed: end of block
0
268-
269void QBasicDrag::drop(const QPoint &)-
270{-
271 disableEventFilter();-
272 restoreCursor();-
273 m_drag_icon_window->setVisible(false);-
274}
never executed: end of block
0
275-
276void QBasicDrag::exitDndEventLoop()-
277{-
278 if (m_eventLoop && m_eventLoop->isRunning())
m_eventLoopDescription
TRUEnever evaluated
FALSEnever evaluated
m_eventLoop->isRunning()Description
TRUEnever evaluated
FALSEnever evaluated
0
279 m_eventLoop->exit();
never executed: m_eventLoop->exit();
0
280}
never executed: end of block
0
281-
282void QBasicDrag::updateCursor(Qt::DropAction action)-
283{-
284#ifndef QT_NO_CURSOR-
285 Qt::CursorShape cursorShape = Qt::ForbiddenCursor;-
286 if (canDrop()) {
canDrop()Description
TRUEnever evaluated
FALSEnever evaluated
0
287 switch (action) {-
288 case Qt::CopyAction:
never executed: case Qt::CopyAction:
0
289 cursorShape = Qt::DragCopyCursor;-
290 break;
never executed: break;
0
291 case Qt::LinkAction:
never executed: case Qt::LinkAction:
0
292 cursorShape = Qt::DragLinkCursor;-
293 break;
never executed: break;
0
294 default:
never executed: default:
0
295 cursorShape = Qt::DragMoveCursor;-
296 break;
never executed: break;
0
297 }-
298 }-
299-
300 QCursor *cursor = QGuiApplication::overrideCursor();-
301 QPixmap pixmap = m_drag->dragCursor(action);-
302 if (!cursor) {
!cursorDescription
TRUEnever evaluated
FALSEnever evaluated
0
303 QGuiApplication::changeOverrideCursor((pixmap.isNull()) ? QCursor(cursorShape) : QCursor(pixmap));-
304 } else {
never executed: end of block
0
305 if (!pixmap.isNull()) {
!pixmap.isNull()Description
TRUEnever evaluated
FALSEnever evaluated
0
306 if ((cursor->pixmap().cacheKey() != pixmap.cacheKey())) {
(cursor->pixma...ap.cacheKey())Description
TRUEnever evaluated
FALSEnever evaluated
0
307 QGuiApplication::changeOverrideCursor(QCursor(pixmap));-
308 }
never executed: end of block
0
309 } else {
never executed: end of block
0
310 if (cursorShape != cursor->shape()) {
cursorShape != cursor->shape()Description
TRUEnever evaluated
FALSEnever evaluated
0
311 QGuiApplication::changeOverrideCursor(QCursor(cursorShape));-
312 }
never executed: end of block
0
313 }
never executed: end of block
0
314 }-
315#endif-
316 updateAction(action);-
317}
never executed: end of block
0
318-
319/*!-
320 \class QSimpleDrag-
321 \brief QSimpleDrag implements QBasicDrag for Drag and Drop operations within the Qt Application itself.-
322 \since 5.0-
323 \internal-
324 \ingroup qpa-
325-
326 The class checks whether the receiving window is a window of the Qt application-
327 and sets the state accordingly. It does not take windows of other applications-
328 into account.-
329*/-
330-
331QSimpleDrag::QSimpleDrag() : m_current_window(0)-
332{-
333}
never executed: end of block
0
334-
335QMimeData *QSimpleDrag::platformDropData()-
336{-
337 if (drag())
drag()Description
TRUEnever evaluated
FALSEnever evaluated
0
338 return drag()->mimeData();
never executed: return drag()->mimeData();
0
339 return 0;
never executed: return 0;
0
340}-
341-
342void QSimpleDrag::startDrag()-
343{-
344 QBasicDrag::startDrag();-
345 m_current_window = topLevelAt(QCursor::pos());-
346 if (m_current_window) {
m_current_windowDescription
TRUEnever evaluated
FALSEnever evaluated
0
347 QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_current_window, drag()->mimeData(), QCursor::pos(), drag()->supportedActions());-
348 setCanDrop(response.isAccepted());-
349 updateCursor(response.acceptedAction());-
350 } else {
never executed: end of block
0
351 setCanDrop(false);-
352 updateCursor(Qt::IgnoreAction);-
353 }
never executed: end of block
0
354 setExecutedDropAction(Qt::IgnoreAction);-
355}
never executed: end of block
0
356-
357void QSimpleDrag::cancel()-
358{-
359 QBasicDrag::cancel();-
360 if (drag() && m_current_window) {
drag()Description
TRUEnever evaluated
FALSEnever evaluated
m_current_windowDescription
TRUEnever evaluated
FALSEnever evaluated
0
361 QWindowSystemInterface::handleDrag(m_current_window, 0, QPoint(), Qt::IgnoreAction);-
362 m_current_window = 0;-
363 }
never executed: end of block
0
364}
never executed: end of block
0
365-
366void QSimpleDrag::move(const QPoint &globalPos)-
367{-
368 //### not high-DPI aware-
369 moveShapedPixmapWindow(globalPos);-
370 QWindow *window = topLevelAt(globalPos);-
371 if (!window)
!windowDescription
TRUEnever evaluated
FALSEnever evaluated
0
372 return;
never executed: return;
0
373-
374 const QPoint pos = globalPos - window->geometry().topLeft();-
375 const QPlatformDragQtResponse qt_response =-
376 QWindowSystemInterface::handleDrag(window, drag()->mimeData(), pos, drag()->supportedActions());-
377-
378 updateCursor(qt_response.acceptedAction());-
379 setCanDrop(qt_response.isAccepted());-
380}
never executed: end of block
0
381-
382void QSimpleDrag::drop(const QPoint &globalPos)-
383{-
384 //### not high-DPI aware-
385-
386 QBasicDrag::drop(globalPos);-
387 QWindow *window = topLevelAt(globalPos);-
388 if (!window)
!windowDescription
TRUEnever evaluated
FALSEnever evaluated
0
389 return;
never executed: return;
0
390-
391 const QPoint pos = globalPos - window->geometry().topLeft();-
392 const QPlatformDropQtResponse response =-
393 QWindowSystemInterface::handleDrop(window, drag()->mimeData(),pos, drag()->supportedActions());-
394 if (response.isAccepted()) {
response.isAccepted()Description
TRUEnever evaluated
FALSEnever evaluated
0
395 setExecutedDropAction(response.acceptedAction());-
396 } else {
never executed: end of block
0
397 setExecutedDropAction(Qt::IgnoreAction);-
398 }
never executed: end of block
0
399}-
400-
401#endif // QT_NO_DRAGANDDROP-
402-
403QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

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