[evolution] Move the clipboard handling from EMsgComposer to EHTMLEditorView
- From: Tomas Popela <tpopela src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution] Move the clipboard handling from EMsgComposer to EHTMLEditorView
- Date: Wed, 4 May 2016 12:48:25 +0000 (UTC)
commit 2a1ce52988fa8c94154c2a6293312040af3ced78
Author: Tomas Popela <tpopela redhat com>
Date: Wed May 4 14:41:37 2016 +0200
Move the clipboard handling from EMsgComposer to EHTMLEditorView
Before this change the clipboard handling would be different when the view was
embedded inside a composer or e.g. in the signature editor. Move the handling
to EHTMLEditorView to unify the behavior for most cases apart from pasting an
image or uri in the plain text mode as the content is inserted to the attachment
view.
composer/e-composer-private.c | 130 +++---------------------------
composer/e-composer-private.h | 6 +-
composer/e-msg-composer.c | 107 ++++++++-----------------
e-util/e-html-editor-selection.c | 1 +
e-util/e-html-editor-view.c | 166 ++++++++++++++++++++++++++++++++++++++
e-util/e-html-editor-view.h | 2 +
e-util/e-misc-utils.c | 54 ++++++++++++
e-util/e-misc-utils.h | 2 +
8 files changed, 272 insertions(+), 196 deletions(-)
---
diff --git a/composer/e-composer-private.c b/composer/e-composer-private.c
index 708cc1d..65b8dd5 100644
--- a/composer/e-composer-private.c
+++ b/composer/e-composer-private.c
@@ -139,6 +139,7 @@ e_composer_private_constructed (EMsgComposer *composer)
priv->check_if_signature_is_changed = FALSE;
priv->ignore_next_signature_change = FALSE;
priv->dnd_history_saved = FALSE;
+ priv->ignore_next_paste_clipboard_signals_emission = FALSE;
priv->focused_entry = NULL;
@@ -495,48 +496,13 @@ e_composer_get_default_charset (void)
}
gboolean
-e_composer_paste_html (EMsgComposer *composer,
- GtkClipboard *clipboard)
-{
- EHTMLEditor *editor;
- EHTMLEditorView *view;
- EHTMLEditorSelection *editor_selection;
- gchar *html;
-
- g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE);
- g_return_val_if_fail (GTK_IS_CLIPBOARD (clipboard), FALSE);
-
- if (!(html = e_clipboard_wait_for_html (clipboard)))
- return FALSE;
-
- g_return_val_if_fail (html != NULL, FALSE);
-
- editor = e_msg_composer_get_editor (composer);
- view = e_html_editor_get_view (editor);
- editor_selection = e_html_editor_view_get_selection (view);
- /* If Web View doesn't have focus, focus it */
- if (!gtk_widget_has_focus (GTK_WIDGET (view)))
- gtk_widget_grab_focus (GTK_WIDGET (view));
- e_html_editor_selection_insert_html (editor_selection, html);
-
- g_free (html);
-
- return TRUE;
-}
-
-gboolean
e_composer_paste_image (EMsgComposer *composer,
GtkClipboard *clipboard)
{
- EHTMLEditor *editor;
- EHTMLEditorView *html_editor_view;
+ EAttachment *attachment;
EAttachmentStore *store;
EAttachmentView *view;
- GdkPixbuf *pixbuf = NULL;
- gchar *filename = NULL;
- gchar *uri = NULL;
- gboolean success = FALSE;
- GError *error = NULL;
+ gchar *uri;
g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE);
g_return_val_if_fail (GTK_IS_CLIPBOARD (clipboard), FALSE);
@@ -544,91 +510,17 @@ e_composer_paste_image (EMsgComposer *composer,
view = e_msg_composer_get_attachment_view (composer);
store = e_attachment_view_get_store (view);
- /* Extract the image data from the clipboard. */
- pixbuf = gtk_clipboard_wait_for_image (clipboard);
- g_return_val_if_fail (pixbuf != NULL, FALSE);
-
- /* Reserve a temporary file. */
- filename = e_mktemp (NULL);
- if (filename == NULL) {
- g_set_error (
- &error, G_FILE_ERROR,
- g_file_error_from_errno (errno),
- "Could not create temporary file: %s",
- g_strerror (errno));
- goto exit;
- }
-
- /* Save the pixbuf as a temporary file in image/png format. */
- if (!gdk_pixbuf_save (pixbuf, filename, "png", &error, NULL))
- goto exit;
-
- /* Convert the filename to a URI. */
- uri = g_filename_to_uri (filename, NULL, &error);
- if (uri == NULL)
- goto exit;
-
- /* In HTML mode, paste the image into the message body.
- * In text mode, add the image to the attachment store. */
- editor = e_msg_composer_get_editor (composer);
- html_editor_view = e_html_editor_get_view (editor);
- if (e_html_editor_view_get_html_mode (html_editor_view)) {
- EHTMLEditorSelection *selection;
-
- selection = e_html_editor_view_get_selection (html_editor_view);
- e_html_editor_selection_insert_image (selection, uri);
- e_html_editor_selection_scroll_to_caret (selection);
- } else {
- EAttachment *attachment;
-
- attachment = e_attachment_new_for_uri (uri);
- e_attachment_store_add_attachment (store, attachment);
- e_attachment_load_async (
- attachment, (GAsyncReadyCallback)
- e_attachment_load_handle_error, composer);
- g_object_unref (attachment);
- }
-
- success = TRUE;
-
-exit:
- if (error != NULL) {
- g_warning ("%s", error->message);
- g_error_free (error);
- }
-
- g_object_unref (pixbuf);
- g_free (filename);
- g_free (uri);
-
- return success;
-}
-
-gboolean
-e_composer_paste_text (EMsgComposer *composer,
- GtkClipboard *clipboard)
-{
- EHTMLEditor *editor;
- EHTMLEditorView *view;
- EHTMLEditorSelection *editor_selection;
- gchar *text;
-
- g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE);
- g_return_val_if_fail (GTK_IS_CLIPBOARD (clipboard), FALSE);
-
- if (!(text = gtk_clipboard_wait_for_text (clipboard)))
+ if (!(uri = e_util_save_image_from_clipboard (clipboard)))
return FALSE;
- editor = e_msg_composer_get_editor (composer);
- view = e_html_editor_get_view (editor);
- editor_selection = e_html_editor_view_get_selection (view);
- /* If WebView doesn't have focus, focus it */
- if (!gtk_widget_has_focus (GTK_WIDGET (view)))
- gtk_widget_grab_focus (GTK_WIDGET (view));
-
- e_html_editor_selection_insert_text (editor_selection, text);
+ attachment = e_attachment_new_for_uri (uri);
+ e_attachment_store_add_attachment (store, attachment);
+ e_attachment_load_async (
+ attachment, (GAsyncReadyCallback)
+ e_attachment_load_handle_error, composer);
+ g_object_unref (attachment);
- g_free (text);
+ g_free (uri);
return TRUE;
}
diff --git a/composer/e-composer-private.h b/composer/e-composer-private.h
index 4672e55..9a90499 100644
--- a/composer/e-composer-private.h
+++ b/composer/e-composer-private.h
@@ -105,6 +105,8 @@ struct _EMsgComposerPrivate {
gboolean ignore_next_signature_change;
gboolean is_sending_message;
gboolean dnd_history_saved;
+ gboolean ignore_next_paste_clipboard_signals_emission;
+ gboolean last_signal_was_paste_primary;
gint focused_entry_selection_start;
gint focused_entry_selection_end;
@@ -130,12 +132,8 @@ gchar * e_composer_find_data_file (const gchar *basename);
gchar * e_composer_get_default_charset (void);
gchar * e_composer_decode_clue_value (const gchar *encoded_value);
gchar * e_composer_encode_clue_value (const gchar *decoded_value);
-gboolean e_composer_paste_html (EMsgComposer *composer,
- GtkClipboard *clipboard);
gboolean e_composer_paste_image (EMsgComposer *composer,
GtkClipboard *clipboard);
-gboolean e_composer_paste_text (EMsgComposer *composer,
- GtkClipboard *clipboard);
gboolean e_composer_paste_uris (EMsgComposer *composer,
GtkClipboard *clipboard);
gboolean e_composer_selection_is_base64_uris
diff --git a/composer/e-msg-composer.c b/composer/e-msg-composer.c
index f70484f..fe49d14 100644
--- a/composer/e-msg-composer.c
+++ b/composer/e-msg-composer.c
@@ -1706,65 +1706,60 @@ msg_composer_paste_clipboard_targets_cb (GtkClipboard *clipboard,
return;
}
- /* Prefer plain text over HTML when in the plain text mode, but only
- * when pasting content from outside the editor view. */
- if (e_html_editor_view_get_html_mode (editor_view) ||
- e_html_editor_view_is_pasting_content_from_itself (editor_view)) {
- if (e_targets_include_html (targets, n_targets)) {
- e_composer_paste_html (composer, clipboard);
- return;
- }
-
- if (gtk_targets_include_text (targets, n_targets)) {
- e_composer_paste_text (composer, clipboard);
- return;
- }
- } else {
- if (gtk_targets_include_text (targets, n_targets)) {
- e_composer_paste_text (composer, clipboard);
- return;
- }
-
- if (e_targets_include_html (targets, n_targets)) {
- e_composer_paste_html (composer, clipboard);
- return;
- }
- }
-
- if (gtk_targets_include_image (targets, n_targets, TRUE)) {
+ if (!e_html_editor_view_get_html_mode (editor_view) &&
+ gtk_targets_include_image (targets, n_targets, TRUE)) {
e_composer_paste_image (composer, clipboard);
return;
}
+
+ composer->priv->ignore_next_paste_clipboard_signals_emission = TRUE;
+
+ g_signal_emit_by_name (
+ editor_view,
+ composer->priv->last_signal_was_paste_primary ?
+ "paste-primary-clipboard" : "paste-clipboard");
}
static void
msg_composer_paste_primary_clipboard_cb (EHTMLEditorView *view,
EMsgComposer *composer)
{
- GtkClipboard *clipboard;
+ if (composer->priv->ignore_next_paste_clipboard_signals_emission)
+ composer->priv->ignore_next_paste_clipboard_signals_emission = FALSE;
+ else {
+ GtkClipboard *clipboard;
- clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
+ clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
- gtk_clipboard_request_targets (
- clipboard, (GtkClipboardTargetsReceivedFunc)
- msg_composer_paste_clipboard_targets_cb, composer);
+ composer->priv->last_signal_was_paste_primary = TRUE;
- g_signal_stop_emission_by_name (view, "paste-primary-clipboard");
+ gtk_clipboard_request_targets (
+ clipboard, (GtkClipboardTargetsReceivedFunc)
+ msg_composer_paste_clipboard_targets_cb, composer);
+
+ g_signal_stop_emission_by_name (view, "paste-primary-clipboard");
+ }
}
static void
msg_composer_paste_clipboard_cb (EHTMLEditorView *view,
EMsgComposer *composer)
{
- GtkClipboard *clipboard;
+ if (composer->priv->ignore_next_paste_clipboard_signals_emission)
+ composer->priv->ignore_next_paste_clipboard_signals_emission = FALSE;
+ else {
+ GtkClipboard *clipboard;
+
+ clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
- clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
+ composer->priv->last_signal_was_paste_primary = FALSE;
- gtk_clipboard_request_targets (
- clipboard, (GtkClipboardTargetsReceivedFunc)
- msg_composer_paste_clipboard_targets_cb, composer);
+ gtk_clipboard_request_targets (
+ clipboard, (GtkClipboardTargetsReceivedFunc)
+ msg_composer_paste_clipboard_targets_cb, composer);
- g_signal_stop_emission_by_name (view, "paste-clipboard");
+ g_signal_stop_emission_by_name (view, "paste-clipboard");
+ }
}
static gboolean
@@ -2659,6 +2654,7 @@ msg_composer_constructed (GObject *object)
html_editor_view, "paste-primary-clipboard",
G_CALLBACK (msg_composer_paste_primary_clipboard_cb), composer);
+ e_html_editor_view_reconnect_paste_clipboard_signals (html_editor_view);
/* Drag-and-Drop Support */
g_signal_connect (
@@ -2882,41 +2878,6 @@ msg_composer_key_press_event (GtkWidget *widget,
return TRUE;
}
-
- if ((((event)->state & GDK_SHIFT_MASK) &&
- ((event)->keyval == GDK_KEY_Insert)) ||
- (((event)->state & GDK_CONTROL_MASK) &&
- ((event)->keyval == GDK_KEY_v))) {
- g_signal_emit_by_name (
- WEBKIT_WEB_VIEW (view), "paste-clipboard");
- return TRUE;
- }
-
- if (((event)->state & GDK_CONTROL_MASK) &&
- ((event)->keyval == GDK_KEY_Insert)) {
- g_signal_emit_by_name (
- WEBKIT_WEB_VIEW (view), "copy-clipboard");
- return TRUE;
- }
-
- if (((event)->state & GDK_CONTROL_MASK) &&
- ((event)->keyval == GDK_KEY_z)) {
- e_html_editor_view_undo (view);
- return TRUE;
- }
-
- if (((event)->state & (GDK_CONTROL_MASK)) &&
- ((event)->keyval == GDK_KEY_Z)) {
- e_html_editor_view_redo (view);
- return TRUE;
- }
-
- if (((event)->state & GDK_SHIFT_MASK) &&
- ((event)->keyval == GDK_KEY_Delete)) {
- g_signal_emit_by_name (
- WEBKIT_WEB_VIEW (view), "cut-clipboard");
- return TRUE;
- }
}
/* Chain up to parent's key_press_event() method. */
diff --git a/e-util/e-html-editor-selection.c b/e-util/e-html-editor-selection.c
index fdbeabf..3dc12d1 100644
--- a/e-util/e-html-editor-selection.c
+++ b/e-util/e-html-editor-selection.c
@@ -5991,6 +5991,7 @@ insert_base64_image (EHTMLEditorSelection *selection,
e_html_editor_selection_restore (selection);
e_html_editor_view_force_spell_check_for_current_paragraph (view);
+ e_html_editor_selection_scroll_to_caret (selection);
g_object_unref (view);
}
diff --git a/e-util/e-html-editor-view.c b/e-util/e-html-editor-view.c
index c5a9808..4f241c1 100644
--- a/e-util/e-html-editor-view.c
+++ b/e-util/e-html-editor-view.c
@@ -6106,6 +6106,41 @@ html_editor_view_key_press_event (GtkWidget *widget,
return event_handled;
}
+ if ((((event)->state & GDK_SHIFT_MASK) &&
+ ((event)->keyval == GDK_KEY_Insert)) ||
+ (((event)->state & GDK_CONTROL_MASK) &&
+ ((event)->keyval == GDK_KEY_v))) {
+ g_signal_emit_by_name (
+ WEBKIT_WEB_VIEW (view), "paste-clipboard");
+ return TRUE;
+ }
+
+ if (((event)->state & GDK_CONTROL_MASK) &&
+ ((event)->keyval == GDK_KEY_Insert)) {
+ g_signal_emit_by_name (
+ WEBKIT_WEB_VIEW (view), "copy-clipboard");
+ return TRUE;
+ }
+
+ if (((event)->state & GDK_CONTROL_MASK) &&
+ ((event)->keyval == GDK_KEY_z)) {
+ e_html_editor_view_undo (view);
+ return TRUE;
+ }
+
+ if (((event)->state & (GDK_CONTROL_MASK)) &&
+ ((event)->keyval == GDK_KEY_Z)) {
+ e_html_editor_view_redo (view);
+ return TRUE;
+ }
+
+ if (((event)->state & GDK_SHIFT_MASK) &&
+ ((event)->keyval == GDK_KEY_Delete)) {
+ g_signal_emit_by_name (
+ WEBKIT_WEB_VIEW (view), "cut-clipboard");
+ return TRUE;
+ }
+
if (event->keyval == GDK_KEY_Tab || event->keyval == GDK_KEY_ISO_Left_Tab) {
if (jump_to_next_table_cell (view, event->keyval == GDK_KEY_ISO_Left_Tab))
return TRUE;
@@ -11561,6 +11596,130 @@ html_editor_view_copy_cut_clipboard_cb (EHTMLEditorView *view)
}
static void
+html_editor_view_paste_clipboard_targets_cb (GtkClipboard *clipboard,
+ GdkAtom *targets,
+ gint n_targets,
+ EHTMLEditorView *view)
+{
+ EHTMLEditorSelection *selection;
+
+ if (targets == NULL || n_targets < 0)
+ return;
+
+ selection = e_html_editor_view_get_selection (view);
+
+ /* If view doesn't have focus, focus it */
+ if (!gtk_widget_has_focus (GTK_WIDGET (view)))
+ gtk_widget_grab_focus (GTK_WIDGET (view));
+
+ /* Order is important here to ensure common use cases are
+ * handled correctly. See GNOME bug #603715 for details. */
+ /* Prefer plain text over HTML when in the plain text mode, but only
+ * when pasting content from outside the editor view. */
+ if (e_html_editor_view_get_html_mode (view) ||
+ e_html_editor_view_is_pasting_content_from_itself (view)) {
+ gchar *content = NULL;
+
+ if (e_targets_include_html (targets, n_targets)) {
+ if (!(content = e_clipboard_wait_for_html (clipboard)))
+ return;
+
+ e_html_editor_selection_insert_html (selection, content);
+ g_free (content);
+ return;
+ }
+
+ if (gtk_targets_include_text (targets, n_targets)) {
+ if (!(content = gtk_clipboard_wait_for_text (clipboard)))
+ return;
+
+ e_html_editor_selection_insert_text (selection, content);
+ g_free (content);
+ return;
+ }
+ } else {
+ gchar *content = NULL;
+
+ if (gtk_targets_include_text (targets, n_targets)) {
+ if (!(content = gtk_clipboard_wait_for_text (clipboard)))
+ return;
+
+ e_html_editor_selection_insert_text (selection, content);
+ g_free (content);
+ return;
+ }
+
+ if (e_targets_include_html (targets, n_targets)) {
+ if (!(content = e_clipboard_wait_for_html (clipboard)))
+ return;
+
+ e_html_editor_selection_insert_html (selection, content);
+ g_free (content);
+ return;
+ }
+ }
+
+ if (gtk_targets_include_image (targets, n_targets, TRUE)) {
+ gchar *uri;
+
+ if (!(uri = e_util_save_image_from_clipboard (clipboard)))
+ return;
+
+ e_html_editor_selection_insert_image (selection, uri);
+
+ g_free (uri);
+
+ return;
+ }
+}
+
+static void
+html_editor_view_paste_primary_clipboard_cb (EHTMLEditorView *view)
+{
+ GtkClipboard *clipboard;
+
+ clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
+
+ gtk_clipboard_request_targets (
+ clipboard, (GtkClipboardTargetsReceivedFunc)
+ html_editor_view_paste_clipboard_targets_cb, view);
+
+ g_signal_stop_emission_by_name (view, "paste-primary-clipboard");
+}
+
+static void
+html_editor_view_paste_clipboard_cb (EHTMLEditorView *view)
+{
+ GtkClipboard *clipboard;
+
+ clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
+
+ gtk_clipboard_request_targets (
+ clipboard, (GtkClipboardTargetsReceivedFunc)
+ html_editor_view_paste_clipboard_targets_cb, view);
+
+ g_signal_stop_emission_by_name (view, "paste-clipboard");
+}
+
+void
+e_html_editor_view_reconnect_paste_clipboard_signals (EHTMLEditorView *view)
+{
+ g_return_if_fail (E_IS_HTML_EDITOR_VIEW (view));
+
+ g_signal_handlers_disconnect_by_func (
+ view, html_editor_view_paste_clipboard_cb, NULL);
+ g_signal_handlers_disconnect_by_func (
+ view, html_editor_view_paste_primary_clipboard_cb, NULL);
+
+ g_signal_connect (
+ view, "paste-clipboard",
+ G_CALLBACK (html_editor_view_paste_clipboard_cb), NULL);
+ g_signal_connect (
+ view, "paste-primary-clipboard",
+ G_CALLBACK (html_editor_view_paste_primary_clipboard_cb), NULL);
+}
+
+static void
e_html_editor_view_init (EHTMLEditorView *view)
{
WebKitWebSettings *settings;
@@ -11630,6 +11789,13 @@ e_html_editor_view_init (EHTMLEditorView *view)
G_CALLBACK (html_editor_view_load_status_changed), NULL);
g_signal_connect (
+ view, "paste-clipboard",
+ G_CALLBACK (html_editor_view_paste_clipboard_cb), NULL);
+ g_signal_connect (
+ view, "paste-primary-clipboard",
+ G_CALLBACK (html_editor_view_paste_primary_clipboard_cb), NULL);
+
+ g_signal_connect (
view, "style-updated",
G_CALLBACK (style_updated_cb), NULL);
diff --git a/e-util/e-html-editor-view.h b/e-util/e-html-editor-view.h
index 67c399f..724ef24 100644
--- a/e-util/e-html-editor-view.h
+++ b/e-util/e-html-editor-view.h
@@ -335,6 +335,8 @@ gchar * e_html_editor_view_insert_signature
gboolean *check_if_signature_is_changed,
gboolean *ignore_next_signature_change);
gboolean e_html_editor_view_is_ready (EHTMLEditorView *view);
+void e_html_editor_view_reconnect_paste_clipboard_signals
+ (EHTMLEditorView *view);
G_END_DECLS
#endif /* E_HTML_EDITOR_VIEW_H */
diff --git a/e-util/e-misc-utils.c b/e-util/e-misc-utils.c
index baa0849..1bc7d8d 100644
--- a/e-util/e-misc-utils.c
+++ b/e-util/e-misc-utils.c
@@ -56,6 +56,7 @@
#include "e-client-cache.h"
#include "e-filter-option.h"
#include "e-util-private.h"
+#include "e-mktemp.h"
typedef struct _WindowData WindowData;
@@ -3342,3 +3343,56 @@ e_util_set_entry_issue_hint (GtkWidget *entry,
gtk_entry_set_icon_tooltip_text (eentry, GTK_ENTRY_ICON_SECONDARY, NULL);
}
}
+
+/**
+ * e_util_save_image_from_clipboard:
+ * @clipboard: a #GtkClipboard
+ * @hint: (allow none): a hint to set, or %NULL to unset
+ *
+ * Saves the image from @clipboard to a temporary file and returns its URI.
+ *
+ * Since: 3.22
+ **/
+gchar *
+e_util_save_image_from_clipboard (GtkClipboard *clipboard)
+{
+ GdkPixbuf *pixbuf = NULL;
+ gchar *filename = NULL;
+ gchar *uri = NULL;
+ GError *error = NULL;
+
+ g_return_val_if_fail (GTK_IS_CLIPBOARD (clipboard), NULL);
+
+ /* Extract the image data from the clipboard. */
+ pixbuf = gtk_clipboard_wait_for_image (clipboard);
+ g_return_val_if_fail (pixbuf != NULL, FALSE);
+
+ /* Reserve a temporary file. */
+ filename = e_mktemp (NULL);
+ if (filename == NULL) {
+ g_set_error (
+ &error, G_FILE_ERROR,
+ g_file_error_from_errno (errno),
+ "Could not create temporary file: %s",
+ g_strerror (errno));
+ goto exit;
+ }
+
+ /* Save the pixbuf as a temporary file in image/png format. */
+ if (!gdk_pixbuf_save (pixbuf, filename, "png", &error, NULL))
+ goto exit;
+
+ /* Convert the filename to a URI. */
+ uri = g_filename_to_uri (filename, NULL, &error);
+
+exit:
+ if (error != NULL) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+
+ g_object_unref (pixbuf);
+ g_free (filename);
+
+ return uri;
+}
diff --git a/e-util/e-misc-utils.h b/e-util/e-misc-utils.h
index 7b41112..bde194a 100644
--- a/e-util/e-misc-utils.h
+++ b/e-util/e-misc-utils.h
@@ -290,6 +290,8 @@ gboolean e_util_is_running_gnome (void);
void e_util_set_entry_issue_hint (GtkWidget *entry,
const gchar *hint);
+gchar * e_util_save_image_from_clipboard
+ (GtkClipboard *clipboard);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]