summaryrefslogtreecommitdiffstats
path: root/widget/gtk/AsyncGtkClipboardRequest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'widget/gtk/AsyncGtkClipboardRequest.cpp')
-rw-r--r--widget/gtk/AsyncGtkClipboardRequest.cpp120
1 files changed, 120 insertions, 0 deletions
diff --git a/widget/gtk/AsyncGtkClipboardRequest.cpp b/widget/gtk/AsyncGtkClipboardRequest.cpp
new file mode 100644
index 0000000000..75801c698d
--- /dev/null
+++ b/widget/gtk/AsyncGtkClipboardRequest.cpp
@@ -0,0 +1,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