From 8545ba936647480094afee262ec774d4e97d5af2 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 27 Jan 2014 13:36:35 +0100 Subject: Fixed Drag and Drop driven by touch-synthesized mouse events. When dragging by touch driven by synthesized mouse events, the cursor is suppressed. Use a popup window to show the drag cursor instead. [ChangeLog][QDrag][Windows] Fixed Drag and Drop driven by touch-synthesized mouse events. Change-Id: Id8c1aab79a091c89986ee7ee62ded44a3267fd3f Reviewed-by: Joerg Bornemann --- src/plugins/platforms/windows/qwindowsdrag.cpp | 107 +++++++++++++++++++++++-- 1 file changed, 102 insertions(+), 5 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp index ae9e3867ab..8f3ccdc0be 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.cpp +++ b/src/plugins/platforms/windows/qwindowsdrag.cpp @@ -54,6 +54,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -206,6 +209,77 @@ static const char * const ignoreDragCursorXpmC[] = { ".............XXaaaaXX...", "...............XXXX....."}; +/*! + \class QWindowsDragCursorWindow + \brief A toplevel window showing the drag icon in case of touch drag. + + \sa QWindowsOleDropSource + \internal + \ingroup qt-lighthouse-win +*/ + +class QWindowsDragCursorWindow : public QWindow +{ +public: + explicit QWindowsDragCursorWindow(QWindow *parent = 0); + + void setPixmap(const QPixmap &p); + +protected: + void exposeEvent(QExposeEvent *); + +private: + void render(); + + QBackingStore m_backingStore; + QPixmap m_pixmap; +}; + +QWindowsDragCursorWindow::QWindowsDragCursorWindow(QWindow *parent) + : QWindow(parent) + , m_backingStore(this) +{ + QSurfaceFormat windowFormat = format(); + windowFormat.setAlphaBufferSize(8); + setFormat(windowFormat); + setObjectName(QStringLiteral("QWindowsDragCursorWindow")); + setFlags(Qt::Popup | Qt::NoDropShadowWindowHint + | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint + | Qt::WindowDoesNotAcceptFocus | Qt::WindowTransparentForInput); +} + +void QWindowsDragCursorWindow::setPixmap(const QPixmap &p) +{ + if (p.cacheKey() == m_pixmap.cacheKey()) + return; + const QSize oldSize = m_pixmap.size(); + const QSize newSize = p.size(); + qCDebug(lcQpaMime) << __FUNCTION__ << p.cacheKey() << newSize; + m_pixmap = p; + if (oldSize != newSize) { + resize(newSize); + m_backingStore.resize(newSize); + } + if (isVisible()) + render(); +} + +void QWindowsDragCursorWindow::exposeEvent(QExposeEvent *) +{ + Q_ASSERT(!m_pixmap.isNull()); + render(); +} + +void QWindowsDragCursorWindow::render() +{ + const QRect rect(QPoint(0, 0), m_pixmap.size()); + m_backingStore.beginPaint(rect); + QPainter painter(m_backingStore.paintDevice()); + painter.drawPixmap(0, 0, m_pixmap); + m_backingStore.endPaint(); + m_backingStore.flush(rect); +} + /*! \class QWindowsDropMimeData \brief Special mime data class for data retrieval from Drag operations. @@ -286,6 +360,11 @@ static inline Qt::KeyboardModifiers toQtKeyboardModifiers(DWORD keyState) class QWindowsOleDropSource : public IDropSource { public: + enum Mode { + MouseDrag, + TouchDrag // Mouse cursor suppressed, use window as cursor. + }; + explicit QWindowsOleDropSource(QWindowsDrag *drag); virtual ~QWindowsOleDropSource(); @@ -325,9 +404,11 @@ private: typedef ActionCursorMap::Iterator ActionCursorMapIt; typedef ActionCursorMap::ConstIterator ActionCursorMapConstIt; + const Mode m_mode; QWindowsDrag *m_drag; Qt::MouseButtons m_currentButtons; ActionCursorMap m_cursors; + QWindowsDragCursorWindow *m_touchDragWindow; ULONG m_refs; #ifndef QT_NO_DEBUG_OUTPUT @@ -335,16 +416,20 @@ private: #endif }; -QWindowsOleDropSource::QWindowsOleDropSource(QWindowsDrag *drag) : - m_drag(drag), m_currentButtons(Qt::NoButton), - m_refs(1) +QWindowsOleDropSource::QWindowsOleDropSource(QWindowsDrag *drag) + : m_mode(QWindowsCursor::cursorState() != QWindowsCursor::CursorSuppressed ? MouseDrag : TouchDrag) + , m_drag(drag) + , m_currentButtons(Qt::NoButton) + , m_touchDragWindow(0) + , m_refs(1) { - qCDebug(lcQpaMime) << __FUNCTION__; + qCDebug(lcQpaMime) << __FUNCTION__ << m_mode; } QWindowsOleDropSource::~QWindowsOleDropSource() { m_cursors.clear(); + delete m_touchDragWindow; qCDebug(lcQpaMime) << __FUNCTION__; } @@ -517,7 +602,19 @@ QWindowsOleDropSource::GiveFeedback(DWORD dwEffect) if (it != m_cursors.constEnd()) { const CursorEntry &e = it.value(); - SetCursor(e.cursor->cursor); + switch (m_mode) { + case MouseDrag: + SetCursor(e.cursor->cursor); + break; + case TouchDrag: + if (!m_touchDragWindow) + m_touchDragWindow = new QWindowsDragCursorWindow; + m_touchDragWindow->setPixmap(e.pixmap); + m_touchDragWindow->setFramePosition(QWindowsCursor::mousePosition() - e.hotSpot); + if (!m_touchDragWindow->isVisible()) + m_touchDragWindow->show(); + break; + } return ResultFromScode(S_OK); } -- cgit v1.2.3