source: trunk/src/gui/kernel/qdnd_s60.cpp@ 603

Last change on this file since 603 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

  • Property svn:eol-style set to native
File size: 10.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qapplication.h"
43
44#ifndef QT_NO_DRAGANDDROP
45
46#include "qwidget.h"
47#include "qdatetime.h"
48#include "qbitmap.h"
49#include "qcursor.h"
50#include "qevent.h"
51#include "qpainter.h"
52#include "qdnd_p.h"
53#include "qt_s60_p.h"
54
55#include <COECNTRL.H>
56// pointer cursor
57#include <w32std.h>
58#include <gdi.h>
59#include <QCursor>
60
61QT_BEGIN_NAMESPACE
62//### artistic impression of Symbians default DnD cursor ?
63
64static QPixmap *defaultPm = 0;
65static const int default_pm_hotx = -50;
66static const int default_pm_hoty = -50;
67static const char *const default_pm[] = {
68"13 9 3 1",
69". c None",
70" c #000000",
71"X c #FFFFFF",
72"X X X X X X X",
73" X X X X X X ",
74"X ......... X",
75" X.........X ",
76"X ......... X",
77" X.........X ",
78"X ......... X",
79" X X X X X X ",
80"X X X X X X X",
81};
82//### actions need to be redefined for S60
83// Shift/Ctrl handling, and final drop status
84static Qt::DropAction global_accepted_action = Qt::MoveAction;
85static Qt::DropActions possible_actions = Qt::IgnoreAction;
86
87
88// static variables in place of a proper cross-process solution
89static QDrag *drag_object;
90static bool qt_symbian_dnd_dragging = false;
91
92
93static Qt::KeyboardModifiers oldstate;
94
95void QDragManager::updatePixmap()
96{
97 QPixmap pm;
98 QPoint pm_hot(default_pm_hotx,default_pm_hoty);
99 if (drag_object) {
100 pm = drag_object->pixmap();
101 if (!pm.isNull())
102 pm_hot = drag_object->hotSpot();
103 }
104 if (pm.isNull()) {
105 if (!defaultPm)
106 defaultPm = new QPixmap(default_pm);
107 pm = *defaultPm;
108 }
109#ifndef QT_NO_CURSOR
110 QCursor cursor(pm, pm_hot.x(), pm_hot.y());
111 overrideCursor = cursor;
112#endif
113}
114
115void QDragManager::timerEvent(QTimerEvent *) { }
116
117void QDragManager::move(const QPoint&) {
118}
119
120void QDragManager::updateCursor()
121{
122#ifndef QT_NO_CURSOR
123 QCursor cursor = willDrop ? overrideCursor : Qt::ForbiddenCursor;
124 if (!restoreCursor) {
125 QApplication::setOverrideCursor(cursor);
126 restoreCursor = true;
127 }
128 else {
129 QApplication::changeOverrideCursor(cursor);
130 }
131#endif
132}
133
134
135bool QDragManager::eventFilter(QObject *o, QEvent *e)
136{
137 if (beingCancelled) {
138 return false;
139 }
140 if (!o->isWidgetType())
141 return false;
142
143 switch(e->type()) {
144 case QEvent::MouseButtonPress:
145 {
146 }
147 case QEvent::MouseMove:
148 {
149 if (!object) { //#### this should not happen
150 qWarning("QDragManager::eventFilter: No object");
151 return true;
152 }
153 QDragManager *manager = QDragManager::self();
154 QMimeData *dropData = manager->object ? manager->dragPrivate()->data : manager->dropData;
155 if (manager->object)
156 possible_actions = manager->dragPrivate()->possible_actions;
157 else
158 possible_actions = Qt::IgnoreAction;
159
160 QMouseEvent *me = (QMouseEvent *)e;
161
162 if (me->buttons()) {
163 Qt::DropAction prevAction = global_accepted_action;
164 QWidget *cw = QApplication::widgetAt(me->globalPos());
165 // map the Coords relative to the window.
166 if (!cw)
167 return true;
168
169 while (cw && !cw->acceptDrops() && !cw->isWindow())
170 cw = cw->parentWidget();
171
172 bool oldWillDrop = willDrop;
173 if (object->target() != cw) {
174 if (object->target()) {
175 QDragLeaveEvent dle;
176 QApplication::sendEvent(object->target(), &dle);
177 willDrop = false;
178 global_accepted_action = Qt::IgnoreAction;
179 if (oldWillDrop != willDrop)
180 updateCursor();
181 object->d_func()->target = 0;
182 }
183 if (cw && cw->acceptDrops()) {
184 object->d_func()->target = cw;
185 QDragEnterEvent dee(cw->mapFromGlobal(me->globalPos()), possible_actions, dropData,
186 me->buttons(), me->modifiers());
187 QApplication::sendEvent(object->target(), &dee);
188 willDrop = dee.isAccepted() && dee.dropAction() != Qt::IgnoreAction;
189 global_accepted_action = willDrop ? dee.dropAction() : Qt::IgnoreAction;
190 if (oldWillDrop != willDrop)
191 updateCursor();
192 }
193 } else if (cw) {
194 QDragMoveEvent dme(cw->mapFromGlobal(me->globalPos()), possible_actions, dropData,
195 me->buttons(), me->modifiers());
196 if (global_accepted_action != Qt::IgnoreAction) {
197 dme.setDropAction(global_accepted_action);
198 dme.accept();
199 }
200 QApplication::sendEvent(cw, &dme);
201 willDrop = dme.isAccepted();
202 global_accepted_action = willDrop ? dme.dropAction() : Qt::IgnoreAction;
203 if (oldWillDrop != willDrop) {
204 updatePixmap();
205 updateCursor();
206 }
207 }
208 if (global_accepted_action != prevAction)
209 emitActionChanged(global_accepted_action);
210 }
211 return true; // Eat all mouse events
212 }
213
214 case QEvent::MouseButtonRelease:
215 {
216 qApp->removeEventFilter(this);
217#ifndef QT_NO_CURSOR
218 if (restoreCursor) {
219 QApplication::restoreOverrideCursor();
220 willDrop = false;
221 restoreCursor = false;
222 }
223#endif
224 if (object && object->target()) {
225
226 QMouseEvent *me = (QMouseEvent *)e;
227
228 QDragManager *manager = QDragManager::self();
229 QMimeData *dropData = manager->object ? manager->dragPrivate()->data : manager->dropData;
230
231 QDropEvent de(object->target()->mapFromGlobal(me->globalPos()), possible_actions, dropData,
232 me->buttons(), me->modifiers());
233 QApplication::sendEvent(object->target(), &de);
234 if (de.isAccepted())
235 global_accepted_action = de.dropAction();
236 else
237 global_accepted_action = Qt::IgnoreAction;
238
239 if (object)
240 object->deleteLater();
241 drag_object = object = 0;
242 }
243 eventLoop->exit();
244 return true; // Eat all mouse events
245 }
246
247 default:
248 break;
249 }
250 return false;
251}
252
253Qt::DropAction QDragManager::drag(QDrag *o)
254{
255 Q_ASSERT(!qt_symbian_dnd_dragging);
256 if (object == o || !o || !o->source())
257 return Qt::IgnoreAction;
258
259 if (object) {
260 cancel();
261 qApp->removeEventFilter(this);
262 beingCancelled = false;
263 }
264
265 object = drag_object = o;
266
267 oldstate = Qt::NoModifier; // #### Should use state that caused the drag
268 willDrop = false;
269 updatePixmap();
270 updateCursor();
271
272#ifndef QT_NO_CURSOR
273 qt_symbian_set_cursor_visible(true); //force cursor on even for touch phone
274#endif