1
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
5
#include "oxide_qt_clipboard.h"
10
#include "base/basictypes.h"
11
#include "base/files/file_path.h"
12
#include "base/logging.h"
13
#include "base/memory/ref_counted_memory.h"
14
#include "base/memory/scoped_ptr.h"
15
#include "base/memory/singleton.h"
16
#include "base/metrics/histogram.h"
17
#include "base/stl_util.h"
18
#include "base/strings/utf_string_conversions.h"
19
#include "third_party/skia/include/core/SkBitmap.h"
20
#include "third_party/skia/include/core/SkImageInfo.h"
21
#include "ui/base/clipboard/custom_data_helper.h"
22
#include "ui/events/platform/platform_event_dispatcher.h"
23
#include "ui/events/platform/platform_event_observer.h"
24
#include "ui/events/platform/platform_event_source.h"
25
#include "ui/gfx/codec/png_codec.h"
26
#include "ui/gfx/geometry/size.h"
30
#include <QGuiApplication>
37
#define GET_CLIPBOARD_DATA(c) \
39
type == ui::CLIPBOARD_TYPE_COPY_PASTE ? \
40
QClipboard::Clipboard \
41
: QClipboard::Selection)
43
class ClipboardChangedListener : public QObject {
47
ClipboardChangedListener();
48
uint64 clipboard_sequence_number() const {
49
return clipboard_sequence_number_;
51
uint64 selection_sequence_number() const {
52
return selection_sequence_number_;
55
void OnClipboardDataChanged(QClipboard::Mode mode);
57
uint64 clipboard_sequence_number_;
58
uint64 selection_sequence_number_;
60
DISALLOW_COPY_AND_ASSIGN(ClipboardChangedListener);
63
ClipboardChangedListener::ClipboardChangedListener()
64
: clipboard_sequence_number_(0),
65
selection_sequence_number_(0) {
67
QGuiApplication::clipboard(),
68
SIGNAL(changed(QClipboard::Mode)),
70
SLOT(OnClipboardDataChanged(QClipboard::Mode)));
73
void ClipboardChangedListener::OnClipboardDataChanged(
74
QClipboard::Mode mode) {
76
case QClipboard::Clipboard:
77
++clipboard_sequence_number_;
79
case QClipboard::Selection:
80
++selection_sequence_number_;
93
const char kMimeTypeWebkitSmartPaste[] = "chromium/x-webkit-paste";
97
///////////////////////////////////////////////////////////////////////////////
100
ClipboardQt::ClipboardQt()
101
: clipboard_changed_listener_(new ClipboardChangedListener()),
102
write_mime_data_acc_(new QMimeData()) {
103
DCHECK(CalledOnValidThread());
106
ui::Clipboard* ClipboardQt::DoCreate() {
107
return new ClipboardQt();
110
ClipboardQt::~ClipboardQt() {
111
DCHECK(CalledOnValidThread());
114
uint64 ClipboardQt::GetSequenceNumber(ui::ClipboardType type) const {
115
DCHECK(CalledOnValidThread());
116
return type == ui::CLIPBOARD_TYPE_COPY_PASTE
117
? clipboard_changed_listener_->clipboard_sequence_number()
118
: clipboard_changed_listener_->selection_sequence_number();
121
bool ClipboardQt::IsFormatAvailable(const FormatType& format,
122
ui::ClipboardType type) const {
123
DCHECK(CalledOnValidThread());
124
DCHECK(IsSupportedClipboardType(type));
126
QClipboard* clipboard = QGuiApplication::clipboard();
128
qCritical() << "Could not access clipboard";
132
const QMimeData *data = GET_CLIPBOARD_DATA(clipboard);
137
return data->hasFormat(format.ToString().c_str());
140
void ClipboardQt::Clear(ui::ClipboardType type) {
141
DCHECK(CalledOnValidThread());
142
DCHECK(IsSupportedClipboardType(type));
144
QClipboard* clipboard = QGuiApplication::clipboard();
146
qCritical() << "Could not access clipboard";
153
void ClipboardQt::ReadAvailableTypes(ui::ClipboardType type,
154
std::vector<base::string16>* types,
155
bool* contains_filenames) const {
156
DCHECK(IsSupportedClipboardType(type));
157
DCHECK(CalledOnValidThread());
158
DCHECK(types != nullptr);
159
DCHECK(contains_filenames != nullptr);
161
QClipboard* clipboard = QGuiApplication::clipboard();
163
qCritical() << "Could not access clipboard";
167
const QMimeData *data = GET_CLIPBOARD_DATA(clipboard);
172
std::vector<base::string16> out_types;
173
Q_FOREACH (const QString& format, data->formats()) {
174
out_types.push_back(base::UTF8ToUTF16(format.toUtf8().data()));
176
std::swap(*types, out_types);
178
*contains_filenames = false;
181
void ClipboardQt::ReadText(ui::ClipboardType type,
182
base::string16* result) const {
183
DCHECK(IsSupportedClipboardType(type));
184
DCHECK(CalledOnValidThread());
186
QClipboard* clipboard = QGuiApplication::clipboard();
188
qCritical() << "Could not access clipboard";
192
const QMimeData *data = GET_CLIPBOARD_DATA(clipboard);
193
if ( ! data || ! data->hasText()) {
197
*result = base::UTF8ToUTF16(data->text().toUtf8().data());
200
void ClipboardQt::ReadAsciiText(ui::ClipboardType type,
201
std::string* result) const {
202
DCHECK(IsSupportedClipboardType(type));
203
DCHECK(CalledOnValidThread());
205
QClipboard* clipboard = QGuiApplication::clipboard();
207
qCritical() << "Could not access clipboard";
211
const QMimeData *data = GET_CLIPBOARD_DATA(clipboard);
212
if ( ! data || ! data->hasText()) {
216
*result = data->text().toStdString().c_str();
219
void ClipboardQt::ReadHTML(ui::ClipboardType type,
220
base::string16* markup,
221
std::string* src_url,
222
uint32* fragment_start,
223
uint32* fragment_end) const {
224
DCHECK(IsSupportedClipboardType(type));
225
DCHECK(CalledOnValidThread());
227
QClipboard* clipboard = QGuiApplication::clipboard();
229
qCritical() << "Could not access clipboard";
233
const QMimeData *data = GET_CLIPBOARD_DATA(clipboard);
234
if ( ! data || ! data->hasHtml()) {
243
*markup = base::UTF8ToUTF16(data->html().toStdString());
245
DCHECK(markup->length() <= kuint32max);
246
*fragment_end = static_cast<uint32>(markup->length());
249
void ClipboardQt::ReadRTF(ui::ClipboardType type, std::string* result) const {
250
DCHECK(IsSupportedClipboardType(type));
251
DCHECK(CalledOnValidThread());
253
QClipboard* clipboard = QGuiApplication::clipboard();
255
qCritical() << "Could not access clipboard";
259
const QMimeData *data = GET_CLIPBOARD_DATA(clipboard);
260
if ( ! data || ! data->hasFormat(QString::fromLatin1(kMimeTypeRTF))) {
264
*result = data->data(QString::fromLatin1(kMimeTypeRTF)).data();
267
SkBitmap ClipboardQt::ReadImage(ui::ClipboardType type) const {
268
DCHECK(IsSupportedClipboardType(type));
269
DCHECK(CalledOnValidThread());
271
QClipboard* clipboard = QGuiApplication::clipboard();
273
qCritical() << "Could not access clipboard";
277
const QMimeData *md = GET_CLIPBOARD_DATA(clipboard);
283
if (md->hasImage()) {
284
image = qvariant_cast<QImage>(md->imageData());
286
* ReadImage() is called from Blink when 'clipboardData.getAsFile'
287
* is called with a forced explicit mime type of 'image/png'.
289
* See third_party/WebKit/Source/core/clipboard/DataObjectItem.cpp
291
} else if (md->hasFormat(Clipboard::kMimeTypePNG)) {
292
image.loadFromData(md->data(Clipboard::kMimeTypePNG), "PNG");
297
if (image.format() != QImage::Format_RGBA8888) {
298
image.convertToFormat(QImage::Format_RGBA8888);
303
SkImageInfo::MakeN32(
306
kOpaque_SkAlphaType));
308
bitmap.setPixels(const_cast<uchar*>(image.constBits()));
310
// Force a deep copy of the image data
312
bitmap.copyTo(©, kN32_SkColorType);
316
void ClipboardQt::ReadCustomData(ui::ClipboardType type,
317
const base::string16& data_type,
318
base::string16* result) const {
319
DCHECK(CalledOnValidThread());
320
DCHECK(IsSupportedClipboardType(type));
322
QClipboard* clipboard = QGuiApplication::clipboard();
324
qCritical() << "Could not access clipboard";
328
const QMimeData *data = GET_CLIPBOARD_DATA(clipboard);
329
QString mime_type = QString::fromStdString(base::UTF16ToUTF8(data_type));
330
if ( ! data || ! data->hasFormat(mime_type)) {
334
ui::ReadCustomDataForType(
335
data->data(mime_type).constData(),
336
data->data(mime_type).size(),
341
void ClipboardQt::ReadBookmark(base::string16* title,
342
std::string* url) const {
346
void ClipboardQt::ReadData(const FormatType& format,
347
std::string* result) const {
348
DCHECK(CalledOnValidThread());
350
QClipboard* clipboard = QGuiApplication::clipboard();
352
qCritical() << "Could not access clipboard";
356
const QMimeData *data = clipboard->mimeData(QClipboard::Clipboard);
361
*result = data->data(format.ToString().c_str()).data();
364
void ClipboardQt::WriteObjects(ui::ClipboardType type,
365
const ObjectMap& objects) {
366
DCHECK(CalledOnValidThread());
367
DCHECK(IsSupportedClipboardType(type));
369
if (! write_mime_data_acc_) {
370
write_mime_data_acc_.reset(new QMimeData());
373
// dispatch all objects and gather the resulting mime data
374
for (ObjectMap::const_iterator iter = objects.begin();
375
iter != objects.end();
377
DispatchObject(static_cast<ObjectType>(iter->first), iter->second);
380
QClipboard* clipboard = QGuiApplication::clipboard();
382
qCritical() << "Could not access clipboard";
386
clipboard->setMimeData(
387
write_mime_data_acc_.release(),
388
type == ui::CLIPBOARD_TYPE_COPY_PASTE
389
? QClipboard::Clipboard
390
: QClipboard::Selection);
393
void ClipboardQt::WriteText(const char* text_data, size_t text_len) {
394
write_mime_data_acc_->setText(QString::fromUtf8(text_data, text_len));
397
void ClipboardQt::WriteHTML(const char* markup_data,
399
const char* url_data,
401
write_mime_data_acc_->setHtml(
402
QString::fromUtf8(markup_data, markup_len));
405
void ClipboardQt::WriteRTF(const char* rtf_data, size_t data_len) {
406
write_mime_data_acc_->setData(QString::fromLatin1(kMimeTypeRTF), QByteArray(rtf_data, data_len));
409
void ClipboardQt::WriteBookmark(const char* title_data,
411
const char* url_data,
416
void ClipboardQt::WriteWebSmartPaste() {
417
write_mime_data_acc_->setData(
418
QString::fromLatin1(kMimeTypeWebkitSmartPaste),
422
void ClipboardQt::WriteBitmap(const SkBitmap& bitmap) {
424
if (bitmap.info().colorType() != kN32_SkColorType) {
426
SkImageInfo::MakeN32(
431
SkBitmap convertedBitmap;
432
if (!convertedBitmap.tryAllocPixels(info)) {
438
convertedBitmap.getPixels(),
441
image = QImage(reinterpret_cast<const uchar *>(convertedBitmap.getPixels()),
444
QImage::Format_RGBA8888);
446
image = QImage(reinterpret_cast<const uchar *>(bitmap.getPixels()),
449
QImage::Format_RGBA8888);
452
write_mime_data_acc_->setImageData(image.copy());
455
void ClipboardQt::WriteData(const FormatType& format,
456
const char* data_data,
458
write_mime_data_acc_->setData(
459
QString::fromStdString(format.ToString()),
460
QByteArray(data_data, data_len));
466
#include "oxide_qt_clipboard.moc"