summaryrefslogtreecommitdiffstats
path: root/src/st/st-clipboard.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/st/st-clipboard.c')
-rw-r--r--src/st/st-clipboard.c348
1 files changed, 348 insertions, 0 deletions
diff --git a/src/st/st-clipboard.c b/src/st/st-clipboard.c
new file mode 100644
index 0000000..4b730c9
--- /dev/null
+++ b/src/st/st-clipboard.c
@@ -0,0 +1,348 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * st-clipboard.c: clipboard object
+ *
+ * Copyright 2009 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * SECTION:st-clipboard
+ * @short_description: a simple representation of the clipboard
+ *
+ * #StCliboard is a very simple object representation of the clipboard
+ * available to applications. Text is always assumed to be UTF-8 and non-text
+ * items are not handled.
+ */
+
+#include "config.h"
+
+#include "st-clipboard.h"
+
+#include <meta/display.h>
+#include <meta/meta-selection-source-memory.h>
+#include <meta/meta-selection.h>
+
+G_DEFINE_TYPE (StClipboard, st_clipboard, G_TYPE_OBJECT)
+
+typedef struct _TransferData TransferData;
+struct _TransferData
+{
+ StClipboard *clipboard;
+ GCallback callback;
+ gpointer user_data;
+ GOutputStream *stream;
+};
+
+const char *supported_mimetypes[] = {
+ "text/plain;charset=utf-8",
+ "UTF8_STRING",
+ "text/plain",
+ "STRING",
+};
+
+static MetaSelection *meta_selection = NULL;
+
+static void
+st_clipboard_class_init (StClipboardClass *klass)
+{
+}
+
+static void
+st_clipboard_init (StClipboard *self)
+{
+}
+
+/**
+ * st_clipboard_get_default:
+ *
+ * Get the global #StClipboard object that represents the clipboard.
+ *
+ * Returns: (transfer none): a #StClipboard owned by St and must not be
+ * unrefferenced or freed.
+ */
+StClipboard*
+st_clipboard_get_default (void)
+{
+ static StClipboard *default_clipboard = NULL;
+
+ if (!default_clipboard)
+ {
+ default_clipboard = g_object_new (ST_TYPE_CLIPBOARD, NULL);
+ }
+
+ return default_clipboard;
+}
+
+static gboolean
+convert_type (StClipboardType type,
+ MetaSelectionType *type_out)
+{
+ if (type == ST_CLIPBOARD_TYPE_PRIMARY)
+ *type_out = META_SELECTION_PRIMARY;
+ else if (type == ST_CLIPBOARD_TYPE_CLIPBOARD)
+ *type_out = META_SELECTION_CLIPBOARD;
+ else
+ return FALSE;
+
+ return TRUE;
+}
+
+static const char *
+pick_mimetype (MetaSelection *meta_selection,
+ MetaSelectionType selection_type)
+{
+ const char *selected_mimetype = NULL;
+ GList *mimetypes;
+ int i;
+
+ mimetypes = meta_selection_get_mimetypes (meta_selection, selection_type);
+
+ for (i = 0; i < G_N_ELEMENTS (supported_mimetypes); i++)
+ {
+ if (g_list_find_custom (mimetypes, supported_mimetypes[i],
+ (GCompareFunc) g_strcmp0))
+ {
+ selected_mimetype = supported_mimetypes[i];
+ break;
+ }
+ }
+
+ g_list_free_full (mimetypes, g_free);
+ return selected_mimetype;
+}
+
+static void
+transfer_cb (MetaSelection *selection,
+ GAsyncResult *res,
+ TransferData *data)
+{
+ gchar *text = NULL;
+
+ if (meta_selection_transfer_finish (selection, res, NULL))
+ {
+ gsize data_size;
+
+ data_size =
+ g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (data->stream));
+ text = g_new0 (char, data_size + 1);
+ memcpy (text, g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (data->stream)), data_size);
+ }
+
+ ((StClipboardCallbackFunc) data->callback) (data->clipboard, text,
+ data->user_data);
+ g_object_unref (data->stream);
+ g_free (data);
+ g_free (text);
+}
+
+static void
+transfer_bytes_cb (MetaSelection *selection,
+ GAsyncResult *res,
+ TransferData *data)
+{
+ GBytes *bytes = NULL;
+
+ if (meta_selection_transfer_finish (selection, res, NULL))
+ bytes = g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (data->stream));
+
+ ((StClipboardContentCallbackFunc) data->callback) (data->clipboard, bytes,
+ data->user_data);
+ g_object_unref (data->stream);
+ g_clear_pointer (&bytes, g_bytes_unref);
+}
+
+/**
+ * st_clipboard_get_mimetypes:
+ * @clipboard: a #StClipboard
+ *
+ * Gets a list of the mimetypes supported by the default #StClipboard.
+ *
+ * Returns: (element-type utf8) (transfer full): the supported mimetypes
+ */
+GList *
+st_clipboard_get_mimetypes (StClipboard *clipboard,
+ StClipboardType type)
+{
+ MetaSelectionType selection_type;
+
+ g_return_val_if_fail (ST_IS_CLIPBOARD (clipboard), NULL);
+ g_return_val_if_fail (meta_selection != NULL, NULL);
+
+ if (!convert_type (type, &selection_type))
+ return NULL;
+
+ return meta_selection_get_mimetypes (meta_selection, selection_type);
+}
+
+/**
+ * st_clipboard_get_text:
+ * @clipboard: A #StCliboard
+ * @type: The type of clipboard data you want
+ * @callback: (scope async): function to be called when the text is retrieved
+ * @user_data: data to be passed to the callback
+ *
+ * Request the data from the clipboard in text form. @callback is executed
+ * when the data is retrieved.
+ */
+void
+st_clipboard_get_text (StClipboard *clipboard,
+ StClipboardType type,
+ StClipboardCallbackFunc callback,
+ gpointer user_data)
+{
+ MetaSelectionType selection_type;
+ TransferData *data;
+ const char *mimetype = NULL;
+
+ g_return_if_fail (ST_IS_CLIPBOARD (clipboard));
+ g_return_if_fail (meta_selection != NULL);
+ g_return_if_fail (callback != NULL);
+
+ if (convert_type (type, &selection_type))
+ mimetype = pick_mimetype (meta_selection, selection_type);
+
+ if (!mimetype)
+ {
+ callback (clipboard, NULL, user_data);
+ return;
+ }
+
+ data = g_new0 (TransferData, 1);
+ data->clipboard = clipboard;
+ data->callback = G_CALLBACK (callback);
+ data->user_data = user_data;
+ data->stream = g_memory_output_stream_new_resizable ();
+
+ meta_selection_transfer_async (meta_selection,
+ selection_type,
+ mimetype, -1,
+ data->stream, NULL,
+ (GAsyncReadyCallback) transfer_cb,
+ data);
+}
+
+/**
+ * st_clipboard_get_content:
+ * @clipboard: A #StCliboard
+ * @type: The type of clipboard data you want
+ * @mimetype: The mimetype to get content for
+ * @callback: (scope async): function to be called when the type is retrieved
+ * @user_data: data to be passed to the callback
+ *
+ * Request the data from the clipboard in #GBytes form. @callback is executed
+ * when the data is retrieved.
+ */
+void
+st_clipboard_get_content (StClipboard *clipboard,
+ StClipboardType type,
+ const gchar *mimetype,
+ StClipboardContentCallbackFunc callback,
+ gpointer user_data)
+{
+ MetaSelectionType selection_type;
+ TransferData *data;
+
+ g_return_if_fail (ST_IS_CLIPBOARD (clipboard));
+ g_return_if_fail (meta_selection != NULL);
+ g_return_if_fail (callback != NULL);
+
+ if (!mimetype || !convert_type (type, &selection_type))
+ {
+ callback (clipboard, NULL, user_data);
+ return;
+ }
+
+ data = g_new0 (TransferData, 1);
+ data->clipboard = clipboard;
+ data->callback = G_CALLBACK (callback);
+ data->user_data = user_data;
+ data->stream = g_memory_output_stream_new_resizable ();
+
+ meta_selection_transfer_async (meta_selection,
+ selection_type,
+ mimetype, -1,
+ data->stream, NULL,
+ (GAsyncReadyCallback) transfer_bytes_cb,
+ data);
+}
+
+/**
+ * st_clipboard_set_content:
+ * @clipboard: A #StClipboard
+ * @type: The type of clipboard that you want to set
+ * @mimetype: content mimetype
+ * @bytes: content data
+ *
+ * Sets the clipboard content to @bytes.
+ *
+ * @mimetype is a semi-colon separated list of mime-type strings.
+ **/
+void
+st_clipboard_set_content (StClipboard *clipboard,
+ StClipboardType type,
+ const gchar *mimetype,
+ GBytes *bytes)
+{
+ MetaSelectionType selection_type;
+ MetaSelectionSource *source;
+
+ g_return_if_fail (ST_IS_CLIPBOARD (clipboard));
+ g_return_if_fail (meta_selection != NULL);
+ g_return_if_fail (bytes != NULL);
+
+ if (!convert_type (type, &selection_type))
+ return;
+
+ source = meta_selection_source_memory_new (mimetype, bytes);
+ meta_selection_set_owner (meta_selection, selection_type, source);
+ g_object_unref (source);
+}
+
+/**
+ * st_clipboard_set_text:
+ * @clipboard: A #StClipboard
+ * @type: The type of clipboard that you want to set
+ * @text: text to copy to the clipboard
+ *
+ * Sets text as the current contents of the clipboard.
+ */
+void
+st_clipboard_set_text (StClipboard *clipboard,
+ StClipboardType type,
+ const gchar *text)
+{
+ GBytes *bytes;
+
+ g_return_if_fail (ST_IS_CLIPBOARD (clipboard));
+ g_return_if_fail (meta_selection != NULL);
+ g_return_if_fail (text != NULL);
+
+ bytes = g_bytes_new_take (g_strdup (text), strlen (text));
+ st_clipboard_set_content (clipboard, type, "text/plain;charset=utf-8", bytes);
+ g_bytes_unref (bytes);
+}
+
+/**
+ * st_clipboard_set_selection: (skip)
+ *
+ * Sets the #MetaSelection of the default #StClipboard.
+ *
+ * This function is called during the initialization of GNOME Shell.
+ */
+void
+st_clipboard_set_selection (MetaSelection *selection)
+{
+ meta_selection = selection;
+}