add a platform interface for DnD

Use the simple in process DnD implementation
for xcb.
This commit is contained in:
Lars Knoll 2011-05-31 20:45:27 +02:00
parent 07f8aecb52
commit 38745b341c
13 changed files with 433 additions and 150 deletions

View File

@ -42,6 +42,7 @@ qpa {
kernel/qwindowsysteminterface_qpa.h \
kernel/qwindowsysteminterface_qpa_p.h \
kernel/qplatformintegration_qpa.h \
kernel/qplatformdrag_qpa.h \
kernel/qplatformscreen_qpa.h \
kernel/qplatformintegrationfactory_qpa_p.h \
kernel/qplatformintegrationplugin_qpa.h \

View File

@ -58,6 +58,7 @@
#include "qimagewriter.h"
#include "qdebug.h"
#include <ctype.h>
#include <qplatformdrag_qpa.h>
#include <private/qguiapplication_p.h>
@ -121,19 +122,6 @@ QString KeyboardModifiersToString(Qt::KeyboardModifiers moderfies)
}
#endif
class QDropData : public QInternalMimeData
{
public:
QDropData();
~QDropData();
protected:
bool hasFormat_sys(const QString &mimeType) const;
QStringList formats_sys() const;
QVariant retrieveData_sys(const QString &mimeType, QVariant::Type type) const;
};
// the universe's only drag manager
QDragManager *QDragManager::instance = 0;
@ -151,15 +139,19 @@ QDragManager::QDragManager()
restoreCursor = false;
willDrop = false;
eventLoop = 0;
platformDropData = new QDropData();
currentDropTarget = 0;
#ifdef Q_WS_X11
xdndMimeTransferedPixmapIndex = 0;
#endif
currentWindow = 0;
possible_actions = Qt::IgnoreAction;
QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration();
platformDrag = pi->drag();
platformDropData = 0;
if (platformDrag)
platformDropData = platformDrag->platformDropData();
}
@ -170,7 +162,6 @@ QDragManager::~QDragManager()
QGuiApplication::restoreOverrideCursor();
#endif
instance = 0;
delete platformDropData;
}
QDragManager *QDragManager::self()
@ -304,8 +295,6 @@ static const char *const default_pm[] = {
"X X X X X X X",
};
// Shift/Ctrl handling, and final drop status
static Qt::DropAction global_accepted_action = Qt::CopyAction;
static Qt::KeyboardModifiers oldstate;
@ -375,50 +364,6 @@ void QDragManager::updatePixmap()
}
}
void QDragManager::move(const QMouseEvent *me)
{
QWindow *window = QGuiApplication::topLevelAt(me->globalPos());
QPoint pos;
if (window)
pos = me->globalPos() - window->geometry().topLeft();
if (me->buttons()) {
Qt::DropAction prevAction = global_accepted_action;
if (currentWindow != window) {
if (currentWindow) {
QDragLeaveEvent dle;
QCoreApplication::sendEvent(currentWindow, &dle);
willDrop = false;
global_accepted_action = Qt::IgnoreAction;
}
currentWindow = window;
if (currentWindow) {
QDragEnterEvent dee(pos, possible_actions, dropData(), me->buttons(), me->modifiers());
QCoreApplication::sendEvent(currentWindow, &dee);
willDrop = dee.isAccepted() && dee.dropAction() != Qt::IgnoreAction;
global_accepted_action = willDrop ? dee.dropAction() : Qt::IgnoreAction;
}
updateCursor();
restoreCursor = true;
} else if (window) {
Q_ASSERT(currentWindow);
QDragMoveEvent dme(pos, possible_actions, dropData(), me->buttons(), me->modifiers());
if (global_accepted_action != Qt::IgnoreAction) {
dme.setDropAction(global_accepted_action);
dme.accept();
}
QCoreApplication::sendEvent(currentWindow, &dme);
willDrop = dme.isAccepted();
global_accepted_action = willDrop ? dme.dropAction() : Qt::IgnoreAction;
updatePixmap();
updateCursor();
}
if (global_accepted_action != prevAction)
emitActionChanged(global_accepted_action);
}
}
void QDragManager::updateCursor()
{
#ifndef QT_NO_CURSOR
@ -508,9 +453,14 @@ bool QDragManager::eventFilter(QObject *o, QEvent *e)
Qt::DropAction QDragManager::drag(QDrag *o)
{
if (object == o || !o || !o->source())
if (!o || object == o)
return Qt::IgnoreAction;
if (!platformDrag || !o->source()) {
o->deleteLater();
return Qt::IgnoreAction;
}
if (object) {
cancel();
qApp->removeEventFilter(this);
@ -526,9 +476,6 @@ Qt::DropAction QDragManager::drag(QDrag *o)
possible_actions = dragPrivate()->possible_actions;
willDrop = false;
updatePixmap();
updateCursor();
restoreCursor = true;
object->d_func()->target = 0;
qApp->installEventFilter(this);
@ -538,6 +485,7 @@ Qt::DropAction QDragManager::drag(QDrag *o)
restoreCursor = true;
updateCursor();
#endif
updatePixmap();
eventLoop = new QEventLoop;
(void) eventLoop->exec();
@ -550,39 +498,39 @@ Qt::DropAction QDragManager::drag(QDrag *o)
return global_accepted_action;
}
void QDragManager::cancel(bool deleteSource)
void QDragManager::move(const QMouseEvent *me)
{
// qDebug("QDragManager::cancel");
beingCancelled = true;
if (!platformDrag)
return;
if (object->target()) {
QDragLeaveEvent dle;
QCoreApplication::sendEvent(object->target(), &dle);
}
#ifndef QT_NO_CURSOR
if (restoreCursor) {
QGuiApplication::restoreOverrideCursor();
restoreCursor = false;
}
#endif
if (object) {
if (deleteSource)
object->deleteLater();
object = 0;
}
delete qt_qws_dnd_deco;
qt_qws_dnd_deco = 0;
global_accepted_action = Qt::IgnoreAction;
platformDrag->move(me);
}
void QDragManager::drop(const QMouseEvent *me)
{
if (!platformDrag)
return;
#ifndef QT_NO_CURSOR
if (restoreCursor) {
QGuiApplication::restoreOverrideCursor();
restoreCursor = false;
}
#endif
willDrop = false;
platformDrag->drop(me);
if (object)
object->deleteLater();
object = 0;
}
void QDragManager::cancel(bool deleteSource)
{
if (!platformDrag)
return;
#ifndef QT_NO_CURSOR
if (restoreCursor) {
QGuiApplication::restoreOverrideCursor();
@ -590,57 +538,15 @@ void QDragManager::drop(const QMouseEvent *me)
}
#endif
willDrop = false;
QWindow *window = QGuiApplication::topLevelAt(me->globalPos());
beingCancelled = true;
if (window) {
QPoint pos = me->globalPos() - window->geometry().topLeft();
platformDrag->cancel();
QDropEvent de(pos, possible_actions, dropData(), me->buttons(), me->modifiers());
QCoreApplication::sendEvent(window, &de);
if (de.isAccepted())
global_accepted_action = de.dropAction();
else
global_accepted_action = Qt::IgnoreAction;
if (object && deleteSource)
object->deleteLater();
object = 0;
if (object)
object->deleteLater();
object = 0;
}
currentWindow = 0;
}
QDropData::QDropData()
: QInternalMimeData()
{
}
QDropData::~QDropData()
{
}
QVariant QDropData::retrieveData_sys(const QString &mimetype, QVariant::Type type) const
{
QDrag *object = QDragManager::self()->object;
if (!object)
return QVariant();
QByteArray data = object->mimeData()->data(mimetype);
if (type == QVariant::String)
return QString::fromUtf8(data);
return data;
}
bool QDropData::hasFormat_sys(const QString &format) const
{
return formats().contains(format);
}
QStringList QDropData::formats_sys() const
{
QDrag *object = QDragManager::self()->object;
if (object)
return object->mimeData()->formats();
return QStringList();
global_accepted_action = Qt::IgnoreAction;
}
#endif // QT_NO_DRAGANDDROP

View File

@ -66,6 +66,7 @@ QT_BEGIN_NAMESPACE
class QEventLoop;
class QMouseEvent;
class QPlatformDrag;
#ifndef QT_NO_DRAGANDDROP
@ -142,32 +143,35 @@ public:
inline QMimeData *dropData()
{ return object ? dragPrivate()->data : platformDropData; }
void emitActionChanged(Qt::DropAction newAction) { if (object) emit object->actionChanged(newAction); }
void setCurrentTarget(QObject *target, bool dropped = false);
QObject *currentTarget();
QDrag *object;
QMimeData *platformDropData;
bool beingCancelled;
bool restoreCursor;
bool willDrop;
QEventLoop *eventLoop;
void emitActionChanged(Qt::DropAction newAction) { if (object) emit object->actionChanged(newAction); }
void setCurrentTarget(QObject *target, bool dropped = false);
QObject *currentTarget();
QWindow *currentWindow;
Qt::DropActions possible_actions;
// Shift/Ctrl handling, and final drop status
Qt::DropAction global_accepted_action;
private:
QMimeData *platformDropData;
Qt::DropAction currentActionForOverrideCursor;
QObject *currentDropTarget;
QPlatformDrag *platformDrag;
static QDragManager *instance;
Q_DISABLE_COPY(QDragManager)
};
#endif // !QT_NO_DRAGANDDROP

View File

@ -0,0 +1,66 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QPLATFORMDRAG_H
#define QPLATFORMDRAG_H
#include <qglobal.h>
QT_BEGIN_NAMESPACE
class QMimeData;
class QMouseEvent;
class QPlatformDrag
{
public:
virtual ~QPlatformDrag() {}
virtual QMimeData *platformDropData() = 0;
virtual void move(const QMouseEvent *me) = 0;
virtual void drop(const QMouseEvent *me) = 0;
virtual void cancel() = 0;
};
QT_END_NAMESPACE
#endif

View File

@ -44,6 +44,7 @@
#include <QtGui/QPlatformFontDatabase>
#include <QtGui/QPlatformClipboard>
#include <QtGui/QPlatformPrinterSupport>
#include <private/qdnd_p.h>
QT_BEGIN_NAMESPACE
@ -107,6 +108,13 @@ QPlatformClipboard *QPlatformIntegration::clipboard() const
#endif
#ifndef QT_NO_DRAGANDDROP
QPlatformDrag *QPlatformIntegration::drag() const
{
return 0;
}
#endif
QPlatformNativeInterface * QPlatformIntegration::nativeInterface() const
{
return 0;

View File

@ -61,6 +61,7 @@ class QPlatformFontDatabase;
class QPlatformClipboard;
class QPlatformNativeInterface;
class QPlatformPrinterSupport;
class QPlatformDrag;
class Q_GUI_EXPORT QPlatformIntegration
{
@ -90,6 +91,9 @@ public:
#ifndef QT_NO_CLIPBOARD
virtual QPlatformClipboard *clipboard() const;
#endif
#ifndef QT_NO_DRAGANDDROP
virtual QPlatformDrag *drag() const;
#endif
// Experimental in mainthread eventloop integration
// This should only be used if it is only possible to do window system event processing in

View File

@ -42,6 +42,7 @@
#include "qwindowsysteminterface_qpa_p.h"
#include "private/qguiapplication_p.h"
#include <QAbstractEventDispatcher>
#include <qdebug.h>
QT_BEGIN_NAMESPACE

View File

@ -0,0 +1,4 @@
INCLUDEPATH += $$PWD
HEADERS += $$PWD/qsimpledrag.h
SOURCES += $$PWD/qsimpledrag.cpp
QT += gui-private

View File

@ -0,0 +1,202 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsimpledrag.h"
#include "qbitmap.h"
#include "qdrag.h"
#include "qpixmap.h"
#include "qevent.h"
#include "qfile.h"
#include "qtextcodec.h"
#include "qguiapplication.h"
#include "qpoint.h"
#include "qbuffer.h"
#include "qimage.h"
#include "qregexp.h"
#include "qdir.h"
#include "qimagereader.h"
#include "qimagewriter.h"
#include <private/qguiapplication_p.h>
#include <private/qdnd_p.h>
QT_BEGIN_NAMESPACE
class QDropData : public QInternalMimeData
{
public:
QDropData();
~QDropData();
protected:
bool hasFormat_sys(const QString &mimeType) const;
QStringList formats_sys() const;
QVariant retrieveData_sys(const QString &mimeType, QVariant::Type type) const;
};
QSimpleDrag::QSimpleDrag()
{
m_dropData = new QDropData();
currentWindow = 0;
}
QSimpleDrag::~QSimpleDrag()
{
delete m_dropData;
}
QMimeData *QSimpleDrag::platformDropData()
{
return m_dropData;
}
void QSimpleDrag::cancel()
{
QDragManager *m = QDragManager::self();
// qDebug("QDragManager::cancel");
if (m->object->target()) {
QDragLeaveEvent dle;
QCoreApplication::sendEvent(m->object->target(), &dle);
}
}
void QSimpleDrag::move(const QMouseEvent *me)
{
QWindow *window = QGuiApplication::topLevelAt(me->globalPos());
QPoint pos;
if (window)
pos = me->globalPos() - window->geometry().topLeft();
QDragManager *m = QDragManager::self();
if (me->buttons()) {
Qt::DropAction prevAction = m->global_accepted_action;
if (currentWindow != window) {
if (currentWindow) {
QDragLeaveEvent dle;
QCoreApplication::sendEvent(currentWindow, &dle);
m->willDrop = false;
m->global_accepted_action = Qt::IgnoreAction;
}
currentWindow = window;
if (currentWindow) {
QDragEnterEvent dee(pos, m->possible_actions, m->dropData(), me->buttons(), me->modifiers());
QCoreApplication::sendEvent(currentWindow, &dee);
m->willDrop = dee.isAccepted() && dee.dropAction() != Qt::IgnoreAction;
m->global_accepted_action = m->willDrop ? dee.dropAction() : Qt::IgnoreAction;
}
m->updateCursor();
} else if (window) {
Q_ASSERT(currentWindow);
QDragMoveEvent dme(pos, m->possible_actions, m->dropData(), me->buttons(), me->modifiers());
if (m->global_accepted_action != Qt::IgnoreAction) {
dme.setDropAction(m->global_accepted_action);
dme.accept();
}
QCoreApplication::sendEvent(currentWindow, &dme);
m->willDrop = dme.isAccepted();
m->global_accepted_action = m->willDrop ? dme.dropAction() : Qt::IgnoreAction;
m->updatePixmap();
m->updateCursor();
}
if (m->global_accepted_action != prevAction)
m->emitActionChanged(m->global_accepted_action);
}
}
void QSimpleDrag::drop(const QMouseEvent *me)
{
QDragManager *m = QDragManager::self();
QWindow *window = QGuiApplication::topLevelAt(me->globalPos());
if (window) {
QPoint pos = me->globalPos() - window->geometry().topLeft();
QDropEvent de(pos, m->possible_actions, m->dropData(), me->buttons(), me->modifiers());
QCoreApplication::sendEvent(window, &de);
if (de.isAccepted())
m->global_accepted_action = de.dropAction();
else
m->global_accepted_action = Qt::IgnoreAction;
}
currentWindow = 0;
}
QDropData::QDropData()
: QInternalMimeData()
{
}
QDropData::~QDropData()
{
}
QVariant QDropData::retrieveData_sys(const QString &mimetype, QVariant::Type type) const
{
QDrag *object = QDragManager::self()->object;
if (!object)
return QVariant();
QByteArray data = object->mimeData()->data(mimetype);
if (type == QVariant::String)
return QString::fromUtf8(data);
return data;
}
bool QDropData::hasFormat_sys(const QString &format) const
{
return formats().contains(format);
}
QStringList QDropData::formats_sys() const
{
QDrag *object = QDragManager::self()->object;
if (object)
return object->mimeData()->formats();
return QStringList();
}
QT_END_NAMESPACE

View File

@ -0,0 +1,75 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSIMPLEDRAG_H
#define QSIMPLEDRAG_H
#include <qplatformdrag_qpa.h>
QT_BEGIN_NAMESPACE
class QMouseEvent;
class QWindow;
class QDropData;
class QSimpleDrag : public QPlatformDrag
{
public:
QSimpleDrag();
~QSimpleDrag();
virtual QMimeData *platformDropData();
// virtual Qt::DropAction drag(QDrag *);
virtual void cancel();
virtual void move(const QMouseEvent *me);
virtual void drop(const QMouseEvent *me);
private:
QDropData *m_dropData;
QWindow *currentWindow;
};
QT_END_NAMESPACE
#endif

View File

@ -46,6 +46,7 @@
#include "qxcbwindowsurface.h"
#include "qxcbnativeinterface.h"
#include "qxcbclipboard.h"
#include <qsimpledrag.h>
#include <qgenericunixprintersupport.h>
@ -69,11 +70,13 @@ QXcbIntegration::QXcbIntegration()
m_fontDatabase = new QGenericUnixFontDatabase();
m_nativeInterface = new QXcbNativeInterface;
m_drag = new QSimpleDrag;
}
QXcbIntegration::~QXcbIntegration()
{
delete m_connection;
delete m_drag;
}
bool QXcbIntegration::hasCapability(QPlatformIntegration::Capability cap) const
@ -161,3 +164,8 @@ QPlatformClipboard *QXcbIntegration::clipboard() const
{
return m_connection->clipboard();
}
QPlatformDrag *QXcbIntegration::drag() const
{
return m_drag;
}

View File

@ -48,6 +48,7 @@
QT_BEGIN_NAMESPACE
class QXcbConnection;
class QSimpleDrag;
class QXcbIntegration : public QPlatformIntegration
{
@ -71,6 +72,7 @@ public:
QPlatformPrinterSupport *printerSupport() const;
QPlatformClipboard *clipboard() const;
QPlatformDrag *drag() const;
private:
bool hasOpenGL() const;
@ -80,6 +82,7 @@ private:
QPlatformFontDatabase *m_fontDatabase;
QPlatformNativeInterface *m_nativeInterface;
QPlatformPrinterSupport *m_printerSupport;
QSimpleDrag *m_drag;
};
QT_END_NAMESPACE

View File

@ -74,6 +74,7 @@ LIBS += -lxcb -lxcb-image -lxcb-keysyms -lxcb-icccm -lxcb-sync
include (../fontdatabases/genericunix/genericunix.pri)
include (../printersupport/genericunix/genericunix.pri)
include (../dnd/dnd.pri)
target.path += $$[QT_INSTALL_PLUGINS]/platforms
INSTALLS += target