diff options
Diffstat (limited to 'src/st/st-clipboard.c')
-rw-r--r-- | src/st/st-clipboard.c | 348 |
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; +} |