diff options
author | Friedemann Kleint <Friedemann.Kleint@digia.com> | 2014-01-27 13:36:35 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-01-28 19:33:16 +0100 |
commit | 8545ba936647480094afee262ec774d4e97d5af2 (patch) | |
tree | 1c85825d29c7afec826226977b3d6d01f477e2a3 /src/plugins/platforms/windows/qwindowsdrag.cpp | |
parent | a46198a7b31e233a9bb05502b8b3128120fb3fb1 (diff) |
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 <joerg.bornemann@digia.com>
Diffstat (limited to 'src/plugins/platforms/windows/qwindowsdrag.cpp')
-rw-r--r-- | src/plugins/platforms/windows/qwindowsdrag.cpp | 107 |
1 files 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 <QtGui/QMouseEvent> #include <QtGui/QPixmap> #include <QtGui/QPainter> +#include <QtGui/QPaintDevice> +#include <QtGui/QBackingStore> +#include <QtGui/QWindow> #include <QtGui/QGuiApplication> #include <qpa/qwindowsysteminterface_p.h> #include <QtGui/private/qguiapplication_p.h> @@ -207,6 +210,77 @@ static const char * const ignoreDragCursorXpmC[] = { "...............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); } |