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) {-
74 QWindow *w = list.at(i);-
75 if (w->isVisible() && w->geometry().contains(pos) && !qobject_cast<QShapedPixmapWindow*>(w))-
76 return w;-
77 }-
78 return 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}-
101-
102QBasicDrag::~QBasicDrag()-
103{-
104 delete m_drag_icon_window;-
105}-
106-
107void QBasicDrag::enableEventFilter()-
108{-
109 qApp->installEventFilter(this);-
110}-
111-
112void QBasicDrag::disableEventFilter()-
113{-
114 qApp->removeEventFilter(this);-
115}-
116-
117-
118static inline QPoint getNativeMousePos(QEvent *e, QObject *o)-
119{-
120 return QHighDpi::toNativePixels(static_cast<QMouseEvent *>(e)->globalPos(), qobject_cast<QWindow*>(o));-
121}-
122-
123bool QBasicDrag::eventFilter(QObject *o, QEvent *e)-
124{-
125 Q_UNUSED(o);-
126-
127 if (!m_drag) {-
128 if (e->type() == QEvent::KeyRelease && static_cast<QKeyEvent*>(e)->key() == Qt::Key_Escape) {-
129 disableEventFilter();-
130 exitDndEventLoop();-
131 return true; // block the key release-
132 }-
133 return false;-
134 }-
135-
136 switch (e->type()) {-
137 case QEvent::ShortcutOverride:-
138 // prevent accelerators from firing while dragging-
139 e->accept();-
140 return true;-
141-
142 case QEvent::KeyPress:-
143 case QEvent::KeyRelease:-
144 {-
145 QKeyEvent *ke = static_cast<QKeyEvent *>(e);-
146 if (ke->key() == Qt::Key_Escape && e->type() == QEvent::KeyPress) {-
147 cancel();-
148 disableEventFilter();-
149 exitDndEventLoop();-
150-
151 }-
152 return true; // Eat all key events-
153 }-
154-
155 case QEvent::MouseMove:-
156 {-
157 QPoint nativePosition = getNativeMousePos(e, o);-
158 move(nativePosition);-
159 return true; // Eat all mouse move events-
160 }-
161 case QEvent::MouseButtonRelease:-
162 disableEventFilter();-
163 if (canDrop()) {-
164 QPoint nativePosition = getNativeMousePos(e, o);-
165 drop(nativePosition);-
166 } else {-
167 cancel();-
168 }-
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-
172 case QEvent::MouseButtonDblClick:-
173 case QEvent::Wheel:-
174 return true;-
175 default:-
176 break;-
177 }-
178 return false;-
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;-
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) {-
212#ifndef QT_NO_CURSOR-
213 QGuiApplication::restoreOverrideCursor();-
214#endif-
215 m_restoreCursor = false;-
216 }-
217}-
218-
219void QBasicDrag::startDrag()-
220{-
221 QPoint pos;-
222#ifndef QT_NO_CURSOR-
223 pos = QCursor::pos();-
224 if (pos.x() == int(qInf())) {-
225 // ### fixme: no mouse pos registered. Get pos from touch...-
226 pos = QPoint();-
227 }-
228#endif-
229 recreateShapedPixmapWindow(m_screen, pos);-
230 enableEventFilter();-
231}-
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}-
250-
251void QBasicDrag::cancel()-
252{-
253 disableEventFilter();-
254 restoreCursor();-
255 m_drag_icon_window->setVisible(false);-
256}-
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)-
266 m_drag_icon_window->updateGeometry(globalPos);-
267}-
268-
269void QBasicDrag::drop(const QPoint &)-
270{-
271 disableEventFilter();-
272 restoreCursor();-
273 m_drag_icon_window->setVisible(false);-
274}-
275-
276void QBasicDrag::exitDndEventLoop()-
277{-
278 if (m_eventLoop && m_eventLoop->isRunning())-
279 m_eventLoop->exit();-
280}-
281-
282void QBasicDrag::updateCursor(Qt::DropAction action)-
283{-
284#ifndef QT_NO_CURSOR-
285 Qt::CursorShape cursorShape = Qt::ForbiddenCursor;-
286 if (canDrop()) {-
287 switch (action) {-
288 case Qt::CopyAction:-
289 cursorShape = Qt::DragCopyCursor;-
290 break;-
291 case Qt::LinkAction:-
292 cursorShape = Qt::DragLinkCursor;-
293 break;-
294 default:-
295 cursorShape = Qt::DragMoveCursor;-
296 break;-
297 }-
298 }-
299-
300 QCursor *cursor = QGuiApplication::overrideCursor();-
301 QPixmap pixmap = m_drag->dragCursor(action);-
302 if (!cursor) {-
303 QGuiApplication::changeOverrideCursor((pixmap.isNull()) ? QCursor(cursorShape) : QCursor(pixmap));-
304 } else {-
305 if (!pixmap.isNull()) {-
306 if ((cursor->pixmap().cacheKey() != pixmap.cacheKey())) {-
307 QGuiApplication::changeOverrideCursor(QCursor(pixmap));-
308 }-
309 } else {-
310 if (cursorShape != cursor->shape()) {-
311 QGuiApplication::changeOverrideCursor(QCursor(cursorShape));-
312 }-
313 }-
314 }-
315#endif-
316 updateAction(action);-
317}-
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}-
334-
335QMimeData *QSimpleDrag::platformDropData()-
336{-
337 if (drag())-
338 return drag()->mimeData();-
339 return 0;-
340}-
341-
342void QSimpleDrag::startDrag()-
343{-
344 QBasicDrag::startDrag();-
345 m_current_window = topLevelAt(QCursor::pos());-
346 if (m_current_window) {-
347 QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_current_window, drag()->mimeData(), QCursor::pos(), drag()->supportedActions());-
348 setCanDrop(response.isAccepted());-
349 updateCursor(response.acceptedAction());-
350 } else {-
351 setCanDrop(false);-
352 updateCursor(Qt::IgnoreAction);-
353 }-
354 setExecutedDropAction(Qt::IgnoreAction);-
355}-
356-
357void QSimpleDrag::cancel()-
358{-
359 QBasicDrag::cancel();-
360 if (drag() && m_current_window) {-
361 QWindowSystemInterface::handleDrag(m_current_window, 0, QPoint(), Qt::IgnoreAction);-
362 m_current_window = 0;-
363 }-
364}-
365-
366void QSimpleDrag::move(const QPoint &globalPos)-
367{-
368 //### not high-DPI aware-
369 moveShapedPixmapWindow(globalPos);-
370 QWindow *window = topLevelAt(globalPos);-
371 if (!window)-
372 return;-
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}-
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)-
389 return;-
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()) {-
395 setExecutedDropAction(response.acceptedAction());-
396 } else {-
397 setExecutedDropAction(Qt::IgnoreAction);-
398 }-
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