winrt: Fix clipboard

Native implementation was missing and so far it only used the Qt
internal fallback mode.

Unfortunately this does not apply to Windows Phone 8.1.

Task-number: QTBUG-49766
Change-Id: I8cbbb0c843d077d7df1396d673fedeab2799b5a6
Reviewed-by: Oliver Wolff <oliver.wolff@theqtcompany.com>
bb10
Maurice Kalinowski 2016-02-15 16:01:21 +01:00
parent ad16703fa8
commit e7a06c9843
5 changed files with 275 additions and 0 deletions

View File

@ -0,0 +1,185 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or later 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 2.0 requirements will be
** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qwinrtclipboard.h"
#include <QtCore/QCoreApplication>
#include <QtCore/qfunctions_winrt.h>
#include <QtCore/private/qeventdispatcher_winrt_p.h>
#include <Windows.ApplicationModel.datatransfer.h>
#include <functional>
using namespace ABI::Windows::ApplicationModel::DataTransfer;
using namespace ABI::Windows::Foundation;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
typedef IEventHandler<IInspectable *> ContentChangedHandler;
#define RETURN_NULLPTR_IF_FAILED(msg) RETURN_IF_FAILED(msg, return nullptr)
QT_BEGIN_NAMESPACE
QWinRTClipboard::QWinRTClipboard()
{
#ifndef Q_OS_WINPHONE
QEventDispatcherWinRT::runOnXamlThread([this]() {
HRESULT hr;
hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_ApplicationModel_DataTransfer_Clipboard).Get(),
&m_nativeClipBoard);
Q_ASSERT_SUCCEEDED(hr);
EventRegistrationToken tok;
hr = m_nativeClipBoard->add_ContentChanged(Callback<ContentChangedHandler>(this, &QWinRTClipboard::onContentChanged).Get(), &tok);
Q_ASSERT_SUCCEEDED(hr);
return hr;
});
#endif // !Q_OS_WINPHONE
}
QMimeData *QWinRTClipboard::mimeData(QClipboard::Mode mode)
{
if (!supportsMode(mode))
return nullptr;
#ifndef Q_OS_WINPHONE
ComPtr<IDataPackageView> view;
HRESULT hr;
hr = m_nativeClipBoard->GetContent(&view);
RETURN_NULLPTR_IF_FAILED("Could not get clipboard content.");
ComPtr<IAsyncOperation<HSTRING>> op;
HString result;
// This throws a security exception (WinRT originate error / 0x40080201.
// Unfortunately there seems to be no way to avoid this, neither
// running on the XAML thread, nor some other way. Stack Overflow
// confirms this problem since Windows (Phone) 8.0.
hr = view->GetTextAsync(&op);
RETURN_NULLPTR_IF_FAILED("Could not get clipboard text.");
hr = QWinRTFunctions::await(op, result.GetAddressOf());
RETURN_NULLPTR_IF_FAILED("Could not get clipboard text content");
quint32 size;
const wchar_t *textStr = result.GetRawBuffer(&size);
QString text = QString::fromWCharArray(textStr, size);
text.replace(QStringLiteral("\r\n"), QStringLiteral("\n"));
m_mimeData.setText(text);
return &m_mimeData;
#else // Q_OS_WINPHONE
return QPlatformClipboard::mimeData(mode);
#endif // Q_OS_WINPHONE
}
// Inspired by QWindowsMimeText::convertFromMime
inline QString convertToWindowsLineEnding(const QString &text)
{
const QChar *u = text.unicode();
QString res;
const int s = text.length();
int maxsize = s + s / 40 + 3;
res.resize(maxsize);
int ri = 0;
bool cr = false;
for (int i = 0; i < s; ++i) {
if (*u == QLatin1Char('\r'))
cr = true;
else {
if (*u == QLatin1Char('\n') && !cr)
res[ri++] = QLatin1Char('\r');
cr = false;
}
res[ri++] = *u;
if (ri+3 >= maxsize) {
maxsize += maxsize / 4;
res.resize(maxsize);
}
++u;
}
res.truncate(ri);
return res;
}
void QWinRTClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
{
if (!supportsMode(mode))
return;
#ifndef Q_OS_WINPHONE
const QString text = data->text();
HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, text]() {
HRESULT hr;
ComPtr<IDataPackage> package;
hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_ApplicationModel_DataTransfer_DataPackage).Get(),
&package);
const QString nativeString = convertToWindowsLineEnding(text);
HStringReference textRef(reinterpret_cast<LPCWSTR>(nativeString.utf16()), nativeString.length());
hr = package->SetText(textRef.Get());
RETURN_HR_IF_FAILED("Could not set text to clipboard data package.");
hr = m_nativeClipBoard->SetContent(package.Get());
RETURN_HR_IF_FAILED("Could not set clipboard content.");
return S_OK;
});
RETURN_VOID_IF_FAILED("Could not set clipboard text.");
emitChanged(mode);
#else // Q_OS_WINPHONE
QPlatformClipboard::setMimeData(data, mode);
#endif // Q_OS_WINPHONE
}
bool QWinRTClipboard::supportsMode(QClipboard::Mode mode) const
{
#ifndef Q_OS_WINPHONE
return mode == QClipboard::Clipboard;
#else
return QPlatformClipboard::supportsMode(mode);
#endif
}
HRESULT QWinRTClipboard::onContentChanged(IInspectable *, IInspectable *)
{
emitChanged(QClipboard::Clipboard);
return S_OK;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,78 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or later 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 2.0 requirements will be
** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QWINRTPLATFORMCLIPBOARD_H
#define QWINRTPLATFORMCLIPBOARD_H
#include <qpa/qplatformclipboard.h>
#include <QMimeData>
#include <wrl.h>
#ifndef Q_OS_WINPHONE
namespace ABI {
namespace Windows {
namespace ApplicationModel {
namespace DataTransfer {
struct IClipboardStatics;
}
}
}
}
#endif // !Q_OS_WINPHONE
QT_BEGIN_NAMESPACE
class QWinRTClipboard: public QPlatformClipboard
{
public:
QWinRTClipboard();
QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE;
void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE;
bool supportsMode(QClipboard::Mode mode) const Q_DECL_OVERRIDE;
HRESULT onContentChanged(IInspectable *, IInspectable *);
private:
#ifndef Q_OS_WINPHONE
Microsoft::WRL::ComPtr<ABI::Windows::ApplicationModel::DataTransfer::IClipboardStatics> m_nativeClipBoard;
#endif
QMimeData m_mimeData;
};
QT_END_NAMESPACE
#endif // QWINRTPLATFORMCLIPBOARD_H

View File

@ -44,6 +44,7 @@
#include "qwinrteglcontext.h"
#include "qwinrtfontdatabase.h"
#include "qwinrttheme.h"
#include "qwinrtclipboard.h"
#include <QtGui/QOffscreenSurface>
#include <QtGui/QOpenGLContext>
@ -111,6 +112,7 @@ class QWinRTIntegrationPrivate
public:
QPlatformFontDatabase *fontDatabase;
QPlatformServices *platformServices;
QPlatformClipboard *clipboard;
QWinRTScreen *mainScreen;
QScopedPointer<QWinRTInputContext> inputContext;
@ -195,6 +197,7 @@ QWinRTIntegration::QWinRTIntegration() : d_ptr(new QWinRTIntegrationPrivate)
screenAdded(d->mainScreen);
d->platformServices = new QWinRTServices;
d->clipboard = new QWinRTClipboard;
}
QWinRTIntegration::~QWinRTIntegration()
@ -300,6 +303,12 @@ QPlatformServices *QWinRTIntegration::services() const
return d->platformServices;
}
QPlatformClipboard *QWinRTIntegration::clipboard() const
{
Q_D(const QWinRTIntegration);
return d->clipboard;
}
Qt::KeyboardModifiers QWinRTIntegration::queryKeyboardModifiers() const
{
Q_D(const QWinRTIntegration);

View File

@ -93,6 +93,7 @@ public:
QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE;
QPlatformServices *services() const Q_DECL_OVERRIDE;
QPlatformClipboard *clipboard() const Q_DECL_OVERRIDE;
Qt::KeyboardModifiers queryKeyboardModifiers() const Q_DECL_OVERRIDE;
QStringList themeNames() const Q_DECL_OVERRIDE;

View File

@ -16,6 +16,7 @@ INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/freetype/include
SOURCES = \
main.cpp \
qwinrtbackingstore.cpp \
qwinrtclipboard.cpp \
qwinrtcursor.cpp \
qwinrteglcontext.cpp \
qwinrteventdispatcher.cpp \
@ -33,6 +34,7 @@ SOURCES = \
HEADERS = \
qwinrtbackingstore.h \
qwinrtclipboard.h \
qwinrtcursor.h \
qwinrteglcontext.h \
qwinrteventdispatcher.h \