Changeset 447 for trunk/src


Ignore:
Timestamp:
Jan 12, 2010, 12:00:10 PM (16 years ago)
Author:
Dmitry A. Kuminov
Message:

gui: DnD: Implemented support for painting in widgets during drag and draw.

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

Legend:

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

    r438 r447  
    6464#include "qkeymapper_p.h"
    6565#include "qcursor_p.h"
     66#include "qdnd_p.h"
    6667
    6768#define WM_KBDLAYERCHANGED   0x0BD4 // defined in OS2TK45/h/pmbidi.h
     
    702703#define SV_WORKAREA_XLEFT   54
    703704
    704 #ifndef QT_NO_DRAGANDDROP
    705 extern MRESULT qt_dispatchDragAndDrop(QWidget *, const QMSG &); // qdnd_pm.cpp
    706 #endif
    707 
    708705/*!
    709706    \internal
     
    921918#ifndef QT_NO_DRAGANDDROP
    922919        } else if (msg >= WM_DRAGFIRST && msg <= WM_DRAGLAST) {
    923             return qt_dispatchDragAndDrop(widget, qmsg);
     920            return QDragManager::self()->dispatchDragAndDrop(widget, qmsg);
    924921#endif
    925922        } else {
     
    21422139    if (rc == RGN_ERROR) { // The update bounding rect is invalid
    21432140        GpiDestroyRegion(displayPS, hrgn);
    2144         d_func()->hd = NULLHANDLE;
    21452141        setAttribute(Qt::WA_PendingUpdate, false);
    21462142        return false;
     
    21662162    if (rcl.xRight <= rcl.xLeft || rcl.yTop <= rcl.yBottom) {
    21672163        WinEndPaint(d_func()->hd);
     2164        d_func()->hd = NULLHANDLE;
    21682165        GpiDestroyRegion(displayPS, hrgn);
    2169         d_func()->hd = NULLHANDLE;
    21702166        setAttribute(Qt::WA_PendingUpdate, false);
    21712167        return true;
     
    21732169
    21742170    // flip y coordinate
    2175     rcl.yBottom = height() - (rcl.yBottom + 1);
    2176     rcl.yTop = height() - (rcl.yTop + 1);
    2177 
    21782171    // note: right top point is exlusive in rcl
    2179     QRect updRect(QPoint(rcl.xLeft, rcl.yTop + 1),
    2180                   QPoint(rcl.xRight - 1, rcl.yBottom));
     2172    QRect updRect(QPoint(rcl.xLeft, height() - rcl.yTop),
     2173                  QPoint(rcl.xRight - 1, height() - (rcl.yBottom + 1)));
    21812174
    21822175    // Mapping region from system to qt (32 bit) coordinate system.
  • trunk/src/gui/kernel/qdnd.cpp

    r438 r447  
    358358    xdndMimeTransferedPixmapIndex = 0;
    359359#endif
     360#ifdef Q_WS_PM
     361    init_sys();
     362#endif
    360363}
    361364
     
    363366QDragManager::~QDragManager()
    364367{
     368#ifdef Q_WS_PM
     369    uninit_sys();
     370#endif
    365371#ifndef QT_NO_CURSOR
    366372    if (restoreCursor)
  • trunk/src/gui/kernel/qdnd_p.h

    r438 r447  
    6363#ifdef Q_WS_MAC
    6464# include "private/qt_mac_p.h"
     65#endif
     66
     67#if defined(Q_WS_PM)
     68#include "qt_os2.h"
    6569#endif
    6670
     
    205209    LPDATAOBJECT currentDataObject;
    206210#elif defined(Q_WS_PM)
    207     friend class QPMDragData;
     211    friend class QDragManager;
    208212    QPMDragData *d;
    209213#endif
     
    267271#endif
    268272
     273#ifdef Q_WS_PM
     274    void init_sys();
     275    void uninit_sys();
     276    void sendDropEvent(QWidget *receiver, QEvent *event);
     277    MRESULT dispatchDragAndDrop(QWidget *widget, const QMSG &qmsg);
     278    bool isInDrag() const { return inDrag; }
     279#endif
     280
    269281private:
    270282    QPixmap *pm_cursor;
     
    272284#ifdef Q_WS_QWS
    273285    Qt::DropAction currentActionForOverrideCursor;
     286#endif
     287#ifdef Q_WS_PM
     288    bool inDrag;
    274289#endif
    275290
  • trunk/src/gui/kernel/qdnd_pm.cpp

    r444 r447  
    9393
    9494private:
     95    friend class QDragManager;
    9596
    9697    void initWorkers();
     
    102103    DRAGINFO *di;
    103104    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
    104117};
    105118
     
    107120    : initialized(false), dropped(false)
    108121    , 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{
    113127}
    114128
     
    116130{
    117131    reset();
    118 
    119     QDragManager *manager = QDragManager::self();
    120     if (manager) {
    121         Q_ASSERT(manager->dropData->d == this);
    122         manager->dropData->d = 0;
    123     }
    124132}
    125133
     
    265273}
    266274
     275void QDragManager::init_sys()
     276{
     277    inDrag = false;
     278
     279    Q_ASSERT(dropData);
     280    Q_ASSERT(!dropData->d);
     281    dropData->d = new QPMDragData();
     282}
     283
     284void QDragManager::uninit_sys()
     285{
     286    Q_ASSERT(dropData);
     287    Q_ASSERT(dropData->d);
     288    delete dropData->d;
     289    dropData->d = 0;
     290}
     291
     292void 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
    267305/*!
    268306 *  \internal
    269307 *  Direct manipulation (Drag & Drop) event handler
    270308 */
    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 
     309MRESULT QDragManager::dispatchDragAndDrop(QWidget *widget, const QMSG &qmsg)
     310{
    288311    Q_ASSERT(widget);
    289312
     
    291314
    292315    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
    293320
    294321    switch (qmsg.msg) {
     
    312339                dragOverWidget = widget;
    313340
    314             bool first = lastDragOverWidget != dragOverWidget;
     341            bool first = dragData->lastDragOverWidget != dragOverWidget;
    315342            if (first) {
    316343                // the first DM_DRAGOVER message
    317                 if (lastDragOverWidget != 0) {
     344                if (dragData->lastDragOverWidget != 0) {
    318345                    // send drag leave to the old widget
    319                     dragData.reset();
     346                    dragData->reset();
    320347                    QPointer<QWidget> dragOverWidgetGuard(dragOverWidget);
    321348                    QDragLeaveEvent dle;
    322                     QApplication::sendEvent(lastDragOverWidget, &dle);
     349                    sendDropEvent(dragData->lastDragOverWidget, &dle);
    323350                    if (!dragOverWidgetGuard) {
    324351                        dragOverWidget = widget->childAt(pnt);
     
    327354                    }
    328355                }
    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();
    338366                // ensure drag data is reset (just in case of a wrong msg flow...)
    339                 dragData.reset();
     367                dragData->reset();
    340368            }
    341369
     
    362390                        break;
    363391                    }
    364                     supportedOps &= item->fsSupportedOps;
     392                    dragData->supportedOps &= item->fsSupportedOps;
    365393                }
    366394                if (dropReply != DOR_NEVERDROP) {
    367395                    Q_ASSERT(itemCount);
    368                     if (!itemCount || !supportedOps) {
     396                    if (!itemCount || !dragData->supportedOps) {
    369397                        // items don't have even a single common operation...
    370398                        dropReply = DOR_NEVERDROP;
     
    375403            if (dropReply != DOR_NEVERDROP) {
    376404
    377                 if (first || lastDragOverOp != info->usOperation) {
     405                if (first || dragData->lastDragOverOp != info->usOperation) {
    378406                    // the current drop operation was changed by a modifier key
    379                     lastDragOverOp = info->usOperation;
     407                    dragData->lastDragOverOp = info->usOperation;
    380408                    USHORT realOp = info->usOperation;
    381409                    if (realOp == DO_DEFAULT || realOp == DO_UNKNOWN) {
    382410                        // the default operation is requested
    383                         realOp = toPmDragDropOp(lastProposedAction);
     411                        realOp = toPmDragDropOp(dragData->lastProposedAction);
    384412                    }
    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);
    389417                }
    390418
     
    396424                QMimeData *data = manager->source() ? manager->dragPrivate()->data : manager->dropData;
    397425
    398                 Qt::DropAction action = toQDragDropAction(lastOpRequest);
     426                Qt::DropAction action = toQDragDropAction(dragData->lastOpRequest);
    399427
    400428                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(),
    404433                                        QApplication::keyboardModifiers());
    405                     QApplication::sendEvent(dragOverWidget, &dee);
     434                    sendDropEvent(dragOverWidget, &dee);
    406435                    // if not allowed or not accepted, always reply DOR_NODROP
    407436                    // to have DM_DRAGOVER delivered to us again for a new test
    408                     if (sourceAllowsOp && dee.isAccepted()) {
     437                    if (dragData->sourceAllowsOp && dee.isAccepted()) {
    409438                        dropReply = DOR_DROP;
    410439                        action = dee.dropAction();
    411                         lastProposedAction = dee.proposedAction();
    412                         lastAnswerRect = dee.answerRect();
     440                        dragData->lastProposedAction = dee.proposedAction();
     441                        dragData->lastAnswerRect = dee.answerRect();
    413442                    } else {
    414443                        dropReply = DOR_NODROP;
     
    420449                // the target accepts it)
    421450                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());
    425455                    // accept by default, since enter event was accepted.
    426456                    dme.setDropAction(action);
    427457                    dme.accept();
    428                     QApplication::sendEvent(dragOverWidget, &dme);
    429                     if (sourceAllowsOp && dme.isAccepted()) {
     458                    sendDropEvent(dragOverWidget, &dme);
     459                    if (dragData->sourceAllowsOp && dme.isAccepted()) {
    430460                        dropReply = DOR_DROP;
    431461                        action = dme.dropAction();
    432                         lastProposedAction = dme.proposedAction();
    433                         lastAnswerRect = dme.answerRect();
     462                        dragData->lastProposedAction = dme.proposedAction();
     463                        dragData->lastAnswerRect = dme.answerRect();
    434464                    } else {
    435465                        dropReply = DOR_NODROP;
     
    437467                }
    438468
    439                 lastDropReply = dropReply;
    440                 lastOpRequest = toPmDragDropOp(action);
     469                dragData->lastDropReply = dropReply;
     470                dragData->lastOpRequest = toPmDragDropOp(action);
    441471            }
    442472
    443473            DrgFreeDraginfo(info);
    444474
    445             return MRFROM2SHORT(dropReply, lastOpRequest);
     475            return MRFROM2SHORT(dropReply, dragData->lastOpRequest);
    446476        }
    447477        case DM_DRAGLEAVE: {
     
    449479
    450480            // 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)
    453483                return 0;
    454484
    455485            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();
    460490
    461491            return 0;
     
    465495
    466496            // 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)
    469499                return 0;
    470500
    471501            // Odin32 apps send DM_DROP even if we replied DOR_NEVERDROP or
    472502            // 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) {
    475505                QMSG qmsg2 = qmsg;
    476506                qmsg2.msg = DM_DRAGLEAVE;
    477                 qt_dispatchDragAndDrop(widget, qmsg2);
     507                dispatchDragAndDrop(widget, qmsg2);
    478508                return 0;
    479509            }
     
    490520            pnt = widget->mapFromGlobal(pnt);
    491521
    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()) {
    496526                DrgDeleteDraginfoStrHandles(info);
    497527                DrgFreeDraginfo(info);
     
    499529            }
    500530
    501             QDragManager *manager = QDragManager::self();
    502531            QMimeData *data = manager->source() ? manager->dragPrivate()->data : manager->dropData;
    503532
    504             Qt::DropAction action = toQDragDropAction(lastOpRequest);
    505 
    506             dragData.setDropped(true);
     533            Qt::DropAction action = toQDragDropAction(dragData->lastOpRequest);
     534
     535            dragData->setDropped(true);
    507536
    508537            QDropEvent de(pnt, action, data, QApplication::mouseButtons(),
    509538                          QApplication::keyboardModifiers());
    510             if (lastDropReply == DOR_DROP)
     539            if (dragData->lastDropReply == DOR_DROP)
    511540                de.setDropAction(action);
    512541
    513             QApplication::sendEvent(lastDragOverWidget, &de);
    514 
    515             if (lastDropReply == DOR_DROP)
     542            sendDropEvent(dragData->lastDragOverWidget, &de);
     543
     544            if (dragData->lastDropReply == DOR_DROP)
    516545                de.accept();
    517546
    518             lastDragOverWidget = 0;
    519             dragData.reset(de.isAccepted());
     547            dragData->lastDragOverWidget = 0;
     548            dragData->reset(de.isAccepted());
    520549
    521550            ULONG targetReply = de.isAccepted() ?
  • trunk/src/gui/kernel/qwidget.cpp

    r352 r447  
    8686#if defined (Q_WS_WIN)
    8787# include <private/qwininputcontext_p.h>
     88#endif
     89
     90#if defined (Q_WS_PM)
     91# include "qdnd_p.h"
    8892#endif
    8993
     
    1041110415    if (d->hd != NULLHANDLE)
    1041210416        return (HPS) d->hd;
     10417#ifndef QT_NO_DRAGANDDROP
     10418    if (QDragManager::self()->isInDrag())
     10419        return DrgGetPS(winId());
     10420#endif
    1041310421    return WinGetPS(winId());
    1041410422}
     
    1042410432    // If there is a widget's own ps, the release operation is ignored because
    1042510433    // it will be released elsewhere. Otherwise, we assume that the given hps
    10426     // was acquired by WinGetPS in the getPS() call and release it.
    10427     if (d->hd == NULLHANDLE)
     10434    // was acquired by DrgGetPS/WinGetPS in the getPS() call and release it.
     10435    if (d->hd == NULLHANDLE) {
     10436#ifndef QT_NO_DRAGANDDROP
     10437        if (QDragManager::self()->isInDrag())
     10438            DrgReleasePS(hps);
     10439        else
     10440#endif
    1042810441        WinReleasePS(hps);
     10442    }
    1042910443}
    1043010444#else
Note: See TracChangeset for help on using the changeset viewer.