/* -*- 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 . */ /** * 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 #include #include 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; }