summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/generic/evdevkeyboard/evdevkeyboard.pro4
-rw-r--r--src/plugins/generic/evdevmouse/evdevmouse.pro2
-rw-r--r--src/plugins/generic/evdevmouse/qevdevmouse.cpp23
-rw-r--r--src/plugins/generic/evdevtouch/README12
-rw-r--r--src/plugins/generic/evdevtouch/evdevtouch.pro6
-rw-r--r--src/plugins/generic/evdevtouch/qevdevtouch.cpp89
-rw-r--r--src/plugins/generic/evdevtouch/qevdevtouch.h8
-rw-r--r--src/plugins/platforms/blackberry/qbbclipboard.cpp184
-rw-r--r--src/plugins/platforms/blackberry/qbbclipboard.h5
-rw-r--r--src/plugins/platforms/blackberry/qbbscreen.cpp2
-rw-r--r--src/plugins/platforms/cocoa/cocoa.pro8
-rw-r--r--src/plugins/platforms/cocoa/qcocoacursor.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoacursor.mm3
-rw-r--r--src/plugins/platforms/cocoa/qcocoadrag.h76
-rw-r--r--src/plugins/platforms/cocoa/qcocoadrag.mm99
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.h5
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.mm58
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h5
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm17
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuloader.mm1
-rw-r--r--src/plugins/platforms/cocoa/qcocoasystemsettings.h57
-rw-r--r--src/plugins/platforms/cocoa/qcocoasystemsettings.mm272
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.h11
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.mm26
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm2
-rw-r--r--src/plugins/platforms/cocoa/qmacclipboard.h93
-rw-r--r--src/plugins/platforms/cocoa/qmacclipboard.mm653
-rw-r--r--src/plugins/platforms/cocoa/qmacdefines_mac.h11
-rw-r--r--src/plugins/platforms/cocoa/qmacmime.h77
-rw-r--r--src/plugins/platforms/cocoa/qmacmime.mm938
-rw-r--r--src/plugins/platforms/cocoa/qnsview.h4
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm74
-rw-r--r--src/plugins/platforms/cocoa/qt_mac_p.h38
-rw-r--r--src/plugins/platforms/directfb/qdirectfbcursor.cpp4
-rw-r--r--src/plugins/platforms/directfb/qdirectfbcursor.h1
-rw-r--r--src/plugins/platforms/directfb/qdirectfbscreen.h1
-rw-r--r--src/plugins/platforms/kms/qkmscursor.cpp2
-rw-r--r--src/plugins/platforms/kms/qkmsscreen.cpp5
-rw-r--r--src/plugins/platforms/kms/qkmsscreen.h1
-rw-r--r--src/plugins/platforms/windows/main.cpp6
-rw-r--r--src/plugins/platforms/windows/qtwindows_additional.h3
-rw-r--r--src/plugins/platforms/windows/qwindowsaccessibility.cpp134
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.cpp5
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.cpp278
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.h14
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.cpp49
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.h1
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp40
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase_ft.h5
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.cpp8
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.cpp14
-rw-r--r--src/plugins/platforms/windows/qwindowsole.cpp10
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp10
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.h15
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.cpp148
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.h8
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp24
-rw-r--r--src/plugins/platforms/xcb/README4
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.cpp18
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp55
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h6
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.cpp438
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.h45
-rw-r--r--src/plugins/platforms/xcb/qxcbimage.cpp8
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp6
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp9
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbsharedbuffermanager.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp45
-rw-r--r--src/plugins/platforms/xcb/qxcbwmsupport.cpp7
-rw-r--r--src/plugins/platforms/xcb/xcb.pro2
-rw-r--r--src/plugins/platforms/xlib/qxlibcursor.cpp8
-rw-r--r--src/plugins/platforms/xlib/qxlibcursor.h5
-rw-r--r--src/plugins/platforms/xlib/qxlibscreen.cpp5
-rw-r--r--src/plugins/platforms/xlib/qxlibscreen.h1
81 files changed, 3472 insertions, 862 deletions
diff --git a/src/plugins/generic/evdevkeyboard/evdevkeyboard.pro b/src/plugins/generic/evdevkeyboard/evdevkeyboard.pro
index 82edf170a8..21e4bf63ee 100644
--- a/src/plugins/generic/evdevkeyboard/evdevkeyboard.pro
+++ b/src/plugins/generic/evdevkeyboard/evdevkeyboard.pro
@@ -12,11 +12,11 @@ HEADERS = \
QT += core-private platformsupport-private
-LIBS += -ludev
-
SOURCES = main.cpp \
qevdevkeyboardhandler.cpp \
qevdevkeyboardmanager.cpp
OTHER_FILES += \
evdevkeyboard.json
+
+LIBS += $$QMAKE_LIBS_LIBUDEV
diff --git a/src/plugins/generic/evdevmouse/evdevmouse.pro b/src/plugins/generic/evdevmouse/evdevmouse.pro
index c5d162fb2f..781d901f28 100644
--- a/src/plugins/generic/evdevmouse/evdevmouse.pro
+++ b/src/plugins/generic/evdevmouse/evdevmouse.pro
@@ -14,3 +14,5 @@ SOURCES = main.cpp \
OTHER_FILES += \
evdevmouse.json
+
+LIBS += $$QMAKE_LIBS_LIBUDEV
diff --git a/src/plugins/generic/evdevmouse/qevdevmouse.cpp b/src/plugins/generic/evdevmouse/qevdevmouse.cpp
index 0b72123c02..be779c68a5 100644
--- a/src/plugins/generic/evdevmouse/qevdevmouse.cpp
+++ b/src/plugins/generic/evdevmouse/qevdevmouse.cpp
@@ -176,12 +176,27 @@ void QEvdevMouseHandler::readMouseData()
sendMouseEvent();
pendingMouseEvent = false;
- } else if (data->type == EV_KEY && data->code >= BTN_LEFT && data->code <= BTN_MIDDLE) {
+ } else if (data->type == EV_KEY && data->code >= BTN_LEFT && data->code <= BTN_JOYSTICK) {
Qt::MouseButton button = Qt::NoButton;
+ // BTN_LEFT == 0x110 in kernel's input.h
+ // The range of possible mouse buttons ends just before BTN_JOYSTICK, value 0x120.
switch (data->code) {
- case BTN_LEFT: button = Qt::LeftButton; break;
- case BTN_MIDDLE: button = Qt::MidButton; break;
- case BTN_RIGHT: button = Qt::RightButton; break;
+ case 0x110: button = Qt::LeftButton; break; // BTN_LEFT
+ case 0x111: button = Qt::RightButton; break;
+ case 0x112: button = Qt::MiddleButton; break;
+ case 0x113: button = Qt::ExtraButton1; break; // AKA Qt::BackButton
+ case 0x114: button = Qt::ExtraButton2; break; // AKA Qt::ForwardButton
+ case 0x115: button = Qt::ExtraButton3; break; // AKA Qt::TaskButton
+ case 0x116: button = Qt::ExtraButton4; break;
+ case 0x117: button = Qt::ExtraButton5; break;
+ case 0x118: button = Qt::ExtraButton6; break;
+ case 0x119: button = Qt::ExtraButton7; break;
+ case 0x11a: button = Qt::ExtraButton8; break;
+ case 0x11b: button = Qt::ExtraButton9; break;
+ case 0x11c: button = Qt::ExtraButton10; break;
+ case 0x11d: button = Qt::ExtraButton11; break;
+ case 0x11e: button = Qt::ExtraButton12; break;
+ case 0x11f: button = Qt::ExtraButton13; break;
}
if (data->value)
m_buttons |= button;
diff --git a/src/plugins/generic/evdevtouch/README b/src/plugins/generic/evdevtouch/README
index 4764ef8f70..119f2a2c9e 100644
--- a/src/plugins/generic/evdevtouch/README
+++ b/src/plugins/generic/evdevtouch/README
@@ -1,8 +1,14 @@
-Generic plug-in for evdev touch events. (protocol type A)
+Generic plug-in for evdev touch (ABS_MT) events.
+Supports protocol type A & B.
+Type B is supported both directly and via libmtdev.
-Tested with the following drivers: bcm5974, hid_magicmouse.
+The protocol type will be detected automatically.
+To enable libmtdev support uncomment the USE_MTDEV define in
+evdevtouch.pro.
-To use it, pass -plugin EvdevTouch on the command line.
+Tested with the following kernel drivers: bcm5974, hid_magicmouse.
+
+To use this "driver", pass -plugin EvdevTouch on the command line.
If automatic detection does not work, use -plugin
EvdevTouch:/dev/input/eventN to explicitly set the device file
diff --git a/src/plugins/generic/evdevtouch/evdevtouch.pro b/src/plugins/generic/evdevtouch/evdevtouch.pro
index 284f1d1221..192a87c2a3 100644
--- a/src/plugins/generic/evdevtouch/evdevtouch.pro
+++ b/src/plugins/generic/evdevtouch/evdevtouch.pro
@@ -15,3 +15,9 @@ QT += core-private platformsupport-private
OTHER_FILES += \
evdevtouch.json
+
+LIBS += $$QMAKE_LIBS_LIBUDEV
+
+# DEFINES += USE_MTDEV
+
+contains(DEFINES, USE_MTDEV): LIBS += -lmtdev
diff --git a/src/plugins/generic/evdevtouch/qevdevtouch.cpp b/src/plugins/generic/evdevtouch/qevdevtouch.cpp
index d508c4a12a..9e6347457d 100644
--- a/src/plugins/generic/evdevtouch/qevdevtouch.cpp
+++ b/src/plugins/generic/evdevtouch/qevdevtouch.cpp
@@ -49,8 +49,18 @@
#include <QtPlatformSupport/private/qudevhelper_p.h>
#include <linux/input.h>
+#ifdef USE_MTDEV
+extern "C" {
+#include <mtdev.h>
+}
+#endif
+
QT_BEGIN_NAMESPACE
+#ifndef ABS_MT_SLOT
+#define ABS_MT_SLOT 0x2f
+#endif
+
class QTouchScreenData
{
public:
@@ -75,8 +85,10 @@ public:
x(0), y(0), maj(1), pressure(0),
state(Qt::TouchPointPressed), flags(0) { }
};
- QHash<int, Contact> m_contacts, m_lastContacts;
+ QHash<int, Contact> m_contacts; // The key is a tracking id for type A, slot number for type B.
+ QHash<int, Contact> m_lastContacts;
Contact m_currentData;
+ int m_currentSlot;
int findClosestContact(const QHash<int, Contact> &contacts, int x, int y, int *dist);
void reportPoints();
@@ -91,11 +103,13 @@ public:
QString hw_name;
bool m_forceToActiveWindow;
QTouchDevice *m_device;
+ bool m_typeB;
};
QTouchScreenData::QTouchScreenData(QTouchScreenHandler *q_ptr, const QStringList &args)
: q(q_ptr),
m_lastEventType(-1),
+ m_currentSlot(0),
hw_range_x_min(0), hw_range_x_max(0),
hw_range_y_min(0), hw_range_y_max(0),
hw_pressure_min(0), hw_pressure_max(0)
@@ -115,8 +129,19 @@ void QTouchScreenData::registerDevice()
QWindowSystemInterface::registerTouchDevice(m_device);
}
+#define LONG_BITS (sizeof(long) << 3)
+#define NUM_LONGS(bits) (((bits) + LONG_BITS - 1) / LONG_BITS)
+
+static inline bool testBit(long bit, const long *array)
+{
+ return (array[bit / LONG_BITS] >> bit % LONG_BITS) & 1;
+}
+
QTouchScreenHandler::QTouchScreenHandler(const QString &spec)
: m_notify(0), m_fd(-1), d(0)
+#ifdef USE_MTDEV
+ , m_mtdev(0)
+#endif
{
setObjectName(QLatin1String("Evdev Touch Handler"));
@@ -141,6 +166,16 @@ QTouchScreenHandler::QTouchScreenHandler(const QString &spec)
return;
}
+#ifdef USE_MTDEV
+ m_mtdev = static_cast<mtdev *>(calloc(1, sizeof(mtdev)));
+ int mtdeverr = mtdev_open(m_mtdev, m_fd);
+ if (mtdeverr) {
+ qWarning("mtdev_open failed: %d", mtdeverr);
+ QT_CLOSE(m_fd);
+ return;
+ }
+#endif
+
d = new QTouchScreenData(this, args);
input_absinfo absInfo;
@@ -168,11 +203,30 @@ QTouchScreenHandler::QTouchScreenHandler(const QString &spec)
qDebug("device name: %s", name);
}
+#ifdef USE_MTDEV
+ const char *mtdevStr = "(mtdev)";
+ d->m_typeB = true;
+#else
+ const char *mtdevStr = "";
+ d->m_typeB = false;
+ long absbits[NUM_LONGS(ABS_CNT)];
+ if (ioctl(m_fd, EVIOCGBIT(EV_ABS, sizeof(absbits)), absbits) >= 0)
+ d->m_typeB = testBit(ABS_MT_SLOT, absbits);
+#endif
+ qDebug("Protocol type %c %s", d->m_typeB ? 'B' : 'A', mtdevStr);
+
d->registerDevice();
}
QTouchScreenHandler::~QTouchScreenHandler()
{
+#ifdef USE_MTDEV
+ if (m_mtdev) {
+ mtdev_close(m_mtdev);
+ free(m_mtdev);
+ }
+#endif
+
if (m_fd >= 0)
QT_CLOSE(m_fd);
@@ -184,8 +238,13 @@ void QTouchScreenHandler::readData()
::input_event buffer[32];
int n = 0;
for (; ;) {
+#ifdef USE_MTDEV
+ n = mtdev_get(m_mtdev, m_fd, buffer, sizeof(buffer) / sizeof(::input_event));
+ if (n > 0)
+ n *= sizeof(::input_event);
+#else
n = QT_READ(m_fd, reinterpret_cast<char*>(buffer) + n, sizeof(buffer) - n);
-
+#endif
if (!n) {
qWarning("Got EOF from input device");
return;
@@ -215,16 +274,32 @@ void QTouchScreenData::processInputEvent(input_event *data)
if (data->code == ABS_MT_POSITION_X) {
m_currentData.x = qBound(hw_range_x_min, data->value, hw_range_x_max);
+ if (m_typeB)
+ m_contacts[m_currentSlot].x = m_currentData.x;
} else if (data->code == ABS_MT_POSITION_Y) {
m_currentData.y = qBound(hw_range_y_min, data->value, hw_range_y_max);
+ if (m_typeB)
+ m_contacts[m_currentSlot].y = m_currentData.y;
} else if (data->code == ABS_MT_TRACKING_ID) {
m_currentData.trackingId = data->value;
+ if (m_typeB) {
+ if (m_currentData.trackingId == -1)
+ m_contacts[m_currentSlot].state = Qt::TouchPointReleased;
+ else
+ m_contacts[m_currentSlot].trackingId = m_currentData.trackingId;
+ }
} else if (data->code == ABS_MT_TOUCH_MAJOR) {
m_currentData.maj = data->value;
if (data->value == 0)
m_currentData.state = Qt::TouchPointReleased;
+ if (m_typeB)
+ m_contacts[m_currentSlot].maj = m_currentData.maj;
} else if (data->code == ABS_PRESSURE) {
m_currentData.pressure = qBound(hw_pressure_min, data->value, hw_pressure_max);
+ if (m_typeB)
+ m_contacts[m_currentSlot].pressure = m_currentData.pressure;
+ } else if (data->code == ABS_MT_SLOT) {
+ m_currentSlot = data->value;
}
} else if (data->type == EV_SYN && data->code == SYN_MT_REPORT && m_lastEventType != EV_SYN) {
@@ -254,8 +329,9 @@ void QTouchScreenData::processInputEvent(input_event *data)
tp.id = contact.trackingId;
tp.flags = contact.flags;
- if (m_lastContacts.contains(contact.trackingId)) {
- const Contact &prev(m_lastContacts.value(contact.trackingId));
+ int key = m_typeB ? it.key() : contact.trackingId;
+ if (m_lastContacts.contains(key)) {
+ const Contact &prev(m_lastContacts.value(key));
if (contact.state == Qt::TouchPointReleased) {
// Copy over the previous values for released points, just in case.
contact.x = prev.x;
@@ -269,7 +345,7 @@ void QTouchScreenData::processInputEvent(input_event *data)
// Avoid reporting a contact in released state more than once.
if (contact.state == Qt::TouchPointReleased
- && !m_lastContacts.contains(contact.trackingId)) {
+ && !m_lastContacts.contains(key)) {
it.remove();
continue;
}
@@ -293,7 +369,8 @@ void QTouchScreenData::processInputEvent(input_event *data)
}
m_lastContacts = m_contacts;
- m_contacts.clear();
+ if (!m_typeB)
+ m_contacts.clear();
if (!m_touchPoints.isEmpty() && combinedStates != Qt::TouchPointStationary)
reportPoints();
diff --git a/src/plugins/generic/evdevtouch/qevdevtouch.h b/src/plugins/generic/evdevtouch/qevdevtouch.h
index 343f638526..28a3b215fb 100644
--- a/src/plugins/generic/evdevtouch/qevdevtouch.h
+++ b/src/plugins/generic/evdevtouch/qevdevtouch.h
@@ -54,6 +54,9 @@ QT_BEGIN_NAMESPACE
class QSocketNotifier;
class QTouchScreenData;
+#ifdef USE_MTDEV
+struct mtdev;
+#endif
class QTouchScreenHandler : public QObject
{
@@ -67,11 +70,12 @@ private slots:
void readData();
private:
- void pathFromUdev(QString *path);
-
QSocketNotifier *m_notify;
int m_fd;
QTouchScreenData *d;
+#ifdef USE_MTDEV
+ mtdev *m_mtdev;
+#endif
};
class QTouchScreenHandlerThread : public QThread
diff --git a/src/plugins/platforms/blackberry/qbbclipboard.cpp b/src/plugins/platforms/blackberry/qbbclipboard.cpp
index fce016d5ee..293a0c771b 100644
--- a/src/plugins/platforms/blackberry/qbbclipboard.cpp
+++ b/src/plugins/platforms/blackberry/qbbclipboard.cpp
@@ -46,6 +46,7 @@
#include <QtGui/QColor>
#include <QtCore/QDebug>
+#include <QtCore/QMimeData>
#include <QtCore/QStringList>
#include <QtCore/QUrl>
@@ -53,11 +54,131 @@
#include <errno.h>
QT_BEGIN_NAMESPACE
-static const char *typeList[] = {"text/html", "text/plain", "application/x-color"};
+
+// null terminated array
+static const char *typeList[] = {"text/html", "text/plain", "image/png", "image/jpeg", "application/x-color", 0};
+
+static QByteArray readClipboardBuff(const char *type)
+{
+ char *pbuffer;
+ if (is_clipboard_format_present(type) == 0) {
+ int size = get_clipboard_data(type, &pbuffer);
+ if (size != -1 && pbuffer) {
+ const QByteArray result = QByteArray(pbuffer, size);
+ free(pbuffer);
+ return result;
+ }
+ }
+
+ return QByteArray();
+}
+
+class QBBClipboard::MimeData : public QMimeData
+{
+ Q_OBJECT
+public:
+ MimeData(QBBClipboard *clipboard)
+ : QMimeData(),
+ m_clipboard(clipboard),
+ m_userMimeData(0)
+ {
+ Q_ASSERT(clipboard);
+
+ for (int i = 0; typeList[i] != 0; ++i) {
+ m_formatsToCheck << QString::fromUtf8(typeList[i]);
+ }
+ }
+
+ ~MimeData()
+ {
+ delete m_userMimeData;
+ }
+
+ void addFormatToCheck(const QString &format) {
+ m_formatsToCheck << format;
+
+#if defined(QBBCLIPBOARD_DEBUG)
+ qDebug() << Q_FUNC_INFO << "formats=" << m_formatsToCheck;
+#endif
+ }
+
+ bool hasFormat(const QString &mimetype) const
+ {
+ const bool result = is_clipboard_format_present(mimetype.toUtf8().constData()) == 0;
+#if defined(QBBCLIPBOARD_DEBUG)
+ qDebug() << Q_FUNC_INFO << "mimetype=" << mimetype << "result=" << result;
+#endif
+ return result;
+ }
+
+ QStringList formats() const
+ {
+ QStringList result;
+
+ Q_FOREACH (const QString &format, m_formatsToCheck) {
+ if (is_clipboard_format_present(format.toUtf8().constData()) == 0)
+ result << format;
+ }
+
+#if defined(QBBCLIPBOARD_DEBUG)
+ qDebug() << Q_FUNC_INFO << "result=" << result;
+#endif
+ return result;
+ }
+
+ void setUserMimeData(QMimeData *userMimeData)
+ {
+ delete m_userMimeData;
+ m_userMimeData = userMimeData;
+
+ // system clipboard API doesn't allow detection of changes by other applications
+ // simulate an owner change through delayed invocation
+ // basically transfer ownership of data to the system clipboard once event processing resumes
+ if (m_userMimeData)
+ QMetaObject::invokeMethod(this, "releaseOwnership", Qt::QueuedConnection);
+ }
+
+ QMimeData *userMimeData()
+ {
+ return m_userMimeData;
+ }
+
+protected:
+ QVariant retrieveData(const QString &mimetype, QVariant::Type preferredType) const
+ {
+#if defined(QBBCLIPBOARD_DEBUG)
+ qDebug() << Q_FUNC_INFO << "mimetype=" << mimetype << "preferredType=" << preferredType;
+#endif
+ if (is_clipboard_format_present(mimetype.toUtf8().constData()) != 0)
+ return QMimeData::retrieveData(mimetype, preferredType);
+
+ const QByteArray data = readClipboardBuff(mimetype.toUtf8().constData());
+ return qVariantFromValue(data);
+ }
+
+private Q_SLOTS:
+ void releaseOwnership()
+ {
+ if (m_userMimeData) {
+#if defined(QBBCLIPBOARD_DEBUG)
+ qDebug() << Q_FUNC_INFO << "user data formats=" << m_userMimeData->formats() << "system formats=" << formats();
+#endif
+ delete m_userMimeData;
+ m_userMimeData = 0;
+ m_clipboard->emitChanged(QClipboard::Clipboard);
+ }
+ }
+
+private:
+ QBBClipboard * const m_clipboard;
+
+ QSet<QString> m_formatsToCheck;
+ QMimeData *m_userMimeData;
+};
QBBClipboard::QBBClipboard()
+ : m_mimeData(new MimeData(this))
{
- m_mimeData = 0;
}
QBBClipboard::~QBBClipboard()
@@ -70,46 +191,37 @@ void QBBClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
if (mode != QClipboard::Clipboard)
return;
- if (m_mimeData != data) {
- delete m_mimeData;
- m_mimeData = data;
- }
+ if (data == m_mimeData || data == m_mimeData->userMimeData())
+ return;
empty_clipboard();
+ m_mimeData->clear();
+ m_mimeData->setUserMimeData(data);
+
if (data == 0)
return;
- QStringList format = data->formats();
- for (int i = 0; i < format.size(); ++i) {
- QString type = format.at(i);
- QByteArray buf = data->data(type);
- if (!buf.size())
- continue;
-
- int ret = set_clipboard_data(type.toUtf8().data(), buf.size(), buf.data());
+ const QStringList formats = data->formats();
#if defined(QBBCLIPBOARD_DEBUG)
- qDebug() << "QBB: set " << type.toUtf8().data() << "to clipboard, size=" << buf.size() << ";ret=" << ret;
-#else
- Q_UNUSED(ret);
+ qDebug() << Q_FUNC_INFO << "formats=" << formats;
#endif
- }
-}
-void QBBClipboard::readClipboardBuff(const char *type)
-{
- char *pbuffer;
- if (is_clipboard_format_present(type) == 0) {
- int size = get_clipboard_data(type, &pbuffer);
- if (size != -1 && pbuffer) {
- QString qtype = type;
+ Q_FOREACH (const QString &format, formats) {
+ const QByteArray buf = data->data(format);
+
+ if (buf.isEmpty())
+ continue;
+
+ int ret = set_clipboard_data(format.toUtf8().data(), buf.size(), buf.data());
#if defined(QBBCLIPBOARD_DEBUG)
- qDebug() << "QBB: clipboard has " << qtype;
+ qDebug() << "QBB: set " << format << "to clipboard, size=" << buf.size() << ";ret=" << ret;
#endif
- m_mimeData->setData(qtype, QByteArray(pbuffer, size));
- delete pbuffer;
- }
+ if (ret)
+ m_mimeData->addFormatToCheck(format);
}
+
+ emitChanged(QClipboard::Clipboard);
}
QMimeData *QBBClipboard::mimeData(QClipboard::Mode mode)
@@ -117,16 +229,16 @@ QMimeData *QBBClipboard::mimeData(QClipboard::Mode mode)
if (mode != QClipboard::Clipboard)
return 0;
- if (!m_mimeData)
- m_mimeData = new QMimeData();
+ if (m_mimeData->userMimeData())
+ return m_mimeData->userMimeData();
m_mimeData->clear();
- for (int i = 0; i < 3; i++)
- readClipboardBuff(typeList[i]);
-
return m_mimeData;
}
QT_END_NAMESPACE
-#endif //QT_NO_CLIPBOAR
+
+#include "qbbclipboard.moc"
+
+#endif //QT_NO_CLIPBOARD
diff --git a/src/plugins/platforms/blackberry/qbbclipboard.h b/src/plugins/platforms/blackberry/qbbclipboard.h
index b9de9b3e36..11a36ba8e5 100644
--- a/src/plugins/platforms/blackberry/qbbclipboard.h
+++ b/src/plugins/platforms/blackberry/qbbclipboard.h
@@ -44,7 +44,6 @@
#ifndef QT_NO_CLIPBOARD
#include <QtGui/QPlatformClipboard>
-#include <QMimeData>
QT_BEGIN_NAMESPACE
@@ -57,8 +56,8 @@ public:
virtual void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard);
private:
- QMimeData *m_mimeData;
- void readClipboardBuff(const char *type);
+ class MimeData;
+ MimeData *m_mimeData;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/blackberry/qbbscreen.cpp b/src/plugins/platforms/blackberry/qbbscreen.cpp
index 39d2136b7d..11e40f6150 100644
--- a/src/plugins/platforms/blackberry/qbbscreen.cpp
+++ b/src/plugins/platforms/blackberry/qbbscreen.cpp
@@ -286,7 +286,7 @@ void QBBScreen::updateHierarchy()
#endif
QList<QBBWindow*>::iterator it;
- int topZorder = 0;
+ int topZorder = 1; // root window is z-order 0, all "top" level windows are "above" it
for (it = ms_childWindows.begin(); it != ms_childWindows.end(); it++)
(*it)->updateZorder(topZorder);
diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro
index 45dd3525d5..b953210720 100644
--- a/src/plugins/platforms/cocoa/cocoa.pro
+++ b/src/plugins/platforms/cocoa/cocoa.pro
@@ -27,6 +27,10 @@ OBJECTIVE_SOURCES += main.mm \
qcocoafiledialoghelper.mm \
qcocoafontdialoghelper.mm \
qcocoacursor.mm \
+ qcocoadrag.mm \
+ qmacclipboard.mm \
+ qmacmime.mm \
+ qcocoasystemsettings.mm \
HEADERS += qcocoaintegration.h \
qcocoatheme.h \
@@ -51,6 +55,10 @@ HEADERS += qcocoaintegration.h \
qcocoafiledialoghelper.h \
qcocoafontdialoghelper.h \
qcocoacursor.h \
+ qcocoadrag.h \
+ qmacclipboard.h \
+ qmacmime.h \
+ qcocoasystemsettings.h \
FORMS += $$PWD/../../../widgets/dialogs/qfiledialog.ui
RESOURCES += qcocoaresources.qrc
diff --git a/src/plugins/platforms/cocoa/qcocoacursor.h b/src/plugins/platforms/cocoa/qcocoacursor.h
index bccaa1e06b..85892ee820 100644
--- a/src/plugins/platforms/cocoa/qcocoacursor.h
+++ b/src/plugins/platforms/cocoa/qcocoacursor.h
@@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE
class QCocoaCursor : public QPlatformCursor
{
public:
- explicit QCocoaCursor(QPlatformScreen *);
+ QCocoaCursor();
virtual void changeCursor(QCursor * widgetCursor, QWindow * widget);
virtual QPoint pos() const;
diff --git a/src/plugins/platforms/cocoa/qcocoacursor.mm b/src/plugins/platforms/cocoa/qcocoacursor.mm
index bddfaa752e..56f0dcf72e 100644
--- a/src/plugins/platforms/cocoa/qcocoacursor.mm
+++ b/src/plugins/platforms/cocoa/qcocoacursor.mm
@@ -47,8 +47,7 @@
QT_BEGIN_NAMESPACE
-QCocoaCursor::QCocoaCursor(QPlatformScreen *s) :
- QPlatformCursor(s)
+QCocoaCursor::QCocoaCursor()
{
// release cursors
QHash<Qt::CursorShape, NSCursor *>::const_iterator i = m_cursors.constBegin();
diff --git a/src/plugins/platforms/cocoa/qcocoadrag.h b/src/plugins/platforms/cocoa/qcocoadrag.h
new file mode 100644
index 0000000000..17df54f748
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qcocoadrag.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 QCOCOADRAG_H
+#define QCOCOADRAG_H
+
+#include <Cocoa/Cocoa.h>
+#include <QtGui>
+#include <qplatformdrag_qpa.h>
+#include <QtPlatformSupport/private/qsimpledrag_p.h>
+
+#include <QtGui/private/qdnd_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QCocoaDrag : public QSimpleDrag
+{
+public:
+private:
+};
+
+class QCocoaDropData : public QInternalMimeData
+{
+public:
+ QCocoaDropData(NSPasteboard *pasteboard);
+ ~QCocoaDropData();
+protected:
+ bool hasFormat_sys(const QString &mimeType) const;
+ QStringList formats_sys() const;
+ QVariant retrieveData_sys(const QString &mimeType, QVariant::Type type) const;
+public:
+ CFStringRef dropPasteboard;
+};
+
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/cocoa/qcocoadrag.mm b/src/plugins/platforms/cocoa/qcocoadrag.mm
new file mode 100644
index 0000000000..c596e3fdbb
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qcocoadrag.mm
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 "qcocoadrag.h"
+#include "qmacmime.h"
+#include "qmacclipboard.h"
+
+QT_BEGIN_NAMESPACE
+
+QCocoaDropData::QCocoaDropData(NSPasteboard *pasteboard)
+{
+ dropPasteboard = reinterpret_cast<CFStringRef>(const_cast<const NSString *>([pasteboard name]));
+ CFRetain(dropPasteboard);
+}
+
+QCocoaDropData::~QCocoaDropData()
+{
+ CFRelease(dropPasteboard);
+}
+
+QStringList QCocoaDropData::formats_sys() const
+{
+ QStringList formats;
+ PasteboardRef board;
+ if (PasteboardCreate(dropPasteboard, &board) != noErr) {
+ qDebug("DnD: Cannot get PasteBoard!");
+ return formats;
+ }
+ formats = QMacPasteboard(board, QMacPasteboardMime::MIME_DND).formats();
+ return formats;
+}
+
+QVariant QCocoaDropData::retrieveData_sys(const QString &mimeType, QVariant::Type type) const
+{
+ QVariant data;
+ PasteboardRef board;
+ if (PasteboardCreate(dropPasteboard, &board) != noErr) {
+ qDebug("DnD: Cannot get PasteBoard!");
+ return data;
+ }
+ data = QMacPasteboard(board, QMacPasteboardMime::MIME_DND).retrieveData(mimeType, type);
+ CFRelease(board);
+ return data;
+}
+
+bool QCocoaDropData::hasFormat_sys(const QString &mimeType) const
+{
+ bool has = false;
+ PasteboardRef board;
+ if (PasteboardCreate(dropPasteboard, &board) != noErr) {
+ qDebug("DnD: Cannot get PasteBoard!");
+ return has;
+ }
+ has = QMacPasteboard(board, QMacPasteboardMime::MIME_DND).hasFormat(mimeType);
+ CFRelease(board);
+ return has;
+}
+
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h
index 7b1247b739..3e3e8fa507 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.h
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.h
@@ -77,6 +77,11 @@ NSSize qt_mac_toNSSize(const QSize &qtSize);
QChar qt_mac_qtKey2CocoaKey(Qt::Key key);
Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode);
+NSDragOperation qt_mac_mapDropAction(Qt::DropAction action);
+NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions);
+Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions);
+Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions);
+
// Misc
void qt_mac_transformProccessToForegroundApplication();
QString qt_mac_removeMnemonics(const QString &original);
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm
index 29c505e1ab..ec4399b66c 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.mm
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm
@@ -270,6 +270,64 @@ Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode)
return i->qtKey;
}
+struct dndenum_mapper
+{
+ NSDragOperation mac_code;
+ Qt::DropAction qt_code;
+ bool Qt2Mac;
+};
+
+static dndenum_mapper dnd_enums[] = {
+ { NSDragOperationLink, Qt::LinkAction, true },
+ { NSDragOperationMove, Qt::MoveAction, true },
+ { NSDragOperationCopy, Qt::CopyAction, true },
+ { NSDragOperationGeneric, Qt::CopyAction, false },
+ { NSDragOperationEvery, Qt::ActionMask, false },
+ { NSDragOperationNone, Qt::IgnoreAction, false }
+};
+
+NSDragOperation qt_mac_mapDropAction(Qt::DropAction action)
+{
+ for (int i=0; dnd_enums[i].qt_code; i++) {
+ if (dnd_enums[i].Qt2Mac && (action & dnd_enums[i].qt_code)) {
+ return dnd_enums[i].mac_code;
+ }
+ }
+ return NSDragOperationNone;
+}
+
+NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions)
+{
+ NSDragOperation nsActions = NSDragOperationNone;
+ for (int i=0; dnd_enums[i].qt_code; i++) {
+ if (dnd_enums[i].Qt2Mac && (actions & dnd_enums[i].qt_code))
+ nsActions |= dnd_enums[i].mac_code;
+ }
+ return nsActions;
+}
+
+Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions)
+{
+ Qt::DropAction action = Qt::IgnoreAction;
+ for (int i=0; dnd_enums[i].mac_code; i++) {
+ if (nsActions & dnd_enums[i].mac_code)
+ return dnd_enums[i].qt_code;
+ }
+ return action;
+}
+
+Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions)
+{
+ Qt::DropActions actions = Qt::IgnoreAction;
+ for (int i=0; dnd_enums[i].mac_code; i++) {
+ if (nsActions & dnd_enums[i].mac_code)
+ actions |= dnd_enums[i].qt_code;
+ }
+ return actions;
+}
+
+
+
//
// Misc
//
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h
index be061547a9..bf54915365 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.h
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.h
@@ -46,6 +46,7 @@
#include "qcocoaautoreleasepool.h"
#include "qcocoacursor.h"
+#include "qcocoadrag.h"
#include <QtCore/QScopedPointer>
#include <QtGui/QPlatformIntegration>
@@ -62,6 +63,7 @@ public:
int depth() const { return m_depth; }
QImage::Format format() const { return m_format; }
QSizeF physicalSize() const { return m_physicalSize; }
+ QPlatformCursor *cursor() const { return m_cursor; }
public:
NSScreen *m_screen;
@@ -88,6 +90,7 @@ public:
QPlatformNativeInterface *nativeInterface() const;
QPlatformAccessibility *accessibility() const;
+ QPlatformDrag *drag() const;
QPlatformTheme *platformTheme() const;
private:
@@ -97,6 +100,8 @@ private:
QScopedPointer<QPlatformAccessibility> mAccessibility;
QScopedPointer<QPlatformTheme> mPlatformTheme;
+ QList<QCocoaScreen *> mScreens;
+ QScopedPointer<QCocoaDrag> mCocoaDrag;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index fb8e487029..8411a795c1 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -52,6 +52,7 @@
#include "qmenu_mac.h"
#include "qcocoafiledialoghelper.h"
#include "qcocoatheme.h"
+#include "qmacmime.h"
#include <QtGui/qplatformaccessibility_qpa.h>
#include <QtCore/qcoreapplication.h>
@@ -78,7 +79,7 @@ QCocoaScreen::QCocoaScreen(int screenIndex)
const qreal inch = 25.4;
m_physicalSize = QSizeF(m_geometry.size()) * inch / dpi;
- m_cursor = new QCocoaCursor(this);
+ m_cursor = new QCocoaCursor;
};
QCocoaScreen::~QCocoaScreen()
@@ -91,7 +92,7 @@ QCocoaIntegration::QCocoaIntegration()
, mEventDispatcher(new QCocoaEventDispatcher())
, mAccessibility(new QPlatformAccessibility)
, mPlatformTheme(new QCocoaTheme)
-
+ , mCocoaDrag(new QCocoaDrag)
{
QCocoaAutoReleasePool pool;
@@ -134,14 +135,21 @@ QCocoaIntegration::QCocoaIntegration()
NSArray *screens = [NSScreen screens];
for (uint i = 0; i < [screens count]; i++) {
QCocoaScreen *screen = new QCocoaScreen(i);
+ mScreens.append(screen);
screenAdded(screen);
}
+ QMacPasteboardMime::initialize();
}
QCocoaIntegration::~QCocoaIntegration()
{
[[NSApplication sharedApplication] setDelegate: 0];
+
+ // Delete screens in reverse order to avoid crash in case of multiple screens
+ while (!mScreens.isEmpty()) {
+ delete mScreens.takeLast();
+ }
}
bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) const
@@ -192,6 +200,11 @@ QPlatformAccessibility *QCocoaIntegration::accessibility() const
return mAccessibility.data();
}
+QPlatformDrag *QCocoaIntegration::drag() const
+{
+ return mCocoaDrag.data();
+}
+
QPlatformTheme *QCocoaIntegration::platformTheme() const
{
return mPlatformTheme.data();
diff --git a/src/plugins/platforms/cocoa/qcocoamenuloader.mm b/src/plugins/platforms/cocoa/qcocoamenuloader.mm
index 3a1f92fcf9..70e974161e 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuloader.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenuloader.mm
@@ -93,7 +93,6 @@ void qt_mac_loadMenuNib(QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *qtMenuLoader)
// Load and instantiate nib file from temp
NSURL *nibUrl = [NSURL fileURLWithPath : QCFString::toNSString(nibDir)];
- [nibUrl autorelease];
NSNib *nib = [[NSNib alloc] initWithContentsOfURL : nibUrl];
[nib autorelease];
if(!nib) {
diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.h b/src/plugins/platforms/cocoa/qcocoasystemsettings.h
new file mode 100644
index 0000000000..10cac27dcd
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 QCOCOASYSTEMSETTINGS_H
+#define QCOCOASYSTEMSETTINGS_H
+
+#include <QtCore/qhash.h>
+#include <QtGui/qpalette.h>
+#include <QtGui/qplatformtheme_qpa.h>
+
+QT_BEGIN_NAMESPACE
+
+QPalette * qt_mac_createSystemPalette();
+QHash<QPlatformTheme::Palette, QPalette*> qt_mac_createRolePalettes();
+QHash<QPlatformTheme::Font, QFont *> qt_mac_createRoleFonts();
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
new file mode 100644
index 0000000000..c2f5df4d38
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
@@ -0,0 +1,272 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 "qcocoasystemsettings.h"
+
+#include <QtCore/private/qcore_mac_p.h>
+#include <QtGui/qfont.h>
+
+#include <Carbon/Carbon.h>
+
+QT_BEGIN_NAMESPACE
+
+QColor qt_mac_colorFromCGColor(CGColorRef cgcolor)
+{
+ QColor pc;
+ CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(cgcolor));
+ const CGFloat *components = CGColorGetComponents(cgcolor);
+ if (model == kCGColorSpaceModelRGB) {
+ pc.setRgbF(components[0], components[1], components[2], components[3]);
+ } else if (model == kCGColorSpaceModelCMYK) {
+ pc.setCmykF(components[0], components[1], components[2], components[3]);
+ } else if (model == kCGColorSpaceModelMonochrome) {
+ pc.setRgbF(components[0], components[0], components[0], components[1]);
+ } else {
+ // Colorspace we can't deal with.
+ qWarning("Qt: qcolorFromCGColor: cannot convert from colorspace model: %d", model);
+ Q_ASSERT(false);
+ }
+ return pc;
+}
+
+QColor qt_mac_colorForTheme(ThemeBrush brush)
+{
+ QCFType<CGColorRef> cgClr = 0;
+ HIThemeBrushCreateCGColor(brush, &cgClr);
+ return qt_mac_colorFromCGColor(cgClr);
+}
+
+QColor qt_mac_colorForThemeTextColor(ThemeTextColor themeColor)
+{
+ // No GetThemeTextColor in 64-bit mode, use hardcoded values:
+ switch (themeColor) {
+ case kThemeTextColorAlertActive:
+ case kThemeTextColorTabFrontActive:
+ case kThemeTextColorBevelButtonActive:
+ case kThemeTextColorListView:
+ case kThemeTextColorPlacardActive:
+ case kThemeTextColorPopupButtonActive:
+ case kThemeTextColorPopupLabelActive:
+ case kThemeTextColorPushButtonActive:
+ return Qt::black;
+ case kThemeTextColorAlertInactive:
+ case kThemeTextColorDialogInactive:
+ case kThemeTextColorPlacardInactive:
+ return QColor(69, 69, 69, 255);
+ case kThemeTextColorPopupButtonInactive:
+ case kThemeTextColorPopupLabelInactive:
+ case kThemeTextColorPushButtonInactive:
+ case kThemeTextColorTabFrontInactive:
+ case kThemeTextColorBevelButtonInactive:
+ return QColor(127, 127, 127, 255);
+ default:
+ return QColor(0, 0, 0, 255); // ### TODO: Sample color like Qt 4.
+ }
+}
+
+QPalette * qt_mac_createSystemPalette()
+{
+ QColor qc;
+
+ // Standard palette initialization (copied from Qt 4 styles)
+ QColor background = QColor(0xd4, 0xd0, 0xc8); // win 2000 grey
+ QColor light(background.lighter());
+ QColor dark(background.darker());
+ QColor mid(Qt::gray);
+ QPalette *palette = new QPalette(Qt::black, background, light, dark, mid, Qt::black, Qt::white);
+
+ palette->setBrush(QPalette::Disabled, QPalette::WindowText, dark);
+ palette->setBrush(QPalette::Disabled, QPalette::Text, dark);
+ palette->setBrush(QPalette::Disabled, QPalette::ButtonText, dark);
+ palette->setBrush(QPalette::Disabled, QPalette::Base, background);
+ palette->setColor(QPalette::Disabled, QPalette::Dark, QColor(191, 191, 191));
+ palette->setColor(QPalette::Active, QPalette::Dark, QColor(191, 191, 191));
+ palette->setColor(QPalette::Inactive, QPalette::Dark, QColor(191, 191, 191));
+
+ // System palette initialization:
+ palette->setBrush( QPalette::Active, QPalette::Highlight, qt_mac_colorForTheme(kThemeBrushPrimaryHighlightColor) );
+ palette->setBrush( QPalette::Inactive, QPalette::Highlight, qt_mac_colorForTheme(kThemeBrushSecondaryHighlightColor) );
+
+ palette->setBrush( QPalette::Disabled, QPalette::Highlight, qt_mac_colorForTheme(kThemeBrushSecondaryHighlightColor) );
+ palette->setBrush( QPalette::Active, QPalette::Shadow, qt_mac_colorForTheme(kThemeBrushButtonActiveDarkShadow) );
+
+ palette->setBrush( QPalette::Inactive, QPalette::Shadow, qt_mac_colorForTheme(kThemeBrushButtonInactiveDarkShadow) );
+ palette->setBrush( QPalette::Disabled, QPalette::Shadow, qt_mac_colorForTheme(kThemeBrushButtonInactiveDarkShadow) );
+
+ qc = qt_mac_colorForThemeTextColor(kThemeTextColorDialogActive);
+ palette->setColor(QPalette::Active, QPalette::Text, qc);
+ palette->setColor(QPalette::Active, QPalette::WindowText, qc);
+ palette->setColor(QPalette::Active, QPalette::HighlightedText, qc);
+
+ qc = qt_mac_colorForThemeTextColor(kThemeTextColorDialogInactive);
+ palette->setColor(QPalette::Inactive, QPalette::Text, qc);
+ palette->setColor(QPalette::Inactive, QPalette::WindowText, qc);
+ palette->setColor(QPalette::Inactive, QPalette::HighlightedText, qc);
+ palette->setColor(QPalette::Disabled, QPalette::Text, qc);
+ palette->setColor(QPalette::Disabled, QPalette::WindowText, qc);
+ palette->setColor(QPalette::Disabled, QPalette::HighlightedText, qc);
+ palette->setBrush(QPalette::ToolTipBase, QColor(255, 255, 199));
+ return palette;
+}
+
+struct QMacPaletteMap {
+ inline QMacPaletteMap(QPlatformTheme::Palette p, ThemeBrush a, ThemeBrush i) :
+ paletteRole(p), active(a), inactive(i) { }
+
+ QPlatformTheme::Palette paletteRole;
+ ThemeBrush active, inactive;
+};
+
+static QMacPaletteMap mac_widget_colors[] = {
+// TODO (msorvig): Fix/match palette behavior with Qt 4 and enable.
+//
+// QMacPaletteMap(QPlatformTheme::ToolButtonPalette, kThemeTextColorBevelButtonActive, kThemeTextColorBevelButtonInactive),
+// QMacPaletteMap(QPlatformTheme::ButtonPalette, kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive),
+// QMacPaletteMap(QPlatformTheme::HeaderPalette, kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive),
+// QMacPaletteMap(QPlatformTheme::ComboBoxPalette, kThemeTextColorPopupButtonActive, kThemeTextColorPopupButtonInactive),
+// QMacPaletteMap(QPlatformTheme::ItemViewPalette, kThemeTextColorListView, kThemeTextColorDialogInactive),
+// QMacPaletteMap(QPlatformTheme::MessageBoxLabelPelette, kThemeTextColorAlertActive, kThemeTextColorAlertInactive),
+// QMacPaletteMap(QPlatformTheme::TabBarPalette, kThemeTextColorTabFrontActive, kThemeTextColorTabFrontInactive),
+// QMacPaletteMap(QPlatformTheme::LabelPalette, kThemeTextColorPlacardActive, kThemeTextColorPlacardInactive),
+// QMacPaletteMap(QPlatformTheme::GroupBoxPalette, kThemeTextColorPlacardActive, kThemeTextColorPlacardInactive),
+// QMacPaletteMap(QPlatformTheme::MenuPalette, kThemeTextColorPopupLabelActive, kThemeTextColorPopupLabelInactive),
+// ### TODO: The zeros below gives white-on-black text.
+// QMacPaletteMap(QPlatformTheme::TextEditPalette, 0, 0),
+// QMacPaletteMap(QPlatformTheme::TextLineEditPalette, 0, 0),
+ QMacPaletteMap(QPlatformTheme::NPalettes, 0, 0) };
+
+QHash<QPlatformTheme::Palette, QPalette*> qt_mac_createRolePalettes()
+{
+ QHash<QPlatformTheme::Palette, QPalette*> palettes;
+ QColor qc;
+ for (int i = 0; mac_widget_colors[i].paletteRole != QPlatformTheme::NPalettes; i++) {
+ QPalette pal;
+ if (mac_widget_colors[i].active != 0) {
+ qc = qt_mac_colorForThemeTextColor(mac_widget_colors[i].active);
+ pal.setColor(QPalette::Active, QPalette::Text, qc);
+ pal.setColor(QPalette::Active, QPalette::WindowText, qc);
+ pal.setColor(QPalette::Active, QPalette::HighlightedText, qc);
+ qc = qt_mac_colorForThemeTextColor(mac_widget_colors[i].inactive);
+ pal.setColor(QPalette::Inactive, QPalette::Text, qc);
+ pal.setColor(QPalette::Disabled, QPalette::Text, qc);
+ pal.setColor(QPalette::Inactive, QPalette::WindowText, qc);
+ pal.setColor(QPalette::Disabled, QPalette::WindowText, qc);
+ pal.setColor(QPalette::Inactive, QPalette::HighlightedText, qc);
+ pal.setColor(QPalette::Disabled, QPalette::HighlightedText, qc);
+ }
+ if (mac_widget_colors[i].paletteRole == QPlatformTheme::MenuPalette) {
+ qc = qt_mac_colorForThemeTextColor(kThemeTextColorMenuItemActive);
+ pal.setBrush(QPalette::ButtonText, qc);
+ qc = qt_mac_colorForThemeTextColor(kThemeTextColorMenuItemSelected);
+ pal.setBrush(QPalette::HighlightedText, qc);
+ qc = qt_mac_colorForThemeTextColor(kThemeTextColorMenuItemDisabled);
+ pal.setBrush(QPalette::Disabled, QPalette::Text, qc);
+ } else if ((mac_widget_colors[i].paletteRole == QPlatformTheme::ButtonPalette)
+ || (mac_widget_colors[i].paletteRole == QPlatformTheme::HeaderPalette)) {
+ pal.setColor(QPalette::Disabled, QPalette::ButtonText,
+ pal.color(QPalette::Disabled, QPalette::Text));
+ pal.setColor(QPalette::Inactive, QPalette::ButtonText,
+ pal.color(QPalette::Inactive, QPalette::Text));
+ pal.setColor(QPalette::Active, QPalette::ButtonText,
+ pal.color(QPalette::Active, QPalette::Text));
+ } else if (mac_widget_colors[i].paletteRole == QPlatformTheme::ItemViewPalette) {
+ pal.setBrush(QPalette::Active, QPalette::Highlight,
+ qt_mac_colorForTheme(kThemeBrushAlternatePrimaryHighlightColor));
+ qc = qt_mac_colorForThemeTextColor(kThemeTextColorMenuItemSelected);
+ pal.setBrush(QPalette::Active, QPalette::HighlightedText, qc);
+ pal.setBrush(QPalette::Inactive, QPalette::Text,
+ pal.brush(QPalette::Active, QPalette::Text));
+ pal.setBrush(QPalette::Inactive, QPalette::HighlightedText,
+ pal.brush(QPalette::Active, QPalette::Text));
+ } else if (mac_widget_colors[i].paletteRole == QPlatformTheme::TextEditPalette) {
+ pal.setBrush(QPalette::Inactive, QPalette::Text,
+ pal.brush(QPalette::Active, QPalette::Text));
+ pal.setBrush(QPalette::Inactive, QPalette::HighlightedText,
+ pal.brush(QPalette::Active, QPalette::Text));
+ } else if (mac_widget_colors[i].paletteRole == QPlatformTheme::TextLineEditPalette) {
+ pal.setBrush(QPalette::Disabled, QPalette::Base,
+ pal.brush(QPalette::Active, QPalette::Base));
+ }
+ palettes.insert(mac_widget_colors[i].paletteRole, new QPalette(pal));
+ }
+ return palettes;
+}
+
+QFont *qt_mac_qfontForThemeFont(ThemeFontID themeID)
+{
+ CTFontUIFontType ctID = HIThemeGetUIFontType(themeID);
+ QCFType<CTFontRef> ctfont = CTFontCreateUIFontForLanguage(ctID, 0, 0);
+ QString familyName = QCFString(CTFontCopyFamilyName(ctfont));
+ QCFType<CFDictionaryRef> dict = CTFontCopyTraits(ctfont);
+ CFNumberRef num = static_cast<CFNumberRef>(CFDictionaryGetValue(dict, kCTFontWeightTrait));
+ float fW;
+ CFNumberGetValue(num, kCFNumberFloat32Type, &fW);
+ QFont::Weight wght = fW > 0. ? QFont::Bold : QFont::Normal;
+ num = static_cast<CFNumberRef>(CFDictionaryGetValue(dict, kCTFontSlantTrait));
+ CFNumberGetValue(num, kCFNumberFloatType, &fW);
+ bool italic = (fW != 0.0);
+ return new QFont(familyName, CTFontGetSize(ctfont), wght, italic);
+}
+
+QHash<QPlatformTheme::Font, QFont *> qt_mac_createRoleFonts()
+{
+ QHash<QPlatformTheme::Font, QFont *> fonts;
+
+ fonts.insert(QPlatformTheme::SystemFont, qt_mac_qfontForThemeFont(kThemeApplicationFont));
+ fonts.insert(QPlatformTheme::PushButtonFont, qt_mac_qfontForThemeFont(kThemePushButtonFont));
+ fonts.insert(QPlatformTheme::ListViewFont, qt_mac_qfontForThemeFont(kThemeViewsFont));
+ fonts.insert(QPlatformTheme::ListBoxFont, qt_mac_qfontForThemeFont(kThemeViewsFont));
+ fonts.insert(QPlatformTheme::TitleBarFont, qt_mac_qfontForThemeFont(kThemeWindowTitleFont));
+ fonts.insert(QPlatformTheme::MenuFont, qt_mac_qfontForThemeFont(kThemeMenuItemFont));
+ fonts.insert(QPlatformTheme::ComboMenuItemFont, qt_mac_qfontForThemeFont(kThemeSystemFont));
+ fonts.insert(QPlatformTheme::HeaderViewFont, qt_mac_qfontForThemeFont(kThemeSmallSystemFont));
+ fonts.insert(QPlatformTheme::TipLabelFont, qt_mac_qfontForThemeFont(kThemeSmallSystemFont));
+ fonts.insert(QPlatformTheme::LabelFont, qt_mac_qfontForThemeFont(kThemeSystemFont));
+ fonts.insert(QPlatformTheme::ToolButtonFont, qt_mac_qfontForThemeFont(kThemeSmallSystemFont));
+ fonts.insert(QPlatformTheme::MenuItemFont, qt_mac_qfontForThemeFont(kThemeMenuItemFont));
+ fonts.insert(QPlatformTheme::ComboLineEditFont, qt_mac_qfontForThemeFont(kThemeViewsFont));
+ fonts.insert(QPlatformTheme::SmallFont, qt_mac_qfontForThemeFont(kThemeSmallSystemFont));
+ fonts.insert(QPlatformTheme::MiniFont, qt_mac_qfontForThemeFont(kThemeMiniSystemFont));
+
+ return fonts;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.h b/src/plugins/platforms/cocoa/qcocoatheme.h
index a7dc973937..030db1822c 100644
--- a/src/plugins/platforms/cocoa/qcocoatheme.h
+++ b/src/plugins/platforms/cocoa/qcocoatheme.h
@@ -42,12 +42,12 @@
#ifndef QPLATFORMTHEME_COCOA_H
#define QPLATFORMTHEME_COCOA_H
-#include <Cocoa/Cocoa.h>
-
+#include <QtCore/QHash>
#include <QtGui/QPlatformTheme>
QT_BEGIN_NAMESPACE
+class QPalette;
class QCocoaTheme : public QPlatformTheme
{
public:
@@ -60,7 +60,14 @@ public:
bool usePlatformNativeDialog(DialogType dialogType) const;
QPlatformDialogHelper *createPlatformDialogHelper(DialogType dialogType) const;
+ const QPalette *palette(Palette type = SystemPalette) const;
+ const QFont *font(Font type = SystemFont) const;
+
QVariant themeHint(ThemeHint hint) const;
+private:
+ mutable QPalette *m_systemPalette;
+ mutable QHash<QPlatformTheme::Palette, QPalette*> m_palettes;
+ mutable QHash<QPlatformTheme::Font, QFont*> m_fonts;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm
index 0fef3234b4..8ec6e3801e 100644
--- a/src/plugins/platforms/cocoa/qcocoatheme.mm
+++ b/src/plugins/platforms/cocoa/qcocoatheme.mm
@@ -45,17 +45,19 @@
#include "qcocoacolordialoghelper.h"
#include "qcocoafiledialoghelper.h"
#include "qcocoafontdialoghelper.h"
+#include "qcocoasystemsettings.h"
QT_BEGIN_NAMESPACE
QCocoaTheme::QCocoaTheme()
+ :m_systemPalette(0)
{
}
QCocoaTheme::~QCocoaTheme()
{
-
+ delete m_systemPalette;
}
QPlatformMenu *QCocoaTheme::createPlatformMenu(QMenu *menu) const
@@ -102,6 +104,28 @@ QPlatformDialogHelper * QCocoaTheme::createPlatformDialogHelper(DialogType dialo
}
}
+const QPalette *QCocoaTheme::palette(Palette type) const
+{
+ if (type == SystemPalette) {
+ if (!m_systemPalette)
+ m_systemPalette = qt_mac_createSystemPalette();
+ return m_systemPalette;
+ } else {
+ if (m_palettes.isEmpty())
+ m_palettes = qt_mac_createRolePalettes();
+ return m_palettes.value(type, 0);
+ }
+ return 0;
+}
+
+const QFont *QCocoaTheme::font(Font type) const
+{
+ if (m_fonts.isEmpty()) {
+ m_fonts = qt_mac_createRoleFonts();
+ }
+ return m_fonts.value(type, 0);
+}
+
QVariant QCocoaTheme::themeHint(ThemeHint hint) const
{
switch (hint) {
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index b2e93470c9..3f566ccb44 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -201,7 +201,7 @@ void QCocoaWindow::propagateSizeHints()
[m_nsWindow setResizeIncrements : qt_mac_toNSSize(window()->sizeIncrement())];
QSize baseSize = window()->baseSize();
- if (!baseSize.isNull()) {
+ if (!baseSize.isNull() && baseSize.isValid()) {
[m_nsWindow setFrameSize : NSMakeSize(baseSize.width(), baseSize.height()) display : YES];
}
}
diff --git a/src/plugins/platforms/cocoa/qmacclipboard.h b/src/plugins/platforms/cocoa/qmacclipboard.h
new file mode 100644
index 0000000000..9371aca459
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qmacclipboard.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 QMACCLIPBOARD_H
+#define QMACCLIPBOARD_H
+
+#include <QtGui>
+#include "qmacmime.h"
+
+#undef slots
+
+#import <Cocoa/Cocoa.h>
+
+class QMacPasteboard
+{
+ struct Promise {
+ Promise() : itemId(0), convertor(0) { }
+ Promise(int itemId, QMacPasteboardMime *c, QString m, QVariant d, int o=0) : itemId(itemId), offset(o), convertor(c), mime(m), data(d) { }
+ int itemId, offset;
+ QMacPasteboardMime *convertor;
+ QString mime;
+ QVariant data;
+ };
+ QList<Promise> promises;
+
+ PasteboardRef paste;
+ uchar mime_type;
+ mutable QPointer<QMimeData> mime;
+ mutable bool mac_mime_source;
+ static OSStatus promiseKeeper(PasteboardRef, PasteboardItemID, CFStringRef, void *);
+ void clear_helper();
+public:
+ QMacPasteboard(PasteboardRef p, uchar mime_type=0);
+ QMacPasteboard(uchar mime_type);
+ QMacPasteboard(CFStringRef name=0, uchar mime_type=0);
+ ~QMacPasteboard();
+
+ bool hasFlavor(QString flavor) const;
+ bool hasOSType(int c_flavor) const;
+
+ PasteboardRef pasteBoard() const;
+ QMimeData *mimeData() const;
+ void setMimeData(QMimeData *mime);
+
+ QStringList formats() const;
+ bool hasFormat(const QString &format) const;
+ QVariant retrieveData(const QString &format, QVariant::Type) const;
+
+ void clear();
+ bool sync() const;
+};
+
+QString qt_mac_get_pasteboardString(PasteboardRef paste);
+
+#endif
diff --git a/src/plugins/platforms/cocoa/qmacclipboard.mm b/src/plugins/platforms/cocoa/qmacclipboard.mm
new file mode 100644
index 0000000000..d5af6de69c
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qmacclipboard.mm
@@ -0,0 +1,653 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 "qmacclipboard.h"
+#include "qclipboard.h"
+#include "qapplication.h"
+#include "qbitmap.h"
+#include "qdatetime.h"
+#include "qdebug.h"
+#include "qguiapplication.h"
+#include "qevent.h"
+#include "qurl.h"
+#include <stdlib.h>
+#include <string.h>
+#include "qcocoahelpers.h"
+#include "qmacmime.h"
+#include "qcocoaautoreleasepool.h"
+
+QT_BEGIN_NAMESPACE
+
+QT_USE_NAMESPACE
+
+/*****************************************************************************
+ QClipboard debug facilities
+ *****************************************************************************/
+//#define DEBUG_PASTEBOARD
+
+#ifndef QT_NO_CLIPBOARD
+
+/*****************************************************************************
+ QClipboard member functions for mac.
+ *****************************************************************************/
+
+static QMacPasteboard *qt_mac_pasteboards[2] = {0, 0};
+
+static inline QMacPasteboard *qt_mac_pasteboard(QClipboard::Mode mode)
+{
+ Q_ASSERT(mode == QClipboard::Clipboard || mode == QClipboard::FindBuffer);
+ if (mode == QClipboard::Clipboard)
+ return qt_mac_pasteboards[0];
+ else
+ return qt_mac_pasteboards[1];
+}
+
+static void qt_mac_cleanupPasteboard() {
+ delete qt_mac_pasteboards[0];
+ delete qt_mac_pasteboards[1];
+ qt_mac_pasteboards[0] = 0;
+ qt_mac_pasteboards[1] = 0;
+}
+
+static bool qt_mac_updateScrap(QClipboard::Mode mode)
+{
+ if (!qt_mac_pasteboards[0]) {
+ qt_mac_pasteboards[0] = new QMacPasteboard(kPasteboardClipboard, QMacPasteboardMime::MIME_CLIP);
+ qt_mac_pasteboards[1] = new QMacPasteboard(kPasteboardFind, QMacPasteboardMime::MIME_CLIP);
+ qAddPostRoutine(qt_mac_cleanupPasteboard);
+ return true;
+ }
+ return qt_mac_pasteboard(mode)->sync();
+}
+
+void QClipboard::clear(Mode mode)
+{
+ if (!supportsMode(mode))
+ return;
+ qt_mac_updateScrap(mode);
+ qt_mac_pasteboard(mode)->clear();
+ setMimeData(0, mode);
+}
+
+void QClipboard::ownerDestroyed()
+{
+}
+
+
+void QClipboard::connectNotify(const char *signal)
+{
+ Q_UNUSED(signal);
+}
+
+bool QClipboard::event(QEvent *e)
+{
+ if (e->type() != QEvent::Clipboard)
+ return QObject::event(e);
+
+ if (qt_mac_updateScrap(QClipboard::Clipboard)) {
+ emitChanged(QClipboard::Clipboard);
+ }
+
+ if (qt_mac_updateScrap(QClipboard::FindBuffer)) {
+ emitChanged(QClipboard::FindBuffer);
+ }
+
+ return QObject::event(e);
+}
+
+const QMimeData *QClipboard::mimeData(Mode mode) const
+{
+ if (!supportsMode(mode))
+ return 0;
+ qt_mac_updateScrap(mode);
+ return qt_mac_pasteboard(mode)->mimeData();
+}
+
+void QClipboard::setMimeData(QMimeData *src, Mode mode)
+{
+ if (!supportsMode(mode))
+ return;
+ qt_mac_updateScrap(mode);
+ qt_mac_pasteboard(mode)->setMimeData(src);
+ emitChanged(mode);
+}
+
+bool QClipboard::supportsMode(Mode mode) const
+{
+ return (mode == Clipboard || mode == FindBuffer);
+}
+
+bool QClipboard::ownsMode(Mode mode) const
+{
+ Q_UNUSED(mode);
+ return false;
+}
+
+#endif // QT_NO_CLIPBOARD
+
+/*****************************************************************************
+ QMacPasteboard code
+*****************************************************************************/
+
+QMacPasteboard::QMacPasteboard(PasteboardRef p, uchar mt)
+{
+ mac_mime_source = false;
+ mime_type = mt ? mt : uchar(QMacPasteboardMime::MIME_ALL);
+ paste = p;
+ CFRetain(paste);
+}
+
+QMacPasteboard::QMacPasteboard(uchar mt)
+{
+ mac_mime_source = false;
+ mime_type = mt ? mt : uchar(QMacPasteboardMime::MIME_ALL);
+ paste = 0;
+ OSStatus err = PasteboardCreate(0, &paste);
+ if (err == noErr) {
+ PasteboardSetPromiseKeeper(paste, promiseKeeper, this);
+ } else {
+ qDebug("PasteBoard: Error creating pasteboard: [%d]", (int)err);
+ }
+}
+
+QMacPasteboard::QMacPasteboard(CFStringRef name, uchar mt)
+{
+ mac_mime_source = false;
+ mime_type = mt ? mt : uchar(QMacPasteboardMime::MIME_ALL);
+ paste = 0;
+ OSStatus err = PasteboardCreate(name, &paste);
+ if (err == noErr) {
+ PasteboardSetPromiseKeeper(paste, promiseKeeper, this);
+ } else {
+ qDebug("PasteBoard: Error creating pasteboard: %s [%d]", QCFString::toQString(name).toLatin1().constData(), (int)err);
+ }
+}
+
+QMacPasteboard::~QMacPasteboard()
+{
+ // commit all promises for paste after exit close
+ for (int i = 0; i < promises.count(); ++i) {
+ const Promise &promise = promises.at(i);
+ QCFString flavor = QCFString(promise.convertor->flavorFor(promise.mime));
+ promiseKeeper(paste, (PasteboardItemID)promise.itemId, flavor, this);
+ }
+
+ if (paste)
+ CFRelease(paste);
+}
+
+PasteboardRef
+QMacPasteboard::pasteBoard() const
+{
+ return paste;
+}
+
+OSStatus QMacPasteboard::promiseKeeper(PasteboardRef paste, PasteboardItemID id, CFStringRef flavor, void *_qpaste)
+{
+ QMacPasteboard *qpaste = (QMacPasteboard*)_qpaste;
+ const long promise_id = (long)id;
+
+ // Find the kept promise
+ const QString flavorAsQString = QCFString::toQString(flavor);
+ QMacPasteboard::Promise promise;
+ for (int i = 0; i < qpaste->promises.size(); i++){
+ QMacPasteboard::Promise tmp = qpaste->promises[i];
+ if (tmp.itemId == promise_id && tmp.convertor->canConvert(tmp.mime, flavorAsQString)){
+ promise = tmp;
+ break;
+ }
+ }
+
+ if (!promise.itemId && flavorAsQString == QLatin1String("com.trolltech.qt.MimeTypeName")) {
+ // we have promised this data, but wont be able to convert, so return null data.
+ // This helps in making the application/x-qt-mime-type-name hidden from normal use.
+ QByteArray ba;
+ QCFType<CFDataRef> data = CFDataCreate(0, (UInt8*)ba.constData(), ba.size());
+ PasteboardPutItemFlavor(paste, id, flavor, data, kPasteboardFlavorNoFlags);
+ return noErr;
+ }
+
+ if (!promise.itemId) {
+ // There was no promise that could deliver data for the
+ // given id and flavor. This should not happend.
+ qDebug("Pasteboard: %d: Request for %ld, %s, but no promise found!", __LINE__, promise_id, qPrintable(flavorAsQString));
+ return cantGetFlavorErr;
+ }
+
+#ifdef DEBUG_PASTEBOARD
+ qDebug("PasteBoard: Calling in promise for %s[%ld] [%s] (%s) [%d]", qPrintable(promise.mime), promise_id,
+ qPrintable(flavorAsQString), qPrintable(promise.convertor->convertorName()), promise.offset);
+#endif
+
+ QList<QByteArray> md = promise.convertor->convertFromMime(promise.mime, promise.data, flavorAsQString);
+ if (md.size() <= promise.offset)
+ return cantGetFlavorErr;
+ const QByteArray &ba = md[promise.offset];
+ QCFType<CFDataRef> data = CFDataCreate(0, (UInt8*)ba.constData(), ba.size());
+ PasteboardPutItemFlavor(paste, id, flavor, data, kPasteboardFlavorNoFlags);
+ return noErr;
+}
+
+bool
+QMacPasteboard::hasOSType(int c_flavor) const
+{
+ if (!paste)
+ return false;
+
+ sync();
+
+ ItemCount cnt = 0;
+ if (PasteboardGetItemCount(paste, &cnt) || !cnt)
+ return false;
+
+#ifdef DEBUG_PASTEBOARD
+ qDebug("PasteBoard: hasOSType [%c%c%c%c]", (c_flavor>>24)&0xFF, (c_flavor>>16)&0xFF,
+ (c_flavor>>8)&0xFF, (c_flavor>>0)&0xFF);
+#endif
+ for (uint index = 1; index <= cnt; ++index) {
+
+ PasteboardItemID id;
+ if (PasteboardGetItemIdentifier(paste, index, &id) != noErr)
+ return false;
+
+ QCFType<CFArrayRef> types;
+ if (PasteboardCopyItemFlavors(paste, id, &types ) != noErr)
+ return false;
+
+ const int type_count = CFArrayGetCount(types);
+ for (int i = 0; i < type_count; ++i) {
+ CFStringRef flavor = (CFStringRef)CFArrayGetValueAtIndex(types, i);
+ const int os_flavor = UTGetOSTypeFromString(UTTypeCopyPreferredTagWithClass(flavor, kUTTagClassOSType));
+ if (os_flavor == c_flavor) {
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" - Found!");
+#endif
+ return true;
+ }
+ }
+ }
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" - NotFound!");
+#endif
+ return false;
+}
+
+bool
+QMacPasteboard::hasFlavor(QString c_flavor) const
+{
+ if (!paste)
+ return false;
+
+ sync();
+
+ ItemCount cnt = 0;
+ if (PasteboardGetItemCount(paste, &cnt) || !cnt)
+ return false;
+
+#ifdef DEBUG_PASTEBOARD
+ qDebug("PasteBoard: hasFlavor [%s]", qPrintable(c_flavor));
+#endif
+ for (uint index = 1; index <= cnt; ++index) {
+
+ PasteboardItemID id;
+ if (PasteboardGetItemIdentifier(paste, index, &id) != noErr)
+ return false;
+
+ PasteboardFlavorFlags flags;
+ if (PasteboardGetItemFlavorFlags(paste, id, QCFString(c_flavor), &flags) == noErr) {
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" - Found!");
+#endif
+ return true;
+ }
+ }
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" - NotFound!");
+#endif
+ return false;
+}
+
+class QMacPasteboardMimeSource : public QMimeData {
+ const QMacPasteboard *paste;
+public:
+ QMacPasteboardMimeSource(const QMacPasteboard *p) : QMimeData(), paste(p) { }
+ ~QMacPasteboardMimeSource() { }
+ virtual QStringList formats() const { return paste->formats(); }
+ virtual QVariant retrieveData(const QString &format, QVariant::Type type) const { return paste->retrieveData(format, type); }
+};
+
+QMimeData
+*QMacPasteboard::mimeData() const
+{
+ if (!mime) {
+ mac_mime_source = true;
+ mime = new QMacPasteboardMimeSource(this);
+
+ }
+ return mime;
+}
+
+class QMacMimeData : public QMimeData
+{
+public:
+ QVariant variantData(const QString &mime) { return retrieveData(mime, QVariant::Invalid); }
+private:
+ QMacMimeData();
+};
+
+void
+QMacPasteboard::setMimeData(QMimeData *mime_src)
+{
+ if (!paste)
+ return;
+
+ if (mime == mime_src || (!mime_src && mime && mac_mime_source))
+ return;
+ mac_mime_source = false;
+ delete mime;
+ mime = mime_src;
+
+ QList<QMacPasteboardMime*> availableConverters = QMacPasteboardMime::all(mime_type);
+ if (mime != 0) {
+ clear_helper();
+ QStringList formats = mime_src->formats();
+
+ // QMimeData sub classes reimplementing the formats() might not expose the
+ // temporary "application/x-qt-mime-type-name" mimetype. So check the existence
+ // of this mime type while doing drag and drop.
+ QString dummyMimeType(QLatin1String("application/x-qt-mime-type-name"));
+ if (!formats.contains(dummyMimeType)) {
+ QByteArray dummyType = mime_src->data(dummyMimeType);
+ if (!dummyType.isEmpty()) {
+ formats.append(dummyMimeType);
+ }
+ }
+ for (int f = 0; f < formats.size(); ++f) {
+ QString mimeType = formats.at(f);
+ for (QList<QMacPasteboardMime *>::Iterator it = availableConverters.begin(); it != availableConverters.end(); ++it) {
+ QMacPasteboardMime *c = (*it);
+ QString flavor(c->flavorFor(mimeType));
+ if (!flavor.isEmpty()) {
+ QVariant mimeData = static_cast<QMacMimeData*>(mime_src)->variantData(mimeType);
+#if 0
+ //### Grrr, why didn't I put in a virtual int QMacPasteboardMime::count()? --Sam
+ const int numItems = c->convertFromMime(mimeType, mimeData, flavor).size();
+#else
+ int numItems = 1; //this is a hack but it is much faster than allowing conversion above
+ if (c->convertorName() == QLatin1String("FileURL"))
+ numItems = mime_src->urls().count();
+#endif
+ for (int item = 0; item < numItems; ++item) {
+ const int itemID = item+1; //id starts at 1
+ promises.append(QMacPasteboard::Promise(itemID, c, mimeType, mimeData, item));
+ PasteboardPutItemFlavor(paste, (PasteboardItemID)itemID, QCFString(flavor), 0, kPasteboardFlavorNoFlags);
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" - adding %d %s [%s] <%s> [%d]",
+ itemID, qPrintable(mimeType), qPrintable(flavor), qPrintable(c->convertorName()), item);
+#endif
+ }
+ }
+ }
+ }
+ }
+}
+
+QStringList
+QMacPasteboard::formats() const
+{
+ if (!paste)
+ return QStringList();
+
+ sync();
+
+ QStringList ret;
+ ItemCount cnt = 0;
+ if (PasteboardGetItemCount(paste, &cnt) || !cnt)
+ return ret;
+
+#ifdef DEBUG_PASTEBOARD
+ qDebug("PasteBoard: Formats [%d]", (int)cnt);
+#endif
+ for (uint index = 1; index <= cnt; ++index) {
+
+ PasteboardItemID id;
+ if (PasteboardGetItemIdentifier(paste, index, &id) != noErr)
+ continue;
+
+ QCFType<CFArrayRef> types;
+ if (PasteboardCopyItemFlavors(paste, id, &types ) != noErr)
+ continue;
+
+ const int type_count = CFArrayGetCount(types);
+ for (int i = 0; i < type_count; ++i) {
+ const QString flavor = QCFString::toQString((CFStringRef)CFArrayGetValueAtIndex(types, i));
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" -%s", qPrintable(QString(flavor)));
+#endif
+ QString mimeType = QMacPasteboardMime::flavorToMime(mime_type, flavor);
+ if (!mimeType.isEmpty() && !ret.contains(mimeType)) {
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" -<%d> %s [%s]", ret.size(), qPrintable(mimeType), qPrintable(QString(flavor)));
+#endif
+ ret << mimeType;
+ }
+ }
+ }
+ return ret;
+}
+
+bool
+QMacPasteboard::hasFormat(const QString &format) const
+{
+ if (!paste)
+ return false;
+
+ sync();
+
+ ItemCount cnt = 0;
+ if (PasteboardGetItemCount(paste, &cnt) || !cnt)
+ return false;
+
+#ifdef DEBUG_PASTEBOARD
+ qDebug("PasteBoard: hasFormat [%s]", qPrintable(format));
+#endif
+ for (uint index = 1; index <= cnt; ++index) {
+
+ PasteboardItemID id;
+ if (PasteboardGetItemIdentifier(paste, index, &id) != noErr)
+ continue;
+
+ QCFType<CFArrayRef> types;
+ if (PasteboardCopyItemFlavors(paste, id, &types ) != noErr)
+ continue;
+
+ const int type_count = CFArrayGetCount(types);
+ for (int i = 0; i < type_count; ++i) {
+ const QString flavor = QCFString::toQString((CFStringRef)CFArrayGetValueAtIndex(types, i));
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" -%s [0x%x]", qPrintable(QString(flavor)), mime_type);
+#endif
+ QString mimeType = QMacPasteboardMime::flavorToMime(mime_type, flavor);
+#ifdef DEBUG_PASTEBOARD
+ if (!mimeType.isEmpty())
+ qDebug(" - %s", qPrintable(mimeType));
+#endif
+ if (mimeType == format)
+ return true;
+ }
+ }
+ return false;
+}
+
+QVariant
+QMacPasteboard::retrieveData(const QString &format, QVariant::Type) const
+{
+ if (!paste)
+ return QVariant();
+
+ sync();
+
+ ItemCount cnt = 0;
+ if (PasteboardGetItemCount(paste, &cnt) || !cnt)
+ return QByteArray();
+
+#ifdef DEBUG_PASTEBOARD
+ qDebug("Pasteboard: retrieveData [%s]", qPrintable(format));
+#endif
+ const QList<QMacPasteboardMime *> mimes = QMacPasteboardMime::all(mime_type);
+ for (int mime = 0; mime < mimes.size(); ++mime) {
+ QMacPasteboardMime *c = mimes.at(mime);
+ QString c_flavor = c->flavorFor(format);
+ if (!c_flavor.isEmpty()) {
+ // Handle text/plain a little differently. Try handling Unicode first.
+ bool checkForUtf16 = (c_flavor == QLatin1String("com.apple.traditional-mac-plain-text")
+ || c_flavor == QLatin1String("public.utf8-plain-text"));
+ if (checkForUtf16 || c_flavor == QLatin1String("public.utf16-plain-text")) {
+ // Try to get the NSStringPboardType from NSPasteboard, newlines are mapped
+ // correctly (as '\n') in this data. The 'public.utf16-plain-text' type
+ // usually maps newlines to '\r' instead.
+ QString str = qt_mac_get_pasteboardString(paste);
+ if (!str.isEmpty())
+ return str;
+ }
+ if (checkForUtf16 && hasFlavor(QLatin1String("public.utf16-plain-text")))
+ c_flavor = QLatin1String("public.utf16-plain-text");
+
+ QVariant ret;
+ QList<QByteArray> retList;
+ for (uint index = 1; index <= cnt; ++index) {
+ PasteboardItemID id;
+ if (PasteboardGetItemIdentifier(paste, index, &id) != noErr)
+ continue;
+
+ QCFType<CFArrayRef> types;
+ if (PasteboardCopyItemFlavors(paste, id, &types ) != noErr)
+ continue;
+
+ const int type_count = CFArrayGetCount(types);
+ for (int i = 0; i < type_count; ++i) {
+ CFStringRef flavor = static_cast<CFStringRef>(CFArrayGetValueAtIndex(types, i));
+ if (c_flavor == QCFString::toQString(flavor)) {
+ QCFType<CFDataRef> macBuffer;
+ if (PasteboardCopyItemFlavorData(paste, id, flavor, &macBuffer) == noErr) {
+ QByteArray buffer((const char *)CFDataGetBytePtr(macBuffer), CFDataGetLength(macBuffer));
+ if (!buffer.isEmpty()) {
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" - %s [%s] (%s)", qPrintable(format), qPrintable(QCFString::toQString(flavor)), qPrintable(c->convertorName()));
+#endif
+ buffer.detach(); //detach since we release the macBuffer
+ retList.append(buffer);
+ break; //skip to next element
+ }
+ }
+ } else {
+#ifdef DEBUG_PASTEBOARD
+ qDebug(" - NoMatch %s [%s] (%s)", qPrintable(c_flavor), qPrintable(QCFString::toQString(flavor)), qPrintable(c->convertorName()));
+#endif
+ }
+ }
+ }
+
+ if (!retList.isEmpty()) {
+ ret = c->convertToMime(format, retList, c_flavor);
+ return ret;
+ }
+ }
+ }
+ return QVariant();
+}
+
+void QMacPasteboard::clear_helper()
+{
+ if (paste)
+ PasteboardClear(paste);
+ promises.clear();
+}
+
+void
+QMacPasteboard::clear()
+{
+#ifdef DEBUG_PASTEBOARD
+ qDebug("PasteBoard: clear!");
+#endif
+ clear_helper();
+}
+
+bool
+QMacPasteboard::sync() const
+{
+ if (!paste)
+ return false;
+ const bool fromGlobal = PasteboardSynchronize(paste) & kPasteboardModified;
+
+ if (fromGlobal)
+ const_cast<QMacPasteboard *>(this)->setMimeData(0);
+
+#ifdef DEBUG_PASTEBOARD
+ if (fromGlobal)
+ qDebug("Pasteboard: Synchronize!");
+#endif
+ return fromGlobal;
+}
+
+
+QString qt_mac_get_pasteboardString(PasteboardRef paste)
+{
+ QCocoaAutoReleasePool pool;
+ NSPasteboard *pb = nil;
+ CFStringRef pbname;
+ if (PasteboardCopyName(paste, &pbname) == noErr) {
+ pb = [NSPasteboard pasteboardWithName:const_cast<NSString *>(reinterpret_cast<const NSString *>(pbname))];
+ CFRelease(pbname);
+ } else {
+ pb = [NSPasteboard generalPasteboard];
+ }
+ if (pb) {
+ NSString *text = [pb stringForType:NSStringPboardType];
+ if (text)
+ return QCFString::toQString(text);
+ }
+ return QString();
+}
+
+
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qmacdefines_mac.h b/src/plugins/platforms/cocoa/qmacdefines_mac.h
index a35df47227..d89e313bcb 100644
--- a/src/plugins/platforms/cocoa/qmacdefines_mac.h
+++ b/src/plugins/platforms/cocoa/qmacdefines_mac.h
@@ -93,11 +93,6 @@ Yes, it is an informative comment ;-)
#include <QtCore/qglobal.h>
-#ifdef qDebug
-# define old_qDebug qDebug
-# undef qDebug
-#endif
-
#ifdef __LP64__
typedef signed int OSStatus;
#else
@@ -149,9 +144,3 @@ typedef AERecord AppleEvent;
#ifdef check
#undef check
#endif
-
-#ifdef old_qDebug
-# undef qDebug
-# define qDebug QT_NO_QDEBUG_MACRO
-# undef old_qDebug
-#endif
diff --git a/src/plugins/platforms/cocoa/qmacmime.h b/src/plugins/platforms/cocoa/qmacmime.h
new file mode 100644
index 0000000000..842caa5f2f
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qmacmime.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 QMACMIME_H
+#define QMACMIME_H
+
+#include <QtCore>
+
+#include <CoreFoundation/CoreFoundation.h>
+
+class Q_GUI_EXPORT QMacPasteboardMime {
+ char type;
+public:
+ enum QMacPasteboardMimeType { MIME_DND=0x01,
+ MIME_CLIP=0x02,
+ MIME_QT_CONVERTOR=0x04,
+ MIME_QT3_CONVERTOR=0x08,
+ MIME_ALL=MIME_DND|MIME_CLIP
+ };
+ explicit QMacPasteboardMime(char);
+ virtual ~QMacPasteboardMime();
+
+ static void initialize();
+
+ static QList<QMacPasteboardMime*> all(uchar);
+ static QMacPasteboardMime *convertor(uchar, const QString &mime, QString flav);
+ static QString flavorToMime(uchar, QString flav);
+
+ virtual QString convertorName() = 0;
+
+ virtual bool canConvert(const QString &mime, QString flav) = 0;
+ virtual QString mimeFor(QString flav) = 0;
+ virtual QString flavorFor(const QString &mime) = 0;
+ virtual QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav) = 0;
+ virtual QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav) = 0;
+};
+
+#endif
+
diff --git a/src/plugins/platforms/cocoa/qmacmime.mm b/src/plugins/platforms/cocoa/qmacmime.mm
new file mode 100644
index 0000000000..db86deb91c
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qmacmime.mm
@@ -0,0 +1,938 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins 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 "qmacmime.h"
+#include "qcocoahelpers.h"
+#include "qmacclipboard.h"
+
+#include "qdebug.h"
+#include "qpixmap.h"
+#include "qimagewriter.h"
+#include "qimagereader.h"
+#include "qdatastream.h"
+#include "qbuffer.h"
+#include "qdatetime.h"
+#include "qguiapplication.h"
+#include "qtextcodec.h"
+#include "qregexp.h"
+#include "qurl.h"
+#include "qmap.h"
+
+#include <Cocoa/Cocoa.h>
+
+QT_BEGIN_NAMESPACE
+
+extern CGImageRef qt_mac_createCGImageFromQImage(const QImage &img, const QImage **imagePtr = 0); // qpaintengine_mac.cpp
+
+typedef QList<QMacPasteboardMime*> MimeList;
+Q_GLOBAL_STATIC(MimeList, globalMimeList)
+
+static void cleanup_mimes()
+{
+ MimeList *mimes = globalMimeList();
+ while (!mimes->isEmpty())
+ delete mimes->takeFirst();
+}
+
+Q_GLOBAL_STATIC(QStringList, globalDraggedTypesList)
+
+/*!
+ \fn void qRegisterDraggedTypes(const QStringList &types)
+ \relates QMacPasteboardMime
+
+ Registers the given \a types as custom pasteboard types.
+
+ This function should be called to enable the Drag and Drop events
+ for custom pasteboard types on Cocoa implementations. This is required
+ in addition to a QMacPasteboardMime subclass implementation. By default
+ drag and drop is enabled for all standard pasteboard types.
+
+ \sa QMacPasteboardMime
+*/
+Q_WIDGETS_EXPORT void qRegisterDraggedTypes(const QStringList &types)
+{
+ (*globalDraggedTypesList()) += types;
+}
+
+const QStringList& qEnabledDraggedTypes()
+{
+ return (*globalDraggedTypesList());
+}
+
+
+/*****************************************************************************
+ QDnD debug facilities
+ *****************************************************************************/
+//#define DEBUG_MIME_MAPS
+
+//functions
+extern QString qt_mac_from_pascal_string(const Str255); //qglobal.cpp
+extern void qt_mac_from_pascal_string(QString, Str255, TextEncoding encoding=0, int len=-1); //qglobal.cpp
+
+ScrapFlavorType qt_mac_mime_type = 'CUTE';
+CFStringRef qt_mac_mime_typeUTI = CFSTR("com.pasteboard.trolltech.marker");
+
+/*!
+ \class QMacPasteboardMime
+ \brief The QMacPasteboardMime class converts between a MIME type and a
+ \l{http://developer.apple.com/macosx/uniformtypeidentifiers.html}{Uniform
+ Type Identifier (UTI)} format.
+ \since 4.2
+
+ \ingroup draganddrop
+ \inmodule QtWidgets
+
+ Qt's drag and drop and clipboard facilities use the MIME
+ standard. On X11, this maps trivially to the Xdnd protocol. On
+ Mac, although some applications use MIME to describe clipboard
+ contents, it is more common to use Apple's UTI format.
+
+ QMacPasteboardMime's role is to bridge the gap between MIME and UTI;
+ By subclasses this class, one can extend Qt's drag and drop
+ and clipboard handling to convert to and from unsupported, or proprietary, UTI formats.
+
+ A subclass of QMacPasteboardMime will automatically be registered, and active, upon instantiation.
+
+ Qt has predefined support for the following UTIs:
+ \list
+ \i public.utf8-plain-text - converts to "text/plain"
+ \i public.utf16-plain-text - converts to "text/plain"
+ \i public.html - converts to "text/html"
+ \i public.url - converts to "text/uri-list"
+ \i public.file-url - converts to "text/uri-list"
+ \i public.tiff - converts to "application/x-qt-image"
+ \i public.vcard - converts to "text/plain"
+ \i com.apple.traditional-mac-plain-text - converts to "text/plain"
+ \i com.apple.pict - converts to "application/x-qt-image"
+ \endlist
+
+ When working with MIME data, Qt will interate through all instances of QMacPasteboardMime to
+ find an instance that can convert to, or from, a specific MIME type. It will do this by calling
+ canConvert() on each instance, starting with (and choosing) the last created instance first.
+ The actual conversions will be done by using convertToMime() and convertFromMime().
+
+ \note The API uses the term "flavor" in some cases. This is for backwards
+ compatibility reasons, and should now be understood as UTIs.
+*/
+
+/*! \enum QMacPasteboardMime::QMacPasteboardMimeType
+ \internal
+*/
+
+/*!
+ Constructs a new conversion object of type \a t, adding it to the
+ globally accessed list of available convertors.
+*/
+QMacPasteboardMime::QMacPasteboardMime(char t) : type(t)
+{
+ globalMimeList()->append(this);
+}
+
+/*!
+ Destroys a conversion object, removing it from the global
+ list of available convertors.
+*/
+QMacPasteboardMime::~QMacPasteboardMime()
+{
+ if (!QGuiApplication::closingDown())
+ globalMimeList()->removeAll(this);
+}
+
+class QMacPasteboardMimeAny : public QMacPasteboardMime {
+private:
+
+public:
+ QMacPasteboardMimeAny() : QMacPasteboardMime(MIME_QT_CONVERTOR|MIME_ALL) {
+ }
+ ~QMacPasteboardMimeAny() {
+ }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeAny::convertorName()
+{
+ return QLatin1String("Any-Mime");
+}
+
+QString QMacPasteboardMimeAny::flavorFor(const QString &mime)
+{
+ // do not handle the mime type name in the drag pasteboard
+ if (mime == QLatin1String("application/x-qt-mime-type-name"))
+ return QString();
+ QString ret = QLatin1String("com.trolltech.anymime.") + mime;
+ return ret.replace(QLatin1Char('/'), QLatin1String("--"));
+}
+
+QString QMacPasteboardMimeAny::mimeFor(QString flav)
+{
+ const QString any_prefix = QLatin1String("com.trolltech.anymime.");
+ if (flav.size() > any_prefix.length() && flav.startsWith(any_prefix))
+ return flav.mid(any_prefix.length()).replace(QLatin1String("--"), QLatin1String("/"));
+ return QString();
+}
+
+bool QMacPasteboardMimeAny::canConvert(const QString &mime, QString flav)
+{
+ return mimeFor(flav) == mime;
+}
+
+QVariant QMacPasteboardMimeAny::convertToMime(const QString &mime, QList<QByteArray> data, QString)
+{
+ if (data.count() > 1)
+ qWarning("QMacPasteboardMimeAny: Cannot handle multiple member data");
+ QVariant ret;
+ if (mime == QLatin1String("text/plain"))
+ ret = QString::fromUtf8(data.first());
+ else
+ ret = data.first();
+ return ret;
+}
+
+QList<QByteArray> QMacPasteboardMimeAny::convertFromMime(const QString &mime, QVariant data, QString)
+{
+ QList<QByteArray> ret;
+ if (mime == QLatin1String("text/plain"))
+ ret.append(data.toString().toUtf8());
+ else
+ ret.append(data.toByteArray());
+ return ret;
+}
+
+class QMacPasteboardMimeTypeName : public QMacPasteboardMime {
+private:
+
+public:
+ QMacPasteboardMimeTypeName() : QMacPasteboardMime(MIME_QT_CONVERTOR|MIME_ALL) {
+ }
+ ~QMacPasteboardMimeTypeName() {
+ }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeTypeName::convertorName()
+{
+ return QLatin1String("Qt-Mime-Type");
+}
+
+QString QMacPasteboardMimeTypeName::flavorFor(const QString &mime)
+{
+ if (mime == QLatin1String("application/x-qt-mime-type-name"))
+ return QLatin1String("com.trolltech.qt.MimeTypeName");
+ return QString();
+}
+
+QString QMacPasteboardMimeTypeName::mimeFor(QString)
+{
+ return QString();
+}
+
+bool QMacPasteboardMimeTypeName::canConvert(const QString &, QString)
+{
+ return false;
+}
+
+QVariant QMacPasteboardMimeTypeName::convertToMime(const QString &, QList<QByteArray>, QString)
+{
+ QVariant ret;
+ return ret;
+}
+
+QList<QByteArray> QMacPasteboardMimeTypeName::convertFromMime(const QString &, QVariant, QString)
+{
+ QList<QByteArray> ret;
+ ret.append(QString("x-qt-mime-type-name").toUtf8());
+ return ret;
+}
+
+class QMacPasteboardMimePlainText : public QMacPasteboardMime {
+public:
+ QMacPasteboardMimePlainText() : QMacPasteboardMime(MIME_ALL) { }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimePlainText::convertorName()
+{
+ return QLatin1String("PlainText");
+}
+
+QString QMacPasteboardMimePlainText::flavorFor(const QString &mime)
+{
+ if (mime == QLatin1String("text/plain"))
+ return QLatin1String("com.apple.traditional-mac-plain-text");
+ return QString();
+}
+
+QString QMacPasteboardMimePlainText::mimeFor(QString flav)
+{
+ if (flav == QLatin1String("com.apple.traditional-mac-plain-text"))
+ return QLatin1String("text/plain");
+ return QString();
+}
+
+bool QMacPasteboardMimePlainText::canConvert(const QString &mime, QString flav)
+{
+ return flavorFor(mime) == flav;
+}
+
+QVariant QMacPasteboardMimePlainText::convertToMime(const QString &mimetype, QList<QByteArray> data, QString flavor)
+{
+ if (data.count() > 1)
+ qWarning("QMacPasteboardMimePlainText: Cannot handle multiple member data");
+ const QByteArray &firstData = data.first();
+ QVariant ret;
+ if (flavor == QCFString(QLatin1String("com.apple.traditional-mac-plain-text"))) {
+ QCFString str(CFStringCreateWithBytes(kCFAllocatorDefault,
+ reinterpret_cast<const UInt8 *>(firstData.constData()),
+ firstData.size(), CFStringGetSystemEncoding(), false));
+ ret = QString(str);
+ } else {
+ qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype));
+ }
+ return ret;
+}
+
+QList<QByteArray> QMacPasteboardMimePlainText::convertFromMime(const QString &, QVariant data, QString flavor)
+{
+ QList<QByteArray> ret;
+ QString string = data.toString();
+ if (flavor == QCFString(QLatin1String("com.apple.traditional-mac-plain-text")))
+ ret.append(string.toLatin1());
+ return ret;
+}
+
+class QMacPasteboardMimeUnicodeText : public QMacPasteboardMime {
+public:
+ QMacPasteboardMimeUnicodeText() : QMacPasteboardMime(MIME_ALL) { }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeUnicodeText::convertorName()
+{
+ return QLatin1String("UnicodeText");
+}
+
+QString QMacPasteboardMimeUnicodeText::flavorFor(const QString &mime)
+{
+ if (mime == QLatin1String("text/plain"))
+ return QLatin1String("public.utf16-plain-text");
+ int i = mime.indexOf(QLatin1String("charset="));
+ if (i >= 0) {
+ QString cs(mime.mid(i+8).toLower());
+ i = cs.indexOf(QLatin1Char(';'));
+ if (i>=0)
+ cs = cs.left(i);
+ if (cs == QLatin1String("system"))
+ return QLatin1String("public.utf8-plain-text");
+ else if (cs == QLatin1String("iso-10646-ucs-2")
+ || cs == QLatin1String("utf16"))
+ return QLatin1String("public.utf16-plain-text");
+ }
+ return QString();
+}
+
+QString QMacPasteboardMimeUnicodeText::mimeFor(QString flav)
+{
+ if (flav == QLatin1String("public.utf16-plain-text") || flav == QLatin1String("public.utf8-plain-text"))
+ return QLatin1String("text/plain");
+ return QString();
+}
+
+bool QMacPasteboardMimeUnicodeText::canConvert(const QString &mime, QString flav)
+{
+ return flavorFor(mime) == flav;
+}
+
+QVariant QMacPasteboardMimeUnicodeText::convertToMime(const QString &mimetype, QList<QByteArray> data, QString flavor)
+{
+ if (data.count() > 1)
+ qWarning("QMacPasteboardMimeUnicodeText: Cannot handle multiple member data");
+ const QByteArray &firstData = data.first();
+ // I can only handle two types (system and unicode) so deal with them that way
+ QVariant ret;
+ if (flavor == QLatin1String("public.utf8-plain-text")) {
+ QCFString str(CFStringCreateWithBytes(kCFAllocatorDefault,
+ reinterpret_cast<const UInt8 *>(firstData.constData()),
+ firstData.size(), CFStringGetSystemEncoding(), false));
+ ret = QString(str);
+ } else if (flavor == QLatin1String("public.utf16-plain-text")) {
+ ret = QString(reinterpret_cast<const QChar *>(firstData.constData()),
+ firstData.size() / sizeof(QChar));
+ } else {
+ qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype));
+ }
+ return ret;
+}
+
+QList<QByteArray> QMacPasteboardMimeUnicodeText::convertFromMime(const QString &, QVariant data, QString flavor)
+{
+ QList<QByteArray> ret;
+ QString string = data.toString();
+ if (flavor == QLatin1String("public.utf8-plain-text"))
+ ret.append(string.toUtf8());
+ else if (flavor == QLatin1String("public.utf16-plain-text"))
+ ret.append(QByteArray((char*)string.utf16(), string.length()*2));
+ return ret;
+}
+
+class QMacPasteboardMimeHTMLText : public QMacPasteboardMime {
+public:
+ QMacPasteboardMimeHTMLText() : QMacPasteboardMime(MIME_ALL) { }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeHTMLText::convertorName()
+{
+ return QLatin1String("HTML");
+}
+
+QString QMacPasteboardMimeHTMLText::flavorFor(const QString &mime)
+{
+ if (mime == QLatin1String("text/html"))
+ return QLatin1String("public.html");
+ return QString();
+}
+
+QString QMacPasteboardMimeHTMLText::mimeFor(QString flav)
+{
+ if (flav == QLatin1String("public.html"))
+ return QLatin1String("text/html");
+ return QString();
+}
+
+bool QMacPasteboardMimeHTMLText::canConvert(const QString &mime, QString flav)
+{
+ return flavorFor(mime) == flav;
+}
+
+QVariant QMacPasteboardMimeHTMLText::convertToMime(const QString &mimeType, QList<QByteArray> data, QString flavor)
+{
+ if (!canConvert(mimeType, flavor))
+ return QVariant();
+ if (data.count() > 1)
+ qWarning("QMacPasteboardMimeHTMLText: Cannot handle multiple member data");
+ return data.first();
+}
+
+QList<QByteArray> QMacPasteboardMimeHTMLText::convertFromMime(const QString &mime, QVariant data, QString flavor)
+{
+ QList<QByteArray> ret;
+ if (!canConvert(mime, flavor))
+ return ret;
+ ret.append(data.toByteArray());
+ return ret;
+}
+
+class QMacPasteboardMimeTiff : public QMacPasteboardMime {
+public:
+ QMacPasteboardMimeTiff() : QMacPasteboardMime(MIME_ALL) { }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeTiff::convertorName()
+{
+ return QLatin1String("Tiff");
+}
+
+QString QMacPasteboardMimeTiff::flavorFor(const QString &mime)
+{
+ if (mime.startsWith(QLatin1String("application/x-qt-image")))
+ return QLatin1String("public.tiff");
+ return QString();
+}
+
+QString QMacPasteboardMimeTiff::mimeFor(QString flav)
+{
+ if (flav == QLatin1String("public.tiff"))
+ return QLatin1String("application/x-qt-image");
+ return QString();
+}
+
+bool QMacPasteboardMimeTiff::canConvert(const QString &mime, QString flav)
+{
+ return flav == QLatin1String("public.tiff") && mime == QLatin1String("application/x-qt-image");
+}
+
+QVariant QMacPasteboardMimeTiff::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
+{
+ if (data.count() > 1)
+ qWarning("QMacPasteboardMimeTiff: Cannot handle multiple member data");
+ QVariant ret;
+ if (!canConvert(mime, flav))
+ return ret;
+ const QByteArray &a = data.first();
+ QCFType<CGImageRef> image;
+ QCFType<CFDataRef> tiffData = CFDataCreateWithBytesNoCopy(0,
+ reinterpret_cast<const UInt8 *>(a.constData()),
+ a.size(), kCFAllocatorNull);
+ QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithData(tiffData, 0);
+ image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0);
+
+ // ### TODO (msorvig) QPixmap conversion
+ //if (image != 0)
+ // ret = QVariant(QPixmap::fromMacCGImageRef(image).toImage());
+ return ret;
+}
+
+QList<QByteArray> QMacPasteboardMimeTiff::convertFromMime(const QString &mime, QVariant variant, QString flav)
+{
+ QList<QByteArray> ret;
+ if (!canConvert(mime, flav))
+ return ret;
+
+ QImage img = qvariant_cast<QImage>(variant);
+ QCFType<CGImageRef> cgimage = qt_mac_image_to_cgimage(img);
+
+ QCFType<CFMutableDataRef> data = CFDataCreateMutable(0, 0);
+ QCFType<CGImageDestinationRef> imageDestination = CGImageDestinationCreateWithData(data, kUTTypeTIFF, 1, 0);
+ if (imageDestination != 0) {
+ CFTypeRef keys[2];
+ QCFType<CFTypeRef> values[2];
+ QCFType<CFDictionaryRef> options;
+ keys[0] = kCGImagePropertyPixelWidth;
+ keys[1] = kCGImagePropertyPixelHeight;
+ int width = img.width();
+ int height = img.height();
+ values[0] = CFNumberCreate(0, kCFNumberIntType, &width);
+ values[1] = CFNumberCreate(0, kCFNumberIntType, &height);
+ options = CFDictionaryCreate(0, reinterpret_cast<const void **>(keys),
+ reinterpret_cast<const void **>(values), 2,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ CGImageDestinationAddImage(imageDestination, cgimage, options);
+ CGImageDestinationFinalize(imageDestination);
+ }
+ QByteArray ar(CFDataGetLength(data), 0);
+ CFDataGetBytes(data,
+ CFRangeMake(0, ar.size()),
+ reinterpret_cast<UInt8 *>(ar.data()));
+ ret.append(ar);
+ return ret;
+}
+
+
+class QMacPasteboardMimeFileUri : public QMacPasteboardMime {
+public:
+ QMacPasteboardMimeFileUri() : QMacPasteboardMime(MIME_ALL) { }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeFileUri::convertorName()
+{
+ return QLatin1String("FileURL");
+}
+
+QString QMacPasteboardMimeFileUri::flavorFor(const QString &mime)
+{
+ if (mime == QLatin1String("text/uri-list"))
+ return QCFString(UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, CFSTR("furl"), 0));
+ return QString();
+}
+
+QString QMacPasteboardMimeFileUri::mimeFor(QString flav)
+{
+ if (flav == QCFString(UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, CFSTR("furl"), 0)))
+ return QLatin1String("text/uri-list");
+ return QString();
+}
+
+bool QMacPasteboardMimeFileUri::canConvert(const QString &mime, QString flav)
+{
+ return mime == QLatin1String("text/uri-list")
+ && flav == QCFString(UTTypeCreatePreferredIdentifierForTag(kUTTagClassOSType, CFSTR("furl"), 0));
+}
+
+QVariant QMacPasteboardMimeFileUri::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
+{
+ if (!canConvert(mime, flav))
+ return QVariant();
+ QList<QVariant> ret;
+ for (int i = 0; i < data.size(); ++i) {
+ QUrl url = QUrl::fromEncoded(data.at(i));
+ if (url.host().toLower() == QLatin1String("localhost"))
+ url.setHost(QString());
+ url.setPath(url.path().normalized(QString::NormalizationForm_C));
+ ret.append(url);
+ }
+ return QVariant(ret);
+}
+
+QList<QByteArray> QMacPasteboardMimeFileUri::convertFromMime(const QString &mime, QVariant data, QString flav)
+{
+ QList<QByteArray> ret;
+ if (!canConvert(mime, flav))
+ return ret;
+ QList<QVariant> urls = data.toList();
+ for (int i = 0; i < urls.size(); ++i) {
+ QUrl url = urls.at(i).toUrl();
+ if (url.scheme().isEmpty())
+ url.setScheme(QLatin1String("file"));
+ if (url.scheme().toLower() == QLatin1String("file")) {
+ if (url.host().isEmpty())
+ url.setHost(QLatin1String("localhost"));
+ url.setPath(url.path().normalized(QString::NormalizationForm_D));
+ }
+ ret.append(url.toEncoded());
+ }
+ return ret;
+}
+
+class QMacPasteboardMimeUrl : public QMacPasteboardMime {
+public:
+ QMacPasteboardMimeUrl() : QMacPasteboardMime(MIME_ALL) { }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeUrl::convertorName()
+{
+ return QLatin1String("URL");
+}
+
+QString QMacPasteboardMimeUrl::flavorFor(const QString &mime)
+{
+ if (mime.startsWith(QLatin1String("text/uri-list")))
+ return QLatin1String("public.url");
+ return QString();
+}
+
+QString QMacPasteboardMimeUrl::mimeFor(QString flav)
+{
+ if (flav == QLatin1String("public.url"))
+ return QLatin1String("text/uri-list");
+ return QString();
+}
+
+bool QMacPasteboardMimeUrl::canConvert(const QString &mime, QString flav)
+{
+ return flav == QLatin1String("public.url")
+ && mime == QLatin1String("text/uri-list");
+}
+
+QVariant QMacPasteboardMimeUrl::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
+{
+ if (!canConvert(mime, flav))
+ return QVariant();
+
+ QList<QVariant> ret;
+ for (int i=0; i<data.size(); ++i) {
+ QUrl url = QUrl::fromEncoded(data.at(i));
+ if (url.host().toLower() == QLatin1String("localhost"))
+ url.setHost(QString());
+ url.setPath(url.path().normalized(QString::NormalizationForm_C));
+ ret.append(url);
+ }
+ return QVariant(ret);
+}
+
+QList<QByteArray> QMacPasteboardMimeUrl::convertFromMime(const QString &mime, QVariant data, QString flav)
+{
+ QList<QByteArray> ret;
+ if (!canConvert(mime, flav))
+ return ret;
+
+ QList<QVariant> urls = data.toList();
+ for (int i=0; i<urls.size(); ++i) {
+ QUrl url = urls.at(i).toUrl();
+ if (url.scheme().isEmpty())
+ url.setScheme(QLatin1String("file"));
+ if (url.scheme().toLower() == QLatin1String("file")) {
+ if (url.host().isEmpty())
+ url.setHost(QLatin1String("localhost"));
+ url.setPath(url.path().normalized(QString::NormalizationForm_D));
+ }
+ ret.append(url.toEncoded());
+ }
+ return ret;
+}
+
+class QMacPasteboardMimeVCard : public QMacPasteboardMime
+{
+public:
+ QMacPasteboardMimeVCard() : QMacPasteboardMime(MIME_ALL){ }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeVCard::convertorName()
+{
+ return QString("VCard");
+}
+
+bool QMacPasteboardMimeVCard::canConvert(const QString &mime, QString flav)
+{
+ return mimeFor(flav) == mime;
+}
+
+QString QMacPasteboardMimeVCard::flavorFor(const QString &mime)
+{
+ if (mime.startsWith(QLatin1String("text/plain")))
+ return QLatin1String("public.vcard");
+ return QString();
+}
+
+QString QMacPasteboardMimeVCard::mimeFor(QString flav)
+{
+ if (flav == QLatin1String("public.vcard"))
+ return QLatin1String("text/plain");
+ return QString();
+}
+
+QVariant QMacPasteboardMimeVCard::convertToMime(const QString &mime, QList<QByteArray> data, QString)
+{
+ QByteArray cards;
+ if (mime == QLatin1String("text/plain")) {
+ for (int i=0; i<data.size(); ++i)
+ cards += data[i];
+ }
+ return QVariant(cards);
+}
+
+QList<QByteArray> QMacPasteboardMimeVCard::convertFromMime(const QString &mime, QVariant data, QString)
+{
+ QList<QByteArray> ret;
+ if (mime == QLatin1String("text/plain"))
+ ret.append(data.toString().toUtf8());
+ return ret;
+}
+
+
+/*!
+ \internal
+
+ This is an internal function.
+*/
+void QMacPasteboardMime::initialize()
+{
+ if (globalMimeList()->isEmpty()) {
+ qAddPostRoutine(cleanup_mimes);
+
+ //standard types that we wrap
+ new QMacPasteboardMimeTiff;
+ new QMacPasteboardMimeUnicodeText;
+ new QMacPasteboardMimePlainText;
+ new QMacPasteboardMimeHTMLText;
+ new QMacPasteboardMimeFileUri;
+ new QMacPasteboardMimeUrl;
+ new QMacPasteboardMimeTypeName;
+ new QMacPasteboardMimeVCard;
+ //make sure our "non-standard" types are always last! --Sam
+ new QMacPasteboardMimeAny;
+ }
+}
+
+/*!
+ Returns the most-recently created QMacPasteboardMime of type \a t that can convert
+ between the \a mime and \a flav formats. Returns 0 if no such convertor
+ exists.
+*/
+QMacPasteboardMime*
+QMacPasteboardMime::convertor(uchar t, const QString &mime, QString flav)
+{
+ MimeList *mimes = globalMimeList();
+ for (MimeList::const_iterator it = mimes->constBegin(); it != mimes->constEnd(); ++it) {
+#ifdef DEBUG_MIME_MAPS
+ qDebug("QMacPasteboardMime::convertor: seeing if %s (%d) can convert %s to %d[%c%c%c%c] [%d]",
+ (*it)->convertorName().toLatin1().constData(),
+ (*it)->type & t, mime.toLatin1().constData(),
+ flav, (flav >> 24) & 0xFF, (flav >> 16) & 0xFF, (flav >> 8) & 0xFF, (flav) & 0xFF,
+ (*it)->canConvert(mime,flav));
+ for (int i = 0; i < (*it)->countFlavors(); ++i) {
+ int f = (*it)->flavor(i);
+ qDebug(" %d) %d[%c%c%c%c] [%s]", i, f,
+ (f >> 24) & 0xFF, (f >> 16) & 0xFF, (f >> 8) & 0xFF, (f) & 0xFF,
+ (*it)->convertorName().toLatin1().constData());
+ }
+#endif
+ if (((*it)->type & t) && (*it)->canConvert(mime, flav))
+ return (*it);
+ }
+ return 0;
+}
+/*!
+ Returns a MIME type of type \a t for \a flav, or 0 if none exists.
+*/
+QString QMacPasteboardMime::flavorToMime(uchar t, QString flav)
+{
+ MimeList *mimes = globalMimeList();
+ for (MimeList::const_iterator it = mimes->constBegin(); it != mimes->constEnd(); ++it) {
+#ifdef DEBUG_MIME_MAPS
+ qDebug("QMacMIme::flavorToMime: attempting %s (%d) for flavor %d[%c%c%c%c] [%s]",
+ (*it)->convertorName().toLatin1().constData(),
+ (*it)->type & t, flav, (flav >> 24) & 0xFF, (flav >> 16) & 0xFF, (flav >> 8) & 0xFF, (flav) & 0xFF,
+ (*it)->mimeFor(flav).toLatin1().constData());
+
+#endif
+ if ((*it)->type & t) {
+ QString mimeType = (*it)->mimeFor(flav);
+ if (!mimeType.isNull())
+ return mimeType;
+ }
+ }
+ return QString();
+}
+
+/*!
+ Returns a list of all currently defined QMacPasteboardMime objects of type \a t.
+*/
+QList<QMacPasteboardMime*> QMacPasteboardMime::all(uchar t)
+{
+ MimeList ret;
+ MimeList *mimes = globalMimeList();
+ for (MimeList::const_iterator it = mimes->constBegin(); it != mimes->constEnd(); ++it) {
+ if ((*it)->type & t)
+ ret.append((*it));
+ }
+ return ret;
+}
+
+
+/*!
+ \fn QString QMacPasteboardMime::convertorName()
+
+ Returns a name for the convertor.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn bool QMacPasteboardMime::canConvert(const QString &mime, QString flav)
+
+ Returns true if the convertor can convert (both ways) between
+ \a mime and \a flav; otherwise returns false.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn QString QMacPasteboardMime::mimeFor(QString flav)
+
+ Returns the MIME UTI used for Mac flavor \a flav, or 0 if this
+ convertor does not support \a flav.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn QString QMacPasteboardMime::flavorFor(const QString &mime)
+
+ Returns the Mac UTI used for MIME type \a mime, or 0 if this
+ convertor does not support \a mime.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn QVariant QMacPasteboardMime::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
+
+ Returns \a data converted from Mac UTI \a flav to MIME type \a
+ mime.
+
+ Note that Mac flavors must all be self-terminating. The input \a
+ data may contain trailing data.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn QList<QByteArray> QMacPasteboardMime::convertFromMime(const QString &mime, QVariant data, QString flav)
+
+ Returns \a data converted from MIME type \a mime
+ to Mac UTI \a flav.
+
+ Note that Mac flavors must all be self-terminating. The return
+ value may contain trailing data.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h
index c61ff2bd02..1a1a1cd3b9 100644
--- a/src/plugins/platforms/cocoa/qnsview.h
+++ b/src/plugins/platforms/cocoa/qnsview.h
@@ -57,6 +57,7 @@ QT_END_NAMESPACE
QCocoaWindow *m_platformWindow;
Qt::MouseButtons m_buttons;
QAccessibleInterface *m_accessibleRoot;
+ QStringList *currentCustomDragTypes;
}
- (id)init;
@@ -91,6 +92,9 @@ QT_END_NAMESPACE
- (void)keyDown:(NSEvent *)theEvent;
- (void)keyUp:(NSEvent *)theEvent;
+- (void)registerDragTypes;
+- (NSDragOperation)handleDrag:(id <NSDraggingInfo>)sender;
+
@end
#endif //QNSVIEW_H
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index a43b3fe893..9ed3332ba5 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -46,7 +46,9 @@
#include "qnsview.h"
#include "qcocoawindow.h"
#include "qcocoahelpers.h"
+#include "qcocoaautoreleasepool.h"
#include "qmultitouch_mac_p.h"
+#include "qcocoadrag.h"
#include <QtGui/QWindowSystemInterface>
#include <QtCore/QDebug>
@@ -72,6 +74,7 @@ static QTouchDevice *touchDevice = 0;
m_cgImage = 0;
m_window = 0;
m_buttons = Qt::NoButton;
+ currentCustomDragTypes = 0;
if (!touchDevice) {
touchDevice = new QTouchDevice;
touchDevice->setType(QTouchDevice::TouchPad);
@@ -109,6 +112,7 @@ static QTouchDevice *touchDevice = 0;
m_accessibleRoot = window->accessibleRoot();
#endif
+ [self registerDragTypes];
[self setPostsFrameChangedNotifications : YES];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(updateGeometry)
@@ -471,4 +475,74 @@ static QTouchDevice *touchDevice = 0;
[self handleKeyEvent : theEvent eventType :int(QEvent::KeyRelease)];
}
+-(void)registerDragTypes
+{
+ QCocoaAutoReleasePool pool;
+ // ### Custom types disabled.
+ QStringList customTypes; // = qEnabledDraggedTypes();
+ if (currentCustomDragTypes == 0 || *currentCustomDragTypes != customTypes) {
+ if (currentCustomDragTypes == 0)
+ currentCustomDragTypes = new QStringList();
+ *currentCustomDragTypes = customTypes;
+ const NSString* mimeTypeGeneric = @"com.trolltech.qt.MimeTypeName";
+ NSMutableArray *supportedTypes = [NSMutableArray arrayWithObjects:NSColorPboardType,
+ NSFilenamesPboardType, NSStringPboardType,
+ NSFilenamesPboardType, NSPostScriptPboardType, NSTIFFPboardType,
+ NSRTFPboardType, NSTabularTextPboardType, NSFontPboardType,
+ NSRulerPboardType, NSFileContentsPboardType, NSColorPboardType,
+ NSRTFDPboardType, NSHTMLPboardType, NSPICTPboardType,
+ NSURLPboardType, NSPDFPboardType, NSVCardPboardType,
+ NSFilesPromisePboardType, NSInkTextPboardType,
+ NSMultipleTextSelectionPboardType, mimeTypeGeneric, nil];
+ // Add custom types supported by the application.
+ for (int i = 0; i < customTypes.size(); i++) {
+ [supportedTypes addObject:QCFString::toNSString(customTypes[i])];
+ }
+ [self registerForDraggedTypes:supportedTypes];
+ }
+}
+
+- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
+{
+ return [self handleDrag : sender];
+}
+
+- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
+{
+ return [self handleDrag : sender];
+}
+
+// Sends drag update to Qt, return the action
+- (NSDragOperation)handleDrag:(id <NSDraggingInfo>)sender
+{
+ NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil];
+ QPoint qt_windowPoint(windowPoint.x, windowPoint.y);
+ Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations([sender draggingSourceOperationMask]);
+ QCocoaDropData mimeData([sender draggingPasteboard]);
+
+ QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_window, &mimeData, qt_windowPoint, qtAllowed);
+ return qt_mac_mapDropAction(response.acceptedAction());
+}
+
+- (void)draggingExited:(id <NSDraggingInfo>)sender
+{
+ NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil];
+ QPoint qt_windowPoint(windowPoint.x, windowPoint.y);
+
+ // Send 0 mime data to indicate drag exit
+ QWindowSystemInterface::handleDrag(m_window, 0 ,qt_windowPoint, Qt::IgnoreAction);
+}
+
+// called on drop, send the drop to Qt and return if it was accepted.
+- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
+{
+ NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil];
+ QPoint qt_windowPoint(windowPoint.x, windowPoint.y);
+ Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations([sender draggingSourceOperationMask]);
+ QCocoaDropData mimeData([sender draggingPasteboard]);
+
+ QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(m_window, &mimeData, qt_windowPoint, qtAllowed);
+ return response.isAccepted();
+}
+
@end
diff --git a/src/plugins/platforms/cocoa/qt_mac_p.h b/src/plugins/platforms/cocoa/qt_mac_p.h
index 8e94880c5a..b75e6e2bcb 100644
--- a/src/plugins/platforms/cocoa/qt_mac_p.h
+++ b/src/plugins/platforms/cocoa/qt_mac_p.h
@@ -196,44 +196,6 @@ public:
class QMacPasteboardMime;
class QMimeData;
-class QMacPasteboard
-{
- struct Promise {
- Promise() : itemId(0), convertor(0) { }
- Promise(int itemId, QMacPasteboardMime *c, QString m, QVariant d, int o=0) : itemId(itemId), offset(o), convertor(c), mime(m), data(d) { }
- int itemId, offset;
- QMacPasteboardMime *convertor;
- QString mime;
- QVariant data;
- };
- QList<Promise> promises;
-
- OSPasteboardRef paste;
- uchar mime_type;
- mutable QPointer<QMimeData> mime;
- mutable bool mac_mime_source;
- static OSStatus promiseKeeper(OSPasteboardRef, PasteboardItemID, CFStringRef, void *);
- void clear_helper();
-public:
- QMacPasteboard(OSPasteboardRef p, uchar mime_type=0);
- QMacPasteboard(uchar mime_type);
- QMacPasteboard(CFStringRef name=0, uchar mime_type=0);
- ~QMacPasteboard();
-
- bool hasFlavor(QString flavor) const;
- bool hasOSType(int c_flavor) const;
-
- OSPasteboardRef pasteBoard() const;
- QMimeData *mimeData() const;
- void setMimeData(QMimeData *mime);
-
- QStringList formats() const;
- bool hasFormat(const QString &format) const;
- QVariant retrieveData(const QString &format, QVariant::Type) const;
-
- void clear();
- bool sync() const;
-};
extern QPaintDevice *qt_mac_safe_pdev; //qapplication_mac.cpp
diff --git a/src/plugins/platforms/directfb/qdirectfbcursor.cpp b/src/plugins/platforms/directfb/qdirectfbcursor.cpp
index e1660a998a..a63bc48133 100644
--- a/src/plugins/platforms/directfb/qdirectfbcursor.cpp
+++ b/src/plugins/platforms/directfb/qdirectfbcursor.cpp
@@ -45,7 +45,7 @@
QT_BEGIN_NAMESPACE
QDirectFBCursor::QDirectFBCursor(QPlatformScreen *screen)
- : QPlatformCursor(screen)
+ : m_screen(screen)
{
m_image.reset(new QPlatformCursorImage(0, 0, 0, 0, 0, 0));
}
@@ -70,7 +70,7 @@ void QDirectFBCursor::changeCursor(QCursor *cursor, QWindow *)
}
DFBResult res;
- IDirectFBDisplayLayer *layer = toDfbLayer(screen);
+ IDirectFBDisplayLayer *layer = toDfbLayer(m_screen);
IDirectFBSurface* surface(QDirectFbConvenience::dfbSurfaceForPlatformPixmap(map.handle()));
res = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE);
diff --git a/src/plugins/platforms/directfb/qdirectfbcursor.h b/src/plugins/platforms/directfb/qdirectfbcursor.h
index 3cc2825b28..f28e225dc7 100644
--- a/src/plugins/platforms/directfb/qdirectfbcursor.h
+++ b/src/plugins/platforms/directfb/qdirectfbcursor.h
@@ -60,6 +60,7 @@ public:
private:
QScopedPointer<QPlatformCursorImage> m_image;
+ QPlatformScreen *m_screen;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/directfb/qdirectfbscreen.h b/src/plugins/platforms/directfb/qdirectfbscreen.h
index ad80576c8f..8535239088 100644
--- a/src/plugins/platforms/directfb/qdirectfbscreen.h
+++ b/src/plugins/platforms/directfb/qdirectfbscreen.h
@@ -61,6 +61,7 @@ public:
int depth() const { return m_depth; }
QImage::Format format() const { return m_format; }
QSizeF physicalSize() const { return m_physicalSize; }
+ QPlatformCursor *cursor() const { return m_cursor.data(); }
// DirectFb helpers
IDirectFBDisplayLayer *dfbLayer() const;
diff --git a/src/plugins/platforms/kms/qkmscursor.cpp b/src/plugins/platforms/kms/qkmscursor.cpp
index a38f66bd02..37817af39d 100644
--- a/src/plugins/platforms/kms/qkmscursor.cpp
+++ b/src/plugins/platforms/kms/qkmscursor.cpp
@@ -46,7 +46,7 @@
QT_BEGIN_NAMESPACE
QKmsCursor::QKmsCursor(QKmsScreen *screen)
- : QPlatformCursor(screen), m_screen(screen),
+ : m_screen(screen),
m_graphicsBufferManager(screen->device()->gbmDevice())
{
gbm_bo *bo = gbm_bo_create(m_graphicsBufferManager, 64, 64,
diff --git a/src/plugins/platforms/kms/qkmsscreen.cpp b/src/plugins/platforms/kms/qkmsscreen.cpp
index f1b9baf120..76b9bce28f 100644
--- a/src/plugins/platforms/kms/qkmsscreen.cpp
+++ b/src/plugins/platforms/kms/qkmsscreen.cpp
@@ -96,6 +96,11 @@ QSizeF QKmsScreen::physicalSize() const
return m_physicalSize;
}
+QPlatformCursor *QKmsScreen::cursor() const
+{
+ return m_cursor;
+}
+
GLuint QKmsScreen::framebufferObject() const
{
return m_bufferManager.framebufferObject();
diff --git a/src/plugins/platforms/kms/qkmsscreen.h b/src/plugins/platforms/kms/qkmsscreen.h
index 4cb547b424..058314a515 100644
--- a/src/plugins/platforms/kms/qkmsscreen.h
+++ b/src/plugins/platforms/kms/qkmsscreen.h
@@ -61,6 +61,7 @@ public:
int depth() const;
QImage::Format format() const;
QSizeF physicalSize() const;
+ QPlatformCursor *cursor() const;
GLuint framebufferObject() const;
quint32 crtcId() const { return m_crtcId; }
diff --git a/src/plugins/platforms/windows/main.cpp b/src/plugins/platforms/windows/main.cpp
index f16eff5449..6d7c89e086 100644
--- a/src/plugins/platforms/windows/main.cpp
+++ b/src/plugins/platforms/windows/main.cpp
@@ -59,15 +59,15 @@ QT_BEGIN_NAMESPACE
of QGuiApplication:
\list
- \o \c fontengine=native Indicates that the freetype font
+ \li \c fontengine=native Indicates that the freetype font
engine should not be used.
- \o \c gl=gdi Indicates that ARB Open GL functionality should not be used
+ \li \c gl=gdi Indicates that ARB Open GL functionality should not be used
\endlist
\section1 Tips
\list
- \o The environment variable \c QT_LIGHTHOUSE_WINDOWS_VERBOSE controls
+ \li The environment variable \c QT_LIGHTHOUSE_WINDOWS_VERBOSE controls
the debug level. It takes the form
\c{<keyword1>:<level1>,<keyword2>:<level2>}, where
keyword is one of \c integration, \c windows, \c backingstore and
diff --git a/src/plugins/platforms/windows/qtwindows_additional.h b/src/plugins/platforms/windows/qtwindows_additional.h
index d82240255e..ac768e2dab 100644
--- a/src/plugins/platforms/windows/qtwindows_additional.h
+++ b/src/plugins/platforms/windows/qtwindows_additional.h
@@ -61,7 +61,8 @@
# define FE_FONTSMOOTHINGCLEARTYPE 0x0002
# define CLEARTYPE_QUALITY 5
# define SPI_GETDROPSHADOW 0x1024
-
+# define COLOR_MENUHILIGHT 29
+# define COLOR_MENUBAR 30
# define CF_DIBV5 17
#define CO_E_NOT_SUPPORTED _HRESULT_TYPEDEF_(0x80004021L)
diff --git a/src/plugins/platforms/windows/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/qwindowsaccessibility.cpp
index 3ef21fa0b7..134b1c81ce 100644
--- a/src/plugins/platforms/windows/qwindowsaccessibility.cpp
+++ b/src/plugins/platforms/windows/qwindowsaccessibility.cpp
@@ -88,25 +88,54 @@
QT_BEGIN_NAMESPACE
-//#define DEBUG_SHOW_ATCLIENT_COMMANDS
-#ifdef DEBUG_SHOW_ATCLIENT_COMMANDS
+#ifndef QT_NO_DEBUG
QT_BEGIN_INCLUDE_NAMESPACE
-#include <qdebug.h>
+# include <qdebug.h>
QT_END_INCLUDE_NAMESPACE
+static inline bool debug_accessibility()
+{
+ static signed int debugging = -1;
+ if (debugging == -1)
+ debugging = qgetenv("QT_DEBUG_ACCESSIBILITY").toInt();
+ return !!debugging;
+}
+# define accessibleDebug !debug_accessibility() ? (void)0 : qDebug
+#else
+# define accessibleDebug()
+#endif
-void showDebug(const char* funcName, const QAccessibleInterface *iface)
+//#define DEBUG_SHOW_ATCLIENT_COMMANDS
+#if defined(DEBUG_SHOW_ATCLIENT_COMMANDS)
+void accessibleDebugClientCalls_helper(const char* funcName, const QAccessibleInterface *iface)
{
- qDebug() << "Role:" << qAccessibleRoleString(iface->role(0))
- << "Name:" << iface->text(QAccessible::Name, 0)
- << "State:" << QString::number(int(iface->state(0)), 16)
- << QLatin1String(funcName);
+ QString str;
+ QDebug dbg(&str);
+ dbg << iface << QLatin1String(funcName);
+ accessibleDebug("%s", qPrintable(str));
}
+# define accessibleDebugClientCalls(iface) accessibleDebugClientCalls_helper(Q_FUNC_INFO, iface)
#else
-# define showDebug(f, iface)
+# define accessibleDebugClientCalls(iface)
#endif
+
typedef QSharedPointer<QAccessibleInterface> QAIPointer;
+static bool compareAccessible(QAccessibleInterface *one, QAccessibleInterface *other)
+{
+ if (one == other) return true;
+ if (!one || !other) return false;
+
+ if (one->object() && other->object() && (one->object() == other->object()))
+ return true;
+ QAIPointer onePar(one->parent());
+ QAIPointer otherPar(other->parent());
+
+ if (compareAccessible(onePar.data(), otherPar.data()))
+ return onePar->indexOfChild(one) == otherPar->indexOfChild(other);
+ return false;
+}
+
// This stuff is used for widgets/items with no window handle:
typedef QMap<int, QPair<QObject*,int> > NotifyMap;
Q_GLOBAL_STATIC(NotifyMap, qAccessibleRecentSentEvents)
@@ -595,7 +624,7 @@ IAccessible::accHitTest documents the value returned in pvarID like this:
HRESULT STDMETHODCALLTYPE QWindowsAccessible::accHitTest(long xLeft, long yTop, VARIANT *pvarID)
{
- showDebug(__FUNCTION__, accessible);
+ accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
return E_FAIL;
@@ -635,7 +664,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accHitTest(long xLeft, long yTop,
// moz: [important]
HRESULT STDMETHODCALLTYPE QWindowsAccessible::accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varID)
{
- showDebug(__FUNCTION__, accessible);
+ accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
return E_FAIL;
@@ -659,7 +688,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accLocation(long *pxLeft, long *py
// moz: [important, but no need to implement up/down/left/right]
HRESULT STDMETHODCALLTYPE QWindowsAccessible::accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEnd)
{
- showDebug(__FUNCTION__, accessible);
+ accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
return E_FAIL;
@@ -799,7 +828,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accNavigate(long navDir, VARIANT v
// moz: [important]
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChild(VARIANT varChildID, IDispatch** ppdispChild)
{
- showDebug(__FUNCTION__, accessible);
+ accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
return E_FAIL;
@@ -815,14 +844,12 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChild(VARIANT varChildID, I
QPair<QObject*, int> ref = qAccessibleRecentSentEvents()->value(entry);
if (ref.first) {
acc = QAccessible::queryAccessibleInterface(ref.first);
- if (acc && ref.second) {
- if (ref.second) {
- QAccessibleInterface *res = acc->child(ref.second - 1);
- delete acc;
- if (!res)
- return E_INVALIDARG;
- acc = res;
- }
+ if (acc && ref.second >= 0) {
+ QAccessibleInterface *res = acc->child(ref.second);
+ delete acc;
+ if (!res)
+ return E_INVALIDARG;
+ acc = res;
}
}
} else {
@@ -853,7 +880,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChild(VARIANT varChildID, I
// moz: [important]
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChildCount(long* pcountChildren)
{
- showDebug(__FUNCTION__, accessible);
+ accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
return E_FAIL;
@@ -864,7 +891,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChildCount(long* pcountChil
// moz: [important]
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accParent(IDispatch** ppdispParent)
{
- showDebug(__FUNCTION__, accessible);
+ accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
return E_FAIL;
@@ -887,7 +914,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accParent(IDispatch** ppdispPa
HRESULT STDMETHODCALLTYPE QWindowsAccessible::accDoDefaultAction(VARIANT varID)
{
Q_UNUSED(varID);
- showDebug(__FUNCTION__, accessible);
+ accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
return E_FAIL;
@@ -904,7 +931,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accDoDefaultAction(VARIANT varID)
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDefaultAction(VARIANT varID, BSTR* pszDefaultAction)
{
Q_UNUSED(varID);
- showDebug(__FUNCTION__, accessible);
+ accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
return E_FAIL;
@@ -919,7 +946,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDefaultAction(VARIANT varID
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDescription(VARIANT varID, BSTR* pszDescription)
{
- showDebug(__FUNCTION__, accessible);
+ accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
return E_FAIL;
@@ -944,7 +971,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDescription(VARIANT varID,
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accHelp(VARIANT varID, BSTR *pszHelp)
{
- showDebug(__FUNCTION__, accessible);
+ accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
return E_FAIL;
@@ -974,7 +1001,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accHelpTopic(BSTR *, VARIANT,
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accKeyboardShortcut(VARIANT varID, BSTR *pszKeyboardShortcut)
{
Q_UNUSED(varID);
- showDebug(__FUNCTION__, accessible);
+ accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
return E_FAIL;
@@ -1004,7 +1031,7 @@ static QAccessibleInterface *relatedInterface(QAccessibleInterface *iface, QAcce
// moz: [important]
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accName(VARIANT varID, BSTR* pszName)
{
- showDebug(__FUNCTION__, accessible);
+ accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
return E_FAIL;
@@ -1040,14 +1067,14 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accName(VARIANT varID, BSTR* p
HRESULT STDMETHODCALLTYPE QWindowsAccessible::put_accName(VARIANT, BSTR)
{
- showDebug(__FUNCTION__, accessible);
+ accessibleDebugClientCalls(accessible);
return DISP_E_MEMBERNOTFOUND;
}
// moz: [important]
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accRole(VARIANT varID, VARIANT *pvarRole)
{
- showDebug(__FUNCTION__, accessible);
+ accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
return E_FAIL;
@@ -1075,7 +1102,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accRole(VARIANT varID, VARIANT
// moz: [important]
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accState(VARIANT varID, VARIANT *pvarState)
{
- showDebug(__FUNCTION__, accessible);
+ accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
return E_FAIL;
@@ -1151,7 +1178,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accState(VARIANT varID, VARIAN
// moz: [important]
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accValue(VARIANT varID, BSTR* pszValue)
{
- showDebug(__FUNCTION__, accessible);
+ accessibleDebugClientCalls(accessible);
if (!accessible->isValid() || varID.lVal)
return E_FAIL;
@@ -1172,7 +1199,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accValue(VARIANT varID, BSTR*
HRESULT STDMETHODCALLTYPE QWindowsAccessible::put_accValue(VARIANT, BSTR)
{
- showDebug(__FUNCTION__, accessible);
+ accessibleDebugClientCalls(accessible);
return DISP_E_MEMBERNOTFOUND;
}
@@ -1181,7 +1208,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accSelect(long flagsSelect, VARIAN
{
Q_UNUSED(flagsSelect);
Q_UNUSED(varID);
- showDebug(__FUNCTION__, accessible);
+ accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
return E_FAIL;
@@ -1207,24 +1234,43 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accSelect(long flagsSelect, VARIAN
return res ? S_OK : S_FALSE;
}
-// moz: [important]
+/*!
+ \internal
+ Can return:
+
+ +-------------+------------------------------------------------------------------------------+
+ | VT_EMPTY | None. Neither this object nor any of its children has the keyboard focus. |
+ +-------------+------------------------------------------------------------------------------+
+ | VT_I4 | lVal is CHILDID_SELF. The object itself has the keyboard focus. |
+ +-------------+------------------------------------------------------------------------------+
+ | VT_I4 | lVal contains the child ID of the child element that has the keyboard focus. |
+ +-------------+------------------------------------------------------------------------------+
+ | VT_DISPATCH | pdispVal member is the address of the IDispatch interface for the child |
+ | | object that has the keyboard focus. |
+ +-------------+------------------------------------------------------------------------------+
+ moz: [important]
+*/
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accFocus(VARIANT *pvarID)
{
- showDebug(__FUNCTION__, accessible);
+ accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
return E_FAIL;
if (QAccessibleInterface *acc = accessible->focusChild()) {
- QWindowsAccessible* wacc = new QWindowsAccessible(acc);
- IDispatch *iface = 0;
- wacc->QueryInterface(IID_IDispatch, (void**)&iface);
- if (iface) {
+ if (compareAccessible(acc, accessible)) {
+ (*pvarID).vt = VT_I4;
+ (*pvarID).lVal = CHILDID_SELF;
+ delete acc;
+ return S_OK;
+ } else {
+ QWindowsAccessible* wacc = new QWindowsAccessible(acc);
+ IDispatch *iface = 0;
+ wacc->QueryInterface(IID_IDispatch, (void**)&iface);
(*pvarID).vt = VT_DISPATCH;
(*pvarID).pdispVal = iface;
return S_OK;
- } else {
- delete wacc;
}
+ delete acc;
}
(*pvarID).vt = VT_EMPTY;
return S_FALSE;
@@ -1232,7 +1278,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accFocus(VARIANT *pvarID)
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accSelection(VARIANT *pvarChildren)
{
- showDebug(__FUNCTION__, accessible);
+ accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
return E_FAIL;
diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp
index f75cbeb078..337ba9ab27 100644
--- a/src/plugins/platforms/windows/qwindowscursor.cpp
+++ b/src/plugins/platforms/windows/qwindowscursor.cpp
@@ -72,11 +72,6 @@ Q_GUI_EXPORT HBITMAP qt_createIconMask(const QBitmap &bitmap);
\sa QWindowsWindowCursor
*/
-QWindowsCursor::QWindowsCursor(QPlatformScreen *s) :
- QPlatformCursor(s)
-{
-}
-
HCURSOR QWindowsCursor::createPixmapCursor(const QPixmap &pixmap, int hotX, int hotY)
{
HCURSOR cur = 0;
diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h
index a03c77a3b6..61c43dc4d2 100644
--- a/src/plugins/platforms/windows/qwindowscursor.h
+++ b/src/plugins/platforms/windows/qwindowscursor.h
@@ -70,7 +70,7 @@ private:
class QWindowsCursor : public QPlatformCursor
{
public:
- explicit QWindowsCursor(QPlatformScreen *);
+ QWindowsCursor() {}
virtual void changeCursor(QCursor * widgetCursor, QWindow * widget);
virtual QPoint pos() const { return mousePosition(); }
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
index 25b9336361..1239f3d8e2 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
@@ -366,10 +366,10 @@ void eatMouseMove()
There 2 types of native dialogs:
\list
- \o Dialogs provided by the Comdlg32 library (ChooseColor,
+ \li Dialogs provided by the Comdlg32 library (ChooseColor,
ChooseFont). They only provide a modal, blocking
function call (with idle processing).
- \o File dialogs are classes derived from IFileDialog. They
+ \li File dialogs are classes derived from IFileDialog. They
inherit IModalWindow and their exec() method (calling
IModalWindow::Show()) is similarly blocking, but methods
like close() can be called on them from event handlers.
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()
diff --git a/src/plugins/platforms/windows/qwindowsdrag.h b/src/plugins/platforms/windows/qwindowsdrag.h
index 86b5539f92..7b629baccc 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.h
+++ b/src/plugins/platforms/windows/qwindowsdrag.h
@@ -45,9 +45,9 @@
#include "qwindowsinternalmimedata.h"
#include <QtGui/QPlatformDrag>
+#include <QtGui/QPixmap>
QT_BEGIN_NAMESPACE
-
class QWindowsDropMimeData : public QWindowsInternalMimeData {
public:
QWindowsDropMimeData() {}
@@ -73,11 +73,10 @@ public:
private:
inline QWindow *findDragOverWindow(const POINTL &pt) const;
- void sendDragEnterEvent(QWindow *to, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect);
+ void handleDrag(QWindow *window, DWORD grfKeyState, const QPoint &, LPDWORD pdwEffect);
ULONG m_refs;
QWindow *const m_window;
- QWindow *m_currentWindow;
QRect m_answerRect;
QPoint m_lastPoint;
DWORD m_chosenEffect;
@@ -92,25 +91,20 @@ public:
virtual QMimeData *platformDropData() { return &m_dropData; }
- virtual void startDrag();
- virtual void move(const QMouseEvent *me);
- virtual void drop(const QMouseEvent *me);
- virtual void cancel();
+ virtual Qt::DropAction drag(QDrag *drag);
static QWindowsDrag *instance();
IDataObject *dropDataObject() const { return m_dropDataObject; }
void setDropDataObject(IDataObject *dataObject) { m_dropDataObject = dataObject; }
void releaseDropDataObject();
-
- bool dragBeingCancelled() const { return m_dragBeingCancelled; }
+ QMimeData *dropData();
QPixmap defaultCursor(Qt::DropAction action) const;
private:
QWindowsDropMimeData m_dropData;
IDataObject *m_dropDataObject;
- bool m_dragBeingCancelled;
mutable QPixmap m_copyDragCursor;
mutable QPixmap m_moveDragCursor;
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
index fba7794a12..5094ad9dc3 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qwindowsfontdatabase.h"
+#include "qwindowsfontdatabase_ft.h" // for default font
#include "qwindowscontext.h"
#include "qwindowsfontengine.h"
#include "qwindowsfontenginedirectwrite.h"
@@ -1066,53 +1067,7 @@ static inline int verticalDPI()
QFont QWindowsFontDatabase::defaultFont() const
{
- LOGFONT lf;
- GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(lf), &lf);
- QFont systemFont = QWindowsFontDatabase::LOGFONT_to_QFont(lf);
- // "MS Shell Dlg 2" is the correct system font >= Win2k
- if (systemFont.family() == QStringLiteral("MS Shell Dlg"))
- systemFont.setFamily(QStringLiteral("MS Shell Dlg 2"));
- if (QWindowsContext::verboseFonts)
- qDebug() << __FUNCTION__ << systemFont;
- return systemFont;
-}
-
-QHash<QByteArray, QFont> QWindowsFontDatabase::defaultFonts() const
-{
- QHash<QByteArray, QFont> result;
- NONCLIENTMETRICS ncm;
- ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT);
- SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0);
-
- const int verticalRes = verticalDPI();
-
- const QFont menuFont = LOGFONT_to_QFont(ncm.lfMenuFont, verticalRes);
- const QFont messageFont = LOGFONT_to_QFont(ncm.lfMessageFont, verticalRes);
- const QFont statusFont = LOGFONT_to_QFont(ncm.lfStatusFont, verticalRes);
- const QFont titleFont = LOGFONT_to_QFont(ncm.lfCaptionFont, verticalRes);
-
- LOGFONT lfIconTitleFont;
- SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0);
- const QFont iconTitleFont = LOGFONT_to_QFont(lfIconTitleFont, verticalRes);
-
- result.insert(QByteArray("QMenu"), menuFont);
- result.insert(QByteArray("QMenuBar"), menuFont);
- result.insert(QByteArray("QMessageBox"), messageFont);
- result.insert(QByteArray("QTipLabel"), statusFont);
- result.insert(QByteArray("QStatusBar"), statusFont);
- result.insert(QByteArray("Q3TitleBar"), titleFont);
- result.insert(QByteArray("QWorkspaceTitleBar"), titleFont);
- result.insert(QByteArray("QAbstractItemView"), iconTitleFont);
- result.insert(QByteArray("QDockWidgetTitle"), iconTitleFont);
- if (QWindowsContext::verboseFonts) {
- typedef QHash<QByteArray, QFont>::const_iterator CIT;
- QDebug nsp = qDebug().nospace();
- nsp << __FUNCTION__ << " DPI=" << verticalRes << "\n";
- const CIT cend = result.constEnd();
- for (CIT it = result.constBegin(); it != cend; ++it)
- nsp << it.key() << ' ' << it.value() << '\n';
- }
- return result;
+ return QWindowsFontDatabaseFT::systemDefaultFont();
}
QFont QWindowsFontDatabase::LOGFONT_to_QFont(const LOGFONT& logFont, int verticalDPI_In)
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.h b/src/plugins/platforms/windows/qwindowsfontdatabase.h
index b08b682991..04d6ccdd91 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.h
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.h
@@ -86,7 +86,6 @@ public:
virtual QString fontDir() const;
virtual QFont defaultFont() const;
- virtual QHash<QByteArray, QFont> defaultFonts() const;
static QFontEngine *createEngine(int script, const QFontDef &request,
HDC fontHdc, int dpi, bool rawMode,
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
index e972ae23ee..fcce87d0bd 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
@@ -460,7 +460,7 @@ static inline int verticalDPI()
return GetDeviceCaps(QWindowsContext::instance()->displayContext(), LOGPIXELSY);
}
-QFont QWindowsFontDatabaseFT::defaultFont() const
+QFont QWindowsFontDatabaseFT::systemDefaultFont()
{
LOGFONT lf;
GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(lf), &lf);
@@ -473,44 +473,6 @@ QFont QWindowsFontDatabaseFT::defaultFont() const
return systemFont;
}
-QHash<QByteArray, QFont> QWindowsFontDatabaseFT::defaultFonts() const
-{
- QHash<QByteArray, QFont> result;
- NONCLIENTMETRICS ncm;
- ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT);
- SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0);
-
- const int verticalRes = verticalDPI();
-
- const QFont menuFont = LOGFONT_to_QFont(ncm.lfMenuFont, verticalRes);
- const QFont messageFont = LOGFONT_to_QFont(ncm.lfMessageFont, verticalRes);
- const QFont statusFont = LOGFONT_to_QFont(ncm.lfStatusFont, verticalRes);
- const QFont titleFont = LOGFONT_to_QFont(ncm.lfCaptionFont, verticalRes);
-
- LOGFONT lfIconTitleFont;
- SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0);
- const QFont iconTitleFont = LOGFONT_to_QFont(lfIconTitleFont, verticalRes);
-
- result.insert(QByteArray("QMenu"), menuFont);
- result.insert(QByteArray("QMenuBar"), menuFont);
- result.insert(QByteArray("QMessageBox"), messageFont);
- result.insert(QByteArray("QTipLabel"), statusFont);
- result.insert(QByteArray("QStatusBar"), statusFont);
- result.insert(QByteArray("Q3TitleBar"), titleFont);
- result.insert(QByteArray("QWorkspaceTitleBar"), titleFont);
- result.insert(QByteArray("QAbstractItemView"), iconTitleFont);
- result.insert(QByteArray("QDockWidgetTitle"), iconTitleFont);
- if (QWindowsContext::verboseFonts) {
- typedef QHash<QByteArray, QFont>::const_iterator CIT;
- QDebug nsp = qDebug().nospace();
- nsp << __FUNCTION__ << " DPI=" << verticalRes << "\n";
- const CIT cend = result.constEnd();
- for (CIT it = result.constBegin(); it != cend; ++it)
- nsp << it.key() << ' ' << it.value() << '\n';
- }
- return result;
-}
-
QFont QWindowsFontDatabaseFT::LOGFONT_to_QFont(const LOGFONT& logFont, int verticalDPI_In)
{
if (verticalDPI_In <= 0)
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
index 5a0c4c6377..4136b75dd8 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
@@ -59,8 +59,9 @@ public:
QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName);
virtual QString fontDir() const;
- virtual QFont defaultFont() const;
- virtual QHash<QByteArray, QFont> defaultFonts() const;
+ virtual QFont defaultFont() const { return systemDefaultFont(); }
+ static QFont systemDefaultFont();
+
static HFONT systemFont();
static QFont LOGFONT_to_QFont(const LOGFONT& lf, int verticalDPI = 0);
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
index 5085dfefb7..ae5053210e 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
@@ -108,11 +108,11 @@ template <class T>
\section1 Testing
\list
- \o Install the East Asian language support and choose Japanese (say).
- \o Compile the \a mainwindows/mdi example and open a text window.
- \o In the language bar, switch to Japanese and choose the
+ \li Install the East Asian language support and choose Japanese (say).
+ \li Compile the \a mainwindows/mdi example and open a text window.
+ \li In the language bar, switch to Japanese and choose the
Input method 'Hiragana'.
- \o In a text editor control, type the syllable \a 'la'.
+ \li In a text editor control, type the syllable \a 'la'.
Underlined characters show up, indicating that there is completion
available. Press the Space key two times. A completion popup occurs
which shows the options.
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index 3e98be4741..b43362c045 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -74,9 +74,9 @@ QT_BEGIN_NAMESPACE
Currently implemented keys
\list
- \o handle (HWND)
- \o getDC (DC)
- \o releaseDC Releases the previously acquired DC and returns 0.
+ \li handle (HWND)
+ \li getDC (DC)
+ \li releaseDC Releases the previously acquired DC and returns 0.
\endlist
\ingroup qt-lighthouse-win
diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp
index 570e4b3b6b..e41db3f60f 100644
--- a/src/plugins/platforms/windows/qwindowsmime.cpp
+++ b/src/plugins/platforms/windows/qwindowsmime.cpp
@@ -413,14 +413,14 @@ static bool canGetData(int cf, IDataObject * pDataObj)
Qt has predefined support for the following Windows Clipboard formats:
\table
- \header \o Windows Format \o Equivalent MIME type
- \row \o \c CF_UNICODETEXT \o \c text/plain
- \row \o \c CF_TEXT \o \c text/plain
- \row \o \c CF_DIB \o \c{image/xyz}, where \c xyz is
+ \header \li Windows Format \li Equivalent MIME type
+ \row \li \c CF_UNICODETEXT \li \c text/plain
+ \row \li \c CF_TEXT \li \c text/plain
+ \row \li \c CF_DIB \li \c{image/xyz}, where \c xyz is
a \l{QImageWriter::supportedImageFormats()}{Qt image format}
- \row \o \c CF_HDROP \o \c text/uri-list
- \row \o \c CF_INETURL \o \c text/uri-list
- \row \o \c CF_HTML \o \c text/html
+ \row \li \c CF_HDROP \li \c text/uri-list
+ \row \li \c CF_INETURL \li \c text/uri-list
+ \row \li \c CF_HTML \li \c text/html
\endtable
An example use of this class would be to map the Windows Metafile
diff --git a/src/plugins/platforms/windows/qwindowsole.cpp b/src/plugins/platforms/windows/qwindowsole.cpp
index 3ae9fe1048..6f34967ee8 100644
--- a/src/plugins/platforms/windows/qwindowsole.cpp
+++ b/src/plugins/platforms/windows/qwindowsole.cpp
@@ -63,11 +63,11 @@ QT_BEGIN_NAMESPACE
The following methods are NOT supported for data transfer using the
clipboard or drag-drop:
\list
- \o IDataObject::SetData -- return E_NOTIMPL
- \o IDataObject::DAdvise -- return OLE_E_ADVISENOTSUPPORTED
- \o ::DUnadvise
- \o ::EnumDAdvise
- \o IDataObject::GetCanonicalFormatEtc -- return E_NOTIMPL
+ \li IDataObject::SetData -- return E_NOTIMPL
+ \li IDataObject::DAdvise -- return OLE_E_ADVISENOTSUPPORTED
+ \li ::DUnadvise
+ \li ::EnumDAdvise
+ \li IDataObject::GetCanonicalFormatEtc -- return E_NOTIMPL
(NOTE: must set pformatetcOut->ptd = NULL)
\endlist
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index 1dc5175515..2476e15169 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -147,6 +147,14 @@ static QDebug operator<<(QDebug dbg, const QWindowsScreenData &d)
return dbg;
}
+// Return the cursor to be shared by all screens (virtual desktop).
+static inline QSharedPointer<QWindowsCursor> sharedCursor()
+{
+ if (const QScreen *primaryScreen = QGuiApplication::primaryScreen())
+ return static_cast<const QWindowsScreen *>(primaryScreen->handle())->windowsCursor();
+ return QSharedPointer<QWindowsCursor>(new QWindowsCursor);
+}
+
/*!
\class QWindowsScreen
\brief Windows screen.
@@ -155,7 +163,7 @@ static QDebug operator<<(QDebug dbg, const QWindowsScreenData &d)
*/
QWindowsScreen::QWindowsScreen(const QWindowsScreenData &data) :
- m_data(data), m_cursor(this)
+ m_data(data), m_cursor(sharedCursor())
{
}
diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h
index 436cc2c0d9..5b9a50b2ab 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.h
+++ b/src/plugins/platforms/windows/qwindowsscreen.h
@@ -46,6 +46,7 @@
#include <QtCore/QList>
#include <QtCore/QPair>
+#include <QtCore/QSharedPointer>
#include <QtGui/QPlatformScreen>
QT_BEGIN_NAMESPACE
@@ -74,6 +75,8 @@ struct QWindowsScreenData
class QWindowsScreen : public QPlatformScreen
{
public:
+ typedef QSharedPointer<QWindowsCursor> WindowsCursorPtr;
+
explicit QWindowsScreen(const QWindowsScreenData &data);
static QWindowsScreen *screenOf(const QWindow *w = 0);
@@ -98,14 +101,14 @@ public:
inline void handleChanges(const QWindowsScreenData &newData);
- const QWindowsCursor &cursor() const { return m_cursor; }
- QWindowsCursor &cursor() { return m_cursor; }
+ QPlatformCursor *cursor() const { return m_cursor.data(); }
+ const WindowsCursorPtr &windowsCursor() const { return m_cursor; }
const QWindowsScreenData &data() const { return m_data; }
private:
QWindowsScreenData m_data;
- QWindowsCursor m_cursor;
+ const WindowsCursorPtr m_cursor;
};
class QWindowsScreenManager
@@ -115,7 +118,11 @@ public:
QWindowsScreenManager();
- inline void clearScreens() { qDeleteAll(m_screens); m_screens.clear(); }
+ inline void clearScreens() {
+ // Delete screens in reverse order to avoid crash in case of multiple screens
+ while (!m_screens.isEmpty())
+ delete m_screens.takeLast();
+ }
void handleScreenChanges();
bool handleDisplayChange(WPARAM wParam, LPARAM lParam);
diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp
index 5350b3ca3f..10b4682ad8 100644
--- a/src/plugins/platforms/windows/qwindowstheme.cpp
+++ b/src/plugins/platforms/windows/qwindowstheme.cpp
@@ -44,6 +44,7 @@
#include "qwindowscontext.h"
#include "qwindowsintegration.h"
#include "qt_windows.h"
+#include "qwindowsfontdatabase_ft.h"
#include <QtCore/QVariant>
#include <QtCore/QCoreApplication>
@@ -76,6 +77,22 @@ static inline QString paletteToString(const QPalette &palette)
return result;
}
+static inline bool booleanSystemParametersInfo(UINT what, bool defaultValue)
+{
+ BOOL result;
+ if (SystemParametersInfo(what, 0, &result, 0))
+ return result ? true : false;
+ return defaultValue;
+}
+
+static inline bool dWordSystemParametersInfo(UINT what, DWORD defaultValue)
+{
+ DWORD result;
+ if (SystemParametersInfo(what, 0, &result, 0))
+ return result;
+ return defaultValue;
+}
+
static inline QColor mixColors(const QColor &c1, const QColor &c2)
{
return QColor ((c1.red() + c2.red()) / 2,
@@ -138,7 +155,7 @@ static inline QPalette systemPalette()
return result;
}
-QPalette toolTipPalette(const QPalette &systemPalette)
+static inline QPalette toolTipPalette(const QPalette &systemPalette)
{
QPalette result(systemPalette);
const QColor tipBgColor(getSysColor(COLOR_INFOBK));
@@ -163,24 +180,58 @@ QPalette toolTipPalette(const QPalette &systemPalette)
return result;
}
-static inline bool booleanSystemParametersInfo(UINT what, bool defaultValue)
+static inline QPalette menuPalette(const QPalette &systemPalette)
{
- BOOL result;
- if (SystemParametersInfo(what, 0, &result, 0))
- return result ? true : false;
- return defaultValue;
+ QPalette result(systemPalette);
+ const QColor menuColor(getSysColor(COLOR_INFOBK));
+ const QColor menuTextColor(getSysColor(COLOR_MENUTEXT));
+ const QColor disabled(getSysColor(COLOR_GRAYTEXT));
+ const bool isFlat = booleanSystemParametersInfo(SPI_GETFLATMENU, false);
+ // we might need a special color group for the result.
+ result.setColor(QPalette::Active, QPalette::Button, menuColor);
+ result.setColor(QPalette::Active, QPalette::Text, menuTextColor);
+ result.setColor(QPalette::Active, QPalette::WindowText, menuTextColor);
+ result.setColor(QPalette::Active, QPalette::ButtonText, menuTextColor);
+ result.setColor(QPalette::Disabled, QPalette::WindowText, disabled);
+ result.setColor(QPalette::Disabled, QPalette::Text, disabled);
+ result.setColor(QPalette::Disabled, QPalette::Highlight,
+ getSysColor(isFlat ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT));
+ result.setColor(QPalette::Disabled, QPalette::HighlightedText, disabled);
+ result.setColor(QPalette::Disabled, QPalette::Button,
+ result.color(QPalette::Active, QPalette::Button));
+ result.setColor(QPalette::Inactive, QPalette::Button,
+ result.color(QPalette::Active, QPalette::Button));
+ result.setColor(QPalette::Inactive, QPalette::Text,
+ result.color(QPalette::Active, QPalette::Text));
+ result.setColor(QPalette::Inactive, QPalette::WindowText,
+ result.color(QPalette::Active, QPalette::WindowText));
+ result.setColor(QPalette::Inactive, QPalette::ButtonText,
+ result.color(QPalette::Active, QPalette::ButtonText));
+ result.setColor(QPalette::Inactive, QPalette::Highlight,
+ result.color(QPalette::Active, QPalette::Highlight));
+ result.setColor(QPalette::Inactive, QPalette::HighlightedText,
+ result.color(QPalette::Active, QPalette::HighlightedText));
+ result.setColor(QPalette::Inactive, QPalette::ButtonText,
+ systemPalette.color(QPalette::Inactive, QPalette::Dark));
+ return result;
}
-static inline bool dWordSystemParametersInfo(UINT what, DWORD defaultValue)
+static inline QPalette *menuBarPalette(const QPalette &menuPalette)
{
- DWORD result;
- if (SystemParametersInfo(what, 0, &result, 0))
- return result;
- return defaultValue;
+ QPalette *result = 0;
+ if (booleanSystemParametersInfo(SPI_GETFLATMENU, false)) {
+ result = new QPalette(menuPalette);
+ const QColor menubar(getSysColor(COLOR_MENUBAR));
+ result->setColor(QPalette::Active, QPalette::Button, menubar);
+ result->setColor(QPalette::Disabled, QPalette::Button, menubar);
+ result->setColor(QPalette::Inactive, QPalette::Button, menubar);
+ }
+ return result;
}
QWindowsTheme::QWindowsTheme()
{
+ qFill(m_fonts, m_fonts + NFonts, static_cast<QFont *>(0));
qFill(m_palettes, m_palettes + NPalettes, static_cast<QPalette *>(0));
refresh();
}
@@ -188,12 +239,7 @@ QWindowsTheme::QWindowsTheme()
QWindowsTheme::~QWindowsTheme()
{
clearPalettes();
-}
-
-void QWindowsTheme::clearPalettes()
-{
- qDeleteAll(m_palettes, m_palettes + NPalettes);
- qFill(m_palettes, m_palettes + NPalettes, static_cast<QPalette *>(0));
+ clearFonts();
}
QWindowsTheme *QWindowsTheme::instance()
@@ -243,17 +289,65 @@ QVariant QWindowsTheme::themeHint(ThemeHint hint) const
return QPlatformTheme::themeHint(hint);
}
-void QWindowsTheme::refresh()
+void QWindowsTheme::clearPalettes()
{
- clearPalettes();
- if (QGuiApplication::desktopSettingsAware()) {
- m_palettes[SystemPalette] = new QPalette(systemPalette());
- m_palettes[ToolTipPalette] = new QPalette(toolTipPalette(*m_palettes[SystemPalette]));
- if (QWindowsContext::verboseTheming)
- qDebug() << __FUNCTION__ << '\n'
- << " system=" << paletteToString(*m_palettes[SystemPalette])
- << " tooltip=" << paletteToString(*m_palettes[ToolTipPalette]);
- }
+ qDeleteAll(m_palettes, m_palettes + NPalettes);
+ qFill(m_palettes, m_palettes + NPalettes, static_cast<QPalette *>(0));
+}
+
+void QWindowsTheme::refreshPalettes()
+{
+
+ if (!QGuiApplication::desktopSettingsAware())
+ return;
+ m_palettes[SystemPalette] = new QPalette(systemPalette());
+ m_palettes[ToolTipPalette] = new QPalette(toolTipPalette(*m_palettes[SystemPalette]));
+ m_palettes[MenuPalette] = new QPalette(menuPalette(*m_palettes[SystemPalette]));
+ m_palettes[MenuBarPalette] = menuBarPalette(*m_palettes[MenuPalette]);
+ if (QWindowsContext::verboseTheming)
+ qDebug() << __FUNCTION__ << '\n'
+ << " system=" << paletteToString(*m_palettes[SystemPalette])
+ << " tooltip=" << paletteToString(*m_palettes[ToolTipPalette]);
+}
+
+void QWindowsTheme::clearFonts()
+{
+ qDeleteAll(m_fonts, m_fonts + NFonts);
+ qFill(m_fonts, m_fonts + NFonts, static_cast<QFont *>(0));
+}
+
+void QWindowsTheme::refreshFonts()
+{
+ clearFonts();
+ if (!QGuiApplication::desktopSettingsAware())
+ return;
+ NONCLIENTMETRICS ncm;
+ ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT);
+ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0);
+
+ const QFont menuFont = QWindowsFontDatabaseFT::LOGFONT_to_QFont(ncm.lfMenuFont);
+ const QFont messageBoxFont = QWindowsFontDatabaseFT::LOGFONT_to_QFont(ncm.lfMessageFont);
+ const QFont statusFont = QWindowsFontDatabaseFT::LOGFONT_to_QFont(ncm.lfStatusFont);
+ const QFont titleFont = QWindowsFontDatabaseFT::LOGFONT_to_QFont(ncm.lfCaptionFont);
+
+ LOGFONT lfIconTitleFont;
+ SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0);
+ const QFont iconTitleFont = QWindowsFontDatabaseFT::LOGFONT_to_QFont(lfIconTitleFont);
+
+ m_fonts[SystemFont] = new QFont(QWindowsFontDatabaseFT::systemDefaultFont());
+ m_fonts[MenuFont] = new QFont(menuFont);
+ m_fonts[MenuBarFont] = new QFont(menuFont);
+ m_fonts[MessageBoxFont] = new QFont(messageBoxFont);
+ m_fonts[TipLabelFont] = new QFont(statusFont);
+ m_fonts[StatusBarFont] = new QFont(statusFont);
+ m_fonts[MdiSubWindowTitleFont] = new QFont(titleFont);
+ m_fonts[DockWidgetTitleFont] = new QFont(titleFont);
+ m_fonts[ItemViewFont] = new QFont(iconTitleFont);
+
+ if (QWindowsContext::verboseTheming)
+ qDebug() << __FUNCTION__ << '\n'
+ << " menuFont=" << menuFont
+ << " messageBox=" << MessageBoxFont;
}
bool QWindowsTheme::usePlatformNativeDialog(DialogType type) const
diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h
index 950c380737..37346eed3a 100644
--- a/src/plugins/platforms/windows/qwindowstheme.h
+++ b/src/plugins/platforms/windows/qwindowstheme.h
@@ -64,14 +64,20 @@ public:
virtual QVariant themeHint(ThemeHint) const;
virtual const QPalette *palette(Palette type = SystemPalette) const
{ return m_palettes[type]; }
+ virtual const QFont *font(Font type = SystemFont) const
+ { return m_fonts[type]; }
void windowsThemeChanged(QWindow *window);
private:
- void refresh();
+ void refresh() { refreshPalettes(); refreshFonts(); }
void clearPalettes();
+ void refreshPalettes();
+ void clearFonts();
+ void refreshFonts();
QPalette *m_palettes[NPalettes];
+ QFont *m_fonts[NFonts];
};
static inline COLORREF qColorToCOLORREF(const QColor &color)
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 3e0bec8d46..1edb243f4e 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -205,18 +205,18 @@ static bool shouldShowMaximizeButton(Qt::WindowFlags flags)
Window creation is split in 3 steps:
\list
- \o fromWindow() Gather all required information
- \o create() Create the system handle.
- \o initialize() Post creation initialization steps.
+ \li fromWindow() Gather all required information
+ \li create() Create the system handle.
+ \li initialize() Post creation initialization steps.
\endlist
The reason for this split is to also enable changing the QWindowFlags
by calling:
\list
- \o fromWindow() Gather information and determine new system styles
- \o applyWindowFlags() to apply the new window system styles.
- \o initialize() Post creation initialization steps.
+ \li fromWindow() Gather information and determine new system styles
+ \li applyWindowFlags() to apply the new window system styles.
+ \li initialize() Post creation initialization steps.
\endlist
Contains the window creation code formerly in qwidget_win.cpp.
@@ -594,13 +594,13 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w,
\brief Raster or OpenGL Window.
\list
- \o Raster type: handleWmPaint() is implemented to
+ \li Raster type: handleWmPaint() is implemented to
to bitblt the image. The DC can be accessed
via getDC/Relase DC, which has a special handling
when within a paint event (in that case, the DC obtained
from BeginPaint() is returned).
- \o Open GL: The first time QWindowsGLContext accesses
+ \li Open GL: The first time QWindowsGLContext accesses
the handle, it sets up the pixelformat on the DC
which in turn sets it on the window (see flag
PixelFormatInitialized).
@@ -618,7 +618,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const WindowData &data) :
m_windowState(aWindow->windowState()),
m_opacity(1.0),
m_mouseGrab(false),
- m_cursor(QWindowsScreen::screenOf(aWindow)->cursor().standardWindowCursor()),
+ m_cursor(QWindowsScreen::screenOf(aWindow)->windowsCursor()->standardWindowCursor()),
m_dropTarget(0),
m_savedStyle(0)
{
@@ -1309,16 +1309,14 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const
}
/*!
- \brief Applies to cursor property set on the window to the global cursor
- unless there is an override cursor.
+ \brief Applies to cursor property set on the window to the global cursor.
\sa QWindowsCursor
*/
void QWindowsWindow::applyCursor()
{
- if (!QGuiApplication::overrideCursor())
- SetCursor(m_cursor.handle());
+ SetCursor(m_cursor.handle());
}
void QWindowsWindow::setCursor(const QWindowsWindowCursor &c)
diff --git a/src/plugins/platforms/xcb/README b/src/plugins/platforms/xcb/README
index ab802ced27..17e8bb53eb 100644
--- a/src/plugins/platforms/xcb/README
+++ b/src/plugins/platforms/xcb/README
@@ -1,6 +1,6 @@
Required packages:
-libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm1 libxcb-icccm1-dev libxcb-sync0 libxcb-sync0-dev libxcb-render-util0 libxcb-render-util0-dev libxcb-xfixes0-dev libxrender-dev
+libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm1 libxcb-icccm1-dev libxcb-sync0 libxcb-sync0-dev libxcb-render-util0 libxcb-render-util0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev
On Ubuntu 11.10 icccm1 is replaced by icccm4 and xcb-render-util is not available:
-libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm4 libxcb-icccm4-dev libxcb-sync0 libxcb-sync0-dev libxcb-xfixes0-dev libxrender-dev
+libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm4 libxcb-icccm4-dev libxcb-sync0 libxcb-sync0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev
The packages for xcb-render-util can be installed manually from http://packages.ubuntu.com/natty/libxcb-render-util0 and http://packages.ubuntu.com/natty/libxcb-render-util0-dev
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp
index f8d35ed4da..63ce73993f 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp
@@ -74,7 +74,7 @@ public:
break;
default:
- qWarning("QTestLiteMime: Internal error: Unsupported clipboard mode");
+ qWarning("QXcbClipboardMime: Internal error: Unsupported clipboard mode");
break;
}
}
@@ -209,7 +209,7 @@ QXcbClipboard::~QXcbClipboard()
// waiting until the clipboard manager fetches the content.
if (!waitForClipboardEvent(m_owner, XCB_SELECTION_NOTIFY, clipboard_timeout, true)) {
- qWarning("QClipboard: Unable to receive an event from the "
+ qWarning("QXcbClipboard: Unable to receive an event from the "
"clipboard manager in a reasonable time");
}
}
@@ -292,7 +292,7 @@ void QXcbClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
xcb_set_selection_owner(xcb_connection(), newOwner, modeAtom, connection()->time());
if (getSelectionOwner(modeAtom) != newOwner) {
- qWarning("QClipboard::setData: Cannot set X11 selection owner");
+ qWarning("QXcbClipboard::setData: Cannot set X11 selection owner");
}
emitChanged(mode);
@@ -403,7 +403,7 @@ xcb_atom_t QXcbClipboard::sendSelection(QMimeData *d, xcb_atom_t target, xcb_win
atom(QXcbAtom::INCR), 32, 1, (const void *)&bytes);
// (void)new QClipboardINCRTransaction(window, property, atomFormat, dataFormat, data, increment);
- qWarning() << "not implemented INCR just YET!";
+ qWarning("QXcbClipboard: INCR is unimplemented");
return property;
}
@@ -445,7 +445,7 @@ void QXcbClipboard::handleSelectionClearRequest(xcb_selection_clear_event_t *eve
void QXcbClipboard::handleSelectionRequest(xcb_selection_request_event_t *req)
{
if (requestor() && req->requestor == requestor()) {
- qDebug() << "This should be caught before";
+ qWarning("QXcbClipboard: Selection request should be caught before");
return;
}
@@ -460,7 +460,7 @@ void QXcbClipboard::handleSelectionRequest(xcb_selection_request_event_t *req)
QMimeData *d;
QClipboard::Mode mode = modeForAtom(req->selection);
if (mode > QClipboard::Selection) {
- qWarning() << "QClipboard: Unknown selection" << connection()->atomName(req->selection);
+ qWarning() << "QXcbClipboard: Unknown selection" << connection()->atomName(req->selection);
xcb_send_event(xcb_connection(), false, req->requestor, XCB_EVENT_MASK_NO_EVENT, (const char *)&event);
return;
}
@@ -468,14 +468,14 @@ void QXcbClipboard::handleSelectionRequest(xcb_selection_request_event_t *req)
d = m_clientClipboard[mode];
if (!d) {
- qWarning("QClipboard: Cannot transfer data, no data available");
+ qWarning("QXcbClipboard: Cannot transfer data, no data available");
xcb_send_event(xcb_connection(), false, req->requestor, XCB_EVENT_MASK_NO_EVENT, (const char *)&event);
return;
}
if (m_timestamp[mode] == XCB_CURRENT_TIME // we don't own the selection anymore
|| (req->time != XCB_CURRENT_TIME && req->time < m_timestamp[mode])) {
- qDebug("QClipboard: SelectionRequest too old");
+ qWarning("QXcbClipboard: SelectionRequest too old");
xcb_send_event(xcb_connection(), false, req->requestor, XCB_EVENT_MASK_NO_EVENT, (const char *)&event);
return;
}
@@ -530,7 +530,7 @@ void QXcbClipboard::handleSelectionRequest(xcb_selection_request_event_t *req)
property, XCB_ATOM_INTEGER, 32, 1, &m_timestamp[mode]);
ret = property;
} else {
- qWarning("QClipboard: Invalid data timestamp");
+ qWarning("QXcbClipboard: Invalid data timestamp");
}
} else if (target == xa_targets) {
ret = sendTargetsSelection(d, req->requestor, property);
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index fdc2c76fea..367b24da9d 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -109,6 +109,8 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, const char
, m_has_support_for_dri2(false)
#endif
, xfixes_first_event(0)
+ , has_shape_extension(false)
+ , has_input_shape(false)
{
m_primaryScreen = 0;
@@ -133,7 +135,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, const char
#endif //XCB_USE_XLIB
if (!m_connection || xcb_connection_has_error(m_connection))
- qFatal("Could not connect to display %s", m_displayName.constData());
+ qFatal("QXcbConnection: Could not connect to display %s", m_displayName.constData());
m_reader = new QXcbEventReader(this);
#ifdef XCB_POLL_FOR_QUEUED_EVENT
@@ -175,6 +177,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, const char
#ifdef XCB_USE_XINPUT2_MAEMO
initializeXInput2();
#endif
+ initializeXShape();
m_wmSupport.reset(new QXcbWMSupport(this));
m_keyboard = new QXcbKeyboard(this);
@@ -191,7 +194,9 @@ QXcbConnection::~QXcbConnection()
{
delete m_clipboard;
- qDeleteAll(m_screens);
+ // Delete screens in reverse order to avoid crash in case of multiple screens
+ while (!m_screens.isEmpty())
+ delete m_screens.takeLast();
#ifdef XCB_USE_XINPUT2_MAEMO
finalizeXInput2();
@@ -250,7 +255,7 @@ void printXcbEvent(const char *message, xcb_generic_event_t *event)
#ifdef XCB_EVENT_DEBUG
#define PRINT_XCB_EVENT(ev) \
case ev: \
- qDebug("%s: %d - %s - sequence: %d", message, int(ev), #ev, event->sequence); \
+ qDebug("QXcbConnection: %s: %d - %s - sequence: %d", message, int(ev), #ev, event->sequence); \
break;
switch (event->response_type & ~0x80) {
@@ -287,7 +292,7 @@ void printXcbEvent(const char *message, xcb_generic_event_t *event)
PRINT_XCB_EVENT(XCB_CLIENT_MESSAGE);
PRINT_XCB_EVENT(XCB_MAPPING_NOTIFY);
default:
- qDebug("%s: unknown event - response_type: %d - sequence: %d", message, int(event->response_type & ~0x80), int(event->sequence));
+ qDebug("QXcbConnection: %s: unknown event - response_type: %d - sequence: %d", message, int(event->response_type & ~0x80), int(event->sequence));
}
#else
Q_UNUSED(message);
@@ -460,7 +465,7 @@ void QXcbConnection::handleXcbError(xcb_generic_error_t *error)
uint clamped_error_code = qMin<uint>(error->error_code, (sizeof(xcb_errors) / sizeof(xcb_errors[0])) - 1);
uint clamped_major_code = qMin<uint>(error->major_code, (sizeof(xcb_protocol_request_codes) / sizeof(xcb_protocol_request_codes[0])) - 1);
- qDebug("XCB error: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d",
+ qWarning("QXcbConnection: XCB error: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d",
int(error->error_code), xcb_errors[clamped_error_code],
int(error->sequence), int(error->resource_id),
int(error->major_code), xcb_protocol_request_codes[clamped_major_code],
@@ -552,7 +557,6 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
break;
case XCB_SELECTION_NOTIFY:
setTime(((xcb_selection_notify_event_t *)event)->time);
- qDebug() << "XCB_SELECTION_NOTIFY";
handled = false;
break;
case XCB_PROPERTY_NOTIFY:
@@ -714,9 +718,9 @@ void QXcbConnection::handleClientMessageEvent(const xcb_client_message_event_t *
return;
if (event->type == atom(QXcbAtom::XdndStatus)) {
- drag()->handleStatus(event, false);
+ drag()->handleStatus(event);
} else if (event->type == atom(QXcbAtom::XdndFinished)) {
- drag()->handleFinished(event, false);
+ drag()->handleFinished(event);
}
QXcbWindow *window = platformWindowFromId(event->window);
@@ -1024,7 +1028,7 @@ void QXcbConnection::initializeXFixes()
xcb_xfixes_query_version_reply_t *xfixes_query = xcb_xfixes_query_version_reply (m_connection,
xfixes_query_cookie, &error);
if (!xfixes_query || error || xfixes_query->major_version < 2) {
- qWarning("Failed to initialize XFixes");
+ qWarning("QXcbConnection: Failed to initialize XFixes");
free(error);
xfixes_first_event = 0;
}
@@ -1041,13 +1045,32 @@ void QXcbConnection::initializeXRender()
xcb_render_query_version_reply_t *xrender_query = xcb_render_query_version_reply(m_connection,
xrender_query_cookie, &error);
if (!xrender_query || error || (xrender_query->major_version == 0 && xrender_query->minor_version < 5)) {
- qWarning("Failed to initialize XRender");
+ qWarning("QXcbConnection: Failed to initialize XRender");
free(error);
}
free(xrender_query);
#endif
}
+void QXcbConnection::initializeXShape()
+{
+ const xcb_query_extension_reply_t *xshape_reply = xcb_get_extension_data(m_connection, &xcb_shape_id);
+ if (!xshape_reply || !xshape_reply->present)
+ return;
+
+ has_shape_extension = true;
+ xcb_shape_query_version_cookie_t cookie = xcb_shape_query_version(m_connection);
+ xcb_shape_query_version_reply_t *shape_query = xcb_shape_query_version_reply(m_connection,
+ cookie, NULL);
+ if (!shape_query) {
+ qWarning("QXcbConnection: Failed to initialize SHAPE extension");
+ } else if (shape_query->major_version > 1 || (shape_query->major_version == 1 && shape_query->minor_version >= 1)) {
+ // The input shape is the only thing added in SHAPE 1.1
+ has_input_shape = true;
+ }
+ free(shape_query);
+}
+
#if defined(XCB_USE_EGL)
bool QXcbConnection::hasEgl() const
{
@@ -1066,7 +1089,7 @@ void QXcbConnection::initializeDri2()
connect_cookie, NULL);
if (! connect || connect->driver_name_length + connect->device_name_length == 0) {
- qDebug() << "Failed to connect to dri2";
+ qWarning("QXcbConnection: Failed to connect to DRI2");
return;
}
@@ -1076,14 +1099,14 @@ void QXcbConnection::initializeDri2()
int fd = open(m_dri2_device_name.constData(), O_RDWR);
if (fd < 0) {
- qDebug() << "InitializeDri2: Could'nt open device << dri2DeviceName";
+ qWarning() << "QXcbConnection: Couldn't open DRI2 device" << m_dri2_device_name;
m_dri2_device_name = QByteArray();
return;
}
drm_magic_t magic;
if (drmGetMagic(fd, &magic)) {
- qDebug() << "Failed to get drmMagic";
+ qWarning("QXcbConnection: Failed to get drmMagic");
return;
}
@@ -1092,7 +1115,7 @@ void QXcbConnection::initializeDri2()
xcb_dri2_authenticate_reply_t *authenticate = xcb_dri2_authenticate_reply(m_connection,
authenticate_cookie, NULL);
if (authenticate == NULL || !authenticate->authenticated) {
- qWarning("DRI2: failed to authenticate");
+ qWarning("QXcbConnection: DRI2: failed to authenticate");
free(authenticate);
return;
}
@@ -1101,14 +1124,14 @@ void QXcbConnection::initializeDri2()
EGLDisplay display = eglGetDRMDisplayMESA(fd);
if (!display) {
- qWarning("failed to create display");
+ qWarning("QXcbConnection: Failed to create EGL display using DRI2");
return;
}
m_egl_display = display;
EGLint major,minor;
if (!eglInitialize(display, &major, &minor)) {
- qWarning("failed to initialize display");
+ qWarning("QXcbConnection: Failed to initialize EGL display using DRI2");
return;
}
}
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 7beb41bdd7..34943bfdef 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -354,6 +354,8 @@ public:
inline void setTime(xcb_timestamp_t t) { if (t > m_time) m_time = t; }
bool hasXFixes() const { return xfixes_first_event > 0; }
+ bool hasXShape() const { return has_shape_extension; }
+ bool hasInputShape() const { return has_input_shape; }
private slots:
void processXcbEvents();
@@ -363,6 +365,7 @@ private:
void sendConnectionEvent(QXcbAtom::Atom atom, uint id = 0);
void initializeXFixes();
void initializeXRender();
+ void initializeXShape();
#ifdef XCB_USE_DRI2
void initializeDri2();
#endif
@@ -429,6 +432,9 @@ private:
QVector<PeekFunc> m_peekFuncs;
uint32_t xfixes_first_event;
+
+ bool has_shape_extension;
+ bool has_input_shape;
};
#define DISPLAY_FROM_XCB(object) ((Display *)(object->connection()->xlib_display()))
diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp
index ed7c22b1e6..7e1b66829a 100644
--- a/src/plugins/platforms/xcb/qxcbcursor.cpp
+++ b/src/plugins/platforms/xcb/qxcbcursor.cpp
@@ -261,7 +261,7 @@ static const char * const cursorNames[] = {
};
QXcbCursor::QXcbCursor(QXcbConnection *conn, QXcbScreen *screen)
- : QXcbObject(conn), QPlatformCursor(screen), m_screen(screen)
+ : QXcbObject(conn), m_screen(screen)
{
if (cursorCount++)
return;
diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp
index e928fe2d0a..3aeaaba2d8 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.cpp
+++ b/src/plugins/platforms/xcb/qxcbdrag.cpp
@@ -52,6 +52,12 @@
#include <qevent.h>
#include <qguiapplication.h>
#include <qrect.h>
+#include <qpainter.h>
+
+#include <QtGui/QWindowSystemInterface>
+
+#include <QtPlatformSupport/private/qshapedpixmapdndwindow_p.h>
+#include <QtPlatformSupport/private/qsimpledrag_p.h>
QT_BEGIN_NAMESPACE
@@ -109,12 +115,11 @@ static xcb_window_t xdndProxy(QXcbConnection *c, xcb_window_t w)
return proxy;
}
-
-class QDropData : public QXcbMime
+class QXcbDropData : public QXcbMime
{
public:
- QDropData(QXcbDrag *d);
- ~QDropData();
+ QXcbDropData(QXcbDrag *d);
+ ~QXcbDropData();
protected:
bool hasFormat_sys(const QString &mimeType) const;
@@ -127,10 +132,9 @@ protected:
};
-QXcbDrag::QXcbDrag(QXcbConnection *c)
- : QXcbObject(c)
+QXcbDrag::QXcbDrag(QXcbConnection *c) : QXcbObject(c)
{
- dropData = new QDropData(this);
+ dropData = new QXcbDropData(this);
init();
heartbeat = -1;
@@ -147,13 +151,13 @@ void QXcbDrag::init()
{
currentWindow.clear();
+ accepted_drop_action = Qt::IgnoreAction;
+
xdnd_dragsource = XCB_NONE;
- last_target_accepted_action = Qt::IgnoreAction;
waiting_for_status = false;
current_target = XCB_NONE;
current_proxy_target = XCB_NONE;
- xdnd_dragging = false;
source_time = XCB_CURRENT_TIME;
target_time = XCB_CURRENT_TIME;
@@ -169,16 +173,17 @@ QMimeData *QXcbDrag::platformDropData()
void QXcbDrag::startDrag()
{
+ // #fixme enableEventFilter();
+
init();
heartbeat = startTimer(200);
- xdnd_dragging = true;
+
xcb_set_selection_owner(xcb_connection(), connection()->clipboard()->owner(),
atom(QXcbAtom::XdndSelection), connection()->time());
- QDragManager *manager = QDragManager::self();
- QStringList fmts = QXcbMime::formatsHelper(manager->dropData());
+ QStringList fmts = QXcbMime::formatsHelper(drag()->mimeData());
for (int i = 0; i < fmts.size(); ++i) {
QList<xcb_atom_t> atoms = QXcbMime::mimeAtomsForFormat(connection(), fmts.at(i));
for (int j = 0; j < atoms.size(); ++j) {
@@ -190,23 +195,16 @@ void QXcbDrag::startDrag()
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, connection()->clipboard()->owner(),
atom(QXcbAtom::XdndTypelist),
XCB_ATOM_ATOM, 32, drag_types.size(), (const void *)drag_types.constData());
-
- QPointF pos = QCursor::pos();
- QMouseEvent me(QEvent::MouseMove, pos, pos, pos, Qt::LeftButton,
- QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
- move(&me);
-
-// if (!QWidget::mouseGrabber())
-// manager->shapedPixmapWindow->grabMouse();
+ QBasicDrag::startDrag();
}
void QXcbDrag::endDrag()
{
- Q_ASSERT(heartbeat != -1);
- killTimer(heartbeat);
- heartbeat = -1;
-
- xdnd_dragging = false;
+ if (heartbeat != -1) {
+ killTimer(heartbeat);
+ heartbeat = -1;
+ }
+ QBasicDrag::endDrag();
}
static xcb_translate_coordinates_reply_t *
@@ -217,9 +215,29 @@ translateCoordinates(QXcbConnection *c, xcb_window_t from, xcb_window_t to, int
return xcb_translate_coordinates_reply(c->xcb_connection(), cookie, 0);
}
+static
+bool windowInteractsWithPosition(xcb_connection_t *connection, const QPoint & pos, xcb_window_t w, xcb_shape_sk_t shapeType)
+{
+ bool interacts = true;
+ xcb_shape_get_rectangles_reply_t *reply = xcb_shape_get_rectangles_reply(connection, xcb_shape_get_rectangles(connection, w, shapeType), NULL);
+ if (reply) {
+ xcb_rectangle_t *rectangles = xcb_shape_get_rectangles_rectangles(reply);
+ if (rectangles) {
+ interacts = false;
+ const int nRectangles = xcb_shape_get_rectangles_rectangles_length(reply);
+ for (int i = 0; !interacts && i < nRectangles; ++i) {
+ interacts = QRect(rectangles[i].x, rectangles[i].y, rectangles[i].width, rectangles[i].height).contains(pos);
+ }
+ }
+ free(reply);
+ }
+
+ return interacts;
+}
+
xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md)
{
- if (w == QDragManager::self()->shapedPixmapWindow->handle()->winId())
+ if (w == shapedPixmapWindow()->handle()->winId())
return 0;
if (md) {
@@ -244,22 +262,12 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md
bool isAware = reply && reply->type != XCB_NONE;
free(reply);
if (isAware) {
- xcb_xfixes_region_t region = xcb_generate_id(xcb_connection());
- xcb_xfixes_create_region_from_window(xcb_connection(), region, w, XCB_SHAPE_SK_BOUNDING);
- xcb_xfixes_fetch_region_reply_t *reply = xcb_xfixes_fetch_region_reply(xcb_connection(), xcb_xfixes_fetch_region(xcb_connection(), region), NULL);
- if (reply) {
- xcb_rectangle_t *rectangles = xcb_xfixes_fetch_region_rectangles(reply);
- if (rectangles) {
- windowContainsMouse = false;
- const int nRectangles = xcb_xfixes_fetch_region_rectangles_length(reply);
- for (int i = 0; !windowContainsMouse && i < nRectangles; ++i) {
- windowContainsMouse = QRect(rectangles[i].x, rectangles[i].y, rectangles[i].width, rectangles[i].height).contains(pos);
- }
- }
- free(reply);
- }
- xcb_xfixes_destroy_region(xcb_connection(), region);
-
+ // When ShapeInput and ShapeBounding are not set they return a single rectangle with the geometry of the window, this is why we
+ // need to check both here so that in the case one is set and the other is not we still get the correct result.
+ if (connection()->hasInputShape())
+ windowContainsMouse = windowInteractsWithPosition(xcb_connection(), pos, w, XCB_SHAPE_SK_INPUT);
+ if (windowContainsMouse && connection()->hasXShape())
+ windowContainsMouse = windowInteractsWithPosition(xcb_connection(), pos, w, XCB_SHAPE_SK_BOUNDING);
if (windowContainsMouse)
return w;
}
@@ -296,9 +304,7 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md
void QXcbDrag::move(const QMouseEvent *me)
{
- DEBUG() << "QDragManager::move enter" << me->globalPos();
-
- // ###
+ QBasicDrag::move(me);
QPoint globalPos = me->globalPos();
if (source_sameanswer.contains(globalPos) && source_sameanswer.isValid())
@@ -337,15 +343,13 @@ void QXcbDrag::move(const QMouseEvent *me)
::translateCoordinates(connection(), rootwin, rootwin, globalPos.x(), globalPos.y());
if (!translate)
return;
+
xcb_window_t target = translate->child;
int lx = translate->dst_x;
int ly = translate->dst_y;
free (translate);
- if (target == rootwin) {
- // Ok.
- } else if (target) {
- //me
+ if (target && target != rootwin) {
xcb_window_t src = rootwin;
while (target != 0) {
DNDDEBUG << "checking target for XdndAware" << target << lx << ly;
@@ -376,7 +380,7 @@ void QXcbDrag::move(const QMouseEvent *me)
target = child;
}
- if (!target || target == QDragManager::self()->shapedPixmapWindow->handle()->winId()) {
+ if (!target || target == shapedPixmapWindow()->handle()->winId()) {
DNDDEBUG << "need to find real window";
target = findRealWindow(globalPos, rootwin, 6);
DNDDEBUG << "real window found" << target;
@@ -393,9 +397,6 @@ void QXcbDrag::move(const QMouseEvent *me)
target = rootwin;
}
- DNDDEBUG << "and the final target is " << target;
- DNDDEBUG << "the widget w is" << (w ? w->window() : 0);
-
xcb_window_t proxy_target = xdndProxy(connection(), target);
if (!proxy_target)
proxy_target = target;
@@ -414,7 +415,6 @@ void QXcbDrag::move(const QMouseEvent *me)
free(reply);
}
- DEBUG() << "target=" << target << "current_target=" << current_target;
if (target != current_target) {
if (current_target)
send_leave();
@@ -447,11 +447,10 @@ void QXcbDrag::move(const QMouseEvent *me)
waiting_for_status = false;
}
}
+
if (waiting_for_status)
return;
- QDragManager *m = QDragManager::self();
-
if (target) {
waiting_for_status = true;
@@ -465,28 +464,21 @@ void QXcbDrag::move(const QMouseEvent *me)
move.data.data32[1] = 0; // flags
move.data.data32[2] = (globalPos.x() << 16) + globalPos.y();
move.data.data32[3] = connection()->time();
- move.data.data32[4] = toXdndAction(m->defaultAction(m->dragPrivate()->possible_actions, QGuiApplication::keyboardModifiers()));
+ move.data.data32[4] = toXdndAction(defaultAction(currentDrag()->supportedActions(), QGuiApplication::keyboardModifiers()));
DEBUG() << "sending Xdnd position source=" << move.data.data32[0] << "target=" << move.window;
source_time = connection()->time();
if (w)
- handle_xdnd_position(w->window(), &move, false);
+ handle_xdnd_position(w->window(), &move);
else
xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&move);
- } else {
- if (m->willDrop) {
- m->willDrop = false;
- }
}
- m->updateCursor();
- DEBUG() << "QDragManager::move leave";
}
-void QXcbDrag::drop(const QMouseEvent *)
+void QXcbDrag::drop(const QMouseEvent *event)
{
- endDrag();
-
+ QBasicDrag::drop(event);
if (!current_target)
return;
@@ -500,14 +492,13 @@ void QXcbDrag::drop(const QMouseEvent *)
drop.data.data32[2] = connection()->time();
drop.data.data32[3] = 0;
- drop.data.data32[4] = 0;
+ drop.data.data32[4] = currentDrag()->supportedActions();
QXcbWindow *w = connection()->platformWindowFromId(current_proxy_target);
if (w && (w->window()->windowType() == Qt::Desktop) /*&& !w->acceptDrops()*/)
w = 0;
- QDragManager *manager = QDragManager::self();
Transaction t = {
connection()->time(),
@@ -515,21 +506,22 @@ void QXcbDrag::drop(const QMouseEvent *)
current_proxy_target,
(w ? w->window() : 0),
// current_embedding_widget,
- manager->object
+ currentDrag()
};
transactions.append(t);
restartDropExpiryTimer();
- if (w)
- handleDrop(w->window(), &drop, false);
- else
+ if (w) {
+ handleDrop(w->window(), &drop);
+ } else {
xcb_send_event(xcb_connection(), false, current_proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&drop);
+ }
current_target = 0;
current_proxy_target = 0;
source_time = 0;
// current_embedding_widget = 0;
- manager->object = 0;
+ // #fixme resetDndState(false);
}
Qt::DropAction QXcbDrag::toDropAction(xcb_atom_t a) const
@@ -719,7 +711,7 @@ void QXcbDrag::handleEnter(QWindow *window, const xcb_client_message_event_t *ev
DEBUG() << " " << connection()->atomName(xdnd_types.at(i));
}
-void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t *e, bool passive)
+void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t *e)
{
QPoint p((e->data.data32[2] & 0xffff0000) >> 16, e->data.data32[2] & 0x0000ffff);
Q_ASSERT(w);
@@ -727,11 +719,7 @@ void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t
p -= geometry.topLeft();
- // ####
-// if (!passive && checkEmbedded(w, e))
-// return;
-
- if (!w || (/*!w->acceptDrops() &&*/ (w->windowType() == Qt::Desktop)))
+ if (!w || (w->windowType() == Qt::Desktop))
return;
if (e->data.data32[0] != xdnd_dragsource) {
@@ -739,12 +727,27 @@ void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t
return;
}
+ currentPosition = p;
+ currentWindow = w;
+
// timestamp from the source
- if (e->data.data32[3] != XCB_NONE)
- target_time /*= X11->userTime*/ = e->data.data32[3];
+ if (e->data.data32[3] != XCB_NONE) {
+ target_time = e->data.data32[3];
+ }
- QDragManager *manager = QDragManager::self();
- QMimeData *dropData = manager->dropData();
+ QMimeData *dropData = 0;
+ Qt::DropActions supported_actions = Qt::IgnoreAction;
+ if (currentDrag()) {
+ dropData = currentDrag()->mimeData();
+ supported_actions = currentDrag()->supportedActions();
+ } else {
+ dropData = platformDropData();
+ supported_actions = Qt::DropActions(toDropAction(e->data.data32[4]));
+ }
+
+ QPlatformDragQtResponse qt_response = QWindowSystemInterface::handleDrag(w,dropData,p,supported_actions);
+ QRect answerRect(p + geometry.topLeft(), QSize(1,1));
+ answerRect = qt_response.answerRect().translated(geometry.topLeft()).intersected(geometry);
xcb_client_message_event_t response;
response.response_type = XCB_CLIENT_MESSAGE;
@@ -752,83 +755,33 @@ void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t
response.format = 32;
response.type = atom(QXcbAtom::XdndStatus);
response.data.data32[0] = xcb_window(w);
- response.data.data32[1] = 0; // flags
+ response.data.data32[1] = qt_response.isAccepted(); // flags
response.data.data32[2] = 0; // x, y
response.data.data32[3] = 0; // w, h
- response.data.data32[4] = 0; // action
+ response.data.data32[4] = toXdndAction(qt_response.acceptedAction()); // action
- if (!passive) { // otherwise just reject
- QRect answerRect(p + geometry.topLeft(), QSize(1,1));
- if (manager->object) {
- manager->possible_actions = manager->dragPrivate()->possible_actions;
- } else {
- manager->possible_actions = Qt::DropActions(toDropAction(e->data.data32[4]));
- }
- QDragMoveEvent me(p, manager->possible_actions, dropData,
- QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
-
- Qt::DropAction accepted_action = Qt::IgnoreAction;
-
- currentPosition = p;
-
- if (w != currentWindow.data()) {
- if (currentWindow) {
- QDragLeaveEvent e;
- QGuiApplication::sendEvent(currentWindow.data(), &e);
- }
- currentWindow = w;
-
- last_target_accepted_action = Qt::IgnoreAction;
- QDragEnterEvent de(p, manager->possible_actions, dropData,
- QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
- QGuiApplication::sendEvent(w, &de);
- if (de.isAccepted() && de.dropAction() != Qt::IgnoreAction)
- last_target_accepted_action = de.dropAction();
- }
- DEBUG() << "qt_handle_xdnd_position action=" << connection()->atomName(e->data.data32[4]);
+ if (answerRect.left() < 0)
+ answerRect.setLeft(0);
+ if (answerRect.right() > 4096)
+ answerRect.setRight(4096);
+ if (answerRect.top() < 0)
+ answerRect.setTop(0);
+ if (answerRect.bottom() > 4096)
+ answerRect.setBottom(4096);
+ if (answerRect.width() < 0)
+ answerRect.setWidth(0);
+ if (answerRect.height() < 0)
+ answerRect.setHeight(0);
- if (last_target_accepted_action != Qt::IgnoreAction) {
- me.setDropAction(last_target_accepted_action);
- me.accept();
- }
- QGuiApplication::sendEvent(w, &me);
- if (me.isAccepted()) {
- response.data.data32[1] = 1; // yes
- accepted_action = me.dropAction();
- last_target_accepted_action = accepted_action;
- } else {
- response.data.data32[0] = 0;
- last_target_accepted_action = Qt::IgnoreAction;
- }
- answerRect = me.answerRect().translated(geometry.topLeft()).intersected(geometry);
-
- if (answerRect.left() < 0)
- answerRect.setLeft(0);
- if (answerRect.right() > 4096)
- answerRect.setRight(4096);
- if (answerRect.top() < 0)
- answerRect.setTop(0);
- if (answerRect.bottom() > 4096)
- answerRect.setBottom(4096);
- if (answerRect.width() < 0)
- answerRect.setWidth(0);
- if (answerRect.height() < 0)
- answerRect.setHeight(0);
-
-// response.data.data32[2] = (answerRect.x() << 16) + answerRect.y();
-// response.data.data32[3] = (answerRect.width() << 16) + answerRect.height();
- response.data.data32[4] = toXdndAction(accepted_action);
- }
+ response.data.data32[4] = toXdndAction(qt_response.acceptedAction());
// reset
target_time = XCB_CURRENT_TIME;
- DEBUG() << "sending XdndStatus" << (xdnd_dragsource == connection()->clipboard()->owner()) << xdnd_dragsource
- << response.data.data32[1] << connection()->atomName(response.data.data32[4]);
if (xdnd_dragsource == connection()->clipboard()->owner())
- handle_xdnd_status(&response, passive);
+ handle_xdnd_status(&response);
else
Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xdnd_dragsource,
XCB_EVENT_MASK_NO_EVENT, (const char *)&response));
@@ -850,7 +803,7 @@ namespace
};
}
-void QXcbDrag::handlePosition(QWindow * w, const xcb_client_message_event_t *event, bool passive)
+void QXcbDrag::handlePosition(QWindow * w, const xcb_client_message_event_t *event)
{
xcb_client_message_event_t *lastEvent = const_cast<xcb_client_message_event_t *>(event);
xcb_generic_event_t *nextEvent;
@@ -861,19 +814,28 @@ void QXcbDrag::handlePosition(QWindow * w, const xcb_client_message_event_t *eve
lastEvent = (xcb_client_message_event_t *)nextEvent;
}
- handle_xdnd_position(w, lastEvent, passive);
+ handle_xdnd_position(w, lastEvent);
if (lastEvent != event)
free(lastEvent);
}
-void QXcbDrag::handle_xdnd_status(const xcb_client_message_event_t *event, bool)
+void QXcbDrag::handle_xdnd_status(const xcb_client_message_event_t *event)
{
DEBUG("xdndHandleStatus");
+ waiting_for_status = false;
// ignore late status messages
if (event->data.data32[0] && event->data.data32[0] != current_proxy_target)
return;
- Qt::DropAction newAction = (event->data.data32[1] & 0x1) ? toDropAction(event->data.data32[4]) : Qt::IgnoreAction;
+ const bool dropPossible = event->data.data32[1];
+ setCanDrop(dropPossible);
+
+ if (dropPossible) {
+ accepted_drop_action = toDropAction(event->data.data32[4]);
+ updateCursor(accepted_drop_action);
+ } else {
+ updateCursor(Qt::IgnoreAction);
+ }
if ((event->data.data32[1] & 2) == 0) {
QPoint p((event->data.data32[2] & 0xffff0000) >> 16, event->data.data32[2] & 0x0000ffff);
@@ -882,18 +844,9 @@ void QXcbDrag::handle_xdnd_status(const xcb_client_message_event_t *event, bool)
} else {
source_sameanswer = QRect();
}
- QDragManager *manager = QDragManager::self();
- manager->willDrop = (event->data.data32[1] & 0x1);
- if (manager->global_accepted_action != newAction) {
- manager->global_accepted_action = newAction;
- manager->emitActionChanged(newAction);
- }
- DEBUG() << "willDrop=" << manager->willDrop << "action=" << newAction;
- manager->updateCursor();
- waiting_for_status = false;
}
-void QXcbDrag::handleStatus(const xcb_client_message_event_t *event, bool passive)
+void QXcbDrag::handleStatus(const xcb_client_message_event_t *event)
{
if (event->window != connection()->clipboard()->owner())
return;
@@ -907,13 +860,13 @@ void QXcbDrag::handleStatus(const xcb_client_message_event_t *event, bool passiv
lastEvent = (xcb_client_message_event_t *)nextEvent;
}
- handle_xdnd_status(lastEvent, passive);
+ handle_xdnd_status(lastEvent);
if (lastEvent != event)
free(lastEvent);
DEBUG("xdndHandleStatus end");
}
-void QXcbDrag::handleLeave(QWindow *w, const xcb_client_message_event_t *event, bool /*passive*/)
+void QXcbDrag::handleLeave(QWindow *w, const xcb_client_message_event_t *event)
{
DEBUG("xdnd leave");
if (!currentWindow || w != currentWindow.data())
@@ -931,8 +884,8 @@ void QXcbDrag::handleLeave(QWindow *w, const xcb_client_message_event_t *event,
DEBUG("xdnd drag leave from unexpected source (%x not %x", event->data.data32[0], xdnd_dragsource);
}
- QDragLeaveEvent e;
- QGuiApplication::sendEvent(currentWindow.data(), &e);
+ QWindowSystemInterface::handleDrag(w,0,QPoint(),Qt::IgnoreAction);
+ updateAction(Qt::IgnoreAction);
xdnd_dragsource = 0;
xdnd_types.clear();
@@ -944,7 +897,6 @@ void QXcbDrag::send_leave()
if (!current_target)
return;
- QDragManager *manager = QDragManager::self();
xcb_client_message_event_t leave;
leave.response_type = XCB_CLIENT_MESSAGE;
@@ -963,24 +915,18 @@ void QXcbDrag::send_leave()
w = 0;
if (w)
- handleLeave(w->window(), (const xcb_client_message_event_t *)&leave, false);
+ handleLeave(w->window(), (const xcb_client_message_event_t *)&leave);
else
xcb_send_event(xcb_connection(), false,current_proxy_target,
XCB_EVENT_MASK_NO_EVENT, (const char *)&leave);
- // reset the drag manager state
- manager->willDrop = false;
- if (manager->global_accepted_action != Qt::IgnoreAction)
- manager->emitActionChanged(Qt::IgnoreAction);
- manager->global_accepted_action = Qt::IgnoreAction;
- manager->updateCursor();
current_target = 0;
current_proxy_target = 0;
source_time = XCB_CURRENT_TIME;
waiting_for_status = false;
}
-void QXcbDrag::handleDrop(QWindow *, const xcb_client_message_event_t *event, bool passive)
+void QXcbDrag::handleDrop(QWindow *, const xcb_client_message_event_t *event)
{
DEBUG("xdndHandleDrop");
if (!currentWindow) {
@@ -988,16 +934,8 @@ void QXcbDrag::handleDrop(QWindow *, const xcb_client_message_event_t *event, bo
return; // sanity
}
- // ###
-// if (!passive && checkEmbedded(currentWindow, xe)){
-// current_embedding_widget = 0;
-// xdnd_dragsource = 0;
-// currentWindow = 0;
-// return;
-// }
const uint32_t *l = event->data.data32;
- QDragManager *manager = QDragManager::self();
DEBUG("xdnd drop");
if (l[0] != xdnd_dragsource) {
@@ -1009,50 +947,39 @@ void QXcbDrag::handleDrop(QWindow *, const xcb_client_message_event_t *event, bo
if (l[2] != 0)
target_time = /*X11->userTime =*/ l[2];
- if (!passive) {
- // this could be a same-application drop, just proxied due to
- // some XEMBEDding, so try to find the real QMimeData used
- // based on the timestamp for this drop.
- QMimeData *dropData = 0;
- // ###
-// int at = findXdndDropTransactionByTime(target_time);
-// if (at != -1)
-// dropData = QDragManager::dragPrivate(X11->dndDropTransactions.at(at).object)->data;
- // if we can't find it, then use the data in the drag manager
- if (!dropData)
- dropData = manager->dropData();
-
- // Drop coming from another app? Update keyboard modifiers.
-// if (!qt_xdnd_dragging) {
-// QApplicationPrivate::modifier_buttons = currentKeyboardModifiers();
-// }
-
- QDropEvent de(currentPosition, manager->possible_actions, dropData,
- QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
- QGuiApplication::sendEvent(currentWindow.data(), &de);
- if (!de.isAccepted()) {
- // Ignore a failed drag
- manager->global_accepted_action = Qt::IgnoreAction;
- } else {
- manager->global_accepted_action = de.dropAction();
- }
- xcb_client_message_event_t finished;
- finished.response_type = XCB_CLIENT_MESSAGE;
- finished.window = xdnd_dragsource;
- finished.format = 32;
- finished.type = atom(QXcbAtom::XdndFinished);
- DNDDEBUG << "xdndHandleDrop"
- << "currentWindow" << currentWindow.data()
- << (currentWindow ? xcb_window(currentWindow.data()) : 0);
- finished.data.data32[0] = currentWindow ? xcb_window(currentWindow.data()) : XCB_NONE;
- finished.data.data32[1] = de.isAccepted() ? 1 : 0; // flags
- finished.data.data32[2] = toXdndAction(manager->global_accepted_action);
- Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xdnd_dragsource,
- XCB_EVENT_MASK_NO_EVENT, (char *)&finished));
+ // this could be a same-application drop, just proxied due to
+ // some XEMBEDding, so try to find the real QMimeData used
+ // based on the timestamp for this drop.
+ Qt::DropActions supported_drop_actions(l[4]);
+ QMimeData *dropData = 0;
+ if (currentDrag()) {
+ dropData = currentDrag()->mimeData();
} else {
- QDragLeaveEvent e;
- QGuiApplication::sendEvent(currentWindow.data(), &e);
+ dropData = platformDropData();
}
+
+ if (!dropData)
+ return;
+ // ###
+ // int at = findXdndDropTransactionByTime(target_time);
+ // if (at != -1)
+ // dropData = QDragManager::dragPrivate(X11->dndDropTransactions.at(at).object)->data;
+ // if we can't find it, then use the data in the drag manager
+
+ QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(currentWindow.data(),dropData,currentPosition,supported_drop_actions);
+ setExecutedDropAction(response.acceptedAction());
+
+ xcb_client_message_event_t finished;
+ finished.response_type = XCB_CLIENT_MESSAGE;
+ finished.window = xdnd_dragsource;
+ finished.format = 32;
+ finished.type = atom(QXcbAtom::XdndFinished);
+ finished.data.data32[0] = currentWindow ? xcb_window(currentWindow.data()) : XCB_NONE;
+ finished.data.data32[1] = response.isAccepted(); // flags
+ finished.data.data32[2] = toXdndAction(response.acceptedAction());
+ Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xdnd_dragsource,
+ XCB_EVENT_MASK_NO_EVENT, (char *)&finished));
+
xdnd_dragsource = 0;
currentWindow.clear();
waiting_for_status = false;
@@ -1062,7 +989,7 @@ void QXcbDrag::handleDrop(QWindow *, const xcb_client_message_event_t *event, bo
}
-void QXcbDrag::handleFinished(const xcb_client_message_event_t *event, bool)
+void QXcbDrag::handleFinished(const xcb_client_message_event_t *event)
{
DEBUG("xdndHandleFinished");
if (event->window != connection()->clipboard()->owner())
@@ -1099,8 +1026,8 @@ void QXcbDrag::handleFinished(const xcb_client_message_event_t *event, bool)
// current_target = 0;
// current_proxy_target = 0;
- if (t.object)
- t.object->deleteLater();
+ if (t.drag)
+ t.drag->deleteLater();
// current_target = target;
// current_proxy_target = proxy_target;
@@ -1126,7 +1053,7 @@ void QXcbDrag::timerEvent(QTimerEvent* e)
// dnd within the same process, don't delete these
continue;
}
- t.object->deleteLater();
+ t.drag->deleteLater();
transactions.removeAt(i--);
}
@@ -1138,12 +1065,9 @@ void QXcbDrag::timerEvent(QTimerEvent* e)
void QXcbDrag::cancel()
{
DEBUG("QXcbDrag::cancel");
- endDrag();
-
+ QBasicDrag::cancel();
if (current_target)
send_leave();
-
- current_target = 0;
}
@@ -1157,14 +1081,11 @@ void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event
notify.property = XCB_NONE;
notify.time = event->time;
- QDragManager *manager = QDragManager::self();
- QDrag *currentObject = manager->object;
-
// which transaction do we use? (note: -2 means use current manager->object)
int at = -1;
// figure out which data the requestor is really interested in
- if (manager->object && event->time == source_time) {
+ if (currentDrag() && event->time == source_time) {
// requestor wants the current drag data
at = -2;
} else {
@@ -1188,20 +1109,18 @@ void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event
// }
// }
}
+
+ QDrag *transactionDrag = 0;
if (at >= 0) {
restartDropExpiryTimer();
- // use the drag object from an XdndDrop tansaction
- manager->object = transactions.at(at).object;
- } else if (at != -2) {
- // no transaction found, we'll have to reject the request
- manager->object = 0;
+ transactionDrag = transactions.at(at).drag;
}
- if (manager->object) {
+ if (transactionDrag) {
xcb_atom_t atomFormat = event->target;
int dataFormat = 0;
QByteArray data;
- if (QXcbMime::mimeDataForAtom(connection(), event->target, manager->dragPrivate()->data,
+ if (QXcbMime::mimeDataForAtom(connection(), event->target, transactionDrag->mimeData(),
&data, &atomFormat, &dataFormat)) {
int dataSize = data.size() / (dataFormat / 8);
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, event->requestor, event->property,
@@ -1211,9 +1130,6 @@ void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event
}
}
- // reset manager->object in case we modified it above
- manager->object = currentObject;
-
xcb_send_event(xcb_connection(), false, event->requestor, XCB_EVENT_MASK_NO_EVENT, (const char *)&notify);
}
@@ -1268,20 +1184,17 @@ bool QXcbDrag::dndEnable(QXcbWindow *w, bool on)
}
}
-
-
-
-QDropData::QDropData(QXcbDrag *d)
+QXcbDropData::QXcbDropData(QXcbDrag *d)
: QXcbMime(),
drag(d)
{
}
-QDropData::~QDropData()
+QXcbDropData::~QXcbDropData()
{
}
-QVariant QDropData::retrieveData_sys(const QString &mimetype, QVariant::Type requestedType) const
+QVariant QXcbDropData::retrieveData_sys(const QString &mimetype, QVariant::Type requestedType) const
{
QByteArray mime = mimetype.toLatin1();
QVariant data = /*X11->motifdnd_active
@@ -1290,17 +1203,16 @@ QVariant QDropData::retrieveData_sys(const QString &mimetype, QVariant::Type req
return data;
}
-QVariant QDropData::xdndObtainData(const QByteArray &format, QVariant::Type requestedType) const
+QVariant QXcbDropData::xdndObtainData(const QByteArray &format, QVariant::Type requestedType) const
{
QByteArray result;
- QDragManager *manager = QDragManager::self();
QXcbConnection *c = drag->connection();
QXcbWindow *xcb_window = c->platformWindowFromId(drag->xdnd_dragsource);
- if (xcb_window && manager->object && xcb_window->window()->windowType() != Qt::Desktop) {
- QDragPrivate *o = manager->dragPrivate();
- if (o->data->hasFormat(QLatin1String(format)))
- result = o->data->data(QLatin1String(format));
+ if (xcb_window && drag->currentDrag() && xcb_window->window()->windowType() != Qt::Desktop) {
+ QMimeData *data = drag->currentDrag()->mimeData();
+ if (data->hasFormat(QLatin1String(format)))
+ result = data->data(QLatin1String(format));
return result;
}
@@ -1320,12 +1232,12 @@ QVariant QDropData::xdndObtainData(const QByteArray &format, QVariant::Type requ
}
-bool QDropData::hasFormat_sys(const QString &format) const
+bool QXcbDropData::hasFormat_sys(const QString &format) const
{
return formats().contains(format);
}
-QStringList QDropData::formats_sys() const
+QStringList QXcbDropData::formats_sys() const
{
QStringList formats;
// if (X11->motifdnd_active) {
diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h
index e32e630548..710a07a5a4 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.h
+++ b/src/plugins/platforms/xcb/qxcbdrag.h
@@ -43,6 +43,7 @@
#define QXCBDRAG_H
#include <qplatformdrag_qpa.h>
+#include <QtPlatformSupport/private/qsimpledrag_p.h>
#include <qxcbobject.h>
#include <xcb/xcb.h>
#include <qlist.h>
@@ -51,17 +52,23 @@
#include <qsharedpointer.h>
#include <qvector.h>
+#include <qpixmap.h>
+#include <qbackingstore.h>
+
+#include <QtCore/QDebug>
+
QT_BEGIN_NAMESPACE
class QMouseEvent;
class QWindow;
class QXcbConnection;
class QXcbWindow;
-class QDropData;
+class QXcbDropData;
class QXcbScreen;
class QDrag;
+class QShapedPixmapWindow;
-class QXcbDrag : public QObject, public QXcbObject, public QPlatformDrag
+class QXcbDrag : public QXcbObject, public QBasicDrag
{
public:
QXcbDrag(QXcbConnection *c);
@@ -69,35 +76,36 @@ public:
virtual QMimeData *platformDropData();
-// virtual Qt::DropAction drag(QDrag *);
- virtual void startDrag();
- virtual void cancel();
- virtual void move(const QMouseEvent *me);
- virtual void drop(const QMouseEvent *me);
+ void startDrag();
+ void cancel();
+ void move(const QMouseEvent *me);
+ void drop(const QMouseEvent *me);
void endDrag();
void handleEnter(QWindow *window, const xcb_client_message_event_t *event);
- void handlePosition(QWindow *w, const xcb_client_message_event_t *event, bool passive);
- void handleLeave(QWindow *w, const xcb_client_message_event_t *event, bool /*passive*/);
- void handleDrop(QWindow *, const xcb_client_message_event_t *event, bool passive);
+ void handlePosition(QWindow *w, const xcb_client_message_event_t *event);
+ void handleLeave(QWindow *w, const xcb_client_message_event_t *event);
+ void handleDrop(QWindow *, const xcb_client_message_event_t *event);
- void handleStatus(const xcb_client_message_event_t *event, bool passive);
+ void handleStatus(const xcb_client_message_event_t *event);
void handleSelectionRequest(const xcb_selection_request_event_t *event);
- void handleFinished(const xcb_client_message_event_t *event, bool passive);
+ void handleFinished(const xcb_client_message_event_t *event);
bool dndEnable(QXcbWindow *win, bool on);
+ void updatePixmap();
+
protected:
void timerEvent(QTimerEvent* e);
private:
- friend class QDropData;
+ friend class QXcbDropData;
void init();
- void handle_xdnd_position(QWindow *w, const xcb_client_message_event_t *event, bool passive);
- void handle_xdnd_status(const xcb_client_message_event_t *event, bool);
+ void handle_xdnd_position(QWindow *w, const xcb_client_message_event_t *event);
+ void handle_xdnd_status(const xcb_client_message_event_t *event);
void send_leave();
Qt::DropAction toDropAction(xcb_atom_t atom) const;
@@ -106,7 +114,8 @@ private:
QWeakPointer<QWindow> currentWindow;
QPoint currentPosition;
- QDropData *dropData;
+ QXcbDropData *dropData;
+ Qt::DropAction accepted_drop_action;
QWindow *desktop_proxy;
@@ -118,7 +127,6 @@ private:
xcb_timestamp_t target_time;
xcb_timestamp_t source_time;
- Qt::DropAction last_target_accepted_action;
// rectangle in which the answer will be the same
QRect source_sameanswer;
@@ -132,7 +140,6 @@ private:
QXcbScreen *current_screen;
int heartbeat;
- bool xdnd_dragging;
QVector<xcb_atom_t> drag_types;
@@ -143,7 +150,7 @@ private:
xcb_window_t proxy_target;
QWindow *targetWindow;
// QWidget *embedding_widget;
- QDrag *object;
+ QDrag *drag;
};
QList<Transaction> transactions;
diff --git a/src/plugins/platforms/xcb/qxcbimage.cpp b/src/plugins/platforms/xcb/qxcbimage.cpp
index 13ff8ab2a5..12979bfb68 100644
--- a/src/plugins/platforms/xcb/qxcbimage.cpp
+++ b/src/plugins/platforms/xcb/qxcbimage.cpp
@@ -201,7 +201,7 @@ xcb_cursor_t qt_xcb_createCursorXRender(QXcbScreen *screen, const QImage &image,
formatsCookie,
&error);
if (!formatsReply || error) {
- qWarning("createCursorXRender: query_pict_formats failed");
+ qWarning("qt_xcb_createCursorXRender: query_pict_formats failed");
free(formatsReply);
free(error);
return XCB_NONE;
@@ -209,7 +209,7 @@ xcb_cursor_t qt_xcb_createCursorXRender(QXcbScreen *screen, const QImage &image,
xcb_render_pictforminfo_t *fmt = xcb_render_util_find_standard_format(formatsReply,
XCB_PICT_STANDARD_ARGB_32);
if (!fmt) {
- qWarning("createCursorXRender: Failed to find format PICT_STANDARD_ARGB_32");
+ qWarning("qt_xcb_createCursorXRender: Failed to find format PICT_STANDARD_ARGB_32");
free(formatsReply);
return XCB_NONE;
}
@@ -221,13 +221,13 @@ xcb_cursor_t qt_xcb_createCursorXRender(QXcbScreen *screen, const QImage &image,
XCB_IMAGE_ORDER_MSB_FIRST,
0, 0, 0);
if (!xi) {
- qWarning("createCursorXRender: xcb_image_create failed");
+ qWarning("qt_xcb_createCursorXRender: xcb_image_create failed");
free(formatsReply);
return XCB_NONE;
}
xi->data = (uint8_t *) malloc(xi->stride * h);
if (!xi->data) {
- qWarning("createCursorXRender: Failed to malloc() image data");
+ qWarning("qt_xcb_createCursorXRender: Failed to malloc() image data");
xcb_image_destroy(xi);
free(formatsReply);
return XCB_NONE;
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index 98f69e9e16..fe33bd7153 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -101,7 +101,9 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters)
m_connections << new QXcbConnection(m_nativeInterface.data());
for (int i = 0; i < parameters.size() - 1; i += 2) {
- qDebug() << parameters.at(i) << parameters.at(i+1);
+#ifdef Q_XCB_DEBUG
+ qDebug() << "QXcbIntegration: Connecting to additional display: " << parameters.at(i) << parameters.at(i+1);
+#endif
QString display = parameters.at(i) + ':' + parameters.at(i+1);
m_connections << new QXcbConnection(m_nativeInterface.data(), display.toAscii().constData());
}
@@ -185,7 +187,7 @@ QPlatformOpenGLContext *QXcbIntegration::createPlatformOpenGLContext(QOpenGLCont
#elif defined(XCB_USE_DRI2)
return new QDri2Context(context->format(), context->shareHandle());
#endif
- qWarning("Cannot create platform GL context, none of GLX, EGL, DRI2 is enabled");
+ qWarning("QXcbIntegration: Cannot create platform OpenGL context, none of GLX, EGL, or DRI2 are enabled");
return 0;
}
#endif
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index b682b87bc3..03156dc544 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -935,7 +935,7 @@ void QXcbKeyboard::setupModifiers()
xcb_get_modifier_mapping_reply_t *modMapReply =
xcb_get_modifier_mapping_reply(conn, modMapCookie, &error);
if (error) {
- qWarning("xcb keyboard: failed to get modifier mapping");
+ qWarning("QXcbKeyboard: failed to get modifier mapping");
free(error);
return;
}
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
index 406f9c24bd..f56072f9d7 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
@@ -137,7 +137,7 @@ QPlatformNativeInterface::EventFilter QXcbNativeInterface::setEventFilter(const
if (eventType == QByteArrayLiteral("xcb_generic_event_t"))
type = GenericEventFilter;
if (type == -1) {
- qWarning("%s: Attempt to set invalid event filter type '%s'.",
+ qWarning("QXcbNativeInterface: %s: Attempt to set invalid event filter type '%s'.",
Q_FUNC_INFO, eventType.constData());
return 0;
}
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index c93b4863e1..8b66ef4603 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -55,6 +55,7 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int num
, m_screen(screen)
, m_number(number)
{
+#ifdef Q_XCB_DEBUG
qDebug();
qDebug("Information of screen %d:", screen->root);
qDebug(" width.........: %d", screen->width_in_pixels);
@@ -63,6 +64,7 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int num
qDebug(" white pixel...: %x", screen->white_pixel);
qDebug(" black pixel...: %x", screen->black_pixel);
qDebug();
+#endif
const quint32 mask = XCB_CW_EVENT_MASK;
const quint32 values[] = {
@@ -93,7 +95,9 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int num
atom(QXcbAtom::UTF8_STRING), 0, 1024), &error);
if (windowManagerReply && windowManagerReply->format == 8 && windowManagerReply->type == atom(QXcbAtom::UTF8_STRING)) {
m_windowManagerName = QString::fromUtf8((const char *)xcb_get_property_value(windowManagerReply), xcb_get_property_value_length(windowManagerReply));
+#ifdef Q_XCB_DEBUG
qDebug("Running window manager: %s", qPrintable(m_windowManagerName));
+#endif
} else if (error) {
connection->handleXcbError(error);
free(error);
@@ -233,6 +237,11 @@ QSizeF QXcbScreen::physicalSize() const
return QSizeF(m_screen->width_in_millimeters, m_screen->height_in_millimeters);
}
+QPlatformCursor *QXcbScreen::cursor() const
+{
+ return m_cursor;
+}
+
int QXcbScreen::screenNumber() const
{
return m_number;
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index 870d4d5662..ac4ecb1c8d 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -68,6 +68,7 @@ public:
int depth() const;
QImage::Format format() const;
QSizeF physicalSize() const;
+ QPlatformCursor *cursor() const;
int screenNumber() const;
diff --git a/src/plugins/platforms/xcb/qxcbsharedbuffermanager.cpp b/src/plugins/platforms/xcb/qxcbsharedbuffermanager.cpp
index f9e388b662..8bd3aea259 100644
--- a/src/plugins/platforms/xcb/qxcbsharedbuffermanager.cpp
+++ b/src/plugins/platforms/xcb/qxcbsharedbuffermanager.cpp
@@ -581,7 +581,7 @@ QXcbSharedBufferManager::Buffer *QXcbSharedBufferManager::allocateBuffer(int wid
bool ok = buffer->buffer->create(buffer->width * buffer->height * buffer->bytesPerPixel,
QSharedMemory::ReadWrite);
if (!ok) {
- qWarning("SharedBufferManager::findAvailableBuffer: Can't create new buffer (%s)",
+ qWarning("QXcbSharedBufferManager::findAvailableBuffer: Can't create new buffer (%s)",
qPrintable(buffer->buffer->errorString()));
delete buffer;
return 0;
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 067cb775c8..542d7ab69f 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -369,6 +369,14 @@ void QXcbWindow::destroy()
if (m_syncCounter && m_screen->syncRequestSupported())
Q_XCB_CALL(xcb_sync_destroy_counter(xcb_connection(), m_syncCounter));
if (m_window) {
+ if (m_netWmUserTimeWindow) {
+ xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_USER_TIME_WINDOW));
+ // Some window managers, like metacity, do XSelectInput on the _NET_WM_USER_TIME_WINDOW window,
+ // without trapping BadWindow (which crashes when the user time window is destroyed).
+ connection()->sync();
+ xcb_destroy_window(xcb_connection(), m_netWmUserTimeWindow);
+ m_netWmUserTimeWindow = XCB_NONE;
+ }
connection()->removeWindow(m_window);
Q_XCB_CALL(xcb_destroy_window(xcb_connection(), m_window));
}
@@ -540,6 +548,8 @@ void QXcbWindow::show()
updateNetWmStateBeforeMap();
}
+ updateNetWmUserTime(connection()->time());
+
Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window));
xcb_flush(xcb_connection());
@@ -1168,10 +1178,31 @@ void QXcbWindow::propagateSizeHints()
void QXcbWindow::requestActivateWindow()
{
- if (m_mapped){
- updateNetWmUserTime(connection()->time());
+ if (!m_mapped)
+ return;
+
+ updateNetWmUserTime(connection()->time());
+
+ if (window()->isTopLevel()
+ && connection()->wmSupport()->isSupportedByWM(atom(QXcbAtom::_NET_ACTIVE_WINDOW))) {
+ xcb_client_message_event_t event;
+
+ event.response_type = XCB_CLIENT_MESSAGE;
+ event.format = 32;
+ event.window = m_window;
+ event.type = atom(QXcbAtom::_NET_ACTIVE_WINDOW);
+ event.data.data32[0] = 1;
+ event.data.data32[1] = connection()->time();
+ QWindow *focusWindow = QGuiApplication::focusWindow();
+ event.data.data32[2] = focusWindow ? focusWindow->winId() : XCB_NONE;
+ event.data.data32[3] = 0;
+ event.data.data32[4] = 0;
+
+ Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
+ } else {
Q_XCB_CALL(xcb_set_input_focus(xcb_connection(), XCB_INPUT_FOCUS_PARENT, m_window, connection()->time()));
}
+
connection()->sync();
}
@@ -1252,18 +1283,18 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even
m_syncValue.lo = event->data.data32[2];
m_syncValue.hi = event->data.data32[3];
} else {
- qWarning() << "unhandled WM_PROTOCOLS message:" << connection()->atomName(event->data.data32[0]);
+ qWarning() << "QXcbWindow: Unhandled WM_PROTOCOLS message:" << connection()->atomName(event->data.data32[0]);
}
} else if (event->type == atom(QXcbAtom::XdndEnter)) {
connection()->drag()->handleEnter(window(), event);
} else if (event->type == atom(QXcbAtom::XdndPosition)) {
- connection()->drag()->handlePosition(window(), event, false);
+ connection()->drag()->handlePosition(window(), event);
} else if (event->type == atom(QXcbAtom::XdndLeave)) {
- connection()->drag()->handleLeave(window(), event, false);
+ connection()->drag()->handleLeave(window(), event);
} else if (event->type == atom(QXcbAtom::XdndDrop)) {
- connection()->drag()->handleDrop(window(), event, false);
+ connection()->drag()->handleDrop(window(), event);
} else {
- qWarning() << "unhandled client message:" << connection()->atomName(event->type);
+ qWarning() << "QXcbWindow: Unhandled client message:" << connection()->atomName(event->type);
}
}
diff --git a/src/plugins/platforms/xcb/qxcbwmsupport.cpp b/src/plugins/platforms/xcb/qxcbwmsupport.cpp
index 114049f911..c9f4ca69dd 100644
--- a/src/plugins/platforms/xcb/qxcbwmsupport.cpp
+++ b/src/plugins/platforms/xcb/qxcbwmsupport.cpp
@@ -89,11 +89,6 @@ void QXcbWMSupport::updateNetWMAtoms()
free(reply);
} while (remaining > 0);
-
-// qDebug() << "======== updateNetWMAtoms";
-// for (int i = 0; i < net_wm_atoms.size(); ++i)
-// qDebug() << atomName(net_wm_atoms.at(i));
-// qDebug() << "======== updateNetWMAtoms";
}
// update the virtual roots array
@@ -130,10 +125,12 @@ void QXcbWMSupport::updateVirtualRoots()
free(reply);
} while (remaining > 0);
+#ifdef Q_XCB_DEBUG
qDebug() << "======== updateVirtualRoots";
for (int i = 0; i < net_virtual_roots.size(); ++i)
qDebug() << connection()->atomName(net_virtual_roots.at(i));
qDebug() << "======== updateVirtualRoots";
+#endif
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/xcb.pro b/src/plugins/platforms/xcb/xcb.pro
index 7bad2b4dad..d220766be0 100644
--- a/src/plugins/platforms/xcb/xcb.pro
+++ b/src/plugins/platforms/xcb/xcb.pro
@@ -94,7 +94,7 @@ contains(DEFINES, XCB_USE_DRI2) {
}
}
-LIBS += -lxcb -lxcb-image -lxcb-keysyms -lxcb-icccm -lxcb-sync -lxcb-xfixes
+LIBS += -lxcb -lxcb-image -lxcb-keysyms -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shape
DEFINES += $$QMAKE_DEFINES_XCB
LIBS += $$QMAKE_LIBS_XCB
diff --git a/src/plugins/platforms/xlib/qxlibcursor.cpp b/src/plugins/platforms/xlib/qxlibcursor.cpp
index 8ab40e31ef..a714f82371 100644
--- a/src/plugins/platforms/xlib/qxlibcursor.cpp
+++ b/src/plugins/platforms/xlib/qxlibcursor.cpp
@@ -52,8 +52,7 @@
QT_BEGIN_NAMESPACE
-QXlibCursor::QXlibCursor(QXlibScreen *screen)
- : QPlatformCursor(screen)
+QXlibCursor::QXlibCursor(QXlibScreen *screen) : m_screen(screen)
{
}
@@ -191,9 +190,4 @@ Cursor QXlibCursor::createCursorShape(int cshape)
return cursor;
}
-QXlibScreen * QXlibCursor::testLiteScreen() const
-{
- return static_cast<QXlibScreen *>(screen);
-}
-
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xlib/qxlibcursor.h b/src/plugins/platforms/xlib/qxlibcursor.h
index 92e42ac7a1..0056aa9554 100644
--- a/src/plugins/platforms/xlib/qxlibcursor.h
+++ b/src/plugins/platforms/xlib/qxlibcursor.h
@@ -48,7 +48,7 @@
QT_BEGIN_NAMESPACE
-class QXlibCursor : QPlatformCursor
+class QXlibCursor : public QPlatformCursor
{
public:
QXlibCursor(QXlibScreen *screen);
@@ -59,8 +59,9 @@ private:
Cursor createCursorBitmap(QCursor * cursor);
Cursor createCursorShape(int cshape);
- QXlibScreen *testLiteScreen() const;
+ QXlibScreen *testLiteScreen() const { return m_screen; }
QMap<int, Cursor> cursorMap;
+ QXlibScreen *m_screen;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xlib/qxlibscreen.cpp b/src/plugins/platforms/xlib/qxlibscreen.cpp
index fc903708b3..62c80b6ad4 100644
--- a/src/plugins/platforms/xlib/qxlibscreen.cpp
+++ b/src/plugins/platforms/xlib/qxlibscreen.cpp
@@ -241,6 +241,11 @@ QXlibScreen::~QXlibScreen()
delete mDisplay;
}
+QPlatformCursor *QXlibScreen::cursor() const
+{
+ return mCursor;
+}
+
Window QXlibScreen::rootWindow()
{
return RootWindow(mDisplay->nativeDisplay(), mScreen);
diff --git a/src/plugins/platforms/xlib/qxlibscreen.h b/src/plugins/platforms/xlib/qxlibscreen.h
index c6672c3540..5bb6cc7735 100644
--- a/src/plugins/platforms/xlib/qxlibscreen.h
+++ b/src/plugins/platforms/xlib/qxlibscreen.h
@@ -63,6 +63,7 @@ public:
int depth() const { return mDepth; }
QImage::Format format() const { return mFormat; }
QSizeF physicalSize() const { return mPhysicalSize; }
+ QPlatformCursor *cursor() const;
Window rootWindow();
unsigned long blackPixel();