summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaurice Kalinowski <maurice.kalinowski@qt.io>2016-05-27 13:13:40 +0200
committerMaurice Kalinowski <maurice.kalinowski@qt.io>2016-05-31 11:54:03 +0000
commite8ff3c8cbc8a66c344e2c974ae92f2cea7a2e5fe (patch)
tree3f6fcff6153ffd4dbb3c176b55723dcf848198ab
parent94f319a2bb191b24498a7575d3b9e186eb772d4d (diff)
downloadqtbase-e8ff3c8cbc8a66c344e2c974ae92f2cea7a2e5fe.tar.gz
winrt: fix drag pixmap support
Previously dragging only displayed the type of operation provided by the system. Now, in case a pixmap is specified, an image is shown. Also incorporated some cleanups. Task-number: QTBUG-50827 Change-Id: I471e2081eabfed014b08d189538d1d62cdb7248e Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
-rw-r--r--src/plugins/platforms/winrt/qwinrtdrag.cpp156
1 files changed, 96 insertions, 60 deletions
diff --git a/src/plugins/platforms/winrt/qwinrtdrag.cpp b/src/plugins/platforms/winrt/qwinrtdrag.cpp
index 8ccb211e4f..14bea7ab30 100644
--- a/src/plugins/platforms/winrt/qwinrtdrag.cpp
+++ b/src/plugins/platforms/winrt/qwinrtdrag.cpp
@@ -47,6 +47,7 @@
#include <Windows.ApplicationModel.datatransfer.h>
#include <windows.ui.xaml.h>
#include <windows.foundation.collections.h>
+#include <windows.graphics.imaging.h>
#include <windows.storage.streams.h>
#include <functional>
#include <robuffer.h>
@@ -55,6 +56,7 @@ using namespace ABI::Windows::ApplicationModel::DataTransfer;
using namespace ABI::Windows::ApplicationModel::DataTransfer::DragDrop;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::Foundation::Collections;
+using namespace ABI::Windows::Graphics::Imaging;
using namespace ABI::Windows::Storage;
using namespace ABI::Windows::Storage::Streams;
using namespace ABI::Windows::UI::Xaml;
@@ -65,6 +67,34 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcQpaMime, "qt.qpa.mime")
+ComPtr<IBuffer> createIBufferFromData(const char *data, qint32 size)
+{
+ static ComPtr<IBufferFactory> bufferFactory;
+ HRESULT hr;
+ if (!bufferFactory) {
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(),
+ IID_PPV_ARGS(&bufferFactory));
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+
+ ComPtr<IBuffer> buffer;
+ const UINT32 length = size;
+ hr = bufferFactory->Create(length, &buffer);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = buffer->put_Length(length);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteArrayAccess;
+ hr = buffer.As(&byteArrayAccess);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ byte *bytes;
+ hr = byteArrayAccess->Buffer(&bytes);
+ Q_ASSERT_SUCCEEDED(hr);
+ memcpy(bytes, data, length);
+ return buffer;
+}
+
class DragThreadTransferData : public QObject
{
Q_OBJECT
@@ -175,36 +205,42 @@ QStringList QWinRTInternalMimeData::formats_sys() const
if (!formats.isEmpty())
return formats;
- boolean contains;
HRESULT hr;
- hr = dataView->Contains(NativeFormatStrings::text, &contains);
- if (SUCCEEDED(hr) && contains)
- formats.append(QLatin1String("text/plain"));
-
- hr = dataView->Contains(NativeFormatStrings::html, &contains);
- if (SUCCEEDED(hr) && contains)
- formats.append(QLatin1String("text/html"));
-
- hr = dataView->Contains(NativeFormatStrings::storage, &contains);
- if (SUCCEEDED(hr) && contains)
- formats.append(QLatin1String("text/uri-list"));
-
- // We need to add any additional format as well, for legacy windows
- // reasons, but also in case someone adds custom formats.
- ComPtr<IVectorView<HSTRING>> availableFormats;
- hr = dataView->get_AvailableFormats(&availableFormats);
- RETURN_IF_FAILED("Could not query available formats.", return formats);
-
- quint32 size;
- hr = availableFormats->get_Size(&size);
- RETURN_IF_FAILED("Could not query format vector size.", return formats);
- for (quint32 i = 0; i < size; ++i) {
- HString str;
- hr = availableFormats->GetAt(i, str.GetAddressOf());
- if (FAILED(hr))
- continue;
- formats.append(hStringToQString(str));
- }
+ hr = QEventDispatcherWinRT::runOnXamlThread([this]() {
+ boolean contains;
+ HRESULT hr;
+ hr = dataView->Contains(NativeFormatStrings::text, &contains);
+ if (SUCCEEDED(hr) && contains)
+ formats.append(QLatin1String("text/plain"));
+
+ hr = dataView->Contains(NativeFormatStrings::html, &contains);
+ if (SUCCEEDED(hr) && contains)
+ formats.append(QLatin1String("text/html"));
+
+ hr = dataView->Contains(NativeFormatStrings::storage, &contains);
+ if (SUCCEEDED(hr) && contains)
+ formats.append(QLatin1String("text/uri-list"));
+
+ // We need to add any additional format as well, for legacy windows
+ // reasons, but also in case someone adds custom formats.
+ ComPtr<IVectorView<HSTRING>> availableFormats;
+ hr = dataView->get_AvailableFormats(&availableFormats);
+ RETURN_OK_IF_FAILED("Could not query available formats.");
+
+ quint32 size;
+ hr = availableFormats->get_Size(&size);
+ RETURN_OK_IF_FAILED("Could not query format vector size.");
+ for (quint32 i = 0; i < size; ++i) {
+ HString str;
+ hr = availableFormats->GetAt(i, str.GetAddressOf());
+ if (FAILED(hr))
+ continue;
+ formats.append(hStringToQString(str));
+ }
+ return S_OK;
+ });
+ Q_ASSERT_SUCCEEDED(hr);
+
return formats;
}
@@ -265,8 +301,6 @@ QVariant QWinRTInternalMimeData::retrieveData_sys(const QString &mimetype, QVari
result.setValue(hStringToQString(res));
return S_OK;
});
- } else if (mimetype.startsWith(QLatin1String("image/"))) {
- Q_UNIMPLEMENTED();
} else {
// Asking for custom data
hr = QEventDispatcherWinRT::runOnXamlThread([this, &result, mimetype]() {
@@ -615,30 +649,39 @@ Qt::DropAction QWinRTDrag::drag(QDrag *drag)
}
// ### TODO: Missing: weblink, image
- const QStringList formats = mimeData->formats();
- for (auto item : formats) {
- QByteArray data = mimeData->data(item);
+ if (!drag->pixmap().isNull()) {
+ const QImage image2 = drag->pixmap().toImage();
+ const QImage image = image2.convertToFormat(QImage::Format_ARGB32);
+ if (!image.isNull()) {
+ // Create IBuffer containing image
+ ComPtr<IBuffer> imageBuffer = createIBufferFromData(reinterpret_cast<const char*>(image.bits()), image.byteCount());
- ComPtr<IBufferFactory> bufferFactory;
- hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(),
- IID_PPV_ARGS(&bufferFactory));
- Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<ISoftwareBitmapFactory> bitmapFactory;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Graphics_Imaging_SoftwareBitmap).Get(),
+ IID_PPV_ARGS(&bitmapFactory));
+ Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IBuffer> buffer;
- const UINT32 length = data.size();
- hr = bufferFactory->Create(length, &buffer);
- Q_ASSERT_SUCCEEDED(hr);
- hr = buffer->put_Length(length);
- Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<ISoftwareBitmap> bitmap;
+ hr = bitmapFactory->Create(BitmapPixelFormat_Rgba8, image.width(), image.height(), &bitmap);
+ Q_ASSERT_SUCCEEDED(hr);
- ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteArrayAccess;
- hr = buffer.As(&byteArrayAccess);
- Q_ASSERT_SUCCEEDED(hr);
+ hr = bitmap->CopyFromBuffer(imageBuffer.Get());
+ Q_ASSERT_SUCCEEDED(hr);
- byte *bytes;
- hr = byteArrayAccess->Buffer(&bytes);
- Q_ASSERT_SUCCEEDED(hr);
- memcpy(bytes, data.constData(), length);
+ ComPtr<IDragUI> dragUi;
+ hr = args->get_DragUI(dragUi.GetAddressOf());
+ Q_ASSERT_SUCCEEDED(hr);
+
+ hr = dragUi->SetContentFromSoftwareBitmap(bitmap.Get());
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+ }
+
+ const QStringList formats = mimeData->formats();
+ for (auto item : formats) {
+ QByteArray data = mimeData->data(item);
+
+ ComPtr<IBuffer> buffer = createIBufferFromData(data.constData(), data.size());
// We cannot push the buffer to the data package as the result on
// recipient side is different from native events. It still sends a
@@ -648,7 +691,7 @@ Qt::DropAction QWinRTDrag::drag(QDrag *drag)
hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_InMemoryRandomAccessStream).Get(), &ras);
Q_ASSERT_SUCCEEDED(hr);
- hr = ras->put_Size(length);
+ hr = ras->put_Size(data.size());
ComPtr<IOutputStream> outputStream;
hr = ras->GetOutputStreamAt(0, &outputStream);
Q_ASSERT_SUCCEEDED(hr);
@@ -663,7 +706,7 @@ Qt::DropAction QWinRTDrag::drag(QDrag *drag)
unsigned char flushResult;
ComPtr<IAsyncOperation<bool>> flushOp;
- hr = outputStream.Get()->FlushAsync(&flushOp);
+ hr = outputStream->FlushAsync(&flushOp);
Q_ASSERT_SUCCEEDED(hr);
hr = QWinRTFunctions::await(flushOp, &flushResult);
@@ -671,7 +714,6 @@ Qt::DropAction QWinRTDrag::drag(QDrag *drag)
hr = dataPackage->SetData(qStringToHString(item).Get(), ras.Get());
Q_ASSERT_SUCCEEDED(hr);
-
}
return S_OK;
});
@@ -679,12 +721,6 @@ Qt::DropAction QWinRTDrag::drag(QDrag *drag)
hr = elem3->add_DragStarting(startingCallback.Get(), &startingToken);
Q_ASSERT_SUCCEEDED(hr);
- ComPtr<ABI::Windows::UI::Input::IPointerPointStatics> pointStatics;
-
- hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Input_PointerPoint).Get(),
- IID_PPV_ARGS(&pointStatics));
- Q_ASSERT_SUCCEEDED(hr);
-
hr = elem3->StartDragAsync(qt_winrt_lastPointerPoint.Get(), &op);
Q_ASSERT_SUCCEEDED(hr);