From 9150563940f61be9fb17510be49c0734244866a5 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 1 Jul 2014 12:21:03 +0200 Subject: Windows clipboard: Deny CF_DIB support for images with alpha. Support CF_DIBV5 for these images so that transparency is preserved. Task-number: QTBUG-11463 Change-Id: I51881ae8bfbd05b92abd309766f4da9a7ea26c2d Reviewed-by: Joerg Bornemann --- src/plugins/platforms/windows/qwindowsmime.cpp | 21 ++++----- tests/auto/gui/kernel/qclipboard/paster/main.cpp | 55 ++++++++++++++++++---- .../auto/gui/kernel/qclipboard/tst_qclipboard.cpp | 33 +++++++++++-- 3 files changed, 86 insertions(+), 23 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp index 0343b7f110..37f51e85bd 100644 --- a/src/plugins/platforms/windows/qwindowsmime.cpp +++ b/src/plugins/platforms/windows/qwindowsmime.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -1035,17 +1035,14 @@ bool QWindowsMimeImage::canConvertToMime(const QString &mimeType, IDataObject *p bool QWindowsMimeImage::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const { int cf = getCf(formatetc); - if (mimeData->hasImage()) { - if (cf == CF_DIB) - return true; - else if (cf == CF_DIBV5) { - //support DIBV5 conversion only if the image has alpha channel - QImage image = qvariant_cast(mimeData->imageData()); - if (!image.isNull() && image.hasAlphaChannel()) - return true; - } - } - return false; + if (!mimeData->hasImage()) + return false; + const QImage image = qvariant_cast(mimeData->imageData()); + if (image.isNull()) + return false; + // QTBUG-11463, deny CF_DIB support for images with alpha to prevent loss of + // transparency in conversion. + return cf == CF_DIBV5 || (cf == CF_DIB && !image.hasAlphaChannel()); } bool QWindowsMimeImage::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const diff --git a/tests/auto/gui/kernel/qclipboard/paster/main.cpp b/tests/auto/gui/kernel/qclipboard/paster/main.cpp index 0dd7dd87af..3fd4267598 100644 --- a/tests/auto/gui/kernel/qclipboard/paster/main.cpp +++ b/tests/auto/gui/kernel/qclipboard/paster/main.cpp @@ -40,20 +40,59 @@ ****************************************************************************/ #include #include +#include +#include #include +#include int main(int argc, char **argv) { QGuiApplication app(argc, argv); - QString expected = QStringLiteral("testString.!"); -#ifndef Q_OS_WINCE - const QStringList arguments = app.arguments(); - if (arguments.size() > 1) - expected = arguments.at(1); + QCommandLineParser parser; + parser.addHelpOption(); + QCommandLineOption textOption(QStringLiteral("text"), + QStringLiteral("Text to compare"), + QStringLiteral("text")); + parser.addOption(textOption); + QCommandLineOption imageOption(QStringLiteral("image"), + QStringLiteral("Perform image check")); + parser.addOption(imageOption); + parser.process(QCoreApplication::arguments()); + + if (parser.isSet(imageOption)) { +#ifndef QT_NO_CLIPBOARD + const QImage actual = QGuiApplication::clipboard()->image(); +#else + const QImage actual; #endif - QString actual; + // Perform hard-coded checks on copied image (size, pixel 0,0: transparent, + // pixel 1,0: blue). Note: Windows sets RGB of transparent to 0xFF when converting + // to DIB5. + if (actual.size() != QSize(100, 100)) + return 1; + const QRgb pixel00 = actual.pixel(QPoint(0, 0)); + if (qAlpha(pixel00)) + return 2; + const QRgb pixel01 = actual.pixel(QPoint(1, 0)); + if (pixel01 != QColor(Qt::blue).rgba()) + return 3; + return 0; + } + +#ifndef Q_OS_WINCE + QString expected; + if (parser.isSet(textOption)) + expected = parser.value(textOption); +#else // !Q_OS_WINCE + const QString expected = QStringLiteral("testString.!"); +#endif // Q_OS_WINCE + if (!expected.isEmpty()) { #ifndef QT_NO_CLIPBOARD - actual = QGuiApplication::clipboard()->text(); + const QString actual = QGuiApplication::clipboard()->text(); +#else + const QString actual; #endif - return actual == expected ? 0 : 1; + return actual == expected ? 0 : 1; + } + return -2; } diff --git a/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp b/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp index 8a2009a601..b677ee1ea4 100644 --- a/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp +++ b/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp @@ -46,6 +46,8 @@ #include #include #include +#include +#include #include "../../../shared/platformclipboard.h" class tst_QClipboard : public QObject @@ -59,6 +61,7 @@ private slots: void init(); #if defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(Q_OS_QNX) void copy_exit_paste(); + void copyImage(); #endif void capabilityFunctions(); void modes(); @@ -278,18 +281,42 @@ void tst_QClipboard::copy_exit_paste() // ### It's still possible to test copy/paste - just keep the apps running if (!PlatformClipboard::isAvailable()) QSKIP("Native clipboard not working in this setup"); - const QStringList stringArgument(QStringLiteral("Test string.")); + const QString stringArgument(QStringLiteral("Test string.")); QByteArray errorMessage; - QVERIFY2(runHelper(QStringLiteral("copier/copier"), stringArgument, &errorMessage), + QVERIFY2(runHelper(QStringLiteral("copier/copier"), QStringList(stringArgument), &errorMessage), errorMessage.constData()); #ifdef Q_OS_MAC // The Pasteboard needs a moment to breathe (at least on older Macs). QTest::qWait(100); #endif // Q_OS_MAC - QVERIFY2(runHelper(QStringLiteral("paster/paster"), stringArgument, &errorMessage), + QVERIFY2(runHelper(QStringLiteral("paster/paster"), + QStringList() << QStringLiteral("--text") << stringArgument, + &errorMessage), errorMessage.constData()); #endif // QT_NO_PROCESS } + +void tst_QClipboard::copyImage() +{ +#ifndef QT_NO_PROCESS + if (!PlatformClipboard::isAvailable()) + QSKIP("Native clipboard not working in this setup"); + QImage image(100, 100, QImage::Format_ARGB32); + image.fill(QColor(Qt::transparent)); + image.setPixel(QPoint(1, 0), QColor(Qt::blue).rgba()); + QGuiApplication::clipboard()->setImage(image); +#ifdef Q_OS_OSX + // The Pasteboard needs a moment to breathe (at least on older Macs). + QTest::qWait(100); +#endif // Q_OS_OSX + // paster will perform hard-coded checks on the copied image. + QByteArray errorMessage; + QVERIFY2(runHelper(QStringLiteral("paster/paster"), + QStringList(QStringLiteral("--image")), &errorMessage), + errorMessage.constData()); +#endif // QT_NO_PROCESS +} + #endif // Q_OS_WIN || Q_OS_MAC || Q_OS_QNX void tst_QClipboard::setMimeData() -- cgit v1.2.3