]> Pileus Git - ~andy/gtk/blob - demos/gtk-demo/clipboard.c
Deprecate widget flag: GTK_WIDGET_VISIBLE
[~andy/gtk] / demos / gtk-demo / clipboard.c
1 /* Clipboard
2  *
3  * 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  * drag-and-drop, and how to make clipboard contents persist after
8  * the application exits. Clipboard persistence requires a clipboard
9  * manager to run.
10  */
11
12 #include <gtk/gtk.h>
13 #include <string.h>
14
15 static GtkWidget *window = NULL;
16
17 void
18 copy_button_clicked (GtkWidget *button,
19                      gpointer   user_data)
20 {
21   GtkWidget *entry;
22   GtkClipboard *clipboard;
23
24   entry = GTK_WIDGET (user_data);
25
26   /* Get the clipboard object */
27   clipboard = gtk_widget_get_clipboard (entry,
28                                         GDK_SELECTION_CLIPBOARD);
29
30   /* Set clipboard text */
31   gtk_clipboard_set_text (clipboard, gtk_entry_get_text (GTK_ENTRY (entry)), -1);
32 }
33
34 void
35 paste_received (GtkClipboard *clipboard,
36                 const gchar  *text,
37                 gpointer      user_data)
38 {
39   GtkWidget *entry;
40
41   entry = GTK_WIDGET (user_data);
42
43   /* Set the entry text */
44   if(text)
45     gtk_entry_set_text (GTK_ENTRY (entry), text);
46 }
47
48 void
49 paste_button_clicked (GtkWidget *button,
50                      gpointer   user_data)
51 {
52   GtkWidget *entry;
53   GtkClipboard *clipboard;
54
55   entry = GTK_WIDGET (user_data);
56
57   /* Get the clipboard object */
58   clipboard = gtk_widget_get_clipboard (entry,
59                                         GDK_SELECTION_CLIPBOARD);
60
61   /* Request the contents of the clipboard, contents_received will be
62      called when we do get the contents.
63    */
64   gtk_clipboard_request_text (clipboard,
65                               paste_received, entry);
66 }
67
68 static GdkPixbuf *
69 get_image_pixbuf (GtkImage *image)
70 {
71   gchar *stock_id;
72   GtkIconSize size;
73
74   switch (gtk_image_get_storage_type (image))
75     {
76     case GTK_IMAGE_PIXBUF:
77       return g_object_ref (gtk_image_get_pixbuf (image));
78     case GTK_IMAGE_STOCK:
79       gtk_image_get_stock (image, &stock_id, &size);
80       return gtk_widget_render_icon (GTK_WIDGET (image),
81                                      stock_id, size, NULL);
82     default:
83       g_warning ("Image storage type %d not handled",
84                  gtk_image_get_storage_type (image));
85       return NULL;
86     }
87 }
88
89 static void
90 drag_begin (GtkWidget      *widget,
91             GdkDragContext *context,
92             gpointer        data)
93 {
94   GdkPixbuf *pixbuf;
95
96   pixbuf = get_image_pixbuf (GTK_IMAGE (data));
97   gtk_drag_set_icon_pixbuf (context, pixbuf, -2, -2);
98   g_object_unref (pixbuf);
99 }
100
101 void
102 drag_data_get  (GtkWidget        *widget,
103                 GdkDragContext   *context,
104                 GtkSelectionData *selection_data,
105                 guint             info,
106                 guint             time,
107                 gpointer          data)
108 {
109   GdkPixbuf *pixbuf;
110
111   pixbuf = get_image_pixbuf (GTK_IMAGE (data));
112   gtk_selection_data_set_pixbuf (selection_data, pixbuf);
113   g_object_unref (pixbuf);
114 }
115
116 static void
117 drag_data_received (GtkWidget        *widget,
118                     GdkDragContext   *context,
119                     gint              x,
120                     gint              y,
121                     GtkSelectionData *selection_data,
122                     guint             info,
123                     guint32           time,
124                     gpointer          data)
125 {
126   GdkPixbuf *pixbuf;
127
128   if (selection_data->length > 0)
129     {
130       pixbuf = gtk_selection_data_get_pixbuf (selection_data);
131       gtk_image_set_from_pixbuf (GTK_IMAGE (data), pixbuf);
132       g_object_unref (pixbuf);
133     }
134 }
135
136 static void
137 copy_image (GtkMenuItem *item,
138             gpointer     data)
139 {
140   GtkClipboard *clipboard;
141   GdkPixbuf *pixbuf;
142
143   clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
144   pixbuf = get_image_pixbuf (GTK_IMAGE (data));
145
146   gtk_clipboard_set_image (clipboard, pixbuf);
147   g_object_unref (pixbuf);
148 }
149
150 static void
151 paste_image (GtkMenuItem *item,
152              gpointer     data)
153 {
154   GtkClipboard *clipboard;
155   GdkPixbuf *pixbuf;
156
157   clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
158   pixbuf = gtk_clipboard_wait_for_image (clipboard);
159
160   if (pixbuf)
161     {
162       gtk_image_set_from_pixbuf (GTK_IMAGE (data), pixbuf);
163       g_object_unref (pixbuf);
164     }
165 }
166
167 static gboolean
168 button_press (GtkWidget      *widget,
169               GdkEventButton *button,
170               gpointer        data)
171 {
172   GtkWidget *menu;
173   GtkWidget *item;
174
175   if (button->button != 3)
176     return FALSE;
177
178   menu = gtk_menu_new ();
179
180   item = gtk_image_menu_item_new_from_stock (GTK_STOCK_COPY, NULL);
181   g_signal_connect (item, "activate", G_CALLBACK (copy_image), data);
182   gtk_widget_show (item);
183   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
184
185   item = gtk_image_menu_item_new_from_stock (GTK_STOCK_PASTE, NULL);
186   g_signal_connect (item, "activate", G_CALLBACK (paste_image), data);
187   gtk_widget_show (item);
188   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
189
190   gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 3, button->time);
191   return TRUE;
192 }
193
194 GtkWidget *
195 do_clipboard (GtkWidget *do_widget)
196 {
197   if (!window)
198     {
199       GtkWidget *vbox, *hbox;
200       GtkWidget *label;
201       GtkWidget *entry, *button;
202       GtkWidget *ebox, *image;
203       GtkClipboard *clipboard;
204
205       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
206       gtk_window_set_screen (GTK_WINDOW (window),
207                              gtk_widget_get_screen (do_widget));
208       gtk_window_set_title (GTK_WINDOW (window), "Clipboard demo");
209
210       g_signal_connect (window, "destroy",
211                         G_CALLBACK (gtk_widget_destroyed), &window);
212
213       vbox = gtk_vbox_new (FALSE, 0);
214       gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
215
216       gtk_container_add (GTK_CONTAINER (window), vbox);
217
218       label = gtk_label_new ("\"Copy\" will copy the text\nin the entry to the clipboard");
219
220       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
221
222       hbox = gtk_hbox_new (FALSE, 4);
223       gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
224       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
225
226       /* Create the first entry */
227       entry = gtk_entry_new ();
228       gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
229
230       /* Create the button */
231       button = gtk_button_new_from_stock (GTK_STOCK_COPY);
232       gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
233       g_signal_connect (button, "clicked",
234                         G_CALLBACK (copy_button_clicked), entry);
235
236       label = gtk_label_new ("\"Paste\" will paste the text from the clipboard to the entry");
237       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
238
239       hbox = gtk_hbox_new (FALSE, 4);
240       gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
241       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
242
243       /* Create the second entry */
244       entry = gtk_entry_new ();
245       gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
246
247       /* Create the button */
248       button = gtk_button_new_from_stock (GTK_STOCK_PASTE);
249       gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
250       g_signal_connect (button, "clicked",
251                         G_CALLBACK (paste_button_clicked), entry);
252
253       label = gtk_label_new ("Images can be transferred via the clipboard, too");
254       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
255
256       hbox = gtk_hbox_new (FALSE, 4);
257       gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
258       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
259
260       /* Create the first image */
261       image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
262                                         GTK_ICON_SIZE_BUTTON);
263       ebox = gtk_event_box_new ();
264       gtk_container_add (GTK_CONTAINER (ebox), image);
265       gtk_container_add (GTK_CONTAINER (hbox), ebox);
266
267       /* make ebox a drag source */
268       gtk_drag_source_set (ebox, GDK_BUTTON1_MASK, NULL, 0, GDK_ACTION_COPY);
269       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                          NULL, 0, GDK_ACTION_COPY);
278       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                         G_CALLBACK (button_press), image);
285
286       /* Create the second image */
287       image = gtk_image_new_from_stock (GTK_STOCK_STOP,
288                                         GTK_ICON_SIZE_BUTTON);
289       ebox = gtk_event_box_new ();
290       gtk_container_add (GTK_CONTAINER (ebox), image);
291       gtk_container_add (GTK_CONTAINER (hbox), ebox);
292
293       /* make ebox a drag source */
294       gtk_drag_source_set (ebox, GDK_BUTTON1_MASK, NULL, 0, GDK_ACTION_COPY);
295       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                          NULL, 0, GDK_ACTION_COPY);
304       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       /* tell the clipboard manager to make the data persistent */
313       clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
314       gtk_clipboard_set_can_store (clipboard, NULL, 0);
315     }
316
317   if (!gtk_widget_get_visible (window))
318     gtk_widget_show_all (window);
319   else
320     {
321       gtk_widget_destroy (window);
322       window = NULL;
323     }
324
325   return window;
326 }