src/gui/kernel/qdnd_s60.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    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 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    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 
       
    61 QT_BEGIN_NAMESPACE
       
    62 //### artistic impression of Symbians default DnD cursor ?
       
    63 
       
    64 static QPixmap *defaultPm = 0;
       
    65 static const int default_pm_hotx = -50;
       
    66 static const int default_pm_hoty = -50;
       
    67 static 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
       
    84 static Qt::DropAction global_accepted_action = Qt::MoveAction;
       
    85 static Qt::DropActions possible_actions = Qt::IgnoreAction;
       
    86 
       
    87 
       
    88 // static variables in place of a proper cross-process solution
       
    89 static QDrag *drag_object;
       
    90 static bool qt_symbian_dnd_dragging = false;
       
    91 
       
    92 
       
    93 static Qt::KeyboardModifiers oldstate;
       
    94 
       
    95 void 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 
       
   115 void QDragManager::timerEvent(QTimerEvent *) { }
       
   116 
       
   117 void QDragManager::move(const QPoint&) {
       
   118 }
       
   119 
       
   120 void 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 
       
   135 bool 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 
       
   253 Qt::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
       
   275 
       
   276     object->d_func()->target = 0;
       
   277 
       
   278     qApp->installEventFilter(this);
       
   279 
       
   280     global_accepted_action = defaultAction(dragPrivate()->possible_actions, Qt::NoModifier);
       
   281     qt_symbian_dnd_dragging = true;
       
   282 
       
   283     eventLoop = new QEventLoop;
       
   284     // block
       
   285     (void) eventLoop->exec(QEventLoop::AllEvents);
       
   286     delete eventLoop;
       
   287     eventLoop = 0;
       
   288 
       
   289 #ifndef QT_NO_CURSOR
       
   290     qt_symbian_set_cursor_visible(false);
       
   291 
       
   292     overrideCursor = QCursor(); //deref the cursor data
       
   293     qt_symbian_dnd_dragging = false;
       
   294 #endif
       
   295 
       
   296     return global_accepted_action;
       
   297 }
       
   298 
       
   299 
       
   300 void QDragManager::cancel(bool deleteSource)
       
   301 {
       
   302     beingCancelled = true;
       
   303 
       
   304     if (object->target()) {
       
   305         QDragLeaveEvent dle;
       
   306         QApplication::sendEvent(object->target(), &dle);
       
   307     }
       
   308 
       
   309     if (drag_object) {
       
   310         if (deleteSource)
       
   311             object->deleteLater();
       
   312         drag_object = object = 0;
       
   313     }
       
   314 
       
   315 #ifndef QT_NO_CURSOR
       
   316     if (restoreCursor) {
       
   317         QApplication::restoreOverrideCursor();
       
   318         restoreCursor = false;
       
   319     }
       
   320 #endif
       
   321 
       
   322     global_accepted_action = Qt::IgnoreAction;
       
   323 }
       
   324 
       
   325 
       
   326 void QDragManager::drop()
       
   327 {
       
   328 #ifndef QT_NO_CURSOR
       
   329     if (restoreCursor) {
       
   330         QApplication::restoreOverrideCursor();
       
   331         restoreCursor = false;
       
   332     }
       
   333 #endif
       
   334 }
       
   335 
       
   336 QVariant QDropData::retrieveData_sys(const QString &mimetype, QVariant::Type type) const
       
   337 {
       
   338     if (!drag_object)
       
   339         return QVariant();
       
   340     QByteArray data =  drag_object->mimeData()->data(mimetype);
       
   341     if (type == QVariant::String)
       
   342         return QString::fromUtf8(data);
       
   343     return data;
       
   344 }
       
   345 
       
   346 bool QDropData::hasFormat_sys(const QString &format) const
       
   347 {
       
   348     return formats().contains(format);
       
   349 }
       
   350 
       
   351 QStringList QDropData::formats_sys() const
       
   352 {
       
   353     if (drag_object)
       
   354         return drag_object->mimeData()->formats();
       
   355     return QStringList();
       
   356 }
       
   357 
       
   358 QT_END_NAMESPACE
       
   359 #endif // QT_NO_DRAGANDDROP