5#include <QtCore/qt_windows.h>
9#if QT_CONFIG(clipboard)
10# include "qwindowsclipboard.h"
19#include <QtGui/qevent.h>
20#include <QtGui/qpixmap.h>
21#include <QtGui/qpainter.h>
22#include <QtGui/qrasterwindow.h>
23#include <QtGui/qguiapplication.h>
24#include <qpa/qwindowsysteminterface_p.h>
25#include <QtGui/private/qdnd_p.h>
26#include <QtGui/private/qguiapplication_p.h>
27#include <QtGui/private/qhighdpiscaling_p.h>
29#include <QtCore/qdebug.h>
30#include <QtCore/qbuffer.h>
31#include <QtCore/qpoint.h>
32#include <QtCore/qpointer.h>
33#include <QtCore/private/qcomobject_p.h>
40
41
42
43
44
45
57 QPainter painter(
this);
58 painter.drawPixmap(0, 0, m_pixmap);
68 QSurfaceFormat windowFormat = format();
69 windowFormat.setAlphaBufferSize(8);
70 setFormat(windowFormat);
71 setObjectName(QStringLiteral(
"QWindowsDragCursorWindow"));
72 setFlags(Qt::Popup | Qt::NoDropShadowWindowHint
73 | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint
74 | Qt::WindowDoesNotAcceptFocus | Qt::WindowTransparentForInput);
79 if (p.cacheKey() == m_pixmap.cacheKey())
81 const QSize oldSize = m_pixmap.size();
82 QSize newSize = p.size();
83 qCDebug(lcQpaMime) <<
__FUNCTION__ << p.cacheKey() << newSize;
85 if (oldSize != newSize) {
86 const qreal pixDevicePixelRatio = p.devicePixelRatio();
87 if (pixDevicePixelRatio > 1.0 && qFuzzyCompare(pixDevicePixelRatio, devicePixelRatio()))
88 newSize /= qRound(pixDevicePixelRatio);
96
97
98
99
100
101
102
103
104
113 Qt::DropActions actions = Qt::IgnoreAction;
114 if (pdwEffects & DROPEFFECT_LINK)
115 actions |= Qt::LinkAction;
116 if (pdwEffects & DROPEFFECT_COPY)
117 actions |= Qt::CopyAction;
118 if (pdwEffects & DROPEFFECT_MOVE)
119 actions |= Qt::MoveAction;
125 if (pdwEffect & DROPEFFECT_LINK)
126 return Qt::LinkAction;
127 if (pdwEffect & DROPEFFECT_COPY)
128 return Qt::CopyAction;
129 if (pdwEffect & DROPEFFECT_MOVE)
130 return Qt::MoveAction;
131 return Qt::IgnoreAction;
136 DWORD effect = DROPEFFECT_NONE;
137 if (action & Qt::LinkAction)
138 effect |= DROPEFFECT_LINK;
139 if (action & Qt::CopyAction)
140 effect |= DROPEFFECT_COPY;
141 if (action & Qt::MoveAction)
142 effect |= DROPEFFECT_MOVE;
148 Qt::KeyboardModifiers modifiers = Qt::NoModifier;
150 if (keyState & MK_SHIFT)
151 modifiers |= Qt::ShiftModifier;
152 if (keyState & MK_CONTROL)
153 modifiers |= Qt::ControlModifier;
154 if (keyState & MK_ALT)
155 modifiers |= Qt::AltModifier;
164
165
166
167
168
169
170
171
192 CursorEntry() : cacheKey(0) {}
193 CursorEntry(
const QPixmap &p, qint64 cK,
const CursorHandlePtr &c,
const QPoint &h) :
194 pixmap(p), cacheKey(cK), cursor(c), hotSpot(h) {}
198 CursorHandlePtr cursor;
202 typedef QMap<Qt::DropAction, CursorEntry> ActionCursorMap;
206 QPointer<QWindow> m_windowUnderMouse;
207 Qt::MouseButtons m_currentButtons;
208 ActionCursorMap m_cursors;
211#ifndef QT_NO_DEBUG_STREAM
221 , m_touchDragWindow(
nullptr)
223 qCDebug(lcQpaMime) <<
__FUNCTION__ << m_mode;
229 delete m_touchDragWindow;
230 qCDebug(lcQpaMime) <<
__FUNCTION__;
233#ifndef QT_NO_DEBUG_STREAM
236 d <<
"CursorEntry:" << e.pixmap.size() <<
'#' << e.cacheKey
237 <<
"HCURSOR" << e.cursor->handle() <<
"hotspot:" << e.hotSpot;
243
244
248 const QDrag *drag = m_drag->currentDrag();
249 const QPixmap pixmap = drag->pixmap();
250 const bool hasPixmap = !pixmap.isNull();
254 if (!platformScreen) {
255 if (
const QScreen *primaryScreen = QGuiApplication::primaryScreen())
256 platformScreen = primaryScreen->handle();
258 QPlatformCursor *platformCursor =
nullptr;
260 platformCursor = platformScreen->cursor();
262 if (GetSystemMetrics (SM_REMOTESESSION) != 0) {
264
265
266 const int rdpLargeCursor = qRound(qreal(96) / QHighDpiScaling::factor(platformScreen));
267 if (pixmap.width() > rdpLargeCursor || pixmap.height() > rdpLargeCursor)
271 qreal pixmapScaleFactor = 1;
272 qreal hotSpotScaleFactor = 1;
274 hotSpotScaleFactor = QHighDpiScaling::factor(platformScreen);
275 pixmapScaleFactor = hotSpotScaleFactor / pixmap.devicePixelRatio();
277 QPixmap scaledPixmap = (!hasPixmap || qFuzzyCompare(pixmapScaleFactor, 1.0))
279 : pixmap.scaled((QSizeF(pixmap.size()) * pixmapScaleFactor).toSize(),
280 Qt::KeepAspectRatio, Qt::SmoothTransformation);
281 scaledPixmap.setDevicePixelRatio(1);
283 Qt::DropAction actions[] = { Qt::MoveAction, Qt::CopyAction, Qt::LinkAction, Qt::IgnoreAction };
284 int actionCount =
int(
sizeof(actions) /
sizeof(actions[0]));
287 const QPoint hotSpot = qFuzzyCompare(hotSpotScaleFactor, 1.0)
289 : (QPointF(drag->hotSpot()) * hotSpotScaleFactor).toPoint();
290 for (
int cnum = 0; cnum < actionCount; ++cnum) {
291 const Qt::DropAction action = actions[cnum];
292 QPixmap cursorPixmap = drag->dragCursor(action);
293 if (cursorPixmap.isNull() && platformCursor)
294 cursorPixmap =
static_cast<
QWindowsCursor *>(platformCursor)->dragDefaultCursor(action);
295 const qint64 cacheKey = cursorPixmap.cacheKey();
296 const auto it = m_cursors.find(action);
297 if (it != m_cursors.end() && it.value().cacheKey == cacheKey)
299 if (cursorPixmap.isNull()) {
300 qWarning(
"%s: Unable to obtain drag cursor for %d.",
__FUNCTION__, action);
305 QPixmap newPixmap = cursorPixmap;
308 const int x1 = qMin(-hotSpot.x(), 0);
309 const int x2 = qMax(scaledPixmap.width() - hotSpot.x(), cursorPixmap.width());
310 const int y1 = qMin(-hotSpot.y(), 0);
311 const int y2 = qMax(scaledPixmap.height() - hotSpot.y(), cursorPixmap.height());
312 QPixmap newCursor(x2 - x1 + 1, y2 - y1 + 1);
313 newCursor.fill(Qt::transparent);
314 QPainter p(&newCursor);
315 const QPoint pmDest = QPoint(qMax(0, -hotSpot.x()), qMax(0, -hotSpot.y()));
316 p.drawPixmap(pmDest, scaledPixmap);
317 p.drawPixmap(qMax(0, hotSpot.x()),qMax(0, hotSpot.y()), cursorPixmap);
318 newPixmap = newCursor;
319 newHotSpot =
QPoint(qMax(0, hotSpot.x()), qMax(0, hotSpot.y()));
322 if (
const HCURSOR sysCursor = QWindowsCursor::createPixmapCursor(newPixmap, newHotSpot)) {
323 const CursorEntry entry(newPixmap, cacheKey, CursorHandlePtr(
new CursorHandle(sysCursor)), newHotSpot);
324 if (it == m_cursors.end())
325 m_cursors.insert(action, entry);
330#ifndef QT_NO_DEBUG_OUTPUT
331 if (lcQpaMime().isDebugEnabled())
332 qCDebug(lcQpaMime) <<
__FUNCTION__ <<
"pixmap" << pixmap.size() << m_cursors.size() <<
"cursors:\n" << m_cursors;
337
338
340QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
341QWindowsOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
noexcept
346 Qt::MouseButtons buttons = QWindowsPointerHandler::queryMouseButtons();
349 if (fEscapePressed || QWindowsDrag::isCanceled()) {
350 result = DRAGDROP_S_CANCEL;
351 buttons = Qt::NoButton;
353 if (buttons && !m_currentButtons) {
354 m_currentButtons = buttons;
355 }
else if (m_currentButtons != buttons) {
356 result = DRAGDROP_S_DROP;
361 case DRAGDROP_S_DROP:
362 case DRAGDROP_S_CANCEL:
363 if (!m_windowUnderMouse.isNull() && m_mode != TouchDrag && fEscapePressed == FALSE
364 && buttons != lastButtons) {
367 const QPoint globalPos = QWindowsCursor::mousePosition();
368 const QPoint localPos = m_windowUnderMouse->handle()->mapFromGlobal(globalPos);
369 QWindowSystemInterface::handleMouseEvent(m_windowUnderMouse.data(),
370 QPointF(localPos), QPointF(globalPos),
371 QWindowsPointerHandler::queryMouseButtons(),
372 Qt::LeftButton, QEvent::MouseButtonRelease);
374 m_currentButtons = Qt::NoButton;
378 QGuiApplication::processEvents();
382 if (QWindowsContext::verbose > 1 || result != S_OK) {
383 qCDebug(lcQpaMime) <<
__FUNCTION__ <<
"fEscapePressed=" << fEscapePressed
384 <<
"grfKeyState=" << grfKeyState <<
"buttons" << m_currentButtons
385 <<
"returns 0x" << Qt::hex <<
int(result) << Qt::dec;
387 return ResultFromScode(result);
391
392
394QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
395QWindowsOleDropSource::GiveFeedback(DWORD dwEffect)
noexcept
397 const Qt::DropAction action = translateToQDragDropAction(dwEffect);
398 m_drag->updateAction(action);
400 const qint64 currentCacheKey = m_drag->currentDrag()->dragCursor(action).cacheKey();
401 auto it = m_cursors.constFind(action);
403 if (it == m_cursors.constEnd() || (currentCacheKey && currentCacheKey != it.value().cacheKey)) {
405 it = m_cursors.constFind(action);
408 if (it != m_cursors.constEnd()) {
409 const CursorEntry &e = it.value();
412 SetCursor(e.cursor->handle());
416 if (QWindowsCursor::cursorState() != QWindowsCursor::State::Suppressed)
418 if (!m_touchDragWindow)
419 m_touchDragWindow =
new QWindowsDragCursorWindow;
420 m_touchDragWindow->setPixmap(e.pixmap);
421 m_touchDragWindow->setFramePosition(QCursor::pos() - e.hotSpot);
422 if (!m_touchDragWindow->isVisible())
423 m_touchDragWindow->show();
426 return ResultFromScode(S_OK);
429 return ResultFromScode(DRAGDROP_S_USEDEFAULTCURSORS);
433
434
435
436
437
438
439
440
441
442
446 qCDebug(lcQpaMime) <<
__FUNCTION__ <<
this << w;
451 qCDebug(lcQpaMime) <<
__FUNCTION__ <<
this;
455 const QPoint &point, LPDWORD pdwEffect)
459 m_lastKeyState = grfKeyState;
462 const Qt::DropActions actions = translateToQDragDropActions(*pdwEffect);
464 lastModifiers = toQtKeyboardModifiers(grfKeyState);
465 lastButtons = QWindowsPointerHandler::queryMouseButtons();
467 const QPlatformDragQtResponse response =
468 QWindowSystemInterface::handleDrag(window, windowsDrag->dropData(),
469 m_lastPoint, actions,
470 lastButtons, lastModifiers);
472 m_answerRect = response.answerRect();
473 const Qt::DropAction action = response.acceptedAction();
474 if (response.isAccepted()) {
475 m_chosenEffect = translateToWinDragEffects(action);
477 m_chosenEffect = DROPEFFECT_NONE;
479 *pdwEffect = m_chosenEffect;
480 qCDebug(lcQpaMime) <<
__FUNCTION__ << m_window
481 << windowsDrag->dropData() <<
" supported actions=" << actions
482 <<
" mods=" << lastModifiers <<
" mouse=" << lastButtons
483 <<
" accepted: " << response.isAccepted() << action
484 << m_answerRect <<
" effect" << *pdwEffect;
487QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
488QWindowsOleDropTarget::DragEnter(LPDATAOBJECT pDataObj, DWORD grfKeyState,
489 POINTL pt, LPDWORD pdwEffect)
noexcept
491 if (IDropTargetHelper* dh = QWindowsDrag::instance()->dropHelper())
492 dh->DragEnter(
reinterpret_cast<HWND>(m_window->winId()), pDataObj,
reinterpret_cast<POINT*>(&pt), *pdwEffect);
494 qCDebug(lcQpaMime) <<
__FUNCTION__ <<
"widget=" << m_window <<
" key=" << grfKeyState
495 <<
"pt=" << pt.x << pt.y;
497 QWindowsDrag::instance()->setDropDataObject(pDataObj);
499 const QPoint point = QWindowsGeometryHint::mapFromGlobal(m_window, QPoint(pt.x,pt.y));
500 handleDrag(m_window, grfKeyState, point, pdwEffect);
504QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
505QWindowsOleDropTarget::DragOver(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
noexcept
507 if (IDropTargetHelper* dh = QWindowsDrag::instance()->dropHelper())
508 dh->DragOver(
reinterpret_cast<POINT*>(&pt), *pdwEffect);
510 qCDebug(lcQpaMime) <<
__FUNCTION__ <<
"m_window" << m_window <<
"key=" << grfKeyState
511 <<
"pt=" << pt.x << pt.y;
512 const QPoint tmpPoint = QWindowsGeometryHint::mapFromGlobal(m_window, QPoint(pt.x,pt.y));
514 if ((tmpPoint == m_lastPoint || m_answerRect.contains(tmpPoint))
515 && m_lastKeyState == grfKeyState) {
516 *pdwEffect = m_chosenEffect;
517 qCDebug(lcQpaMime) <<
__FUNCTION__ <<
"compressed event";
521 handleDrag(m_window, grfKeyState, tmpPoint, pdwEffect);
525QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
526QWindowsOleDropTarget::DragLeave()
noexcept
528 if (IDropTargetHelper* dh = QWindowsDrag::instance()->dropHelper())
531 qCDebug(lcQpaMime) <<
__FUNCTION__ <<
' ' << m_window;
533 const auto *keyMapper = QWindowsContext::instance()->keyMapper();
534 lastModifiers = keyMapper->queryKeyboardModifiers();
535 lastButtons = QWindowsPointerHandler::queryMouseButtons();
537 QWindowSystemInterface::handleDrag(m_window,
nullptr, QPoint(), Qt::IgnoreAction,
538 Qt::NoButton, Qt::NoModifier);
540 if (!QDragManager::self()->source())
542 QWindowsDrag::instance()->releaseDropDataObject();
547#define KEY_STATE_BUTTON_MASK (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)
549QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
550QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState,
551 POINTL pt, LPDWORD pdwEffect)
noexcept
553 if (IDropTargetHelper* dh = QWindowsDrag::instance()->dropHelper())
554 dh->Drop(pDataObj,
reinterpret_cast<POINT*>(&pt), *pdwEffect);
556 qCDebug(lcQpaMime) <<
__FUNCTION__ <<
' ' << m_window
557 <<
"keys=" << grfKeyState <<
"pt=" << pt.x <<
',' << pt.y;
559 m_lastPoint = QWindowsGeometryHint::mapFromGlobal(m_window, QPoint(pt.x,pt.y));
561 QWindowsDrag *windowsDrag = QWindowsDrag::instance();
563 lastModifiers = toQtKeyboardModifiers(grfKeyState);
564 lastButtons = QWindowsPointerHandler::queryMouseButtons();
566 const QPlatformDropQtResponse response =
567 QWindowSystemInterface::handleDrop(m_window, windowsDrag->dropData(),
569 translateToQDragDropActions(*pdwEffect),
573 m_lastKeyState = grfKeyState;
575 if (response.isAccepted()) {
576 const Qt::DropAction action = response.acceptedAction();
577 if (action == Qt::MoveAction || action == Qt::TargetMoveAction) {
578 if (action == Qt::MoveAction)
579 m_chosenEffect = DROPEFFECT_MOVE;
581 m_chosenEffect = DROPEFFECT_COPY;
582 HGLOBAL hData = GlobalAlloc(0,
sizeof(DWORD));
584 auto *moveEffect =
reinterpret_cast<DWORD *>(GlobalLock(hData));
585 *moveEffect = DROPEFFECT_MOVE;
588 memset(&medium, 0,
sizeof(STGMEDIUM));
589 medium.tymed = TYMED_HGLOBAL;
590 medium.hGlobal = hData;
592 format.cfFormat = CLIPFORMAT(RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT));
593 format.tymed = TYMED_HGLOBAL;
594 format.ptd =
nullptr;
597 windowsDrag->dropDataObject()->SetData(&format, &medium,
true);
600 m_chosenEffect = translateToWinDragEffects(action);
603 m_chosenEffect = DROPEFFECT_NONE;
605 *pdwEffect = m_chosenEffect;
607 windowsDrag->releaseDropDataObject();
613
614
615
616
624 if (m_cachedDropTargetHelper)
625 m_cachedDropTargetHelper->Release();
629
630
634 if (
const QDrag *drag = currentDrag())
635 return drag->mimeData();
640
641
643 if (!m_cachedDropTargetHelper) {
644 CoCreateInstance(CLSID_DragDropHelper,
nullptr, CLSCTX_INPROC_SERVER,
645 IID_IDropTargetHelper,
646 reinterpret_cast<
void**>(&m_cachedDropTargetHelper));
648 return m_cachedDropTargetHelper;
657 const HWND hwnd = hasMouseCapture ?
reinterpret_cast<HWND>(underMouse->winId()) : ::GetFocus();
658 bool starting =
false;
662 if (::GetMessage(&msg, hwnd, 0, 0) > 0) {
664 if (msg.message == WM_MOUSEMOVE) {
667 if (!starting && (msg.wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON | MK_XBUTTON1 | MK_XBUTTON2)) == 0)
670 return ::DoDragDrop(pDataObj, pDropSource, dwOKEffects, pdwEffect);
675 const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
677 POINTER_INFO pointerInfo{};
678 if (!GetPointerInfo(pointerId, &pointerInfo))
681 if (pointerInfo.pointerFlags & POINTER_FLAG_PRIMARY) {
683 DWORD flags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_VIRTUALDESK | MOUSEEVENTF_MOVE;
684 if (IS_POINTER_FIRSTBUTTON_WPARAM(msg.wParam))
685 flags |= MOUSEEVENTF_LEFTDOWN;
686 if (IS_POINTER_SECONDBUTTON_WPARAM(msg.wParam))
687 flags |= MOUSEEVENTF_RIGHTDOWN;
688 if (IS_POINTER_THIRDBUTTON_WPARAM(msg.wParam))
689 flags |= MOUSEEVENTF_MIDDLEDOWN;
693 if (::GetCursorPos(&pt)) {
696 if ((flags & MOUSEEVENTF_LEFTDOWN || flags & MOUSEEVENTF_RIGHTDOWN || flags & MOUSEEVENTF_MIDDLEDOWN)
697 && (pt.x != pointerInfo.ptPixelLocation.x || pt.y != pointerInfo.ptPixelLocation.y)) {
699 const int origin_x = ::GetSystemMetrics(SM_XVIRTUALSCREEN);
700 const int origin_y = ::GetSystemMetrics(SM_YVIRTUALSCREEN);
701 const int virt_w = ::GetSystemMetrics(SM_CXVIRTUALSCREEN);
702 const int virt_h = ::GetSystemMetrics(SM_CYVIRTUALSCREEN);
703 const int virt_x = pointerInfo.ptPixelLocation.x - origin_x;
704 const int virt_y = pointerInfo.ptPixelLocation.y - origin_y;
707 input.type = INPUT_MOUSE;
708 input.mi.dx =
static_cast<DWORD>(virt_x * (65535.0 / virt_w));
709 input.mi.dy =
static_cast<DWORD>(virt_y * (65535.0 / virt_h));
710 input.mi.dwFlags = flags;
712 ::SendInput(1, &input,
sizeof(input));
720 qWindowsWndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
734 QMimeData *dropData = drag->mimeData();
735 Qt::DropAction dragResult = Qt::IgnoreAction;
742 const Qt::DropActions possibleActions = drag->supportedActions();
743 const DWORD allowedEffects = translateToWinDragEffects(possibleActions);
744 qCDebug(lcQpaMime) <<
'>' <<
__FUNCTION__ <<
"possible Actions=0x"
745 << Qt::hex <<
int(possibleActions) <<
"effects=0x" << allowedEffects << Qt::dec;
746 const HRESULT r = startDoDragDrop(dropDataObject, windowDropSource, allowedEffects, &resultEffect);
747 const DWORD reportedPerformedEffect = dropDataObject->reportedPerformedEffect();
748 if (r == DRAGDROP_S_DROP) {
749 if (reportedPerformedEffect == DROPEFFECT_MOVE && resultEffect != DROPEFFECT_MOVE) {
750 dragResult = Qt::TargetMoveAction;
751 resultEffect = DROPEFFECT_MOVE;
753 dragResult = translateToQDragDropAction(resultEffect);
757 if (resultEffect != DROPEFFECT_NONE && !(resultEffect & allowedEffects)) {
758 qWarning(
"%s: Forcing Qt::CopyAction",
__FUNCTION__);
759 dragResult = Qt::CopyAction;
763 dropDataObject->releaseQt();
764 dropDataObject->Release();
765 windowDropSource->Release();
766 qCDebug(lcQpaMime) <<
'<' <<
__FUNCTION__ << Qt::hex <<
"allowedEffects=0x" << allowedEffects
767 <<
"reportedPerformedEffect=0x" << reportedPerformedEffect
768 <<
" resultEffect=0x" << resultEffect <<
"hr=0x" <<
int(r) << Qt::dec <<
"dropAction=" << dragResult;
779 qCDebug(lcQpaMime) <<
__FUNCTION__ << m_dropDataObject;
780 if (m_dropDataObject) {
781 m_dropDataObject->Release();
782 m_dropDataObject =
nullptr;
\inmodule QtCore\reentrant
Singleton container for all relevant information.
QWindowsScreenManager & screenManager()
static QWindowsContext * instance()
Platform cursor implementation.
static QPoint mousePosition()
static State cursorState()
A toplevel window showing the drag icon in case of touch drag.
void setPixmap(const QPixmap &p)
void paintEvent(QPaintEvent *) override
Handles paint events passed in the event parameter.
QWindowsDragCursorWindow(QWindow *parent=nullptr)
Windows drag implementation.
QMimeData * dropData()
Return data for a drop in process.
static QWindowsDrag * instance()
void releaseDropDataObject()
IDropTargetHelper * dropHelper()
May be used to handle extended cursors functionality for drags from outside the app.
Qt::DropAction drag(QDrag *drag) override
QWindowsOleDataObject subclass specialized for handling Drag&Drop.
QWindowsDropDataObject(QMimeData *mimeData)
Special mime data class for data retrieval from Drag operations.
IDataObject * retrieveDataObject() const override
static QWindowsIntegration * instance()
Implementation of IDropSource.
STDMETHOD GiveFeedback(DWORD dwEffect) noexcept override
Give feedback: Change cursor according to action.
~QWindowsOleDropSource() override
void createCursors()
Blend custom pixmap with cursors.
QWindowsOleDropSource(QWindowsDrag *drag)
STDMETHOD QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState) noexcept override
Check for cancel.
Implementation of IDropTarget.
~QWindowsOleDropTarget() override
const QWindowsScreen * screenAtDp(const QPoint &p) const
bool hasMouseCapture() const
Combined button and popup list for selecting options.
static HRESULT startDoDragDrop(LPDATAOBJECT pDataObj, LPDROPSOURCE pDropSource, DWORD dwOKEffects, LPDWORD pdwEffect)
static Qt::DropActions translateToQDragDropActions(DWORD pdwEffects)
static Qt::KeyboardModifiers toQtKeyboardModifiers(DWORD keyState)
static Qt::MouseButtons lastButtons
static Qt::DropAction translateToQDragDropAction(DWORD pdwEffect)
static DWORD translateToWinDragEffects(Qt::DropActions action)
static Qt::KeyboardModifiers lastModifiers