summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/windows/qwindowsdrag.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/windows/qwindowsdrag.cpp')
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.cpp278
1 files changed, 96 insertions, 182 deletions
diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp
index 9f2a1dc00c..d75752bc04 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.cpp
+++ b/src/plugins/platforms/windows/qwindowsdrag.cpp
@@ -53,8 +53,11 @@
#include <QtGui/QPixmap>
#include <QtGui/QPainter>
#include <QtGui/QGuiApplication>
+#include <QtGui/private/qwindowsysteminterface_qpa_p.h>
+#include <QtGui/private/qguiapplication_p.h>
#include <QtCore/QDebug>
+#include <QtCore/QBuffer>
#include <QtCore/QPoint>
#include <shlobj.h>
@@ -300,14 +303,13 @@ private:
QWindowsDrag *m_drag;
Qt::MouseButtons m_currentButtons;
- Qt::DropAction m_currentAction;
ActionCursorMap m_cursors;
ULONG m_refs;
};
QWindowsOleDropSource::QWindowsOleDropSource(QWindowsDrag *drag) :
- m_drag(drag), m_currentButtons(Qt::NoButton), m_currentAction(Qt::IgnoreAction),
+ m_drag(drag), m_currentButtons(Qt::NoButton),
m_refs(1)
{
if (QWindowsContext::verboseOLE)
@@ -321,24 +323,26 @@ QWindowsOleDropSource::~QWindowsOleDropSource()
qDebug("%s", __FUNCTION__);
}
+/*!
+ \brief Blend custom pixmap with cursors.
+*/
+
void QWindowsOleDropSource::createCursors()
{
- QDragManager *manager = QDragManager::self();
- if (!manager || !manager->object)
- return;
- const QPixmap pixmap = manager->object->pixmap();
+ const QDrag *drag = m_drag->currentDrag();
+ const QPixmap pixmap = drag->pixmap();
const bool hasPixmap = !pixmap.isNull();
- if (!hasPixmap && manager->dragPrivate()->customCursors.isEmpty())
+ if (!hasPixmap)
return;
QList<Qt::DropAction> actions;
actions << Qt::MoveAction << Qt::CopyAction << Qt::LinkAction;
if (hasPixmap)
actions << Qt::IgnoreAction;
- const QPoint hotSpot = manager->object->hotSpot();
+ const QPoint hotSpot = drag->hotSpot();
for (int cnum = 0; cnum < actions.size(); ++cnum) {
const Qt::DropAction action = actions.at(cnum);
- QPixmap cpm = manager->dragCursor(action);
+ QPixmap cpm = drag->dragCursor(action);
if (cpm.isNull())
cpm = m_drag->defaultCursor(action);
if (cpm.isNull()) {
@@ -361,7 +365,7 @@ void QWindowsOleDropSource::createCursors()
const QPoint newHotSpot = hotSpot;
QPixmap newCursor(w, h);
if (hasPixmap) {
- newCursor.fill(QColor(0, 0, 0, 0));
+ newCursor.fill(Qt::transparent);
QPainter p(&newCursor);
const QRect srcRect = pixmap.rect();
const QPoint pmDest = QPoint(qMax(0, -hotSpot.x()), qMax(0, -hotSpot.y()));
@@ -375,7 +379,7 @@ void QWindowsOleDropSource::createCursors()
const int hotY = hasPixmap ? qMax(0,newHotSpot.y()) : 0;
if (const HCURSOR sysCursor = QWindowsCursor::createPixmapCursor(newCursor, hotX, hotY))
- m_cursors.insert(action, sysCursor);
+ m_cursors.insert(actions.at(cnum), sysCursor);
}
if (QWindowsContext::verboseOLE)
qDebug("%s %d cursors", __FUNCTION__, m_cursors.size());
@@ -432,7 +436,7 @@ QWindowsOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
{
HRESULT hr = S_OK;
do {
- if (fEscapePressed || QWindowsDrag::instance()->dragBeingCancelled()) {
+ if (fEscapePressed) {
hr = ResultFromScode(DRAGDROP_S_CANCEL);
break;
}
@@ -461,13 +465,11 @@ QWindowsOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
} while (false);
- QDragManager::self()->willDrop = hr == DRAGDROP_S_DROP;
-
if (QWindowsContext::verboseOLE
&& (QWindowsContext::verboseOLE > 1 || hr != S_OK))
- qDebug("%s fEscapePressed=%d, grfKeyState=%lu buttons=%d willDrop = %d returns 0x%x",
+ qDebug("%s fEscapePressed=%d, grfKeyState=%lu buttons=%d returns 0x%x",
__FUNCTION__, fEscapePressed,grfKeyState, int(m_currentButtons),
- QDragManager::self()->willDrop, int(hr));
+ int(hr));
return hr;
}
@@ -479,16 +481,12 @@ QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
QWindowsOleDropSource::GiveFeedback(DWORD dwEffect)
{
const Qt::DropAction action = translateToQDragDropAction(dwEffect);
+ m_drag->updateAction(action);
if (QWindowsContext::verboseOLE > 2)
qDebug("%s dwEffect=%lu, action=%d", __FUNCTION__, dwEffect, action);
- if (m_currentAction != action) {
- m_currentAction = action;
- QDragManager::self()->emitActionChanged(m_currentAction);
- }
-
- const ActionCursorMap::const_iterator it = m_cursors.constFind(m_currentAction);
+ const ActionCursorMap::const_iterator it = m_cursors.constFind(action);
if (it != m_cursors.constEnd()) {
SetCursor(it.value());
return ResultFromScode(S_OK);
@@ -510,7 +508,7 @@ QWindowsOleDropSource::GiveFeedback(DWORD dwEffect)
*/
QWindowsOleDropTarget::QWindowsOleDropTarget(QWindow *w) :
- m_refs(1), m_window(w), m_currentWindow(0), m_chosenEffect(0), m_lastKeyState(0)
+ m_refs(1), m_window(w), m_chosenEffect(0), m_lastKeyState(0)
{
if (QWindowsContext::verboseOLE)
qDebug() << __FUNCTION__ << this << w;
@@ -558,6 +556,38 @@ QWindow *QWindowsOleDropTarget::findDragOverWindow(const POINTL &pt) const
return m_window;
}
+void QWindowsOleDropTarget::handleDrag(QWindow *window, DWORD grfKeyState,
+ const QPoint &point, LPDWORD pdwEffect)
+{
+ Q_ASSERT(window);
+ m_lastPoint = point;
+ m_lastKeyState = grfKeyState;
+
+ QWindowsDrag *windowsDrag = QWindowsDrag::instance();
+ const Qt::DropActions actions = translateToQDragDropActions(*pdwEffect);
+ QGuiApplicationPrivate::modifier_buttons = toQtKeyboardModifiers(grfKeyState);
+ QGuiApplicationPrivate::mouse_buttons = QWindowsMouseHandler::keyStateToMouseButtons(grfKeyState);
+
+ const QPlatformDragQtResponse response =
+ QWindowSystemInterface::handleDrag(window, windowsDrag->dropData(), m_lastPoint, actions);
+
+ m_answerRect = response.answerRect();
+ const Qt::DropAction action = response.acceptedAction();
+ if (response.isAccepted()) {
+ m_chosenEffect = translateToWinDragEffects(action);
+ } else {
+ m_chosenEffect = DROPEFFECT_NONE;
+ }
+ *pdwEffect = m_chosenEffect;
+ if (QWindowsContext::verboseOLE)
+ qDebug() << __FUNCTION__ << m_window
+ << windowsDrag->dropData() << " supported actions=" << actions
+ << " mods=" << QGuiApplicationPrivate::modifier_buttons
+ << " mouse=" << QGuiApplicationPrivate::mouse_buttons
+ << " accepted: " << response.isAccepted() << action
+ << m_answerRect << " effect" << *pdwEffect;
+}
+
QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
QWindowsOleDropTarget::DragEnter(LPDATAOBJECT pDataObj, DWORD grfKeyState,
POINTL pt, LPDWORD pdwEffect)
@@ -567,124 +597,28 @@ QWindowsOleDropTarget::DragEnter(LPDATAOBJECT pDataObj, DWORD grfKeyState,
QWindowsDrag::instance()->setDropDataObject(pDataObj);
pDataObj->AddRef();
- m_currentWindow = m_window;
- sendDragEnterEvent(m_window, grfKeyState, pt, pdwEffect);
- *pdwEffect = m_chosenEffect;
+ const QPoint point = QWindowsGeometryHint::mapFromGlobal(m_window, QPoint(pt.x,pt.y));
+ handleDrag(m_window, grfKeyState, point, pdwEffect);
return NOERROR;
}
-void QWindowsOleDropTarget::sendDragEnterEvent(QWindow *dragEnterWidget,
- DWORD grfKeyState,
- POINTL pt, LPDWORD pdwEffect)
-{
- Q_ASSERT(dragEnterWidget);
-
- m_lastPoint = QWindowsGeometryHint::mapFromGlobal(dragEnterWidget, QPoint(pt.x,pt.y));
- m_lastKeyState = grfKeyState;
-
- m_chosenEffect = DROPEFFECT_NONE;
-
- QDragManager *manager = QDragManager::self();
- QMimeData *md = manager->dropData();
- const Qt::MouseButtons mouseButtons
- = QWindowsMouseHandler::keyStateToMouseButtons(grfKeyState);
- const Qt::DropActions actions = translateToQDragDropActions(*pdwEffect);
- const Qt::KeyboardModifiers keyMods = toQtKeyboardModifiers(grfKeyState);
- QDragEnterEvent enterEvent(m_lastPoint, actions, md, mouseButtons, keyMods);
- QGuiApplication::sendEvent(m_currentWindow, &enterEvent);
- m_answerRect = enterEvent.answerRect();
- if (QWindowsContext::verboseOLE)
- qDebug() << __FUNCTION__ << " sent drag enter to " << m_window
- << *md << " actions=" << actions
- << " mods=" << keyMods << " accepted: "
- << enterEvent.isAccepted();
-
- if (enterEvent.isAccepted())
- m_chosenEffect = translateToWinDragEffects(enterEvent.dropAction());
- // Documentation states that a drag move event is sent immediately after
- // a drag enter event. This will honor widgets overriding dragMoveEvent only:
- if (enterEvent.isAccepted()) {
- QDragMoveEvent moveEvent(m_lastPoint, actions, md, mouseButtons, keyMods);
- m_answerRect = enterEvent.answerRect();
- moveEvent.setDropAction(enterEvent.dropAction());
- moveEvent.accept(); // accept by default, since enter event was accepted.
-
- QGuiApplication::sendEvent(dragEnterWidget, &moveEvent);
- if (moveEvent.isAccepted()) {
- m_answerRect = moveEvent.answerRect();
- m_chosenEffect = translateToWinDragEffects(moveEvent.dropAction());
- } else {
- m_chosenEffect = DROPEFFECT_NONE;
- }
- }
-}
-
QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
QWindowsOleDropTarget::DragOver(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
{
QWindow *dragOverWindow = findDragOverWindow(pt);
-
+ if (QWindowsContext::verboseOLE)
+ qDebug("%s widget=%p key=%lu, pt=%ld,%ld", __FUNCTION__, dragOverWindow, grfKeyState, pt.x, pt.y);
const QPoint tmpPoint = QWindowsGeometryHint::mapFromGlobal(dragOverWindow, QPoint(pt.x,pt.y));
// see if we should compress this event
if ((tmpPoint == m_lastPoint || m_answerRect.contains(tmpPoint))
&& m_lastKeyState == grfKeyState) {
*pdwEffect = m_chosenEffect;
+ if (QWindowsContext::verboseOLE)
+ qDebug("%s: compressed event", __FUNCTION__);
return NOERROR;
}
- if (QWindowsContext::verboseOLE > 1)
- qDebug().nospace() << '>' << __FUNCTION__ << ' ' << m_window << " current "
- << dragOverWindow << " key=" << grfKeyState
- << " pt=" <<pt.x << ',' << pt.y;
-
- if (dragOverWindow != m_currentWindow) {
- QPointer<QWindow> dragOverWindowGuard(dragOverWindow);
- // Send drag leave event to the previous drag widget.
- // Drag-Over widget might be deleted in DragLeave,
- // (tasktracker 218353).
- QDragLeaveEvent dragLeave;
- if (m_currentWindow)
- QGuiApplication::sendEvent(m_currentWindow, &dragLeave);
- if (!dragOverWindowGuard) {
- dragOverWindow = findDragOverWindow(pt);
- }
- // Send drag enter event to the current drag widget.
- m_currentWindow = dragOverWindow;
- sendDragEnterEvent(dragOverWindow, grfKeyState, pt, pdwEffect);
- }
-
- QDragManager *manager = QDragManager::self();
- QMimeData *md = manager->dropData();
-
- const Qt::DropActions actions = translateToQDragDropActions(*pdwEffect);
-
- QDragMoveEvent oldEvent(m_lastPoint, actions, md,
- QWindowsMouseHandler::keyStateToMouseButtons(m_lastKeyState),
- toQtKeyboardModifiers(m_lastKeyState));
-
- m_lastPoint = tmpPoint;
- m_lastKeyState = grfKeyState;
-
- QDragMoveEvent e(tmpPoint, actions, md,
- QWindowsMouseHandler::keyStateToMouseButtons(grfKeyState),
- toQtKeyboardModifiers(grfKeyState));
- if (m_chosenEffect != DROPEFFECT_NONE) {
- if (oldEvent.dropAction() == e.dropAction() &&
- oldEvent.keyboardModifiers() == e.keyboardModifiers())
- e.setDropAction(translateToQDragDropAction(m_chosenEffect));
- e.accept();
- }
- QGuiApplication::sendEvent(dragOverWindow, &e);
-
- m_answerRect = e.answerRect();
- if (e.isAccepted())
- m_chosenEffect = translateToWinDragEffects(e.dropAction());
- else
- m_chosenEffect = DROPEFFECT_NONE;
- *pdwEffect = m_chosenEffect;
-
- if (QWindowsContext::verboseOLE > 1)
- qDebug("<%s effect=0x%lx", __FUNCTION__, m_chosenEffect);
+ handleDrag(dragOverWindow, grfKeyState, tmpPoint, pdwEffect);
return NOERROR;
}
@@ -694,9 +628,7 @@ QWindowsOleDropTarget::DragLeave()
if (QWindowsContext::verboseOLE)
qDebug().nospace() <<__FUNCTION__ << ' ' << m_window;
- m_currentWindow = 0;
- QDragLeaveEvent e;
- QGuiApplication::sendEvent(m_window, &e);
+ QWindowSystemInterface::handleDrag(m_window, 0, QPoint(), Qt::IgnoreAction);
QWindowsDrag::instance()->releaseDropDataObject();
return NOERROR;
@@ -724,21 +656,15 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT /*pDataObj*/, DWORD grfKeyState,
m_lastKeyState = grfKeyState;
QWindowsDrag *windowsDrag = QWindowsDrag::instance();
- QDragManager *manager = QDragManager::self();
- QMimeData *md = manager->dropData();
- QDropEvent e(m_lastPoint, translateToQDragDropActions(*pdwEffect), md,
- QWindowsMouseHandler::keyStateToMouseButtons(grfKeyState),
- toQtKeyboardModifiers(grfKeyState));
- if (m_chosenEffect != DROPEFFECT_NONE)
- e.setDropAction(translateToQDragDropAction(m_chosenEffect));
-
- QGuiApplication::sendEvent(dropWindow, &e);
- if (m_chosenEffect != DROPEFFECT_NONE)
- e.accept();
-
- if (e.isAccepted()) {
- if (e.dropAction() == Qt::MoveAction || e.dropAction() == Qt::TargetMoveAction) {
- if (e.dropAction() == Qt::MoveAction)
+
+ const QPlatformDropQtResponse response =
+ QWindowSystemInterface::handleDrop(dropWindow, windowsDrag->dropData(), m_lastPoint,
+ translateToQDragDropActions(*pdwEffect));
+
+ if (response.isAccepted()) {
+ const Qt::DropAction action = response.acceptedAction();
+ if (action == Qt::MoveAction || action == Qt::TargetMoveAction) {
+ if (action == Qt::MoveAction)
m_chosenEffect = DROPEFFECT_MOVE;
else
m_chosenEffect = DROPEFFECT_COPY;
@@ -760,7 +686,7 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT /*pDataObj*/, DWORD grfKeyState,
windowsDrag->dropDataObject()->SetData(&format, &medium, true);
}
} else {
- m_chosenEffect = translateToWinDragEffects(e.dropAction());
+ m_chosenEffect = translateToWinDragEffects(action);
}
} else {
m_chosenEffect = DROPEFFECT_NONE;
@@ -778,7 +704,7 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT /*pDataObj*/, DWORD grfKeyState,
\ingroup qt-lighthouse-win
*/
-QWindowsDrag::QWindowsDrag() : m_dropDataObject(0), m_dragBeingCancelled(false)
+QWindowsDrag::QWindowsDrag() : m_dropDataObject(0)
{
}
@@ -786,6 +712,17 @@ QWindowsDrag::~QWindowsDrag()
{
}
+/*!
+ \brief Return data for a drop in process. If it stems from a current drag, use a shortcut.
+*/
+
+QMimeData *QWindowsDrag::dropData()
+{
+ if (const QDrag *drag = currentDrag())
+ return drag->mimeData();
+ return &m_dropData;
+}
+
QPixmap QWindowsDrag::defaultCursor(Qt::DropAction action) const
{
switch (action) {
@@ -810,69 +747,46 @@ QPixmap QWindowsDrag::defaultCursor(Qt::DropAction action) const
return m_ignoreDragCursor;
}
-void QWindowsDrag::startDrag()
+Qt::DropAction QWindowsDrag::drag(QDrag *drag)
{
// TODO: Accessibility handling?
- QDragManager *dragManager = QDragManager::self();
- QMimeData *dropData = dragManager->dropData();
- m_dragBeingCancelled = false;
+ QMimeData *dropData = drag->mimeData();
+ Qt::DropAction dragResult = Qt::IgnoreAction;
DWORD resultEffect;
QWindowsOleDropSource *windowDropSource = new QWindowsOleDropSource(this);
windowDropSource->createCursors();
QWindowsOleDataObject *dropDataObject = new QWindowsOleDataObject(dropData);
- const Qt::DropActions possibleActions = dragManager->possible_actions;
+ const Qt::DropActions possibleActions = drag->supportedActions();
const DWORD allowedEffects = translateToWinDragEffects(possibleActions);
if (QWindowsContext::verboseOLE)
qDebug(">%s possible Actions=%x, effects=0x%lx", __FUNCTION__,
int(possibleActions), allowedEffects);
const HRESULT r = DoDragDrop(dropDataObject, windowDropSource, allowedEffects, &resultEffect);
const DWORD reportedPerformedEffect = dropDataObject->reportedPerformedEffect();
- Qt::DropAction ret = Qt::IgnoreAction;
if (r == DRAGDROP_S_DROP) {
if (reportedPerformedEffect == DROPEFFECT_MOVE && resultEffect != DROPEFFECT_MOVE) {
- ret = Qt::TargetMoveAction;
+ dragResult = Qt::TargetMoveAction;
resultEffect = DROPEFFECT_MOVE;
} else {
- ret = translateToQDragDropAction(resultEffect);
+ dragResult = translateToQDragDropAction(resultEffect);
}
// Force it to be a copy if an unsupported operation occurred.
// This indicates a bug in the drop target.
- if (resultEffect != DROPEFFECT_NONE && !(resultEffect & allowedEffects))
- ret = Qt::CopyAction;
- } else {
- dragManager->setCurrentTarget(0);
+ if (resultEffect != DROPEFFECT_NONE && !(resultEffect & allowedEffects)) {
+ qWarning("%s: Forcing Qt::CopyAction", __FUNCTION__);
+ dragResult = Qt::CopyAction;
+ }
}
-
// clean up
dropDataObject->releaseQt();
dropDataObject->Release(); // Will delete obj if refcount becomes 0
windowDropSource->Release(); // Will delete src if refcount becomes 0
if (QWindowsContext::verboseOLE)
qDebug("<%s allowedEffects=0x%lx, reportedPerformedEffect=0x%lx, resultEffect=0x%lx, hr=0x%x, dropAction=%d",
- __FUNCTION__, allowedEffects, reportedPerformedEffect, resultEffect, int(r), ret);
-}
-
-void QWindowsDrag::move(const QMouseEvent *me)
-{
- const QPoint pos = me->pos();
- if (QWindowsContext::verboseOLE)
- qDebug("%s %d %d", __FUNCTION__, pos.x(), pos.y());
-}
-
-void QWindowsDrag::drop(const QMouseEvent *me)
-{
- const QPoint pos = me->pos();
- if (QWindowsContext::verboseOLE)
- qDebug("%s %d %d", __FUNCTION__, pos.x(), pos.y());
-}
-
-void QWindowsDrag::cancel()
-{
- // TODO: Accessibility handling?
- if (QWindowsContext::verboseOLE)
- qDebug("%s", __FUNCTION__);
- m_dragBeingCancelled = true;
+ __FUNCTION__, allowedEffects, reportedPerformedEffect,
+ resultEffect, int(r), dragResult);
+ return dragResult;
}
QWindowsDrag *QWindowsDrag::instance()