Possibility to change custom Drag&Drop cursors while dragging something. Implementation for Windows and X11.

Additional checks to figure out if new Drag&Drop cursors where set. This means it is possible now to keep QDrag object in your program and call setDragCursor() method every time we need to change cursor depending on context.

Change-Id: I4be69e44b2863371a7ffbb29efc17c18210d6cde
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Reviewed-by: Gatis Paeglis <gatis.paeglis@digia.com>
Reviewed-by: Samuel Rødal <samuel.rodal@digia.com>
This commit is contained in:
Cyril Oblikov 2012-09-27 17:55:16 +03:00 committed by The Qt Project
parent 80e87c0241
commit 38e02188ee
2 changed files with 36 additions and 19 deletions

View File

@ -253,8 +253,19 @@ void QBasicDrag::updateCursor(Qt::DropAction action)
} }
QCursor *cursor = qApp->overrideCursor(); QCursor *cursor = qApp->overrideCursor();
if (cursor && cursorShape != cursor->shape()) { QPixmap pixmap = m_drag->dragCursor(action);
qApp->changeOverrideCursor(QCursor(cursorShape)); if (!cursor) {
qApp->changeOverrideCursor((pixmap.isNull()) ? QCursor(cursorShape) : QCursor(pixmap));
} else {
if (!pixmap.isNull()) {
if ((cursor->pixmap().cacheKey() != pixmap.cacheKey())) {
qApp->changeOverrideCursor(QCursor(pixmap));
}
} else {
if (cursorShape != cursor->shape()) {
qApp->changeOverrideCursor(QCursor(cursorShape));
}
}
} }
updateAction(action); updateAction(action);
} }

View File

@ -301,9 +301,15 @@ public:
STDMETHOD(GiveFeedback)(DWORD dwEffect); STDMETHOD(GiveFeedback)(DWORD dwEffect);
private: private:
typedef QMap <Qt::DropAction, HCURSOR> ActionCursorMap; class DragCursorHandle {
Q_DISABLE_COPY(DragCursorHandle)
inline void clearCursors(); public:
DragCursorHandle(HCURSOR c, quint64 k) : cursor(c), cacheKey(k) {}
~DragCursorHandle() { DestroyCursor(cursor); }
HCURSOR cursor;
quint64 cacheKey;
};
typedef QMap <Qt::DropAction, QSharedPointer<DragCursorHandle> > ActionCursorMap;
QWindowsDrag *m_drag; QWindowsDrag *m_drag;
Qt::MouseButtons m_currentButtons; Qt::MouseButtons m_currentButtons;
@ -322,7 +328,7 @@ QWindowsOleDropSource::QWindowsOleDropSource(QWindowsDrag *drag) :
QWindowsOleDropSource::~QWindowsOleDropSource() QWindowsOleDropSource::~QWindowsOleDropSource()
{ {
clearCursors(); m_cursors.clear();
if (QWindowsContext::verboseOLE) if (QWindowsContext::verboseOLE)
qDebug("%s", __FUNCTION__); qDebug("%s", __FUNCTION__);
} }
@ -347,10 +353,14 @@ void QWindowsOleDropSource::createCursors()
QPixmap cpm = drag->dragCursor(action); QPixmap cpm = drag->dragCursor(action);
if (cpm.isNull()) if (cpm.isNull())
cpm = m_drag->defaultCursor(action); cpm = m_drag->defaultCursor(action);
QSharedPointer<DragCursorHandle> cursorHandler = m_cursors.value(action);
if (!cursorHandler.isNull() && cpm.cacheKey() == cursorHandler->cacheKey)
continue;
if (cpm.isNull()) { if (cpm.isNull()) {
qWarning("%s: Unable to obtain drag cursor for %d.", __FUNCTION__, action); qWarning("%s: Unable to obtain drag cursor for %d.", __FUNCTION__, action);
continue; continue;
} }
int w = cpm.width(); int w = cpm.width();
int h = cpm.height(); int h = cpm.height();
@ -380,23 +390,14 @@ void QWindowsOleDropSource::createCursors()
const int hotX = hasPixmap ? qMax(0,newHotSpot.x()) : 0; const int hotX = hasPixmap ? qMax(0,newHotSpot.x()) : 0;
const int hotY = hasPixmap ? qMax(0,newHotSpot.y()) : 0; const int hotY = hasPixmap ? qMax(0,newHotSpot.y()) : 0;
if (const HCURSOR sysCursor = QWindowsCursor::createPixmapCursor(newCursor, hotX, hotY)) if (const HCURSOR sysCursor = QWindowsCursor::createPixmapCursor(newCursor, hotX, hotY)) {
m_cursors.insert(actions.at(cnum), sysCursor); m_cursors.insert(action, QSharedPointer<DragCursorHandle>(new DragCursorHandle(sysCursor, cpm.cacheKey())));
}
} }
if (QWindowsContext::verboseOLE) if (QWindowsContext::verboseOLE)
qDebug("%s %d cursors", __FUNCTION__, m_cursors.size()); qDebug("%s %d cursors", __FUNCTION__, m_cursors.size());
} }
void QWindowsOleDropSource::clearCursors()
{
if (!m_cursors.isEmpty()) {
const ActionCursorMap::const_iterator cend = m_cursors.constEnd();
for (ActionCursorMap::const_iterator it = m_cursors.constBegin(); it != cend; ++it)
DestroyCursor(it.value());
m_cursors.clear();
}
}
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// IUnknown Methods // IUnknown Methods
//--------------------------------------------------------------------- //---------------------------------------------------------------------
@ -488,9 +489,14 @@ QWindowsOleDropSource::GiveFeedback(DWORD dwEffect)
if (QWindowsContext::verboseOLE > 2) if (QWindowsContext::verboseOLE > 2)
qDebug("%s dwEffect=%lu, action=%d", __FUNCTION__, dwEffect, action); qDebug("%s dwEffect=%lu, action=%d", __FUNCTION__, dwEffect, action);
QSharedPointer<DragCursorHandle> cursorHandler = m_cursors.value(action);
quint64 currentCacheKey = m_drag->currentDrag()->dragCursor(action).cacheKey();
if (cursorHandler.isNull() || currentCacheKey != cursorHandler->cacheKey)
createCursors();
const ActionCursorMap::const_iterator it = m_cursors.constFind(action); const ActionCursorMap::const_iterator it = m_cursors.constFind(action);
if (it != m_cursors.constEnd()) { if (it != m_cursors.constEnd()) {
SetCursor(it.value()); SetCursor(it.value()->cursor);
return ResultFromScode(S_OK); return ResultFromScode(S_OK);
} }