]> Pileus Git - ~andy/gtk/blob - tests/testgtk.c
testgtk: Don't use deprecated functions in properties example
[~andy/gtk] / tests / testgtk.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27
28 #include "config.h"
29
30 #undef  G_LOG_DOMAIN
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <sys/stat.h>
36 #include <math.h>
37 #include <time.h>
38 #ifdef HAVE_UNISTD_H
39 #include <unistd.h>
40 #endif
41
42 #include "gtk/gtk.h"
43 #include "gdk/gdk.h"
44 #include "gdk/gdkkeysyms.h"
45
46 #ifdef G_OS_WIN32
47 #define sleep(n) _sleep(n)
48 #endif
49
50 #include "prop-editor.h"
51
52 #include "test.xpm"
53
54 gboolean
55 file_exists (const char *filename)
56 {
57   struct stat statbuf;
58
59   return stat (filename, &statbuf) == 0;
60 }
61
62 GtkWidget *
63 shape_create_icon (GdkScreen *screen,
64                    char      *xpm_file,
65                    gint       x,
66                    gint       y,
67                    gint       px,
68                    gint       py,
69                    gint       window_type);
70
71 static GtkWidget *
72 build_option_menu (gchar           *items[],
73                    gint             num_items,
74                    gint             history,
75                    void           (*func) (GtkWidget *widget, gpointer data),
76                    gpointer         data);
77
78 /* macro, structure and variables used by tree window demos */
79 #define DEFAULT_NUMBER_OF_ITEM  3
80 #define DEFAULT_RECURSION_LEVEL 3
81
82 struct {
83   GSList* selection_mode_group;
84   GtkWidget* single_button;
85   GtkWidget* browse_button;
86   GtkWidget* multiple_button;
87   GtkWidget* draw_line_button;
88   GtkWidget* view_line_button;
89   GtkWidget* no_root_item_button;
90   GtkWidget* nb_item_spinner;
91   GtkWidget* recursion_spinner;
92 } sTreeSampleSelection;
93
94 typedef struct sTreeButtons {
95   guint nb_item_add;
96   GtkWidget* add_button;
97   GtkWidget* remove_button;
98   GtkWidget* subtree_button;
99 } sTreeButtons;
100 /* end of tree section */
101
102 static GtkWidget *
103 build_option_menu (gchar           *items[],
104                    gint             num_items,
105                    gint             history,
106                    void           (*func)(GtkWidget *widget, gpointer data),
107                    gpointer         data)
108 {
109   GtkWidget *omenu;
110   gint i;
111
112   omenu = gtk_combo_box_text_new ();
113   g_signal_connect (omenu, "changed",
114                     G_CALLBACK (func), data);
115       
116   for (i = 0; i < num_items; i++)
117       gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (omenu), items[i]);
118
119   gtk_combo_box_set_active (GTK_COMBO_BOX (omenu), history);
120   
121   return omenu;
122 }
123
124 /*
125  * Windows with an alpha channel
126  */
127
128
129 static gboolean
130 on_alpha_window_draw (GtkWidget *widget,
131                       cairo_t   *cr)
132 {
133   cairo_pattern_t *pattern;
134   int radius, width, height;
135
136   width = gtk_widget_get_allocated_width (widget);
137   height = gtk_widget_get_allocated_height (widget);
138   radius = MIN (width, height) / 2;
139   pattern = cairo_pattern_create_radial (width / 2,
140                                          height / 2,
141                                          0.0,
142                                          width / 2,
143                                          height / 2,
144                                          radius * 1.33);
145
146   if (gdk_screen_get_rgba_visual (gtk_widget_get_screen (widget)) &&
147       gtk_widget_is_composited (widget))
148     cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0); /* transparent */
149   else
150     cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* opaque white */
151     
152   cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
153   cairo_paint (cr);
154   
155   cairo_pattern_add_color_stop_rgba (pattern, 0.0,
156                                      1.0, 0.75, 0.0, 1.0); /* solid orange */
157   cairo_pattern_add_color_stop_rgba (pattern, 1.0,
158                                      1.0, 0.75, 0.0, 0.0); /* transparent orange */
159
160   cairo_set_source (cr, pattern);
161   cairo_pattern_destroy (pattern);
162   
163   cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
164   cairo_paint (cr);
165
166   return FALSE;
167 }
168
169 static GtkWidget *
170 build_alpha_widgets (void)
171 {
172   GtkWidget *grid;
173   GtkWidget *radio_button;
174   GtkWidget *check_button;
175   GtkWidget *hbox;
176   GtkWidget *label;
177   GtkWidget *entry;
178
179   grid = gtk_grid_new ();
180
181   radio_button = gtk_radio_button_new_with_label (NULL, "Red");
182   gtk_widget_set_hexpand (radio_button, TRUE);
183   gtk_grid_attach (GTK_GRID (grid), radio_button, 0, 0, 1, 1);
184
185   radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Green");
186   gtk_widget_set_hexpand (radio_button, TRUE);
187   gtk_grid_attach (GTK_GRID (grid), radio_button, 0, 1, 1, 1);
188
189   radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Blue"),
190   gtk_widget_set_hexpand (radio_button, TRUE);
191   gtk_grid_attach (GTK_GRID (grid), radio_button, 0, 2, 1, 1);
192
193   check_button = gtk_check_button_new_with_label ("Sedentary"),
194   gtk_widget_set_hexpand (check_button, TRUE);
195   gtk_grid_attach (GTK_GRID (grid), check_button, 1, 0, 1, 1);
196
197   check_button = gtk_check_button_new_with_label ("Nocturnal"),
198   gtk_widget_set_hexpand (check_button, TRUE);
199   gtk_grid_attach (GTK_GRID (grid), check_button, 1, 1, 1, 1);
200
201   check_button = gtk_check_button_new_with_label ("Compulsive"),
202   gtk_widget_set_hexpand (check_button, TRUE);
203   gtk_grid_attach (GTK_GRID (grid), check_button, 1, 2, 1, 1);
204
205   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
206   label = gtk_label_new (NULL);
207   gtk_label_set_markup (GTK_LABEL (label), "<i>Entry: </i>");
208   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
209   entry = gtk_entry_new ();
210   gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
211   gtk_widget_set_hexpand (hbox, TRUE);
212   gtk_grid_attach (GTK_GRID (grid), hbox, 0, 3, 2, 1);
213   
214   return grid;
215 }
216
217 static void
218 on_alpha_screen_changed (GtkWindow *window,
219                          GdkScreen *old_screen,
220                          GtkWidget *label)
221 {
222   GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (window));
223   GdkVisual *visual = gdk_screen_get_rgba_visual (screen);
224
225   if (!visual)
226     {
227       visual = gdk_screen_get_system_visual (screen);
228       gtk_label_set_markup (GTK_LABEL (label), "<b>Screen doesn't support alpha</b>");
229     }
230   else
231     {
232       gtk_label_set_markup (GTK_LABEL (label), "<b>Screen supports alpha</b>");
233     }
234
235   gtk_widget_set_visual (GTK_WIDGET (window), visual);
236 }
237
238 static void
239 on_composited_changed (GtkWidget *window,
240                       GtkLabel *label)
241 {
242   gboolean is_composited = gtk_widget_is_composited (window);
243
244   if (is_composited)
245     gtk_label_set_text (label, "Composited");
246   else
247     gtk_label_set_text (label, "Not composited");
248 }
249
250 void
251 create_alpha_window (GtkWidget *widget)
252 {
253   static GtkWidget *window;
254
255   if (!window)
256     {
257       GtkWidget *content_area;
258       GtkWidget *vbox;
259       GtkWidget *label;
260       
261       window = gtk_dialog_new_with_buttons ("Alpha Window",
262                                             GTK_WINDOW (gtk_widget_get_toplevel (widget)), 0,
263                                             GTK_STOCK_CLOSE, 0,
264                                             NULL);
265
266       gtk_widget_set_app_paintable (window, TRUE);
267       g_signal_connect (window, "draw",
268                         G_CALLBACK (on_alpha_window_draw), NULL);
269
270       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
271       
272       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8);
273       gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
274       gtk_box_pack_start (GTK_BOX (content_area), vbox,
275                           TRUE, TRUE, 0);
276
277       label = gtk_label_new (NULL);
278       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
279       on_alpha_screen_changed (GTK_WINDOW (window), NULL, label);
280       g_signal_connect (window, "screen-changed",
281                         G_CALLBACK (on_alpha_screen_changed), label);
282       
283       label = gtk_label_new (NULL);
284       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
285       on_composited_changed (window, GTK_LABEL (label));
286       g_signal_connect (window, "composited_changed", G_CALLBACK (on_composited_changed), label);
287       
288       gtk_box_pack_start (GTK_BOX (vbox), build_alpha_widgets (), TRUE, TRUE, 0);
289
290       g_signal_connect (window, "destroy",
291                         G_CALLBACK (gtk_widget_destroyed),
292                         &window);
293       
294       g_signal_connect (window, "response",
295                         G_CALLBACK (gtk_widget_destroy),
296                         NULL); 
297     }
298
299   if (!gtk_widget_get_visible (window))
300     gtk_widget_show_all (window);
301   else
302     gtk_widget_destroy (window);
303 }
304
305 /*
306  * Composited non-toplevel window
307  */
308
309 /* The draw event handler for the event box.
310  *
311  * This function simply draws a transparency onto a widget on the area
312  * for which it receives expose events.  This is intended to give the
313  * event box a "transparent" background.
314  *
315  * In order for this to work properly, the widget must have an RGBA
316  * colourmap.  The widget should also be set as app-paintable since it
317  * doesn't make sense for GTK to draw a background if we are drawing it
318  * (and because GTK might actually replace our transparency with its
319  * default background colour).
320  */
321 static gboolean
322 transparent_draw (GtkWidget *widget,
323                   cairo_t   *cr)
324 {
325   cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
326   cairo_paint (cr);
327
328   return FALSE;
329 }
330
331 /* The expose event handler for the window.
332  *
333  * This function performs the actual compositing of the event box onto
334  * the already-existing background of the window at 50% normal opacity.
335  *
336  * In this case we do not want app-paintable to be set on the widget
337  * since we want it to draw its own (red) background.  Because of this,
338  * however, we must ensure that we use g_signal_register_after so that
339  * this handler is called after the red has been drawn.  If it was
340  * called before then GTK would just blindly paint over our work.
341  */
342 static gboolean
343 window_draw (GtkWidget *widget,
344              cairo_t   *cr)
345 {
346   GtkAllocation allocation;
347   GtkWidget *child;
348
349   /* get our child (in this case, the event box) */ 
350   child = gtk_bin_get_child (GTK_BIN (widget));
351
352   gtk_widget_get_allocation (child, &allocation);
353
354   /* the source data is the (composited) event box */
355   gdk_cairo_set_source_window (cr, gtk_widget_get_window (child),
356                                allocation.x,
357                                allocation.y);
358
359   /* composite, with a 50% opacity */
360   cairo_paint_with_alpha (cr, 0.5);
361
362   return FALSE;
363 }
364
365 void
366 create_composited_window (GtkWidget *widget)
367 {
368   static GtkWidget *window;
369
370   if (!window)
371     {
372       GtkWidget *event, *button;
373       GdkRGBA red;
374
375       /* make the widgets */
376       button = gtk_button_new_with_label ("A Button");
377       event = gtk_event_box_new ();
378       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
379
380       g_signal_connect (window, "destroy",
381                         G_CALLBACK (gtk_widget_destroyed),
382                         &window);
383
384       /* put a red background on the window */
385       gdk_rgba_parse (&red, "red");
386       gtk_widget_override_background_color (window, 0, &red);
387
388       /* set our event box to have a fully-transparent background
389        * drawn on it.  currently there is no way to simply tell gtk
390        * that "transparency" is the background colour for a widget.
391        */
392       gtk_widget_set_app_paintable (GTK_WIDGET (event), TRUE);
393       g_signal_connect (event, "draw",
394                         G_CALLBACK (transparent_draw), NULL);
395
396       /* put them inside one another */
397       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
398       gtk_container_add (GTK_CONTAINER (window), event);
399       gtk_container_add (GTK_CONTAINER (event), button);
400
401       /* realise and show everything */
402       gtk_widget_realize (button);
403
404       /* set the event box GdkWindow to be composited.
405        * obviously must be performed after event box is realised.
406        */
407       gdk_window_set_composited (gtk_widget_get_window (event),
408                                  TRUE);
409
410       /* set up the compositing handler.
411        * note that we do _after so that the normal (red) background is drawn
412        * by gtk before our compositing occurs.
413        */
414       g_signal_connect_after (window, "draw",
415                               G_CALLBACK (window_draw), NULL);
416     }
417
418   if (!gtk_widget_get_visible (window))
419     gtk_widget_show_all (window);
420   else
421     gtk_widget_destroy (window);
422 }
423
424 /*
425  * Big windows and guffaw scrolling
426  */
427
428 static void
429 pattern_set_bg (GtkWidget   *widget,
430                 GdkWindow   *child,
431                 gint         level)
432 {
433   static const GdkColor colors[] = {
434     { 0, 0x4444, 0x4444, 0xffff },
435     { 0, 0x8888, 0x8888, 0xffff },
436     { 0, 0xaaaa, 0xaaaa, 0xffff }
437   };
438     
439   gdk_window_set_user_data (child, widget);
440   gdk_window_set_background (child, &colors[level]);
441 }
442
443 static void
444 create_pattern (GtkWidget   *widget,
445                 GdkWindow   *parent,
446                 gint         level,
447                 gint         width,
448                 gint         height)
449 {
450   gint h = 1;
451   gint i = 0;
452     
453   GdkWindow *child;
454
455   while (2 * h <= height)
456     {
457       gint w = 1;
458       gint j = 0;
459       
460       while (2 * w <= width)
461         {
462           if ((i + j) % 2 == 0)
463             {
464               gint x = w  - 1;
465               gint y = h - 1;
466               
467               GdkWindowAttr attributes;
468
469               attributes.window_type = GDK_WINDOW_CHILD;
470               attributes.x = x;
471               attributes.y = y;
472               attributes.width = w;
473               attributes.height = h;
474               attributes.wclass = GDK_INPUT_OUTPUT;
475               attributes.event_mask = GDK_EXPOSURE_MASK;
476               attributes.visual = gtk_widget_get_visual (widget);
477               
478               child = gdk_window_new (parent, &attributes,
479                                       GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL);
480
481               pattern_set_bg (widget, child, level);
482
483               if (level < 2)
484                 create_pattern (widget, child, level + 1, w, h);
485
486               gdk_window_show (child);
487             }
488           j++;
489           w *= 2;
490         }
491       i++;
492       h *= 2;
493     }
494 }
495
496 #define PATTERN_SIZE (1 << 18)
497
498 static void
499 pattern_hadj_changed (GtkAdjustment *adjustment,
500                       GtkWidget     *darea)
501 {
502   gint *old_value = g_object_get_data (G_OBJECT (adjustment), "old-value");
503   gint new_value = gtk_adjustment_get_value (adjustment);
504
505   if (gtk_widget_get_realized (darea))
506     {
507       gdk_window_scroll (gtk_widget_get_window (darea),
508                          *old_value - new_value, 0);
509       *old_value = new_value;
510     }
511 }
512
513 static void
514 pattern_vadj_changed (GtkAdjustment *adjustment,
515                       GtkWidget *darea)
516 {
517   gint *old_value = g_object_get_data (G_OBJECT (adjustment), "old-value");
518   gint new_value = gtk_adjustment_get_value (adjustment);
519
520   if (gtk_widget_get_realized (darea))
521     {
522       gdk_window_scroll (gtk_widget_get_window (darea),
523                          0, *old_value - new_value);
524       *old_value = new_value;
525     }
526 }
527
528 static void
529 pattern_realize (GtkWidget *widget,
530                  gpointer   data)
531 {
532   GdkWindow *window;
533
534   window = gtk_widget_get_window (widget);
535   pattern_set_bg (widget, window, 0);
536   create_pattern (widget, window, 1, PATTERN_SIZE, PATTERN_SIZE);
537 }
538
539 static void 
540 create_big_windows (GtkWidget *widget)
541 {
542   static GtkWidget *window = NULL;
543   GtkWidget *content_area;
544   GtkWidget *darea, *grid, *scrollbar;
545   GtkWidget *eventbox;
546   GtkAdjustment *hadjustment;
547   GtkAdjustment *vadjustment;
548   static gint current_x;
549   static gint current_y;
550  
551   if (!window)
552     {
553       current_x = 0;
554       current_y = 0;
555       
556       window = gtk_dialog_new_with_buttons ("Big Windows",
557                                             NULL, 0,
558                                             GTK_STOCK_CLOSE,
559                                             GTK_RESPONSE_NONE,
560                                             NULL);
561  
562       gtk_window_set_screen (GTK_WINDOW (window),
563                              gtk_widget_get_screen (widget));
564
565       gtk_window_set_default_size (GTK_WINDOW (window), 200, 300);
566
567       g_signal_connect (window, "destroy",
568                         G_CALLBACK (gtk_widget_destroyed),
569                         &window);
570
571       g_signal_connect (window, "response",
572                         G_CALLBACK (gtk_widget_destroy),
573                         NULL);
574
575       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
576
577       grid = gtk_grid_new ();
578       gtk_box_pack_start (GTK_BOX (content_area), grid, TRUE, TRUE, 0);
579
580       darea = gtk_drawing_area_new ();
581
582       hadjustment = gtk_adjustment_new (0, 0, PATTERN_SIZE, 10, 100, 100);
583       g_signal_connect (hadjustment, "value_changed",
584                         G_CALLBACK (pattern_hadj_changed), darea);
585       g_object_set_data (G_OBJECT (hadjustment), "old-value", &current_x);
586
587       vadjustment = gtk_adjustment_new (0, 0, PATTERN_SIZE, 10, 100, 100);
588       g_signal_connect (vadjustment, "value_changed",
589                         G_CALLBACK (pattern_vadj_changed), darea);
590       g_object_set_data (G_OBJECT (vadjustment), "old-value", &current_y);
591       
592       g_signal_connect (darea, "realize",
593                         G_CALLBACK (pattern_realize),
594                         NULL);
595
596       eventbox = gtk_event_box_new ();
597       gtk_widget_set_hexpand (eventbox, TRUE);
598       gtk_widget_set_vexpand (eventbox, TRUE);
599       gtk_grid_attach (GTK_GRID (grid), eventbox, 0, 0, 1, 1);
600
601       gtk_container_add (GTK_CONTAINER (eventbox), darea);
602
603       scrollbar = gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL, hadjustment);
604       gtk_widget_set_hexpand (scrollbar, TRUE);
605       gtk_grid_attach (GTK_GRID (grid), scrollbar, 0, 1, 1, 1);
606
607       scrollbar = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, vadjustment);
608       gtk_widget_set_vexpand (scrollbar, TRUE);
609       gtk_grid_attach (GTK_GRID (grid), scrollbar, 1, 0, 1, 1);
610     }
611
612   if (!gtk_widget_get_visible (window))
613     gtk_widget_show_all (window);
614   else
615     gtk_widget_hide (window);
616 }
617
618 /*
619  * GtkButton
620  */
621
622 static void
623 button_window (GtkWidget *widget,
624                GtkWidget *button)
625 {
626   if (!gtk_widget_get_visible (button))
627     gtk_widget_show (button);
628   else
629     gtk_widget_hide (button);
630 }
631
632 static void
633 create_buttons (GtkWidget *widget)
634 {
635   static GtkWidget *window = NULL;
636   GtkWidget *box1;
637   GtkWidget *box2;
638   GtkWidget *grid;
639   GtkWidget *separator;
640   GtkWidget *button[10];
641   int button_x[9] = { 0, 1, 2, 0, 2, 1, 1, 2, 0 };
642   int button_y[9] = { 0, 1, 2, 2, 0, 2, 0, 1, 1 };
643   guint i;
644
645   if (!window)
646     {
647       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
648       gtk_window_set_screen (GTK_WINDOW (window),
649                              gtk_widget_get_screen (widget));
650
651       g_signal_connect (window, "destroy",
652                         G_CALLBACK (gtk_widget_destroyed),
653                         &window);
654
655       gtk_window_set_title (GTK_WINDOW (window), "GtkButton");
656       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
657
658       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
659       gtk_container_add (GTK_CONTAINER (window), box1);
660
661       grid = gtk_grid_new ();
662       gtk_grid_set_row_spacing (GTK_GRID (grid), 5);
663       gtk_grid_set_column_spacing (GTK_GRID (grid), 5);
664       gtk_container_set_border_width (GTK_CONTAINER (grid), 10);
665       gtk_box_pack_start (GTK_BOX (box1), grid, TRUE, TRUE, 0);
666
667       button[0] = gtk_button_new_with_label ("button1");
668       button[1] = gtk_button_new_with_mnemonic ("_button2");
669       button[2] = gtk_button_new_with_mnemonic ("_button3");
670       button[3] = gtk_button_new_from_stock (GTK_STOCK_OK);
671       button[4] = gtk_button_new_with_label ("button5");
672       button[5] = gtk_button_new_with_label ("button6");
673       button[6] = gtk_button_new_with_label ("button7");
674       button[7] = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
675       button[8] = gtk_button_new_with_label ("button9");
676       
677       for (i = 0; i < 9; i++)
678         {
679           g_signal_connect (button[i], "clicked",
680                             G_CALLBACK (button_window),
681                             button[(i + 1) % 9]);
682           gtk_widget_set_hexpand (button[i], TRUE);
683           gtk_widget_set_vexpand (button[i], TRUE);
684
685           gtk_grid_attach (GTK_GRID (grid), button[i],
686                            button_x[i], button_y[i] + 1, 1, 1);
687         }
688
689       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
690       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
691
692       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
693       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
694       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
695
696       button[9] = gtk_button_new_with_label ("close");
697       g_signal_connect_swapped (button[9], "clicked",
698                                 G_CALLBACK (gtk_widget_destroy),
699                                 window);
700       gtk_box_pack_start (GTK_BOX (box2), button[9], TRUE, TRUE, 0);
701       gtk_widget_set_can_default (button[9], TRUE);
702       gtk_widget_grab_default (button[9]);
703     }
704
705   if (!gtk_widget_get_visible (window))
706     gtk_widget_show_all (window);
707   else
708     gtk_widget_destroy (window);
709 }
710
711 /*
712  * GtkToggleButton
713  */
714
715 static void
716 create_toggle_buttons (GtkWidget *widget)
717 {
718   static GtkWidget *window = NULL;
719   GtkWidget *box1;
720   GtkWidget *box2;
721   GtkWidget *button;
722   GtkWidget *separator;
723
724   if (!window)
725     {
726       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
727       gtk_window_set_screen (GTK_WINDOW (window),
728                              gtk_widget_get_screen (widget));
729
730       g_signal_connect (window, "destroy",
731                         G_CALLBACK (gtk_widget_destroyed),
732                         &window);
733
734       gtk_window_set_title (GTK_WINDOW (window), "GtkToggleButton");
735       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
736
737       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
738       gtk_container_add (GTK_CONTAINER (window), box1);
739
740       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
741       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
742       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
743
744       button = gtk_toggle_button_new_with_label ("button1");
745       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
746
747       button = gtk_toggle_button_new_with_label ("button2");
748       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
749
750       button = gtk_toggle_button_new_with_label ("button3");
751       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
752
753       button = gtk_toggle_button_new_with_label ("inconsistent");
754       gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button), TRUE);
755       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
756       
757       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
758       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
759
760       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
761       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
762       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
763
764       button = gtk_button_new_with_label ("close");
765       g_signal_connect_swapped (button, "clicked",
766                                 G_CALLBACK (gtk_widget_destroy),
767                                 window);
768       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
769       gtk_widget_set_can_default (button, TRUE);
770       gtk_widget_grab_default (button);
771     }
772
773   if (!gtk_widget_get_visible (window))
774     gtk_widget_show_all (window);
775   else
776     gtk_widget_destroy (window);
777 }
778
779 static GtkWidget *
780 create_widget_grid (GType widget_type)
781 {
782   GtkWidget *grid;
783   GtkWidget *group_widget = NULL;
784   gint i, j;
785   
786   grid = gtk_grid_new ();
787   
788   for (i = 0; i < 5; i++)
789     {
790       for (j = 0; j < 5; j++)
791         {
792           GtkWidget *widget;
793           char *tmp;
794           
795           if (i == 0 && j == 0)
796             {
797               widget = NULL;
798             }
799           else if (i == 0)
800             {
801               tmp = g_strdup_printf ("%d", j);
802               widget = gtk_label_new (tmp);
803               g_free (tmp);
804             }
805           else if (j == 0)
806             {
807               tmp = g_strdup_printf ("%c", 'A' + i - 1);
808               widget = gtk_label_new (tmp);
809               g_free (tmp);
810             }
811           else
812             {
813               widget = g_object_new (widget_type, NULL);
814               
815               if (g_type_is_a (widget_type, GTK_TYPE_RADIO_BUTTON))
816                 {
817                   if (!group_widget)
818                     group_widget = widget;
819                   else
820                     g_object_set (widget, "group", group_widget, NULL);
821                 }
822             }
823           
824           if (widget)
825             gtk_grid_attach (GTK_GRID (grid), widget, i, j, 1, 1);
826         }
827     }
828
829   return grid;
830 }
831
832 /*
833  * GtkCheckButton
834  */
835
836 static void
837 create_check_buttons (GtkWidget *widget)
838 {
839   static GtkWidget *window = NULL;
840   GtkWidget *box1;
841   GtkWidget *box2;
842   GtkWidget *button;
843   GtkWidget *separator;
844   GtkWidget *table;
845   
846   if (!window)
847     {
848       window = gtk_dialog_new_with_buttons ("Check Buttons",
849                                             NULL, 0,
850                                             GTK_STOCK_CLOSE,
851                                             GTK_RESPONSE_NONE,
852                                             NULL);
853
854       gtk_window_set_screen (GTK_WINDOW (window), 
855                              gtk_widget_get_screen (widget));
856
857       g_signal_connect (window, "destroy",
858                         G_CALLBACK (gtk_widget_destroyed),
859                         &window);
860       g_signal_connect (window, "response",
861                         G_CALLBACK (gtk_widget_destroy),
862                         NULL);
863
864       box1 = gtk_dialog_get_content_area (GTK_DIALOG (window));
865       
866       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
867       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
868       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
869
870       button = gtk_check_button_new_with_mnemonic ("_button1");
871       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
872
873       button = gtk_check_button_new_with_label ("button2");
874       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
875
876       button = gtk_check_button_new_with_label ("button3");
877       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
878
879       button = gtk_check_button_new_with_label ("inconsistent");
880       gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button), TRUE);
881       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
882
883       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
884       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
885
886       table = create_widget_grid (GTK_TYPE_CHECK_BUTTON);
887       gtk_container_set_border_width (GTK_CONTAINER (table), 10);
888       gtk_box_pack_start (GTK_BOX (box1), table, TRUE, TRUE, 0);
889     }
890
891   if (!gtk_widget_get_visible (window))
892     gtk_widget_show_all (window);
893   else
894     gtk_widget_destroy (window);
895 }
896
897 /*
898  * GtkRadioButton
899  */
900
901 static void
902 create_radio_buttons (GtkWidget *widget)
903 {
904   static GtkWidget *window = NULL;
905   GtkWidget *box1;
906   GtkWidget *box2;
907   GtkWidget *button;
908   GtkWidget *separator;
909   GtkWidget *table;
910
911   if (!window)
912     {
913       window = gtk_dialog_new_with_buttons ("Radio Buttons",
914                                             NULL, 0,
915                                             GTK_STOCK_CLOSE,
916                                             GTK_RESPONSE_NONE,
917                                             NULL);
918
919       gtk_window_set_screen (GTK_WINDOW (window),
920                              gtk_widget_get_screen (widget));
921
922       g_signal_connect (window, "destroy",
923                         G_CALLBACK (gtk_widget_destroyed),
924                         &window);
925       g_signal_connect (window, "response",
926                         G_CALLBACK (gtk_widget_destroy),
927                         NULL);
928
929       box1 = gtk_dialog_get_content_area (GTK_DIALOG (window));
930
931       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
932       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
933       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
934
935       button = gtk_radio_button_new_with_label (NULL, "button1");
936       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
937
938       button = gtk_radio_button_new_with_label (
939                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
940                  "button2");
941       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
942       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
943
944       button = gtk_radio_button_new_with_label (
945                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
946                  "button3");
947       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
948
949       button = gtk_radio_button_new_with_label (
950                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
951                  "inconsistent");
952       gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button), TRUE);
953       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
954       
955       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
956       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
957
958       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
959       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
960       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
961
962       button = gtk_radio_button_new_with_label (NULL, "button4");
963       gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
964       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
965
966       button = gtk_radio_button_new_with_label (
967                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
968                  "button5");
969       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
970       gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
971       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
972
973       button = gtk_radio_button_new_with_label (
974                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
975                  "button6");
976       gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
977       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
978
979       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
980       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
981
982       table = create_widget_grid (GTK_TYPE_RADIO_BUTTON);
983       gtk_container_set_border_width (GTK_CONTAINER (table), 10);
984       gtk_box_pack_start (GTK_BOX (box1), table, TRUE, TRUE, 0);
985     }
986
987   if (!gtk_widget_get_visible (window))
988     gtk_widget_show_all (window);
989   else
990     gtk_widget_destroy (window);
991 }
992
993 /*
994  * GtkButtonBox
995  */
996
997 static GtkWidget *
998 create_bbox (gint  horizontal,
999              char* title, 
1000              gint  spacing,
1001              gint  child_w,
1002              gint  child_h,
1003              gint  layout)
1004 {
1005   GtkWidget *frame;
1006   GtkWidget *bbox;
1007   GtkWidget *button;
1008         
1009   frame = gtk_frame_new (title);
1010
1011   if (horizontal)
1012     bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
1013   else
1014     bbox = gtk_button_box_new (GTK_ORIENTATION_VERTICAL);
1015
1016   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
1017   gtk_container_add (GTK_CONTAINER (frame), bbox);
1018
1019   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), layout);
1020   gtk_box_set_spacing (GTK_BOX (bbox), spacing);
1021   
1022   button = gtk_button_new_with_label ("OK");
1023   gtk_container_add (GTK_CONTAINER (bbox), button);
1024   
1025   button = gtk_button_new_with_label ("Cancel");
1026   gtk_container_add (GTK_CONTAINER (bbox), button);
1027   
1028   button = gtk_button_new_with_label ("Help");
1029   gtk_container_add (GTK_CONTAINER (bbox), button);
1030
1031   return frame;
1032 }
1033
1034 static void
1035 create_button_box (GtkWidget *widget)
1036 {
1037   static GtkWidget* window = NULL;
1038   GtkWidget *main_vbox;
1039   GtkWidget *vbox;
1040   GtkWidget *hbox;
1041   GtkWidget *frame_horz;
1042   GtkWidget *frame_vert;
1043
1044   if (!window)
1045   {
1046     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1047     gtk_window_set_screen (GTK_WINDOW (window), gtk_widget_get_screen (widget));
1048     gtk_window_set_title (GTK_WINDOW (window), "Button Boxes");
1049     
1050     g_signal_connect (window, "destroy",
1051                       G_CALLBACK (gtk_widget_destroyed),
1052                       &window);
1053
1054     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1055
1056     main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1057     gtk_container_add (GTK_CONTAINER (window), main_vbox);
1058     
1059     frame_horz = gtk_frame_new ("Horizontal Button Boxes");
1060     gtk_box_pack_start (GTK_BOX (main_vbox), frame_horz, TRUE, TRUE, 10);
1061     
1062     vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1063     gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
1064     gtk_container_add (GTK_CONTAINER (frame_horz), vbox);
1065     
1066     gtk_box_pack_start (GTK_BOX (vbox), 
1067                         create_bbox (TRUE, "Spread", 40, 85, 20, GTK_BUTTONBOX_SPREAD),
1068                         TRUE, TRUE, 0);
1069     
1070     gtk_box_pack_start (GTK_BOX (vbox), 
1071                         create_bbox (TRUE, "Edge", 40, 85, 20, GTK_BUTTONBOX_EDGE),
1072                         TRUE, TRUE, 5);
1073     
1074     gtk_box_pack_start (GTK_BOX (vbox), 
1075                         create_bbox (TRUE, "Start", 40, 85, 20, GTK_BUTTONBOX_START),
1076                         TRUE, TRUE, 5);
1077     
1078     gtk_box_pack_start (GTK_BOX (vbox), 
1079                         create_bbox (TRUE, "End", 40, 85, 20, GTK_BUTTONBOX_END),
1080                         TRUE, TRUE, 5);
1081     
1082     gtk_box_pack_start (GTK_BOX (vbox),
1083                         create_bbox (TRUE, "Center", 40, 85, 20, GTK_BUTTONBOX_CENTER),
1084                         TRUE, TRUE, 5);
1085     
1086     frame_vert = gtk_frame_new ("Vertical Button Boxes");
1087     gtk_box_pack_start (GTK_BOX (main_vbox), frame_vert, TRUE, TRUE, 10);
1088     
1089     hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
1090     gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
1091     gtk_container_add (GTK_CONTAINER (frame_vert), hbox);
1092
1093     gtk_box_pack_start (GTK_BOX (hbox), 
1094                         create_bbox (FALSE, "Spread", 30, 85, 20, GTK_BUTTONBOX_SPREAD),
1095                         TRUE, TRUE, 0);
1096     
1097     gtk_box_pack_start (GTK_BOX (hbox), 
1098                         create_bbox (FALSE, "Edge", 30, 85, 20, GTK_BUTTONBOX_EDGE),
1099                         TRUE, TRUE, 5);
1100     
1101     gtk_box_pack_start (GTK_BOX (hbox), 
1102                         create_bbox (FALSE, "Start", 30, 85, 20, GTK_BUTTONBOX_START),
1103                         TRUE, TRUE, 5);
1104     
1105     gtk_box_pack_start (GTK_BOX (hbox), 
1106                         create_bbox (FALSE, "End", 30, 85, 20, GTK_BUTTONBOX_END),
1107                         TRUE, TRUE, 5);
1108     
1109     gtk_box_pack_start (GTK_BOX (hbox),
1110                         create_bbox (FALSE, "Center", 30, 85, 20, GTK_BUTTONBOX_CENTER),
1111                         TRUE, TRUE, 5);
1112   }
1113
1114   if (!gtk_widget_get_visible (window))
1115     gtk_widget_show_all (window);
1116   else
1117     gtk_widget_destroy (window);
1118 }
1119
1120 /*
1121  * GtkToolBar
1122  */
1123
1124 static GtkWidget*
1125 new_pixbuf (char      *filename,
1126             GdkWindow *window)
1127 {
1128   GtkWidget *widget;
1129   GdkPixbuf *pixbuf;
1130
1131   if (strcmp (filename, "test.xpm") == 0)
1132     pixbuf = NULL;
1133   else
1134     pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
1135
1136   if (pixbuf == NULL)
1137     pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **) openfile);
1138   
1139   widget = gtk_image_new_from_pixbuf (pixbuf);
1140
1141   g_object_unref (pixbuf);
1142
1143   return widget;
1144 }
1145
1146
1147 static void
1148 set_toolbar_small_stock (GtkWidget *widget,
1149                          gpointer   data)
1150 {
1151   gtk_toolbar_set_icon_size (GTK_TOOLBAR (data), GTK_ICON_SIZE_SMALL_TOOLBAR);
1152 }
1153
1154 static void
1155 set_toolbar_large_stock (GtkWidget *widget,
1156                          gpointer   data)
1157 {
1158   gtk_toolbar_set_icon_size (GTK_TOOLBAR (data), GTK_ICON_SIZE_LARGE_TOOLBAR);
1159 }
1160
1161 static void
1162 set_toolbar_horizontal (GtkWidget *widget,
1163                         gpointer   data)
1164 {
1165   gtk_orientable_set_orientation (GTK_ORIENTABLE (data), GTK_ORIENTATION_HORIZONTAL);
1166 }
1167
1168 static void
1169 set_toolbar_vertical (GtkWidget *widget,
1170                       gpointer   data)
1171 {
1172   gtk_orientable_set_orientation (GTK_ORIENTABLE (data), GTK_ORIENTATION_VERTICAL);
1173 }
1174
1175 static void
1176 set_toolbar_icons (GtkWidget *widget,
1177                    gpointer   data)
1178 {
1179   gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_ICONS);
1180 }
1181
1182 static void
1183 set_toolbar_text (GtkWidget *widget,
1184                   gpointer   data)
1185 {
1186   gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_TEXT);
1187 }
1188
1189 static void
1190 set_toolbar_both (GtkWidget *widget,
1191                   gpointer   data)
1192 {
1193   gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_BOTH);
1194 }
1195
1196 static void
1197 set_toolbar_both_horiz (GtkWidget *widget,
1198                         gpointer   data)
1199 {
1200   gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_BOTH_HORIZ);
1201 }
1202
1203 static void
1204 set_toolbar_enable (GtkWidget *widget,
1205                     gpointer   data)
1206 {
1207   GtkSettings *settings = gtk_widget_get_settings (widget);
1208   g_object_set (settings, "gtk-enable-tooltips", TRUE, NULL);
1209 }
1210
1211 static void
1212 set_toolbar_disable (GtkWidget *widget,
1213                      gpointer   data)
1214 {
1215   GtkSettings *settings = gtk_widget_get_settings (widget);
1216   g_object_set (settings, "gtk-enable-tooltips", FALSE, NULL);
1217 }
1218
1219 static GtkActionEntry create_toolbar_items[] = {
1220     { NULL, GTK_STOCK_NEW, NULL, NULL, "Stock icon: New",
1221       G_CALLBACK (set_toolbar_small_stock) },
1222     { NULL, GTK_STOCK_OPEN, NULL, NULL, "Stock icon: Open",
1223       G_CALLBACK (set_toolbar_large_stock) },
1224     { NULL, NULL, "Horizontal", NULL, "Horizontal toolbar layout",
1225       G_CALLBACK (set_toolbar_horizontal) },
1226     { NULL, NULL, "Vertical", NULL, "Vertical toolbar layout",
1227       G_CALLBACK (set_toolbar_vertical) },
1228     { NULL },
1229     { NULL, NULL, "Icons", NULL, "Only show toolbar icons",
1230       G_CALLBACK (set_toolbar_icons) },
1231     { NULL, NULL, "Text", NULL, "Only show toolbar text",
1232       G_CALLBACK (set_toolbar_text) },
1233     { NULL, NULL, "Both", NULL, "Show toolbar icons and text",
1234       G_CALLBACK (set_toolbar_both) },
1235     { NULL, NULL, "Both (horizontal)", NULL, "Show toolbar icons and text in a horizontal fashion",
1236       G_CALLBACK (set_toolbar_both_horiz) },
1237     { NULL },
1238     { "entry", NULL, NULL, "This is an unusable GtkEntry ;)",
1239       NULL },
1240     { NULL },
1241     { NULL },
1242     { NULL, NULL, "Enable", NULL, "Enable tooltips",
1243       G_CALLBACK (set_toolbar_enable) },
1244     { NULL, NULL, "Disable", NULL, "Disable tooltips",
1245       G_CALLBACK (set_toolbar_disable) },
1246     { NULL },
1247     { NULL, NULL, "Frobate", NULL, "Frobate tooltip",
1248       NULL },
1249     { NULL, NULL, "Baz", NULL, "Baz tooltip",
1250       NULL },
1251     { NULL },
1252     { NULL, NULL, "Blah", NULL, "Blash tooltip",
1253       NULL },
1254     { NULL, NULL, "Bar", NULL, "Bar tooltip",
1255       NULL },
1256 };
1257
1258 static void
1259 create_toolbar (GtkWidget *widget)
1260 {
1261   static GtkWidget *window = NULL;
1262   GtkWidget *toolbar;
1263
1264   if (!window)
1265     {
1266       guint i;
1267
1268       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1269       gtk_window_set_screen (GTK_WINDOW (window),
1270                              gtk_widget_get_screen (widget));
1271       
1272       gtk_window_set_title (GTK_WINDOW (window), "Toolbar test");
1273
1274       g_signal_connect (window, "destroy",
1275                         G_CALLBACK (gtk_widget_destroyed),
1276                         &window);
1277
1278       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
1279       gtk_widget_realize (window);
1280
1281       toolbar = gtk_toolbar_new ();
1282       for (i = 0; i < G_N_ELEMENTS (create_toolbar_items); i++)
1283         {
1284           GtkToolItem *toolitem;
1285
1286           if (create_toolbar_items[i].tooltip == NULL)
1287             toolitem = gtk_separator_tool_item_new ();
1288           else if (g_strcmp0 (create_toolbar_items[i].name, "entry") == 0)
1289             {
1290               GtkWidget *entry;
1291
1292               toolitem = gtk_tool_item_new ();
1293               entry = gtk_entry_new ();
1294               gtk_container_add (GTK_CONTAINER (toolitem), entry);
1295             }
1296           else if (create_toolbar_items[i].stock_id)
1297             toolitem = gtk_tool_button_new_from_stock (create_toolbar_items[i].stock_id);
1298           else
1299             {
1300               GtkWidget *icon;
1301
1302               icon = new_pixbuf ("test.xpm", gtk_widget_get_window (window));
1303               toolitem = gtk_tool_button_new (icon, create_toolbar_items[i].label);
1304             }
1305           if (create_toolbar_items[i].callback)
1306             g_signal_connect (toolitem, "clicked",
1307                               create_toolbar_items[i].callback, toolbar);
1308           gtk_tool_item_set_tooltip_text (toolitem, create_toolbar_items[i].tooltip);
1309           gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
1310         }
1311
1312       gtk_container_add (GTK_CONTAINER (window), toolbar);
1313
1314       gtk_widget_set_size_request (toolbar, 200, -1);
1315     }
1316
1317   if (!gtk_widget_get_visible (window))
1318     gtk_widget_show_all (window);
1319   else
1320     gtk_widget_destroy (window);
1321 }
1322
1323 /*
1324  * GtkStatusBar
1325  */
1326
1327 static guint statusbar_counter = 1;
1328
1329 static void
1330 statusbar_push (GtkWidget *button,
1331                 GtkStatusbar *statusbar)
1332 {
1333   gchar text[1024];
1334
1335   sprintf (text, "something %d", statusbar_counter++);
1336
1337   gtk_statusbar_push (statusbar, 1, text);
1338 }
1339
1340 static void
1341 statusbar_push_long (GtkWidget *button,
1342                      GtkStatusbar *statusbar)
1343 {
1344   gchar text[1024];
1345
1346   sprintf (text, "Just because a system has menu choices written with English words, phrases or sentences, that is no guarantee, that it is comprehensible. Individual words may not be familiar to some users (for example, \"repaginate\"), and two menu items may appear to satisfy the users's needs, whereas only one does (for example, \"put away\" or \"eject\").");
1347
1348   gtk_statusbar_push (statusbar, 1, text);
1349 }
1350
1351 static void
1352 statusbar_pop (GtkWidget *button,
1353                GtkStatusbar *statusbar)
1354 {
1355   gtk_statusbar_pop (statusbar, 1);
1356 }
1357
1358 static void
1359 statusbar_steal (GtkWidget *button,
1360                  GtkStatusbar *statusbar)
1361 {
1362   gtk_statusbar_remove (statusbar, 1, 4);
1363 }
1364
1365 static void
1366 statusbar_popped (GtkStatusbar  *statusbar,
1367                   guint          context_id,
1368                   const gchar   *text)
1369 {
1370   if (!text)
1371     statusbar_counter = 1;
1372 }
1373
1374 static void
1375 statusbar_contexts (GtkStatusbar *statusbar)
1376 {
1377   gchar *string;
1378
1379   string = "any context";
1380   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1381            string,
1382            gtk_statusbar_get_context_id (statusbar, string));
1383   
1384   string = "idle messages";
1385   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1386            string,
1387            gtk_statusbar_get_context_id (statusbar, string));
1388   
1389   string = "some text";
1390   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1391            string,
1392            gtk_statusbar_get_context_id (statusbar, string));
1393
1394   string = "hit the mouse";
1395   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1396            string,
1397            gtk_statusbar_get_context_id (statusbar, string));
1398
1399   string = "hit the mouse2";
1400   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1401            string,
1402            gtk_statusbar_get_context_id (statusbar, string));
1403 }
1404
1405 static void
1406 create_statusbar (GtkWidget *widget)
1407 {
1408   static GtkWidget *window = NULL;
1409   GtkWidget *box1;
1410   GtkWidget *box2;
1411   GtkWidget *button;
1412   GtkWidget *separator;
1413   GtkWidget *statusbar;
1414
1415   if (!window)
1416     {
1417       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1418       gtk_window_set_screen (GTK_WINDOW (window),
1419                              gtk_widget_get_screen (widget));
1420
1421       g_signal_connect (window, "destroy",
1422                         G_CALLBACK (gtk_widget_destroyed),
1423                         &window);
1424
1425       gtk_window_set_title (GTK_WINDOW (window), "statusbar");
1426       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
1427
1428       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1429       gtk_container_add (GTK_CONTAINER (window), box1);
1430
1431       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
1432       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
1433       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
1434
1435       statusbar = gtk_statusbar_new ();
1436       gtk_box_pack_end (GTK_BOX (box1), statusbar, TRUE, TRUE, 0);
1437       g_signal_connect (statusbar,
1438                         "text_popped",
1439                         G_CALLBACK (statusbar_popped),
1440                         NULL);
1441
1442       button = g_object_new (gtk_button_get_type (),
1443                                "label", "push something",
1444                                "visible", TRUE,
1445                                "parent", box2,
1446                                NULL);
1447       g_object_connect (button,
1448                         "signal::clicked", statusbar_push, statusbar,
1449                         NULL);
1450
1451       button = g_object_connect (g_object_new (gtk_button_get_type (),
1452                                                  "label", "pop",
1453                                                  "visible", TRUE,
1454                                                  "parent", box2,
1455                                                  NULL),
1456                                  "signal_after::clicked", statusbar_pop, statusbar,
1457                                  NULL);
1458
1459       button = g_object_connect (g_object_new (gtk_button_get_type (),
1460                                                  "label", "steal #4",
1461                                                  "visible", TRUE,
1462                                                  "parent", box2,
1463                                                  NULL),
1464                                  "signal_after::clicked", statusbar_steal, statusbar,
1465                                  NULL);
1466
1467       button = g_object_connect (g_object_new (gtk_button_get_type (),
1468                                                  "label", "test contexts",
1469                                                  "visible", TRUE,
1470                                                  "parent", box2,
1471                                                  NULL),
1472                                  "swapped_signal_after::clicked", statusbar_contexts, statusbar,
1473                                  NULL);
1474
1475       button = g_object_connect (g_object_new (gtk_button_get_type (),
1476                                                  "label", "push something long",
1477                                                  "visible", TRUE,
1478                                                  "parent", box2,
1479                                                  NULL),
1480                                  "signal_after::clicked", statusbar_push_long, statusbar,
1481                                  NULL);
1482       
1483       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
1484       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
1485
1486       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
1487       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
1488       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
1489
1490       button = gtk_button_new_with_label ("close");
1491       g_signal_connect_swapped (button, "clicked",
1492                                 G_CALLBACK (gtk_widget_destroy),
1493                                 window);
1494       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1495       gtk_widget_set_can_default (button, TRUE);
1496       gtk_widget_grab_default (button);
1497     }
1498
1499   if (!gtk_widget_get_visible (window))
1500     gtk_widget_show_all (window);
1501   else
1502     gtk_widget_destroy (window);
1503 }
1504
1505 /* 
1506  * Label Demo
1507  */
1508 static void
1509 sensitivity_toggled (GtkWidget *toggle,
1510                      GtkWidget *widget)
1511 {
1512   gtk_widget_set_sensitive (widget,
1513                             gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle)));
1514 }
1515
1516 static GtkWidget*
1517 create_sensitivity_control (GtkWidget *widget)
1518 {
1519   GtkWidget *button;
1520
1521   button = gtk_toggle_button_new_with_label ("Sensitive");  
1522
1523   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
1524                                 gtk_widget_is_sensitive (widget));
1525   
1526   g_signal_connect (button,
1527                     "toggled",
1528                     G_CALLBACK (sensitivity_toggled),
1529                     widget);
1530   
1531   gtk_widget_show_all (button);
1532
1533   return button;
1534 }
1535
1536 static void
1537 set_selectable_recursive (GtkWidget *widget,
1538                           gboolean   setting)
1539 {
1540   if (GTK_IS_CONTAINER (widget))
1541     {
1542       GList *children;
1543       GList *tmp;
1544       
1545       children = gtk_container_get_children (GTK_CONTAINER (widget));
1546       tmp = children;
1547       while (tmp)
1548         {
1549           set_selectable_recursive (tmp->data, setting);
1550
1551           tmp = tmp->next;
1552         }
1553       g_list_free (children);
1554     }
1555   else if (GTK_IS_LABEL (widget))
1556     {
1557       gtk_label_set_selectable (GTK_LABEL (widget), setting);
1558     }
1559 }
1560
1561 static void
1562 selectable_toggled (GtkWidget *toggle,
1563                     GtkWidget *widget)
1564 {
1565   set_selectable_recursive (widget,
1566                             gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle)));
1567 }
1568
1569 static GtkWidget*
1570 create_selectable_control (GtkWidget *widget)
1571 {
1572   GtkWidget *button;
1573
1574   button = gtk_toggle_button_new_with_label ("Selectable");  
1575
1576   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
1577                                 FALSE);
1578   
1579   g_signal_connect (button,
1580                     "toggled",
1581                     G_CALLBACK (selectable_toggled),
1582                     widget);
1583   
1584   gtk_widget_show_all (button);
1585
1586   return button;
1587 }
1588
1589 static void
1590 dialog_response (GtkWidget *dialog, gint response_id, GtkLabel *label)
1591 {
1592   const gchar *text;
1593
1594   gtk_widget_destroy (dialog);
1595
1596   text = "Some <a href=\"http://en.wikipedia.org/wiki/Text\" title=\"plain text\">text</a> may be marked up\n"
1597          "as hyperlinks, which can be clicked\n"
1598          "or activated via <a href=\"keynav\">keynav</a>.\n"
1599          "The links remain the same.";
1600   gtk_label_set_markup (label, text);
1601 }
1602
1603 static gboolean
1604 activate_link (GtkWidget *label, const gchar *uri, gpointer data)
1605 {
1606   if (g_strcmp0 (uri, "keynav") == 0)
1607     {
1608       GtkWidget *dialog;
1609
1610       dialog = gtk_message_dialog_new_with_markup (GTK_WINDOW (gtk_widget_get_toplevel (label)),
1611                                        GTK_DIALOG_DESTROY_WITH_PARENT,
1612                                        GTK_MESSAGE_INFO,
1613                                        GTK_BUTTONS_OK,
1614                                        "The term <i>keynav</i> is a shorthand for "
1615                                        "keyboard navigation and refers to the process of using a program "
1616                                        "(exclusively) via keyboard input.");
1617
1618       gtk_window_present (GTK_WINDOW (dialog));
1619
1620       g_signal_connect (dialog, "response", G_CALLBACK (dialog_response), label);
1621
1622       return TRUE;
1623     }
1624
1625   return FALSE;
1626 }
1627
1628 void create_labels (GtkWidget *widget)
1629 {
1630   static GtkWidget *window = NULL;
1631   GtkWidget *hbox;
1632   GtkWidget *vbox;
1633   GtkWidget *frame;
1634   GtkWidget *label;
1635   GtkWidget *button;
1636
1637   if (!window)
1638     {
1639       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1640
1641       gtk_window_set_screen (GTK_WINDOW (window),
1642                              gtk_widget_get_screen (widget));
1643
1644       g_signal_connect (window, "destroy",
1645                         G_CALLBACK (gtk_widget_destroyed),
1646                         &window);
1647
1648       gtk_window_set_title (GTK_WINDOW (window), "Label");
1649
1650       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
1651       
1652       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
1653       gtk_container_add (GTK_CONTAINER (window), vbox);
1654
1655       gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1656
1657       button = create_sensitivity_control (hbox);
1658
1659       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
1660
1661       button = create_selectable_control (hbox);
1662
1663       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
1664       
1665       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
1666       
1667       gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
1668       gtk_container_set_border_width (GTK_CONTAINER (window), 5);
1669
1670       frame = gtk_frame_new ("Normal Label");
1671       label = gtk_label_new ("This is a Normal label");
1672       gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_START);
1673       gtk_container_add (GTK_CONTAINER (frame), label);
1674       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
1675
1676       frame = gtk_frame_new ("Multi-line Label");
1677       label = gtk_label_new ("This is a Multi-line label.\nSecond line\nThird line");
1678       gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
1679       gtk_container_add (GTK_CONTAINER (frame), label);
1680       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
1681
1682       frame = gtk_frame_new ("Left Justified Label");
1683       label = gtk_label_new ("This is a Left-Justified\nMulti-line label.\nThird      line");
1684       gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_MIDDLE);
1685       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
1686       gtk_container_add (GTK_CONTAINER (frame), label);
1687       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
1688
1689       frame = gtk_frame_new ("Right Justified Label");
1690       gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_START);
1691       label = gtk_label_new ("This is a Right-Justified\nMulti-line label.\nFourth line, (j/k)");
1692       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_RIGHT);
1693       gtk_container_add (GTK_CONTAINER (frame), label);
1694       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
1695
1696       frame = gtk_frame_new ("Internationalized Label");
1697       label = gtk_label_new (NULL);
1698       gtk_label_set_markup (GTK_LABEL (label),
1699                             "French (Fran\303\247ais) Bonjour, Salut\n"
1700                             "Korean (\355\225\234\352\270\200)   \354\225\210\353\205\225\355\225\230\354\204\270\354\232\224, \354\225\210\353\205\225\355\225\230\354\213\255\353\213\210\352\271\214\n"
1701                             "Russian (\320\240\321\203\321\201\321\201\320\272\320\270\320\271) \320\227\320\264\321\200\320\260\320\262\321\201\321\202\320\262\321\203\320\271\321\202\320\265!\n"
1702                             "Chinese (Simplified) <span lang=\"zh-cn\">\345\205\203\346\260\224 \345\274\200\345\217\221</span>\n"
1703                             "Chinese (Traditional) <span lang=\"zh-tw\">\345\205\203\346\260\243        \351\226\213\347\231\274</span>\n"
1704                             "Japanese <span lang=\"ja\">\345\205\203\346\260\227        \351\226\213\347\231\272</span>");
1705       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
1706       gtk_container_add (GTK_CONTAINER (frame), label);
1707       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
1708
1709       frame = gtk_frame_new ("Bidirection Label");
1710       label = gtk_label_new ("\342\200\217Arabic        \330\247\331\204\330\263\331\204\330\247\331\205 \330\271\331\204\331\212\331\203\331\205\n"
1711                              "\342\200\217Hebrew        \327\251\327\234\327\225\327\235");
1712       gtk_container_add (GTK_CONTAINER (frame), label);
1713       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
1714
1715       frame = gtk_frame_new ("Links in a label");
1716       label = gtk_label_new ("Some <a href=\"http://en.wikipedia.org/wiki/Text\" title=\"plain text\">text</a> may be marked up\n"
1717                              "as hyperlinks, which can be clicked\n"
1718                              "or activated via <a href=\"keynav\">keynav</a>");
1719       gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
1720       gtk_container_add (GTK_CONTAINER (frame), label);
1721       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
1722       g_signal_connect (label, "activate-link", G_CALLBACK (activate_link), NULL);
1723
1724       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
1725       gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
1726       frame = gtk_frame_new ("Line wrapped label");
1727       label = gtk_label_new ("This is an example of a line-wrapped label.  It should not be taking "\
1728                              "up the entire             "/* big space to test spacing */\
1729                              "width allocated to it, but automatically wraps the words to fit.  "\
1730                              "The time has come, for all good men, to come to the aid of their party.  "\
1731                              "The sixth sheik's six sheep's sick.\n"\
1732                              "     It supports multiple paragraphs correctly, and  correctly   adds "\
1733                              "many          extra  spaces. ");
1734
1735       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
1736       gtk_container_add (GTK_CONTAINER (frame), label);
1737       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
1738
1739       frame = gtk_frame_new ("Filled, wrapped label");
1740       label = gtk_label_new ("This is an example of a line-wrapped, filled label.  It should be taking "\
1741                              "up the entire              width allocated to it.  Here is a seneance to prove "\
1742                              "my point.  Here is another sentence. "\
1743                              "Here comes the sun, do de do de do.\n"\
1744                              "    This is a new paragraph.\n"\
1745                              "    This is another newer, longer, better paragraph.  It is coming to an end, "\
1746                              "unfortunately.");
1747       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_FILL);
1748       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
1749       gtk_container_add (GTK_CONTAINER (frame), label);
1750       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
1751
1752       frame = gtk_frame_new ("Underlined label");
1753       label = gtk_label_new ("This label is underlined!\n"
1754                              "This one is underlined (\343\201\223\343\202\223\343\201\253\343\201\241\343\201\257) in quite a funky fashion");
1755       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
1756       gtk_label_set_pattern (GTK_LABEL (label), "_________________________ _ _________ _ _____ _ __ __  ___ ____ _____");
1757       gtk_container_add (GTK_CONTAINER (frame), label);
1758       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
1759
1760       frame = gtk_frame_new ("Markup label");
1761       label = gtk_label_new (NULL);
1762
1763       /* There's also a gtk_label_set_markup() without accel if you
1764        * don't have an accelerator key
1765        */
1766       gtk_label_set_markup_with_mnemonic (GTK_LABEL (label),
1767                                           "This <span foreground=\"blue\" background=\"orange\">label</span> has "
1768                                           "<b>markup</b> _such as "
1769                                           "<big><i>Big Italics</i></big>\n"
1770                                           "<tt>Monospace font</tt>\n"
1771                                           "<u>Underline!</u>\n"
1772                                           "foo\n"
1773                                           "<span foreground=\"green\" background=\"red\">Ugly colors</span>\n"
1774                                           "and nothing on this line,\n"
1775                                           "or this.\n"
1776                                           "or this either\n"
1777                                           "or even on this one\n"
1778                                           "la <big>la <big>la <big>la <big>la</big></big></big></big>\n"
1779                                           "but this _word is <span foreground=\"purple\"><big>purple</big></span>\n"
1780                                           "<span underline=\"double\">We like <sup>superscript</sup> and <sub>subscript</sub> too</span>");
1781
1782       g_assert (gtk_label_get_mnemonic_keyval (GTK_LABEL (label)) == GDK_KEY_s);
1783       
1784       gtk_container_add (GTK_CONTAINER (frame), label);
1785       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
1786     }
1787   
1788   if (!gtk_widget_get_visible (window))
1789     gtk_widget_show_all (window);
1790   else
1791     gtk_widget_destroy (window);
1792 }
1793
1794 static void
1795 on_angle_scale_changed (GtkRange *range,
1796                         GtkLabel *label)
1797 {
1798   gtk_label_set_angle (GTK_LABEL (label), gtk_range_get_value (range));
1799 }
1800
1801 static void
1802 create_rotated_label (GtkWidget *widget)
1803 {
1804   static GtkWidget *window = NULL;
1805   GtkWidget *content_area;
1806   GtkWidget *vbox;
1807   GtkWidget *hscale;
1808   GtkWidget *label;  
1809   GtkWidget *scale_label;  
1810   GtkWidget *scale_hbox;  
1811
1812   if (!window)
1813     {
1814       window = gtk_dialog_new_with_buttons ("Rotated Label",
1815                                             GTK_WINDOW (gtk_widget_get_toplevel (widget)), 0,
1816                                             GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
1817                                             NULL);
1818
1819       gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
1820
1821       gtk_window_set_screen (GTK_WINDOW (window),
1822                              gtk_widget_get_screen (widget));
1823
1824       g_signal_connect (window, "response",
1825                         G_CALLBACK (gtk_widget_destroy), NULL);
1826       g_signal_connect (window, "destroy",
1827                         G_CALLBACK (gtk_widget_destroyed), &window);
1828
1829       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
1830
1831       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
1832       gtk_box_pack_start (GTK_BOX (content_area), vbox, TRUE, TRUE, 0);
1833       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
1834
1835       label = gtk_label_new (NULL);
1836       gtk_label_set_markup (GTK_LABEL (label), "Hello World\n<i>Rotate</i> <span underline='single' foreground='blue'>me</span>");
1837       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
1838
1839       scale_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
1840       gtk_box_pack_start (GTK_BOX (vbox), scale_hbox, FALSE, FALSE, 0);
1841       
1842       scale_label = gtk_label_new (NULL);
1843       gtk_label_set_markup (GTK_LABEL (scale_label), "<i>Angle: </i>");
1844       gtk_box_pack_start (GTK_BOX (scale_hbox), scale_label, FALSE, FALSE, 0);
1845
1846       hscale = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL,
1847                                          0, 360, 5);
1848       g_signal_connect (hscale, "value-changed",
1849                         G_CALLBACK (on_angle_scale_changed), label);
1850       
1851       gtk_range_set_value (GTK_RANGE (hscale), 45);
1852       gtk_widget_set_size_request (hscale, 200, -1);
1853       gtk_box_pack_start (GTK_BOX (scale_hbox), hscale, TRUE, TRUE, 0);
1854     }
1855   
1856   if (!gtk_widget_get_visible (window))
1857     gtk_widget_show_all (window);
1858   else
1859     gtk_widget_destroy (window);
1860 }
1861
1862 #define DEFAULT_TEXT_RADIUS 200
1863
1864 static void
1865 on_rotated_text_unrealize (GtkWidget *widget)
1866 {
1867   g_object_set_data (G_OBJECT (widget), "text-gc", NULL);
1868 }
1869
1870 static gboolean
1871 on_rotated_text_draw (GtkWidget *widget,
1872                       cairo_t   *cr,
1873                       GdkPixbuf *tile_pixbuf)
1874 {
1875   static const gchar *words[] = { "The", "grand", "old", "Duke", "of", "York",
1876                                   "had", "10,000", "men" };
1877   int n_words;
1878   int i;
1879   int width, height;
1880   double radius;
1881   PangoLayout *layout;
1882   PangoContext *context;
1883   PangoFontDescription *desc;
1884
1885   if (tile_pixbuf)
1886     {
1887       gdk_cairo_set_source_pixbuf (cr, tile_pixbuf, 0, 0);
1888       cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
1889     }
1890   else
1891     cairo_set_source_rgb (cr, 0, 0, 0);
1892
1893   width = gtk_widget_get_allocated_width (widget);
1894   height = gtk_widget_get_allocated_height (widget);
1895   radius = MIN (width, height) / 2.;
1896
1897   cairo_translate (cr,
1898                    radius + (width - 2 * radius) / 2,
1899                    radius + (height - 2 * radius) / 2);
1900   cairo_scale (cr, radius / DEFAULT_TEXT_RADIUS, radius / DEFAULT_TEXT_RADIUS);
1901
1902   context = gtk_widget_get_pango_context (widget);
1903   layout = pango_layout_new (context);
1904   desc = pango_font_description_from_string ("Sans Bold 30");
1905   pango_layout_set_font_description (layout, desc);
1906   pango_font_description_free (desc);
1907     
1908   n_words = G_N_ELEMENTS (words);
1909   for (i = 0; i < n_words; i++)
1910     {
1911       int width, height;
1912
1913       cairo_save (cr);
1914
1915       cairo_rotate (cr, 2 * G_PI * i / n_words);
1916       pango_cairo_update_layout (cr, layout);
1917
1918       pango_layout_set_text (layout, words[i], -1);
1919       pango_layout_get_size (layout, &width, &height);
1920
1921       cairo_move_to (cr, - width / 2 / PANGO_SCALE, - DEFAULT_TEXT_RADIUS);
1922       pango_cairo_show_layout (cr, layout);
1923
1924       cairo_restore (cr);
1925     }
1926   
1927   g_object_unref (layout);
1928
1929   return FALSE;
1930 }
1931
1932 static void
1933 create_rotated_text (GtkWidget *widget)
1934 {
1935   static GtkWidget *window = NULL;
1936
1937   if (!window)
1938     {
1939       const GdkRGBA white = { 1.0, 1.0, 1.0, 1.0 };
1940       GtkRequisition requisition;
1941       GtkWidget *content_area;
1942       GtkWidget *drawing_area;
1943       GdkPixbuf *tile_pixbuf;
1944
1945       window = gtk_dialog_new_with_buttons ("Rotated Text",
1946                                             GTK_WINDOW (gtk_widget_get_toplevel (widget)), 0,
1947                                             GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
1948                                             NULL);
1949
1950       gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
1951
1952       gtk_window_set_screen (GTK_WINDOW (window),
1953                              gtk_widget_get_screen (widget));
1954
1955       g_signal_connect (window, "response",
1956                         G_CALLBACK (gtk_widget_destroy), NULL);
1957       g_signal_connect (window, "destroy",
1958                         G_CALLBACK (gtk_widget_destroyed), &window);
1959
1960       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
1961
1962       drawing_area = gtk_drawing_area_new ();
1963       gtk_box_pack_start (GTK_BOX (content_area), drawing_area, TRUE, TRUE, 0);
1964       gtk_widget_override_background_color (drawing_area, 0, &white);
1965
1966       tile_pixbuf = gdk_pixbuf_new_from_file ("marble.xpm", NULL);
1967       
1968       g_signal_connect (drawing_area, "draw",
1969                         G_CALLBACK (on_rotated_text_draw), tile_pixbuf);
1970       g_signal_connect (drawing_area, "unrealize",
1971                         G_CALLBACK (on_rotated_text_unrealize), NULL);
1972
1973       gtk_widget_show_all (gtk_bin_get_child (GTK_BIN (window)));
1974       
1975       gtk_widget_set_size_request (drawing_area, DEFAULT_TEXT_RADIUS * 2, DEFAULT_TEXT_RADIUS * 2);
1976       gtk_widget_get_preferred_size ( (window),
1977                                  &requisition, NULL);
1978       gtk_widget_set_size_request (drawing_area, -1, -1);
1979       gtk_window_resize (GTK_WINDOW (window), requisition.width, requisition.height);
1980     }
1981   
1982   if (!gtk_widget_get_visible (window))
1983     gtk_widget_show (window);
1984   else
1985     gtk_widget_destroy (window);
1986 }
1987
1988 /*
1989  * Reparent demo
1990  */
1991
1992 static void
1993 reparent_label (GtkWidget *widget,
1994                 GtkWidget *new_parent)
1995 {
1996   GtkWidget *label;
1997
1998   label = g_object_get_data (G_OBJECT (widget), "user_data");
1999
2000   gtk_widget_reparent (label, new_parent);
2001 }
2002
2003 static void
2004 set_parent_signal (GtkWidget *child,
2005                    GtkWidget *old_parent,
2006                    gpointer   func_data)
2007 {
2008   GtkWidget *parent;
2009
2010   parent = gtk_widget_get_parent (child);
2011   g_message ("set_parent for \"%s\": new parent: \"%s\", old parent: \"%s\", data: %d\n",
2012              g_type_name (G_OBJECT_TYPE (child)),
2013              parent ? g_type_name (G_OBJECT_TYPE (parent)) : "NULL",
2014              old_parent ? g_type_name (G_OBJECT_TYPE (old_parent)) : "NULL",
2015              GPOINTER_TO_INT (func_data));
2016 }
2017
2018 static void
2019 create_reparent (GtkWidget *widget)
2020 {
2021   static GtkWidget *window = NULL;
2022   GtkWidget *box1;
2023   GtkWidget *box2;
2024   GtkWidget *box3;
2025   GtkWidget *frame;
2026   GtkWidget *button;
2027   GtkWidget *label;
2028   GtkWidget *separator;
2029   GtkWidget *event_box;
2030
2031   if (!window)
2032     {
2033       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2034
2035       gtk_window_set_screen (GTK_WINDOW (window),
2036                              gtk_widget_get_screen (widget));
2037
2038       g_signal_connect (window, "destroy",
2039                         G_CALLBACK (gtk_widget_destroyed),
2040                         &window);
2041
2042       gtk_window_set_title (GTK_WINDOW (window), "reparent");
2043       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
2044
2045       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
2046       gtk_container_add (GTK_CONTAINER (window), box1);
2047
2048       box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
2049       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2050       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2051
2052       label = gtk_label_new ("Hello World");
2053
2054       frame = gtk_frame_new ("Frame 1");
2055       gtk_box_pack_start (GTK_BOX (box2), frame, TRUE, TRUE, 0);
2056
2057       box3 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
2058       gtk_container_set_border_width (GTK_CONTAINER (box3), 5);
2059       gtk_container_add (GTK_CONTAINER (frame), box3);
2060
2061       button = gtk_button_new_with_label ("switch");
2062       g_object_set_data (G_OBJECT (button), "user_data", label);
2063       gtk_box_pack_start (GTK_BOX (box3), button, FALSE, TRUE, 0);
2064
2065       event_box = gtk_event_box_new ();
2066       gtk_box_pack_start (GTK_BOX (box3), event_box, FALSE, TRUE, 0);
2067       gtk_container_add (GTK_CONTAINER (event_box), label);
2068                          
2069       g_signal_connect (button, "clicked",
2070                         G_CALLBACK (reparent_label),
2071                         event_box);
2072       
2073       g_signal_connect (label, "parent_set",
2074                         G_CALLBACK (set_parent_signal),
2075                         GINT_TO_POINTER (42));
2076
2077       frame = gtk_frame_new ("Frame 2");
2078       gtk_box_pack_start (GTK_BOX (box2), frame, TRUE, TRUE, 0);
2079
2080       box3 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
2081       gtk_container_set_border_width (GTK_CONTAINER (box3), 5);
2082       gtk_container_add (GTK_CONTAINER (frame), box3);
2083
2084       button = gtk_button_new_with_label ("switch");
2085       g_object_set_data (G_OBJECT (button), "user_data", label);
2086       gtk_box_pack_start (GTK_BOX (box3), button, FALSE, TRUE, 0);
2087       
2088       event_box = gtk_event_box_new ();
2089       gtk_box_pack_start (GTK_BOX (box3), event_box, FALSE, TRUE, 0);
2090
2091       g_signal_connect (button, "clicked",
2092                         G_CALLBACK (reparent_label),
2093                         event_box);
2094
2095       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
2096       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2097
2098       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
2099       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2100       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2101
2102       button = gtk_button_new_with_label ("close");
2103       g_signal_connect_swapped (button, "clicked",
2104                                 G_CALLBACK (gtk_widget_destroy), window);
2105       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2106       gtk_widget_set_can_default (button, TRUE);
2107       gtk_widget_grab_default (button);
2108     }
2109
2110   if (!gtk_widget_get_visible (window))
2111     gtk_widget_show_all (window);
2112   else
2113     gtk_widget_destroy (window);
2114 }
2115
2116 /*
2117  * Resize Grips
2118  */
2119 static gboolean
2120 grippy_button_press (GtkWidget *area, GdkEventButton *event, GdkWindowEdge edge)
2121 {
2122   if (event->type == GDK_BUTTON_PRESS) 
2123     {
2124       if (event->button == 1)
2125         gtk_window_begin_resize_drag (GTK_WINDOW (gtk_widget_get_toplevel (area)), edge,
2126                                       event->button, event->x_root, event->y_root,
2127                                       event->time);
2128       else if (event->button == 2)
2129         gtk_window_begin_move_drag (GTK_WINDOW (gtk_widget_get_toplevel (area)), 
2130                                     event->button, event->x_root, event->y_root,
2131                                     event->time);
2132     }
2133   return TRUE;
2134 }
2135
2136 static gboolean
2137 grippy_draw (GtkWidget *area, cairo_t *cr, GdkWindowEdge edge)
2138 {
2139   GtkStyleContext *context;
2140   GtkJunctionSides sides;
2141
2142   switch (edge)
2143     {
2144     case GDK_WINDOW_EDGE_NORTH_WEST:
2145       sides = GTK_JUNCTION_CORNER_TOPLEFT;
2146       break;
2147     case GDK_WINDOW_EDGE_NORTH:
2148       sides = GTK_JUNCTION_TOP;
2149       break;
2150     case GDK_WINDOW_EDGE_NORTH_EAST:
2151       sides = GTK_JUNCTION_CORNER_TOPRIGHT;
2152       break;
2153     case GDK_WINDOW_EDGE_WEST:
2154       sides = GTK_JUNCTION_LEFT;
2155       break;
2156     case GDK_WINDOW_EDGE_EAST:
2157       sides = GTK_JUNCTION_RIGHT;
2158       break;
2159     case GDK_WINDOW_EDGE_SOUTH_WEST:
2160       sides = GTK_JUNCTION_CORNER_BOTTOMLEFT;
2161       break;
2162     case GDK_WINDOW_EDGE_SOUTH:
2163       sides = GTK_JUNCTION_BOTTOM;
2164       break;
2165     case GDK_WINDOW_EDGE_SOUTH_EAST:
2166       sides = GTK_JUNCTION_CORNER_BOTTOMRIGHT;
2167       break;
2168     default:
2169       g_assert_not_reached();
2170     }
2171
2172   context = gtk_widget_get_style_context (area);
2173   gtk_style_context_save (context);
2174   gtk_style_context_add_class (context, "grip");
2175   gtk_style_context_set_junction_sides (context, sides);
2176   gtk_render_handle (context, cr,
2177                      0, 0,
2178                      gtk_widget_get_allocated_width (area),
2179                      gtk_widget_get_allocated_height (area));
2180
2181   gtk_style_context_restore (context);
2182
2183   return TRUE;
2184 }
2185
2186 static void
2187 create_resize_grips (GtkWidget *widget)
2188 {
2189   static GtkWidget *window = NULL;
2190   GtkWidget *area;
2191   GtkWidget *hbox, *vbox;
2192   if (!window)
2193     {
2194       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2195
2196       gtk_window_set_screen (GTK_WINDOW (window),
2197                              gtk_widget_get_screen (widget));
2198
2199       gtk_window_set_title (GTK_WINDOW (window), "resize grips");
2200       
2201       g_signal_connect (window, "destroy",
2202                         G_CALLBACK (gtk_widget_destroyed),
2203                         &window);
2204
2205       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
2206       gtk_container_add (GTK_CONTAINER (window), vbox);
2207       
2208       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
2209       gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
2210
2211       /* North west */
2212       area = gtk_drawing_area_new ();
2213       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
2214       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
2215       g_signal_connect (area, "draw", G_CALLBACK (grippy_draw),
2216                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH_WEST));
2217       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
2218                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH_WEST));
2219       
2220       /* North */
2221       area = gtk_drawing_area_new ();
2222       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
2223       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
2224       g_signal_connect (area, "draw", G_CALLBACK (grippy_draw),
2225                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH));
2226       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
2227                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH));
2228
2229       /* North east */
2230       area = gtk_drawing_area_new ();
2231       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
2232       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
2233       g_signal_connect (area, "draw", G_CALLBACK (grippy_draw),
2234                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH_EAST));
2235       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
2236                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH_EAST));
2237
2238       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
2239       gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
2240
2241       /* West */
2242       area = gtk_drawing_area_new ();
2243       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
2244       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
2245       g_signal_connect (area, "draw", G_CALLBACK (grippy_draw),
2246                         GINT_TO_POINTER (GDK_WINDOW_EDGE_WEST));
2247       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
2248                         GINT_TO_POINTER (GDK_WINDOW_EDGE_WEST));
2249
2250       /* Middle */
2251       area = gtk_drawing_area_new ();
2252       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
2253
2254       /* East */
2255       area = gtk_drawing_area_new ();
2256       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
2257       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
2258       g_signal_connect (area, "draw", G_CALLBACK (grippy_draw),
2259                         GINT_TO_POINTER (GDK_WINDOW_EDGE_EAST));
2260       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
2261                         GINT_TO_POINTER (GDK_WINDOW_EDGE_EAST));
2262
2263
2264       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
2265       gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
2266
2267       /* South west */
2268       area = gtk_drawing_area_new ();
2269       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
2270       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
2271       g_signal_connect (area, "draw", G_CALLBACK (grippy_draw),
2272                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH_WEST));
2273       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
2274                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH_WEST));
2275       /* South */
2276       area = gtk_drawing_area_new ();
2277       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
2278       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
2279       g_signal_connect (area, "draw", G_CALLBACK (grippy_draw),
2280                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH));
2281       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
2282                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH));
2283       
2284       /* South east */
2285       area = gtk_drawing_area_new ();
2286       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
2287       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
2288       g_signal_connect (area, "draw", G_CALLBACK (grippy_draw),
2289                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH_EAST));
2290       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
2291                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH_EAST));
2292     }
2293
2294   if (!gtk_widget_get_visible (window))
2295     gtk_widget_show_all (window);
2296   else
2297     gtk_widget_destroy (window);
2298 }
2299
2300 /*
2301  * Saved Position
2302  */
2303 gint upositionx = 0;
2304 gint upositiony = 0;
2305
2306 static gint
2307 uposition_configure (GtkWidget *window)
2308 {
2309   GtkLabel *lx;
2310   GtkLabel *ly;
2311   gchar buffer[64];
2312
2313   lx = g_object_get_data (G_OBJECT (window), "x");
2314   ly = g_object_get_data (G_OBJECT (window), "y");
2315
2316   gdk_window_get_root_origin (gtk_widget_get_window (window),
2317                               &upositionx, &upositiony);
2318   sprintf (buffer, "%d", upositionx);
2319   gtk_label_set_text (lx, buffer);
2320   sprintf (buffer, "%d", upositiony);
2321   gtk_label_set_text (ly, buffer);
2322
2323   return FALSE;
2324 }
2325
2326 static void
2327 uposition_stop_configure (GtkToggleButton *toggle,
2328                           GObject         *window)
2329 {
2330   if (gtk_toggle_button_get_active (toggle))
2331     g_signal_handlers_block_by_func (window, G_CALLBACK (uposition_configure), NULL);
2332   else
2333     g_signal_handlers_unblock_by_func (window, G_CALLBACK (uposition_configure), NULL);
2334 }
2335
2336 static void
2337 create_saved_position (GtkWidget *widget)
2338 {
2339   static GtkWidget *window = NULL;
2340
2341   if (!window)
2342     {
2343       GtkWidget *hbox;
2344       GtkWidget *main_vbox;
2345       GtkWidget *vbox;
2346       GtkWidget *x_label;
2347       GtkWidget *y_label;
2348       GtkWidget *button;
2349       GtkWidget *label;
2350       GtkWidget *any;
2351
2352       window = g_object_connect (g_object_new (GTK_TYPE_WINDOW,
2353                                                  "type", GTK_WINDOW_TOPLEVEL,
2354                                                  "title", "Saved Position",
2355                                                  NULL),
2356                                  "signal::configure_event", uposition_configure, NULL,
2357                                  NULL);
2358
2359       gtk_window_move (GTK_WINDOW (window), upositionx, upositiony);
2360
2361       gtk_window_set_screen (GTK_WINDOW (window),
2362                              gtk_widget_get_screen (widget));
2363       
2364
2365       g_signal_connect (window, "destroy",
2366                         G_CALLBACK (gtk_widget_destroyed),
2367                         &window);
2368
2369       main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
2370       gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 0);
2371       gtk_container_add (GTK_CONTAINER (window), main_vbox);
2372
2373       vbox =
2374         g_object_new (GTK_TYPE_BOX,
2375                       "orientation", GTK_ORIENTATION_VERTICAL,
2376                         "GtkBox::homogeneous", FALSE,
2377                         "GtkBox::spacing", 5,
2378                         "GtkContainer::border_width", 10,
2379                         "GtkWidget::parent", main_vbox,
2380                         "GtkWidget::visible", TRUE,
2381                         "child", g_object_connect (g_object_new (GTK_TYPE_TOGGLE_BUTTON,
2382                                                                    "label", "Stop Events",
2383                                                                    "active", FALSE,
2384                                                                    "visible", TRUE,
2385                                                                    NULL),
2386                                                    "signal::clicked", uposition_stop_configure, window,
2387                                                    NULL),
2388                         NULL);
2389
2390       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
2391       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
2392       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
2393
2394       label = gtk_label_new ("X Origin : ");
2395       gtk_widget_set_halign (label, GTK_ALIGN_START);
2396       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
2397       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
2398
2399       x_label = gtk_label_new ("");
2400       gtk_box_pack_start (GTK_BOX (hbox), x_label, TRUE, TRUE, 0);
2401       g_object_set_data (G_OBJECT (window), "x", x_label);
2402
2403       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
2404       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
2405       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
2406
2407       label = gtk_label_new ("Y Origin : ");
2408       gtk_widget_set_halign (label, GTK_ALIGN_START);
2409       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
2410       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
2411
2412       y_label = gtk_label_new ("");
2413       gtk_box_pack_start (GTK_BOX (hbox), y_label, TRUE, TRUE, 0);
2414       g_object_set_data (G_OBJECT (window), "y", y_label);
2415
2416       any =
2417         g_object_new (gtk_separator_get_type (),
2418                         "GtkWidget::visible", TRUE,
2419                         NULL);
2420       gtk_box_pack_start (GTK_BOX (main_vbox), any, FALSE, TRUE, 0);
2421
2422       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
2423       gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
2424       gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
2425
2426       button = gtk_button_new_with_label ("Close");
2427       g_signal_connect_swapped (button, "clicked",
2428                                 G_CALLBACK (gtk_widget_destroy),
2429                                 window);
2430       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
2431       gtk_widget_set_can_default (button, TRUE);
2432       gtk_widget_grab_default (button);
2433       
2434       gtk_widget_show_all (window);
2435     }
2436   else
2437     gtk_widget_destroy (window);
2438 }
2439
2440 /*
2441  * GtkPixmap
2442  */
2443
2444 static void
2445 create_pixbuf (GtkWidget *widget)
2446 {
2447   static GtkWidget *window = NULL;
2448   GtkWidget *box1;
2449   GtkWidget *box2;
2450   GtkWidget *box3;
2451   GtkWidget *button;
2452   GtkWidget *label;
2453   GtkWidget *separator;
2454   GtkWidget *pixbufwid;
2455   GdkWindow *gdk_window;
2456
2457   if (!window)
2458     {
2459       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2460
2461       gtk_window_set_screen (GTK_WINDOW (window),
2462                              gtk_widget_get_screen (widget));
2463
2464       g_signal_connect (window, "destroy",
2465                         G_CALLBACK (gtk_widget_destroyed),
2466                         &window);
2467
2468       gtk_window_set_title (GTK_WINDOW (window), "GtkPixmap");
2469       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
2470       gtk_widget_realize(window);
2471
2472       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
2473       gtk_container_add (GTK_CONTAINER (window), box1);
2474
2475       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
2476       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2477       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2478
2479       button = gtk_button_new ();
2480       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, FALSE, 0);
2481
2482       gdk_window = gtk_widget_get_window (window);
2483
2484       pixbufwid = new_pixbuf ("test.xpm", gdk_window);
2485
2486       label = gtk_label_new ("Pixbuf\ntest");
2487       box3 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
2488       gtk_container_set_border_width (GTK_CONTAINER (box3), 2);
2489       gtk_container_add (GTK_CONTAINER (box3), pixbufwid);
2490       gtk_container_add (GTK_CONTAINER (box3), label);
2491       gtk_container_add (GTK_CONTAINER (button), box3);
2492
2493       button = gtk_button_new ();
2494       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, FALSE, 0);
2495
2496       pixbufwid = new_pixbuf ("test.xpm", gdk_window);
2497
2498       label = gtk_label_new ("Pixbuf\ntest");
2499       box3 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
2500       gtk_container_set_border_width (GTK_CONTAINER (box3), 2);
2501       gtk_container_add (GTK_CONTAINER (box3), pixbufwid);
2502       gtk_container_add (GTK_CONTAINER (box3), label);
2503       gtk_container_add (GTK_CONTAINER (button), box3);
2504
2505       gtk_widget_set_sensitive (button, FALSE);
2506       
2507       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
2508       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2509
2510       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
2511       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2512       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2513
2514       button = gtk_button_new_with_label ("close");
2515       g_signal_connect_swapped (button, "clicked",
2516                                 G_CALLBACK (gtk_widget_destroy),
2517                                 window);
2518       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2519       gtk_widget_set_can_default (button, TRUE);
2520       gtk_widget_grab_default (button);
2521     }
2522
2523   if (!gtk_widget_get_visible (window))
2524     gtk_widget_show_all (window);
2525   else
2526     gtk_widget_destroy (window);
2527 }
2528
2529 static void
2530 create_tooltips (GtkWidget *widget)
2531 {
2532   static GtkWidget *window = NULL;
2533   GtkWidget *box1;
2534   GtkWidget *box2;
2535   GtkWidget *box3;
2536   GtkWidget *button;
2537   GtkWidget *toggle;
2538   GtkWidget *frame;
2539   GtkWidget *separator;
2540
2541   if (!window)
2542     {
2543       window =
2544         g_object_new (gtk_window_get_type (),
2545                         "GtkWindow::type", GTK_WINDOW_TOPLEVEL,
2546                         "GtkContainer::border_width", 0,
2547                         "GtkWindow::title", "Tooltips",
2548                         "GtkWindow::resizable", FALSE,
2549                         NULL);
2550
2551       gtk_window_set_screen (GTK_WINDOW (window),
2552                              gtk_widget_get_screen (widget));
2553
2554       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
2555       gtk_container_add (GTK_CONTAINER (window), box1);
2556
2557       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
2558       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2559       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2560
2561       button = gtk_toggle_button_new_with_label ("button1");
2562       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2563
2564       gtk_widget_set_tooltip_text (button, "This is button 1");
2565
2566       button = gtk_toggle_button_new_with_label ("button2");
2567       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2568
2569       gtk_widget_set_tooltip_text (button,
2570         "This is button 2. This is also a really long tooltip which probably "
2571         "won't fit on a single line and will therefore need to be wrapped. "
2572         "Hopefully the wrapping will work correctly.");
2573
2574       toggle = gtk_toggle_button_new_with_label ("Override TipsQuery Label");
2575       gtk_box_pack_start (GTK_BOX (box2), toggle, TRUE, TRUE, 0);
2576
2577       gtk_widget_set_tooltip_text (toggle, "Toggle TipsQuery view.");
2578
2579       box3 =
2580         g_object_new (GTK_TYPE_BOX,
2581                       "orientation", GTK_ORIENTATION_VERTICAL,
2582                         "homogeneous", FALSE,
2583                         "spacing", 5,
2584                         "border_width", 5,
2585                         "visible", TRUE,
2586                         NULL);
2587
2588       button =
2589         g_object_new (gtk_button_get_type (),
2590                         "label", "[?]",
2591                         "visible", TRUE,
2592                         "parent", box3,
2593                         NULL);
2594       gtk_box_set_child_packing (GTK_BOX (box3), button, FALSE, FALSE, 0, GTK_PACK_START);
2595       gtk_widget_set_tooltip_text (button, "Start the Tooltips Inspector");
2596       
2597       frame = g_object_new (gtk_frame_get_type (),
2598                               "label", "ToolTips Inspector",
2599                               "label_xalign", (double) 0.5,
2600                               "border_width", 0,
2601                               "visible", TRUE,
2602                               "parent", box2,
2603                               "child", box3,
2604                               NULL);
2605       gtk_box_set_child_packing (GTK_BOX (box2), frame, TRUE, TRUE, 10, GTK_PACK_START);
2606
2607       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
2608       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2609
2610       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
2611       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2612       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2613
2614       button = gtk_button_new_with_label ("close");
2615       g_signal_connect_swapped (button, "clicked",
2616                                 G_CALLBACK (gtk_widget_destroy),
2617                                 window);
2618       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2619       gtk_widget_set_can_default (button, TRUE);
2620       gtk_widget_grab_default (button);
2621
2622       gtk_widget_set_tooltip_text (button, "Push this button to close window");
2623     }
2624
2625   if (!gtk_widget_get_visible (window))
2626     gtk_widget_show_all (window);
2627   else
2628     gtk_widget_destroy (window);
2629 }
2630
2631 /*
2632  * GtkImage
2633  */
2634
2635 static void
2636 pack_image (GtkWidget *box,
2637             const gchar *text,
2638             GtkWidget *image)
2639 {
2640   gtk_box_pack_start (GTK_BOX (box),
2641                       gtk_label_new (text),
2642                       FALSE, FALSE, 0);
2643
2644   gtk_box_pack_start (GTK_BOX (box),
2645                       image,
2646                       TRUE, TRUE, 0);  
2647 }
2648
2649 static void
2650 create_image (GtkWidget *widget)
2651 {
2652   static GtkWidget *window = NULL;
2653
2654   if (window == NULL)
2655     {
2656       GtkWidget *vbox;
2657       GdkPixbuf *pixbuf;
2658         
2659       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2660       
2661       gtk_window_set_screen (GTK_WINDOW (window),
2662                              gtk_widget_get_screen (widget));
2663
2664       /* this is bogus for testing drawing when allocation < request,
2665        * don't copy into real code
2666        */
2667       gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
2668
2669       g_signal_connect (window, "destroy",
2670                         G_CALLBACK (gtk_widget_destroyed),
2671                         &window);
2672
2673       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
2674
2675       gtk_container_add (GTK_CONTAINER (window), vbox);
2676
2677       pack_image (vbox, "Stock Warning Dialog",
2678                   gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
2679                                             GTK_ICON_SIZE_DIALOG));
2680
2681       pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **) openfile);
2682       
2683       pack_image (vbox, "Pixbuf",
2684                   gtk_image_new_from_pixbuf (pixbuf));
2685
2686       g_object_unref (pixbuf);
2687     }
2688
2689   if (!gtk_widget_get_visible (window))
2690     gtk_widget_show_all (window);
2691   else
2692     gtk_widget_destroy (window);
2693 }
2694      
2695 /*
2696  * Menu demo
2697  */
2698
2699 static GtkWidget*
2700 create_menu (GdkScreen *screen, gint depth, gint length)
2701 {
2702   GtkWidget *menu;
2703   GtkWidget *menuitem;
2704   GtkWidget *image;
2705   GSList *group;
2706   char buf[32];
2707   int i, j;
2708
2709   if (depth < 1)
2710     return NULL;
2711
2712   menu = gtk_menu_new ();
2713   gtk_menu_set_screen (GTK_MENU (menu), screen);
2714
2715   group = NULL;
2716
2717   image = gtk_image_new_from_stock (GTK_STOCK_OPEN,
2718                                     GTK_ICON_SIZE_MENU);
2719   gtk_widget_show (image);
2720   menuitem = gtk_image_menu_item_new_with_label ("Image item");
2721   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
2722   gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2723   gtk_widget_show (menuitem);
2724   
2725   for (i = 0, j = 1; i < length; i++, j++)
2726     {
2727       sprintf (buf, "item %2d - %d", depth, j);
2728
2729       menuitem = gtk_radio_menu_item_new_with_label (group, buf);
2730       group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem));
2731
2732       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
2733       gtk_widget_show (menuitem);
2734       if (i == 3)
2735         gtk_widget_set_sensitive (menuitem, FALSE);
2736
2737       if (i == 5)
2738         gtk_check_menu_item_set_inconsistent (GTK_CHECK_MENU_ITEM (menuitem),
2739                                               TRUE);
2740
2741       if (i < 5)
2742         gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), 
2743                                    create_menu (screen, depth - 1, 5));
2744     }
2745
2746   return menu;
2747 }
2748
2749 static GtkWidget*
2750 create_table_menu (GdkScreen *screen, gint cols, gint rows)
2751 {
2752   GtkWidget *menu;
2753   GtkWidget *menuitem;
2754   GtkWidget *submenu;
2755   GtkWidget *image;
2756   char buf[32];
2757   int i, j;
2758
2759   menu = gtk_menu_new ();
2760   gtk_menu_set_screen (GTK_MENU (menu), screen);
2761
2762   j = 0;
2763   
2764   menuitem = gtk_menu_item_new_with_label ("items");
2765   gtk_menu_attach (GTK_MENU (menu), menuitem, 0, cols, j, j + 1);
2766
2767   submenu = gtk_menu_new ();
2768   gtk_menu_set_screen (GTK_MENU (submenu), screen);
2769   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
2770   gtk_widget_show (menuitem);
2771   j++;
2772
2773   /* now fill the items submenu */
2774   image = gtk_image_new_from_stock (GTK_STOCK_HELP,
2775                                     GTK_ICON_SIZE_MENU);
2776   gtk_widget_show (image);
2777   menuitem = gtk_image_menu_item_new_with_label ("Image");
2778   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
2779   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 0, 1);
2780   gtk_widget_show (menuitem);
2781
2782   menuitem = gtk_menu_item_new_with_label ("x");
2783   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 0, 1);
2784   gtk_widget_show (menuitem);
2785
2786   menuitem = gtk_menu_item_new_with_label ("x");
2787   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 1, 2);
2788   gtk_widget_show (menuitem);
2789   
2790   image = gtk_image_new_from_stock (GTK_STOCK_HELP,
2791                                     GTK_ICON_SIZE_MENU);
2792   gtk_widget_show (image);
2793   menuitem = gtk_image_menu_item_new_with_label ("Image");
2794   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
2795   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 1, 2);
2796   gtk_widget_show (menuitem);
2797
2798   menuitem = gtk_radio_menu_item_new_with_label (NULL, "Radio");
2799   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 2, 3);
2800   gtk_widget_show (menuitem);
2801
2802   menuitem = gtk_menu_item_new_with_label ("x");
2803   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 2, 3);
2804   gtk_widget_show (menuitem);
2805
2806   menuitem = gtk_menu_item_new_with_label ("x");
2807   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 3, 4);
2808   gtk_widget_show (menuitem);
2809   
2810   menuitem = gtk_radio_menu_item_new_with_label (NULL, "Radio");
2811   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 3, 4);
2812   gtk_widget_show (menuitem);
2813
2814   menuitem = gtk_check_menu_item_new_with_label ("Check");
2815   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 4, 5);
2816   gtk_widget_show (menuitem);
2817
2818   menuitem = gtk_menu_item_new_with_label ("x");
2819   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 4, 5);
2820   gtk_widget_show (menuitem);
2821
2822   menuitem = gtk_menu_item_new_with_label ("x");
2823   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 5, 6);
2824   gtk_widget_show (menuitem);
2825   
2826   menuitem = gtk_check_menu_item_new_with_label ("Check");
2827   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 5, 6);
2828   gtk_widget_show (menuitem);
2829
2830   menuitem = gtk_menu_item_new_with_label ("1. Inserted normally (8)");
2831   gtk_widget_show (menuitem);
2832   gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), menuitem, 8);
2833
2834   menuitem = gtk_menu_item_new_with_label ("2. Inserted normally (2)");
2835   gtk_widget_show (menuitem);
2836   gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), menuitem, 2);
2837
2838   menuitem = gtk_menu_item_new_with_label ("3. Inserted normally (0)");
2839   gtk_widget_show (menuitem);
2840   gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), menuitem, 0);
2841
2842   menuitem = gtk_menu_item_new_with_label ("4. Inserted normally (-1)");
2843   gtk_widget_show (menuitem);
2844   gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), menuitem, -1);
2845   
2846   /* end of items submenu */
2847
2848   menuitem = gtk_menu_item_new_with_label ("spanning");
2849   gtk_menu_attach (GTK_MENU (menu), menuitem, 0, cols, j, j + 1);
2850
2851   submenu = gtk_menu_new ();
2852   gtk_menu_set_screen (GTK_MENU (submenu), screen);
2853   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
2854   gtk_widget_show (menuitem);
2855   j++;
2856
2857   /* now fill the spanning submenu */
2858   menuitem = gtk_menu_item_new_with_label ("a");
2859   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 2, 0, 1);
2860   gtk_widget_show (menuitem);
2861
2862   menuitem = gtk_menu_item_new_with_label ("b");
2863   gtk_menu_attach (GTK_MENU (submenu), menuitem, 2, 3, 0, 2);
2864   gtk_widget_show (menuitem);
2865
2866   menuitem = gtk_menu_item_new_with_label ("c");
2867   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 1, 3);
2868   gtk_widget_show (menuitem);
2869
2870   menuitem = gtk_menu_item_new_with_label ("d");
2871   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 1, 2);
2872   gtk_widget_show (menuitem);
2873
2874   menuitem = gtk_menu_item_new_with_label ("e");
2875   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 3, 2, 3);
2876   gtk_widget_show (menuitem);
2877   /* end of spanning submenu */
2878   
2879   menuitem = gtk_menu_item_new_with_label ("left");
2880   gtk_menu_attach (GTK_MENU (menu), menuitem, 0, 1, j, j + 1);
2881   submenu = gtk_menu_new ();
2882   gtk_menu_set_screen (GTK_MENU (submenu), screen);
2883   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
2884   gtk_widget_show (menuitem);
2885
2886   menuitem = gtk_menu_item_new_with_label ("Empty");
2887   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 0, 1);
2888   submenu = gtk_menu_new ();
2889   gtk_menu_set_screen (GTK_MENU (submenu), screen);
2890   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
2891   gtk_widget_show (menuitem);
2892
2893   menuitem = gtk_menu_item_new_with_label ("right");
2894   gtk_menu_attach (GTK_MENU (menu), menuitem, 1, 2, j, j + 1);
2895   submenu = gtk_menu_new ();
2896   gtk_menu_set_screen (GTK_MENU (submenu), screen);
2897   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
2898   gtk_widget_show (menuitem);
2899
2900   menuitem = gtk_menu_item_new_with_label ("Empty");
2901   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 0, 1);
2902   gtk_widget_show (menuitem);
2903
2904   j++;
2905
2906   for (; j < rows; j++)
2907       for (i = 0; i < cols; i++)
2908       {
2909         sprintf (buf, "(%d %d)", i, j);
2910         menuitem = gtk_menu_item_new_with_label (buf);
2911         gtk_menu_attach (GTK_MENU (menu), menuitem, i, i + 1, j, j + 1);
2912         gtk_widget_show (menuitem);
2913       }
2914   
2915   menuitem = gtk_menu_item_new_with_label ("1. Inserted normally (8)");
2916   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 8);
2917   gtk_widget_show (menuitem);
2918   menuitem = gtk_menu_item_new_with_label ("2. Inserted normally (2)");
2919   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 2);
2920   gtk_widget_show (menuitem);
2921   menuitem = gtk_menu_item_new_with_label ("3. Inserted normally (0)");
2922   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 0);
2923   gtk_widget_show (menuitem);
2924   menuitem = gtk_menu_item_new_with_label ("4. Inserted normally (-1)");
2925   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, -1);
2926   gtk_widget_show (menuitem);
2927   
2928   return menu;
2929 }
2930
2931 static void
2932 create_menus (GtkWidget *widget)
2933 {
2934   static GtkWidget *window = NULL;
2935   GtkWidget *box1;
2936   GtkWidget *box2;
2937   GtkWidget *button;
2938   GtkWidget *optionmenu;
2939   GtkWidget *separator;
2940   
2941   if (!window)
2942     {
2943       GtkWidget *menubar;
2944       GtkWidget *menu;
2945       GtkWidget *menuitem;
2946       GtkAccelGroup *accel_group;
2947       GtkWidget *image;
2948       GdkScreen *screen = gtk_widget_get_screen (widget);
2949       
2950       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2951
2952       gtk_window_set_screen (GTK_WINDOW (window), screen);
2953       
2954       g_signal_connect (window, "destroy",
2955                         G_CALLBACK (gtk_widget_destroyed),
2956                         &window);
2957       g_signal_connect (window, "delete-event",
2958                         G_CALLBACK (gtk_true),
2959                         NULL);
2960       
2961       accel_group = gtk_accel_group_new ();
2962       gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
2963
2964       gtk_window_set_title (GTK_WINDOW (window), "menus");
2965       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
2966       
2967       
2968       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
2969       gtk_container_add (GTK_CONTAINER (window), box1);
2970       gtk_widget_show (box1);
2971       
2972       menubar = gtk_menu_bar_new ();
2973       gtk_box_pack_start (GTK_BOX (box1), menubar, FALSE, TRUE, 0);
2974       gtk_widget_show (menubar);
2975       
2976       menu = create_menu (screen, 2, 50);
2977       
2978       menuitem = gtk_menu_item_new_with_label ("test\nline2");
2979       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
2980       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
2981       gtk_widget_show (menuitem);
2982
2983       menu = create_table_menu (screen, 2, 50);
2984       
2985       menuitem = gtk_menu_item_new_with_label ("table");
2986       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
2987       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
2988       gtk_widget_show (menuitem);
2989       
2990       menuitem = gtk_menu_item_new_with_label ("foo");
2991       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (screen, 3, 5));
2992       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
2993       gtk_widget_show (menuitem);
2994
2995       image = gtk_image_new_from_stock (GTK_STOCK_HELP,
2996                                         GTK_ICON_SIZE_MENU);
2997       gtk_widget_show (image);
2998       menuitem = gtk_image_menu_item_new_with_label ("Help");
2999       gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
3000       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (screen, 4, 5));
3001       gtk_widget_set_hexpand (menuitem, TRUE);
3002       gtk_widget_set_halign (menuitem, GTK_ALIGN_END);
3003       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
3004       gtk_widget_show (menuitem);
3005       
3006       menubar = gtk_menu_bar_new ();
3007       gtk_box_pack_start (GTK_BOX (box1), menubar, FALSE, TRUE, 0);
3008       gtk_widget_show (menubar);
3009       
3010       menu = create_menu (screen, 2, 10);
3011       
3012       menuitem = gtk_menu_item_new_with_label ("Second menu bar");
3013       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
3014       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
3015       gtk_widget_show (menuitem);
3016       
3017       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
3018       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3019       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3020       gtk_widget_show (box2);
3021       
3022       menu = create_menu (screen, 1, 5);
3023       gtk_menu_set_accel_group (GTK_MENU (menu), accel_group);
3024
3025       menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_NEW, accel_group);
3026       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3027       gtk_widget_show (menuitem);
3028       
3029       menuitem = gtk_check_menu_item_new_with_label ("Accelerate Me");
3030       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3031       gtk_widget_show (menuitem);
3032       gtk_widget_add_accelerator (menuitem,
3033                                   "activate",
3034                                   accel_group,
3035                                   GDK_KEY_F1,
3036                                   0,
3037                                   GTK_ACCEL_VISIBLE);
3038       menuitem = gtk_check_menu_item_new_with_label ("Accelerator Locked");
3039       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3040       gtk_widget_show (menuitem);
3041       gtk_widget_add_accelerator (menuitem,
3042                                   "activate",
3043                                   accel_group,
3044                                   GDK_KEY_F2,
3045                                   0,
3046                                   GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED);
3047       menuitem = gtk_check_menu_item_new_with_label ("Accelerators Frozen");
3048       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3049       gtk_widget_show (menuitem);
3050       gtk_widget_add_accelerator (menuitem,
3051                                   "activate",
3052                                   accel_group,
3053                                   GDK_KEY_F2,
3054                                   0,
3055                                   GTK_ACCEL_VISIBLE);
3056       gtk_widget_add_accelerator (menuitem,
3057                                   "activate",
3058                                   accel_group,
3059                                   GDK_KEY_F3,
3060                                   0,
3061                                   GTK_ACCEL_VISIBLE);
3062
3063       optionmenu = gtk_combo_box_text_new ();
3064       gtk_combo_box_set_active (GTK_COMBO_BOX (optionmenu), 3);
3065       gtk_box_pack_start (GTK_BOX (box2), optionmenu, TRUE, TRUE, 0);
3066       gtk_widget_show (optionmenu);
3067
3068       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
3069       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
3070       gtk_widget_show (separator);
3071
3072       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
3073       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3074       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
3075       gtk_widget_show (box2);
3076
3077       button = gtk_button_new_with_label ("close");
3078       g_signal_connect_swapped (button, "clicked",
3079                                 G_CALLBACK (gtk_widget_destroy),
3080                                 window);
3081       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3082       gtk_widget_set_can_default (button, TRUE);
3083       gtk_widget_grab_default (button);
3084       gtk_widget_show (button);
3085     }
3086
3087   if (!gtk_widget_get_visible (window))
3088     gtk_widget_show (window);
3089   else
3090     gtk_widget_destroy (window);
3091 }
3092
3093 /* GdkPixbuf RGBA C-Source image dump */
3094
3095 static const guint8 apple[] = 
3096 { ""
3097   /* Pixbuf magic (0x47646b50) */
3098   "GdkP"
3099   /* length: header (24) + pixel_data (2304) */
3100   "\0\0\11\30"
3101   /* pixdata_type (0x1010002) */
3102   "\1\1\0\2"
3103   /* rowstride (96) */
3104   "\0\0\0`"
3105   /* width (24) */
3106   "\0\0\0\30"
3107   /* height (24) */
3108   "\0\0\0\30"
3109   /* pixel_data: */
3110   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3111   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3112   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3113   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3114   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3115   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3116   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\26\24"
3117   "\17\11\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3118   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`m"
3119   "[pn{a\344hv_\345_k[`\0\0\0\0\0\0\0\0\0\0\0\0D>/\305\0\0\0_\0\0\0\0\0"
3120   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3121   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`l[Blza\373s\202d\354w\206g\372p~c"
3122   "\374`l[y\0\0\0\0[S\77/\27\25\17\335\0\0\0\20\0\0\0\0\0\0\0\0\0\0\0\0"
3123   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3124   "\0\0\0\0\0\0`l\\\20iw_\356y\211h\373x\207g\364~\216i\364u\204e\366gt"
3125   "_\374^jX\241A;-_\0\0\0~\0\0\0\0SM4)SM21B9&\22\320\270\204\1\320\270\204"
3126   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0eq"
3127   "]\212r\200c\366v\205f\371jx_\323_kY\232_kZH^jY\26]iW\211@G9\272:6%j\220"
3128   "\211]\320\221\211`\377\212\203Z\377~xP\377mkE\331]^;|/0\37\21\0\0\0\0"
3129   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ly`\40p~b\360lz`\353^kY\246["
3130   "eT<\216\200Z\203\227\211_\354\234\217c\377\232\217b\362\232\220c\337"
3131   "\243\233k\377\252\241p\377\250\236p\377\241\225h\377\231\214_\377\210"
3132   "\202U\377srI\377[]:\355KO0U\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0i"
3133   "v^\200`lY\211^jY\"\0\0\0\0\221\204\\\273\250\233r\377\302\267\224\377"
3134   "\311\300\237\377\272\256\204\377\271\256\177\377\271\257\200\377\267"
3135   "\260\177\377\260\251x\377\250\236l\377\242\225e\377\226\213]\377~zP\377"
3136   "ff@\377QT5\377LR2d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0]iW(\0\0\0\0\0\0\0"
3137   "\0\213\203[v\253\240t\377\334\326\301\377\344\340\317\377\321\312\253"
3138   "\377\303\271\217\377\300\270\213\377\277\267\210\377\272\264\203\377"
3139   "\261\255z\377\250\242n\377\243\232h\377\232\220`\377\210\202V\377nnE"
3140   "\377SW6\377RX6\364Za<\34\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0b]@\20"
3141   "\234\222e\362\304\274\232\377\337\333\306\377\332\325\273\377\311\302"
3142   "\232\377\312\303\236\377\301\273\216\377\300\271\212\377\270\264\200"
3143   "\377\256\253v\377\246\243n\377\236\232h\377\230\220`\377\213\203V\377"
3144   "wvL\377X]:\377KR0\377NU5v\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\212"
3145   "\203Zl\242\234l\377\321\315\260\377\331\324\271\377\320\313\251\377\307"
3146   "\301\232\377\303\276\224\377\300\272\214\377\274\267\206\377\264\260"
3147   "|\377\253\251s\377\244\243n\377\232\230e\377\223\216^\377\207\200U\377"
3148   "ttJ\377[_<\377HO/\377GN0\200\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3149   "\210\204Y\240\245\237o\377\316\310\253\377\310\303\237\377\304\300\230"
3150   "\377\303\277\225\377\277\272\216\377\274\270\210\377\266\263\200\377"
3151   "\256\254v\377\247\246p\377\237\236j\377\227\226d\377\215\212[\377\203"
3152   "\177T\377qsH\377X]8\377FN.\377DK-\200\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3153   "\0\0\0\0\207\204X\257\244\240o\377\300\275\231\377\301\275\226\377\274"
3154   "\270\213\377\274\270\214\377\267\264\205\377\264\262\200\377\260\256"
3155   "z\377\251\251s\377\243\244n\377\231\232g\377\220\222`\377\210\211Y\377"
3156   "|}Q\377hlC\377PU3\377CK,\377DL/Y\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3157   "\0\0\205\204X\220\232\230h\377\261\260\204\377\266\264\212\377\261\260"
3158   "\201\377\263\260\200\377\260\257}\377\256\256x\377\253\254t\377\244\246"
3159   "o\377\233\236i\377\221\224b\377\211\214\\\377\202\204V\377txM\377]b>"
3160   "\377HP0\377@H+\373CJ-\25\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0xxO>"
3161   "\215\215_\377\237\237r\377\247\247x\377\247\247t\377\252\252w\377\252"
3162   "\252u\377\252\253t\377\243\246o\377\235\240j\377\223\230c\377\213\217"
3163   "]\377\201\206V\377x}P\377gkD\377RY5\377BI,\377AI,\262\0\0\0\0\0\0\0\0"
3164   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\202\205W\312\216\220`\377\230"
3165   "\232g\377\234\236i\377\236\241l\377\241\244n\377\240\244m\377\232\237"
3166   "i\377\223\230c\377\212\221]\377\200\210W\377v|P\377jnG\377Za>\377HP2"
3167   "\377=D)\377HQ1:\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3168   "\0wzQ6\177\201U\371\206\211Z\377\216\222`\377\220\225a\377\220\225b\377"
3169   "\220\226a\377\213\221_\377\204\213Z\377{\203R\377ryN\377iqH\377^fA\377"
3170   "R[;\377BJ-\3778@'\317\0\0\0>\0\0\0\36\0\0\0\7\0\0\0\0\0\0\0\0\0\0\0\0"
3171   "\0\0\0\0\0\0\0\0\0\0\0\0ptJTw|Q\371z\177R\377}\202T\377|\203T\377z\200"
3172   "R\377v|O\377pwL\377jpF\377dlB\377`hB\377Yb@\377LT6\377<C*\377\11\12\6"
3173   "\376\0\0\0\347\0\0\0\262\0\0\0Y\0\0\0\32\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3174   "\0\0\0\0\0\0\0\0\0\0\\`=UgnE\370hnG\377gmE\377djB\377]d>\377[c<\377Y"
3175   "b<\377Zc>\377V_>\377OW8\377BK/\377\16\20\12\377\0\0\0\377\0\0\0\377\0"
3176   "\0\0\374\0\0\0\320\0\0\0I\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3177   "\0\1\0\0\0\40\22\24\15\260@D+\377W`;\377OV5\377.3\36\377.3\37\377IP0"
3178   "\377RZ7\377PZ8\3776=&\377\14\15\10\377\0\0\0\377\0\0\0\377\0\0\0\377"
3179   "\0\0\0\347\0\0\0\217\0\0\0""4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3180   "\0\0\0\0\0\0\0\20\0\0\0P\0\0\0\252\7\10\5\346\7\7\5\375\0\0\0\377\0\0"
3181   "\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\374\0"
3182   "\0\0\336\0\0\0\254\0\0\0i\0\0\0""2\0\0\0\10\0\0\0\0\0\0\0\0\0\0\0\0\0"
3183   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\11\0\0\0\40\0\0\0D\0\0\0m\0\0\0"
3184   "\226\0\0\0\234\0\0\0\234\0\0\0\244\0\0\0\246\0\0\0\232\0\0\0\202\0\0"
3185   "\0i\0\0\0T\0\0\0,\0\0\0\15\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3186   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\2\0\0\0\6\0\0\0"
3187   "\16\0\0\0\22\0\0\0\24\0\0\0\23\0\0\0\17\0\0\0\14\0\0\0\13\0\0\0\10\0"
3188   "\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"};
3189
3190
3191 static GtkWidget *
3192 accel_button_new (GtkAccelGroup *accel_group,
3193                   const gchar   *text,
3194                   const gchar   *accel)
3195 {
3196   guint keyval;
3197   GdkModifierType modifiers;
3198   GtkWidget *button;
3199   GtkWidget *label;
3200
3201   gtk_accelerator_parse (accel, &keyval, &modifiers);
3202   g_assert (keyval);
3203
3204   button = gtk_button_new ();
3205   gtk_widget_add_accelerator (button, "activate", accel_group,
3206                               keyval, modifiers, GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED);
3207
3208   label = gtk_accel_label_new (text);
3209   gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), button);
3210   gtk_widget_show (label);
3211   
3212   gtk_container_add (GTK_CONTAINER (button), label);
3213
3214   return button;
3215 }
3216
3217 static void
3218 create_key_lookup (GtkWidget *widget)
3219 {
3220   static GtkWidget *window = NULL;
3221   gpointer window_ptr;
3222
3223   if (!window)
3224     {
3225       GtkAccelGroup *accel_group = gtk_accel_group_new ();
3226       GtkWidget *button;
3227       GtkWidget *content_area;
3228
3229       window = gtk_dialog_new_with_buttons ("Key Lookup", NULL, 0,
3230                                             GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
3231                                             NULL);
3232
3233       gtk_window_set_screen (GTK_WINDOW (window),
3234                              gtk_widget_get_screen (widget));
3235
3236       /* We have to expand it so the accel labels will draw their labels
3237        */
3238       gtk_window_set_default_size (GTK_WINDOW (window), 300, -1);
3239       
3240       gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
3241
3242       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
3243       
3244       button = gtk_button_new_with_mnemonic ("Button 1 (_a)");
3245       gtk_box_pack_start (GTK_BOX (content_area), button, FALSE, FALSE, 0);
3246       button = gtk_button_new_with_mnemonic ("Button 2 (_A)");
3247       gtk_box_pack_start (GTK_BOX (content_area), button, FALSE, FALSE, 0);
3248       button = gtk_button_new_with_mnemonic ("Button 3 (_\321\204)");
3249       gtk_box_pack_start (GTK_BOX (content_area), button, FALSE, FALSE, 0);
3250       button = gtk_button_new_with_mnemonic ("Button 4 (_\320\244)");
3251       gtk_box_pack_start (GTK_BOX (content_area), button, FALSE, FALSE, 0);
3252       button = gtk_button_new_with_mnemonic ("Button 6 (_b)");
3253       gtk_box_pack_start (GTK_BOX (content_area), button, FALSE, FALSE, 0);
3254       button = accel_button_new (accel_group, "Button 7", "<Alt><Shift>b");
3255       gtk_box_pack_start (GTK_BOX (content_area), button, FALSE, FALSE, 0);
3256       button = accel_button_new (accel_group, "Button 8", "<Alt>d");
3257       gtk_box_pack_start (GTK_BOX (content_area), button, FALSE, FALSE, 0);
3258       button = accel_button_new (accel_group, "Button 9", "<Alt>Cyrillic_ve");
3259       gtk_box_pack_start (GTK_BOX (content_area), button, FALSE, FALSE, 0);
3260       button = gtk_button_new_with_mnemonic ("Button 10 (_1)");
3261       gtk_box_pack_start (GTK_BOX (content_area), button, FALSE, FALSE, 0);
3262       button = gtk_button_new_with_mnemonic ("Button 11 (_!)");
3263       gtk_box_pack_start (GTK_BOX (content_area), button, FALSE, FALSE, 0);
3264       button = accel_button_new (accel_group, "Button 12", "<Super>a");
3265       gtk_box_pack_start (GTK_BOX (content_area), button, FALSE, FALSE, 0);
3266       button = accel_button_new (accel_group, "Button 13", "<Hyper>a");
3267       gtk_box_pack_start (GTK_BOX (content_area), button, FALSE, FALSE, 0);
3268       button = accel_button_new (accel_group, "Button 14", "<Meta>a");
3269       gtk_box_pack_start (GTK_BOX (content_area), button, FALSE, FALSE, 0);
3270       button = accel_button_new (accel_group, "Button 15", "<Shift><Mod4>b");
3271       gtk_box_pack_start (GTK_BOX (content_area), button, FALSE, FALSE, 0);
3272
3273       window_ptr = &window;
3274       g_object_add_weak_pointer (G_OBJECT (window), window_ptr);
3275       g_signal_connect (window, "response", G_CALLBACK (gtk_widget_destroy), NULL);
3276
3277       gtk_widget_show_all (window);
3278     }
3279   else
3280     gtk_widget_destroy (window);
3281 }
3282
3283
3284 /*
3285  create_modal_window
3286  */
3287
3288 static gboolean
3289 cmw_destroy_cb(GtkWidget *widget)
3290 {
3291   /* This is needed to get out of gtk_main */
3292   gtk_main_quit ();
3293
3294   return FALSE;
3295 }
3296
3297 static void
3298 cmw_color (GtkWidget *widget, GtkWidget *parent)
3299 {
3300     GtkWidget *csd;
3301     GtkWidget *colorsel;
3302     GtkWidget *ok_button, *cancel_button;
3303
3304     csd = gtk_color_selection_dialog_new ("This is a modal color selection dialog");
3305
3306     gtk_window_set_screen (GTK_WINDOW (csd), gtk_widget_get_screen (parent));
3307
3308     colorsel = gtk_color_selection_dialog_get_color_selection (GTK_COLOR_SELECTION_DIALOG (csd));
3309     gtk_color_selection_set_has_palette (GTK_COLOR_SELECTION (colorsel),
3310                                          TRUE);
3311     
3312     /* Set as modal */
3313     gtk_window_set_modal (GTK_WINDOW(csd),TRUE);
3314
3315     /* And mark it as a transient dialog */
3316     gtk_window_set_transient_for (GTK_WINDOW (csd), GTK_WINDOW (parent));
3317     
3318     g_signal_connect (csd, "destroy",
3319                       G_CALLBACK (cmw_destroy_cb), NULL);
3320
3321     g_object_get (csd,
3322                   "ok-button", &ok_button,
3323                   "cancel-button", &cancel_button,
3324                   NULL);
3325
3326     g_signal_connect_swapped (ok_button,
3327                              "clicked", G_CALLBACK (gtk_widget_destroy), csd);
3328     g_signal_connect_swapped (cancel_button,
3329                              "clicked", G_CALLBACK (gtk_widget_destroy), csd);
3330     
3331     /* wait until destroy calls gtk_main_quit */
3332     gtk_widget_show (csd);    
3333     gtk_main ();
3334 }
3335
3336 static void
3337 cmw_file (GtkWidget *widget, GtkWidget *parent)
3338 {
3339     GtkWidget *fs;
3340
3341     fs = gtk_file_chooser_dialog_new ("This is a modal file selection dialog",
3342       GTK_WINDOW (parent), GTK_FILE_CHOOSER_ACTION_OPEN,
3343       GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
3344       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
3345       NULL);
3346     gtk_window_set_screen (GTK_WINDOW (fs), gtk_widget_get_screen (parent));
3347     gtk_window_set_modal (GTK_WINDOW (fs), TRUE);
3348
3349     g_signal_connect (fs, "destroy",
3350                       G_CALLBACK (cmw_destroy_cb), NULL);
3351     g_signal_connect_swapped (fs, "response",
3352                       G_CALLBACK (gtk_widget_destroy), fs);
3353
3354     /* wait until destroy calls gtk_main_quit */
3355     gtk_widget_show (fs);
3356     gtk_main();
3357 }
3358
3359
3360 static void
3361 create_modal_window (GtkWidget *widget)
3362 {
3363   GtkWidget *window = NULL;
3364   GtkWidget *box1,*box2;
3365   GtkWidget *frame1;
3366   GtkWidget *btnColor,*btnFile,*btnClose;
3367
3368   /* Create modal window (Here you can use any window descendent )*/
3369   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3370   gtk_window_set_screen (GTK_WINDOW (window),
3371                          gtk_widget_get_screen (widget));
3372
3373   gtk_window_set_title (GTK_WINDOW(window),"This window is modal");
3374
3375   /* Set window as modal */
3376   gtk_window_set_modal (GTK_WINDOW(window),TRUE);
3377
3378   /* Create widgets */
3379   box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
3380   frame1 = gtk_frame_new ("Standard dialogs in modal form");
3381   box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
3382   gtk_box_set_homogeneous (GTK_BOX (box2), TRUE);
3383   btnColor = gtk_button_new_with_label ("Color");
3384   btnFile = gtk_button_new_with_label ("File Selection");
3385   btnClose = gtk_button_new_with_label ("Close");
3386
3387   /* Init widgets */
3388   gtk_container_set_border_width (GTK_CONTAINER (box1), 3);
3389   gtk_container_set_border_width (GTK_CONTAINER (box2), 3);
3390     
3391   /* Pack widgets */
3392   gtk_container_add (GTK_CONTAINER (window), box1);
3393   gtk_box_pack_start (GTK_BOX (box1), frame1, TRUE, TRUE, 4);
3394   gtk_container_add (GTK_CONTAINER (frame1), box2);
3395   gtk_box_pack_start (GTK_BOX (box2), btnColor, FALSE, FALSE, 4);
3396   gtk_box_pack_start (GTK_BOX (box2), btnFile, FALSE, FALSE, 4);
3397   gtk_box_pack_start (GTK_BOX (box1), gtk_separator_new (GTK_ORIENTATION_HORIZONTAL), FALSE, FALSE, 4);
3398   gtk_box_pack_start (GTK_BOX (box1), btnClose, FALSE, FALSE, 4);
3399    
3400   /* connect signals */
3401   g_signal_connect_swapped (btnClose, "clicked",
3402                             G_CALLBACK (gtk_widget_destroy), window);
3403
3404   g_signal_connect (window, "destroy",
3405                     G_CALLBACK (cmw_destroy_cb), NULL);
3406   
3407   g_signal_connect (btnColor, "clicked",
3408                     G_CALLBACK (cmw_color), window);
3409   g_signal_connect (btnFile, "clicked",
3410                     G_CALLBACK (cmw_file), window);
3411
3412   /* Show widgets */
3413   gtk_widget_show_all (window);
3414
3415   /* wait until dialog get destroyed */
3416   gtk_main();
3417 }
3418
3419 /*
3420  * GtkMessageDialog
3421  */
3422
3423 static void
3424 make_message_dialog (GdkScreen *screen,
3425                      GtkWidget **dialog,
3426                      GtkMessageType  type,
3427                      GtkButtonsType  buttons,
3428                      guint           default_response)
3429 {
3430   if (*dialog)
3431     {
3432       gtk_widget_destroy (*dialog);
3433
3434       return;
3435     }
3436
3437   *dialog = gtk_message_dialog_new (NULL, 0, type, buttons,
3438                                     "This is a message dialog; it can wrap long lines. This is a long line. La la la. Look this line is wrapped. Blah blah blah blah blah blah. (Note: testgtk has a nonstandard gtkrc that changes some of the message dialog icons.)");
3439
3440   gtk_window_set_screen (GTK_WINDOW (*dialog), screen);
3441
3442   g_signal_connect_swapped (*dialog,
3443                             "response",
3444                             G_CALLBACK (gtk_widget_destroy),
3445                             *dialog);
3446   
3447   g_signal_connect (*dialog,
3448                     "destroy",
3449                     G_CALLBACK (gtk_widget_destroyed),
3450                     dialog);
3451
3452   gtk_dialog_set_default_response (GTK_DIALOG (*dialog), default_response);
3453
3454   gtk_widget_show (*dialog);
3455 }
3456
3457 static void
3458 create_message_dialog (GtkWidget *widget)
3459 {
3460   static GtkWidget *info = NULL;
3461   static GtkWidget *warning = NULL;
3462   static GtkWidget *error = NULL;
3463   static GtkWidget *question = NULL;
3464   GdkScreen *screen = gtk_widget_get_screen (widget);
3465
3466   make_message_dialog (screen, &info, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, GTK_RESPONSE_OK);
3467   make_message_dialog (screen, &warning, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, GTK_RESPONSE_CLOSE);
3468   make_message_dialog (screen, &error, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK_CANCEL, GTK_RESPONSE_OK);
3469   make_message_dialog (screen, &question, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, GTK_RESPONSE_NO);
3470 }
3471
3472 /*
3473  * GtkScrolledWindow
3474  */
3475
3476 static GtkWidget *sw_parent = NULL;
3477 static GtkWidget *sw_float_parent;
3478 static gulong sw_destroyed_handler = 0;
3479
3480 static gboolean
3481 scrolled_windows_delete_cb (GtkWidget *widget, GdkEventAny *event, GtkWidget *scrollwin)
3482 {
3483   gtk_widget_reparent (scrollwin, sw_parent);
3484   
3485   g_signal_handler_disconnect (sw_parent, sw_destroyed_handler);
3486   sw_float_parent = NULL;
3487   sw_parent = NULL;
3488   sw_destroyed_handler = 0;
3489
3490   return FALSE;
3491 }
3492
3493 static void
3494 scrolled_windows_destroy_cb (GtkWidget *widget, GtkWidget *scrollwin)
3495 {
3496   gtk_widget_destroy (sw_float_parent);
3497
3498   sw_float_parent = NULL;
3499   sw_parent = NULL;
3500   sw_destroyed_handler = 0;
3501 }
3502
3503 static void
3504 scrolled_windows_remove (GtkWidget *widget, GtkWidget *scrollwin)
3505 {
3506   if (sw_parent)
3507     {
3508       gtk_widget_reparent (scrollwin, sw_parent);
3509       gtk_widget_destroy (sw_float_parent);
3510
3511       g_signal_handler_disconnect (sw_parent, sw_destroyed_handler);
3512       sw_float_parent = NULL;
3513       sw_parent = NULL;
3514       sw_destroyed_handler = 0;
3515     }
3516   else
3517     {
3518       sw_parent = gtk_widget_get_parent (scrollwin);
3519       sw_float_parent = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3520       gtk_window_set_screen (GTK_WINDOW (sw_float_parent),
3521                              gtk_widget_get_screen (widget));
3522       
3523       gtk_window_set_default_size (GTK_WINDOW (sw_float_parent), 200, 200);
3524       
3525       gtk_widget_reparent (scrollwin, sw_float_parent);
3526       gtk_widget_show (sw_float_parent);
3527
3528       sw_destroyed_handler =
3529         g_signal_connect (sw_parent, "destroy",
3530                           G_CALLBACK (scrolled_windows_destroy_cb), scrollwin);
3531       g_signal_connect (sw_float_parent, "delete_event",
3532                         G_CALLBACK (scrolled_windows_delete_cb), scrollwin);
3533     }
3534 }
3535
3536 static void
3537 create_scrolled_windows (GtkWidget *widget)
3538 {
3539   static GtkWidget *window;
3540   GtkWidget *content_area, *action_area;
3541   GtkWidget *scrolled_window;
3542   GtkWidget *grid;
3543   GtkWidget *button;
3544   char buffer[32];
3545   int i, j;
3546
3547   if (!window)
3548     {
3549       window = gtk_dialog_new ();
3550
3551       gtk_window_set_screen (GTK_WINDOW (window),
3552                              gtk_widget_get_screen (widget));
3553
3554       g_signal_connect (window, "destroy",
3555                         G_CALLBACK (gtk_widget_destroyed),
3556                         &window);
3557
3558       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
3559       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
3560
3561       gtk_window_set_title (GTK_WINDOW (window), "dialog");
3562       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
3563
3564       scrolled_window = gtk_scrolled_window_new (NULL, NULL);
3565       gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
3566       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
3567                                       GTK_POLICY_AUTOMATIC,
3568                                       GTK_POLICY_AUTOMATIC);
3569       gtk_box_pack_start (GTK_BOX (content_area), scrolled_window, TRUE, TRUE, 0);
3570       gtk_widget_show (scrolled_window);
3571
3572       grid = gtk_grid_new ();
3573       gtk_grid_set_row_spacing (GTK_GRID (grid), 10);
3574       gtk_grid_set_column_spacing (GTK_GRID (grid), 10);
3575       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), grid);
3576       gtk_container_set_focus_hadjustment (GTK_CONTAINER (grid),
3577                                            gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
3578       gtk_container_set_focus_vadjustment (GTK_CONTAINER (grid),
3579                                            gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
3580       gtk_widget_show (grid);
3581
3582       for (i = 0; i < 20; i++)
3583         for (j = 0; j < 20; j++)
3584           {
3585             sprintf (buffer, "button (%d,%d)\n", i, j);
3586             button = gtk_toggle_button_new_with_label (buffer);
3587             gtk_grid_attach (GTK_GRID (grid), button, i, j, 1, 1);
3588             gtk_widget_show (button);
3589           }
3590
3591
3592       button = gtk_button_new_with_label ("Close");
3593       g_signal_connect_swapped (button, "clicked",
3594                                 G_CALLBACK (gtk_widget_destroy),
3595                                 window);
3596       gtk_widget_set_can_default (button, TRUE);
3597       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
3598       gtk_widget_grab_default (button);
3599       gtk_widget_show (button);
3600
3601       button = gtk_button_new_with_label ("Reparent Out");
3602       g_signal_connect (button, "clicked",
3603                         G_CALLBACK (scrolled_windows_remove),
3604                         scrolled_window);
3605       gtk_widget_set_can_default (button, TRUE);
3606       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
3607       gtk_widget_grab_default (button);
3608       gtk_widget_show (button);
3609
3610       gtk_window_set_default_size (GTK_WINDOW (window), 300, 300);
3611     }
3612
3613   if (!gtk_widget_get_visible (window))
3614     gtk_widget_show (window);
3615   else
3616     gtk_widget_destroy (window);
3617 }
3618
3619 /*
3620  * GtkEntry
3621  */
3622
3623 static void
3624 entry_toggle_frame (GtkWidget *checkbutton,
3625                     GtkWidget *entry)
3626 {
3627    gtk_entry_set_has_frame (GTK_ENTRY(entry),
3628                             gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbutton)));
3629 }
3630
3631 static void
3632 entry_toggle_sensitive (GtkWidget *checkbutton,
3633                         GtkWidget *entry)
3634 {
3635    gtk_widget_set_sensitive (entry,
3636                              gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(checkbutton)));
3637 }
3638
3639 static gboolean
3640 entry_progress_timeout (gpointer data)
3641 {
3642   if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (data), "progress-pulse")))
3643     {
3644       gtk_entry_progress_pulse (GTK_ENTRY (data));
3645     }
3646   else
3647     {
3648       gdouble fraction;
3649
3650       fraction = gtk_entry_get_progress_fraction (GTK_ENTRY (data));
3651
3652       fraction += 0.05;
3653       if (fraction > 1.0001)
3654         fraction = 0.0;
3655
3656       gtk_entry_set_progress_fraction (GTK_ENTRY (data), fraction);
3657     }
3658
3659   return TRUE;
3660 }
3661
3662 static void
3663 entry_remove_timeout (gpointer data)
3664 {
3665   g_source_remove (GPOINTER_TO_UINT (data));
3666 }
3667
3668 static void
3669 entry_toggle_progress (GtkWidget *checkbutton,
3670                        GtkWidget *entry)
3671 {
3672   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbutton)))
3673     {
3674       guint timeout = gdk_threads_add_timeout (100,
3675                                                entry_progress_timeout,
3676                                                entry);
3677       g_object_set_data_full (G_OBJECT (entry), "timeout-id",
3678                               GUINT_TO_POINTER (timeout),
3679                               entry_remove_timeout);
3680     }
3681   else
3682     {
3683       g_object_set_data (G_OBJECT (entry), "timeout-id",
3684                          GUINT_TO_POINTER (0));
3685
3686       gtk_entry_set_progress_fraction (GTK_ENTRY (entry), 0.0);
3687     }
3688 }
3689
3690 static void
3691 entry_toggle_pulse (GtkWidget *checkbutton,
3692                     GtkWidget *entry)
3693 {
3694   g_object_set_data (G_OBJECT (entry), "progress-pulse",
3695                      GUINT_TO_POINTER ((guint) gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbutton))));
3696 }
3697
3698 static void
3699 props_clicked (GtkWidget *button,
3700                GObject   *object)
3701 {
3702   GtkWidget *window = create_prop_editor (object, 0);
3703
3704   gtk_window_set_title (GTK_WINDOW (window), "Object Properties");
3705 }
3706
3707 static void
3708 create_entry (GtkWidget *widget)
3709 {
3710   static GtkWidget *window = NULL;
3711   GtkWidget *box1;
3712   GtkWidget *box2;
3713   GtkWidget *hbox;
3714   GtkWidget *has_frame_check;
3715   GtkWidget *sensitive_check;
3716   GtkWidget *progress_check;
3717   GtkWidget *entry;
3718   GtkComboBoxText *cb;
3719   GtkWidget *cb_entry;
3720   GtkWidget *button;
3721   GtkWidget *separator;
3722
3723   if (!window)
3724     {
3725       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3726       gtk_window_set_screen (GTK_WINDOW (window),
3727                              gtk_widget_get_screen (widget));
3728
3729       g_signal_connect (window, "destroy",
3730                         G_CALLBACK (gtk_widget_destroyed),
3731                         &window);
3732
3733       gtk_window_set_title (GTK_WINDOW (window), "entry");
3734       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
3735
3736
3737       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
3738       gtk_container_add (GTK_CONTAINER (window), box1);
3739
3740
3741       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
3742       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3743       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3744
3745       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
3746       gtk_box_pack_start (GTK_BOX (box2), hbox, TRUE, TRUE, 0);
3747       
3748       entry = gtk_entry_new ();
3749       gtk_entry_set_text (GTK_ENTRY (entry), "hello world \330\247\331\204\330\263\331\204\330\247\331\205 \330\271\331\204\331\212\331\203\331\205");
3750       gtk_editable_select_region (GTK_EDITABLE (entry), 0, 5);
3751       gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
3752
3753       button = gtk_button_new_with_mnemonic ("_Props");
3754       gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
3755       g_signal_connect (button, "clicked",
3756                         G_CALLBACK (props_clicked),
3757                         entry);
3758
3759       cb = GTK_COMBO_BOX_TEXT (gtk_combo_box_text_new_with_entry ());
3760
3761       gtk_combo_box_text_append_text (cb, "item0");
3762       gtk_combo_box_text_append_text (cb, "item0");
3763       gtk_combo_box_text_append_text (cb, "item1 item1");
3764       gtk_combo_box_text_append_text (cb, "item2 item2 item2");
3765       gtk_combo_box_text_append_text (cb, "item3 item3 item3 item3");
3766       gtk_combo_box_text_append_text (cb, "item4 item4 item4 item4 item4");
3767       gtk_combo_box_text_append_text (cb, "item5 item5 item5 item5 item5 item5");
3768       gtk_combo_box_text_append_text (cb, "item6 item6 item6 item6 item6");
3769       gtk_combo_box_text_append_text (cb, "item7 item7 item7 item7");
3770       gtk_combo_box_text_append_text (cb, "item8 item8 item8");
3771       gtk_combo_box_text_append_text (cb, "item9 item9");
3772
3773       cb_entry = gtk_bin_get_child (GTK_BIN (cb));
3774       gtk_entry_set_text (GTK_ENTRY (cb_entry), "hello world \n\n\n foo");
3775       gtk_editable_select_region (GTK_EDITABLE (cb_entry), 0, -1);
3776       gtk_box_pack_start (GTK_BOX (box2), GTK_WIDGET (cb), TRUE, TRUE, 0);
3777
3778       sensitive_check = gtk_check_button_new_with_label("Sensitive");
3779       gtk_box_pack_start (GTK_BOX (box2), sensitive_check, FALSE, TRUE, 0);
3780       g_signal_connect (sensitive_check, "toggled",
3781                         G_CALLBACK (entry_toggle_sensitive), entry);
3782       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sensitive_check), TRUE);
3783
3784       has_frame_check = gtk_check_button_new_with_label("Has Frame");
3785       gtk_box_pack_start (GTK_BOX (box2), has_frame_check, FALSE, TRUE, 0);
3786       g_signal_connect (has_frame_check, "toggled",
3787                         G_CALLBACK (entry_toggle_frame), entry);
3788       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (has_frame_check), TRUE);
3789
3790       progress_check = gtk_check_button_new_with_label("Show Progress");
3791       gtk_box_pack_start (GTK_BOX (box2), progress_check, FALSE, TRUE, 0);
3792       g_signal_connect (progress_check, "toggled",
3793                         G_CALLBACK (entry_toggle_progress), entry);
3794
3795       progress_check = gtk_check_button_new_with_label("Pulse Progress");
3796       gtk_box_pack_start (GTK_BOX (box2), progress_check, FALSE, TRUE, 0);
3797       g_signal_connect (progress_check, "toggled",
3798                         G_CALLBACK (entry_toggle_pulse), entry);
3799
3800       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
3801       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
3802
3803       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
3804       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3805       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
3806
3807       button = gtk_button_new_with_label ("close");
3808       g_signal_connect_swapped (button, "clicked",
3809                                 G_CALLBACK (gtk_widget_destroy),
3810                                 window);
3811       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3812       gtk_widget_set_can_default (button, TRUE);
3813       gtk_widget_grab_default (button);
3814     }
3815
3816   if (!gtk_widget_get_visible (window))
3817     gtk_widget_show_all (window);
3818   else
3819     gtk_widget_destroy (window);
3820 }
3821
3822 static void
3823 create_expander (GtkWidget *widget)
3824 {
3825   GtkWidget *box1;
3826   GtkWidget *expander;
3827   GtkWidget *hidden;
3828   static GtkWidget *window = NULL;
3829
3830   if (!window)
3831     {
3832       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3833       gtk_window_set_screen (GTK_WINDOW (window),
3834                              gtk_widget_get_screen (widget));
3835       
3836       g_signal_connect (window, "destroy",
3837                         G_CALLBACK (gtk_widget_destroyed),
3838                         &window);
3839       
3840       gtk_window_set_title (GTK_WINDOW (window), "expander");
3841       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
3842       
3843       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
3844       gtk_container_add (GTK_CONTAINER (window), box1);
3845       
3846       expander = gtk_expander_new ("The Hidden");
3847       
3848       gtk_box_pack_start (GTK_BOX (box1), expander, TRUE, TRUE, 0);
3849       
3850       hidden = gtk_label_new ("Revealed!");
3851       
3852       gtk_container_add (GTK_CONTAINER (expander), hidden);
3853     }
3854   
3855   if (!gtk_widget_get_visible (window))
3856     gtk_widget_show_all (window);
3857   else
3858     gtk_widget_destroy (window);
3859 }
3860
3861
3862 /* GtkEventBox */
3863
3864
3865 static void
3866 event_box_label_pressed (GtkWidget        *widget,
3867                          GdkEventButton   *event,
3868                          gpointer user_data)
3869 {
3870   g_print ("clicked on event box\n");
3871 }
3872
3873 static void
3874 event_box_button_clicked (GtkWidget *widget,
3875                           GtkWidget *button,
3876                           gpointer user_data)
3877 {
3878   g_print ("pushed button\n");
3879 }
3880
3881 static void
3882 event_box_toggle_visible_window (GtkWidget *checkbutton,
3883                                  GtkEventBox *event_box)
3884 {
3885   gtk_event_box_set_visible_window (event_box,
3886                                     gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbutton)));
3887 }
3888
3889 static void
3890 event_box_toggle_above_child (GtkWidget *checkbutton,
3891                               GtkEventBox *event_box)
3892 {
3893   gtk_event_box_set_above_child (event_box,
3894                                  gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbutton)));
3895 }
3896
3897 static void
3898 create_event_box (GtkWidget *widget)
3899 {
3900   static GtkWidget *window = NULL;
3901   GtkWidget *box1;
3902   GtkWidget *box2;
3903   GtkWidget *hbox;
3904   GtkWidget *vbox;
3905   GtkWidget *button;
3906   GtkWidget *separator;
3907   GtkWidget *event_box;
3908   GtkWidget *label;
3909   GtkWidget *visible_window_check;
3910   GtkWidget *above_child_check;
3911   GdkRGBA color;
3912
3913   if (!window)
3914     {
3915       color.red = 0;
3916       color.blue = 1;
3917       color.green = 0;
3918       color.alpha = 1;
3919       
3920       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3921       gtk_window_set_screen (GTK_WINDOW (window),
3922                              gtk_widget_get_screen (widget));
3923
3924       g_signal_connect (window, "destroy",
3925                         G_CALLBACK (gtk_widget_destroyed),
3926                         &window);
3927
3928       gtk_window_set_title (GTK_WINDOW (window), "event box");
3929       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
3930
3931       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
3932       gtk_container_add (GTK_CONTAINER (window), box1);
3933       gtk_widget_override_background_color (window, 0, &color);
3934
3935       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
3936       gtk_box_pack_start (GTK_BOX (box1), hbox, TRUE, FALSE, 0);
3937       
3938       event_box = gtk_event_box_new ();
3939       gtk_box_pack_start (GTK_BOX (hbox), event_box, TRUE, FALSE, 0);
3940
3941       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
3942       gtk_container_add (GTK_CONTAINER (event_box), vbox);
3943       g_signal_connect (event_box, "button_press_event",
3944                         G_CALLBACK (event_box_label_pressed),
3945                         NULL);
3946       
3947       label = gtk_label_new ("Click on this label");
3948       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, FALSE, 0);
3949
3950       button = gtk_button_new_with_label ("button in eventbox");
3951       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, FALSE, 0);
3952       g_signal_connect (button, "clicked",
3953                         G_CALLBACK (event_box_button_clicked),
3954                         NULL);
3955       
3956
3957       visible_window_check = gtk_check_button_new_with_label("Visible Window");
3958       gtk_box_pack_start (GTK_BOX (box1), visible_window_check, FALSE, TRUE, 0);
3959       g_signal_connect (visible_window_check, "toggled",
3960                         G_CALLBACK (event_box_toggle_visible_window), event_box);
3961       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (visible_window_check), FALSE);
3962       
3963       above_child_check = gtk_check_button_new_with_label("Above Child");
3964       gtk_box_pack_start (GTK_BOX (box1), above_child_check, FALSE, TRUE, 0);
3965       g_signal_connect (above_child_check, "toggled",
3966                         G_CALLBACK (event_box_toggle_above_child), event_box);
3967       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (above_child_check), FALSE);
3968       
3969       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
3970       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
3971
3972       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
3973       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3974       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
3975
3976       button = gtk_button_new_with_label ("close");
3977       g_signal_connect_swapped (button, "clicked",
3978                                 G_CALLBACK (gtk_widget_destroy),
3979                                 window);
3980       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3981       gtk_widget_set_can_default (button, TRUE);
3982       gtk_widget_grab_default (button);
3983     }
3984
3985   if (!gtk_widget_get_visible (window))
3986     gtk_widget_show_all (window);
3987   else
3988     gtk_widget_destroy (window);
3989 }
3990
3991
3992 /*
3993  * GtkSizeGroup
3994  */
3995
3996 #define SIZE_GROUP_INITIAL_SIZE 50
3997
3998 static void
3999 size_group_hsize_changed (GtkSpinButton *spin_button,
4000                           GtkWidget     *button)
4001 {
4002   gtk_widget_set_size_request (gtk_bin_get_child (GTK_BIN (button)),
4003                                gtk_spin_button_get_value_as_int (spin_button),
4004                                -1);
4005 }
4006
4007 static void
4008 size_group_vsize_changed (GtkSpinButton *spin_button,
4009                           GtkWidget     *button)
4010 {
4011   gtk_widget_set_size_request (gtk_bin_get_child (GTK_BIN (button)),
4012                                -1,
4013                                gtk_spin_button_get_value_as_int (spin_button));
4014 }
4015
4016 static GtkWidget *
4017 create_size_group_window (GdkScreen    *screen,
4018                           GtkSizeGroup *master_size_group)
4019 {
4020   GtkWidget *content_area;
4021   GtkWidget *window;
4022   GtkWidget *grid;
4023   GtkWidget *main_button;
4024   GtkWidget *button;
4025   GtkWidget *spin_button;
4026   GtkWidget *hbox;
4027   GtkSizeGroup *hgroup1;
4028   GtkSizeGroup *hgroup2;
4029   GtkSizeGroup *vgroup1;
4030   GtkSizeGroup *vgroup2;
4031
4032   window = gtk_dialog_new_with_buttons ("GtkSizeGroup",
4033                                         NULL, 0,
4034                                         GTK_STOCK_CLOSE,
4035                                         GTK_RESPONSE_NONE,
4036                                         NULL);
4037
4038   gtk_window_set_screen (GTK_WINDOW (window), screen);
4039
4040   gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
4041
4042   g_signal_connect (window, "response",
4043                     G_CALLBACK (gtk_widget_destroy),
4044                     NULL);
4045
4046   content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
4047
4048   grid = gtk_grid_new ();
4049   gtk_box_pack_start (GTK_BOX (content_area), grid, TRUE, TRUE, 0);
4050
4051   gtk_grid_set_row_spacing (GTK_GRID (grid), 5);
4052   gtk_grid_set_column_spacing (GTK_GRID (grid), 5);
4053   gtk_container_set_border_width (GTK_CONTAINER (grid), 5);
4054   gtk_widget_set_size_request (grid, 250, 250);
4055
4056   hgroup1 = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4057   hgroup2 = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4058   vgroup1 = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
4059   vgroup2 = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
4060
4061   main_button = gtk_button_new_with_label ("X");
4062   gtk_widget_set_hexpand (main_button, TRUE);
4063   gtk_widget_set_vexpand (main_button, TRUE);
4064   gtk_widget_set_halign (main_button, GTK_ALIGN_CENTER);
4065   gtk_widget_set_valign (main_button, GTK_ALIGN_CENTER);
4066   gtk_grid_attach (GTK_GRID (grid), main_button, 0, 0, 1, 1);
4067   
4068   gtk_size_group_add_widget (master_size_group, main_button);
4069   gtk_size_group_add_widget (hgroup1, main_button);
4070   gtk_size_group_add_widget (vgroup1, main_button);
4071   gtk_widget_set_size_request (gtk_bin_get_child (GTK_BIN (main_button)),
4072                                SIZE_GROUP_INITIAL_SIZE,
4073                                SIZE_GROUP_INITIAL_SIZE);
4074
4075   button = gtk_button_new ();
4076   gtk_widget_set_hexpand (button, TRUE);
4077   gtk_widget_set_vexpand (button, TRUE);
4078   gtk_widget_set_halign (button, GTK_ALIGN_CENTER);
4079   gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
4080   gtk_grid_attach (GTK_GRID (grid), button, 1, 0, 1, 1);
4081
4082   gtk_size_group_add_widget (vgroup1, button);
4083   gtk_size_group_add_widget (vgroup2, button);
4084
4085   button = gtk_button_new ();
4086   gtk_widget_set_hexpand (button, TRUE);
4087   gtk_widget_set_vexpand (button, TRUE);
4088   gtk_widget_set_halign (button, GTK_ALIGN_CENTER);
4089   gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
4090   gtk_grid_attach (GTK_GRID (grid), button, 0, 1, 1, 1);
4091
4092   gtk_size_group_add_widget (hgroup1, button);
4093   gtk_size_group_add_widget (hgroup2, button);
4094
4095   button = gtk_button_new ();
4096   gtk_widget_set_hexpand (button, TRUE);
4097   gtk_widget_set_vexpand (button, TRUE);
4098   gtk_widget_set_halign (button, GTK_ALIGN_CENTER);
4099   gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
4100   gtk_grid_attach (GTK_GRID (grid), button, 1, 1, 1, 1);
4101
4102   gtk_size_group_add_widget (hgroup2, button);
4103   gtk_size_group_add_widget (vgroup2, button);
4104
4105   g_object_unref (hgroup1);
4106   g_object_unref (hgroup2);
4107   g_object_unref (vgroup1);
4108   g_object_unref (vgroup2);
4109   
4110   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
4111   gtk_box_pack_start (GTK_BOX (content_area), hbox, FALSE, FALSE, 0);
4112   
4113   spin_button = gtk_spin_button_new_with_range (1, 100, 1);
4114   gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_button), SIZE_GROUP_INITIAL_SIZE);
4115   gtk_box_pack_start (GTK_BOX (hbox), spin_button, TRUE, TRUE, 0);
4116   g_signal_connect (spin_button, "value_changed",
4117                     G_CALLBACK (size_group_hsize_changed), main_button);
4118
4119   spin_button = gtk_spin_button_new_with_range (1, 100, 1);
4120   gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_button), SIZE_GROUP_INITIAL_SIZE);
4121   gtk_box_pack_start (GTK_BOX (hbox), spin_button, TRUE, TRUE, 0);
4122   g_signal_connect (spin_button, "value_changed",
4123                     G_CALLBACK (size_group_vsize_changed), main_button);
4124
4125   return window;
4126 }
4127
4128 static void
4129 create_size_groups (GtkWidget *widget)
4130 {
4131   static GtkWidget *window1 = NULL;
4132   static GtkWidget *window2 = NULL;
4133   static GtkSizeGroup *master_size_group;
4134
4135   if (!master_size_group)
4136     master_size_group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
4137
4138   if (!window1)
4139     {
4140       window1 = create_size_group_window (gtk_widget_get_screen (widget),
4141                                           master_size_group);
4142
4143       g_signal_connect (window1, "destroy",
4144                         G_CALLBACK (gtk_widget_destroyed),
4145                         &window1);
4146     }
4147
4148   if (!window2)
4149     {
4150       window2 = create_size_group_window (gtk_widget_get_screen (widget),
4151                                           master_size_group);
4152
4153       g_signal_connect (window2, "destroy",
4154                         G_CALLBACK (gtk_widget_destroyed),
4155                         &window2);
4156     }
4157
4158   if (gtk_widget_get_visible (window1) && gtk_widget_get_visible (window2))
4159     {
4160       gtk_widget_destroy (window1);
4161       gtk_widget_destroy (window2);
4162     }
4163   else
4164     {
4165       if (!gtk_widget_get_visible (window1))
4166         gtk_widget_show_all (window1);
4167       if (!gtk_widget_get_visible (window2))
4168         gtk_widget_show_all (window2);
4169     }
4170 }
4171
4172 /*
4173  * GtkSpinButton
4174  */
4175
4176 static GtkWidget *spinner1;
4177
4178 static void
4179 toggle_snap (GtkWidget *widget, GtkSpinButton *spin)
4180 {
4181   gtk_spin_button_set_snap_to_ticks (spin,
4182                                      gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)));
4183 }
4184
4185 static void
4186 toggle_numeric (GtkWidget *widget, GtkSpinButton *spin)
4187 {
4188   gtk_spin_button_set_numeric (spin,
4189                                gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)));
4190 }
4191
4192 static void
4193 change_digits (GtkWidget *widget, GtkSpinButton *spin)
4194 {
4195   gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinner1),
4196                               gtk_spin_button_get_value_as_int (spin));
4197 }
4198
4199 static void
4200 get_value (GtkWidget *widget, gpointer data)
4201 {
4202   gchar buf[32];
4203   GtkLabel *label;
4204   GtkSpinButton *spin;
4205
4206   spin = GTK_SPIN_BUTTON (spinner1);
4207   label = GTK_LABEL (g_object_get_data (G_OBJECT (widget), "user_data"));
4208   if (GPOINTER_TO_INT (data) == 1)
4209     sprintf (buf, "%d", gtk_spin_button_get_value_as_int (spin));
4210   else
4211     sprintf (buf, "%0.*f",
4212              gtk_spin_button_get_digits (spin),
4213              gtk_spin_button_get_value (spin));
4214
4215   gtk_label_set_text (label, buf);
4216 }
4217
4218 static void
4219 get_spin_value (GtkWidget *widget, gpointer data)
4220 {
4221   gchar *buffer;
4222   GtkLabel *label;
4223   GtkSpinButton *spin;
4224
4225   spin = GTK_SPIN_BUTTON (widget);
4226   label = GTK_LABEL (data);
4227
4228   buffer = g_strdup_printf ("%0.*f",
4229                             gtk_spin_button_get_digits (spin),
4230                             gtk_spin_button_get_value (spin));
4231   gtk_label_set_text (label, buffer);
4232
4233   g_free (buffer);
4234 }
4235
4236 static gint
4237 spin_button_time_output_func (GtkSpinButton *spin_button)
4238 {
4239   GtkAdjustment *adjustment;
4240   static gchar buf[6];
4241   gdouble hours;
4242   gdouble minutes;
4243
4244   adjustment = gtk_spin_button_get_adjustment (spin_button);
4245   hours = gtk_adjustment_get_value (adjustment) / 60.0;
4246   minutes = (fabs(floor (hours) - hours) < 1e-5) ? 0.0 : 30;
4247   sprintf (buf, "%02.0f:%02.0f", floor (hours), minutes);
4248   if (strcmp (buf, gtk_entry_get_text (GTK_ENTRY (spin_button))))
4249     gtk_entry_set_text (GTK_ENTRY (spin_button), buf);
4250   return TRUE;
4251 }
4252
4253 static gint
4254 spin_button_month_input_func (GtkSpinButton *spin_button,
4255                               gdouble       *new_val)
4256 {
4257   gint i;
4258   static gchar *month[12] = { "January", "February", "March", "April",
4259                               "May", "June", "July", "August",
4260                               "September", "October", "November", "December" };
4261   gchar *tmp1, *tmp2;
4262   gboolean found = FALSE;
4263
4264   for (i = 1; i <= 12; i++)
4265     {
4266       tmp1 = g_ascii_strup (month[i - 1], -1);
4267       tmp2 = g_ascii_strup (gtk_entry_get_text (GTK_ENTRY (spin_button)), -1);
4268       if (strstr (tmp1, tmp2) == tmp1)
4269         found = TRUE;
4270       g_free (tmp1);
4271       g_free (tmp2);
4272       if (found)
4273         break;
4274     }
4275   if (!found)
4276     {
4277       *new_val = 0.0;
4278       return GTK_INPUT_ERROR;
4279     }
4280   *new_val = (gdouble) i;
4281   return TRUE;
4282 }
4283
4284 static gint
4285 spin_button_month_output_func (GtkSpinButton *spin_button)
4286 {
4287   GtkAdjustment *adjustment;
4288   gdouble value;
4289   gint i;
4290   static gchar *month[12] = { "January", "February", "March", "April",
4291                               "May", "June", "July", "August", "September",
4292                               "October", "November", "December" };
4293
4294   adjustment = gtk_spin_button_get_adjustment (spin_button);
4295   value = gtk_adjustment_get_value (adjustment);
4296   for (i = 1; i <= 12; i++)
4297     if (fabs (value - (double)i) < 1e-5)
4298       {
4299         if (strcmp (month[i-1], gtk_entry_get_text (GTK_ENTRY (spin_button))))
4300           gtk_entry_set_text (GTK_ENTRY (spin_button), month[i-1]);
4301       }
4302   return TRUE;
4303 }
4304
4305 static gint
4306 spin_button_hex_input_func (GtkSpinButton *spin_button,
4307                             gdouble       *new_val)
4308 {
4309   const gchar *buf;
4310   gchar *err;
4311   gdouble res;
4312
4313   buf = gtk_entry_get_text (GTK_ENTRY (spin_button));
4314   res = strtol(buf, &err, 16);
4315   *new_val = res;
4316   if (*err)
4317     return GTK_INPUT_ERROR;
4318   else
4319     return TRUE;
4320 }
4321
4322 static gint
4323 spin_button_hex_output_func (GtkSpinButton *spin_button)
4324 {
4325   GtkAdjustment *adjustment;
4326   static gchar buf[7];
4327   gint val;
4328
4329   adjustment = gtk_spin_button_get_adjustment (spin_button);
4330   val = (gint) gtk_adjustment_get_value (adjustment);
4331   if (fabs (val) < 1e-5)
4332     sprintf (buf, "0x00");
4333   else
4334     sprintf (buf, "0x%.2X", val);
4335   if (strcmp (buf, gtk_entry_get_text (GTK_ENTRY (spin_button))))
4336     gtk_entry_set_text (GTK_ENTRY (spin_button), buf);
4337   return TRUE;
4338 }
4339
4340 static void
4341 create_spins (GtkWidget *widget)
4342 {
4343   static GtkWidget *window = NULL;
4344   GtkWidget *frame;
4345   GtkWidget *hbox;
4346   GtkWidget *main_vbox;
4347   GtkWidget *vbox;
4348   GtkWidget *vbox2;
4349   GtkWidget *spinner2;
4350   GtkWidget *spinner;
4351   GtkWidget *button;
4352   GtkWidget *label;
4353   GtkWidget *val_label;
4354   GtkAdjustment *adjustment;
4355
4356   if (!window)
4357     {
4358       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4359       gtk_window_set_screen (GTK_WINDOW (window),
4360                              gtk_widget_get_screen (widget));
4361       
4362       g_signal_connect (window, "destroy",
4363                         G_CALLBACK (gtk_widget_destroyed),
4364                         &window);
4365       
4366       gtk_window_set_title (GTK_WINDOW (window), "GtkSpinButton");
4367       
4368       main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
4369       gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 10);
4370       gtk_container_add (GTK_CONTAINER (window), main_vbox);
4371       
4372       frame = gtk_frame_new ("Not accelerated");
4373       gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
4374       
4375       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
4376       gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
4377       gtk_container_add (GTK_CONTAINER (frame), vbox);
4378       
4379       /* Time, month, hex spinners */
4380       
4381       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
4382       gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 5);
4383       
4384       vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
4385       gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
4386       
4387       label = gtk_label_new ("Time :");
4388       gtk_widget_set_halign (label, GTK_ALIGN_START);
4389       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
4390       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
4391
4392       adjustment = gtk_adjustment_new (0, 0, 1410, 30, 60, 0);
4393       spinner = gtk_spin_button_new (adjustment, 0, 0);
4394       gtk_editable_set_editable (GTK_EDITABLE (spinner), FALSE);
4395       g_signal_connect (spinner,
4396                         "output",
4397                         G_CALLBACK (spin_button_time_output_func),
4398                         NULL);
4399       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
4400       gtk_entry_set_width_chars (GTK_ENTRY (spinner), 5);
4401       gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
4402
4403       vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
4404       gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
4405       
4406       label = gtk_label_new ("Month :");
4407       gtk_widget_set_halign (label, GTK_ALIGN_START);
4408       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
4409       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
4410
4411       adjustment = gtk_adjustment_new (1.0, 1.0, 12.0, 1.0,
4412                                                   5.0, 0.0);
4413       spinner = gtk_spin_button_new (adjustment, 0, 0);
4414       gtk_spin_button_set_update_policy (GTK_SPIN_BUTTON (spinner),
4415                                          GTK_UPDATE_IF_VALID);
4416       g_signal_connect (spinner,
4417                         "input",
4418                         G_CALLBACK (spin_button_month_input_func),
4419                         NULL);
4420       g_signal_connect (spinner,
4421                         "output",
4422                         G_CALLBACK (spin_button_month_output_func),
4423                         NULL);
4424       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
4425       gtk_entry_set_width_chars (GTK_ENTRY (spinner), 9);
4426       gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
4427       
4428       vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
4429       gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
4430
4431       label = gtk_label_new ("Hex :");
4432       gtk_widget_set_halign (label, GTK_ALIGN_START);
4433       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
4434       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
4435
4436       adjustment = gtk_adjustment_new (0, 0, 255, 1, 16, 0);
4437       spinner = gtk_spin_button_new (adjustment, 0, 0);
4438       gtk_editable_set_editable (GTK_EDITABLE (spinner), TRUE);
4439       g_signal_connect (spinner,
4440                         "input",
4441                         G_CALLBACK (spin_button_hex_input_func),
4442                         NULL);
4443       g_signal_connect (spinner,
4444                         "output",
4445                         G_CALLBACK (spin_button_hex_output_func),
4446                         NULL);
4447       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
4448       gtk_entry_set_width_chars (GTK_ENTRY (spinner), 4);
4449       gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
4450
4451       frame = gtk_frame_new ("Accelerated");
4452       gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
4453   
4454       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
4455       gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
4456       gtk_container_add (GTK_CONTAINER (frame), vbox);
4457       
4458       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
4459       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
4460       
4461       vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
4462       gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 5);
4463       
4464       label = gtk_label_new ("Value :");
4465       gtk_widget_set_halign (label, GTK_ALIGN_START);
4466       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
4467       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
4468
4469       adjustment = gtk_adjustment_new (0.0, -10000.0, 10000.0,
4470                                                   0.5, 100.0, 0.0);
4471       spinner1 = gtk_spin_button_new (adjustment, 1.0, 2);
4472       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner1), TRUE);
4473       gtk_box_pack_start (GTK_BOX (vbox2), spinner1, FALSE, TRUE, 0);
4474
4475       vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
4476       gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 5);
4477
4478       label = gtk_label_new ("Digits :");
4479       gtk_widget_set_halign (label, GTK_ALIGN_START);
4480       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
4481       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
4482
4483       adjustment = gtk_adjustment_new (2, 1, 15, 1, 1, 0);
4484       spinner2 = gtk_spin_button_new (adjustment, 0.0, 0);
4485       g_signal_connect (adjustment, "value_changed",
4486                         G_CALLBACK (change_digits),
4487                         spinner2);
4488       gtk_box_pack_start (GTK_BOX (vbox2), spinner2, FALSE, TRUE, 0);
4489
4490       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
4491       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 5);
4492
4493       button = gtk_check_button_new_with_label ("Snap to 0.5-ticks");
4494       g_signal_connect (button, "clicked",
4495                         G_CALLBACK (toggle_snap),
4496                         spinner1);
4497       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
4498       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
4499
4500       button = gtk_check_button_new_with_label ("Numeric only input mode");
4501       g_signal_connect (button, "clicked",
4502                         G_CALLBACK (toggle_numeric),
4503                         spinner1);
4504       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
4505       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
4506
4507       val_label = gtk_label_new ("");
4508
4509       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
4510       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
4511
4512       button = gtk_button_new_with_label ("Value as Int");
4513       g_object_set_data (G_OBJECT (button), "user_data", val_label);
4514       g_signal_connect (button, "clicked",
4515                         G_CALLBACK (get_value),
4516                         GINT_TO_POINTER (1));
4517       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
4518
4519       button = gtk_button_new_with_label ("Value as Float");
4520       g_object_set_data (G_OBJECT (button), "user_data", val_label);
4521       g_signal_connect (button, "clicked",
4522                         G_CALLBACK (get_value),
4523                         GINT_TO_POINTER (2));
4524       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
4525
4526       gtk_box_pack_start (GTK_BOX (vbox), val_label, TRUE, TRUE, 0);
4527       gtk_label_set_text (GTK_LABEL (val_label), "0");
4528
4529       frame = gtk_frame_new ("Using Convenience Constructor");
4530       gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
4531   
4532       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
4533       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
4534       gtk_container_add (GTK_CONTAINER (frame), hbox);
4535       
4536       val_label = gtk_label_new ("0.0");
4537
4538       spinner = gtk_spin_button_new_with_range (0.0, 10.0, 0.009);
4539       gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinner), 0.0);
4540       g_signal_connect (spinner, "value_changed",
4541                         G_CALLBACK (get_spin_value), val_label);
4542       gtk_box_pack_start (GTK_BOX (hbox), spinner, TRUE, TRUE, 5);
4543       gtk_box_pack_start (GTK_BOX (hbox), val_label, TRUE, TRUE, 5);
4544
4545       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
4546       gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
4547   
4548       button = gtk_button_new_with_label ("Close");
4549       g_signal_connect_swapped (button, "clicked",
4550                                 G_CALLBACK (gtk_widget_destroy),
4551                                 window);
4552       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
4553     }
4554
4555   if (!gtk_widget_get_visible (window))
4556     gtk_widget_show_all (window);
4557   else
4558     gtk_widget_destroy (window);
4559 }
4560
4561
4562 /*
4563  * Cursors
4564  */
4565
4566 static gint
4567 cursor_draw (GtkWidget *widget,
4568              cairo_t   *cr,
4569              gpointer   user_data)
4570 {
4571   int width, height;
4572   GtkStyleContext *context;
4573   GdkRGBA bg;
4574
4575   width = gtk_widget_get_allocated_width (widget);
4576   height = gtk_widget_get_allocated_height (widget);
4577
4578   cairo_set_source_rgb (cr, 1, 1, 1);
4579   cairo_rectangle (cr, 0, 0, width, height / 2);
4580   cairo_fill (cr);
4581
4582   cairo_set_source_rgb (cr, 0, 0, 0);
4583   cairo_rectangle (cr, 0, height / 2, width, height / 2);
4584   cairo_fill (cr);
4585
4586   context = gtk_widget_get_style_context (widget);
4587   gtk_style_context_get_background_color (context, GTK_STATE_FLAG_NORMAL, &bg);
4588   gdk_cairo_set_source_rgba (cr, &bg);
4589   cairo_rectangle (cr, width / 3, height / 3, width / 3, height / 3);
4590   cairo_fill (cr);
4591
4592   return TRUE;
4593 }
4594
4595 static void
4596 set_cursor (GtkWidget *spinner,
4597             GtkWidget *widget)
4598 {
4599   guint c;
4600   GdkCursor *cursor;
4601   GtkWidget *label;
4602   GEnumClass *class;
4603   GEnumValue *vals;
4604
4605   c = CLAMP (gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spinner)), 0, 152);
4606   c &= 0xfe;
4607
4608   label = g_object_get_data (G_OBJECT (spinner), "user_data");
4609   
4610   class = g_type_class_ref (GDK_TYPE_CURSOR_TYPE);
4611   vals = class->values;
4612
4613   while (vals && vals->value != c)
4614     vals++;
4615   if (vals)
4616     gtk_label_set_text (GTK_LABEL (label), vals->value_nick);
4617   else
4618     gtk_label_set_text (GTK_LABEL (label), "<unknown>");
4619
4620   g_type_class_unref (class);
4621
4622   cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), c);
4623   gdk_window_set_cursor (gtk_widget_get_window (widget),
4624                          cursor);
4625   g_object_unref (cursor);
4626 }
4627
4628 static gint
4629 cursor_event (GtkWidget          *widget,
4630               GdkEvent           *event,
4631               GtkSpinButton      *spinner)
4632 {
4633   if ((event->type == GDK_BUTTON_PRESS) &&
4634       ((event->button.button == 1) ||
4635        (event->button.button == 3)))
4636     {
4637       gtk_spin_button_spin (spinner, event->button.button == 1 ?
4638                             GTK_SPIN_STEP_FORWARD : GTK_SPIN_STEP_BACKWARD, 0);
4639       return TRUE;
4640     }
4641
4642   return FALSE;
4643 }
4644
4645 #ifdef GDK_WINDOWING_X11
4646 #include "x11/gdkx.h"
4647
4648 static void
4649 change_cursor_theme (GtkWidget *widget,
4650                      gpointer   data)
4651 {
4652   const gchar *theme;
4653   gint size;
4654   GList *children;
4655
4656   children = gtk_container_get_children (GTK_CONTAINER (data));
4657
4658   theme = gtk_entry_get_text (GTK_ENTRY (children->next->data));
4659   size = (gint) gtk_spin_button_get_value (GTK_SPIN_BUTTON (children->next->next->data));
4660
4661   g_list_free (children);
4662
4663   gdk_x11_display_set_cursor_theme (gtk_widget_get_display (widget),
4664                                     theme, size);
4665 }
4666 #endif
4667
4668
4669 static void
4670 create_cursors (GtkWidget *widget)
4671 {
4672   static GtkWidget *window = NULL;
4673   GtkWidget *frame;
4674   GtkWidget *hbox;
4675   GtkWidget *main_vbox;
4676   GtkWidget *vbox;
4677   GtkWidget *darea;
4678   GtkWidget *spinner;
4679   GtkWidget *button;
4680   GtkWidget *label;
4681   GtkWidget *any;
4682   GtkAdjustment *adjustment;
4683   GtkWidget *entry;
4684   GtkWidget *size;  
4685
4686   if (!window)
4687     {
4688       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4689       gtk_window_set_screen (GTK_WINDOW (window), 
4690                              gtk_widget_get_screen (widget));
4691       
4692       g_signal_connect (window, "destroy",
4693                         G_CALLBACK (gtk_widget_destroyed),
4694                         &window);
4695       
4696       gtk_window_set_title (GTK_WINDOW (window), "Cursors");
4697       
4698       main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
4699       gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 0);
4700       gtk_container_add (GTK_CONTAINER (window), main_vbox);
4701
4702       vbox =
4703         g_object_new (GTK_TYPE_BOX,
4704                       "orientation", GTK_ORIENTATION_VERTICAL,
4705                         "GtkBox::homogeneous", FALSE,
4706                         "GtkBox::spacing", 5,
4707                         "GtkContainer::border_width", 10,
4708                         "GtkWidget::parent", main_vbox,
4709                         "GtkWidget::visible", TRUE,
4710                         NULL);
4711
4712 #ifdef GDK_WINDOWING_X11
4713       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
4714       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
4715       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
4716
4717       label = gtk_label_new ("Cursor Theme : ");
4718       gtk_widget_set_halign (label, GTK_ALIGN_START);
4719       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
4720       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
4721
4722       entry = gtk_entry_new ();
4723       gtk_entry_set_text (GTK_ENTRY (entry), "default");
4724       gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, TRUE, 0);
4725
4726       size = gtk_spin_button_new_with_range (1.0, 64.0, 1.0);
4727       gtk_spin_button_set_value (GTK_SPIN_BUTTON (size), 24.0);
4728       gtk_box_pack_start (GTK_BOX (hbox), size, TRUE, TRUE, 0);
4729       
4730       g_signal_connect (entry, "changed", 
4731                         G_CALLBACK (change_cursor_theme), hbox);
4732       g_signal_connect (size, "changed", 
4733                         G_CALLBACK (change_cursor_theme), hbox);
4734 #endif
4735
4736       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
4737       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
4738       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
4739
4740       label = gtk_label_new ("Cursor Value : ");
4741       gtk_widget_set_halign (label, GTK_ALIGN_START);
4742       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
4743       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
4744
4745       adjustment = gtk_adjustment_new (0,
4746                                 0, 152,
4747                                 2,
4748                                 10, 0);
4749       spinner = gtk_spin_button_new (adjustment, 0, 0);
4750       gtk_box_pack_start (GTK_BOX (hbox), spinner, TRUE, TRUE, 0);
4751
4752       frame =
4753         g_object_new (gtk_frame_get_type (),
4754                         "GtkFrame::label_xalign", 0.5,
4755                         "GtkFrame::label", "Cursor Area",
4756                         "GtkContainer::border_width", 10,
4757                         "GtkWidget::parent", vbox,
4758                         "GtkWidget::visible", TRUE,
4759                         NULL);
4760
4761       darea = gtk_drawing_area_new ();
4762       gtk_widget_set_size_request (darea, 80, 80);
4763       gtk_container_add (GTK_CONTAINER (frame), darea);
4764       g_signal_connect (darea,
4765                         "draw",
4766                         G_CALLBACK (cursor_draw),
4767                         NULL);
4768       gtk_widget_set_events (darea, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
4769       g_signal_connect (darea,
4770                         "button_press_event",
4771                         G_CALLBACK (cursor_event),
4772                         spinner);
4773       gtk_widget_show (darea);
4774
4775       g_signal_connect (spinner, "changed",
4776                         G_CALLBACK (set_cursor),
4777                         darea);
4778
4779       label = g_object_new (GTK_TYPE_LABEL,
4780                               "visible", TRUE,
4781                               "label", "XXX",
4782                               "parent", vbox,
4783                               NULL);
4784       gtk_container_child_set (GTK_CONTAINER (vbox), label,
4785                                "expand", FALSE,
4786                                NULL);
4787       g_object_set_data (G_OBJECT (spinner), "user_data", label);
4788
4789       any = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
4790       gtk_box_pack_start (GTK_BOX (main_vbox), any, FALSE, TRUE, 0);
4791   
4792       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
4793       gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
4794       gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
4795
4796       button = gtk_button_new_with_label ("Close");
4797       g_signal_connect_swapped (button, "clicked",
4798                                 G_CALLBACK (gtk_widget_destroy),
4799                                 window);
4800       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
4801
4802       gtk_widget_show_all (window);
4803
4804       set_cursor (spinner, darea);
4805     }
4806   else
4807     gtk_widget_destroy (window);
4808 }
4809
4810 /*
4811  * GtkColorSelection
4812  */
4813
4814 void
4815 color_selection_ok (GtkWidget               *w,
4816                     GtkColorSelectionDialog *cs)
4817 {
4818   GtkWidget *colorsel;
4819   GdkColor color;
4820
4821   colorsel = gtk_color_selection_dialog_get_color_selection (cs);
4822
4823   gtk_color_selection_get_current_color (GTK_COLOR_SELECTION (colorsel), &color);
4824   gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (colorsel), &color);
4825 }
4826
4827 void
4828 color_selection_changed (GtkWidget *w,
4829                          GtkColorSelectionDialog *cs)
4830 {
4831   GtkWidget *colorsel;
4832   GdkColor color;
4833
4834   colorsel = gtk_color_selection_dialog_get_color_selection (cs);
4835   gtk_color_selection_get_current_color (GTK_COLOR_SELECTION (colorsel), &color);
4836   gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (colorsel), &color);
4837 }
4838
4839 #if 0 /* unused */
4840 static void
4841 opacity_toggled_cb (GtkWidget *w,
4842                     GtkColorSelectionDialog *cs)
4843 {
4844   GtkColorSelection *colorsel;
4845
4846   colorsel = GTK_COLOR_SELECTION (cs->colorsel);
4847   gtk_color_selection_set_has_opacity_control (colorsel,
4848                                                gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
4849 }
4850
4851 static void
4852 palette_toggled_cb (GtkWidget *w,
4853                     GtkColorSelectionDialog *cs)
4854 {
4855   GtkColorSelection *colorsel;
4856
4857   colorsel = GTK_COLOR_SELECTION (cs->colorsel);
4858   gtk_color_selection_set_has_palette (colorsel,
4859                                        gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
4860 }
4861 #endif
4862
4863 void
4864 create_color_selection (GtkWidget *widget)
4865 {
4866   static GtkWidget *window = NULL;
4867
4868   if (!window)
4869     {
4870       GtkWidget *picker;
4871       GtkWidget *hbox;
4872       GtkWidget *label;
4873       GtkWidget *button;
4874       
4875       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4876       gtk_window_set_screen (GTK_WINDOW (window), 
4877                              gtk_widget_get_screen (widget));
4878                              
4879       g_signal_connect (window, "destroy",
4880                         G_CALLBACK (gtk_widget_destroyed),
4881                         &window);
4882
4883       gtk_window_set_title (GTK_WINDOW (window), "GtkColorButton");
4884       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
4885
4886       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
4887       gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
4888       gtk_container_add (GTK_CONTAINER (window), hbox);
4889       
4890       label = gtk_label_new ("Pick a color");
4891       gtk_container_add (GTK_CONTAINER (hbox), label);
4892
4893       picker = gtk_color_button_new ();
4894       gtk_color_button_set_use_alpha (GTK_COLOR_BUTTON (picker), TRUE);
4895       gtk_container_add (GTK_CONTAINER (hbox), picker);
4896
4897       button = gtk_button_new_with_mnemonic ("_Props");
4898       gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
4899       g_signal_connect (button, "clicked",
4900                         G_CALLBACK (props_clicked),
4901                         picker);
4902     }
4903
4904   if (!gtk_widget_get_visible (window))
4905     gtk_widget_show_all (window);
4906   else
4907     gtk_widget_destroy (window);
4908 }
4909
4910 void
4911 flipping_toggled_cb (GtkWidget *widget, gpointer data)
4912 {
4913   int state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
4914   int new_direction = state ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
4915
4916   gtk_widget_set_default_direction (new_direction);
4917 }
4918
4919 static void
4920 orientable_toggle_orientation (GtkOrientable *orientable)
4921 {
4922   GtkOrientation orientation;
4923
4924   orientation = gtk_orientable_get_orientation (orientable);
4925   gtk_orientable_set_orientation (orientable,
4926                                   orientation == GTK_ORIENTATION_HORIZONTAL ?
4927                                   GTK_ORIENTATION_VERTICAL :
4928                                   GTK_ORIENTATION_HORIZONTAL);
4929
4930   if (GTK_IS_CONTAINER (orientable))
4931     {
4932       GList *children;
4933       GList *child;
4934
4935       children = gtk_container_get_children (GTK_CONTAINER (orientable));
4936
4937       for (child = children; child; child = child->next)
4938         {
4939           if (GTK_IS_ORIENTABLE (child->data))
4940             orientable_toggle_orientation (child->data);
4941         }
4942
4943       g_list_free (children);
4944     }
4945 }
4946
4947 void
4948 flipping_orientation_toggled_cb (GtkWidget *widget, gpointer data)
4949 {
4950   GtkWidget *content_area;
4951   GtkWidget *toplevel;
4952
4953   toplevel = gtk_widget_get_toplevel (widget);
4954   content_area = gtk_dialog_get_content_area (GTK_DIALOG (toplevel));
4955   orientable_toggle_orientation (GTK_ORIENTABLE (content_area));
4956 }
4957
4958 static void
4959 set_direction_recurse (GtkWidget *widget,
4960                        gpointer   data)
4961 {
4962   GtkTextDirection *dir = data;
4963   
4964   gtk_widget_set_direction (widget, *dir);
4965   if (GTK_IS_CONTAINER (widget))
4966     gtk_container_foreach (GTK_CONTAINER (widget),
4967                            set_direction_recurse,
4968                            data);
4969 }
4970
4971 static GtkWidget *
4972 create_forward_back (const char       *title,
4973                      GtkTextDirection  text_dir)
4974 {
4975   GtkWidget *frame = gtk_frame_new (title);
4976   GtkWidget *bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
4977   GtkWidget *back_button = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
4978   GtkWidget *forward_button = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
4979
4980   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
4981   
4982   gtk_container_add (GTK_CONTAINER (frame), bbox);
4983   gtk_container_add (GTK_CONTAINER (bbox), back_button);
4984   gtk_container_add (GTK_CONTAINER (bbox), forward_button);
4985
4986   set_direction_recurse (frame, &text_dir);
4987
4988   return frame;
4989 }
4990
4991 void
4992 create_flipping (GtkWidget *widget)
4993 {
4994   static GtkWidget *window = NULL;
4995   GtkWidget *check_button, *button;
4996   GtkWidget *action_area, *content_area;
4997
4998   if (!window)
4999     {
5000       window = gtk_dialog_new ();
5001
5002       gtk_window_set_screen (GTK_WINDOW (window),
5003                              gtk_widget_get_screen (widget));
5004
5005       g_signal_connect (window, "destroy",
5006                         G_CALLBACK (gtk_widget_destroyed),
5007                         &window);
5008
5009       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
5010       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
5011
5012       gtk_window_set_title (GTK_WINDOW (window), "Bidirectional Flipping");
5013
5014       check_button = gtk_check_button_new_with_label ("Right-to-left global direction");
5015       gtk_container_set_border_width (GTK_CONTAINER (check_button), 10);
5016       gtk_box_pack_start (GTK_BOX (content_area), check_button, TRUE, TRUE, 0);
5017
5018       if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL)
5019         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button), TRUE);
5020
5021       g_signal_connect (check_button, "toggled",
5022                         G_CALLBACK (flipping_toggled_cb), NULL);
5023
5024       check_button = gtk_check_button_new_with_label ("Toggle orientation of all boxes");
5025       gtk_container_set_border_width (GTK_CONTAINER (check_button), 10);
5026       gtk_box_pack_start (GTK_BOX (content_area), check_button, TRUE, TRUE, 0);
5027
5028       g_signal_connect (check_button, "toggled",
5029                         G_CALLBACK (flipping_orientation_toggled_cb), NULL);
5030
5031       gtk_box_pack_start (GTK_BOX (content_area),
5032                           create_forward_back ("Default", GTK_TEXT_DIR_NONE),
5033                           TRUE, TRUE, 0);
5034
5035       gtk_box_pack_start (GTK_BOX (content_area),
5036                           create_forward_back ("Left-to-Right", GTK_TEXT_DIR_LTR),
5037                           TRUE, TRUE, 0);
5038
5039       gtk_box_pack_start (GTK_BOX (content_area),
5040                           create_forward_back ("Right-to-Left", GTK_TEXT_DIR_RTL),
5041                           TRUE, TRUE, 0);
5042
5043       button = gtk_button_new_with_label ("Close");
5044       g_signal_connect_swapped (button, "clicked",
5045                                 G_CALLBACK (gtk_widget_destroy), window);
5046       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
5047     }
5048   
5049   if (!gtk_widget_get_visible (window))
5050     gtk_widget_show_all (window);
5051   else
5052     gtk_widget_destroy (window);
5053 }
5054
5055 /*
5056  * Focus test
5057  */
5058
5059 static GtkWidget*
5060 make_focus_table (GList **list)
5061 {
5062   GtkWidget *grid;
5063   gint i, j;
5064   
5065   grid = gtk_grid_new ();
5066
5067   gtk_grid_set_row_spacing (GTK_GRID (grid), 10);
5068   gtk_grid_set_column_spacing (GTK_GRID (grid), 10);
5069
5070   for (i = 0; i < 5; i++)
5071     {
5072       for (j = 0; j < 5; j++)
5073         {
5074           GtkWidget *widget;
5075           
5076           if ((i + j) % 2)
5077             widget = gtk_entry_new ();
5078           else
5079             widget = gtk_button_new_with_label ("Foo");
5080
5081           *list = g_list_prepend (*list, widget);
5082           
5083           gtk_widget_set_hexpand (widget, TRUE);
5084           gtk_widget_set_vexpand (widget, TRUE);
5085
5086           gtk_grid_attach (GTK_GRID (grid), widget, i, j, 1, 1);
5087         }
5088     }
5089
5090   *list = g_list_reverse (*list);
5091   
5092   return grid;
5093 }
5094
5095 static void
5096 create_focus (GtkWidget *widget)
5097 {
5098   static GtkWidget *window = NULL;
5099   
5100   if (!window)
5101     {
5102       GtkWidget *content_area;
5103       GtkWidget *table;
5104       GtkWidget *frame;
5105       GList *list = NULL;
5106       
5107       window = gtk_dialog_new_with_buttons ("Keyboard focus navigation",
5108                                             NULL, 0,
5109                                             GTK_STOCK_CLOSE,
5110                                             GTK_RESPONSE_NONE,
5111                                             NULL);
5112
5113       gtk_window_set_screen (GTK_WINDOW (window),
5114                              gtk_widget_get_screen (widget));
5115
5116       g_signal_connect (window, "destroy",
5117                         G_CALLBACK (gtk_widget_destroyed),
5118                         &window);
5119
5120       g_signal_connect (window, "response",
5121                         G_CALLBACK (gtk_widget_destroy),
5122                         NULL);
5123
5124       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
5125       
5126       gtk_window_set_title (GTK_WINDOW (window), "Keyboard Focus Navigation");
5127
5128       frame = gtk_frame_new ("Weird tab focus chain");
5129
5130       gtk_box_pack_start (GTK_BOX (content_area), frame, TRUE, TRUE, 0);
5131       
5132       table = make_focus_table (&list);
5133
5134       gtk_container_add (GTK_CONTAINER (frame), table);
5135
5136       gtk_container_set_focus_chain (GTK_CONTAINER (table),
5137                                      list);
5138
5139       g_list_free (list);
5140       
5141       frame = gtk_frame_new ("Default tab focus chain");
5142
5143       gtk_box_pack_start (GTK_BOX (content_area), frame, TRUE, TRUE, 0);
5144
5145       list = NULL;
5146       table = make_focus_table (&list);
5147
5148       g_list_free (list);
5149       
5150       gtk_container_add (GTK_CONTAINER (frame), table);      
5151     }
5152   
5153   if (!gtk_widget_get_visible (window))
5154     gtk_widget_show_all (window);
5155   else
5156     gtk_widget_destroy (window);
5157 }
5158
5159 /*
5160  * GtkFontSelection
5161  */
5162
5163 void
5164 create_font_selection (GtkWidget *widget)
5165 {
5166   static GtkWidget *window = NULL;
5167
5168   if (!window)
5169     {
5170       GtkWidget *picker;
5171       GtkWidget *hbox;
5172       GtkWidget *label;
5173       
5174       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5175       gtk_window_set_screen (GTK_WINDOW (window),
5176                              gtk_widget_get_screen (widget));
5177
5178       g_signal_connect (window, "destroy",
5179                         G_CALLBACK (gtk_widget_destroyed),
5180                         &window);
5181
5182       gtk_window_set_title (GTK_WINDOW (window), "GtkFontButton");
5183       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5184
5185       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
5186       gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
5187       gtk_container_add (GTK_CONTAINER (window), hbox);
5188       
5189       label = gtk_label_new ("Pick a font");
5190       gtk_container_add (GTK_CONTAINER (hbox), label);
5191
5192       picker = gtk_font_button_new ();
5193       gtk_font_button_set_use_font (GTK_FONT_BUTTON (picker), TRUE);
5194       gtk_container_add (GTK_CONTAINER (hbox), picker);
5195     }
5196   
5197   if (!gtk_widget_get_visible (window))
5198     gtk_widget_show_all (window);
5199   else
5200     gtk_widget_destroy (window);
5201 }
5202
5203 /*
5204  * GtkDialog
5205  */
5206
5207 static GtkWidget *dialog_window = NULL;
5208
5209 static void
5210 label_toggle (GtkWidget  *widget,
5211               GtkWidget **label)
5212 {
5213   if (!(*label))
5214     {
5215       *label = gtk_label_new ("Dialog Test");
5216       g_signal_connect (*label,
5217                         "destroy",
5218                         G_CALLBACK (gtk_widget_destroyed),
5219                         label);
5220       g_object_set (*label, "margin", 10, NULL);
5221       gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog_window))),
5222                           *label, TRUE, TRUE, 0);
5223       gtk_widget_show (*label);
5224     }
5225   else
5226     gtk_widget_destroy (*label);
5227 }
5228
5229 static void
5230 create_dialog (GtkWidget *widget)
5231 {
5232   static GtkWidget *label;
5233   GtkWidget *action_area;
5234   GtkWidget *button;
5235
5236   if (!dialog_window)
5237     {
5238       /* This is a terrible example; it's much simpler to create
5239        * dialogs than this. Don't use testgtk for example code,
5240        * use gtk-demo ;-)
5241        */
5242       
5243       dialog_window = gtk_dialog_new ();
5244       gtk_window_set_screen (GTK_WINDOW (dialog_window),
5245                              gtk_widget_get_screen (widget));
5246
5247       g_signal_connect (dialog_window, "destroy",
5248                         G_CALLBACK (gtk_widget_destroyed),
5249                         &dialog_window);
5250
5251       action_area = gtk_dialog_get_action_area (GTK_DIALOG (dialog_window));
5252
5253       gtk_window_set_title (GTK_WINDOW (dialog_window), "GtkDialog");
5254       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
5255
5256       button = gtk_button_new_with_label ("OK");
5257       gtk_widget_set_can_default (button, TRUE);
5258       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
5259       gtk_widget_grab_default (button);
5260       gtk_widget_show (button);
5261
5262       button = gtk_button_new_with_label ("Toggle");
5263       g_signal_connect (button, "clicked",
5264                         G_CALLBACK (label_toggle),
5265                         &label);
5266       gtk_widget_set_can_default (button, TRUE);
5267       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
5268       gtk_widget_show (button);
5269
5270       label = NULL;
5271     }
5272
5273   if (!gtk_widget_get_visible (dialog_window))
5274     gtk_widget_show (dialog_window);
5275   else
5276     gtk_widget_destroy (dialog_window);
5277 }
5278
5279 /* Display & Screen test 
5280  */
5281
5282 typedef struct
5283 {
5284   GtkWidget *combo;
5285   GtkWidget *entry;
5286   GtkWidget *radio_dpy;
5287   GtkWidget *toplevel;
5288   GtkWidget *dialog_window;
5289 } ScreenDisplaySelection;
5290
5291 static void
5292 screen_display_check (GtkWidget *widget, ScreenDisplaySelection *data)
5293 {
5294   const gchar *display_name;
5295   GdkDisplay *display = gtk_widget_get_display (widget);
5296   GtkWidget *dialog;
5297   GdkScreen *new_screen = NULL;
5298   GdkScreen *current_screen = gtk_widget_get_screen (widget);
5299   
5300   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->radio_dpy)))
5301     {
5302       display_name = gtk_entry_get_text (GTK_ENTRY (data->entry));
5303       display = gdk_display_open (display_name);
5304       
5305       if (!display)
5306         {
5307           dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (widget)),
5308                                            GTK_DIALOG_DESTROY_WITH_PARENT,
5309                                            GTK_MESSAGE_ERROR,
5310                                            GTK_BUTTONS_OK,
5311                                            "The display :\n%s\ncannot be opened",
5312                                            display_name);
5313           gtk_window_set_screen (GTK_WINDOW (dialog), current_screen);
5314           gtk_widget_show (dialog);
5315           g_signal_connect (dialog, "response",
5316                             G_CALLBACK (gtk_widget_destroy),
5317                             NULL);
5318         }
5319       else
5320         {
5321           GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX (data->combo));
5322           gint i = 0;
5323           GtkTreeIter iter;
5324           gboolean found = FALSE;
5325           while (gtk_tree_model_iter_nth_child (model, &iter, NULL, i++))
5326             {
5327               gchar *name;
5328               gtk_tree_model_get (model, &iter, 0, &name, -1);
5329               found = !g_ascii_strcasecmp (display_name, name);
5330               g_free (name);
5331
5332               if (found)
5333                 break;
5334             }
5335           if (!found)
5336             gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (data->combo), display_name);
5337           new_screen = gdk_display_get_default_screen (display);
5338         }
5339     }
5340   else
5341     {
5342       gint number_of_screens = gdk_display_get_n_screens (display);
5343       gint screen_num = gdk_screen_get_number (current_screen);
5344       if ((screen_num +1) < number_of_screens)
5345         new_screen = gdk_display_get_screen (display, screen_num + 1);
5346       else
5347         new_screen = gdk_display_get_screen (display, 0);
5348     }
5349   
5350   if (new_screen) 
5351     {
5352       gtk_window_set_screen (GTK_WINDOW (data->toplevel), new_screen);
5353       gtk_widget_destroy (data->dialog_window);
5354     }
5355 }
5356
5357 void
5358 screen_display_destroy_diag (GtkWidget *widget, GtkWidget *data)
5359 {
5360   gtk_widget_destroy (data);
5361 }
5362
5363 void
5364 create_display_screen (GtkWidget *widget)
5365 {
5366   GtkWidget *grid, *frame, *window, *combo_dpy, *vbox;
5367   GtkWidget *radio_dpy, *radio_scr, *applyb, *cancelb;
5368   GtkWidget *bbox;
5369   ScreenDisplaySelection *scr_dpy_data;
5370   GdkScreen *screen = gtk_widget_get_screen (widget);
5371   GdkDisplay *display = gdk_screen_get_display (screen);
5372
5373   window = g_object_new (gtk_window_get_type (),
5374                          "screen", screen,
5375                          "type", GTK_WINDOW_TOPLEVEL,
5376                          "title", "Screen or Display selection",
5377                          "border_width",
5378                          10, NULL);
5379   g_signal_connect (window, "destroy", 
5380                     G_CALLBACK (gtk_widget_destroy), NULL);
5381
5382   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3);
5383   gtk_container_add (GTK_CONTAINER (window), vbox);
5384   
5385   frame = gtk_frame_new ("Select screen or display");
5386   gtk_container_add (GTK_CONTAINER (vbox), frame);
5387   
5388   grid = gtk_grid_new ();
5389   gtk_grid_set_row_spacing (GTK_GRID (grid), 3);
5390   gtk_grid_set_column_spacing (GTK_GRID (grid), 3);
5391
5392   gtk_container_add (GTK_CONTAINER (frame), grid);
5393
5394   radio_dpy = gtk_radio_button_new_with_label (NULL, "move to another X display");
5395   if (gdk_display_get_n_screens(display) > 1)
5396     radio_scr = gtk_radio_button_new_with_label 
5397     (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), "move to next screen");
5398   else
5399     {    
5400       radio_scr = gtk_radio_button_new_with_label 
5401         (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), 
5402          "only one screen on the current display");
5403       gtk_widget_set_sensitive (radio_scr, FALSE);
5404     }
5405   combo_dpy = gtk_combo_box_text_new_with_entry ();
5406   gtk_widget_set_hexpand (combo_dpy, TRUE);
5407   gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_dpy), "diabolo:0.0");
5408   gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (combo_dpy))),
5409                       "<hostname>:<X Server Num>.<Screen Num>");
5410
5411   gtk_grid_attach (GTK_GRID (grid), radio_dpy, 0, 0, 1, 1);
5412   gtk_grid_attach (GTK_GRID (grid), radio_scr, 0, 1, 1, 1);
5413   gtk_grid_attach (GTK_GRID (grid), combo_dpy, 1, 0, 1, 1);
5414
5415   bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
5416   applyb = gtk_button_new_from_stock (GTK_STOCK_APPLY);
5417   cancelb = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
5418   
5419   gtk_container_add (GTK_CONTAINER (vbox), bbox);
5420
5421   gtk_container_add (GTK_CONTAINER (bbox), applyb);
5422   gtk_container_add (GTK_CONTAINER (bbox), cancelb);
5423
5424   scr_dpy_data = g_new0 (ScreenDisplaySelection, 1);
5425
5426   scr_dpy_data->entry = gtk_bin_get_child (GTK_BIN (combo_dpy));
5427   scr_dpy_data->radio_dpy = radio_dpy;
5428   scr_dpy_data->toplevel = gtk_widget_get_toplevel (widget);
5429   scr_dpy_data->dialog_window = window;
5430
5431   g_signal_connect (cancelb, "clicked", 
5432                     G_CALLBACK (screen_display_destroy_diag), window);
5433   g_signal_connect (applyb, "clicked", 
5434                     G_CALLBACK (screen_display_check), scr_dpy_data);
5435   gtk_widget_show_all (window);
5436 }
5437
5438 /* Event Watcher
5439  */
5440 static gulong event_watcher_enter_id = 0;
5441 static gulong event_watcher_leave_id = 0;
5442
5443 static gboolean
5444 event_watcher (GSignalInvocationHint *ihint,
5445                guint                  n_param_values,
5446                const GValue          *param_values,
5447                gpointer               data)
5448 {
5449   g_print ("Watch: \"%s\" emitted for %s\n",
5450            g_signal_name (ihint->signal_id),
5451            G_OBJECT_TYPE_NAME (g_value_get_object (param_values + 0)));
5452
5453   return TRUE;
5454 }
5455
5456 static void
5457 event_watcher_down (void)
5458 {
5459   if (event_watcher_enter_id)
5460     {
5461       guint signal_id;
5462
5463       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
5464       g_signal_remove_emission_hook (signal_id, event_watcher_enter_id);
5465       event_watcher_enter_id = 0;
5466       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
5467       g_signal_remove_emission_hook (signal_id, event_watcher_leave_id);
5468       event_watcher_leave_id = 0;
5469     }
5470 }
5471
5472 static void
5473 event_watcher_toggle (void)
5474 {
5475   if (event_watcher_enter_id)
5476     event_watcher_down ();
5477   else
5478     {
5479       guint signal_id;
5480
5481       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
5482       event_watcher_enter_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
5483       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
5484       event_watcher_leave_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
5485     }
5486 }
5487
5488 static void
5489 create_event_watcher (GtkWidget *widget)
5490 {
5491   GtkWidget *action_area, *content_area;
5492   GtkWidget *button;
5493
5494   if (!dialog_window)
5495     {
5496       dialog_window = gtk_dialog_new ();
5497       gtk_window_set_screen (GTK_WINDOW (dialog_window),
5498                              gtk_widget_get_screen (widget));
5499
5500       g_signal_connect (dialog_window, "destroy",
5501                         G_CALLBACK (gtk_widget_destroyed),
5502                         &dialog_window);
5503       g_signal_connect (dialog_window, "destroy",
5504                         G_CALLBACK (event_watcher_down),
5505                         NULL);
5506
5507       content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog_window));
5508       action_area = gtk_dialog_get_action_area (GTK_DIALOG (dialog_window));
5509
5510       gtk_window_set_title (GTK_WINDOW (dialog_window), "Event Watcher");
5511       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
5512       gtk_widget_set_size_request (dialog_window, 200, 110);
5513
5514       button = gtk_toggle_button_new_with_label ("Activate Watch");
5515       g_signal_connect (button, "clicked",
5516                         G_CALLBACK (event_watcher_toggle),
5517                         NULL);
5518       gtk_container_set_border_width (GTK_CONTAINER (button), 10);
5519       gtk_box_pack_start (GTK_BOX (content_area), button, TRUE, TRUE, 0);
5520       gtk_widget_show (button);
5521
5522       button = gtk_button_new_with_label ("Close");
5523       g_signal_connect_swapped (button, "clicked",
5524                                 G_CALLBACK (gtk_widget_destroy),
5525                                 dialog_window);
5526       gtk_widget_set_can_default (button, TRUE);
5527       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
5528       gtk_widget_grab_default (button);
5529       gtk_widget_show (button);
5530     }
5531
5532   if (!gtk_widget_get_visible (dialog_window))
5533     gtk_widget_show (dialog_window);
5534   else
5535     gtk_widget_destroy (dialog_window);
5536 }
5537
5538 /*
5539  * GtkRange
5540  */
5541
5542 static gchar*
5543 reformat_value (GtkScale *scale,
5544                 gdouble   value)
5545 {
5546   return g_strdup_printf ("-->%0.*g<--",
5547                           gtk_scale_get_digits (scale), value);
5548 }
5549
5550 static void
5551 create_range_controls (GtkWidget *widget)
5552 {
5553   static GtkWidget *window = NULL;
5554   GtkWidget *box1;
5555   GtkWidget *box2;
5556   GtkWidget *button;
5557   GtkWidget *scrollbar;
5558   GtkWidget *scale;
5559   GtkWidget *separator;
5560   GtkAdjustment *adjustment;
5561   GtkWidget *hbox;
5562
5563   if (!window)
5564     {
5565       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5566
5567       gtk_window_set_screen (GTK_WINDOW (window),
5568                              gtk_widget_get_screen (widget));
5569
5570       g_signal_connect (window, "destroy",
5571                         G_CALLBACK (gtk_widget_destroyed),
5572                         &window);
5573
5574       gtk_window_set_title (GTK_WINDOW (window), "range controls");
5575       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5576
5577
5578       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
5579       gtk_container_add (GTK_CONTAINER (window), box1);
5580       gtk_widget_show (box1);
5581
5582
5583       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
5584       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
5585       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
5586       gtk_widget_show (box2);
5587
5588
5589       adjustment = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
5590
5591       scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (adjustment));
5592       gtk_widget_set_size_request (GTK_WIDGET (scale), 150, -1);
5593       gtk_scale_set_digits (GTK_SCALE (scale), 1);
5594       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
5595       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
5596       gtk_widget_show (scale);
5597
5598       scrollbar = gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (adjustment));
5599       gtk_box_pack_start (GTK_BOX (box2), scrollbar, TRUE, TRUE, 0);
5600       gtk_widget_show (scrollbar);
5601
5602       scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (adjustment));
5603       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
5604       g_signal_connect (scale,
5605                         "format_value",
5606                         G_CALLBACK (reformat_value),
5607                         NULL);
5608       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
5609       gtk_widget_show (scale);
5610       
5611       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
5612
5613       scale = gtk_scale_new (GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT (adjustment));
5614       gtk_widget_set_size_request (scale, -1, 200);
5615       gtk_scale_set_digits (GTK_SCALE (scale), 2);
5616       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
5617       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
5618       gtk_widget_show (scale);
5619
5620       scale = gtk_scale_new (GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT (adjustment));
5621       gtk_widget_set_size_request (scale, -1, 200);
5622       gtk_scale_set_digits (GTK_SCALE (scale), 2);
5623       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
5624       gtk_range_set_inverted (GTK_RANGE (scale), TRUE);
5625       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
5626       gtk_widget_show (scale);
5627
5628       scale = gtk_scale_new (GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT (adjustment));
5629       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
5630       g_signal_connect (scale,
5631                         "format_value",
5632                         G_CALLBACK (reformat_value),
5633                         NULL);
5634       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
5635       gtk_widget_show (scale);
5636
5637       
5638       gtk_box_pack_start (GTK_BOX (box2), hbox, TRUE, TRUE, 0);
5639       gtk_widget_show (hbox);
5640       
5641       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
5642       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
5643       gtk_widget_show (separator);
5644
5645
5646       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
5647       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
5648       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
5649       gtk_widget_show (box2);
5650
5651
5652       button = gtk_button_new_with_label ("close");
5653       g_signal_connect_swapped (button, "clicked",
5654                                 G_CALLBACK (gtk_widget_destroy),
5655                                 window);
5656       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
5657       gtk_widget_set_can_default (button, TRUE);
5658       gtk_widget_grab_default (button);
5659       gtk_widget_show (button);
5660     }
5661
5662   if (!gtk_widget_get_visible (window))
5663     gtk_widget_show (window);
5664   else
5665     gtk_widget_destroy (window);
5666 }
5667
5668 struct {
5669   GdkColor color;
5670   gchar *name;
5671 } text_colors[] = {
5672  { { 0, 0x0000, 0x0000, 0x0000 }, "black" },
5673  { { 0, 0xFFFF, 0xFFFF, 0xFFFF }, "white" },
5674  { { 0, 0xFFFF, 0x0000, 0x0000 }, "red" },
5675  { { 0, 0x0000, 0xFFFF, 0x0000 }, "green" },
5676  { { 0, 0x0000, 0x0000, 0xFFFF }, "blue" }, 
5677  { { 0, 0x0000, 0xFFFF, 0xFFFF }, "cyan" },
5678  { { 0, 0xFFFF, 0x0000, 0xFFFF }, "magenta" },
5679  { { 0, 0xFFFF, 0xFFFF, 0x0000 }, "yellow" }
5680 };
5681
5682 int ntext_colors = sizeof(text_colors) / sizeof(text_colors[0]);
5683
5684 /*
5685  * GtkNotebook
5686  */
5687
5688 static const char * book_open_xpm[] = {
5689 "16 16 4 1",
5690 "       c None s None",
5691 ".      c black",
5692 "X      c #808080",
5693 "o      c white",
5694 "                ",
5695 "  ..            ",
5696 " .Xo.    ...    ",
5697 " .Xoo. ..oo.    ",
5698 " .Xooo.Xooo...  ",
5699 " .Xooo.oooo.X.  ",
5700 " .Xooo.Xooo.X.  ",
5701 " .Xooo.oooo.X.  ",
5702 " .Xooo.Xooo.X.  ",
5703 " .Xooo.oooo.X.  ",
5704 "  .Xoo.Xoo..X.  ",
5705 "   .Xo.o..ooX.  ",
5706 "    .X..XXXXX.  ",
5707 "    ..X.......  ",
5708 "     ..         ",
5709 "                "};
5710
5711 static const char * book_closed_xpm[] = {
5712 "16 16 6 1",
5713 "       c None s None",
5714 ".      c black",
5715 "X      c red",
5716 "o      c yellow",
5717 "O      c #808080",
5718 "#      c white",
5719 "                ",
5720 "       ..       ",
5721 "     ..XX.      ",
5722 "   ..XXXXX.     ",
5723 " ..XXXXXXXX.    ",
5724 ".ooXXXXXXXXX.   ",
5725 "..ooXXXXXXXXX.  ",
5726 ".X.ooXXXXXXXXX. ",
5727 ".XX.ooXXXXXX..  ",
5728 " .XX.ooXXX..#O  ",
5729 "  .XX.oo..##OO. ",
5730 "   .XX..##OO..  ",
5731 "    .X.#OO..    ",
5732 "     ..O..      ",
5733 "      ..        ",
5734 "                "};
5735
5736 GdkPixbuf *book_open;
5737 GdkPixbuf *book_closed;
5738 GtkWidget *sample_notebook;
5739
5740 static void
5741 set_page_image (GtkNotebook *notebook, gint page_num, GdkPixbuf *pixbuf)
5742 {
5743   GtkWidget *page_widget;
5744   GtkWidget *pixwid;
5745
5746   page_widget = gtk_notebook_get_nth_page (notebook, page_num);
5747
5748   pixwid = g_object_get_data (G_OBJECT (page_widget), "tab_pixmap");
5749   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
5750   
5751   pixwid = g_object_get_data (G_OBJECT (page_widget), "menu_pixmap");
5752   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
5753 }
5754
5755 static void
5756 page_switch (GtkWidget *widget, gpointer *page, gint page_num)
5757 {
5758   GtkNotebook *notebook = GTK_NOTEBOOK (widget);
5759   gint old_page_num = gtk_notebook_get_current_page (notebook);
5760  
5761   if (page_num == old_page_num)
5762     return;
5763
5764   set_page_image (notebook, page_num, book_open);
5765
5766   if (old_page_num != -1)
5767     set_page_image (notebook, old_page_num, book_closed);
5768 }
5769
5770 static void
5771 tab_fill (GtkToggleButton *button, GtkWidget *child)
5772 {
5773   gtk_container_child_set (GTK_CONTAINER (sample_notebook), child,
5774                            "tab-fill", gtk_toggle_button_get_active (button),
5775                            NULL);
5776 }
5777
5778 static void
5779 tab_expand (GtkToggleButton *button, GtkWidget *child)
5780 {
5781   gtk_container_child_set (GTK_CONTAINER (sample_notebook), child,
5782                            "tab-expand", gtk_toggle_button_get_active (button),
5783                            NULL);
5784 }
5785
5786 static void
5787 create_pages (GtkNotebook *notebook, gint start, gint end)
5788 {
5789   GtkWidget *child = NULL;
5790   GtkWidget *button;
5791   GtkWidget *label;
5792   GtkWidget *hbox;
5793   GtkWidget *vbox;
5794   GtkWidget *label_box;
5795   GtkWidget *menu_box;
5796   GtkWidget *pixwid;
5797   gint i;
5798   char buffer[32];
5799   char accel_buffer[32];
5800
5801   for (i = start; i <= end; i++)
5802     {
5803       sprintf (buffer, "Page %d", i);
5804       sprintf (accel_buffer, "Page _%d", i);
5805
5806       child = gtk_frame_new (buffer);
5807       gtk_container_set_border_width (GTK_CONTAINER (child), 10);
5808
5809       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
5810       gtk_box_set_homogeneous (GTK_BOX (vbox), TRUE);
5811       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
5812       gtk_container_add (GTK_CONTAINER (child), vbox);
5813
5814       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
5815       gtk_box_set_homogeneous (GTK_BOX (hbox), TRUE);
5816       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5817
5818       button = gtk_check_button_new_with_label ("Fill Tab");
5819       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5820       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
5821       g_signal_connect (button, "toggled",
5822                         G_CALLBACK (tab_fill), child);
5823
5824       button = gtk_check_button_new_with_label ("Expand Tab");
5825       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5826       g_signal_connect (button, "toggled",
5827                         G_CALLBACK (tab_expand), child);
5828
5829       button = gtk_button_new_with_label ("Hide Page");
5830       gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 5);
5831       g_signal_connect_swapped (button, "clicked",
5832                                 G_CALLBACK (gtk_widget_hide),
5833                                 child);
5834
5835       gtk_widget_show_all (child);
5836
5837       label_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
5838       pixwid = gtk_image_new_from_pixbuf (book_closed);
5839       g_object_set_data (G_OBJECT (child), "tab_pixmap", pixwid);
5840                            
5841       gtk_box_pack_start (GTK_BOX (label_box), pixwid, FALSE, TRUE, 0);
5842       gtk_widget_set_margin_left (pixwid, 3);
5843       gtk_widget_set_margin_right (pixwid, 3);
5844       gtk_widget_set_margin_bottom (pixwid, 1);
5845       gtk_widget_set_margin_top (pixwid, 1);
5846       label = gtk_label_new_with_mnemonic (accel_buffer);
5847       gtk_box_pack_start (GTK_BOX (label_box), label, FALSE, TRUE, 0);
5848       gtk_widget_show_all (label_box);
5849       
5850                                        
5851       menu_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
5852       pixwid = gtk_image_new_from_pixbuf (book_closed);
5853       g_object_set_data (G_OBJECT (child), "menu_pixmap", pixwid);
5854       
5855       gtk_box_pack_start (GTK_BOX (menu_box), pixwid, FALSE, TRUE, 0);
5856       gtk_widget_set_margin_left (pixwid, 3);
5857       gtk_widget_set_margin_right (pixwid, 3);
5858       gtk_widget_set_margin_bottom (pixwid, 1);
5859       gtk_widget_set_margin_top (pixwid, 1);
5860       label = gtk_label_new (buffer);
5861       gtk_box_pack_start (GTK_BOX (menu_box), label, FALSE, TRUE, 0);
5862       gtk_widget_show_all (menu_box);
5863
5864       gtk_notebook_append_page_menu (notebook, child, label_box, menu_box);
5865     }
5866 }
5867
5868 static void
5869 rotate_notebook (GtkButton   *button,
5870                  GtkNotebook *notebook)
5871 {
5872   gtk_notebook_set_tab_pos (notebook, (gtk_notebook_get_tab_pos (notebook) + 1) % 4);
5873 }
5874
5875 static void
5876 show_all_pages (GtkButton   *button,
5877                 GtkNotebook *notebook)
5878 {  
5879   gtk_container_foreach (GTK_CONTAINER (notebook),
5880                          (GtkCallback) gtk_widget_show, NULL);
5881 }
5882
5883 static void
5884 notebook_type_changed (GtkWidget *optionmenu,
5885                        gpointer   data)
5886 {
5887   GtkNotebook *notebook;
5888   gint i, c;
5889
5890   enum {
5891     STANDARD,
5892     NOTABS,
5893     BORDERLESS,
5894     SCROLLABLE
5895   };
5896
5897   notebook = GTK_NOTEBOOK (data);
5898
5899   c = gtk_combo_box_get_active (GTK_COMBO_BOX (optionmenu));
5900
5901   switch (c)
5902     {
5903     case STANDARD:
5904       /* standard notebook */
5905       gtk_notebook_set_show_tabs (notebook, TRUE);
5906       gtk_notebook_set_show_border (notebook, TRUE);
5907       gtk_notebook_set_scrollable (notebook, FALSE);
5908       break;
5909
5910     case NOTABS:
5911       /* notabs notebook */
5912       gtk_notebook_set_show_tabs (notebook, FALSE);
5913       gtk_notebook_set_show_border (notebook, TRUE);
5914       break;
5915
5916     case BORDERLESS:
5917       /* borderless */
5918       gtk_notebook_set_show_tabs (notebook, FALSE);
5919       gtk_notebook_set_show_border (notebook, FALSE);
5920       break;
5921
5922     case SCROLLABLE:  
5923       /* scrollable */
5924       gtk_notebook_set_show_tabs (notebook, TRUE);
5925       gtk_notebook_set_show_border (notebook, TRUE);
5926       gtk_notebook_set_scrollable (notebook, TRUE);
5927       if (gtk_notebook_get_n_pages (notebook) == 5)
5928         create_pages (notebook, 6, 15);
5929
5930       return;
5931       break;
5932     }
5933
5934   if (gtk_notebook_get_n_pages (notebook) == 15)
5935     for (i = 0; i < 10; i++)
5936       gtk_notebook_remove_page (notebook, 5);
5937 }
5938
5939 static void
5940 notebook_popup (GtkToggleButton *button,
5941                 GtkNotebook     *notebook)
5942 {
5943   if (gtk_toggle_button_get_active (button))
5944     gtk_notebook_popup_enable (notebook);
5945   else
5946     gtk_notebook_popup_disable (notebook);
5947 }
5948
5949 static void
5950 create_notebook (GtkWidget *widget)
5951 {
5952   static GtkWidget *window = NULL;
5953   GtkWidget *box1;
5954   GtkWidget *box2;
5955   GtkWidget *button;
5956   GtkWidget *separator;
5957   GtkWidget *omenu;
5958   GtkWidget *label;
5959
5960   static gchar *items[] =
5961   {
5962     "Standard",
5963     "No tabs",
5964     "Borderless",
5965     "Scrollable"
5966   };
5967   
5968   if (!window)
5969     {
5970       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5971       gtk_window_set_screen (GTK_WINDOW (window),
5972                              gtk_widget_get_screen (widget));
5973
5974       g_signal_connect (window, "destroy",
5975                         G_CALLBACK (gtk_widget_destroyed),
5976                         &window);
5977
5978       gtk_window_set_title (GTK_WINDOW (window), "notebook");
5979       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5980
5981       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
5982       gtk_container_add (GTK_CONTAINER (window), box1);
5983
5984       sample_notebook = gtk_notebook_new ();
5985       g_signal_connect (sample_notebook, "switch_page",
5986                         G_CALLBACK (page_switch), NULL);
5987       gtk_notebook_set_tab_pos (GTK_NOTEBOOK (sample_notebook), GTK_POS_TOP);
5988       gtk_box_pack_start (GTK_BOX (box1), sample_notebook, TRUE, TRUE, 0);
5989       gtk_container_set_border_width (GTK_CONTAINER (sample_notebook), 10);
5990
5991       gtk_widget_realize (sample_notebook);
5992
5993       if (!book_open)
5994         book_open = gdk_pixbuf_new_from_xpm_data (book_open_xpm);
5995                                                   
5996       if (!book_closed)
5997         book_closed = gdk_pixbuf_new_from_xpm_data (book_closed_xpm);
5998
5999       create_pages (GTK_NOTEBOOK (sample_notebook), 1, 5);
6000
6001       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
6002       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 10);
6003       
6004       box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
6005       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6006       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
6007
6008       button = gtk_check_button_new_with_label ("popup menu");
6009       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
6010       g_signal_connect (button, "clicked",
6011                         G_CALLBACK (notebook_popup),
6012                         sample_notebook);
6013
6014       box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
6015       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6016       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
6017
6018       label = gtk_label_new ("Notebook Style :");
6019       gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0);
6020
6021       omenu = build_option_menu (items, G_N_ELEMENTS (items), 0,
6022                                  notebook_type_changed,
6023                                  sample_notebook);
6024       gtk_box_pack_start (GTK_BOX (box2), omenu, FALSE, TRUE, 0);
6025
6026       button = gtk_button_new_with_label ("Show all Pages");
6027       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, TRUE, 0);
6028       g_signal_connect (button, "clicked",
6029                         G_CALLBACK (show_all_pages), sample_notebook);
6030
6031       box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
6032       gtk_box_set_homogeneous (GTK_BOX (box2), TRUE);
6033       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6034       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
6035
6036       button = gtk_button_new_with_label ("prev");
6037       g_signal_connect_swapped (button, "clicked",
6038                                 G_CALLBACK (gtk_notebook_prev_page),
6039                                 sample_notebook);
6040       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
6041
6042       button = gtk_button_new_with_label ("next");
6043       g_signal_connect_swapped (button, "clicked",
6044                                 G_CALLBACK (gtk_notebook_next_page),
6045                                 sample_notebook);
6046       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
6047
6048       button = gtk_button_new_with_label ("rotate");
6049       g_signal_connect (button, "clicked",
6050                         G_CALLBACK (rotate_notebook), sample_notebook);
6051       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
6052
6053       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
6054       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
6055
6056       button = gtk_button_new_with_label ("close");
6057       gtk_container_set_border_width (GTK_CONTAINER (button), 5);
6058       g_signal_connect_swapped (button, "clicked",
6059                                 G_CALLBACK (gtk_widget_destroy),
6060                                 window);
6061       gtk_box_pack_start (GTK_BOX (box1), button, FALSE, FALSE, 0);
6062       gtk_widget_set_can_default (button, TRUE);
6063       gtk_widget_grab_default (button);
6064     }
6065
6066   if (!gtk_widget_get_visible (window))
6067     gtk_widget_show_all (window);
6068   else
6069     gtk_widget_destroy (window);
6070 }
6071
6072 /*
6073  * GtkPanes
6074  */
6075
6076 void
6077 toggle_resize (GtkWidget *widget, GtkWidget *child)
6078 {
6079   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
6080   GValue value = G_VALUE_INIT;
6081   g_value_init (&value, G_TYPE_BOOLEAN);
6082   gtk_container_child_get_property (container, child, "resize", &value);
6083   g_value_set_boolean (&value, !g_value_get_boolean (&value));
6084   gtk_container_child_set_property (container, child, "resize", &value);
6085 }
6086
6087 void
6088 toggle_shrink (GtkWidget *widget, GtkWidget *child)
6089 {
6090   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
6091   GValue value = G_VALUE_INIT;
6092   g_value_init (&value, G_TYPE_BOOLEAN);
6093   gtk_container_child_get_property (container, child, "shrink", &value);
6094   g_value_set_boolean (&value, !g_value_get_boolean (&value));
6095   gtk_container_child_set_property (container, child, "shrink", &value);
6096 }
6097
6098 static void
6099 paned_props_clicked (GtkWidget *button,
6100                      GObject   *paned)
6101 {
6102   GtkWidget *window = create_prop_editor (paned, GTK_TYPE_PANED);
6103   
6104   gtk_window_set_title (GTK_WINDOW (window), "Paned Properties");
6105 }
6106
6107 GtkWidget *
6108 create_pane_options (GtkPaned    *paned,
6109                      const gchar *frame_label,
6110                      const gchar *label1,
6111                      const gchar *label2)
6112 {
6113   GtkWidget *child1, *child2;
6114   GtkWidget *frame;
6115   GtkWidget *grid;
6116   GtkWidget *label;
6117   GtkWidget *button;
6118   GtkWidget *check_button;
6119
6120   child1 = gtk_paned_get_child1 (paned);
6121   child2 = gtk_paned_get_child2 (paned);
6122
6123   frame = gtk_frame_new (frame_label);
6124   gtk_container_set_border_width (GTK_CONTAINER (frame), 4);
6125   
6126   grid = gtk_grid_new ();
6127   gtk_container_add (GTK_CONTAINER (frame), grid);
6128   
6129   label = gtk_label_new (label1);
6130   gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
6131   
6132   check_button = gtk_check_button_new_with_label ("Resize");
6133   gtk_grid_attach (GTK_GRID (grid), check_button, 0, 1, 1, 1);
6134   g_signal_connect (check_button, "toggled",
6135                     G_CALLBACK (toggle_resize),
6136                     child1);
6137
6138   check_button = gtk_check_button_new_with_label ("Shrink");
6139   gtk_grid_attach (GTK_GRID (grid), check_button, 0, 2, 1, 1);
6140   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
6141                                TRUE);
6142   g_signal_connect (check_button, "toggled",
6143                     G_CALLBACK (toggle_shrink),
6144                     child1);
6145
6146   label = gtk_label_new (label2);
6147   gtk_grid_attach (GTK_GRID (grid), label, 1, 0, 1, 1);
6148   
6149   check_button = gtk_check_button_new_with_label ("Resize");
6150   gtk_grid_attach (GTK_GRID (grid), check_button, 1, 1, 1, 1);
6151   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
6152                                TRUE);
6153   g_signal_connect (check_button, "toggled",
6154                     G_CALLBACK (toggle_resize),
6155                     child2);
6156
6157   check_button = gtk_check_button_new_with_label ("Shrink");
6158   gtk_grid_attach (GTK_GRID (grid), check_button, 1, 2, 1, 1);
6159   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
6160                                TRUE);
6161   g_signal_connect (check_button, "toggled",
6162                     G_CALLBACK (toggle_shrink),
6163                     child2);
6164
6165   button = gtk_button_new_with_mnemonic ("_Properties");
6166   gtk_grid_attach (GTK_GRID (grid), button, 0, 3, 2, 1);
6167   g_signal_connect (button, "clicked",
6168                     G_CALLBACK (paned_props_clicked),
6169                     paned);
6170
6171   return frame;
6172 }
6173
6174 void
6175 create_panes (GtkWidget *widget)
6176 {
6177   static GtkWidget *window = NULL;
6178   GtkWidget *frame;
6179   GtkWidget *hpaned;
6180   GtkWidget *vpaned;
6181   GtkWidget *button;
6182   GtkWidget *vbox;
6183
6184   if (!window)
6185     {
6186       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6187
6188       gtk_window_set_screen (GTK_WINDOW (window),
6189                              gtk_widget_get_screen (widget));
6190       
6191       g_signal_connect (window, "destroy",
6192                         G_CALLBACK (gtk_widget_destroyed),
6193                         &window);
6194
6195       gtk_window_set_title (GTK_WINDOW (window), "Panes");
6196       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6197
6198       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
6199       gtk_container_add (GTK_CONTAINER (window), vbox);
6200       
6201       vpaned = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6202       gtk_box_pack_start (GTK_BOX (vbox), vpaned, TRUE, TRUE, 0);
6203       gtk_container_set_border_width (GTK_CONTAINER(vpaned), 5);
6204
6205       hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6206       gtk_paned_add1 (GTK_PANED (vpaned), hpaned);
6207
6208       frame = gtk_frame_new (NULL);
6209       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
6210       gtk_widget_set_size_request (frame, 60, 60);
6211       gtk_paned_add1 (GTK_PANED (hpaned), frame);
6212       
6213       button = gtk_button_new_with_label ("Hi there");
6214       gtk_container_add (GTK_CONTAINER(frame), button);
6215
6216       frame = gtk_frame_new (NULL);
6217       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
6218       gtk_widget_set_size_request (frame, 80, 60);
6219       gtk_paned_add2 (GTK_PANED (hpaned), frame);
6220
6221       frame = gtk_frame_new (NULL);
6222       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
6223       gtk_widget_set_size_request (frame, 60, 80);
6224       gtk_paned_add2 (GTK_PANED (vpaned), frame);
6225
6226       /* Now create toggle buttons to control sizing */
6227
6228       gtk_box_pack_start (GTK_BOX (vbox),
6229                           create_pane_options (GTK_PANED (hpaned),
6230                                                "Horizontal",
6231                                                "Left",
6232                                                "Right"),
6233                           FALSE, FALSE, 0);
6234
6235       gtk_box_pack_start (GTK_BOX (vbox),
6236                           create_pane_options (GTK_PANED (vpaned),
6237                                                "Vertical",
6238                                                "Top",
6239                                                "Bottom"),
6240                           FALSE, FALSE, 0);
6241
6242       gtk_widget_show_all (vbox);
6243     }
6244
6245   if (!gtk_widget_get_visible (window))
6246     gtk_widget_show (window);
6247   else
6248     gtk_widget_destroy (window);
6249 }
6250
6251 /*
6252  * Paned keyboard navigation
6253  */
6254
6255 static GtkWidget*
6256 paned_keyboard_window1 (GtkWidget *widget)
6257 {
6258   GtkWidget *window1;
6259   GtkWidget *hpaned1;
6260   GtkWidget *frame1;
6261   GtkWidget *vbox1;
6262   GtkWidget *button7;
6263   GtkWidget *button8;
6264   GtkWidget *button9;
6265   GtkWidget *vpaned1;
6266   GtkWidget *frame2;
6267   GtkWidget *frame5;
6268   GtkWidget *hbox1;
6269   GtkWidget *button5;
6270   GtkWidget *button6;
6271   GtkWidget *frame3;
6272   GtkWidget *frame4;
6273   GtkWidget *grid1;
6274   GtkWidget *button1;
6275   GtkWidget *button2;
6276   GtkWidget *button3;
6277   GtkWidget *button4;
6278
6279   window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6280   gtk_window_set_title (GTK_WINDOW (window1), "Basic paned navigation");
6281   gtk_window_set_screen (GTK_WINDOW (window1), 
6282                          gtk_widget_get_screen (widget));
6283
6284   hpaned1 = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6285   gtk_container_add (GTK_CONTAINER (window1), hpaned1);
6286
6287   frame1 = gtk_frame_new (NULL);
6288   gtk_paned_pack1 (GTK_PANED (hpaned1), frame1, FALSE, TRUE);
6289   gtk_frame_set_shadow_type (GTK_FRAME (frame1), GTK_SHADOW_IN);
6290
6291   vbox1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
6292   gtk_container_add (GTK_CONTAINER (frame1), vbox1);
6293
6294   button7 = gtk_button_new_with_label ("button7");
6295   gtk_box_pack_start (GTK_BOX (vbox1), button7, FALSE, FALSE, 0);
6296
6297   button8 = gtk_button_new_with_label ("button8");
6298   gtk_box_pack_start (GTK_BOX (vbox1), button8, FALSE, FALSE, 0);
6299
6300   button9 = gtk_button_new_with_label ("button9");
6301   gtk_box_pack_start (GTK_BOX (vbox1), button9, FALSE, FALSE, 0);
6302
6303   vpaned1 = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6304   gtk_paned_pack2 (GTK_PANED (hpaned1), vpaned1, TRUE, TRUE);
6305
6306   frame2 = gtk_frame_new (NULL);
6307   gtk_paned_pack1 (GTK_PANED (vpaned1), frame2, FALSE, TRUE);
6308   gtk_frame_set_shadow_type (GTK_FRAME (frame2), GTK_SHADOW_IN);
6309
6310   frame5 = gtk_frame_new (NULL);
6311   gtk_container_add (GTK_CONTAINER (frame2), frame5);
6312
6313   hbox1 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
6314   gtk_container_add (GTK_CONTAINER (frame5), hbox1);
6315
6316   button5 = gtk_button_new_with_label ("button5");
6317   gtk_box_pack_start (GTK_BOX (hbox1), button5, FALSE, FALSE, 0);
6318
6319   button6 = gtk_button_new_with_label ("button6");
6320   gtk_box_pack_start (GTK_BOX (hbox1), button6, FALSE, FALSE, 0);
6321
6322   frame3 = gtk_frame_new (NULL);
6323   gtk_paned_pack2 (GTK_PANED (vpaned1), frame3, TRUE, TRUE);
6324   gtk_frame_set_shadow_type (GTK_FRAME (frame3), GTK_SHADOW_IN);
6325
6326   frame4 = gtk_frame_new ("Buttons");
6327   gtk_container_add (GTK_CONTAINER (frame3), frame4);
6328   gtk_container_set_border_width (GTK_CONTAINER (frame4), 15);
6329
6330   grid1 = gtk_grid_new ();
6331   gtk_container_add (GTK_CONTAINER (frame4), grid1);
6332   gtk_container_set_border_width (GTK_CONTAINER (grid1), 11);
6333
6334   button1 = gtk_button_new_with_label ("button1");
6335   gtk_grid_attach (GTK_GRID (grid1), button1, 0, 0, 1, 1);
6336
6337   button2 = gtk_button_new_with_label ("button2");
6338   gtk_grid_attach (GTK_GRID (grid1), button2, 1, 0, 1, 1);
6339
6340   button3 = gtk_button_new_with_label ("button3");
6341   gtk_grid_attach (GTK_GRID (grid1), button3, 0, 1, 1, 1);
6342
6343   button4 = gtk_button_new_with_label ("button4");
6344   gtk_grid_attach (GTK_GRID (grid1), button4, 1, 1, 1, 1);
6345
6346   return window1;
6347 }
6348
6349 static GtkWidget*
6350 paned_keyboard_window2 (GtkWidget *widget)
6351 {
6352   GtkWidget *window2;
6353   GtkWidget *hpaned2;
6354   GtkWidget *frame6;
6355   GtkWidget *button13;
6356   GtkWidget *hbox2;
6357   GtkWidget *vpaned2;
6358   GtkWidget *frame7;
6359   GtkWidget *button12;
6360   GtkWidget *frame8;
6361   GtkWidget *button11;
6362   GtkWidget *button10;
6363
6364   window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6365   gtk_window_set_title (GTK_WINDOW (window2), "\"button 10\" is not inside the horisontal pane");
6366
6367   gtk_window_set_screen (GTK_WINDOW (window2), 
6368                          gtk_widget_get_screen (widget));
6369
6370   hpaned2 = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6371   gtk_container_add (GTK_CONTAINER (window2), hpaned2);
6372
6373   frame6 = gtk_frame_new (NULL);
6374   gtk_paned_pack1 (GTK_PANED (hpaned2), frame6, FALSE, TRUE);
6375   gtk_frame_set_shadow_type (GTK_FRAME (frame6), GTK_SHADOW_IN);
6376
6377   button13 = gtk_button_new_with_label ("button13");
6378   gtk_container_add (GTK_CONTAINER (frame6), button13);
6379
6380   hbox2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
6381   gtk_paned_pack2 (GTK_PANED (hpaned2), hbox2, TRUE, TRUE);
6382
6383   vpaned2 = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6384   gtk_box_pack_start (GTK_BOX (hbox2), vpaned2, TRUE, TRUE, 0);
6385
6386   frame7 = gtk_frame_new (NULL);
6387   gtk_paned_pack1 (GTK_PANED (vpaned2), frame7, FALSE, TRUE);
6388   gtk_frame_set_shadow_type (GTK_FRAME (frame7), GTK_SHADOW_IN);
6389
6390   button12 = gtk_button_new_with_label ("button12");
6391   gtk_container_add (GTK_CONTAINER (frame7), button12);
6392
6393   frame8 = gtk_frame_new (NULL);
6394   gtk_paned_pack2 (GTK_PANED (vpaned2), frame8, TRUE, TRUE);
6395   gtk_frame_set_shadow_type (GTK_FRAME (frame8), GTK_SHADOW_IN);
6396
6397   button11 = gtk_button_new_with_label ("button11");
6398   gtk_container_add (GTK_CONTAINER (frame8), button11);
6399
6400   button10 = gtk_button_new_with_label ("button10");
6401   gtk_box_pack_start (GTK_BOX (hbox2), button10, FALSE, FALSE, 0);
6402
6403   return window2;
6404 }
6405
6406 static GtkWidget*
6407 paned_keyboard_window3 (GtkWidget *widget)
6408 {
6409   GtkWidget *window3;
6410   GtkWidget *vbox2;
6411   GtkWidget *label1;
6412   GtkWidget *hpaned3;
6413   GtkWidget *frame9;
6414   GtkWidget *button14;
6415   GtkWidget *hpaned4;
6416   GtkWidget *frame10;
6417   GtkWidget *button15;
6418   GtkWidget *hpaned5;
6419   GtkWidget *frame11;
6420   GtkWidget *button16;
6421   GtkWidget *frame12;
6422   GtkWidget *button17;
6423
6424   window3 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6425   g_object_set_data (G_OBJECT (window3), "window3", window3);
6426   gtk_window_set_title (GTK_WINDOW (window3), "Nested panes");
6427
6428   gtk_window_set_screen (GTK_WINDOW (window3), 
6429                          gtk_widget_get_screen (widget));
6430   
6431
6432   vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
6433   gtk_container_add (GTK_CONTAINER (window3), vbox2);
6434
6435   label1 = gtk_label_new ("Three panes nested inside each other");
6436   gtk_box_pack_start (GTK_BOX (vbox2), label1, FALSE, FALSE, 0);
6437
6438   hpaned3 = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6439   gtk_box_pack_start (GTK_BOX (vbox2), hpaned3, TRUE, TRUE, 0);
6440
6441   frame9 = gtk_frame_new (NULL);
6442   gtk_paned_pack1 (GTK_PANED (hpaned3), frame9, FALSE, TRUE);
6443   gtk_frame_set_shadow_type (GTK_FRAME (frame9), GTK_SHADOW_IN);
6444
6445   button14 = gtk_button_new_with_label ("button14");
6446   gtk_container_add (GTK_CONTAINER (frame9), button14);
6447
6448   hpaned4 = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6449   gtk_paned_pack2 (GTK_PANED (hpaned3), hpaned4, TRUE, TRUE);
6450
6451   frame10 = gtk_frame_new (NULL);
6452   gtk_paned_pack1 (GTK_PANED (hpaned4), frame10, FALSE, TRUE);
6453   gtk_frame_set_shadow_type (GTK_FRAME (frame10), GTK_SHADOW_IN);
6454
6455   button15 = gtk_button_new_with_label ("button15");
6456   gtk_container_add (GTK_CONTAINER (frame10), button15);
6457
6458   hpaned5 = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6459   gtk_paned_pack2 (GTK_PANED (hpaned4), hpaned5, TRUE, TRUE);
6460
6461   frame11 = gtk_frame_new (NULL);
6462   gtk_paned_pack1 (GTK_PANED (hpaned5), frame11, FALSE, TRUE);
6463   gtk_frame_set_shadow_type (GTK_FRAME (frame11), GTK_SHADOW_IN);
6464
6465   button16 = gtk_button_new_with_label ("button16");
6466   gtk_container_add (GTK_CONTAINER (frame11), button16);
6467
6468   frame12 = gtk_frame_new (NULL);
6469   gtk_paned_pack2 (GTK_PANED (hpaned5), frame12, TRUE, TRUE);
6470   gtk_frame_set_shadow_type (GTK_FRAME (frame12), GTK_SHADOW_IN);
6471
6472   button17 = gtk_button_new_with_label ("button17");
6473   gtk_container_add (GTK_CONTAINER (frame12), button17);
6474
6475   return window3;
6476 }
6477
6478 static GtkWidget*
6479 paned_keyboard_window4 (GtkWidget *widget)
6480 {
6481   GtkWidget *window4;
6482   GtkWidget *vbox3;
6483   GtkWidget *label2;
6484   GtkWidget *hpaned6;
6485   GtkWidget *vpaned3;
6486   GtkWidget *button19;
6487   GtkWidget *button18;
6488   GtkWidget *hbox3;
6489   GtkWidget *vpaned4;
6490   GtkWidget *button21;
6491   GtkWidget *button20;
6492   GtkWidget *vpaned5;
6493   GtkWidget *button23;
6494   GtkWidget *button22;
6495   GtkWidget *vpaned6;
6496   GtkWidget *button25;
6497   GtkWidget *button24;
6498
6499   window4 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6500   g_object_set_data (G_OBJECT (window4), "window4", window4);
6501   gtk_window_set_title (GTK_WINDOW (window4), "window4");
6502
6503   gtk_window_set_screen (GTK_WINDOW (window4), 
6504                          gtk_widget_get_screen (widget));
6505
6506   vbox3 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
6507   gtk_container_add (GTK_CONTAINER (window4), vbox3);
6508
6509   label2 = gtk_label_new ("Widget tree:\n\nhpaned \n - vpaned\n - hbox\n    - vpaned\n    - vpaned\n    - vpaned\n");
6510   gtk_box_pack_start (GTK_BOX (vbox3), label2, FALSE, FALSE, 0);
6511   gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_LEFT);
6512
6513   hpaned6 = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6514   gtk_box_pack_start (GTK_BOX (vbox3), hpaned6, TRUE, TRUE, 0);
6515
6516   vpaned3 = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6517   gtk_paned_pack1 (GTK_PANED (hpaned6), vpaned3, FALSE, TRUE);
6518
6519   button19 = gtk_button_new_with_label ("button19");
6520   gtk_paned_pack1 (GTK_PANED (vpaned3), button19, FALSE, TRUE);
6521
6522   button18 = gtk_button_new_with_label ("button18");
6523   gtk_paned_pack2 (GTK_PANED (vpaned3), button18, TRUE, TRUE);
6524
6525   hbox3 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
6526   gtk_paned_pack2 (GTK_PANED (hpaned6), hbox3, TRUE, TRUE);
6527
6528   vpaned4 = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6529   gtk_box_pack_start (GTK_BOX (hbox3), vpaned4, TRUE, TRUE, 0);
6530
6531   button21 = gtk_button_new_with_label ("button21");
6532   gtk_paned_pack1 (GTK_PANED (vpaned4), button21, FALSE, TRUE);
6533
6534   button20 = gtk_button_new_with_label ("button20");
6535   gtk_paned_pack2 (GTK_PANED (vpaned4), button20, TRUE, TRUE);
6536
6537   vpaned5 = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6538   gtk_box_pack_start (GTK_BOX (hbox3), vpaned5, TRUE, TRUE, 0);
6539
6540   button23 = gtk_button_new_with_label ("button23");
6541   gtk_paned_pack1 (GTK_PANED (vpaned5), button23, FALSE, TRUE);
6542
6543   button22 = gtk_button_new_with_label ("button22");
6544   gtk_paned_pack2 (GTK_PANED (vpaned5), button22, TRUE, TRUE);
6545
6546   vpaned6 = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6547   gtk_box_pack_start (GTK_BOX (hbox3), vpaned6, TRUE, TRUE, 0);
6548
6549   button25 = gtk_button_new_with_label ("button25");
6550   gtk_paned_pack1 (GTK_PANED (vpaned6), button25, FALSE, TRUE);
6551
6552   button24 = gtk_button_new_with_label ("button24");
6553   gtk_paned_pack2 (GTK_PANED (vpaned6), button24, TRUE, TRUE);
6554
6555   return window4;
6556 }
6557
6558 static void
6559 create_paned_keyboard_navigation (GtkWidget *widget)
6560 {
6561   static GtkWidget *window1 = NULL;
6562   static GtkWidget *window2 = NULL;
6563   static GtkWidget *window3 = NULL;
6564   static GtkWidget *window4 = NULL;
6565
6566   if (window1 && 
6567      (gtk_widget_get_screen (window1) != gtk_widget_get_screen (widget)))
6568     {
6569       gtk_widget_destroy (window1);
6570       gtk_widget_destroy (window2);
6571       gtk_widget_destroy (window3);
6572       gtk_widget_destroy (window4);
6573     }
6574   
6575   if (!window1)
6576     {
6577       window1 = paned_keyboard_window1 (widget);
6578       g_signal_connect (window1, "destroy",
6579                         G_CALLBACK (gtk_widget_destroyed),
6580                         &window1);
6581     }
6582
6583   if (!window2)
6584     {
6585       window2 = paned_keyboard_window2 (widget);
6586       g_signal_connect (window2, "destroy",
6587                         G_CALLBACK (gtk_widget_destroyed),
6588                         &window2);
6589     }
6590
6591   if (!window3)
6592     {
6593       window3 = paned_keyboard_window3 (widget);
6594       g_signal_connect (window3, "destroy",
6595                         G_CALLBACK (gtk_widget_destroyed),
6596                         &window3);
6597     }
6598
6599   if (!window4)
6600     {
6601       window4 = paned_keyboard_window4 (widget);
6602       g_signal_connect (window4, "destroy",
6603                         G_CALLBACK (gtk_widget_destroyed),
6604                         &window4);
6605     }
6606
6607   if (gtk_widget_get_visible (window1))
6608     gtk_widget_destroy (GTK_WIDGET (window1));
6609   else
6610     gtk_widget_show_all (GTK_WIDGET (window1));
6611
6612   if (gtk_widget_get_visible (window2))
6613     gtk_widget_destroy (GTK_WIDGET (window2));
6614   else
6615     gtk_widget_show_all (GTK_WIDGET (window2));
6616
6617   if (gtk_widget_get_visible (window3))
6618     gtk_widget_destroy (GTK_WIDGET (window3));
6619   else
6620     gtk_widget_show_all (GTK_WIDGET (window3));
6621
6622   if (gtk_widget_get_visible (window4))
6623     gtk_widget_destroy (GTK_WIDGET (window4));
6624   else
6625     gtk_widget_show_all (GTK_WIDGET (window4));
6626 }
6627
6628
6629 /*
6630  * Shaped Windows
6631  */
6632
6633 typedef struct _cursoroffset {gint x,y;} CursorOffset;
6634
6635 static void
6636 shape_pressed (GtkWidget *widget, GdkEventButton *event)
6637 {
6638   CursorOffset *p;
6639
6640   /* ignore double and triple click */
6641   if (event->type != GDK_BUTTON_PRESS)
6642     return;
6643
6644   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
6645   p->x = (int) event->x;
6646   p->y = (int) event->y;
6647
6648   gtk_grab_add (widget);
6649   gdk_device_grab (gdk_event_get_device ((GdkEvent*)event),
6650                    gtk_widget_get_window (widget),
6651                    GDK_OWNERSHIP_NONE,
6652                    TRUE,
6653                    GDK_BUTTON_RELEASE_MASK |
6654                    GDK_BUTTON_MOTION_MASK |
6655                    GDK_POINTER_MOTION_HINT_MASK,
6656                    NULL,
6657                    event->time);
6658 }
6659
6660 static void
6661 shape_released (GtkWidget      *widget,
6662                 GdkEventButton *event)
6663 {
6664   gtk_grab_remove (widget);
6665   gdk_device_ungrab (gdk_event_get_device ((GdkEvent*)event), event->time);
6666 }
6667
6668 static void
6669 shape_motion (GtkWidget      *widget,
6670               GdkEventMotion *event)
6671 {
6672   gint xp, yp;
6673   CursorOffset * p;
6674   GdkModifierType mask;
6675
6676   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
6677
6678   /*
6679    * Can't use event->x / event->y here 
6680    * because I need absolute coordinates.
6681    */
6682   gdk_window_get_pointer (NULL, &xp, &yp, &mask);
6683   gtk_window_move (GTK_WINDOW (widget), xp  - p->x, yp  - p->y);
6684 }
6685
6686 GtkWidget *
6687 shape_create_icon (GdkScreen *screen,
6688                    char      *xpm_file,
6689                    gint       x,
6690                    gint       y,
6691                    gint       px,
6692                    gint       py,
6693                    gint       window_type)
6694 {
6695   GtkWidget *window;
6696   GtkWidget *image;
6697   GtkWidget *fixed;
6698   CursorOffset* icon_pos;
6699   cairo_surface_t *mask;
6700   cairo_region_t *mask_region;
6701   GdkPixbuf *pixbuf;
6702   cairo_t *cr;
6703
6704   /*
6705    * GDK_WINDOW_TOPLEVEL works also, giving you a title border
6706    */
6707   window = gtk_window_new (window_type);
6708   gtk_window_set_screen (GTK_WINDOW (window), screen);
6709   
6710   fixed = gtk_fixed_new ();
6711   gtk_widget_set_size_request (fixed, 100, 100);
6712   gtk_container_add (GTK_CONTAINER (window), fixed);
6713   gtk_widget_show (fixed);
6714   
6715   gtk_widget_set_events (window, 
6716                          gtk_widget_get_events (window) |
6717                          GDK_BUTTON_MOTION_MASK |
6718                          GDK_POINTER_MOTION_HINT_MASK |
6719                          GDK_BUTTON_PRESS_MASK);
6720
6721   gtk_widget_realize (window);
6722
6723   pixbuf = gdk_pixbuf_new_from_file (xpm_file, NULL);
6724   g_assert (pixbuf); /* FIXME: error handling */
6725
6726   mask = cairo_image_surface_create (CAIRO_FORMAT_A1,
6727                                      gdk_pixbuf_get_width (pixbuf),
6728                                      gdk_pixbuf_get_height (pixbuf));
6729   cr = cairo_create (mask);
6730   gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
6731   cairo_paint (cr);
6732   cairo_destroy (cr);
6733
6734   mask_region = gdk_cairo_region_create_from_surface (mask);
6735                                                   
6736   cairo_region_translate (mask_region, px, py);
6737
6738   image = gtk_image_new_from_pixbuf (pixbuf);
6739   gtk_fixed_put (GTK_FIXED (fixed), image, px,py);
6740   gtk_widget_show (image);
6741   
6742   gtk_widget_shape_combine_region (window, mask_region);
6743   
6744   cairo_region_destroy (mask_region);
6745   cairo_surface_destroy (mask);
6746   g_object_unref (pixbuf);
6747
6748   g_signal_connect (window, "button_press_event",
6749                     G_CALLBACK (shape_pressed), NULL);
6750   g_signal_connect (window, "button_release_event",
6751                     G_CALLBACK (shape_released), NULL);
6752   g_signal_connect (window, "motion_notify_event",
6753                     G_CALLBACK (shape_motion), NULL);
6754
6755   icon_pos = g_new (CursorOffset, 1);
6756   g_object_set_data (G_OBJECT (window), "cursor_offset", icon_pos);
6757
6758   gtk_window_move (GTK_WINDOW (window), x, y);
6759   gtk_widget_show (window);
6760   
6761   return window;
6762 }
6763
6764 void 
6765 create_shapes (GtkWidget *widget)
6766 {
6767   /* Variables used by the Drag/Drop and Shape Window demos */
6768   static GtkWidget *modeller = NULL;
6769   static GtkWidget *sheets = NULL;
6770   static GtkWidget *rings = NULL;
6771   static GtkWidget *with_region = NULL;
6772   GdkScreen *screen = gtk_widget_get_screen (widget);
6773   
6774   if (!(file_exists ("Modeller.xpm") &&
6775         file_exists ("FilesQueue.xpm") &&
6776         file_exists ("3DRings.xpm")))
6777     return;
6778   
6779
6780   if (!modeller)
6781     {
6782       modeller = shape_create_icon (screen, "Modeller.xpm",
6783                                     440, 140, 0,0, GTK_WINDOW_POPUP);
6784
6785       g_signal_connect (modeller, "destroy",
6786                         G_CALLBACK (gtk_widget_destroyed),
6787                         &modeller);
6788     }
6789   else
6790     gtk_widget_destroy (modeller);
6791
6792   if (!sheets)
6793     {
6794       sheets = shape_create_icon (screen, "FilesQueue.xpm",
6795                                   580, 170, 0,0, GTK_WINDOW_POPUP);
6796
6797       g_signal_connect (sheets, "destroy",
6798                         G_CALLBACK (gtk_widget_destroyed),
6799                         &sheets);
6800
6801     }
6802   else
6803     gtk_widget_destroy (sheets);
6804
6805   if (!rings)
6806     {
6807       rings = shape_create_icon (screen, "3DRings.xpm",
6808                                  460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
6809
6810       g_signal_connect (rings, "destroy",
6811                         G_CALLBACK (gtk_widget_destroyed),
6812                         &rings);
6813     }
6814   else
6815     gtk_widget_destroy (rings);
6816
6817   if (!with_region)
6818     {
6819       cairo_region_t *region;
6820       gint x, y;
6821       
6822       with_region = shape_create_icon (screen, "3DRings.xpm",
6823                                        460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
6824
6825       gtk_window_set_decorated (GTK_WINDOW (with_region), FALSE);
6826       
6827       g_signal_connect (with_region, "destroy",
6828                         G_CALLBACK (gtk_widget_destroyed),
6829                         &with_region);
6830
6831       /* reset shape from mask to a region */
6832       x = 0;
6833       y = 0;
6834       region = cairo_region_create ();
6835
6836       while (x < 460)
6837         {
6838           while (y < 270)
6839             {
6840               GdkRectangle rect;
6841               rect.x = x;
6842               rect.y = y;
6843               rect.width = 10;
6844               rect.height = 10;
6845
6846               cairo_region_union_rectangle (region, &rect);
6847               
6848               y += 20;
6849             }
6850           y = 0;
6851           x += 20;
6852         }
6853
6854       gdk_window_shape_combine_region (gtk_widget_get_window (with_region),
6855                                        region,
6856                                        0, 0);
6857     }
6858   else
6859     gtk_widget_destroy (with_region);
6860 }
6861
6862 /*
6863  * WM Hints demo
6864  */
6865
6866 void
6867 create_wmhints (GtkWidget *widget)
6868 {
6869   static GtkWidget *window = NULL;
6870   GtkWidget *label;
6871   GtkWidget *separator;
6872   GtkWidget *button;
6873   GtkWidget *box1;
6874   GtkWidget *box2;
6875   GdkWindow *gdk_window;
6876   GdkPixbuf *pixbuf;
6877   GList *list;
6878
6879   if (!window)
6880     {
6881       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6882
6883       gtk_window_set_screen (GTK_WINDOW (window),
6884                              gtk_widget_get_screen (widget));
6885       
6886       g_signal_connect (window, "destroy",
6887                         G_CALLBACK (gtk_widget_destroyed),
6888                         &window);
6889
6890       gtk_window_set_title (GTK_WINDOW (window), "WM Hints");
6891       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6892
6893       gtk_widget_realize (window);
6894
6895       gdk_window = gtk_widget_get_window (window);
6896
6897       pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **) openfile);
6898       list = g_list_prepend (NULL, pixbuf);
6899
6900       gdk_window_set_icon_list (gdk_window, list);
6901       
6902       g_list_free (list);
6903       g_object_unref (pixbuf);
6904
6905       gdk_window_set_icon_name (gdk_window, "WMHints Test Icon");
6906   
6907       gdk_window_set_decorations (gdk_window, GDK_DECOR_ALL | GDK_DECOR_MENU);
6908       gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_RESIZE);
6909       
6910       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
6911       gtk_container_add (GTK_CONTAINER (window), box1);
6912       gtk_widget_show (box1);
6913
6914       label = gtk_label_new ("Try iconizing me!");
6915       gtk_widget_set_size_request (label, 150, 50);
6916       gtk_box_pack_start (GTK_BOX (box1), label, TRUE, TRUE, 0);
6917       gtk_widget_show (label);
6918
6919
6920       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
6921       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
6922       gtk_widget_show (separator);
6923
6924
6925       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
6926       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6927       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
6928       gtk_widget_show (box2);
6929
6930
6931       button = gtk_button_new_with_label ("close");
6932
6933       g_signal_connect_swapped (button, "clicked",
6934                                 G_CALLBACK (gtk_widget_destroy),
6935                                 window);
6936
6937       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
6938       gtk_widget_set_can_default (button, TRUE);
6939       gtk_widget_grab_default (button);
6940       gtk_widget_show (button);
6941     }
6942
6943   if (!gtk_widget_get_visible (window))
6944     gtk_widget_show (window);
6945   else
6946     gtk_widget_destroy (window);
6947 }
6948
6949
6950 /*
6951  * Window state tracking
6952  */
6953
6954 static gint
6955 window_state_callback (GtkWidget *widget,
6956                        GdkEventWindowState *event,
6957                        gpointer data)
6958 {
6959   GtkWidget *label = data;
6960   gchar *msg;
6961
6962   msg = g_strconcat (gtk_window_get_title (GTK_WINDOW (widget)), ": ",
6963                      (event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) ?
6964                      "withdrawn" : "not withdrawn", ", ",
6965                      (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) ?
6966                      "iconified" : "not iconified", ", ",
6967                      (event->new_window_state & GDK_WINDOW_STATE_STICKY) ?
6968                      "sticky" : "not sticky", ", ",
6969                      (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) ?
6970                      "maximized" : "not maximized", ", ",
6971                      (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) ?
6972                      "fullscreen" : "not fullscreen",
6973                      (event->new_window_state & GDK_WINDOW_STATE_ABOVE) ?
6974                      "above" : "not above", ", ",
6975                      (event->new_window_state & GDK_WINDOW_STATE_BELOW) ?
6976                      "below" : "not below", ", ",
6977                      NULL);
6978   
6979   gtk_label_set_text (GTK_LABEL (label), msg);
6980
6981   g_free (msg);
6982
6983   return FALSE;
6984 }
6985
6986 static GtkWidget*
6987 tracking_label (GtkWidget *window)
6988 {
6989   GtkWidget *label;
6990   GtkWidget *hbox;
6991   GtkWidget *button;
6992
6993   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
6994
6995   g_signal_connect_object (hbox,
6996                            "destroy",
6997                            G_CALLBACK (gtk_widget_destroy),
6998                            window,
6999                            G_CONNECT_SWAPPED);
7000   
7001   label = gtk_label_new ("<no window state events received>");
7002   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
7003   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
7004   
7005   g_signal_connect (window,
7006                     "window_state_event",
7007                     G_CALLBACK (window_state_callback),
7008                     label);
7009
7010   button = gtk_button_new_with_label ("Deiconify");
7011   g_signal_connect_object (button,
7012                            "clicked",
7013                            G_CALLBACK (gtk_window_deiconify),
7014                            window,
7015                            G_CONNECT_SWAPPED);
7016   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7017
7018   button = gtk_button_new_with_label ("Iconify");
7019   g_signal_connect_object (button,
7020                            "clicked",
7021                            G_CALLBACK (gtk_window_iconify),
7022                            window,
7023                            G_CONNECT_SWAPPED);
7024   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7025
7026   button = gtk_button_new_with_label ("Fullscreen");
7027   g_signal_connect_object (button,
7028                            "clicked",
7029                            G_CALLBACK (gtk_window_fullscreen),
7030                            window,
7031                            G_CONNECT_SWAPPED);
7032   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7033
7034   button = gtk_button_new_with_label ("Unfullscreen");
7035   g_signal_connect_object (button,
7036                            "clicked",
7037                            G_CALLBACK (gtk_window_unfullscreen),
7038                            window,
7039                            G_CONNECT_SWAPPED);
7040   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7041   
7042   button = gtk_button_new_with_label ("Present");
7043   g_signal_connect_object (button,
7044                            "clicked",
7045                            G_CALLBACK (gtk_window_present),
7046                            window,
7047                            G_CONNECT_SWAPPED);
7048   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7049
7050   button = gtk_button_new_with_label ("Show");
7051   g_signal_connect_object (button,
7052                            "clicked",
7053                            G_CALLBACK (gtk_widget_show),
7054                            window,
7055                            G_CONNECT_SWAPPED);
7056   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7057   
7058   gtk_widget_show_all (hbox);
7059   
7060   return hbox;
7061 }
7062
7063 void
7064 keep_window_above (GtkToggleButton *togglebutton, gpointer data)
7065 {
7066   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
7067
7068   gtk_window_set_keep_above (GTK_WINDOW (data),
7069                              gtk_toggle_button_get_active (togglebutton));
7070
7071   if (gtk_toggle_button_get_active (togglebutton))
7072     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
7073 }
7074
7075 void
7076 keep_window_below (GtkToggleButton *togglebutton, gpointer data)
7077 {
7078   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
7079
7080   gtk_window_set_keep_below (GTK_WINDOW (data),
7081                              gtk_toggle_button_get_active (togglebutton));
7082
7083   if (gtk_toggle_button_get_active (togglebutton))
7084     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
7085 }
7086
7087
7088 static GtkWidget*
7089 get_state_controls (GtkWidget *window)
7090 {
7091   GtkWidget *vbox;
7092   GtkWidget *button;
7093   GtkWidget *button_above;
7094   GtkWidget *button_below;
7095
7096   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
7097   
7098   button = gtk_button_new_with_label ("Stick");
7099   g_signal_connect_object (button,
7100                            "clicked",
7101                            G_CALLBACK (gtk_window_stick),
7102                            window,
7103                            G_CONNECT_SWAPPED);
7104   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7105
7106   button = gtk_button_new_with_label ("Unstick");
7107   g_signal_connect_object (button,
7108                            "clicked",
7109                            G_CALLBACK (gtk_window_unstick),
7110                            window,
7111                            G_CONNECT_SWAPPED);
7112   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7113   
7114   button = gtk_button_new_with_label ("Maximize");
7115   g_signal_connect_object (button,
7116                            "clicked",
7117                            G_CALLBACK (gtk_window_maximize),
7118                            window,
7119                            G_CONNECT_SWAPPED);
7120   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7121
7122   button = gtk_button_new_with_label ("Unmaximize");
7123   g_signal_connect_object (button,
7124                            "clicked",
7125                            G_CALLBACK (gtk_window_unmaximize),
7126                            window,
7127                            G_CONNECT_SWAPPED);
7128   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7129
7130   button = gtk_button_new_with_label ("Iconify");
7131   g_signal_connect_object (button,
7132                            "clicked",
7133                            G_CALLBACK (gtk_window_iconify),
7134                            window,
7135                            G_CONNECT_SWAPPED);
7136   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7137
7138   button = gtk_button_new_with_label ("Fullscreen");
7139   g_signal_connect_object (button,
7140                            "clicked",
7141                            G_CALLBACK (gtk_window_fullscreen),
7142                            window,
7143                            G_CONNECT_SWAPPED);
7144   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7145
7146   button = gtk_button_new_with_label ("Unfullscreen");
7147   g_signal_connect_object (button,
7148                            "clicked",
7149                            G_CALLBACK (gtk_window_unfullscreen),
7150                            window,
7151                            G_CONNECT_SWAPPED);
7152   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7153
7154   button_above = gtk_toggle_button_new_with_label ("Keep above");
7155   g_signal_connect (button_above,
7156                     "toggled",
7157                     G_CALLBACK (keep_window_above),
7158                     window);
7159   gtk_box_pack_start (GTK_BOX (vbox), button_above, FALSE, FALSE, 0);
7160
7161   button_below = gtk_toggle_button_new_with_label ("Keep below");
7162   g_signal_connect (button_below,
7163                     "toggled",
7164                     G_CALLBACK (keep_window_below),
7165                     window);
7166   gtk_box_pack_start (GTK_BOX (vbox), button_below, FALSE, FALSE, 0);
7167
7168   g_object_set_data (G_OBJECT (button_above), "radio", button_below);
7169   g_object_set_data (G_OBJECT (button_below), "radio", button_above);
7170
7171   button = gtk_button_new_with_label ("Hide (withdraw)");
7172   g_signal_connect_object (button,
7173                            "clicked",
7174                            G_CALLBACK (gtk_widget_hide),
7175                            window,
7176                            G_CONNECT_SWAPPED);
7177   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7178   
7179   gtk_widget_show_all (vbox);
7180
7181   return vbox;
7182 }
7183
7184 void
7185 create_window_states (GtkWidget *widget)
7186 {
7187   static GtkWidget *window = NULL;
7188   GtkWidget *label;
7189   GtkWidget *box1;
7190   GtkWidget *iconified;
7191   GtkWidget *normal;
7192   GtkWidget *controls;
7193
7194   if (!window)
7195     {
7196       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7197       gtk_window_set_screen (GTK_WINDOW (window),
7198                              gtk_widget_get_screen (widget));
7199
7200       g_signal_connect (window, "destroy",
7201                         G_CALLBACK (gtk_widget_destroyed),
7202                         &window);
7203
7204       gtk_window_set_title (GTK_WINDOW (window), "Window states");
7205       
7206       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
7207       gtk_container_add (GTK_CONTAINER (window), box1);
7208
7209       iconified = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7210
7211       gtk_window_set_screen (GTK_WINDOW (iconified),
7212                              gtk_widget_get_screen (widget));
7213       
7214       g_signal_connect_object (iconified, "destroy",
7215                                G_CALLBACK (gtk_widget_destroy),
7216                                window,
7217                                G_CONNECT_SWAPPED);
7218       gtk_window_iconify (GTK_WINDOW (iconified));
7219       gtk_window_set_title (GTK_WINDOW (iconified), "Iconified initially");
7220       controls = get_state_controls (iconified);
7221       gtk_container_add (GTK_CONTAINER (iconified), controls);
7222       
7223       normal = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7224
7225       gtk_window_set_screen (GTK_WINDOW (normal),
7226                              gtk_widget_get_screen (widget));
7227       
7228       g_signal_connect_object (normal, "destroy",
7229                                G_CALLBACK (gtk_widget_destroy),
7230                                window,
7231                                G_CONNECT_SWAPPED);
7232       
7233       gtk_window_set_title (GTK_WINDOW (normal), "Deiconified initially");
7234       controls = get_state_controls (normal);
7235       gtk_container_add (GTK_CONTAINER (normal), controls);
7236       
7237       label = tracking_label (iconified);
7238       gtk_container_add (GTK_CONTAINER (box1), label);
7239
7240       label = tracking_label (normal);
7241       gtk_container_add (GTK_CONTAINER (box1), label);
7242
7243       gtk_widget_show_all (iconified);
7244       gtk_widget_show_all (normal);
7245       gtk_widget_show_all (box1);
7246     }
7247
7248   if (!gtk_widget_get_visible (window))
7249     gtk_widget_show (window);
7250   else
7251     gtk_widget_destroy (window);
7252 }
7253
7254 /*
7255  * Window sizing
7256  */
7257
7258 static gint
7259 configure_event_callback (GtkWidget *widget,
7260                           GdkEventConfigure *event,
7261                           gpointer data)
7262 {
7263   GtkWidget *label = data;
7264   gchar *msg;
7265   gint x, y;
7266   
7267   gtk_window_get_position (GTK_WINDOW (widget), &x, &y);
7268   
7269   msg = g_strdup_printf ("event: %d,%d  %d x %d\n"
7270                          "position: %d, %d",
7271                          event->x, event->y, event->width, event->height,
7272                          x, y);
7273   
7274   gtk_label_set_text (GTK_LABEL (label), msg);
7275
7276   g_free (msg);
7277
7278   return FALSE;
7279 }
7280
7281 static void
7282 get_ints (GtkWidget *window,
7283           gint      *a,
7284           gint      *b)
7285 {
7286   GtkWidget *spin1;
7287   GtkWidget *spin2;
7288
7289   spin1 = g_object_get_data (G_OBJECT (window), "spin1");
7290   spin2 = g_object_get_data (G_OBJECT (window), "spin2");
7291
7292   *a = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin1));
7293   *b = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin2));
7294 }
7295
7296 static void
7297 set_size_callback (GtkWidget *widget,
7298                    gpointer   data)
7299 {
7300   gint w, h;
7301   
7302   get_ints (data, &w, &h);
7303
7304   gtk_window_resize (GTK_WINDOW (g_object_get_data (data, "target")), w, h);
7305 }
7306
7307 static void
7308 unset_default_size_callback (GtkWidget *widget,
7309                              gpointer   data)
7310 {
7311   gtk_window_set_default_size (g_object_get_data (data, "target"),
7312                                -1, -1);
7313 }
7314
7315 static void
7316 set_default_size_callback (GtkWidget *widget,
7317                            gpointer   data)
7318 {
7319   gint w, h;
7320   
7321   get_ints (data, &w, &h);
7322
7323   gtk_window_set_default_size (g_object_get_data (data, "target"),
7324                                w, h);
7325 }
7326
7327 static void
7328 unset_size_request_callback (GtkWidget *widget,
7329                              gpointer   data)
7330 {
7331   gtk_widget_set_size_request (g_object_get_data (data, "target"),
7332                                -1, -1);
7333 }
7334
7335 static void
7336 set_size_request_callback (GtkWidget *widget,
7337                            gpointer   data)
7338 {
7339   gint w, h;
7340   
7341   get_ints (data, &w, &h);
7342
7343   gtk_widget_set_size_request (g_object_get_data (data, "target"),
7344                                w, h);
7345 }
7346
7347 static void
7348 set_location_callback (GtkWidget *widget,
7349                        gpointer   data)
7350 {
7351   gint x, y;
7352   
7353   get_ints (data, &x, &y);
7354
7355   gtk_window_move (g_object_get_data (data, "target"), x, y);
7356 }
7357
7358 static void
7359 move_to_position_callback (GtkWidget *widget,
7360                            gpointer   data)
7361 {
7362   gint x, y;
7363   GtkWindow *window;
7364
7365   window = g_object_get_data (data, "target");
7366   
7367   gtk_window_get_position (window, &x, &y);
7368
7369   gtk_window_move (window, x, y);
7370 }
7371
7372 static void
7373 set_geometry_callback (GtkWidget *entry,
7374                        gpointer   data)
7375 {
7376   gchar *text;
7377   GtkWindow *target;
7378
7379   target = GTK_WINDOW (g_object_get_data (G_OBJECT (data), "target"));
7380   
7381   text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
7382
7383   if (!gtk_window_parse_geometry (target, text))
7384     g_print ("Bad geometry string '%s'\n", text);
7385
7386   g_free (text);
7387 }
7388
7389 static void
7390 resizable_callback (GtkWidget *widget,
7391                      gpointer   data)
7392 {
7393   g_object_set (g_object_get_data (data, "target"),
7394                 "resizable", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)),
7395                 NULL);
7396 }
7397
7398 static void
7399 gravity_selected (GtkWidget *widget,
7400                   gpointer   data)
7401 {
7402   gtk_window_set_gravity (GTK_WINDOW (g_object_get_data (data, "target")),
7403                           gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) + GDK_GRAVITY_NORTH_WEST);
7404 }
7405
7406 static void
7407 pos_selected (GtkWidget *widget,
7408               gpointer   data)
7409 {
7410   gtk_window_set_position (GTK_WINDOW (g_object_get_data (data, "target")),
7411                            gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) + GTK_WIN_POS_NONE);
7412 }
7413
7414 static void
7415 move_gravity_window_to_current_position (GtkWidget *widget,
7416                                          gpointer   data)
7417 {
7418   gint x, y;
7419   GtkWindow *window;
7420
7421   window = GTK_WINDOW (data);    
7422   
7423   gtk_window_get_position (window, &x, &y);
7424
7425   gtk_window_move (window, x, y);
7426 }
7427
7428 static void
7429 get_screen_corner (GtkWindow *window,
7430                    gint      *x,
7431                    gint      *y)
7432 {
7433   int w, h;
7434   GdkScreen * screen = gtk_window_get_screen (window);
7435   
7436   gtk_window_get_size (GTK_WINDOW (window), &w, &h);
7437
7438   switch (gtk_window_get_gravity (window))
7439     {
7440     case GDK_GRAVITY_SOUTH_EAST:
7441       *x = gdk_screen_get_width (screen) - w;
7442       *y = gdk_screen_get_height (screen) - h;
7443       break;
7444
7445     case GDK_GRAVITY_NORTH_EAST:
7446       *x = gdk_screen_get_width (screen) - w;
7447       *y = 0;
7448       break;
7449
7450     case GDK_GRAVITY_SOUTH_WEST:
7451       *x = 0;
7452       *y = gdk_screen_get_height (screen) - h;
7453       break;
7454
7455     case GDK_GRAVITY_NORTH_WEST:
7456       *x = 0;
7457       *y = 0;
7458       break;
7459       
7460     case GDK_GRAVITY_SOUTH:
7461       *x = (gdk_screen_get_width (screen) - w) / 2;
7462       *y = gdk_screen_get_height (screen) - h;
7463       break;
7464
7465     case GDK_GRAVITY_NORTH:
7466       *x = (gdk_screen_get_width (screen) - w) / 2;
7467       *y = 0;
7468       break;
7469
7470     case GDK_GRAVITY_WEST:
7471       *x = 0;
7472       *y = (gdk_screen_get_height (screen) - h) / 2;
7473       break;
7474
7475     case GDK_GRAVITY_EAST:
7476       *x = gdk_screen_get_width (screen) - w;
7477       *y = (gdk_screen_get_height (screen) - h) / 2;
7478       break;
7479
7480     case GDK_GRAVITY_CENTER:
7481       *x = (gdk_screen_get_width (screen) - w) / 2;
7482       *y = (gdk_screen_get_height (screen) - h) / 2;
7483       break;
7484
7485     case GDK_GRAVITY_STATIC:
7486       /* pick some random numbers */
7487       *x = 350;
7488       *y = 350;
7489       break;
7490
7491     default:
7492       g_assert_not_reached ();
7493       break;
7494     }
7495 }
7496
7497 static void
7498 move_gravity_window_to_starting_position (GtkWidget *widget,
7499                                           gpointer   data)
7500 {
7501   gint x, y;
7502   GtkWindow *window;
7503
7504   window = GTK_WINDOW (data);    
7505   
7506   get_screen_corner (window,
7507                      &x, &y);
7508   
7509   gtk_window_move (window, x, y);
7510 }
7511
7512 static GtkWidget*
7513 make_gravity_window (GtkWidget   *destroy_with,
7514                      GdkGravity   gravity,
7515                      const gchar *title)
7516 {
7517   GtkWidget *window;
7518   GtkWidget *button;
7519   GtkWidget *vbox;
7520   int x, y;
7521   
7522   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7523
7524   gtk_window_set_screen (GTK_WINDOW (window),
7525                          gtk_widget_get_screen (destroy_with));
7526
7527   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
7528   gtk_widget_show (vbox);
7529   
7530   gtk_container_add (GTK_CONTAINER (window), vbox);
7531   gtk_window_set_title (GTK_WINDOW (window), title);
7532   gtk_window_set_gravity (GTK_WINDOW (window), gravity);
7533
7534   g_signal_connect_object (destroy_with,
7535                            "destroy",
7536                            G_CALLBACK (gtk_widget_destroy),
7537                            window,
7538                            G_CONNECT_SWAPPED);
7539
7540   
7541   button = gtk_button_new_with_mnemonic ("_Move to current position");
7542
7543   g_signal_connect (button, "clicked",
7544                     G_CALLBACK (move_gravity_window_to_current_position),
7545                     window);
7546
7547   gtk_container_add (GTK_CONTAINER (vbox), button);
7548   gtk_widget_show (button);
7549
7550   button = gtk_button_new_with_mnemonic ("Move to _starting position");
7551
7552   g_signal_connect (button, "clicked",
7553                     G_CALLBACK (move_gravity_window_to_starting_position),
7554                     window);
7555
7556   gtk_container_add (GTK_CONTAINER (vbox), button);
7557   gtk_widget_show (button);
7558   
7559   /* Pretend this is the result of --geometry.
7560    * DO NOT COPY THIS CODE unless you are setting --geometry results,
7561    * and in that case you probably should just use gtk_window_parse_geometry().
7562    * AGAIN, DO NOT SET GDK_HINT_USER_POS! It violates the ICCCM unless
7563    * you are parsing --geometry or equivalent.
7564    */
7565   gtk_window_set_geometry_hints (GTK_WINDOW (window),
7566                                  NULL, NULL,
7567                                  GDK_HINT_USER_POS);
7568
7569   gtk_window_set_default_size (GTK_WINDOW (window),
7570                                200, 200);
7571
7572   get_screen_corner (GTK_WINDOW (window), &x, &y);
7573   
7574   gtk_window_move (GTK_WINDOW (window),
7575                    x, y);
7576   
7577   return window;
7578 }
7579
7580 static void
7581 do_gravity_test (GtkWidget *widget,
7582                  gpointer   data)
7583 {
7584   GtkWidget *destroy_with = data;
7585   GtkWidget *window;
7586   
7587   /* We put a window at each gravity point on the screen. */
7588   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_WEST,
7589                                 "NorthWest");
7590   gtk_widget_show (window);
7591   
7592   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_EAST,
7593                                 "SouthEast");
7594   gtk_widget_show (window);
7595
7596   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_EAST,
7597                                 "NorthEast");
7598   gtk_widget_show (window);
7599
7600   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_WEST,
7601                                 "SouthWest");
7602   gtk_widget_show (window);
7603
7604   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH,
7605                                 "South");
7606   gtk_widget_show (window);
7607
7608   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH,
7609                                 "North");
7610   gtk_widget_show (window);
7611
7612   
7613   window = make_gravity_window (destroy_with, GDK_GRAVITY_WEST,
7614                                 "West");
7615   gtk_widget_show (window);
7616
7617     
7618   window = make_gravity_window (destroy_with, GDK_GRAVITY_EAST,
7619                                 "East");
7620   gtk_widget_show (window);
7621
7622   window = make_gravity_window (destroy_with, GDK_GRAVITY_CENTER,
7623                                 "Center");
7624   gtk_widget_show (window);
7625
7626   window = make_gravity_window (destroy_with, GDK_GRAVITY_STATIC,
7627                                 "Static");
7628   gtk_widget_show (window);
7629 }
7630
7631 static GtkWidget*
7632 window_controls (GtkWidget *window)
7633 {
7634   GtkWidget *control_window;
7635   GtkWidget *label;
7636   GtkWidget *vbox;
7637   GtkWidget *button;
7638   GtkWidget *spin;
7639   GtkAdjustment *adjustment;
7640   GtkWidget *entry;
7641   GtkWidget *om;
7642   gint i;
7643   
7644   control_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7645
7646   gtk_window_set_screen (GTK_WINDOW (control_window),
7647                          gtk_widget_get_screen (window));
7648
7649   gtk_window_set_title (GTK_WINDOW (control_window), "Size controls");
7650   
7651   g_object_set_data (G_OBJECT (control_window),
7652                      "target",
7653                      window);
7654   
7655   g_signal_connect_object (control_window,
7656                            "destroy",
7657                            G_CALLBACK (gtk_widget_destroy),
7658                            window,
7659                            G_CONNECT_SWAPPED);
7660
7661   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
7662   
7663   gtk_container_add (GTK_CONTAINER (control_window), vbox);
7664   
7665   label = gtk_label_new ("<no configure events>");
7666   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
7667   
7668   g_signal_connect (window,
7669                     "configure_event",
7670                     G_CALLBACK (configure_event_callback),
7671                     label);
7672
7673   adjustment = gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0, 5.0, 0.0);
7674   spin = gtk_spin_button_new (adjustment, 0, 0);
7675
7676   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
7677
7678   g_object_set_data (G_OBJECT (control_window), "spin1", spin);
7679
7680   adjustment = gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0, 5.0, 0.0);
7681   spin = gtk_spin_button_new (adjustment, 0, 0);
7682
7683   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
7684
7685   g_object_set_data (G_OBJECT (control_window), "spin2", spin);
7686
7687   entry = gtk_entry_new ();
7688   gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
7689
7690   g_signal_connect (entry, "changed",
7691                     G_CALLBACK (set_geometry_callback),
7692                     control_window);
7693
7694   button = gtk_button_new_with_label ("Show gravity test windows");
7695   g_signal_connect_swapped (button,
7696                             "clicked",
7697                             G_CALLBACK (do_gravity_test),
7698                             control_window);
7699   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7700
7701   button = gtk_button_new_with_label ("Reshow with initial size");
7702   g_signal_connect_object (button,
7703                            "clicked",
7704                            G_CALLBACK (gtk_window_reshow_with_initial_size),
7705                            window,
7706                            G_CONNECT_SWAPPED);
7707   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7708   
7709   button = gtk_button_new_with_label ("Queue resize");
7710   g_signal_connect_object (button,
7711                            "clicked",
7712                            G_CALLBACK (gtk_widget_queue_resize),
7713                            window,
7714                            G_CONNECT_SWAPPED);
7715   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7716   
7717   button = gtk_button_new_with_label ("Resize");
7718   g_signal_connect (button,
7719                     "clicked",
7720                     G_CALLBACK (set_size_callback),
7721                     control_window);
7722   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7723
7724   button = gtk_button_new_with_label ("Set default size");
7725   g_signal_connect (button,
7726                     "clicked",
7727                     G_CALLBACK (set_default_size_callback),
7728                     control_window);
7729   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7730
7731   button = gtk_button_new_with_label ("Unset default size");
7732   g_signal_connect (button,
7733                     "clicked",
7734                     G_CALLBACK (unset_default_size_callback),
7735                     control_window);
7736   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7737   
7738   button = gtk_button_new_with_label ("Set size request");
7739   g_signal_connect (button,
7740                     "clicked",
7741                     G_CALLBACK (set_size_request_callback),
7742                     control_window);
7743   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7744
7745   button = gtk_button_new_with_label ("Unset size request");
7746   g_signal_connect (button,
7747                     "clicked",
7748                     G_CALLBACK (unset_size_request_callback),
7749                     control_window);
7750   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7751   
7752   button = gtk_button_new_with_label ("Move");
7753   g_signal_connect (button,
7754                     "clicked",
7755                     G_CALLBACK (set_location_callback),
7756                     control_window);
7757   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7758
7759   button = gtk_button_new_with_label ("Move to current position");
7760   g_signal_connect (button,
7761                     "clicked",
7762                     G_CALLBACK (move_to_position_callback),
7763                     control_window);
7764   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7765
7766   button = gtk_check_button_new_with_label ("Allow resize");
7767   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
7768   g_signal_connect (button,
7769                     "toggled",
7770                     G_CALLBACK (resizable_callback),
7771                     control_window);
7772   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7773   
7774   button = gtk_button_new_with_mnemonic ("_Show");
7775   g_signal_connect_object (button,
7776                            "clicked",
7777                            G_CALLBACK (gtk_widget_show),
7778                            window,
7779                            G_CONNECT_SWAPPED);
7780   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7781
7782   button = gtk_button_new_with_mnemonic ("_Hide");
7783   g_signal_connect_object (button,
7784                            "clicked",
7785                            G_CALLBACK (gtk_widget_hide),
7786                            window,
7787                            G_CONNECT_SWAPPED);
7788   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7789
7790   om = gtk_combo_box_text_new ();
7791   i = 0;
7792   while (i < 10)
7793     {
7794       static gchar *names[] = {
7795         "GDK_GRAVITY_NORTH_WEST",
7796         "GDK_GRAVITY_NORTH",
7797         "GDK_GRAVITY_NORTH_EAST",
7798         "GDK_GRAVITY_WEST",
7799         "GDK_GRAVITY_CENTER",
7800         "GDK_GRAVITY_EAST",
7801         "GDK_GRAVITY_SOUTH_WEST",
7802         "GDK_GRAVITY_SOUTH",
7803         "GDK_GRAVITY_SOUTH_EAST",
7804         "GDK_GRAVITY_STATIC",
7805         NULL
7806       };
7807
7808       g_assert (names[i]);
7809       gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (om), names[i]);
7810
7811       ++i;
7812     }
7813   
7814   g_signal_connect (om,
7815                     "changed",
7816                     G_CALLBACK (gravity_selected),
7817                     control_window);
7818
7819   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
7820
7821
7822   om = gtk_combo_box_text_new ();
7823   i = 0;
7824   while (i < 5)
7825     {
7826       static gchar *names[] = {
7827         "GTK_WIN_POS_NONE",
7828         "GTK_WIN_POS_CENTER",
7829         "GTK_WIN_POS_MOUSE",
7830         "GTK_WIN_POS_CENTER_ALWAYS",
7831         "GTK_WIN_POS_CENTER_ON_PARENT",
7832         NULL
7833       };
7834
7835       g_assert (names[i]);
7836       gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (om), names[i]);
7837
7838       ++i;
7839     }
7840
7841   g_signal_connect (om,
7842                     "changed",
7843                     G_CALLBACK (pos_selected),
7844                     control_window);
7845
7846   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
7847   
7848   gtk_widget_show_all (vbox);
7849   
7850   return control_window;
7851 }
7852
7853 void
7854 create_window_sizing (GtkWidget *widget)
7855 {
7856   static GtkWidget *window = NULL;
7857   static GtkWidget *target_window = NULL;
7858
7859   if (!target_window)
7860     {
7861       GtkWidget *label;
7862       
7863       target_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7864       gtk_window_set_screen (GTK_WINDOW (target_window),
7865                              gtk_widget_get_screen (widget));
7866       label = gtk_label_new (NULL);
7867       gtk_label_set_markup (GTK_LABEL (label), "<span foreground=\"purple\"><big>Window being resized</big></span>\nBlah blah blah blah\nblah blah blah\nblah blah blah blah blah");
7868       gtk_container_add (GTK_CONTAINER (target_window), label);
7869       gtk_widget_show (label);
7870       
7871       g_signal_connect (target_window, "destroy",
7872                         G_CALLBACK (gtk_widget_destroyed),
7873                         &target_window);
7874
7875       window = window_controls (target_window);
7876       
7877       g_signal_connect (window, "destroy",
7878                         G_CALLBACK (gtk_widget_destroyed),
7879                         &window);
7880       
7881       gtk_window_set_title (GTK_WINDOW (target_window), "Window to size");
7882     }
7883
7884   /* don't show target window by default, we want to allow testing
7885    * of behavior on first show.
7886    */
7887   
7888   if (!gtk_widget_get_visible (window))
7889     gtk_widget_show (window);
7890   else
7891     gtk_widget_destroy (window);
7892 }
7893
7894 /*
7895  * GtkProgressBar
7896  */
7897
7898 typedef struct _ProgressData {
7899   GtkWidget *window;
7900   GtkWidget *pbar;
7901   GtkWidget *block_spin;
7902   GtkWidget *x_align_spin;
7903   GtkWidget *y_align_spin;
7904   GtkWidget *step_spin;
7905   GtkWidget *act_blocks_spin;
7906   GtkWidget *label;
7907   GtkWidget *omenu1;
7908   GtkWidget *elmenu;
7909   GtkWidget *omenu2;
7910   GtkWidget *entry;
7911   int timer;
7912   gboolean activity;
7913 } ProgressData;
7914
7915 gboolean
7916 progress_timeout (gpointer data)
7917 {
7918   ProgressData *pdata = data;
7919   gdouble new_val;
7920   gchar *text;
7921
7922   if (pdata->activity)
7923     {
7924       gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pdata->pbar));
7925
7926       text = g_strdup_printf ("%s", "???");
7927     }
7928   else
7929     {
7930       new_val = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (pdata->pbar)) + 0.01;
7931       if (new_val > 1.00)
7932         new_val = 0.00;
7933       gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pdata->pbar), new_val);
7934
7935       text = g_strdup_printf ("%.0f%%", 100 * new_val);
7936     }
7937
7938   gtk_label_set_text (GTK_LABEL (pdata->label), text);
7939   g_free (text);
7940
7941   return TRUE;
7942 }
7943
7944 static void
7945 destroy_progress (GtkWidget     *widget,
7946                   ProgressData **pdata)
7947 {
7948   if ((*pdata)->timer)
7949     {
7950       g_source_remove ((*pdata)->timer);
7951       (*pdata)->timer = 0;
7952     }
7953   (*pdata)->window = NULL;
7954   g_free (*pdata);
7955   *pdata = NULL;
7956 }
7957
7958 static void
7959 progressbar_toggle_orientation (GtkWidget *widget, gpointer data)
7960 {
7961   ProgressData *pdata;
7962   gint i;
7963
7964   pdata = (ProgressData *) data;
7965
7966   if (!gtk_widget_get_mapped (widget))
7967     return;
7968
7969   i = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
7970
7971   if (i == 0 || i == 1)
7972     gtk_orientable_set_orientation (GTK_ORIENTABLE (pdata->pbar), GTK_ORIENTATION_HORIZONTAL);
7973   else
7974     gtk_orientable_set_orientation (GTK_ORIENTABLE (pdata->pbar), GTK_ORIENTATION_VERTICAL);
7975  
7976   if (i == 1 || i == 2)
7977     gtk_progress_bar_set_inverted (GTK_PROGRESS_BAR (pdata->pbar), TRUE);
7978   else
7979     gtk_progress_bar_set_inverted (GTK_PROGRESS_BAR (pdata->pbar), FALSE);
7980 }
7981
7982 static void
7983 toggle_show_text (GtkWidget *widget, ProgressData *pdata)
7984 {
7985   gboolean active;
7986
7987   active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
7988   gtk_progress_bar_set_show_text (GTK_PROGRESS_BAR (pdata->pbar), active);
7989 }
7990
7991 static void
7992 progressbar_toggle_ellipsize (GtkWidget *widget,
7993                               gpointer   data)
7994 {
7995   ProgressData *pdata = data;
7996   if (gtk_widget_is_drawable (widget))
7997     {
7998       gint i = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
7999       gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (pdata->pbar), i);
8000     }
8001 }
8002
8003 static void
8004 toggle_activity_mode (GtkWidget *widget, ProgressData *pdata)
8005 {
8006   pdata->activity = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
8007 }
8008
8009 static void
8010 toggle_running (GtkWidget *widget, ProgressData *pdata)
8011 {
8012   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
8013     {
8014       if (pdata->timer == 0)
8015         pdata->timer = g_timeout_add (100, (GSourceFunc)progress_timeout, pdata);
8016     }
8017   else
8018     {
8019       if (pdata->timer != 0)
8020         {
8021           g_source_remove (pdata->timer);
8022           pdata->timer = 0;
8023         }
8024     }
8025 }
8026
8027 static void
8028 entry_changed (GtkWidget *widget, ProgressData *pdata)
8029 {
8030   gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata->pbar),
8031                           gtk_entry_get_text (GTK_ENTRY (pdata->entry)));
8032 }
8033
8034 void
8035 create_progress_bar (GtkWidget *widget)
8036 {
8037   GtkWidget *action_area, *content_area;
8038   GtkWidget *button;
8039   GtkWidget *vbox;
8040   GtkWidget *vbox2;
8041   GtkWidget *hbox;
8042   GtkWidget *check;
8043   GtkWidget *frame;
8044   GtkWidget *grid;
8045   GtkWidget *label;
8046   GtkWidget *align;
8047   static ProgressData *pdata = NULL;
8048
8049   static gchar *items1[] =
8050   {
8051     "Left-Right",
8052     "Right-Left",
8053     "Bottom-Top",
8054     "Top-Bottom"
8055   };
8056
8057     static char *ellipsize_items[] = {
8058     "None",     // PANGO_ELLIPSIZE_NONE,
8059     "Start",    // PANGO_ELLIPSIZE_START,
8060     "Middle",   // PANGO_ELLIPSIZE_MIDDLE,
8061     "End",      // PANGO_ELLIPSIZE_END
8062   };
8063   
8064   if (!pdata)
8065     pdata = g_new0 (ProgressData, 1);
8066
8067   if (!pdata->window)
8068     {
8069       pdata->window = gtk_dialog_new ();
8070
8071       gtk_window_set_screen (GTK_WINDOW (pdata->window),
8072                              gtk_widget_get_screen (widget));
8073
8074       gtk_window_set_resizable (GTK_WINDOW (pdata->window), TRUE);
8075
8076       g_signal_connect (pdata->window, "destroy",
8077                         G_CALLBACK (destroy_progress),
8078                         &pdata);
8079       pdata->timer = 0;
8080
8081       content_area = gtk_dialog_get_content_area (GTK_DIALOG (pdata->window));
8082       action_area = gtk_dialog_get_action_area (GTK_DIALOG (pdata->window));
8083
8084       gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
8085       gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);
8086
8087       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
8088       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
8089       gtk_box_pack_start (GTK_BOX (content_area), vbox, FALSE, TRUE, 0);
8090
8091       frame = gtk_frame_new ("Progress");
8092       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
8093
8094       vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
8095       gtk_container_add (GTK_CONTAINER (frame), vbox2);
8096
8097       align = gtk_alignment_new (0.5, 0.5, 0, 0);
8098       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
8099
8100       pdata->pbar = gtk_progress_bar_new ();
8101       gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (pdata->pbar),
8102                                       PANGO_ELLIPSIZE_MIDDLE);
8103
8104       gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
8105
8106       align = gtk_alignment_new (0.5, 0.5, 0, 0);
8107       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
8108
8109       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
8110       gtk_container_add (GTK_CONTAINER (align), hbox);
8111       label = gtk_label_new ("Label updated by user :"); 
8112       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
8113       pdata->label = gtk_label_new ("");
8114       gtk_box_pack_start (GTK_BOX (hbox), pdata->label, FALSE, TRUE, 0);
8115
8116       frame = gtk_frame_new ("Options");
8117       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
8118
8119       vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
8120       gtk_container_add (GTK_CONTAINER (frame), vbox2);
8121
8122       grid = gtk_grid_new ();
8123       gtk_grid_set_row_spacing (GTK_GRID (grid), 10);
8124       gtk_grid_set_column_spacing (GTK_GRID (grid), 10);
8125       gtk_box_pack_start (GTK_BOX (vbox2), grid, FALSE, TRUE, 0);
8126
8127       label = gtk_label_new ("Orientation :");
8128       gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
8129       gtk_widget_set_halign (label, GTK_ALIGN_START);
8130       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
8131
8132       pdata->omenu1 = build_option_menu (items1, 4, 0,
8133                                          progressbar_toggle_orientation,
8134                                          pdata);
8135       gtk_grid_attach (GTK_GRID (grid), pdata->omenu1, 1, 0, 1, 1);
8136       
8137       check = gtk_check_button_new_with_label ("Running");
8138       g_signal_connect (check, "toggled",
8139                         G_CALLBACK (toggle_running),
8140                         pdata);
8141       gtk_grid_attach (GTK_GRID (grid), check, 0, 1, 2, 1);
8142       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
8143
8144       check = gtk_check_button_new_with_label ("Show text");
8145       g_signal_connect (check, "clicked",
8146                         G_CALLBACK (toggle_show_text),
8147                         pdata);
8148       gtk_grid_attach (GTK_GRID (grid), check, 0, 2, 1, 1);
8149
8150       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
8151       gtk_grid_attach (GTK_GRID (grid), hbox, 1, 2, 1, 1);
8152
8153       label = gtk_label_new ("Text: ");
8154       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
8155
8156       pdata->entry = gtk_entry_new ();
8157       gtk_widget_set_hexpand (pdata->entry, TRUE);
8158       g_signal_connect (pdata->entry, "changed",
8159                         G_CALLBACK (entry_changed),
8160                         pdata);
8161       gtk_box_pack_start (GTK_BOX (hbox), pdata->entry, TRUE, TRUE, 0);
8162       gtk_widget_set_size_request (pdata->entry, 100, -1);
8163
8164       label = gtk_label_new ("Ellipsize text :");
8165       gtk_grid_attach (GTK_GRID (grid), label, 0, 10, 1, 1);
8166
8167       gtk_widget_set_halign (label, GTK_ALIGN_START);
8168       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
8169       pdata->elmenu = build_option_menu (ellipsize_items,
8170                                          sizeof (ellipsize_items) / sizeof (ellipsize_items[0]),
8171                                          2, // PANGO_ELLIPSIZE_MIDDLE
8172                                          progressbar_toggle_ellipsize,
8173                                          pdata);
8174       gtk_grid_attach (GTK_GRID (grid), pdata->elmenu, 1, 10, 1, 1);
8175
8176       check = gtk_check_button_new_with_label ("Activity mode");
8177       g_signal_connect (check, "clicked",
8178                         G_CALLBACK (toggle_activity_mode), pdata);
8179       gtk_grid_attach (GTK_GRID (grid), check, 0, 15, 1, 1);
8180
8181       button = gtk_button_new_with_label ("close");
8182       g_signal_connect_swapped (button, "clicked",
8183                                 G_CALLBACK (gtk_widget_destroy),
8184                                 pdata->window);
8185       gtk_widget_set_can_default (button, TRUE);
8186       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
8187       gtk_widget_grab_default (button);
8188     }
8189
8190   if (!gtk_widget_get_visible (pdata->window))
8191     gtk_widget_show_all (pdata->window);
8192   else
8193     gtk_widget_destroy (pdata->window);
8194 }
8195
8196 /*
8197  * Properties
8198  */
8199
8200 typedef struct {
8201   int x;
8202   int y;
8203   gboolean found;
8204   gboolean first;
8205   GtkWidget *res_widget;
8206 } FindWidgetData;
8207
8208 static void
8209 find_widget (GtkWidget *widget, FindWidgetData *data)
8210 {
8211   GtkAllocation new_allocation;
8212   gint x_offset = 0;
8213   gint y_offset = 0;
8214
8215   gtk_widget_get_allocation (widget, &new_allocation);
8216
8217   if (data->found || !gtk_widget_get_mapped (widget))
8218     return;
8219
8220   /* Note that in the following code, we only count the
8221    * position as being inside a WINDOW widget if it is inside
8222    * widget->window; points that are outside of widget->window
8223    * but within the allocation are not counted. This is consistent
8224    * with the way we highlight drag targets.
8225    */
8226   if (gtk_widget_get_has_window (widget))
8227     {
8228       new_allocation.x = 0;
8229       new_allocation.y = 0;
8230     }
8231
8232   if (gtk_widget_get_parent (widget) && !data->first)
8233     {
8234       GdkWindow *window = gtk_widget_get_window (widget);
8235       while (window != gtk_widget_get_window (gtk_widget_get_parent (widget)))
8236         {
8237           gint tx, ty, twidth, theight;
8238           
8239           twidth = gdk_window_get_width (window);
8240           theight = gdk_window_get_height (window);
8241
8242           if (new_allocation.x < 0)
8243             {
8244               new_allocation.width += new_allocation.x;
8245               new_allocation.x = 0;
8246             }
8247           if (new_allocation.y < 0)
8248             {
8249               new_allocation.height += new_allocation.y;
8250               new_allocation.y = 0;
8251             }
8252           if (new_allocation.x + new_allocation.width > twidth)
8253             new_allocation.width = twidth - new_allocation.x;
8254           if (new_allocation.y + new_allocation.height > theight)
8255             new_allocation.height = theight - new_allocation.y;
8256
8257           gdk_window_get_position (window, &tx, &ty);
8258           new_allocation.x += tx;
8259           x_offset += tx;
8260           new_allocation.y += ty;
8261           y_offset += ty;
8262
8263           window = gdk_window_get_parent (window);
8264         }
8265     }
8266
8267   if ((data->x >= new_allocation.x) && (data->y >= new_allocation.y) &&
8268       (data->x < new_allocation.x + new_allocation.width) && 
8269       (data->y < new_allocation.y + new_allocation.height))
8270     {
8271       /* First, check if the drag is in a valid drop site in
8272        * one of our children 
8273        */
8274       if (GTK_IS_CONTAINER (widget))
8275         {
8276           FindWidgetData new_data = *data;
8277           
8278           new_data.x -= x_offset;
8279           new_data.y -= y_offset;
8280           new_data.found = FALSE;
8281           new_data.first = FALSE;
8282           
8283           gtk_container_forall (GTK_CONTAINER (widget),
8284                                 (GtkCallback)find_widget,
8285                                 &new_data);
8286           
8287           data->found = new_data.found;
8288           if (data->found)
8289             data->res_widget = new_data.res_widget;
8290         }
8291
8292       /* If not, and this widget is registered as a drop site, check to
8293        * emit "drag_motion" to check if we are actually in
8294        * a drop site.
8295        */
8296       if (!data->found)
8297         {
8298           data->found = TRUE;
8299           data->res_widget = widget;
8300         }
8301     }
8302 }
8303
8304 static GtkWidget *
8305 find_widget_at_pointer (GdkDevice *device)
8306 {
8307   GtkWidget *widget = NULL;
8308   GdkWindow *pointer_window;
8309   gint x, y;
8310   FindWidgetData data;
8311  
8312  pointer_window = gdk_device_get_window_at_position (device, NULL, NULL);
8313  
8314  if (pointer_window)
8315    {
8316      gpointer widget_ptr;
8317
8318      gdk_window_get_user_data (pointer_window, &widget_ptr);
8319      widget = widget_ptr;
8320    }
8321
8322  if (widget)
8323    {
8324      gdk_window_get_device_position (gtk_widget_get_window (widget),
8325                                      device,
8326                                      &x, &y, NULL);
8327      
8328      data.x = x;
8329      data.y = y;
8330      data.found = FALSE;
8331      data.first = TRUE;
8332
8333      find_widget (widget, &data);
8334      if (data.found)
8335        return data.res_widget;
8336      return widget;
8337    }
8338  return NULL;
8339 }
8340
8341 struct PropertiesData {
8342   GtkWidget **window;
8343   GdkCursor *cursor;
8344   gboolean in_query;
8345   gulong handler;
8346 };
8347
8348 static void
8349 destroy_properties (GtkWidget             *widget,
8350                     struct PropertiesData *data)
8351 {
8352   if (data->window)
8353     {
8354       *data->window = NULL;
8355       data->window = NULL;
8356     }
8357
8358   if (data->cursor)
8359     {
8360       g_object_unref (data->cursor);
8361       data->cursor = NULL;
8362     }
8363
8364   if (data->handler)
8365     {
8366       g_signal_handler_disconnect (widget, data->handler);
8367       data->handler = 0;
8368     }
8369
8370   g_free (data);
8371 }
8372
8373 static gint
8374 property_query_event (GtkWidget             *widget,
8375                       GdkEvent              *event,
8376                       struct PropertiesData *data)
8377 {
8378   GtkWidget *res_widget = NULL;
8379
8380   if (!data->in_query)
8381     return FALSE;
8382
8383   if (event->type == GDK_BUTTON_RELEASE)
8384     {
8385       gtk_grab_remove (widget);
8386       gdk_device_ungrab (gdk_event_get_device (event), GDK_CURRENT_TIME);
8387
8388       res_widget = find_widget_at_pointer (gdk_event_get_device (event));
8389       if (res_widget)
8390         {
8391           g_object_set_data (G_OBJECT (res_widget), "prop-editor-screen",
8392                              gtk_widget_get_screen (widget));
8393           create_prop_editor (G_OBJECT (res_widget), 0);
8394         }
8395
8396       data->in_query = FALSE;
8397     }
8398   return FALSE;
8399 }
8400
8401
8402 static void
8403 query_properties (GtkButton *button,
8404                   struct PropertiesData *data)
8405 {
8406   GtkWidget *widget = GTK_WIDGET (button);
8407   GdkDisplay *display;
8408   GdkDeviceManager *device_manager;
8409   GdkDevice *device;
8410
8411   g_signal_connect (button, "event",
8412                     G_CALLBACK (property_query_event), data);
8413
8414   display = gtk_widget_get_display (widget);
8415
8416   if (!data->cursor)
8417     data->cursor = gdk_cursor_new_for_display (display, GDK_TARGET);
8418
8419   device_manager = gdk_display_get_device_manager (display);
8420   device = gdk_device_manager_get_client_pointer (device_manager);
8421   gdk_device_grab (device,
8422                    gtk_widget_get_window (widget),
8423                    GDK_OWNERSHIP_NONE,
8424                    TRUE,
8425                    GDK_BUTTON_RELEASE_MASK,
8426                    data->cursor,
8427                    GDK_CURRENT_TIME);
8428   gtk_grab_add (widget);
8429
8430   data->in_query = TRUE;
8431 }
8432
8433 static void
8434 create_properties (GtkWidget *widget)
8435 {
8436   static GtkWidget *window = NULL;
8437   GtkWidget *button;
8438   GtkWidget *vbox;
8439   GtkWidget *label;
8440   struct PropertiesData *data;
8441
8442   data = g_new (struct PropertiesData, 1);
8443   data->window = &window;
8444   data->in_query = FALSE;
8445   data->cursor = NULL;
8446   data->handler = 0;
8447
8448   if (!window)
8449     {
8450       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8451
8452       gtk_window_set_screen (GTK_WINDOW (window),
8453                              gtk_widget_get_screen (widget));      
8454
8455       data->handler = g_signal_connect (window, "destroy",
8456                                         G_CALLBACK (destroy_properties),
8457                                         data);
8458
8459       gtk_window_set_title (GTK_WINDOW (window), "test properties");
8460       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
8461
8462       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 1);
8463       gtk_container_add (GTK_CONTAINER (window), vbox);
8464             
8465       label = gtk_label_new ("This is just a dumb test to test properties.\nIf you need a generic module, get GLE.");
8466       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
8467       
8468       button = gtk_button_new_with_label ("Query properties");
8469       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
8470       g_signal_connect (button, "clicked",
8471                         G_CALLBACK (query_properties),
8472                         data);
8473     }
8474
8475   if (!gtk_widget_get_visible (window))
8476     gtk_widget_show_all (window);
8477   else
8478     gtk_widget_destroy (window);
8479   
8480 }
8481
8482 struct SnapshotData {
8483   GtkWidget *toplevel_button;
8484   GtkWidget **window;
8485   GdkCursor *cursor;
8486   gboolean in_query;
8487   gboolean is_toplevel;
8488   gint handler;
8489 };
8490
8491 static void
8492 destroy_snapshot_data (GtkWidget             *widget,
8493                        struct SnapshotData *data)
8494 {
8495   if (*data->window)
8496     *data->window = NULL;
8497   
8498   if (data->cursor)
8499     {
8500       g_object_unref (data->cursor);
8501       data->cursor = NULL;
8502     }
8503
8504   if (data->handler)
8505     {
8506       g_signal_handler_disconnect (widget, data->handler);
8507       data->handler = 0;
8508     }
8509
8510   g_free (data);
8511 }
8512
8513 static gint
8514 snapshot_widget_event (GtkWidget               *widget,
8515                        GdkEvent        *event,
8516                        struct SnapshotData *data)
8517 {
8518   GtkWidget *res_widget = NULL;
8519
8520   if (!data->in_query)
8521     return FALSE;
8522   
8523   if (event->type == GDK_BUTTON_RELEASE)
8524     {
8525       gtk_grab_remove (widget);
8526       gdk_device_ungrab (gdk_event_get_device (event),
8527                          GDK_CURRENT_TIME);
8528       
8529       res_widget = find_widget_at_pointer (gdk_event_get_device (event));
8530       if (data->is_toplevel && res_widget)
8531         res_widget = gtk_widget_get_toplevel (res_widget);
8532       if (res_widget)
8533         {
8534           cairo_surface_t *surface;
8535           GtkWidget *window, *image;
8536           GdkPixbuf *pixbuf;
8537           int width, height;
8538           cairo_t *cr;
8539
8540           width = gtk_widget_get_allocated_width (res_widget);
8541           height = gtk_widget_get_allocated_height (res_widget);
8542
8543           surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
8544
8545           cr = cairo_create (surface);
8546           gtk_widget_draw (res_widget, cr);
8547           cairo_destroy (cr);
8548
8549           pixbuf = gdk_pixbuf_get_from_surface (surface,
8550                                                 0, 0,
8551                                                 width, height);
8552           cairo_surface_destroy (surface);
8553
8554           window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8555           image = gtk_image_new_from_pixbuf (pixbuf);
8556           g_object_unref (pixbuf);
8557
8558           gtk_container_add (GTK_CONTAINER (window), image);
8559           gtk_widget_show_all (window);
8560         }
8561
8562       data->in_query = FALSE;
8563     }
8564   return FALSE;
8565 }
8566
8567
8568 static void
8569 snapshot_widget (GtkButton *button,
8570                  struct SnapshotData *data)
8571 {
8572   GtkWidget *widget = GTK_WIDGET (button);
8573   GdkDevice *device;
8574
8575   device = gtk_get_current_event_device ();
8576   if (device == NULL)
8577     return;
8578
8579   if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
8580     device = gdk_device_get_associated_device (device);
8581
8582   data->is_toplevel = widget == data->toplevel_button;
8583
8584   if (!data->cursor)
8585     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
8586                                                GDK_TARGET);
8587
8588   gdk_device_grab (device,
8589                    gtk_widget_get_window (widget),
8590                    GDK_OWNERSHIP_APPLICATION,
8591                    TRUE,
8592                    GDK_BUTTON_RELEASE_MASK,
8593                    data->cursor,
8594                    GDK_CURRENT_TIME);
8595
8596   g_signal_connect (button, "event",
8597                     G_CALLBACK (snapshot_widget_event), data);
8598
8599   gtk_grab_add (widget);
8600
8601   data->in_query = TRUE;
8602 }
8603
8604 static void
8605 create_snapshot (GtkWidget *widget)
8606 {
8607   static GtkWidget *window = NULL;
8608   GtkWidget *button;
8609   GtkWidget *vbox;
8610   struct SnapshotData *data;
8611
8612   data = g_new (struct SnapshotData, 1);
8613   data->window = &window;
8614   data->in_query = FALSE;
8615   data->cursor = NULL;
8616   data->handler = 0;
8617
8618   if (!window)
8619     {
8620       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8621
8622       gtk_window_set_screen (GTK_WINDOW (window),
8623                              gtk_widget_get_screen (widget));      
8624
8625       data->handler = g_signal_connect (window, "destroy",
8626                                         G_CALLBACK (destroy_snapshot_data),
8627                                         data);
8628
8629       gtk_window_set_title (GTK_WINDOW (window), "test snapshot");
8630       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
8631
8632       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 1);
8633       gtk_container_add (GTK_CONTAINER (window), vbox);
8634             
8635       button = gtk_button_new_with_label ("Snapshot widget");
8636       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
8637       g_signal_connect (button, "clicked",
8638                         G_CALLBACK (snapshot_widget),
8639                         data);
8640       
8641       button = gtk_button_new_with_label ("Snapshot toplevel");
8642       data->toplevel_button = button;
8643       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
8644       g_signal_connect (button, "clicked",
8645                         G_CALLBACK (snapshot_widget),
8646                         data);
8647     }
8648
8649   if (!gtk_widget_get_visible (window))
8650     gtk_widget_show_all (window);
8651   else
8652     gtk_widget_destroy (window);
8653   
8654 }
8655
8656 /*
8657  * Selection Test
8658  */
8659
8660 void
8661 selection_test_received (GtkWidget        *tree_view,
8662                          GtkSelectionData *selection_data)
8663 {
8664   GtkTreeModel *model;
8665   GtkListStore *store;
8666   GdkAtom *atoms;
8667   int i, l;
8668
8669   if (gtk_selection_data_get_length (selection_data) < 0)
8670     {
8671       g_print ("Selection retrieval failed\n");
8672       return;
8673     }
8674   if (gtk_selection_data_get_data_type (selection_data) != GDK_SELECTION_TYPE_ATOM)
8675     {
8676       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
8677       return;
8678     }
8679
8680   /* Clear out any current list items */
8681
8682   model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
8683   store = GTK_LIST_STORE (model);
8684   gtk_list_store_clear (store);
8685
8686   /* Add new items to list */
8687
8688   gtk_selection_data_get_targets (selection_data,
8689                                   &atoms, &l);
8690
8691   for (i = 0; i < l; i++)
8692     {
8693       char *name;
8694       GtkTreeIter iter;
8695
8696       name = gdk_atom_name (atoms[i]);
8697       if (name != NULL)
8698         {
8699           gtk_list_store_insert_with_values (store, &iter, i, 0, name, -1);
8700           g_free (name);
8701         }
8702       else
8703        gtk_list_store_insert_with_values (store, &iter, i, 0,  "(bad atom)", -1);
8704     }
8705
8706   return;
8707 }
8708
8709 void
8710 selection_test_get_targets (GtkWidget *widget, GtkWidget *tree_view)
8711 {
8712   static GdkAtom targets_atom = GDK_NONE;
8713
8714   if (targets_atom == GDK_NONE)
8715     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
8716
8717   gtk_selection_convert (tree_view, GDK_SELECTION_PRIMARY, targets_atom,
8718                          GDK_CURRENT_TIME);
8719 }
8720
8721 void
8722 create_selection_test (GtkWidget *widget)
8723 {
8724   static GtkWidget *window = NULL;
8725   GtkWidget *action_area, *content_area;
8726   GtkWidget *button;
8727   GtkWidget *vbox;
8728   GtkWidget *scrolled_win;
8729   GtkListStore* store;
8730   GtkWidget *tree_view;
8731   GtkTreeViewColumn *column;
8732   GtkCellRenderer *renderer;
8733   GtkWidget *label;
8734
8735   if (!window)
8736     {
8737       window = gtk_dialog_new ();
8738       
8739       gtk_window_set_screen (GTK_WINDOW (window),
8740                              gtk_widget_get_screen (widget));
8741
8742       g_signal_connect (window, "destroy",
8743                         G_CALLBACK (gtk_widget_destroyed),
8744                         &window);
8745
8746       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
8747       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
8748
8749       gtk_window_set_title (GTK_WINDOW (window), "Selection Test");
8750       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8751
8752       /* Create the list */
8753
8754       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
8755       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
8756       gtk_box_pack_start (GTK_BOX (content_area), vbox, TRUE, TRUE, 0);
8757
8758       label = gtk_label_new ("Gets available targets for current selection");
8759       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
8760
8761       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
8762       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
8763                                       GTK_POLICY_AUTOMATIC, 
8764                                       GTK_POLICY_AUTOMATIC);
8765       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
8766       gtk_widget_set_size_request (scrolled_win, 100, 200);
8767
8768       store = gtk_list_store_new (1, G_TYPE_STRING);
8769       tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
8770       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), tree_view);
8771
8772       renderer = gtk_cell_renderer_text_new ();
8773       column = gtk_tree_view_column_new_with_attributes ("Target", renderer,
8774                                                          "text", 0, NULL);
8775       gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
8776
8777       g_signal_connect (tree_view, "selection_received",
8778                         G_CALLBACK (selection_test_received), NULL);
8779
8780       /* .. And create some buttons */
8781       button = gtk_button_new_with_label ("Get Targets");
8782       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
8783
8784       g_signal_connect (button, "clicked",
8785                         G_CALLBACK (selection_test_get_targets), tree_view);
8786
8787       button = gtk_button_new_with_label ("Quit");
8788       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
8789
8790       g_signal_connect_swapped (button, "clicked",
8791                                 G_CALLBACK (gtk_widget_destroy),
8792                                 window);
8793     }
8794
8795   if (!gtk_widget_get_visible (window))
8796     gtk_widget_show_all (window);
8797   else
8798     gtk_widget_destroy (window);
8799 }
8800
8801 /*
8802  * Test scrolling
8803  */
8804
8805 static int scroll_test_pos = 0.0;
8806
8807 static gint
8808 scroll_test_draw (GtkWidget     *widget,
8809                   cairo_t       *cr,
8810                   GtkAdjustment *adjustment)
8811 {
8812   gint i,j;
8813   gint imin, imax, jmin, jmax;
8814   GdkRectangle clip;
8815   
8816   gdk_cairo_get_clip_rectangle (cr, &clip);
8817
8818   imin = (clip.x) / 10;
8819   imax = (clip.x + clip.width + 9) / 10;
8820
8821   jmin = ((int)gtk_adjustment_get_value (adjustment) + clip.y) / 10;
8822   jmax = ((int)gtk_adjustment_get_value (adjustment) + clip.y + clip.height + 9) / 10;
8823
8824   for (i=imin; i<imax; i++)
8825     for (j=jmin; j<jmax; j++)
8826       if ((i+j) % 2)
8827         cairo_rectangle (cr, 10*i, 10*j - (int)gtk_adjustment_get_value (adjustment), 1+i%10, 1+j%10);
8828
8829   cairo_fill (cr);
8830
8831   return TRUE;
8832 }
8833
8834 static gint
8835 scroll_test_scroll (GtkWidget *widget, GdkEventScroll *event,
8836                     GtkAdjustment *adjustment)
8837 {
8838   gdouble new_value = gtk_adjustment_get_value (adjustment) + ((event->direction == GDK_SCROLL_UP) ?
8839                                     -gtk_adjustment_get_page_increment (adjustment) / 2:
8840                                     gtk_adjustment_get_page_increment (adjustment) / 2);
8841   new_value = CLAMP (new_value, gtk_adjustment_get_lower (adjustment), gtk_adjustment_get_upper (adjustment) - gtk_adjustment_get_page_size (adjustment));
8842   gtk_adjustment_set_value (adjustment, new_value);  
8843   
8844   return TRUE;
8845 }
8846
8847 static void
8848 scroll_test_configure (GtkWidget *widget, GdkEventConfigure *event,
8849                        GtkAdjustment *adjustment)
8850 {
8851   GtkAllocation allocation;
8852
8853   gtk_widget_get_allocation (widget, &allocation);
8854   gtk_adjustment_configure (adjustment,
8855                             gtk_adjustment_get_value (adjustment),
8856                             gtk_adjustment_get_lower (adjustment),
8857                             gtk_adjustment_get_upper (adjustment),
8858                             0.1 * allocation.height,
8859                             0.9 * allocation.height,
8860                             allocation.height);
8861 }
8862
8863 static void
8864 scroll_test_adjustment_changed (GtkAdjustment *adjustment, GtkWidget *widget)
8865 {
8866   GdkWindow *window;
8867   gint dy;
8868
8869   dy = scroll_test_pos - (int)gtk_adjustment_get_value (adjustment);
8870   scroll_test_pos = gtk_adjustment_get_value (adjustment);
8871
8872   if (!gtk_widget_is_drawable (widget))
8873     return;
8874
8875   window = gtk_widget_get_window (widget);
8876   gdk_window_scroll (window, 0, dy);
8877   gdk_window_process_updates (window, FALSE);
8878 }
8879
8880
8881 void
8882 create_scroll_test (GtkWidget *widget)
8883 {
8884   static GtkWidget *window = NULL;
8885   GtkWidget *action_area, *content_area;
8886   GtkWidget *hbox;
8887   GtkWidget *drawing_area;
8888   GtkWidget *scrollbar;
8889   GtkWidget *button;
8890   GtkAdjustment *adjustment;
8891   GdkGeometry geometry;
8892   GdkWindowHints geometry_mask;
8893
8894   if (!window)
8895     {
8896       window = gtk_dialog_new ();
8897
8898       gtk_window_set_screen (GTK_WINDOW (window),
8899                              gtk_widget_get_screen (widget));
8900
8901       g_signal_connect (window, "destroy",
8902                         G_CALLBACK (gtk_widget_destroyed),
8903                         &window);
8904
8905       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
8906       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
8907
8908       gtk_window_set_title (GTK_WINDOW (window), "Scroll Test");
8909       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8910
8911       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
8912       gtk_box_pack_start (GTK_BOX (content_area), hbox, TRUE, TRUE, 0);
8913       gtk_widget_show (hbox);
8914
8915       drawing_area = gtk_drawing_area_new ();
8916       gtk_widget_set_size_request (drawing_area, 200, 200);
8917       gtk_box_pack_start (GTK_BOX (hbox), drawing_area, TRUE, TRUE, 0);
8918       gtk_widget_show (drawing_area);
8919
8920       gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK | GDK_SCROLL_MASK);
8921
8922       adjustment = gtk_adjustment_new (0.0, 0.0, 1000.0, 1.0, 180.0, 200.0);
8923       scroll_test_pos = 0.0;
8924
8925       scrollbar = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, adjustment);
8926       gtk_box_pack_start (GTK_BOX (hbox), scrollbar, FALSE, FALSE, 0);
8927       gtk_widget_show (scrollbar);
8928
8929       g_signal_connect (drawing_area, "draw",
8930                         G_CALLBACK (scroll_test_draw), adjustment);
8931       g_signal_connect (drawing_area, "configure_event",
8932                         G_CALLBACK (scroll_test_configure), adjustment);
8933       g_signal_connect (drawing_area, "scroll_event",
8934                         G_CALLBACK (scroll_test_scroll), adjustment);
8935       
8936       g_signal_connect (adjustment, "value_changed",
8937                         G_CALLBACK (scroll_test_adjustment_changed),
8938                         drawing_area);
8939       
8940       /* .. And create some buttons */
8941
8942       button = gtk_button_new_with_label ("Quit");
8943       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
8944
8945       g_signal_connect_swapped (button, "clicked",
8946                                 G_CALLBACK (gtk_widget_destroy),
8947                                 window);
8948       gtk_widget_show (button);
8949
8950       /* Set up gridded geometry */
8951
8952       geometry_mask = GDK_HINT_MIN_SIZE | 
8953                        GDK_HINT_BASE_SIZE | 
8954                        GDK_HINT_RESIZE_INC;
8955
8956       geometry.min_width = 20;
8957       geometry.min_height = 20;
8958       geometry.base_width = 0;
8959       geometry.base_height = 0;
8960       geometry.width_inc = 10;
8961       geometry.height_inc = 10;
8962       
8963       gtk_window_set_geometry_hints (GTK_WINDOW (window),
8964                                drawing_area, &geometry, geometry_mask);
8965     }
8966
8967   if (!gtk_widget_get_visible (window))
8968     gtk_widget_show (window);
8969   else
8970     gtk_widget_destroy (window);
8971 }
8972
8973 /*
8974  * Timeout Test
8975  */
8976
8977 static int timer = 0;
8978
8979 gint
8980 timeout_test (GtkWidget *label)
8981 {
8982   static int count = 0;
8983   static char buffer[32];
8984
8985   sprintf (buffer, "count: %d", ++count);
8986   gtk_label_set_text (GTK_LABEL (label), buffer);
8987
8988   return TRUE;
8989 }
8990
8991 void
8992 start_timeout_test (GtkWidget *widget,
8993                     GtkWidget *label)
8994 {
8995   if (!timer)
8996     {
8997       timer = g_timeout_add (100, (GSourceFunc)timeout_test, label);
8998     }
8999 }
9000
9001 void
9002 stop_timeout_test (GtkWidget *widget,
9003                    gpointer   data)
9004 {
9005   if (timer)
9006     {
9007       g_source_remove (timer);
9008       timer = 0;
9009     }
9010 }
9011
9012 void
9013 destroy_timeout_test (GtkWidget  *widget,
9014                       GtkWidget **window)
9015 {
9016   stop_timeout_test (NULL, NULL);
9017
9018   *window = NULL;
9019 }
9020
9021 void
9022 create_timeout_test (GtkWidget *widget)
9023 {
9024   static GtkWidget *window = NULL;
9025   GtkWidget *action_area, *content_area;
9026   GtkWidget *button;
9027   GtkWidget *label;
9028
9029   if (!window)
9030     {
9031       window = gtk_dialog_new ();
9032
9033       gtk_window_set_screen (GTK_WINDOW (window),
9034                              gtk_widget_get_screen (widget));
9035
9036       g_signal_connect (window, "destroy",
9037                         G_CALLBACK (destroy_timeout_test),
9038                         &window);
9039
9040       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9041       action_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9042
9043       gtk_window_set_title (GTK_WINDOW (window), "Timeout Test");
9044       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9045
9046       label = gtk_label_new ("count: 0");
9047       g_object_set (label, "margin", 10, NULL);
9048       gtk_box_pack_start (GTK_BOX (content_area), label, TRUE, TRUE, 0);
9049       gtk_widget_show (label);
9050
9051       button = gtk_button_new_with_label ("close");
9052       g_signal_connect_swapped (button, "clicked",
9053                                 G_CALLBACK (gtk_widget_destroy),
9054                                 window);
9055       gtk_widget_set_can_default (button, TRUE);
9056       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9057       gtk_widget_grab_default (button);
9058       gtk_widget_show (button);
9059
9060       button = gtk_button_new_with_label ("start");
9061       g_signal_connect (button, "clicked",
9062                         G_CALLBACK(start_timeout_test),
9063                         label);
9064       gtk_widget_set_can_default (button, TRUE);
9065       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9066       gtk_widget_show (button);
9067
9068       button = gtk_button_new_with_label ("stop");
9069       g_signal_connect (button, "clicked",
9070                         G_CALLBACK (stop_timeout_test),
9071                         NULL);
9072       gtk_widget_set_can_default (button, TRUE);
9073       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9074       gtk_widget_show (button);
9075     }
9076
9077   if (!gtk_widget_get_visible (window))
9078     gtk_widget_show (window);
9079   else
9080     gtk_widget_destroy (window);
9081 }
9082
9083 /*
9084  * Idle Test
9085  */
9086
9087 static int idle_id = 0;
9088
9089 static gint
9090 idle_test (GtkWidget *label)
9091 {
9092   static int count = 0;
9093   static char buffer[32];
9094
9095   sprintf (buffer, "count: %d", ++count);
9096   gtk_label_set_text (GTK_LABEL (label), buffer);
9097
9098   return TRUE;
9099 }
9100
9101 static void
9102 start_idle_test (GtkWidget *widget,
9103                  GtkWidget *label)
9104 {
9105   if (!idle_id)
9106     {
9107       idle_id = g_idle_add ((GSourceFunc) idle_test, label);
9108     }
9109 }
9110
9111 static void
9112 stop_idle_test (GtkWidget *widget,
9113                 gpointer   data)
9114 {
9115   if (idle_id)
9116     {
9117       g_source_remove (idle_id);
9118       idle_id = 0;
9119     }
9120 }
9121
9122 static void
9123 destroy_idle_test (GtkWidget  *widget,
9124                    GtkWidget **window)
9125 {
9126   stop_idle_test (NULL, NULL);
9127
9128   *window = NULL;
9129 }
9130
9131 static void
9132 toggle_idle_container (GObject *button,
9133                        GtkContainer *container)
9134 {
9135   gtk_container_set_resize_mode (container, GPOINTER_TO_INT (g_object_get_data (button, "user_data")));
9136 }
9137
9138 static void
9139 create_idle_test (GtkWidget *widget)
9140 {
9141   static GtkWidget *window = NULL;
9142   GtkWidget *button;
9143   GtkWidget *label;
9144   GtkWidget *container;
9145
9146   if (!window)
9147     {
9148       GtkWidget *action_area, *content_area;
9149       GtkWidget *button2;
9150       GtkWidget *frame;
9151       GtkWidget *box;
9152
9153       window = gtk_dialog_new ();
9154
9155       gtk_window_set_screen (GTK_WINDOW (window),
9156                              gtk_widget_get_screen (widget));
9157
9158       g_signal_connect (window, "destroy",
9159                         G_CALLBACK (destroy_idle_test),
9160                         &window);
9161
9162       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9163       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9164
9165       gtk_window_set_title (GTK_WINDOW (window), "Idle Test");
9166       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9167
9168       label = gtk_label_new ("count: 0");
9169       g_object_set (label, "margin", 10, NULL);
9170       gtk_widget_show (label);
9171       
9172       container =
9173         g_object_new (GTK_TYPE_BOX,
9174                         "visible", TRUE,
9175                         /* "GtkContainer::child", g_object_new (GTK_TYPE_HBOX,
9176                          * "GtkWidget::visible", TRUE,
9177                          */
9178                          "child", label,
9179                         /* NULL), */
9180                         NULL);
9181       gtk_box_pack_start (GTK_BOX (content_area), container, TRUE, TRUE, 0);
9182
9183       frame =
9184         g_object_new (GTK_TYPE_FRAME,
9185                         "border_width", 5,
9186                         "label", "Label Container",
9187                         "visible", TRUE,
9188                         "parent", content_area,
9189                         NULL);
9190       box =
9191         g_object_new (GTK_TYPE_BOX,
9192                         "visible", TRUE,
9193                         "parent", frame,
9194                         "orientation", GTK_ORIENTATION_VERTICAL,
9195                         NULL);
9196       button =
9197         g_object_connect (g_object_new (GTK_TYPE_RADIO_BUTTON,
9198                                           "label", "Resize-Parent",
9199                                           "user_data", (void*)GTK_RESIZE_PARENT,
9200                                           "visible", TRUE,
9201                                           "parent", box,
9202                                           NULL),
9203                           "signal::clicked", toggle_idle_container, container,
9204                           NULL);
9205       button = g_object_new (GTK_TYPE_RADIO_BUTTON,
9206                                "label", "Resize-Queue",
9207                                "user_data", (void*)GTK_RESIZE_QUEUE,
9208                                "group", button,
9209                                "visible", TRUE,
9210                                "parent", box,
9211                                NULL);
9212       g_object_connect (button,
9213                         "signal::clicked", toggle_idle_container, container,
9214                         NULL);
9215       button2 = g_object_new (GTK_TYPE_RADIO_BUTTON,
9216                                 "label", "Resize-Immediate",
9217                                 "user_data", (void*)GTK_RESIZE_IMMEDIATE,
9218                                 NULL);
9219       g_object_connect (button2,
9220                         "signal::clicked", toggle_idle_container, container,
9221                         NULL);
9222       g_object_set (button2,
9223                     "group", button,
9224                     "visible", TRUE,
9225                     "parent", box,
9226                     NULL);
9227
9228       button = gtk_button_new_with_label ("close");
9229       g_signal_connect_swapped (button, "clicked",
9230                                 G_CALLBACK (gtk_widget_destroy),
9231                                 window);
9232       gtk_widget_set_can_default (button, TRUE);
9233       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9234       gtk_widget_grab_default (button);
9235       gtk_widget_show (button);
9236
9237       button = gtk_button_new_with_label ("start");
9238       g_signal_connect (button, "clicked",
9239                         G_CALLBACK (start_idle_test),
9240                         label);
9241       gtk_widget_set_can_default (button, TRUE);
9242       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9243       gtk_widget_show (button);
9244
9245       button = gtk_button_new_with_label ("stop");
9246       g_signal_connect (button, "clicked",
9247                         G_CALLBACK (stop_idle_test),
9248                         NULL);
9249       gtk_widget_set_can_default (button, TRUE);
9250       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9251       gtk_widget_show (button);
9252     }
9253
9254   if (!gtk_widget_get_visible (window))
9255     gtk_widget_show (window);
9256   else
9257     gtk_widget_destroy (window);
9258 }
9259
9260 /*
9261  * rc file test
9262  */
9263
9264 void
9265 create_rc_file (GtkWidget *widget)
9266 {
9267   static GtkWidget *window = NULL;
9268   GtkWidget *action_area, *content_area;
9269   GtkWidget *button;
9270   GtkWidget *frame;
9271   GtkWidget *vbox;
9272   GtkWidget *label;
9273
9274   if (!window)
9275     {
9276       window = gtk_dialog_new ();
9277
9278       gtk_window_set_screen (GTK_WINDOW (window),
9279                              gtk_widget_get_screen (widget));
9280
9281       g_signal_connect (window, "destroy",
9282                         G_CALLBACK (gtk_widget_destroyed),
9283                         &window);
9284
9285       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9286       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9287
9288       frame = gtk_aspect_frame_new ("Testing RC file prioritization", 0.5, 0.5, 0.0, TRUE);
9289       gtk_box_pack_start (GTK_BOX (content_area), frame, FALSE, FALSE, 0);
9290
9291       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
9292       gtk_container_add (GTK_CONTAINER (frame), vbox);
9293       
9294       label = gtk_label_new ("This label should be red");
9295       gtk_widget_set_name (label, "testgtk-red-label");
9296       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9297
9298       label = gtk_label_new ("This label should be green");
9299       gtk_widget_set_name (label, "testgtk-green-label");
9300       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9301
9302       label = gtk_label_new ("This label should be blue");
9303       gtk_widget_set_name (label, "testgtk-blue-label");
9304       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9305
9306       gtk_window_set_title (GTK_WINDOW (window), "Reload Rc file");
9307       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9308
9309       button = gtk_button_new_with_label ("Reload");
9310       g_signal_connect_swapped (button, "clicked",
9311                                 G_CALLBACK (gtk_style_context_reset_widgets),
9312                                 gtk_widget_get_screen (button));
9313       gtk_widget_set_can_default (button, TRUE);
9314       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9315       gtk_widget_grab_default (button);
9316
9317       button = gtk_button_new_with_label ("Close");
9318       g_signal_connect_swapped (button, "clicked",
9319                                 G_CALLBACK (gtk_widget_destroy),
9320                                 window);
9321       gtk_widget_set_can_default (button, TRUE);
9322       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9323     }
9324
9325   if (!gtk_widget_get_visible (window))
9326     gtk_widget_show_all (window);
9327   else
9328     gtk_widget_destroy (window);
9329 }
9330
9331 /*
9332  * Test of recursive mainloop
9333  */
9334
9335 void
9336 mainloop_destroyed (GtkWidget *w, GtkWidget **window)
9337 {
9338   *window = NULL;
9339   gtk_main_quit ();
9340 }
9341
9342 void
9343 create_mainloop (GtkWidget *widget)
9344 {
9345   static GtkWidget *window = NULL;
9346   GtkWidget *action_area, *content_area;
9347   GtkWidget *label;
9348   GtkWidget *button;
9349
9350   if (!window)
9351     {
9352       window = gtk_dialog_new ();
9353
9354       gtk_window_set_screen (GTK_WINDOW (window),
9355                              gtk_widget_get_screen (widget));
9356
9357       gtk_window_set_title (GTK_WINDOW (window), "Test Main Loop");
9358
9359       g_signal_connect (window, "destroy",
9360                         G_CALLBACK (mainloop_destroyed),
9361                         &window);
9362
9363       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9364       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9365
9366       label = gtk_label_new ("In recursive main loop...");
9367       g_object_set (label, "margin", 20, NULL);
9368
9369       gtk_box_pack_start (GTK_BOX (content_area), label, TRUE, TRUE, 0);
9370       gtk_widget_show (label);
9371
9372       button = gtk_button_new_with_label ("Leave");
9373       gtk_box_pack_start (GTK_BOX (action_area), button, FALSE, TRUE, 0);
9374
9375       g_signal_connect_swapped (button, "clicked",
9376                                 G_CALLBACK (gtk_widget_destroy),
9377                                 window);
9378
9379       gtk_widget_set_can_default (button, TRUE);
9380       gtk_widget_grab_default (button);
9381
9382       gtk_widget_show (button);
9383     }
9384
9385   if (!gtk_widget_get_visible (window))
9386     {
9387       gtk_widget_show (window);
9388
9389       g_print ("create_mainloop: start\n");
9390       gtk_main ();
9391       g_print ("create_mainloop: done\n");
9392     }
9393   else
9394     gtk_widget_destroy (window);
9395 }
9396
9397 static gboolean
9398 layout_draw_handler (GtkWidget *widget, cairo_t *cr)
9399 {
9400   GtkLayout *layout;
9401   GdkWindow *bin_window;
9402   GdkRectangle clip;
9403   gint i,j,x,y;
9404   gint imin, imax, jmin, jmax;
9405
9406   layout = GTK_LAYOUT (widget);
9407   bin_window = gtk_layout_get_bin_window (layout);
9408
9409   if (!gtk_cairo_should_draw_window (cr, bin_window))
9410     return FALSE;
9411   
9412   gdk_window_get_position (bin_window, &x, &y);
9413   cairo_translate (cr, x, y);
9414
9415   gdk_cairo_get_clip_rectangle (cr, &clip);
9416
9417   imin = (clip.x) / 10;
9418   imax = (clip.x + clip.width + 9) / 10;
9419
9420   jmin = (clip.y) / 10;
9421   jmax = (clip.y + clip.height + 9) / 10;
9422
9423   for (i=imin; i<imax; i++)
9424     for (j=jmin; j<jmax; j++)
9425       if ((i+j) % 2)
9426         cairo_rectangle (cr,
9427                          10*i, 10*j, 
9428                          1+i%10, 1+j%10);
9429   
9430   cairo_fill (cr);
9431
9432   return FALSE;
9433 }
9434
9435 void create_layout (GtkWidget *widget)
9436 {
9437   GtkAdjustment *hadjustment, *vadjustment;
9438   GtkLayout *layout;
9439   static GtkWidget *window = NULL;
9440   GtkWidget *layout_widget;
9441   GtkWidget *scrolledwindow;
9442   GtkWidget *button;
9443
9444   if (!window)
9445     {
9446       gchar buf[16];
9447
9448       gint i, j;
9449       
9450       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9451       gtk_window_set_screen (GTK_WINDOW (window),
9452                              gtk_widget_get_screen (widget));
9453
9454       g_signal_connect (window, "destroy",
9455                         G_CALLBACK (gtk_widget_destroyed),
9456                         &window);
9457
9458       gtk_window_set_title (GTK_WINDOW (window), "Layout");
9459       gtk_widget_set_size_request (window, 200, 200);
9460
9461       scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
9462       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
9463                                            GTK_SHADOW_IN);
9464       gtk_scrolled_window_set_placement (GTK_SCROLLED_WINDOW (scrolledwindow),
9465                                          GTK_CORNER_TOP_RIGHT);
9466
9467       gtk_container_add (GTK_CONTAINER (window), scrolledwindow);
9468
9469       layout_widget = gtk_layout_new (NULL, NULL);
9470       layout = GTK_LAYOUT (layout_widget);
9471       gtk_container_add (GTK_CONTAINER (scrolledwindow), layout_widget);
9472
9473       /* We set step sizes here since GtkLayout does not set
9474        * them itself.
9475        */
9476       hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (layout));
9477       vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (layout));
9478       gtk_adjustment_set_step_increment (hadjustment, 10.0);
9479       gtk_adjustment_set_step_increment (vadjustment, 10.0);
9480       gtk_scrollable_set_hadjustment (GTK_SCROLLABLE (layout), hadjustment);
9481       gtk_scrollable_set_vadjustment (GTK_SCROLLABLE (layout), vadjustment);
9482
9483       gtk_widget_set_events (layout_widget, GDK_EXPOSURE_MASK);
9484       g_signal_connect (layout, "draw",
9485                         G_CALLBACK (layout_draw_handler), NULL);
9486
9487       gtk_layout_set_size (layout, 1600, 128000);
9488
9489       for (i=0 ; i < 16 ; i++)
9490         for (j=0 ; j < 16 ; j++)
9491           {
9492             sprintf(buf, "Button %d, %d", i, j);
9493             if ((i + j) % 2)
9494               button = gtk_button_new_with_label (buf);
9495             else
9496               button = gtk_label_new (buf);
9497
9498             gtk_layout_put (layout, button, j*100, i*100);
9499           }
9500
9501       for (i=16; i < 1280; i++)
9502         {
9503           sprintf(buf, "Button %d, %d", i, 0);
9504           if (i % 2)
9505             button = gtk_button_new_with_label (buf);
9506           else
9507             button = gtk_label_new (buf);
9508
9509           gtk_layout_put (layout, button, 0, i*100);
9510         }
9511     }
9512
9513   if (!gtk_widget_get_visible (window))
9514     gtk_widget_show_all (window);
9515   else
9516     gtk_widget_destroy (window);
9517 }
9518
9519 #if 0
9520 /* FIXME: need to completely redo this for GtkStyleContext */
9521 void
9522 create_styles (GtkWidget *widget)
9523 {
9524   static GtkWidget *window = NULL;
9525   GtkWidget *content_area, *action_area;
9526   GtkWidget *label;
9527   GtkWidget *button;
9528   GtkWidget *entry;
9529   GtkWidget *vbox;
9530   static GdkRGBA red =    { 1,0,0,1 };
9531   static GdkRGBA green =  { 0,1,0,1 };
9532   static GdkRGBA blue =   { 0,0,1,1 };
9533   static GdkRGBA yellow = { 1,1,0,1 };
9534   static GdkRGBA cyan =   { 0,1,1,1 };
9535   PangoFontDescription *font_desc;
9536
9537   GtkRcStyle *rc_style;
9538
9539   if (!window)
9540     {
9541       window = gtk_dialog_new ();
9542       gtk_window_set_screen (GTK_WINDOW (window),
9543                              gtk_widget_get_screen (widget));
9544      
9545       g_signal_connect (window, "destroy",
9546                         G_CALLBACK (gtk_widget_destroyed),
9547                         &window);
9548
9549       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9550       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9551
9552       button = gtk_button_new_with_label ("Close");
9553       g_signal_connect_swapped (button, "clicked",
9554                                 G_CALLBACK (gtk_widget_destroy),
9555                                 window);
9556       gtk_widget_set_can_default (button, TRUE);
9557       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9558       gtk_widget_show (button);
9559
9560       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
9561       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
9562       gtk_box_pack_start (GTK_BOX (content_area), vbox, FALSE, FALSE, 0);
9563       
9564       label = gtk_label_new ("Font:");
9565       gtk_widget_set_halign (label, GTK_ALIGN_START);
9566       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9567       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9568
9569       font_desc = pango_font_description_from_string ("Helvetica,Sans Oblique 18");
9570
9571       button = gtk_button_new_with_label ("Some Text");
9572       gtk_widget_override_font (gtk_bin_get_child (GTK_BIN (button)), font_desc);
9573       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9574
9575       label = gtk_label_new ("Foreground:");
9576       gtk_widget_set_halign (label, GTK_ALIGN_START);
9577       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9578       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9579
9580       button = gtk_button_new_with_label ("Some Text");
9581       gtk_widget_override_color (gtk_bin_get_child (GTK_BIN (button)), 0, &red);
9582       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9583
9584       label = gtk_label_new ("Background:");
9585       gtk_widget_set_halign (label, GTK_ALIGN_START);
9586       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9587       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9588
9589       button = gtk_button_new_with_label ("Some Text");
9590       gtk_widget_override_background_color (button, 0, &green);
9591       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9592
9593       label = gtk_label_new ("Text:");
9594       gtk_widget_set_halign (label, GTK_ALIGN_START);
9595       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9596       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9597
9598       entry = gtk_entry_new ();
9599       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
9600       gtk_widget_override_color (entry, 0, &blue);
9601       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
9602
9603       label = gtk_label_new ("Base:");
9604       gtk_widget_set_halign (label, GTK_ALIGN_START);
9605       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9606       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9607
9608       entry = gtk_entry_new ();
9609       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
9610       gtk_widget_override_background_color (entry, 0, &yellow);
9611       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
9612
9613       label = gtk_label_new ("Cursor:");
9614       gtk_widget_set_halign (label, GTK_ALIGN_START);
9615       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9616       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9617
9618       entry = gtk_entry_new ();
9619       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
9620       gtk_widget_modify_cursor (entry, &red, &red);
9621       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
9622
9623       label = gtk_label_new ("Multiple:");
9624       gtk_widget_set_halign (label, GTK_ALIGN_START);
9625       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9626       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9627
9628       button = gtk_button_new_with_label ("Some Text");
9629
9630       rc_style = gtk_rc_style_new ();
9631
9632       rc_style->font_desc = pango_font_description_copy (font_desc);
9633       rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG | GTK_RC_BG;
9634       rc_style->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_FG | GTK_RC_BG;
9635       rc_style->color_flags[GTK_STATE_ACTIVE] = GTK_RC_FG | GTK_RC_BG;
9636       rc_style->fg[GTK_STATE_NORMAL] = yellow;
9637       rc_style->bg[GTK_STATE_NORMAL] = blue;
9638       rc_style->fg[GTK_STATE_PRELIGHT] = blue;
9639       rc_style->bg[GTK_STATE_PRELIGHT] = yellow;
9640       rc_style->fg[GTK_STATE_ACTIVE] = red;
9641       rc_style->bg[GTK_STATE_ACTIVE] = cyan;
9642       rc_style->xthickness = 5;
9643       rc_style->ythickness = 5;
9644
9645       gtk_widget_modify_style (button, rc_style);
9646       gtk_widget_modify_style (gtk_bin_get_child (GTK_BIN (button)), rc_style);
9647
9648       g_object_unref (rc_style);
9649       
9650       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9651     }
9652   
9653   if (!gtk_widget_get_visible (window))
9654     gtk_widget_show_all (window);
9655   else
9656     gtk_widget_destroy (window);
9657 }
9658 #endif
9659
9660 /*
9661  * Main Window and Exit
9662  */
9663
9664 void
9665 do_exit (GtkWidget *widget, GtkWidget *window)
9666 {
9667   gtk_widget_destroy (window);
9668   gtk_main_quit ();
9669 }
9670
9671 struct {
9672   char *label;
9673   void (*func) (GtkWidget *widget);
9674   gboolean do_not_benchmark;
9675 } buttons[] =
9676 {
9677   { "alpha window", create_alpha_window },
9678   { "big windows", create_big_windows },
9679   { "button box", create_button_box },
9680   { "buttons", create_buttons },
9681   { "check buttons", create_check_buttons },
9682   { "color selection", create_color_selection },
9683   { "composited window", create_composited_window },
9684   { "cursors", create_cursors },
9685   { "dialog", create_dialog },
9686   { "display & screen", create_display_screen, TRUE },
9687   { "entry", create_entry },
9688   { "event box", create_event_box },
9689   { "event watcher", create_event_watcher },
9690   { "expander", create_expander },
9691   { "flipping", create_flipping },
9692   { "focus", create_focus },
9693   { "font selection", create_font_selection },
9694   { "image", create_image },
9695   { "key lookup", create_key_lookup },
9696   { "labels", create_labels },
9697   { "layout", create_layout },
9698   { "menus", create_menus },
9699   { "message dialog", create_message_dialog },
9700   { "modal window", create_modal_window, TRUE },
9701   { "notebook", create_notebook },
9702   { "panes", create_panes },
9703   { "paned keyboard", create_paned_keyboard_navigation },
9704   { "pixbuf", create_pixbuf },
9705   { "progress bar", create_progress_bar },
9706   { "properties", create_properties },
9707   { "radio buttons", create_radio_buttons },
9708   { "range controls", create_range_controls },
9709   { "rc file", create_rc_file },
9710   { "reparent", create_reparent },
9711   { "resize grips", create_resize_grips },
9712   { "rotated label", create_rotated_label },
9713   { "rotated text", create_rotated_text },
9714   { "saved position", create_saved_position },
9715   { "scrolled windows", create_scrolled_windows },
9716   { "shapes", create_shapes },
9717   { "size groups", create_size_groups },
9718   { "snapshot", create_snapshot },
9719   { "spinbutton", create_spins },
9720   { "statusbar", create_statusbar },
9721 #if 0
9722   { "styles", create_styles },
9723 #endif
9724   { "test idle", create_idle_test },
9725   { "test mainloop", create_mainloop, TRUE },
9726   { "test scrolling", create_scroll_test },
9727   { "test selection", create_selection_test },
9728   { "test timeout", create_timeout_test },
9729   { "toggle buttons", create_toggle_buttons },
9730   { "toolbar", create_toolbar },
9731   { "tooltips", create_tooltips },
9732   { "WM hints", create_wmhints },
9733   { "window sizing", create_window_sizing },
9734   { "window states", create_window_states }
9735 };
9736 int nbuttons = sizeof (buttons) / sizeof (buttons[0]);
9737
9738 void
9739 create_main_window (void)
9740 {
9741   GtkWidget *window;
9742   GtkWidget *box1;
9743   GtkWidget *box2;
9744   GtkWidget *scrolled_window;
9745   GtkWidget *button;
9746   GtkWidget *label;
9747   gchar buffer[64];
9748   GtkWidget *separator;
9749   GdkGeometry geometry;
9750   int i;
9751
9752   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9753   gtk_widget_set_name (window, "main_window");
9754   gtk_window_move (GTK_WINDOW (window), 50, 20);
9755   gtk_window_set_default_size (GTK_WINDOW (window), -1, 400);
9756
9757   geometry.min_width = -1;
9758   geometry.min_height = -1;
9759   geometry.max_width = -1;
9760   geometry.max_height = G_MAXSHORT;
9761   gtk_window_set_geometry_hints (GTK_WINDOW (window), NULL,
9762                                  &geometry,
9763                                  GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
9764
9765   g_signal_connect (window, "destroy",
9766                     G_CALLBACK (gtk_main_quit),
9767                     NULL);
9768   g_signal_connect (window, "delete-event",
9769                     G_CALLBACK (gtk_false),
9770                     NULL);
9771
9772   box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
9773   gtk_container_add (GTK_CONTAINER (window), box1);
9774
9775   if (gtk_micro_version > 0)
9776     sprintf (buffer,
9777              "Gtk+ v%d.%d.%d",
9778              gtk_get_major_version (),
9779              gtk_get_minor_version (),
9780              gtk_get_micro_version ());
9781   else
9782     sprintf (buffer,
9783              "Gtk+ v%d.%d",
9784              gtk_get_major_version (),
9785              gtk_get_minor_version ());
9786
9787   label = gtk_label_new (buffer);
9788   gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
9789   gtk_widget_set_name (label, "testgtk-version-label");
9790
9791   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
9792   gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
9793   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
9794                                   GTK_POLICY_NEVER, 
9795                                   GTK_POLICY_AUTOMATIC);
9796   gtk_box_pack_start (GTK_BOX (box1), scrolled_window, TRUE, TRUE, 0);
9797
9798   box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
9799   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9800   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), box2);
9801   gtk_container_set_focus_vadjustment (GTK_CONTAINER (box2),
9802                                        gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
9803   gtk_widget_show (box2);
9804
9805   for (i = 0; i < nbuttons; i++)
9806     {
9807       button = gtk_button_new_with_label (buttons[i].label);
9808       if (buttons[i].func)
9809         g_signal_connect (button, 
9810                           "clicked", 
9811                           G_CALLBACK(buttons[i].func),
9812                           NULL);
9813       else
9814         gtk_widget_set_sensitive (button, FALSE);
9815       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9816     }
9817
9818   separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
9819   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
9820
9821   box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
9822   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9823   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9824
9825   button = gtk_button_new_with_mnemonic ("_Close");
9826   g_signal_connect (button, "clicked",
9827                     G_CALLBACK (do_exit),
9828                     window);
9829   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9830   gtk_widget_set_can_default (button, TRUE);
9831   gtk_widget_grab_default (button);
9832
9833   gtk_widget_show_all (window);
9834 }
9835
9836 static void
9837 test_init (void)
9838 {
9839   if (g_file_test ("../modules/input/immodules.cache", G_FILE_TEST_EXISTS))
9840     g_setenv ("GTK_IM_MODULE_FILE", "../modules/input/immodules.cache", TRUE);
9841 }
9842
9843 static char *
9844 pad (const char *str, int to)
9845 {
9846   static char buf[256];
9847   int len = strlen (str);
9848   int i;
9849
9850   for (i = 0; i < to; i++)
9851     buf[i] = ' ';
9852
9853   buf[to] = '\0';
9854
9855   memcpy (buf, str, len);
9856
9857   return buf;
9858 }
9859
9860 static void
9861 bench_iteration (GtkWidget *widget, void (* fn) (GtkWidget *widget))
9862 {
9863   fn (widget); /* on */
9864   while (g_main_context_iteration (NULL, FALSE));
9865   fn (widget); /* off */
9866   while (g_main_context_iteration (NULL, FALSE));
9867 }
9868
9869 void
9870 do_real_bench (GtkWidget *widget, void (* fn) (GtkWidget *widget), char *name, int num)
9871 {
9872   GTimeVal tv0, tv1;
9873   double dt_first;
9874   double dt;
9875   int n;
9876   static gboolean printed_headers = FALSE;
9877
9878   if (!printed_headers) {
9879     g_print ("Test                 Iters      First      Other\n");
9880     g_print ("-------------------- ----- ---------- ----------\n");
9881     printed_headers = TRUE;
9882   }
9883
9884   g_get_current_time (&tv0);
9885   bench_iteration (widget, fn); 
9886   g_get_current_time (&tv1);
9887
9888   dt_first = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
9889         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
9890
9891   g_get_current_time (&tv0);
9892   for (n = 0; n < num - 1; n++)
9893     bench_iteration (widget, fn); 
9894   g_get_current_time (&tv1);
9895   dt = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
9896         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
9897
9898   g_print ("%s %5d ", pad (name, 20), num);
9899   if (num > 1)
9900     g_print ("%10.1f %10.1f\n", dt_first, dt/(num-1));
9901   else
9902     g_print ("%10.1f\n", dt_first);
9903 }
9904
9905 void
9906 do_bench (char* what, int num)
9907 {
9908   int i;
9909   GtkWidget *widget;
9910   void (* fn) (GtkWidget *widget);
9911   fn = NULL;
9912   widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9913
9914   if (g_ascii_strcasecmp (what, "ALL") == 0)
9915     {
9916       for (i = 0; i < nbuttons; i++)
9917         {
9918           if (!buttons[i].do_not_benchmark)
9919             do_real_bench (widget, buttons[i].func, buttons[i].label, num);
9920         }
9921
9922       return;
9923     }
9924   else
9925     {
9926       for (i = 0; i < nbuttons; i++)
9927         {
9928           if (strcmp (buttons[i].label, what) == 0)
9929             {
9930               fn = buttons[i].func;
9931               break;
9932             }
9933         }
9934       
9935       if (!fn)
9936         g_print ("Can't bench: \"%s\" not found.\n", what);
9937       else
9938         do_real_bench (widget, fn, buttons[i].label, num);
9939     }
9940 }
9941
9942 void 
9943 usage (void)
9944 {
9945   fprintf (stderr, "Usage: testgtk [--bench ALL|<bench>[:<count>]]\n");
9946   exit (1);
9947 }
9948
9949 int
9950 main (int argc, char *argv[])
9951 {
9952   GtkCssProvider *provider, *memory_provider;
9953   GdkDisplay *display;
9954   GdkScreen *screen;
9955   GtkBindingSet *binding_set;
9956   int i;
9957   gboolean done_benchmarks = FALSE;
9958
9959   srand (time (NULL));
9960
9961   test_init ();
9962
9963   g_set_application_name ("GTK+ Test Program");
9964
9965   gtk_init (&argc, &argv);
9966
9967   provider = gtk_css_provider_new ();
9968
9969   /* Check to see if we are being run from the correct
9970    * directory.
9971    */
9972   if (file_exists ("testgtk.css"))
9973     gtk_css_provider_load_from_path (provider, "testgtk.css", NULL);
9974   else if (file_exists ("tests/testgtk.css"))
9975     gtk_css_provider_load_from_path (provider, "tests/testgtk.css", NULL);
9976   else
9977     g_warning ("Couldn't find file \"testgtk.css\".");
9978
9979   display = gdk_display_get_default ();
9980   screen = gdk_display_get_default_screen (display);
9981
9982   gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER (provider),
9983                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
9984   g_object_unref (provider);
9985
9986   gtk_accelerator_set_default_mod_mask (GDK_SHIFT_MASK |
9987                                         GDK_CONTROL_MASK |
9988                                         GDK_MOD1_MASK | 
9989                                         GDK_META_MASK |
9990                                         GDK_SUPER_MASK |
9991                                         GDK_HYPER_MASK |
9992                                         GDK_MOD4_MASK);
9993   /*  benchmarking
9994    */
9995   for (i = 1; i < argc; i++)
9996     {
9997       if (strncmp (argv[i], "--bench", strlen("--bench")) == 0)
9998         {
9999           int num = 1;
10000           char *nextarg;
10001           char *what;
10002           char *count;
10003           
10004           nextarg = strchr (argv[i], '=');
10005           if (nextarg)
10006             nextarg++;
10007           else
10008             {
10009               i++;
10010               if (i == argc)
10011                 usage ();
10012               nextarg = argv[i];
10013             }
10014
10015           count = strchr (nextarg, ':');
10016           if (count)
10017             {
10018               what = g_strndup (nextarg, count - nextarg);
10019               count++;
10020               num = atoi (count);
10021               if (num <= 0)
10022                 usage ();
10023             }
10024           else
10025             what = g_strdup (nextarg);
10026
10027           do_bench (what, num ? num : 1);
10028           done_benchmarks = TRUE;
10029         }
10030       else
10031         usage ();
10032     }
10033   if (done_benchmarks)
10034     return 0;
10035
10036   /* bindings test
10037    */
10038   binding_set = gtk_binding_set_by_class (g_type_class_ref (GTK_TYPE_WIDGET));
10039   gtk_binding_entry_add_signal (binding_set,
10040                                 '9', GDK_CONTROL_MASK | GDK_RELEASE_MASK,
10041                                 "debug_msg",
10042                                 1,
10043                                 G_TYPE_STRING, "GtkWidgetClass <ctrl><release>9 test");
10044
10045   memory_provider = gtk_css_provider_new ();
10046   gtk_css_provider_load_from_data (memory_provider,
10047                                    "#testgtk-version-label {\n"
10048                                    "  color: #f00;\n"
10049                                    "  font: Sans 18;\n"
10050                                    "}",
10051                                    -1, NULL);
10052   gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER (memory_provider),
10053                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + 1);
10054
10055   create_main_window ();
10056
10057   gtk_main ();
10058
10059   if (1)
10060     {
10061       while (g_main_context_pending (NULL))
10062         g_main_context_iteration (NULL, FALSE);
10063 #if 0
10064       sleep (1);
10065       while (g_main_context_pending (NULL))
10066         g_main_context_iteration (NULL, FALSE);
10067 #endif
10068     }
10069   return 0;
10070 }