1 /****************************************************************************
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
42 #include "qapplication.h"
44 #include "qapplication_p.h"
49 #include "qdatastream.h"
51 #include "qt_windows.h"
53 #ifndef QT_NO_ACCESSIBILITY
54 #include "qaccessible.h"
59 #if defined(Q_OS_WINCE)
60 #include "qguifunctions_wince.h"
63 // support for xbuttons
65 #define MK_XBUTTON1 0x0020
66 #define MK_XBUTTON2 0x0040
71 #if !(defined(QT_NO_DRAGANDDROP) && defined(QT_NO_CLIPBOARD))
73 //---------------------------------------------------------------------
74 // QOleDataObject Constructor
75 //---------------------------------------------------------------------
77 QOleDataObject::QOleDataObject(QMimeData *mimeData)
81 CF_PERFORMEDDROPEFFECT = RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT);
82 performedEffect = DROPEFFECT_NONE;
85 QOleDataObject::~QOleDataObject()
89 void QOleDataObject::releaseQt()
94 const QMimeData *QOleDataObject::mimeData() const
99 DWORD QOleDataObject::reportedPerformedEffect() const
101 return performedEffect;
104 //---------------------------------------------------------------------
106 //---------------------------------------------------------------------
109 QOleDataObject::QueryInterface(REFIID iid, void FAR* FAR* ppv)
111 if (iid == IID_IUnknown || iid == IID_IDataObject) {
117 return ResultFromScode(E_NOINTERFACE);
121 QOleDataObject::AddRef(void)
127 QOleDataObject::Release(void)
137 //---------------------------------------------------------------------
138 // IDataObject Methods
140 // The following methods are NOT supported for data transfer using the
141 // clipboard or drag-drop:
143 // IDataObject::SetData -- return E_NOTIMPL
144 // IDataObject::DAdvise -- return OLE_E_ADVISENOTSUPPORTED
147 // IDataObject::GetCanonicalFormatEtc -- return E_NOTIMPL
148 // (NOTE: must set pformatetcOut->ptd = NULL)
149 //---------------------------------------------------------------------
152 QOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium)
155 qDebug("QOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium)");
157 wchar_t buf[256] = {0};
158 GetClipboardFormatName(pformatetc->cfFormat, buf, 255);
159 qDebug("CF = %d : %s", pformatetc->cfFormat, QString::fromWCharArray(buf));
164 return ResultFromScode(DATA_E_FORMATETC);
166 QWindowsMime *converter = QWindowsMime::converterFromMime(*pformatetc, data);
168 if (converter && converter->convertFromMime(*pformatetc, data, pmedium))
169 return ResultFromScode(S_OK);
171 return ResultFromScode(DATA_E_FORMATETC);
175 QOleDataObject::GetDataHere(LPFORMATETC, LPSTGMEDIUM)
177 return ResultFromScode(DATA_E_FORMATETC);
181 QOleDataObject::QueryGetData(LPFORMATETC pformatetc)
184 qDebug("QOleDataObject::QueryGetData(LPFORMATETC pformatetc)");
188 return ResultFromScode(DATA_E_FORMATETC);
190 if (QWindowsMime::converterFromMime(*pformatetc, data))
191 return ResultFromScode(S_OK);
192 return ResultFromScode(S_FALSE);
196 QOleDataObject::GetCanonicalFormatEtc(LPFORMATETC, LPFORMATETC pformatetcOut)
198 pformatetcOut->ptd = NULL;
199 return ResultFromScode(E_NOTIMPL);
203 QOleDataObject::SetData(LPFORMATETC pFormatetc, STGMEDIUM *pMedium, BOOL fRelease)
205 if (pFormatetc->cfFormat == CF_PERFORMEDDROPEFFECT && pMedium->tymed == TYMED_HGLOBAL) {
206 DWORD * val = (DWORD*)GlobalLock(pMedium->hGlobal);
207 performedEffect = *val;
208 GlobalUnlock(pMedium->hGlobal);
210 ReleaseStgMedium(pMedium);
211 return ResultFromScode(S_OK);
213 return ResultFromScode(E_NOTIMPL);
218 QOleDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC FAR* ppenumFormatEtc)
221 qDebug("QOleDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC FAR* ppenumFormatEtc)");
225 return ResultFromScode(DATA_E_FORMATETC);
229 QVector<FORMATETC> fmtetcs;
230 if (dwDirection == DATADIR_GET) {
231 fmtetcs = QWindowsMime::allFormatsForMime(data);
234 formatetc.cfFormat = CF_PERFORMEDDROPEFFECT;
235 formatetc.dwAspect = DVASPECT_CONTENT;
236 formatetc.lindex = -1;
237 formatetc.ptd = NULL;
238 formatetc.tymed = TYMED_HGLOBAL;
239 fmtetcs.append(formatetc);
242 QOleEnumFmtEtc *enumFmtEtc = new QOleEnumFmtEtc(fmtetcs);
243 *ppenumFormatEtc = enumFmtEtc;
244 if (enumFmtEtc->isNull()) {
246 *ppenumFormatEtc = NULL;
250 return ResultFromScode(sc);
254 QOleDataObject::DAdvise(FORMATETC FAR*, DWORD,
255 LPADVISESINK, DWORD FAR*)
257 return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
262 QOleDataObject::DUnadvise(DWORD)
264 return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
268 QOleDataObject::EnumDAdvise(LPENUMSTATDATA FAR*)
270 return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
273 #endif // QT_NO_DRAGANDDROP && QT_NO_CLIPBOARD
275 #ifndef QT_NO_DRAGANDDROP
280 extern QString dragActionsToString(Qt::DropActions actions);
283 Qt::DropActions translateToQDragDropActions(DWORD pdwEffects)
285 Qt::DropActions actions = Qt::IgnoreAction;
286 if (pdwEffects & DROPEFFECT_LINK)
287 actions |= Qt::LinkAction;
288 if (pdwEffects & DROPEFFECT_COPY)
289 actions |= Qt::CopyAction;
290 if (pdwEffects & DROPEFFECT_MOVE)
291 actions |= Qt::MoveAction;
295 Qt::DropAction translateToQDragDropAction(DWORD pdwEffect)
297 if (pdwEffect & DROPEFFECT_LINK)
298 return Qt::LinkAction;
299 if (pdwEffect & DROPEFFECT_COPY)
300 return Qt::CopyAction;
301 if (pdwEffect & DROPEFFECT_MOVE)
302 return Qt::MoveAction;
303 return Qt::IgnoreAction;
306 DWORD translateToWinDragEffects(Qt::DropActions action)
308 DWORD effect = DROPEFFECT_NONE;
309 if (action & Qt::LinkAction)
310 effect |= DROPEFFECT_LINK;
311 if (action & Qt::CopyAction)
312 effect |= DROPEFFECT_COPY;
313 if (action & Qt::MoveAction)
314 effect |= DROPEFFECT_MOVE;
318 Qt::KeyboardModifiers toQtKeyboardModifiers(DWORD keyState)
320 Qt::KeyboardModifiers modifiers = Qt::NoModifier;
322 if (keyState & MK_SHIFT)
323 modifiers |= Qt::ShiftModifier;
324 if (keyState & MK_CONTROL)
325 modifiers |= Qt::ControlModifier;
326 if (keyState & MK_ALT)
327 modifiers |= Qt::AltModifier;
332 Qt::MouseButtons toQtMouseButtons(DWORD keyState)
334 Qt::MouseButtons buttons = Qt::NoButton;
336 if (keyState & MK_LBUTTON)
337 buttons |= Qt::LeftButton;
338 if (keyState & MK_RBUTTON)
339 buttons |= Qt::RightButton;
340 if (keyState & MK_MBUTTON)
341 buttons |= Qt::MidButton;
346 class QOleDropSource : public IDropSource
350 virtual ~QOleDropSource();
352 void createCursors();
355 STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObj);
356 STDMETHOD_(ULONG,AddRef)(void);
357 STDMETHOD_(ULONG,Release)(void);
359 // IDropSource methods
360 STDMETHOD(QueryContinueDrag)(BOOL fEscapePressed, DWORD grfKeyState);
361 STDMETHOD(GiveFeedback)(DWORD dwEffect);
364 Qt::MouseButtons currentButtons;
365 Qt::DropAction currentAction;
366 QMap <Qt::DropAction, QCursor> cursors;
372 QOleDropSource::QOleDropSource()
374 currentButtons = Qt::NoButton;
376 currentAction = Qt::IgnoreAction;
379 QOleDropSource::~QOleDropSource()
383 void QOleDropSource::createCursors()
385 QDragManager *manager = QDragManager::self();
386 if (manager && manager->object
387 && (!manager->object->pixmap().isNull()
388 || manager->hasCustomDragCursors())) {
389 QPixmap pm = manager->object->pixmap();
390 QList<Qt::DropAction> actions;
391 actions << Qt::MoveAction << Qt::CopyAction << Qt::LinkAction;
392 if (!manager->object->pixmap().isNull())
393 actions << Qt::IgnoreAction;
394 QPoint hotSpot = manager->object->hotSpot();
395 for (int cnum = 0; cnum < actions.size(); ++cnum) {
396 QPixmap cpm = manager->dragCursor(actions.at(cnum));
398 int h = cpm.height();
401 int x1 = qMin(-hotSpot.x(), 0);
402 int x2 = qMax(pm.width() - hotSpot.x(), cpm.width());
403 int y1 = qMin(-hotSpot.y(), 0);
404 int y2 = qMax(pm.height() - hotSpot.y(), cpm.height());
410 QRect srcRect = pm.rect();
411 QPoint pmDest = QPoint(qMax(0, -hotSpot.x()), qMax(0, -hotSpot.y()));
412 QPoint newHotSpot = hotSpot;
414 #if defined(Q_OS_WINCE)
415 // Limited cursor size
416 int reqw = GetSystemMetrics(SM_CXCURSOR);
417 int reqh = GetSystemMetrics(SM_CYCURSOR);
419 QPoint hotspotInPM = newHotSpot - pmDest;
421 // Not wide enough - move objectpm right
422 qreal r = qreal(newHotSpot.x()) / w;
423 newHotSpot = QPoint(int(r * reqw), newHotSpot.y());
424 if (newHotSpot.x() + cpm.width() > reqw)
425 newHotSpot.setX(reqw - cpm.width());
427 srcRect = QRect(QPoint(hotspotInPM.x() - newHotSpot.x(), srcRect.top()), QSize(reqw, srcRect.height()));
430 qreal r = qreal(newHotSpot.y()) / h;
431 newHotSpot = QPoint(newHotSpot.x(), int(r * reqh));
432 if (newHotSpot.y() + cpm.height() > reqh)
433 newHotSpot.setY(reqh - cpm.height());
435 srcRect = QRect(QPoint(srcRect.left(), hotspotInPM.y() - newHotSpot.y()), QSize(srcRect.width(), reqh));
437 // Always use system cursor size
442 QPixmap newCursor(w, h);
444 newCursor.fill(QColor(0, 0, 0, 0));
445 QPainter p(&newCursor);
446 p.drawPixmap(pmDest, pm, srcRect);
447 p.drawPixmap(qMax(0,newHotSpot.x()),qMax(0,newHotSpot.y()),cpm);
453 cursors[actions.at(cnum)] = QCursor(newCursor, pm.isNull() ? 0 : qMax(0,newHotSpot.x()),
454 pm.isNull() ? 0 : qMax(0,newHotSpot.y()));
462 //---------------------------------------------------------------------
464 //---------------------------------------------------------------------
468 QOleDropSource::QueryInterface(REFIID iid, void FAR* FAR* ppv)
470 if(iid == IID_IUnknown || iid == IID_IDropSource)
477 return ResultFromScode(E_NOINTERFACE);
482 QOleDropSource::AddRef(void)
489 QOleDropSource::Release(void)
499 static inline Qt::MouseButtons keystate_to_mousebutton(DWORD grfKeyState)
501 Qt::MouseButtons result;
502 if (grfKeyState & MK_LBUTTON)
503 result |= Qt::LeftButton;
504 if (grfKeyState & MK_MBUTTON)
505 result |= Qt::MidButton;
506 if (grfKeyState & MK_RBUTTON)
507 result |= Qt::RightButton;
508 if (grfKeyState & MK_XBUTTON1)
509 result |= Qt::XButton1;
510 if (grfKeyState & MK_XBUTTON2)
511 result |= Qt::XButton2;
515 //---------------------------------------------------------------------
516 // IDropSource Methods
517 //---------------------------------------------------------------------
518 QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
519 QOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
522 qDebug("QOleDropSource::QueryContinueDrag(fEscapePressed %d, grfKeyState %d)", fEscapePressed, grfKeyState);
525 if (fEscapePressed) {
526 return ResultFromScode(DRAGDROP_S_CANCEL);
527 } else if ((GetAsyncKeyState(VK_LBUTTON) == 0)
528 && (GetAsyncKeyState(VK_MBUTTON) == 0)
529 && (GetAsyncKeyState(VK_RBUTTON) == 0)) {
530 // grfKeyState is broken on CE & some Windows XP versions,
531 // therefore we need to check the state manually
532 return ResultFromScode(DRAGDROP_S_DROP);
534 #if !defined(Q_OS_WINCE)
535 if (currentButtons == Qt::NoButton) {
536 currentButtons = keystate_to_mousebutton(grfKeyState);
538 Qt::MouseButtons buttons = keystate_to_mousebutton(grfKeyState);
539 if (!(currentButtons & buttons))
540 return ResultFromScode(DRAGDROP_S_DROP);
543 Q_UNUSED(grfKeyState);
545 QApplication::processEvents();
550 QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
551 QOleDropSource::GiveFeedback(DWORD dwEffect)
553 Qt::DropAction action = translateToQDragDropAction(dwEffect);
556 qDebug("QOleDropSource::GiveFeedback(DWORD dwEffect)");
557 qDebug("dwEffect = %s", dragActionsToString(action).toLatin1().data());
560 if (currentAction != action) {
561 currentAction = action;
562 QDragManager::self()->emitActionChanged(currentAction);
565 if (cursors.contains(currentAction)) {
567 SetCursor(cursors[currentAction].handle());
569 return ResultFromScode(S_OK);
572 return ResultFromScode(DRAGDROP_S_USEDEFAULTCURSORS);
575 //---------------------------------------------------------------------
577 //---------------------------------------------------------------------
579 QOleDropTarget::QOleDropTarget(QWidget* w)
585 void QOleDropTarget::releaseQt()
590 //---------------------------------------------------------------------
592 //---------------------------------------------------------------------
596 QOleDropTarget::QueryInterface(REFIID iid, void FAR* FAR* ppv)
598 if(iid == IID_IUnknown || iid == IID_IDropTarget)
605 return ResultFromScode(E_NOINTERFACE);
610 QOleDropTarget::AddRef(void)
617 QOleDropTarget::Release(void)
627 //---------------------------------------------------------------------
628 // IDropTarget Methods
629 //---------------------------------------------------------------------
631 QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
632 QOleDropTarget::DragEnter(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
635 qDebug("QOleDropTarget::DragEnter(grfKeyState %d, pt (%d,%d), pdwEffect %lu)",
636 grfKeyState, pt.x, pt.y, *pdwEffect);
639 if (!QApplicationPrivate::tryModalHelper(widget)) {
640 *pdwEffect = DROPEFFECT_NONE;
644 QDragManager *manager = QDragManager::self();
645 manager->dropData->currentDataObject = pDataObj;
646 manager->dropData->currentDataObject->AddRef();
647 sendDragEnterEvent(widget, grfKeyState, pt, pdwEffect);
648 *pdwEffect = chosenEffect;
653 void QOleDropTarget::sendDragEnterEvent(QWidget *dragEnterWidget, DWORD grfKeyState,
654 POINTL pt, LPDWORD pdwEffect)
656 Q_ASSERT(dragEnterWidget);
657 lastPoint = dragEnterWidget->mapFromGlobal(QPoint(pt.x,pt.y));
658 lastKeyState = grfKeyState;
660 chosenEffect = DROPEFFECT_NONE;
661 currentWidget = dragEnterWidget;
663 QDragManager *manager = QDragManager::self();
664 QMimeData * md = manager->source() ? manager->dragPrivate()->data : manager->dropData;
665 QDragEnterEvent enterEvent(lastPoint, translateToQDragDropActions(*pdwEffect), md,
666 toQtMouseButtons(grfKeyState), toQtKeyboardModifiers(grfKeyState));
667 QApplication::sendEvent(dragEnterWidget, &enterEvent);
668 answerRect = enterEvent.answerRect();
670 if (enterEvent.isAccepted()) {
671 chosenEffect = translateToWinDragEffects(enterEvent.dropAction());
674 // Documentation states that a drag move event is sendt immidiatly after
675 // a drag enter event. This will honor widgets overriding dragMoveEvent only:
676 if (enterEvent.isAccepted()) {
677 QDragMoveEvent moveEvent(lastPoint, translateToQDragDropActions(*pdwEffect), md,
678 toQtMouseButtons(grfKeyState), toQtKeyboardModifiers(grfKeyState));
679 answerRect = enterEvent.answerRect();
680 moveEvent.setDropAction(enterEvent.dropAction());
681 moveEvent.accept(); // accept by default, since enter event was accepted.
683 QApplication::sendEvent(dragEnterWidget, &moveEvent);
684 if (moveEvent.isAccepted()) {
685 answerRect = moveEvent.answerRect();
686 chosenEffect = translateToWinDragEffects(moveEvent.dropAction());
688 chosenEffect = DROPEFFECT_NONE;
694 static inline bool acceptsDrop(const QWidget *w)
696 return w->testAttribute(Qt::WA_DropSiteRegistered) && w->acceptDrops();
699 QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
700 QOleDropTarget::DragOver(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
703 qDebug("QOleDropTarget::DragOver(grfKeyState %d, pt (%d,%d), pdwEffect %lu)",
704 grfKeyState, pt.x, pt.y, *pdwEffect);
707 QWidget *dragOverWidget = widget->childAt(widget->mapFromGlobal(QPoint(pt.x, pt.y)));
709 dragOverWidget = widget;
712 if (!QApplicationPrivate::tryModalHelper(dragOverWidget)) {
713 *pdwEffect = DROPEFFECT_NONE;
717 // Try to find a drop-enabled target in the hierarchy. Go beyond 'widget' in case
718 // it is a native child window which has its own drop site registered (QTBUG-27265).
719 while (dragOverWidget && !dragOverWidget->isWindow() && !acceptsDrop(dragOverWidget))
720 dragOverWidget = dragOverWidget->parentWidget();
722 if (!dragOverWidget || !acceptsDrop(dragOverWidget)) {
723 *pdwEffect = DROPEFFECT_NONE;
727 QPoint tmpPoint = dragOverWidget->mapFromGlobal(QPoint(pt.x, pt.y));
728 // see if we should compress this event
729 if ((tmpPoint == lastPoint || answerRect.contains(tmpPoint)) && lastKeyState == grfKeyState) {
730 *pdwEffect = chosenEffect;
734 if (!dragOverWidget->internalWinId() && dragOverWidget != currentWidget) {
735 QPointer<QWidget> dragOverWidgetGuard(dragOverWidget);
736 // Send drag leave event to the previous drag widget.
737 QDragLeaveEvent dragLeave;
739 QApplication::sendEvent(currentWidget, &dragLeave);
740 if (!dragOverWidgetGuard) {
741 dragOverWidget = widget->childAt(widget->mapFromGlobal(QPoint(pt.x, pt.y)));
743 dragOverWidget = widget;
745 // Send drag enter event to the current drag widget.
746 sendDragEnterEvent(dragOverWidget, grfKeyState, pt, pdwEffect);
749 QDragManager *manager = QDragManager::self();
750 QMimeData *md = manager->source() ? manager->dragPrivate()->data : manager->dropData;
752 QDragMoveEvent oldEvent(lastPoint, translateToQDragDropActions(*pdwEffect), md,
753 toQtMouseButtons(lastKeyState), toQtKeyboardModifiers(lastKeyState));
756 lastPoint = tmpPoint;
757 lastKeyState = grfKeyState;
759 QDragMoveEvent e(lastPoint, translateToQDragDropActions(*pdwEffect), md,
760 toQtMouseButtons(grfKeyState), toQtKeyboardModifiers(grfKeyState));
761 if (chosenEffect != DROPEFFECT_NONE) {
762 if (oldEvent.dropAction() == e.dropAction() &&
763 oldEvent.keyboardModifiers() == e.keyboardModifiers())
764 e.setDropAction(translateToQDragDropAction(chosenEffect));
767 QApplication::sendEvent(dragOverWidget, &e);
769 answerRect = e.answerRect();
771 chosenEffect = translateToWinDragEffects(e.dropAction());
773 chosenEffect = DROPEFFECT_NONE;
774 *pdwEffect = chosenEffect;
779 QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
780 QOleDropTarget::DragLeave()
783 qDebug("QOleDropTarget::DragLeave()");
786 if (!QApplicationPrivate::tryModalHelper(widget)) {
792 QApplication::sendEvent(widget, &e);
794 QDragManager *manager = QDragManager::self();
796 if (manager->dropData->currentDataObject) { // Sanity
797 manager->dropData->currentDataObject->Release();
798 manager->dropData->currentDataObject = 0;
804 #define KEY_STATE_BUTTON_MASK (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)
806 QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
807 QOleDropTarget::Drop(LPDATAOBJECT /*pDataObj*/, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
810 qDebug("QOleDropTarget::Drop(LPDATAOBJECT /*pDataObj*/, grfKeyState %d, POINTL pt, LPDWORD pdwEffect)", grfKeyState);
813 QWidget *dropWidget = widget->childAt(widget->mapFromGlobal(QPoint(pt.x, pt.y)));
817 if (!QApplicationPrivate::tryModalHelper(dropWidget)
818 || !dropWidget->testAttribute(Qt::WA_DropSiteRegistered)) {
819 *pdwEffect = DROPEFFECT_NONE;
823 lastPoint = dropWidget->mapFromGlobal(QPoint(pt.x,pt.y));
824 // grfKeyState does not all ways contain button state in the drop so if
825 // it doesn't then use the last known button state;
826 if ((grfKeyState & KEY_STATE_BUTTON_MASK) == 0)
827 grfKeyState |= lastKeyState & KEY_STATE_BUTTON_MASK;
828 lastKeyState = grfKeyState;
830 QDragManager *manager = QDragManager::self();
831 QMimeData *md = manager->source() ? manager->dragPrivate()->data : manager->dropData;
832 QDropEvent e(lastPoint, translateToQDragDropActions(*pdwEffect), md,
833 toQtMouseButtons(grfKeyState), toQtKeyboardModifiers(grfKeyState));
834 if (chosenEffect != DROPEFFECT_NONE) {
835 e.setDropAction(translateToQDragDropAction(chosenEffect));
837 QApplication::sendEvent(dropWidget, &e);
839 if (chosenEffect != DROPEFFECT_NONE) {
844 if (e.isAccepted()) {
845 if (e.dropAction() == Qt::MoveAction || e.dropAction() == Qt::TargetMoveAction) {
846 if (e.dropAction() == Qt::MoveAction)
847 chosenEffect = DROPEFFECT_MOVE;
849 chosenEffect = DROPEFFECT_COPY;
850 HGLOBAL hData = GlobalAlloc(0, sizeof(DWORD));
852 DWORD *moveEffect = (DWORD *)GlobalLock(hData);;
853 *moveEffect = DROPEFFECT_MOVE;
856 memset(&medium, 0, sizeof(STGMEDIUM));
857 medium.tymed = TYMED_HGLOBAL;
858 medium.hGlobal = hData;
860 format.cfFormat = RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT);
861 format.tymed = TYMED_HGLOBAL;
865 manager->dropData->currentDataObject->SetData(&format, &medium, true);
868 chosenEffect = translateToWinDragEffects(e.dropAction());
871 chosenEffect = DROPEFFECT_NONE;
873 *pdwEffect = chosenEffect;
876 if (manager->dropData->currentDataObject) {
877 manager->dropData->currentDataObject->Release();
878 manager->dropData->currentDataObject = 0;
883 // We won't get any mouserelease-event, so manually adjust qApp state:
884 ///### test this QApplication::winMouseButtonUp();
887 //---------------------------------------------------------------------
889 //---------------------------------------------------------------------
891 bool QDropData::hasFormat_sys(const QString &mimeType) const
893 if (!currentDataObject) // Sanity
896 return QWindowsMime::converterToMime(mimeType, currentDataObject) != 0;
899 QStringList QDropData::formats_sys() const
902 if (!currentDataObject) // Sanity
905 fmts = QWindowsMime::allMimesForFormats(currentDataObject);
910 QVariant QDropData::retrieveData_sys(const QString &mimeType, QVariant::Type type) const
914 if (!currentDataObject) // Sanity
917 QWindowsMime *converter = QWindowsMime::converterToMime(mimeType, currentDataObject);
920 result = converter->convertToMime(mimeType, currentDataObject, type);
925 Qt::DropAction QDragManager::drag(QDrag *o)
929 qDebug("QDragManager::drag(QDrag *drag)");
932 if (object == o || !o || !o->d_func()->source)
933 return Qt::IgnoreAction;
937 qApp->removeEventFilter(this);
938 beingCancelled = false;
944 qDebug("actions = %s", dragActionsToString(dragPrivate()->possible_actions).toLatin1().data());
947 dragPrivate()->target = 0;
949 #ifndef QT_NO_ACCESSIBILITY
950 QAccessible::updateAccessibility(this, 0, QAccessible::DragDropStart);
954 QOleDropSource *src = new QOleDropSource();
955 src->createCursors();
956 QOleDataObject *obj = new QOleDataObject(o->mimeData());
957 DWORD allowedEffects = translateToWinDragEffects(dragPrivate()->possible_actions);
959 #if !defined(Q_OS_WINCE) || defined(GWES_ICONCURS)
960 HRESULT r = DoDragDrop(obj, src, allowedEffects, &resultEffect);
962 HRESULT r = DRAGDROP_S_CANCEL;
963 resultEffect = DROPEFFECT_MOVE;
966 Qt::DropAction ret = Qt::IgnoreAction;
967 if (r == DRAGDROP_S_DROP) {
968 if (obj->reportedPerformedEffect() == DROPEFFECT_MOVE && resultEffect != DROPEFFECT_MOVE) {
969 ret = Qt::TargetMoveAction;
970 resultEffect = DROPEFFECT_MOVE;
972 ret = translateToQDragDropAction(resultEffect);
974 // Force it to be a copy if an unsupported operation occurred.
975 // This indicates a bug in the drop target.
976 if (resultEffect != DROPEFFECT_NONE && !(resultEffect & allowedEffects))
977 ret = Qt::CopyAction;
979 dragPrivate()->target = 0;
984 obj->Release(); // Will delete obj if refcount becomes 0
985 src->Release(); // Will delete src if refcount becomes 0
990 #ifndef QT_NO_ACCESSIBILITY
991 QAccessible::updateAccessibility(this, 0, QAccessible::DragDropEnd);
997 void QDragManager::cancel(bool /* deleteSource */)
1000 beingCancelled = true;
1004 #ifndef QT_NO_CURSOR
1005 // insert cancel code here ######## todo
1007 if (restoreCursor) {
1008 QApplication::restoreOverrideCursor();
1009 restoreCursor = false;
1012 #ifndef QT_NO_ACCESSIBILITY
1013 QAccessible::updateAccessibility(this, 0, QAccessible::DragDropEnd);
1017 void QDragManager::updatePixmap()
1019 // not used in windows implementation
1022 bool QDragManager::eventFilter(QObject *, QEvent *)
1024 // not used in windows implementation
1028 void QDragManager::timerEvent(QTimerEvent*)
1030 // not used in windows implementation
1033 void QDragManager::move(const QPoint &)
1035 // not used in windows implementation
1038 void QDragManager::drop()
1040 // not used in windows implementation
1045 #endif // QT_NO_DRAGANDDROP