Changeset 442


Ignore:
Timestamp:
Dec 28, 2009, 2:50:23 AM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

gui: A bunch of updates to the DND code (the drop site party).

Location:
trunk/src/gui/kernel
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/gui/kernel/qdnd_pm.cpp

    r439 r442  
    7878    ~QPMDragData();
    7979
    80     void initialize( DRAGINFO *di );
    81     void reset( bool isAccepted, bool isActAccepted );
    82     void reset() { reset( FALSE, FALSE ); }
    83 
    84     void setDropped( bool d ) { dropped = d; }
     80    void initialize();
     81    void reset();
     82    void reset() { reset(); }
     83
     84    void setDropped() { dropped = d; }
    8585    bool isDropped() const { return dropped; }
    8686
     
    100100
    101101    DRAGINFO *di;
    102     // @todo later
    103 //  QPtrList<QPMMime::DropWorker> workers;
     102    QList<QPMMime::DropWorker*> workers;
    104103};
    105104
     
    118117
    119118    QDragManager *manager = QDragManager::self();
    120     Q_ASSERT(manager->dropData->d == this);
    121     manager->dropData->d = 0;
     119    if (manager) {
     120        Q_ASSERT(manager->dropData->d == this);
     121        manager->dropData->d = 0;
     122    }
    122123}
    123124
     
    140141    gotWorkers = true;
    141142
    142     // @todo later
    143 #if 0
    144     // go through all convertors and collect DropWorkers to use
    145     QPtrList<QPMMime> mimes = QPMMime::all();
    146     for ( QPMMime *mime = mimes.first(); mime; mime = mimes.next() ) {
    147         QPMMime::DropWorker *wrk = mime->dropWorkerFor( di );
    148         if ( wrk ) {
    149             if ( wrk->isExclusive() ) {
     143    // go through all converters and collect DropWorkers to use
     144    foreach (QPMMime *mime, QPMMime::all()) {
     145        QPMMime::DropWorker *wrk = mime->dropWorkerFor(di);
     146        if (wrk) {
     147            if (wrk->isExclusive()) {
    150148                // ignore all other workers if some of them identified itself
    151149                // as exclusive
    152150                workers.clear();
    153                 workers.append( wrk );
     151                workers.append();
    154152                break;
    155153            }
    156             // ensure there are no duplicates
    157             if ( !workers.containsRef( wrk ) )
    158                 workers.append( wrk );
     154            // ensure there are no duplicates
     155            if ()
     156                workers.append();
    159157        }
    160158    }
     
    163161
    164162    // init all workers
    165     for ( QPMMime::DropWorker *w = workers.first(); w; w = workers.next() ) {
     163    for) {
    166164        w->nfo = di;
    167165        w->init();
    168166    }
    169 #endif
    170 }
    171 
    172 void QPMDragData::reset(bool isAccepted, bool isActAccepted)
     167}
     168
     169void QPMDragData::reset(bool isAccepted)
    173170{
    174171    if (!initialized)
    175172        return;
    176173
    177     // @todo later
    178 #if 0
    179174    // cleanup all workers
    180     for ( QPMMime::DropWorker *w = workers.first(); w; w = workers.next() ) {
    181         w->cleanup( isAccepted, isActAccepted );
    182         w->nfo = NULL;
     175    for) {
     176        w->cleanup();
     177        w->nfo = ;
    183178    }
    184179
    185180    workers.clear();
    186 #endif
    187     di = NULL;
    188     initialized = dropped = gotWorkers = FALSE;
     181    di = 0;
     182    initialized = dropped = gotWorkers = false;
    189183}
    190184
    191185bool QPMDragData::hasFormat_sys(const QString &mimeType)
    192186{
     187
     188
     189
     190
     191
     192
     193
    193194    return false;
    194195}
     
    196197QStringList QPMDragData::formats_sys()
    197198{
    198     return QStringList();
     199    QStringList mimes;
     200
     201    if (!gotWorkers)
     202        initWorkers();
     203
     204    foreach (QPMMime::DropWorker *w, workers)
     205        mimes << w->formats();
     206
     207    return mimes;
    199208}
    200209
     
    208217        return result;
    209218
     219
     220
     221
     222
     223
     224
     225
     226
     227
     228
    210229    return result;
    211230}
    212231
    213 // @todo later
    214 #if 0
    215 class QPMDropEvent : public QDropEvent
    216 {
    217 public:
    218     QPMDropEvent( const QPoint &pos, QPMDragData *data )
    219         : QDropEvent( pos ) { d = data; }
    220 
    221     inline bool isTrulyAccepted() const { return accpt; }
    222     inline bool isActionTrulyAccepted() const { return accptact; }
    223 };
    224 
    225 class QPMDragEnterEvent : public QDragEnterEvent
    226 {
    227 public:
    228     QPMDragEnterEvent( const QPoint &pos, QPMDragData *data )
    229         : QDragEnterEvent( pos ) { d = data; }
    230 
    231     inline bool isTrulyAccepted() const { return accpt; }
    232     inline bool isActionTrulyAccepted() const { return accptact; }
    233 };
    234 
    235 class QPMDragMoveEvent : public QDragMoveEvent
    236 {
    237 public:
    238     QPMDragMoveEvent( const QPoint &pos, QPMDragData *data )
    239         : QDragMoveEvent( pos ) { d = data; }
    240 
    241     inline bool isTrulyAccepted() const { return accpt; }
    242     inline bool isActionTrulyAccepted() const { return accptact; }
    243 };
    244 
    245 bool QDropEvent::provides( const char* mimeType ) const
    246 {
    247     QPMDragData *data = static_cast<QPMDragData *> (d);
    248     Q_ASSERT( data );
    249     if ( !data )
    250         return FALSE;
    251 
    252     return data->provides( mimeType );
    253 }
    254 
    255 const char *QDropEvent::format( int fn ) const
    256 {
    257     QPMDragData *data = static_cast<QPMDragData *> (d);
    258     Q_ASSERT( data );
    259     if ( !data )
    260         return NULL;
    261 
    262     return data->format( fn );
    263 }
    264 
    265 QByteArray QDropEvent::encodedData( const char *format ) const
    266 {
    267     QByteArray array;
    268 
    269     QPMDragData *data = static_cast<QPMDragData *> (d);
    270     Q_ASSERT( data );
    271 
    272     if ( !data || !data->isDropped() ) {
    273         // This is a QDragEnterEvent/QDragMoveEvent subclass; we cannot provide
    274         // any MIME contents yet because it's impossible to do data transfers
    275         // before DM_DROP is sent. Return shortly.
    276         return array;
    277     }
    278 
    279     array = data->encodedData( format );
    280     return array;
    281 }
    282 #endif
     232static Qt::DropActions toQDragDropActions(USHORT ops)
     233{
     234    Qt::DropActions actions = Qt::IgnoreAction;
     235    if (ops & DO_LINKABLE)
     236        actions |= Qt::LinkAction;
     237    if (ops & DO_COPYABLE)
     238        actions |= Qt::CopyAction;
     239    if (ops & DO_MOVEABLE)
     240        actions |= Qt::MoveAction;
     241    return actions;
     242}
     243
     244static Qt::DropAction toQDragDropAction(USHORT op)
     245{
     246    if (op == DO_LINK)
     247        return Qt::LinkAction;
     248    if (op == DO_COPY)
     249        return Qt::CopyAction;
     250    if (op == DO_MOVE)
     251        return Qt::MoveAction;
     252    return Qt::IgnoreAction;
     253}
     254
     255static USHORT toPmDragDropOp(Qt::DropActions action)
     256{
     257    if (action & Qt::LinkAction)
     258        return DO_LINK;
     259    if (action & Qt::CopyAction)
     260        return DO_COPY;
     261    if (action & Qt::MoveAction)
     262        return DO_MOVE;
     263    return DO_UNKNOWN;
     264}
    283265
    284266/*!
     
    288270MRESULT qt_dispatchDragAndDrop(QWidget *widget, const QMSG &qmsg)
    289271{
     272
     273
    290274    static HWND lastDragOverHwnd = 0; // last target window
    291275    static USHORT lastDragOverOp = 0; // last DM_DRAGOVER operation
    292     static USHORT lastRealOp = 0; // last real op (never DO_DEFAULT or DO_UNKNOWN)
    293     static USHORT defaultOp = 0; // default op for DO_DEFAULT or DO_UNKNOWN
    294276
    295277    static USHORT supportedOps = 0; // operations supported by all items
    296     static bool sourceAllowsOp = FALSE; // does source allow requested operation
    297 
    298     static bool lastAccept = FALSE; // last reply from the target
    299     static bool lastAcceptAction = FALSE; // last action reply from the target
     278
     279    static USHORT lastDropReply = DOR_NEVERDROP; // last reply to DM_DRAGOVER
     280    static USHORT lastOpRequest = DO_UNKNOWN; // last op requested in DM_DRAGOVER
     281
     282    static Qt::DropAction lastProposedAction = Qt::IgnoreAction; // last proposed action
     283    static QRect lastAnswerRect; // last accepted rectangle from the target
     284    // @todo use lastAnswerRect to compress DM_DRAGOVER events
    300285
    301286    static QPMDragData dragData;
     
    305290    BOOL ok = FALSE;
    306291
    307     switch( qmsg.msg ) {
     292    switch) {
    308293        case DM_DRAGOVER: {
     294
     295
     296
    309297            bool first = lastDragOverHwnd != qmsg.hwnd;
    310298            if (first) {
    311299                // the first DM_DRAGOVER message
    312300                lastDragOverHwnd = qmsg.hwnd;
    313                 lastAccept = lastAcceptAction = FALSE;
     301                lastDropReply = DOR_NEVERDROP;
     302                lastOpRequest = DO_UNKNOWN;
     303                lastProposedAction = Qt::IgnoreAction;
     304                lastAnswerRect = QRect();
    314305                supportedOps = DO_COPYABLE | DO_MOVEABLE | DO_LINKABLE;
    315306                // ensure drag data is reset (just in case of a wrong msg flow...)
     
    355346                        // items don't have even a single common operation...
    356347                        dropReply = DOR_NEVERDROP;
    357                     } else {
    358                         // determine the default operation
    359                         // (in order MOVE, COPY, LINK, for compatibility with Win32)
    360                         if      (supportedOps & DO_MOVEABLE) defaultOp = DO_MOVE;
    361                         else if (supportedOps & DO_COPYABLE) defaultOp = DO_COPY;
    362                         else if (supportedOps & DO_LINKABLE) defaultOp = DO_LINK;
    363                         else Q_ASSERT(false); // should never happen
    364348                    }
    365349                }
     
    367351
    368352            if (dropReply != DOR_NEVERDROP) {
     353
     354
    369355
    370356                if (first || lastDragOverOp != info->usOperation) {
    371357                    // the current drop operation was changed by a modifier key
    372358                    lastDragOverOp = info->usOperation;
    373                     lastRealOp = info->usOperation;
    374                     if (lastRealOp == DO_DEFAULT || lastRealOp == DO_UNKNOWN) {
     359                    ealOp = info->usOperation;
     360                    if (ealOp == DO_UNKNOWN) {
    375361                        // the default operation is requested
    376                         lastRealOp = defaultOp;
     362                        ;
    377363                    }
    378364                    sourceAllowsOp =
    379                         ((supportedOps & DO_MOVEABLE) && lastRealOp == DO_MOVE) ||
    380                         ((supportedOps & DO_COPYABLE) && lastRealOp == DO_COPY) ||
    381                         ((supportedOps & DO_LINKABLE) && lastRealOp == DO_LINK);
     365                        ((supportedOps & DO_MOVEABLE) && ealOp == DO_MOVE) ||
     366                        ((supportedOps & DO_COPYABLE) && ealOp == DO_COPY) ||
     367                        ((supportedOps & DO_LINKABLE) && ealOp == DO_LINK);
    382368                }
    383369
     
    387373                // the drop. Other platforms seem to do the same.
    388374
    389                 // convert the operation to an Action
    390                 Qt::DropAction action = Qt::CopyAction;
    391                 if      (lastRealOp == DO_COPY) action = Qt::CopyAction;
    392                 else if (lastRealOp == DO_MOVE) action = Qt::MoveAction;
    393                 else if (lastRealOp == DO_LINK) action = Qt::LinkAction;
    394                 else Q_ASSERT(false); // should never happen
    395 
    396375                // flip y coordinate
    397376                QPoint pnt(info->xDrop, info->yDrop);
     
    399378                pnt = widget->mapFromGlobal(pnt);
    400379
    401                 // initialize drag data used in QPMDrag.../QPMDrop... events
    402                 if (first)
     380                QDragManager *manager = QDragManager::self();
     381                QMimeData *data = manager->source() ? manager->dragPrivate()->data : manager->dropData;
     382
     383                Qt::DropAction action = toQDragDropAction(lastOpRequest);
     384
     385                if (first) {
    403386                    dragData.initialize(info);
    404 
    405                 // @todo later
    406 #if 0
    407                 QDropEvent *de = NULL;
    408                 QPMDragEnterEvent *dee = NULL;
    409                 QPMDragMoveEvent *dme = NULL;
    410 
    411                 if (first)
    412                     de = dee = new QPMDragEnterEvent(pnt, &dragData);
    413                 else
    414                     de = dme = new QPMDragMoveEvent(pnt, &dragData);
    415 
    416                 de->setAction(action);
    417                 de->accept(lastAccept);
    418                 de->acceptAction(lastAcceptAction);
    419 
    420                 QApplication::sendEvent(widget, de);
    421 
    422                 // if not allowed or not accepted, always reply DOR_NODROP
    423                 // to have DM_DRAGOVER delivered to us again in any case
    424 
    425                 dropReply = sourceAllowsOp && de->isAccepted() ?
    426                             DOR_DROP : DOR_NODROP;
    427 
    428                 lastAccept = dee ? dee->isTrulyAccepted() :
    429                                    dme->isTrulyAccepted();
    430                 lastAcceptAction = dee ? dee->isActionTrulyAccepted() :
    431                                          dme->isActionTrulyAccepted();
    432                 delete de;
    433 #endif
     387                    QDragEnterEvent dee(pnt, toQDragDropActions(supportedOps), data,
     388                                        QApplication::mouseButtons(),
     389                                        QApplication::keyboardModifiers());
     390                    QApplication::sendEvent(widget, &dee);
     391                    // if not allowed or not accepted, always reply DOR_NODROP
     392                    // to have DM_DRAGOVER delivered to us again in any case
     393                    if (sourceAllowsOp && dee.isAccepted()) {
     394                        dropReply = DOR_DROP;
     395                        action = dee.dropAction();
     396                        lastAnswerRect = dee.answerRect();
     397                    } else {
     398                        dropReply = DOR_NODROP;
     399                    }
     400                }
     401
     402                // note: according to the Qt documentation, the move event
     403                // is sent immediately after the enter event, do so (only if
     404                // the target accepts it)
     405                if (!first || dropReply == DOR_DROP) {
     406                    QDragEnterEvent dme(pnt, toQDragDropActions(supportedOps), data,
     407                                        QApplication::mouseButtons(),
     408                                        QApplication::keyboardModifiers());
     409                    // accept by default, since enter event was accepted.
     410                    dme.setDropAction(action);
     411                    dme.accept();
     412                    QApplication::sendEvent(widget, &dme);
     413                    if (sourceAllowsOp && dme.isAccepted()) {
     414                        dropReply = DOR_DROP;
     415                        action = dme.dropAction();
     416                    } else {
     417                        dropReply = DOR_NODROP;
     418                    }
     419                }
     420
     421                lastDropReply = dropReply;
     422                lastOpRequest = toPmDragDropOp(action);
    434423            }
    435424
    436425            DrgFreeDraginfo(info);
    437426
    438             return MRFROM2SHORT(dropReply, lastRealOp);
     427            return MRFROM2SHORT(dropReply, last);
    439428        }
    440429        case DM_DRAGLEAVE: {
     430
     431
    441432            // Odin32 apps produce incorrect message flow, ignore
    442433            Q_ASSERT(lastDragOverHwnd != 0);
     
    455446        }
    456447        case DM_DROP: {
     448
     449
    457450            // Odin32 apps produce incorrect message flow, ignore
    458451            Q_ASSERT(lastDragOverHwnd != 0);
     
    462455            // Odin32 apps send DM_DROP even if we replied DOR_NEVERDROP or
    463456            // DOR_NODROP, simulate DM_DRAGLEAVE
    464             Q_ASSERT(lastAccept || lastAcceptAction);
    465             if (!lastAccept && !lastAcceptAction) {
     457            Q_ASSERT(last);
     458            if () {
    466459                WinSendMsg(qmsg.hwnd, DM_DRAGLEAVE, 0, 0);
    467460                return 0;
     
    480473                return MRFROM2SHORT(DOR_NEVERDROP, 0);
    481474
    482             Q_ASSERT(lastRealOp == info->usOperation);
    483 
    484             // convert the operation to an Action
    485             Qt::DropAction action = Qt::CopyAction;
    486             if      (lastRealOp == DO_COPY ) action = Qt::CopyAction;
    487             else if (lastRealOp == DO_MOVE ) action = Qt::MoveAction;
    488             else if (lastRealOp == DO_LINK ) action = Qt::LinkAction;
    489             else Q_ASSERT(false); // should never happen
     475            Q_ASSERT(lastOpRequest == info->usOperation);
    490476
    491477            // flip y coordinate
    492478            QPoint pnt(info->xDrop, info->yDrop);
    493479            pnt.setY(QApplication::desktop()->height() - (pnt.y() + 1));
     480
     481
     482
     483
     484
     485
    494486
    495487            dragData.setDropped(true);
    496488
    497             // @todo later
    498 #if 0
    499             QPMDropEvent de(widget->mapFromGlobal(pnt), &dragData);
    500             de.setAction(action);
    501             de.accept(lastAccept);
    502             de.acceptAction(lastAcceptAction);
     489            QDropEvent de(pnt, action, data, QApplication::mouseButtons(),
     490                          QApplication::keyboardModifiers());
     491            if (lastDropReply == DOR_DROP)
     492                de.setDropAction(action);
    503493
    504494            QApplication::sendEvent(widget, &de);
    505495
    506             dragData.reset(de.isTrulyAccepted(), de.isActionTrulyAccepted());
    507 
    508             // If the target has accepted the particular Drop action (using
    509             // acceptProposedAction() rather than just accept()), it means that
    510             // it will perform the necessary operation on its own (for example,
    511             // will delete the source if the accepted action is Move). In this
    512             // case, we always send DMFL_TARGETFAIL to the source to prevent it
    513             // from doing the same on its side.
    514 
    515             ULONG targetReply =
    516                 de.isTrulyAccepted() && !de.isActionTrulyAccepted() ?
     496            if (lastDropReply == DOR_DROP)
     497                de.accept();
     498
     499            dragData.reset(de.isAccepted());
     500
     501            ULONG targetReply = de.isAccepted() ?
    517502                DMFL_TARGETSUCCESSFUL : DMFL_TARGETFAIL;
    518 #else
    519             ULONG targetReply = DMFL_TARGETFAIL;
    520 #endif
     503
     504            if (de.isAccepted() && de.dropAction() == Qt::TargetMoveAction) {
     505                // Qt::TargetMoveAction means that the target will move the
     506                // object (e.g. copy it to itself and delete from the source).
     507                // In this case, we always send DMFL_TARGETFAIL to the source to
     508                // prevent it from doing the same on its side.
     509                targetReply = DMFL_TARGETFAIL;
     510            }
    521511
    522512            // send DM_ENDCONVERSATION for every item
     
    528518                    continue;
    529519                // it is possible that this item required DM_RENDERPREPARE but
    530                 // returned FALSE in reply to it (so hwndItem may be NULL)
     520                // returned in reply to it (so hwndItem may be NULL)
    531521                if (!item->hwndItem)
    532522                    continue;
  • trunk/src/gui/kernel/qmime.h

    r441 r442  
    121121#endif
    122122
     123
    123124class QPMCoopDragWorker;
    124125
     
    141142        virtual void init() {}
    142143        // methods always implemented
    143         virtual bool cleanup( bool isCancelled) = 0;
     144        virtual bool cleanup(bool isCancelled) = 0;
    144145        virtual bool isExclusive() const = 0;
    145146        virtual ULONG itemCount() const = 0;
     
    210211
    211212        virtual void init() {}
    212         virtual void cleanup(bool isAccepted, bool isActAccepted) {}
     213        virtual void cleanup(bool isAccepted) {}
    213214        virtual bool isExclusive() const = 0;
    214215
     
    230231
    231232        // DropWorker interface
    232         void cleanup(bool isAccepted, bool isActAccepted);
     233        void cleanup(bool isAccepted);
    233234        bool isExclusive() const;
    234235        bool hasFormat(const QString &mimeType) const;
     
    294295    static void unregisterMimeType(ULONG mimeId);
    295296
     297
     298
    296299    static ULONG allocateMemory(size_t size);
    297300    static void freeMemory(ULONG addr);
     
    315318    friend class QClipboardData;
    316319    friend class QClipboard;
     320
    317321
    318322    struct Match
  • trunk/src/gui/kernel/qmime_pm.cpp

    r441 r442  
    743743}
    744744
    745 void QPMMime::DefaultDropWorker::cleanup(bool isAccepted, bool isActAccepted)
     745void QPMMime::DefaultDropWorker::cleanup(bool isAccepted)
    746746{
    747747    if (d->eventLoop.isRunning()) {
     
    13061306{
    13071307    WinDeleteAtom(WinQuerySystemAtomTable(), mimeId);
     1308
     1309
     1310
     1311
     1312
     1313
     1314
     1315
     1316
    13081317}
    13091318
Note: See TracChangeset for help on using the changeset viewer.