1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=4 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "AsyncGtkClipboardRequest.h"
namespace mozilla {
AsyncGtkClipboardRequest::AsyncGtkClipboardRequest(ClipboardDataType aDataType,
int32_t aWhichClipboard,
const char* aMimeType) {
GtkClipboard* clipboard =
gtk_clipboard_get(GetSelectionAtom(aWhichClipboard));
mRequest = MakeUnique<Request>(aDataType);
switch (aDataType) {
case ClipboardDataType::Data:
LOGCLIP(" getting DATA MIME %s\n", aMimeType);
gtk_clipboard_request_contents(clipboard,
gdk_atom_intern(aMimeType, FALSE),
OnDataReceived, mRequest.get());
break;
case ClipboardDataType::Text:
LOGCLIP(" getting TEXT\n");
gtk_clipboard_request_text(clipboard, OnTextReceived, mRequest.get());
break;
case ClipboardDataType::Targets:
LOGCLIP(" getting TARGETS\n");
gtk_clipboard_request_contents(clipboard,
gdk_atom_intern("TARGETS", FALSE),
OnDataReceived, mRequest.get());
break;
}
}
void AsyncGtkClipboardRequest::OnDataReceived(GtkClipboard* clipboard,
GtkSelectionData* selection_data,
gpointer data) {
int whichClipboard = GetGeckoClipboardType(clipboard);
LOGCLIP("OnDataReceived(%s) callback\n",
whichClipboard == nsClipboard::kSelectionClipboard ? "primary"
: "clipboard");
static_cast<Request*>(data)->Complete(selection_data);
}
void AsyncGtkClipboardRequest::OnTextReceived(GtkClipboard* clipboard,
const gchar* text,
gpointer data) {
int whichClipboard = GetGeckoClipboardType(clipboard);
LOGCLIP("OnTextReceived(%s) callback\n",
whichClipboard == nsClipboard::kSelectionClipboard ? "primary"
: "clipboard");
static_cast<Request*>(data)->Complete(text);
}
void AsyncGtkClipboardRequest::Request::Complete(const void* aData) {
LOGCLIP("Request::Complete(), aData = %p, timedOut = %d\n", aData, mTimedOut);
if (mTimedOut) {
delete this;
return;
}
mData.emplace();
gint dataLength = 0;
if (mDataType == ClipboardDataType::Targets ||
mDataType == ClipboardDataType::Data) {
dataLength = gtk_selection_data_get_length((GtkSelectionData*)aData);
} else {
dataLength = aData ? strlen((const char*)aData) : 0;
}
// Negative size means no data or data error.
if (dataLength <= 0) {
LOGCLIP(" zero dataLength, quit.\n");
return;
}
switch (mDataType) {
case ClipboardDataType::Targets: {
LOGCLIP(" getting %d bytes of clipboard targets.\n", dataLength);
gint n_targets = 0;
GdkAtom* targets = nullptr;
if (!gtk_selection_data_get_targets((GtkSelectionData*)aData, &targets,
&n_targets) ||
!n_targets) {
// We failed to get targets
return;
}
mData->SetTargets(
ClipboardTargets{GUniquePtr<GdkAtom>(targets), uint32_t(n_targets)});
break;
}
case ClipboardDataType::Text: {
LOGCLIP(" getting %d bytes of text.\n", dataLength);
mData->SetText(Span(static_cast<const char*>(aData), dataLength));
LOGCLIP(" done, mClipboardData = %p\n", mData->AsSpan().data());
break;
}
case ClipboardDataType::Data: {
LOGCLIP(" getting %d bytes of data.\n", dataLength);
mData->SetData(Span(gtk_selection_data_get_data((GtkSelectionData*)aData),
dataLength));
LOGCLIP(" done, mClipboardData = %p\n", mData->AsSpan().data());
break;
}
}
}
AsyncGtkClipboardRequest::~AsyncGtkClipboardRequest() {
if (mRequest && mRequest->mData.isNothing()) {
mRequest->mTimedOut = true;
Unused << mRequest.release();
}
}
} // namespace mozilla
|