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