#include #ifdef GDK_WINDOWING_WAYLAND #include "wayland/gdkwayland.h" #endif #ifdef G_OS_WIN32 #include #include #endif G_GNUC_NORETURN static void got_string_cb (GObject *source, GAsyncResult *result, gpointer data) { GdkClipboard *clipboard = GDK_CLIPBOARD (source); GError *error = NULL; char *text; text = gdk_clipboard_read_text_finish (clipboard, result, &error); if (text) { g_print ("%s", text); g_free (text); } else { g_print ("ERROR: %s", error->message); g_clear_error (&error); } exit (0); } G_GNUC_NORETURN static void got_text_cb (GObject *source, GAsyncResult *result, gpointer data) { GdkClipboard *clipboard = GDK_CLIPBOARD (source); GError *error = NULL; char *text; text = gdk_clipboard_read_text_finish (clipboard, result, &error); if (text) { int fd; char *name; fd = g_file_open_tmp ("XXXXXX.out", &name, &error); if (error) g_error ("Failed to create tmp file: %s", error->message); close (fd); g_file_set_contents (name, text, -1, &error); g_print ("%s", name); g_free (text); g_free (name); } else { g_print ("ERROR: %s", error->message); g_clear_error (&error); } exit (0); } G_GNUC_NORETURN static void got_texture_cb (GObject *source, GAsyncResult *result, gpointer data) { GdkClipboard *clipboard = GDK_CLIPBOARD (source); GError *error = NULL; GdkTexture *texture; texture = gdk_clipboard_read_texture_finish (clipboard, result, &error); if (texture) { int fd; char *name; fd = g_file_open_tmp ("XXXXXX.out", &name, &error); if (error) g_error ("Failed to create tmp file: %s", error->message); close (fd); gdk_texture_save_to_png (texture, name); g_print ("%s", name); g_object_unref (texture); g_free (name); } else { g_print ("ERROR: %s", error->message); g_clear_error (&error); } exit (0); } G_GNUC_NORETURN static void got_file (GObject *source, GAsyncResult *result, gpointer data) { GdkClipboard *clipboard = GDK_CLIPBOARD (source); GError *error = NULL; const GValue *value; value = gdk_clipboard_read_value_finish (clipboard, result, &error); if (value) { GFile *file = g_value_get_object (value); char *path = g_file_get_path (file); g_print ("%s", path); g_free (path); } else { g_print ("ERROR: %s", error->message); g_clear_error (&error); } exit (0); } G_GNUC_NORETURN static void got_files (GObject *source, GAsyncResult *result, gpointer data) { GdkClipboard *clipboard = GDK_CLIPBOARD (source); GError *error = NULL; const GValue *value; value = gdk_clipboard_read_value_finish (clipboard, result, &error); if (value) { GSList *files = g_value_get_boxed (value); for (GSList *l = files; l; l = l->next) { GFile *file = l->data; char *path = g_file_get_path (file); if (l != files) g_print (":"); g_print ("%s", path); g_free (path); } } else { g_print ("ERROR: %s", error->message); g_clear_error (&error); } exit (0); } G_GNUC_NORETURN static void got_color (GObject *source, GAsyncResult *result, gpointer data) { GdkClipboard *clipboard = GDK_CLIPBOARD (source); GError *error = NULL; const GValue *value; value = gdk_clipboard_read_value_finish (clipboard, result, &error); if (value) { GdkRGBA *color = g_value_get_boxed (value); char *s = gdk_rgba_to_string (color); g_print ("%s", s); g_free (s); } else { g_print ("ERROR: %s", error->message); g_clear_error (&error); } exit (0); } static const char *action; static const char *type; static const char *value; static gulong handler; static void do_it (GObject *object, GParamSpec *pspec) { GdkClipboard *clipboard; if (object) g_signal_handler_disconnect (object, handler); clipboard = gdk_display_get_clipboard (gdk_display_get_default ()); if (strcmp (action, "info") == 0) { GdkContentFormats *formats; char *s; formats = gdk_clipboard_get_formats (clipboard); s = gdk_content_formats_to_string (formats); g_print ("%s\n", s); g_free (s); } else if (strcmp (action, "set") == 0) { GdkContentFormats *formats; char *s; if (strcmp (type, "string") == 0) { gdk_clipboard_set_text (clipboard, value); } else if (strcmp (type, "text") == 0) { char *contents; gsize len; if (!g_file_get_contents (value, &contents, &len, NULL)) g_error ("Failed to read %s\n", value); gdk_clipboard_set_text (clipboard, contents); g_free (contents); } else if (strcmp (type, "image") == 0) { GFile *file; GdkTexture *texture; file = g_file_new_for_commandline_arg (value); texture = gdk_texture_new_from_file (file, NULL); if (!texture) g_error ("Failed to read %s\n", value); gdk_clipboard_set_texture (clipboard, texture); g_object_unref (texture); g_object_unref (file); } else if (strcmp (type, "file") == 0) { GFile *file; file = g_file_new_for_commandline_arg (value); gdk_clipboard_set (clipboard, G_TYPE_FILE, file); g_object_unref (file); } else if (strcmp (type, "files") == 0) { char **strv; GSList *files; strv = g_strsplit (value, ":", 0); files = NULL; for (int i = 0; strv[i]; i++) files = g_slist_append (files, g_file_new_for_commandline_arg (strv[i])); gdk_clipboard_set (clipboard, GDK_TYPE_FILE_LIST, files); g_slist_free_full (files, g_object_unref); g_strfreev (strv); } else if (strcmp (type, "color") == 0) { GdkRGBA color; gdk_rgba_parse (&color, value); gdk_clipboard_set (clipboard, GDK_TYPE_RGBA, &color); } else g_error ("can't set %s", type); formats = gdk_clipboard_get_formats (clipboard); s = gdk_content_formats_to_string (formats); g_print ("%s\n", s); g_free (s); } else if (strcmp (action, "get") == 0) { if (strcmp (type, "string") == 0) { gdk_clipboard_read_text_async (clipboard, NULL, got_string_cb, NULL); } else if (strcmp (type, "text") == 0) { gdk_clipboard_read_text_async (clipboard, NULL, got_text_cb, NULL); } else if (strcmp (type, "image") == 0) { gdk_clipboard_read_texture_async (clipboard, NULL, got_texture_cb, NULL); } else if (strcmp (type, "file") == 0) { gdk_clipboard_read_value_async (clipboard, G_TYPE_FILE, 0, NULL, got_file, NULL); } else if (strcmp (type, "files") == 0) { gdk_clipboard_read_value_async (clipboard, GDK_TYPE_FILE_LIST, 0, NULL, got_files, NULL); } else if (strcmp (type, "color") == 0) { gdk_clipboard_read_value_async (clipboard, GDK_TYPE_RGBA, 0, NULL, got_color, NULL); } else g_error ("can't get %s", type); } else g_error ("can only set, get or info"); } int main (int argc, char *argv[]) { GtkWidget *window; gboolean done = FALSE; if (argc < 2) g_error ("too few arguments"); action = argv[1]; if (strcmp (action, "info") == 0) { } else if (strcmp (action, "set") == 0) { if (argc < 4) g_error ("too few arguments for set"); type = argv[2]; value = argv[3]; } else if (strcmp (action, "get") == 0) { if (argc < 3) g_error ("too few arguments for get"); type = argv[2]; } else g_error ("can only set or get"); gtk_init (); /* Don't wait for a window manager to give us focus when * we may be running on bare wm-less X. */ #ifdef GDK_WINDOWING_WAYLAND if (GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ())) { window = gtk_window_new (); gtk_window_present (GTK_WINDOW (window)); handler = g_signal_connect (window, "notify::is-active", G_CALLBACK (do_it), NULL); } else #endif do_it (NULL, NULL); while (!done) g_main_context_iteration (NULL, TRUE); return 0; }