clipboard.c 9.96 KB
Newer Older
Anders Carlsson's avatar
Anders Carlsson committed
1 2 3
/* Clipboard
 *
 * GtkClipboard is used for clipboard handling. This demo shows how to
4
 * copy and paste text to and from the clipboard.
5
 *
6
 * It also shows how to transfer images via the clipboard or via
7 8 9
 * drag-and-drop, and how to make clipboard contents persist after
 * the application exits. Clipboard persistence requires a clipboard
 * manager to run.
Anders Carlsson's avatar
Anders Carlsson committed
10 11 12 13 14 15 16 17 18
 */

#include <gtk/gtk.h>
#include <string.h>

static GtkWidget *window = NULL;

void
copy_button_clicked (GtkWidget *button,
19
                     gpointer   user_data)
Anders Carlsson's avatar
Anders Carlsson committed
20 21 22 23 24
{
  GtkWidget *entry;
  GtkClipboard *clipboard;

  entry = GTK_WIDGET (user_data);
25

Anders Carlsson's avatar
Anders Carlsson committed
26 27
  /* Get the clipboard object */
  clipboard = gtk_widget_get_clipboard (entry,
28
                                        GDK_SELECTION_CLIPBOARD);
Anders Carlsson's avatar
Anders Carlsson committed
29 30 31 32 33 34 35

  /* Set clipboard text */
  gtk_clipboard_set_text (clipboard, gtk_entry_get_text (GTK_ENTRY (entry)), -1);
}

void
paste_received (GtkClipboard *clipboard,
36 37
                const gchar  *text,
                gpointer      user_data)
Anders Carlsson's avatar
Anders Carlsson committed
38 39 40 41
{
  GtkWidget *entry;

  entry = GTK_WIDGET (user_data);
42

Anders Carlsson's avatar
Anders Carlsson committed
43
  /* Set the entry text */
44 45
  if(text)
    gtk_entry_set_text (GTK_ENTRY (entry), text);
Anders Carlsson's avatar
Anders Carlsson committed
46 47 48 49
}

void
paste_button_clicked (GtkWidget *button,
50
                     gpointer   user_data)
Anders Carlsson's avatar
Anders Carlsson committed
51 52 53 54 55
{
  GtkWidget *entry;
  GtkClipboard *clipboard;

  entry = GTK_WIDGET (user_data);
56

Anders Carlsson's avatar
Anders Carlsson committed
57 58
  /* Get the clipboard object */
  clipboard = gtk_widget_get_clipboard (entry,
59
                                        GDK_SELECTION_CLIPBOARD);
Anders Carlsson's avatar
Anders Carlsson committed
60 61 62 63 64

  /* Request the contents of the clipboard, contents_received will be
     called when we do get the contents.
   */
  gtk_clipboard_request_text (clipboard,
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
                              paste_received, entry);
}

static GdkPixbuf *
get_image_pixbuf (GtkImage *image)
{
  gchar *stock_id;
  GtkIconSize size;

  switch (gtk_image_get_storage_type (image))
    {
    case GTK_IMAGE_PIXBUF:
      return g_object_ref (gtk_image_get_pixbuf (image));
    case GTK_IMAGE_STOCK:
      gtk_image_get_stock (image, &stock_id, &size);
      return gtk_widget_render_icon (GTK_WIDGET (image),
                                     stock_id, size, NULL);
    default:
83
      g_warning ("Image storage type %d not handled",
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
                 gtk_image_get_storage_type (image));
      return NULL;
    }
}

static void
drag_begin (GtkWidget      *widget,
            GdkDragContext *context,
            gpointer        data)
{
  GdkPixbuf *pixbuf;

  pixbuf = get_image_pixbuf (GTK_IMAGE (data));
  gtk_drag_set_icon_pixbuf (context, pixbuf, -2, -2);
  g_object_unref (pixbuf);
}

101
void
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
drag_data_get  (GtkWidget        *widget,
                GdkDragContext   *context,
                GtkSelectionData *selection_data,
                guint             info,
                guint             time,
                gpointer          data)
{
  GdkPixbuf *pixbuf;

  pixbuf = get_image_pixbuf (GTK_IMAGE (data));
  gtk_selection_data_set_pixbuf (selection_data, pixbuf);
  g_object_unref (pixbuf);
}

static void
drag_data_received (GtkWidget        *widget,
                    GdkDragContext   *context,
                    gint              x,
                    gint              y,
                    GtkSelectionData *selection_data,
                    guint             info,
                    guint32           time,
                    gpointer          data)
{
  GdkPixbuf *pixbuf;

  if (selection_data->length > 0)
    {
      pixbuf = gtk_selection_data_get_pixbuf (selection_data);
      gtk_image_set_from_pixbuf (GTK_IMAGE (data), pixbuf);
      g_object_unref (pixbuf);
    }
}

static void
copy_image (GtkMenuItem *item,
            gpointer     data)
{
  GtkClipboard *clipboard;
  GdkPixbuf *pixbuf;

  clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
  pixbuf = get_image_pixbuf (GTK_IMAGE (data));

  gtk_clipboard_set_image (clipboard, pixbuf);
  g_object_unref (pixbuf);
}

static void
paste_image (GtkMenuItem *item,
             gpointer     data)
{
  GtkClipboard *clipboard;
  GdkPixbuf *pixbuf;

  clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
  pixbuf = gtk_clipboard_wait_for_image (clipboard);

  if (pixbuf)
    {
      gtk_image_set_from_pixbuf (GTK_IMAGE (data), pixbuf);
      g_object_unref (pixbuf);
    }
}

static gboolean
button_press (GtkWidget      *widget,
              GdkEventButton *button,
              gpointer        data)
{
  GtkWidget *menu;
  GtkWidget *item;
174

175 176 177 178
  if (button->button != 3)
    return FALSE;

  menu = gtk_menu_new ();
179

180 181 182 183 184 185 186 187 188 189 190 191
  item = gtk_image_menu_item_new_from_stock (GTK_STOCK_COPY, NULL);
  g_signal_connect (item, "activate", G_CALLBACK (copy_image), data);
  gtk_widget_show (item);
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);

  item = gtk_image_menu_item_new_from_stock (GTK_STOCK_PASTE, NULL);
  g_signal_connect (item, "activate", G_CALLBACK (paste_image), data);
  gtk_widget_show (item);
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);

  gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 3, button->time);
  return TRUE;
Anders Carlsson's avatar
Anders Carlsson committed
192 193 194 195 196 197 198 199 200 201
}

GtkWidget *
do_clipboard (GtkWidget *do_widget)
{
  if (!window)
    {
      GtkWidget *vbox, *hbox;
      GtkWidget *label;
      GtkWidget *entry, *button;
202 203
      GtkWidget *ebox, *image;
      GtkClipboard *clipboard;
204

Anders Carlsson's avatar
Anders Carlsson committed
205
      window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
Matthias Clasen's avatar
Matthias Clasen committed
206 207 208 209
      gtk_window_set_screen (GTK_WINDOW (window),
                             gtk_widget_get_screen (do_widget));
      gtk_window_set_title (GTK_WINDOW (window), "Clipboard demo");

210 211 212
      g_signal_connect (window, "destroy",
                        G_CALLBACK (gtk_widget_destroyed), &window);

213
      vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
Anders Carlsson's avatar
Anders Carlsson committed
214
      gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
215

Anders Carlsson's avatar
Anders Carlsson committed
216 217 218
      gtk_container_add (GTK_CONTAINER (window), vbox);

      label = gtk_label_new ("\"Copy\" will copy the text\nin the entry to the clipboard");
219

Anders Carlsson's avatar
Anders Carlsson committed
220 221
      gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);

222
      hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
Anders Carlsson's avatar
Anders Carlsson committed
223 224 225 226 227 228
      gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
      gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);

      /* Create the first entry */
      entry = gtk_entry_new ();
      gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
229

Anders Carlsson's avatar
Anders Carlsson committed
230 231 232 233
      /* Create the button */
      button = gtk_button_new_from_stock (GTK_STOCK_COPY);
      gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
      g_signal_connect (button, "clicked",
234
                        G_CALLBACK (copy_button_clicked), entry);
Anders Carlsson's avatar
Anders Carlsson committed
235 236 237 238

      label = gtk_label_new ("\"Paste\" will paste the text from the clipboard to the entry");
      gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);

239
      hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
Anders Carlsson's avatar
Anders Carlsson committed
240 241 242 243 244 245
      gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
      gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);

      /* Create the second entry */
      entry = gtk_entry_new ();
      gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
246

Anders Carlsson's avatar
Anders Carlsson committed
247 248 249 250
      /* Create the button */
      button = gtk_button_new_from_stock (GTK_STOCK_PASTE);
      gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
      g_signal_connect (button, "clicked",
251
                        G_CALLBACK (paste_button_clicked), entry);
252

253 254 255
      label = gtk_label_new ("Images can be transferred via the clipboard, too");
      gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);

256
      hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
257 258 259 260
      gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
      gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);

      /* Create the first image */
261
      image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
262 263 264 265 266 267 268 269
                                        GTK_ICON_SIZE_BUTTON);
      ebox = gtk_event_box_new ();
      gtk_container_add (GTK_CONTAINER (ebox), image);
      gtk_container_add (GTK_CONTAINER (hbox), ebox);

      /* make ebox a drag source */
      gtk_drag_source_set (ebox, GDK_BUTTON1_MASK, NULL, 0, GDK_ACTION_COPY);
      gtk_drag_source_add_image_targets (ebox);
270
      g_signal_connect (ebox, "drag-begin",
271
                        G_CALLBACK (drag_begin), image);
272
      g_signal_connect (ebox, "drag-data-get",
273
                        G_CALLBACK (drag_data_get), image);
274

275
      /* accept drops on ebox */
276
      gtk_drag_dest_set (ebox, GTK_DEST_DEFAULT_ALL,
277 278
                         NULL, 0, GDK_ACTION_COPY);
      gtk_drag_dest_add_image_targets (ebox);
279
      g_signal_connect (ebox, "drag-data-received",
280
                        G_CALLBACK (drag_data_received), image);
281

282
      /* context menu on ebox */
283
      g_signal_connect (ebox, "button-press-event",
284 285 286
                        G_CALLBACK (button_press), image);

      /* Create the second image */
287
      image = gtk_image_new_from_stock (GTK_STOCK_STOP,
288 289 290 291 292 293 294 295
                                        GTK_ICON_SIZE_BUTTON);
      ebox = gtk_event_box_new ();
      gtk_container_add (GTK_CONTAINER (ebox), image);
      gtk_container_add (GTK_CONTAINER (hbox), ebox);

      /* make ebox a drag source */
      gtk_drag_source_set (ebox, GDK_BUTTON1_MASK, NULL, 0, GDK_ACTION_COPY);
      gtk_drag_source_add_image_targets (ebox);
296
      g_signal_connect (ebox, "drag-begin",
297
                        G_CALLBACK (drag_begin), image);
298
      g_signal_connect (ebox, "drag-data-get",
299
                        G_CALLBACK (drag_data_get), image);
300

301
      /* accept drops on ebox */
302
      gtk_drag_dest_set (ebox, GTK_DEST_DEFAULT_ALL,
303 304
                         NULL, 0, GDK_ACTION_COPY);
      gtk_drag_dest_add_image_targets (ebox);
305
      g_signal_connect (ebox, "drag-data-received",
306
                        G_CALLBACK (drag_data_received), image);
307

308
      /* context menu on ebox */
309
      g_signal_connect (ebox, "button-press-event",
310
                        G_CALLBACK (button_press), image);
311

312 313 314
      /* tell the clipboard manager to make the data persistent */
      clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
      gtk_clipboard_set_can_store (clipboard, NULL, 0);
Anders Carlsson's avatar
Anders Carlsson committed
315 316
    }

317
  if (!gtk_widget_get_visible (window))
Anders Carlsson's avatar
Anders Carlsson committed
318 319 320 321 322 323 324 325 326
    gtk_widget_show_all (window);
  else
    {
      gtk_widget_destroy (window);
      window = NULL;
    }

  return window;
}