Changeset 442
- Timestamp:
- Dec 28, 2009, 2:50:23 AM (15 years ago)
- Location:
- trunk/src/gui/kernel
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/gui/kernel/qdnd_pm.cpp
r439 r442 78 78 ~QPMDragData(); 79 79 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; } 85 85 bool isDropped() const { return dropped; } 86 86 … … 100 100 101 101 DRAGINFO *di; 102 // @todo later 103 // QPtrList<QPMMime::DropWorker> workers; 102 QList<QPMMime::DropWorker*> workers; 104 103 }; 105 104 … … 118 117 119 118 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 } 122 123 } 123 124 … … 140 141 gotWorkers = true; 141 142 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()) { 150 148 // ignore all other workers if some of them identified itself 151 149 // as exclusive 152 150 workers.clear(); 153 workers.append( wrk);151 workers.append(); 154 152 break; 155 153 } 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(); 159 157 } 160 158 } … … 163 161 164 162 // init all workers 165 for ( QPMMime::DropWorker *w = workers.first(); w; w = workers.next()) {163 for) { 166 164 w->nfo = di; 167 165 w->init(); 168 166 } 169 #endif 170 } 171 172 void QPMDragData::reset(bool isAccepted, bool isActAccepted) 167 } 168 169 void QPMDragData::reset(bool isAccepted) 173 170 { 174 171 if (!initialized) 175 172 return; 176 173 177 // @todo later178 #if 0179 174 // 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 = ; 183 178 } 184 179 185 180 workers.clear(); 186 #endif 187 di = NULL; 188 initialized = dropped = gotWorkers = FALSE; 181 di = 0; 182 initialized = dropped = gotWorkers = false; 189 183 } 190 184 191 185 bool QPMDragData::hasFormat_sys(const QString &mimeType) 192 186 { 187 188 189 190 191 192 193 193 194 return false; 194 195 } … … 196 197 QStringList QPMDragData::formats_sys() 197 198 { 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; 199 208 } 200 209 … … 208 217 return result; 209 218 219 220 221 222 223 224 225 226 227 228 210 229 return result; 211 230 } 212 231 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 232 static 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 244 static 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 255 static 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 } 283 265 284 266 /*! … … 288 270 MRESULT qt_dispatchDragAndDrop(QWidget *widget, const QMSG &qmsg) 289 271 { 272 273 290 274 static HWND lastDragOverHwnd = 0; // last target window 291 275 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_UNKNOWN294 276 295 277 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 300 285 301 286 static QPMDragData dragData; … … 305 290 BOOL ok = FALSE; 306 291 307 switch ( qmsg.msg) {292 switch) { 308 293 case DM_DRAGOVER: { 294 295 296 309 297 bool first = lastDragOverHwnd != qmsg.hwnd; 310 298 if (first) { 311 299 // the first DM_DRAGOVER message 312 300 lastDragOverHwnd = qmsg.hwnd; 313 lastAccept = lastAcceptAction = FALSE; 301 lastDropReply = DOR_NEVERDROP; 302 lastOpRequest = DO_UNKNOWN; 303 lastProposedAction = Qt::IgnoreAction; 304 lastAnswerRect = QRect(); 314 305 supportedOps = DO_COPYABLE | DO_MOVEABLE | DO_LINKABLE; 315 306 // ensure drag data is reset (just in case of a wrong msg flow...) … … 355 346 // items don't have even a single common operation... 356 347 dropReply = DOR_NEVERDROP; 357 } else {358 // determine the default operation359 // (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 happen364 348 } 365 349 } … … 367 351 368 352 if (dropReply != DOR_NEVERDROP) { 353 354 369 355 370 356 if (first || lastDragOverOp != info->usOperation) { 371 357 // the current drop operation was changed by a modifier key 372 358 lastDragOverOp = info->usOperation; 373 lastRealOp = info->usOperation;374 if ( lastRealOp == DO_DEFAULT || lastRealOp == DO_UNKNOWN) {359 ealOp = info->usOperation; 360 if (ealOp == DO_UNKNOWN) { 375 361 // the default operation is requested 376 lastRealOp = defaultOp;362 ; 377 363 } 378 364 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); 382 368 } 383 369 … … 387 373 // the drop. Other platforms seem to do the same. 388 374 389 // convert the operation to an Action390 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 happen395 396 375 // flip y coordinate 397 376 QPoint pnt(info->xDrop, info->yDrop); … … 399 378 pnt = widget->mapFromGlobal(pnt); 400 379 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) { 403 386 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); 434 423 } 435 424 436 425 DrgFreeDraginfo(info); 437 426 438 return MRFROM2SHORT(dropReply, last RealOp);427 return MRFROM2SHORT(dropReply, last); 439 428 } 440 429 case DM_DRAGLEAVE: { 430 431 441 432 // Odin32 apps produce incorrect message flow, ignore 442 433 Q_ASSERT(lastDragOverHwnd != 0); … … 455 446 } 456 447 case DM_DROP: { 448 449 457 450 // Odin32 apps produce incorrect message flow, ignore 458 451 Q_ASSERT(lastDragOverHwnd != 0); … … 462 455 // Odin32 apps send DM_DROP even if we replied DOR_NEVERDROP or 463 456 // DOR_NODROP, simulate DM_DRAGLEAVE 464 Q_ASSERT(last Accept || lastAcceptAction);465 if ( !lastAccept && !lastAcceptAction) {457 Q_ASSERT(last); 458 if () { 466 459 WinSendMsg(qmsg.hwnd, DM_DRAGLEAVE, 0, 0); 467 460 return 0; … … 480 473 return MRFROM2SHORT(DOR_NEVERDROP, 0); 481 474 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); 490 476 491 477 // flip y coordinate 492 478 QPoint pnt(info->xDrop, info->yDrop); 493 479 pnt.setY(QApplication::desktop()->height() - (pnt.y() + 1)); 480 481 482 483 484 485 494 486 495 487 dragData.setDropped(true); 496 488 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); 503 493 504 494 QApplication::sendEvent(widget, &de); 505 495 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() ? 517 502 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 } 521 511 522 512 // send DM_ENDCONVERSATION for every item … … 528 518 continue; 529 519 // it is possible that this item required DM_RENDERPREPARE but 530 // returned FALSEin reply to it (so hwndItem may be NULL)520 // returned in reply to it (so hwndItem may be NULL) 531 521 if (!item->hwndItem) 532 522 continue; -
trunk/src/gui/kernel/qmime.h
r441 r442 121 121 #endif 122 122 123 123 124 class QPMCoopDragWorker; 124 125 … … 141 142 virtual void init() {} 142 143 // methods always implemented 143 virtual bool cleanup( 144 virtual bool cleanup(bool isCancelled) = 0; 144 145 virtual bool isExclusive() const = 0; 145 146 virtual ULONG itemCount() const = 0; … … 210 211 211 212 virtual void init() {} 212 virtual void cleanup(bool isAccepted , bool isActAccepted) {}213 virtual void cleanup(bool isAccepted) {} 213 214 virtual bool isExclusive() const = 0; 214 215 … … 230 231 231 232 // DropWorker interface 232 void cleanup(bool isAccepted , bool isActAccepted);233 void cleanup(bool isAccepted); 233 234 bool isExclusive() const; 234 235 bool hasFormat(const QString &mimeType) const; … … 294 295 static void unregisterMimeType(ULONG mimeId); 295 296 297 298 296 299 static ULONG allocateMemory(size_t size); 297 300 static void freeMemory(ULONG addr); … … 315 318 friend class QClipboardData; 316 319 friend class QClipboard; 320 317 321 318 322 struct Match -
trunk/src/gui/kernel/qmime_pm.cpp
r441 r442 743 743 } 744 744 745 void QPMMime::DefaultDropWorker::cleanup(bool isAccepted , bool isActAccepted)745 void QPMMime::DefaultDropWorker::cleanup(bool isAccepted) 746 746 { 747 747 if (d->eventLoop.isRunning()) { … … 1306 1306 { 1307 1307 WinDeleteAtom(WinQuerySystemAtomTable(), mimeId); 1308 1309 1310 1311 1312 1313 1314 1315 1316 1308 1317 } 1309 1318
Note:
See TracChangeset
for help on using the changeset viewer.