Changeset 447 for trunk/src/gui/kernel/qdnd_pm.cpp
- Timestamp:
- Jan 12, 2010, 12:00:10 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/gui/kernel/qdnd_pm.cpp
r444 r447 93 93 94 94 private: 95 friend class QDragManager; 95 96 96 97 void initWorkers(); … … 102 103 DRAGINFO *di; 103 104 QList<QPMMime::DropWorker*> workers; 105 106 QWidget *lastDragOverWidget; // last target widget 107 USHORT lastDragOverOp; // last DM_DRAGOVER operation 108 109 USHORT supportedOps; // operations supported by all items 110 bool sourceAllowsOp : 1; // does source allow requested operation 111 112 USHORT lastDropReply; // last reply to DM_DRAGOVER 113 USHORT lastOpRequest; // last op requested in DM_DRAGOVER 114 115 Qt::DropAction lastProposedAction; // last proposed action 116 QRect lastAnswerRect; // last accepted rectangle from the target 104 117 }; 105 118 … … 107 120 : initialized(false), dropped(false) 108 121 , gotWorkers(false), di(NULL) 109 { 110 QDragManager *manager = QDragManager::self(); 111 Q_ASSERT(!manager->dropData->d); 112 manager->dropData->d = this; 122 , lastDragOverWidget(0), lastDragOverOp(0) 123 , supportedOps(0), sourceAllowsOp(false) 124 , lastDropReply(DOR_NEVERDROP), lastOpRequest(DO_UNKNOWN) 125 , lastProposedAction(Qt::CopyAction) 126 { 113 127 } 114 128 … … 116 130 { 117 131 reset(); 118 119 QDragManager *manager = QDragManager::self();120 if (manager) {121 Q_ASSERT(manager->dropData->d == this);122 manager->dropData->d = 0;123 }124 132 } 125 133 … … 265 273 } 266 274 275 void QDragManager::init_sys() 276 { 277 inDrag = false; 278 279 Q_ASSERT(dropData); 280 Q_ASSERT(!dropData->d); 281 dropData->d = new QPMDragData(); 282 } 283 284 void QDragManager::uninit_sys() 285 { 286 Q_ASSERT(dropData); 287 Q_ASSERT(dropData->d); 288 delete dropData->d; 289 dropData->d = 0; 290 } 291 292 void QDragManager::sendDropEvent(QWidget *receiver, QEvent *event) 293 { 294 Q_ASSERT(!inDrag); 295 inDrag = true; 296 QApplication::sendEvent(receiver, event); 297 // make sure that all issued update requests are handled before we 298 // return from the DM_DRAGOVER/DM_DRAGLEAVE/DM_DROP message; otherwise 299 // we'll get screen corruption due to unexpected screen updates while 300 // dragging 301 QApplication::sendPostedEvents(0, QEvent::UpdateRequest); 302 inDrag = false; 303 } 304 267 305 /*! 268 306 * \internal 269 307 * Direct manipulation (Drag & Drop) event handler 270 308 */ 271 MRESULT qt_dispatchDragAndDrop(QWidget *widget, const QMSG &qmsg) 272 { 273 static QWidget *lastDragOverWidget = 0; // last target widget 274 static USHORT lastDragOverOp = 0; // last DM_DRAGOVER operation 275 276 static USHORT supportedOps = 0; // operations supported by all items 277 static bool sourceAllowsOp = false; // does source allow requested operation 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::CopyAction; // last proposed action 283 static QRect lastAnswerRect; // last accepted rectangle from the target 284 // @todo use lastAnswerRect to compress DM_DRAGOVER events 285 286 static QPMDragData dragData; 287 309 MRESULT QDragManager::dispatchDragAndDrop(QWidget *widget, const QMSG &qmsg) 310 { 288 311 Q_ASSERT(widget); 289 312 … … 291 314 292 315 QDragManager *manager = QDragManager::self(); 316 QPMDragData *dragData = manager->dropData->d; 317 Q_ASSERT(dragData); 318 319 // @todo use dragData->lastAnswerRect to compress DM_DRAGOVER events 293 320 294 321 switch (qmsg.msg) { … … 312 339 dragOverWidget = widget; 313 340 314 bool first = lastDragOverWidget != dragOverWidget;341 bool first = dragData->lastDragOverWidget != dragOverWidget; 315 342 if (first) { 316 343 // the first DM_DRAGOVER message 317 if ( lastDragOverWidget != 0) {344 if (dragData->lastDragOverWidget != 0) { 318 345 // send drag leave to the old widget 319 dragData .reset();346 dragData->reset(); 320 347 QPointer<QWidget> dragOverWidgetGuard(dragOverWidget); 321 348 QDragLeaveEvent dle; 322 QApplication::sendEvent(lastDragOverWidget, &dle);349 sendDropEvent(dragData->lastDragOverWidget, &dle); 323 350 if (!dragOverWidgetGuard) { 324 351 dragOverWidget = widget->childAt(pnt); … … 327 354 } 328 355 } 329 lastDragOverWidget = dragOverWidget; 330 lastDragOverOp = 0; 331 supportedOps = DO_COPYABLE | DO_MOVEABLE | DO_LINKABLE; 332 sourceAllowsOp = false; 333 lastDropReply = DOR_NEVERDROP; 334 lastOpRequest = DO_UNKNOWN; 335 lastProposedAction = manager->defaultAction(toQDragDropActions(supportedOps), 336 Qt::NoModifier); 337 lastAnswerRect = QRect(); 356 dragData->lastDragOverWidget = dragOverWidget; 357 dragData->lastDragOverOp = 0; 358 dragData->supportedOps = DO_COPYABLE | DO_MOVEABLE | DO_LINKABLE; 359 dragData->sourceAllowsOp = false; 360 dragData->lastDropReply = DOR_NEVERDROP; 361 dragData->lastOpRequest = DO_UNKNOWN; 362 dragData->lastProposedAction = 363 manager->defaultAction(toQDragDropActions(dragData->supportedOps), 364 Qt::NoModifier); 365 dragData->lastAnswerRect = QRect(); 338 366 // ensure drag data is reset (just in case of a wrong msg flow...) 339 dragData .reset();367 dragData->reset(); 340 368 } 341 369 … … 362 390 break; 363 391 } 364 supportedOps &= item->fsSupportedOps;392 dragData->supportedOps &= item->fsSupportedOps; 365 393 } 366 394 if (dropReply != DOR_NEVERDROP) { 367 395 Q_ASSERT(itemCount); 368 if (!itemCount || ! supportedOps) {396 if (!itemCount || !dragData->supportedOps) { 369 397 // items don't have even a single common operation... 370 398 dropReply = DOR_NEVERDROP; … … 375 403 if (dropReply != DOR_NEVERDROP) { 376 404 377 if (first || lastDragOverOp != info->usOperation) {405 if (first || dragData->lastDragOverOp != info->usOperation) { 378 406 // the current drop operation was changed by a modifier key 379 lastDragOverOp = info->usOperation;407 dragData->lastDragOverOp = info->usOperation; 380 408 USHORT realOp = info->usOperation; 381 409 if (realOp == DO_DEFAULT || realOp == DO_UNKNOWN) { 382 410 // the default operation is requested 383 realOp = toPmDragDropOp( lastProposedAction);411 realOp = toPmDragDropOp(dragData->lastProposedAction); 384 412 } 385 sourceAllowsOp =386 (( supportedOps & DO_MOVEABLE) && realOp == DO_MOVE) ||387 (( supportedOps & DO_COPYABLE) && realOp == DO_COPY) ||388 (( supportedOps & DO_LINKABLE) && realOp == DO_LINK);413 dragData->sourceAllowsOp = 414 ((dragData->supportedOps & DO_MOVEABLE) && realOp == DO_MOVE) || 415 ((dragData->supportedOps & DO_COPYABLE) && realOp == DO_COPY) || 416 ((dragData->supportedOps & DO_LINKABLE) && realOp == DO_LINK); 389 417 } 390 418 … … 396 424 QMimeData *data = manager->source() ? manager->dragPrivate()->data : manager->dropData; 397 425 398 Qt::DropAction action = toQDragDropAction( lastOpRequest);426 Qt::DropAction action = toQDragDropAction(dragData->lastOpRequest); 399 427 400 428 if (first) { 401 dragData.initialize(info); 402 QDragEnterEvent dee(pnt, toQDragDropActions(supportedOps), data, 403 QApplication::mouseButtons(), 429 dragData->initialize(info); 430 QDragEnterEvent dee(pnt, 431 toQDragDropActions(dragData->supportedOps), 432 data, QApplication::mouseButtons(), 404 433 QApplication::keyboardModifiers()); 405 QApplication::sendEvent(dragOverWidget, &dee);434 sendDropEvent(dragOverWidget, &dee); 406 435 // if not allowed or not accepted, always reply DOR_NODROP 407 436 // to have DM_DRAGOVER delivered to us again for a new test 408 if ( sourceAllowsOp && dee.isAccepted()) {437 if (dragData->sourceAllowsOp && dee.isAccepted()) { 409 438 dropReply = DOR_DROP; 410 439 action = dee.dropAction(); 411 lastProposedAction = dee.proposedAction();412 lastAnswerRect = dee.answerRect();440 dragData->lastProposedAction = dee.proposedAction(); 441 dragData->lastAnswerRect = dee.answerRect(); 413 442 } else { 414 443 dropReply = DOR_NODROP; … … 420 449 // the target accepts it) 421 450 if (!first || dropReply == DOR_DROP) { 422 QDragEnterEvent dme(pnt, toQDragDropActions(supportedOps), data, 423 QApplication::mouseButtons(), 424 QApplication::keyboardModifiers()); 451 QDragMoveEvent dme(pnt, 452 toQDragDropActions(dragData->supportedOps), 453 data, QApplication::mouseButtons(), 454 QApplication::keyboardModifiers()); 425 455 // accept by default, since enter event was accepted. 426 456 dme.setDropAction(action); 427 457 dme.accept(); 428 QApplication::sendEvent(dragOverWidget, &dme);429 if ( sourceAllowsOp && dme.isAccepted()) {458 sendDropEvent(dragOverWidget, &dme); 459 if (dragData->sourceAllowsOp && dme.isAccepted()) { 430 460 dropReply = DOR_DROP; 431 461 action = dme.dropAction(); 432 lastProposedAction = dme.proposedAction();433 lastAnswerRect = dme.answerRect();462 dragData->lastProposedAction = dme.proposedAction(); 463 dragData->lastAnswerRect = dme.answerRect(); 434 464 } else { 435 465 dropReply = DOR_NODROP; … … 437 467 } 438 468 439 lastDropReply = dropReply;440 lastOpRequest = toPmDragDropOp(action);469 dragData->lastDropReply = dropReply; 470 dragData->lastOpRequest = toPmDragDropOp(action); 441 471 } 442 472 443 473 DrgFreeDraginfo(info); 444 474 445 return MRFROM2SHORT(dropReply, lastOpRequest);475 return MRFROM2SHORT(dropReply, dragData->lastOpRequest); 446 476 } 447 477 case DM_DRAGLEAVE: { … … 449 479 450 480 // Odin32 apps produce incorrect message flow, ignore 451 Q_ASSERT( lastDragOverWidget != 0);452 if ( lastDragOverWidget == 0)481 Q_ASSERT(dragData->lastDragOverWidget != 0); 482 if (dragData->lastDragOverWidget == 0) 453 483 return 0; 454 484 455 485 QDragLeaveEvent de; 456 QApplication::sendEvent(lastDragOverWidget, &de);457 458 lastDragOverWidget = 0;459 dragData .reset();486 sendDropEvent(dragData->lastDragOverWidget, &de); 487 488 dragData->lastDragOverWidget = 0; 489 dragData->reset(); 460 490 461 491 return 0; … … 465 495 466 496 // Odin32 apps produce incorrect message flow, ignore 467 Q_ASSERT( lastDragOverWidget != 0);468 if ( lastDragOverWidget == 0)497 Q_ASSERT(dragData->lastDragOverWidget != 0); 498 if (dragData->lastDragOverWidget == 0) 469 499 return 0; 470 500 471 501 // Odin32 apps send DM_DROP even if we replied DOR_NEVERDROP or 472 502 // DOR_NODROP, simulate DM_DRAGLEAVE 473 Q_ASSERT( lastDropReply == DOR_DROP);474 if ( lastDropReply != DOR_DROP) {503 Q_ASSERT(dragData->lastDropReply == DOR_DROP); 504 if (dragData->lastDropReply != DOR_DROP) { 475 505 QMSG qmsg2 = qmsg; 476 506 qmsg2.msg = DM_DRAGLEAVE; 477 qt_dispatchDragAndDrop(widget, qmsg2);507 dispatchDragAndDrop(widget, qmsg2); 478 508 return 0; 479 509 } … … 490 520 pnt = widget->mapFromGlobal(pnt); 491 521 492 Q_ASSERT( lastOpRequest == info->usOperation);493 494 Q_ASSERT( lastDragOverWidget->acceptDrops());495 if (! lastDragOverWidget->acceptDrops()) {522 Q_ASSERT(dragData->lastOpRequest == info->usOperation); 523 524 Q_ASSERT(dragData->lastDragOverWidget->acceptDrops()); 525 if (!dragData->lastDragOverWidget->acceptDrops()) { 496 526 DrgDeleteDraginfoStrHandles(info); 497 527 DrgFreeDraginfo(info); … … 499 529 } 500 530 501 QDragManager *manager = QDragManager::self();502 531 QMimeData *data = manager->source() ? manager->dragPrivate()->data : manager->dropData; 503 532 504 Qt::DropAction action = toQDragDropAction( lastOpRequest);505 506 dragData .setDropped(true);533 Qt::DropAction action = toQDragDropAction(dragData->lastOpRequest); 534 535 dragData->setDropped(true); 507 536 508 537 QDropEvent de(pnt, action, data, QApplication::mouseButtons(), 509 538 QApplication::keyboardModifiers()); 510 if ( lastDropReply == DOR_DROP)539 if (dragData->lastDropReply == DOR_DROP) 511 540 de.setDropAction(action); 512 541 513 QApplication::sendEvent(lastDragOverWidget, &de);514 515 if ( lastDropReply == DOR_DROP)542 sendDropEvent(dragData->lastDragOverWidget, &de); 543 544 if (dragData->lastDropReply == DOR_DROP) 516 545 de.accept(); 517 546 518 lastDragOverWidget = 0;519 dragData .reset(de.isAccepted());547 dragData->lastDragOverWidget = 0; 548 dragData->reset(de.isAccepted()); 520 549 521 550 ULONG targetReply = de.isAccepted() ?
Note:
See TracChangeset
for help on using the changeset viewer.