]> Pileus Git - ~andy/gtk/blob - tests/testgtk.c
testgtk: Remove deprecations from shapes test
[~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
6675   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
6676
6677   /*
6678    * Can't use event->x / event->y here 
6679    * because I need absolute coordinates.
6680    */
6681   gdk_window_get_device_position (gdk_screen_get_root_window (gtk_widget_get_screen (widget)),
6682                                   gdk_event_get_device ((GdkEvent *) event),
6683                                   &xp, &yp, NULL);
6684   gtk_window_move (GTK_WINDOW (widget), xp  - p->x, yp  - p->y);
6685 }
6686
6687 GtkWidget *
6688 shape_create_icon (GdkScreen *screen,
6689                    char      *xpm_file,
6690                    gint       x,
6691                    gint       y,
6692                    gint       px,
6693                    gint       py,
6694                    gint       window_type)
6695 {
6696   GtkWidget *window;
6697   GtkWidget *image;
6698   GtkWidget *fixed;
6699   CursorOffset* icon_pos;
6700   cairo_surface_t *mask;
6701   cairo_region_t *mask_region;
6702   GdkPixbuf *pixbuf;
6703   cairo_t *cr;
6704
6705   /*
6706    * GDK_WINDOW_TOPLEVEL works also, giving you a title border
6707    */
6708   window = gtk_window_new (window_type);
6709   gtk_window_set_screen (GTK_WINDOW (window), screen);
6710   
6711   fixed = gtk_fixed_new ();
6712   gtk_widget_set_size_request (fixed, 100, 100);
6713   gtk_container_add (GTK_CONTAINER (window), fixed);
6714   gtk_widget_show (fixed);
6715   
6716   gtk_widget_set_events (window, 
6717                          gtk_widget_get_events (window) |
6718                          GDK_BUTTON_MOTION_MASK |
6719                          GDK_POINTER_MOTION_HINT_MASK |
6720                          GDK_BUTTON_PRESS_MASK);
6721
6722   gtk_widget_realize (window);
6723
6724   pixbuf = gdk_pixbuf_new_from_file (xpm_file, NULL);
6725   g_assert (pixbuf); /* FIXME: error handling */
6726
6727   mask = cairo_image_surface_create (CAIRO_FORMAT_A1,
6728                                      gdk_pixbuf_get_width (pixbuf),
6729                                      gdk_pixbuf_get_height (pixbuf));
6730   cr = cairo_create (mask);
6731   gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
6732   cairo_paint (cr);
6733   cairo_destroy (cr);
6734
6735   mask_region = gdk_cairo_region_create_from_surface (mask);
6736                                                   
6737   cairo_region_translate (mask_region, px, py);
6738
6739   image = gtk_image_new_from_pixbuf (pixbuf);
6740   gtk_fixed_put (GTK_FIXED (fixed), image, px,py);
6741   gtk_widget_show (image);
6742   
6743   gtk_widget_shape_combine_region (window, mask_region);
6744   
6745   cairo_region_destroy (mask_region);
6746   cairo_surface_destroy (mask);
6747   g_object_unref (pixbuf);
6748
6749   g_signal_connect (window, "button_press_event",
6750                     G_CALLBACK (shape_pressed), NULL);
6751   g_signal_connect (window, "button_release_event",
6752                     G_CALLBACK (shape_released), NULL);
6753   g_signal_connect (window, "motion_notify_event",
6754                     G_CALLBACK (shape_motion), NULL);
6755
6756   icon_pos = g_new (CursorOffset, 1);
6757   g_object_set_data (G_OBJECT (window), "cursor_offset", icon_pos);
6758
6759   gtk_window_move (GTK_WINDOW (window), x, y);
6760   gtk_widget_show (window);
6761   
6762   return window;
6763 }
6764
6765 void 
6766 create_shapes (GtkWidget *widget)
6767 {
6768   /* Variables used by the Drag/Drop and Shape Window demos */
6769   static GtkWidget *modeller = NULL;
6770   static GtkWidget *sheets = NULL;
6771   static GtkWidget *rings = NULL;
6772   static GtkWidget *with_region = NULL;
6773   GdkScreen *screen = gtk_widget_get_screen (widget);
6774   
6775   if (!(file_exists ("Modeller.xpm") &&
6776         file_exists ("FilesQueue.xpm") &&
6777         file_exists ("3DRings.xpm")))
6778     return;
6779   
6780
6781   if (!modeller)
6782     {
6783       modeller = shape_create_icon (screen, "Modeller.xpm",
6784                                     440, 140, 0,0, GTK_WINDOW_POPUP);
6785
6786       g_signal_connect (modeller, "destroy",
6787                         G_CALLBACK (gtk_widget_destroyed),
6788                         &modeller);
6789     }
6790   else
6791     gtk_widget_destroy (modeller);
6792
6793   if (!sheets)
6794     {
6795       sheets = shape_create_icon (screen, "FilesQueue.xpm",
6796                                   580, 170, 0,0, GTK_WINDOW_POPUP);
6797
6798       g_signal_connect (sheets, "destroy",
6799                         G_CALLBACK (gtk_widget_destroyed),
6800                         &sheets);
6801
6802     }
6803   else
6804     gtk_widget_destroy (sheets);
6805
6806   if (!rings)
6807     {
6808       rings = shape_create_icon (screen, "3DRings.xpm",
6809                                  460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
6810
6811       g_signal_connect (rings, "destroy",
6812                         G_CALLBACK (gtk_widget_destroyed),
6813                         &rings);
6814     }
6815   else
6816     gtk_widget_destroy (rings);
6817
6818   if (!with_region)
6819     {
6820       cairo_region_t *region;
6821       gint x, y;
6822       
6823       with_region = shape_create_icon (screen, "3DRings.xpm",
6824                                        460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
6825
6826       gtk_window_set_decorated (GTK_WINDOW (with_region), FALSE);
6827       
6828       g_signal_connect (with_region, "destroy",
6829                         G_CALLBACK (gtk_widget_destroyed),
6830                         &with_region);
6831
6832       /* reset shape from mask to a region */
6833       x = 0;
6834       y = 0;
6835       region = cairo_region_create ();
6836
6837       while (x < 460)
6838         {
6839           while (y < 270)
6840             {
6841               GdkRectangle rect;
6842               rect.x = x;
6843               rect.y = y;
6844               rect.width = 10;
6845               rect.height = 10;
6846
6847               cairo_region_union_rectangle (region, &rect);
6848               
6849               y += 20;
6850             }
6851           y = 0;
6852           x += 20;
6853         }
6854
6855       gdk_window_shape_combine_region (gtk_widget_get_window (with_region),
6856                                        region,
6857                                        0, 0);
6858     }
6859   else
6860     gtk_widget_destroy (with_region);
6861 }
6862
6863 /*
6864  * WM Hints demo
6865  */
6866
6867 void
6868 create_wmhints (GtkWidget *widget)
6869 {
6870   static GtkWidget *window = NULL;
6871   GtkWidget *label;
6872   GtkWidget *separator;
6873   GtkWidget *button;
6874   GtkWidget *box1;
6875   GtkWidget *box2;
6876   GdkWindow *gdk_window;
6877   GdkPixbuf *pixbuf;
6878   GList *list;
6879
6880   if (!window)
6881     {
6882       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6883
6884       gtk_window_set_screen (GTK_WINDOW (window),
6885                              gtk_widget_get_screen (widget));
6886       
6887       g_signal_connect (window, "destroy",
6888                         G_CALLBACK (gtk_widget_destroyed),
6889                         &window);
6890
6891       gtk_window_set_title (GTK_WINDOW (window), "WM Hints");
6892       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6893
6894       gtk_widget_realize (window);
6895
6896       gdk_window = gtk_widget_get_window (window);
6897
6898       pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **) openfile);
6899       list = g_list_prepend (NULL, pixbuf);
6900
6901       gdk_window_set_icon_list (gdk_window, list);
6902       
6903       g_list_free (list);
6904       g_object_unref (pixbuf);
6905
6906       gdk_window_set_icon_name (gdk_window, "WMHints Test Icon");
6907   
6908       gdk_window_set_decorations (gdk_window, GDK_DECOR_ALL | GDK_DECOR_MENU);
6909       gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_RESIZE);
6910       
6911       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
6912       gtk_container_add (GTK_CONTAINER (window), box1);
6913       gtk_widget_show (box1);
6914
6915       label = gtk_label_new ("Try iconizing me!");
6916       gtk_widget_set_size_request (label, 150, 50);
6917       gtk_box_pack_start (GTK_BOX (box1), label, TRUE, TRUE, 0);
6918       gtk_widget_show (label);
6919
6920
6921       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
6922       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
6923       gtk_widget_show (separator);
6924
6925
6926       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
6927       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6928       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
6929       gtk_widget_show (box2);
6930
6931
6932       button = gtk_button_new_with_label ("close");
6933
6934       g_signal_connect_swapped (button, "clicked",
6935                                 G_CALLBACK (gtk_widget_destroy),
6936                                 window);
6937
6938       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
6939       gtk_widget_set_can_default (button, TRUE);
6940       gtk_widget_grab_default (button);
6941       gtk_widget_show (button);
6942     }
6943
6944   if (!gtk_widget_get_visible (window))
6945     gtk_widget_show (window);
6946   else
6947     gtk_widget_destroy (window);
6948 }
6949
6950
6951 /*
6952  * Window state tracking
6953  */
6954
6955 static gint
6956 window_state_callback (GtkWidget *widget,
6957                        GdkEventWindowState *event,
6958                        gpointer data)
6959 {
6960   GtkWidget *label = data;
6961   gchar *msg;
6962
6963   msg = g_strconcat (gtk_window_get_title (GTK_WINDOW (widget)), ": ",
6964                      (event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) ?
6965                      "withdrawn" : "not withdrawn", ", ",
6966                      (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) ?
6967                      "iconified" : "not iconified", ", ",
6968                      (event->new_window_state & GDK_WINDOW_STATE_STICKY) ?
6969                      "sticky" : "not sticky", ", ",
6970                      (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) ?
6971                      "maximized" : "not maximized", ", ",
6972                      (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) ?
6973                      "fullscreen" : "not fullscreen",
6974                      (event->new_window_state & GDK_WINDOW_STATE_ABOVE) ?
6975                      "above" : "not above", ", ",
6976                      (event->new_window_state & GDK_WINDOW_STATE_BELOW) ?
6977                      "below" : "not below", ", ",
6978                      NULL);
6979   
6980   gtk_label_set_text (GTK_LABEL (label), msg);
6981
6982   g_free (msg);
6983
6984   return FALSE;
6985 }
6986
6987 static GtkWidget*
6988 tracking_label (GtkWidget *window)
6989 {
6990   GtkWidget *label;
6991   GtkWidget *hbox;
6992   GtkWidget *button;
6993
6994   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
6995
6996   g_signal_connect_object (hbox,
6997                            "destroy",
6998                            G_CALLBACK (gtk_widget_destroy),
6999                            window,
7000                            G_CONNECT_SWAPPED);
7001   
7002   label = gtk_label_new ("<no window state events received>");
7003   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
7004   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
7005   
7006   g_signal_connect (window,
7007                     "window_state_event",
7008                     G_CALLBACK (window_state_callback),
7009                     label);
7010
7011   button = gtk_button_new_with_label ("Deiconify");
7012   g_signal_connect_object (button,
7013                            "clicked",
7014                            G_CALLBACK (gtk_window_deiconify),
7015                            window,
7016                            G_CONNECT_SWAPPED);
7017   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7018
7019   button = gtk_button_new_with_label ("Iconify");
7020   g_signal_connect_object (button,
7021                            "clicked",
7022                            G_CALLBACK (gtk_window_iconify),
7023                            window,
7024                            G_CONNECT_SWAPPED);
7025   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7026
7027   button = gtk_button_new_with_label ("Fullscreen");
7028   g_signal_connect_object (button,
7029                            "clicked",
7030                            G_CALLBACK (gtk_window_fullscreen),
7031                            window,
7032                            G_CONNECT_SWAPPED);
7033   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7034
7035   button = gtk_button_new_with_label ("Unfullscreen");
7036   g_signal_connect_object (button,
7037                            "clicked",
7038                            G_CALLBACK (gtk_window_unfullscreen),
7039                            window,
7040                            G_CONNECT_SWAPPED);
7041   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7042   
7043   button = gtk_button_new_with_label ("Present");
7044   g_signal_connect_object (button,
7045                            "clicked",
7046                            G_CALLBACK (gtk_window_present),
7047                            window,
7048                            G_CONNECT_SWAPPED);
7049   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7050
7051   button = gtk_button_new_with_label ("Show");
7052   g_signal_connect_object (button,
7053                            "clicked",
7054                            G_CALLBACK (gtk_widget_show),
7055                            window,
7056                            G_CONNECT_SWAPPED);
7057   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7058   
7059   gtk_widget_show_all (hbox);
7060   
7061   return hbox;
7062 }
7063
7064 void
7065 keep_window_above (GtkToggleButton *togglebutton, gpointer data)
7066 {
7067   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
7068
7069   gtk_window_set_keep_above (GTK_WINDOW (data),
7070                              gtk_toggle_button_get_active (togglebutton));
7071
7072   if (gtk_toggle_button_get_active (togglebutton))
7073     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
7074 }
7075
7076 void
7077 keep_window_below (GtkToggleButton *togglebutton, gpointer data)
7078 {
7079   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
7080
7081   gtk_window_set_keep_below (GTK_WINDOW (data),
7082                              gtk_toggle_button_get_active (togglebutton));
7083
7084   if (gtk_toggle_button_get_active (togglebutton))
7085     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
7086 }
7087
7088
7089 static GtkWidget*
7090 get_state_controls (GtkWidget *window)
7091 {
7092   GtkWidget *vbox;
7093   GtkWidget *button;
7094   GtkWidget *button_above;
7095   GtkWidget *button_below;
7096
7097   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
7098   
7099   button = gtk_button_new_with_label ("Stick");
7100   g_signal_connect_object (button,
7101                            "clicked",
7102                            G_CALLBACK (gtk_window_stick),
7103                            window,
7104                            G_CONNECT_SWAPPED);
7105   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7106
7107   button = gtk_button_new_with_label ("Unstick");
7108   g_signal_connect_object (button,
7109                            "clicked",
7110                            G_CALLBACK (gtk_window_unstick),
7111                            window,
7112                            G_CONNECT_SWAPPED);
7113   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7114   
7115   button = gtk_button_new_with_label ("Maximize");
7116   g_signal_connect_object (button,
7117                            "clicked",
7118                            G_CALLBACK (gtk_window_maximize),
7119                            window,
7120                            G_CONNECT_SWAPPED);
7121   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7122
7123   button = gtk_button_new_with_label ("Unmaximize");
7124   g_signal_connect_object (button,
7125                            "clicked",
7126                            G_CALLBACK (gtk_window_unmaximize),
7127                            window,
7128                            G_CONNECT_SWAPPED);
7129   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7130
7131   button = gtk_button_new_with_label ("Iconify");
7132   g_signal_connect_object (button,
7133                            "clicked",
7134                            G_CALLBACK (gtk_window_iconify),
7135                            window,
7136                            G_CONNECT_SWAPPED);
7137   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7138
7139   button = gtk_button_new_with_label ("Fullscreen");
7140   g_signal_connect_object (button,
7141                            "clicked",
7142                            G_CALLBACK (gtk_window_fullscreen),
7143                            window,
7144                            G_CONNECT_SWAPPED);
7145   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7146
7147   button = gtk_button_new_with_label ("Unfullscreen");
7148   g_signal_connect_object (button,
7149                            "clicked",
7150                            G_CALLBACK (gtk_window_unfullscreen),
7151                            window,
7152                            G_CONNECT_SWAPPED);
7153   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7154
7155   button_above = gtk_toggle_button_new_with_label ("Keep above");
7156   g_signal_connect (button_above,
7157                     "toggled",
7158                     G_CALLBACK (keep_window_above),
7159                     window);
7160   gtk_box_pack_start (GTK_BOX (vbox), button_above, FALSE, FALSE, 0);
7161
7162   button_below = gtk_toggle_button_new_with_label ("Keep below");
7163   g_signal_connect (button_below,
7164                     "toggled",
7165                     G_CALLBACK (keep_window_below),
7166                     window);
7167   gtk_box_pack_start (GTK_BOX (vbox), button_below, FALSE, FALSE, 0);
7168
7169   g_object_set_data (G_OBJECT (button_above), "radio", button_below);
7170   g_object_set_data (G_OBJECT (button_below), "radio", button_above);
7171
7172   button = gtk_button_new_with_label ("Hide (withdraw)");
7173   g_signal_connect_object (button,
7174                            "clicked",
7175                            G_CALLBACK (gtk_widget_hide),
7176                            window,
7177                            G_CONNECT_SWAPPED);
7178   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7179   
7180   gtk_widget_show_all (vbox);
7181
7182   return vbox;
7183 }
7184
7185 void
7186 create_window_states (GtkWidget *widget)
7187 {
7188   static GtkWidget *window = NULL;
7189   GtkWidget *label;
7190   GtkWidget *box1;
7191   GtkWidget *iconified;
7192   GtkWidget *normal;
7193   GtkWidget *controls;
7194
7195   if (!window)
7196     {
7197       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7198       gtk_window_set_screen (GTK_WINDOW (window),
7199                              gtk_widget_get_screen (widget));
7200
7201       g_signal_connect (window, "destroy",
7202                         G_CALLBACK (gtk_widget_destroyed),
7203                         &window);
7204
7205       gtk_window_set_title (GTK_WINDOW (window), "Window states");
7206       
7207       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
7208       gtk_container_add (GTK_CONTAINER (window), box1);
7209
7210       iconified = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7211
7212       gtk_window_set_screen (GTK_WINDOW (iconified),
7213                              gtk_widget_get_screen (widget));
7214       
7215       g_signal_connect_object (iconified, "destroy",
7216                                G_CALLBACK (gtk_widget_destroy),
7217                                window,
7218                                G_CONNECT_SWAPPED);
7219       gtk_window_iconify (GTK_WINDOW (iconified));
7220       gtk_window_set_title (GTK_WINDOW (iconified), "Iconified initially");
7221       controls = get_state_controls (iconified);
7222       gtk_container_add (GTK_CONTAINER (iconified), controls);
7223       
7224       normal = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7225
7226       gtk_window_set_screen (GTK_WINDOW (normal),
7227                              gtk_widget_get_screen (widget));
7228       
7229       g_signal_connect_object (normal, "destroy",
7230                                G_CALLBACK (gtk_widget_destroy),
7231                                window,
7232                                G_CONNECT_SWAPPED);
7233       
7234       gtk_window_set_title (GTK_WINDOW (normal), "Deiconified initially");
7235       controls = get_state_controls (normal);
7236       gtk_container_add (GTK_CONTAINER (normal), controls);
7237       
7238       label = tracking_label (iconified);
7239       gtk_container_add (GTK_CONTAINER (box1), label);
7240
7241       label = tracking_label (normal);
7242       gtk_container_add (GTK_CONTAINER (box1), label);
7243
7244       gtk_widget_show_all (iconified);
7245       gtk_widget_show_all (normal);
7246       gtk_widget_show_all (box1);
7247     }
7248
7249   if (!gtk_widget_get_visible (window))
7250     gtk_widget_show (window);
7251   else
7252     gtk_widget_destroy (window);
7253 }
7254
7255 /*
7256  * Window sizing
7257  */
7258
7259 static gint
7260 configure_event_callback (GtkWidget *widget,
7261                           GdkEventConfigure *event,
7262                           gpointer data)
7263 {
7264   GtkWidget *label = data;
7265   gchar *msg;
7266   gint x, y;
7267   
7268   gtk_window_get_position (GTK_WINDOW (widget), &x, &y);
7269   
7270   msg = g_strdup_printf ("event: %d,%d  %d x %d\n"
7271                          "position: %d, %d",
7272                          event->x, event->y, event->width, event->height,
7273                          x, y);
7274   
7275   gtk_label_set_text (GTK_LABEL (label), msg);
7276
7277   g_free (msg);
7278
7279   return FALSE;
7280 }
7281
7282 static void
7283 get_ints (GtkWidget *window,
7284           gint      *a,
7285           gint      *b)
7286 {
7287   GtkWidget *spin1;
7288   GtkWidget *spin2;
7289
7290   spin1 = g_object_get_data (G_OBJECT (window), "spin1");
7291   spin2 = g_object_get_data (G_OBJECT (window), "spin2");
7292
7293   *a = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin1));
7294   *b = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin2));
7295 }
7296
7297 static void
7298 set_size_callback (GtkWidget *widget,
7299                    gpointer   data)
7300 {
7301   gint w, h;
7302   
7303   get_ints (data, &w, &h);
7304
7305   gtk_window_resize (GTK_WINDOW (g_object_get_data (data, "target")), w, h);
7306 }
7307
7308 static void
7309 unset_default_size_callback (GtkWidget *widget,
7310                              gpointer   data)
7311 {
7312   gtk_window_set_default_size (g_object_get_data (data, "target"),
7313                                -1, -1);
7314 }
7315
7316 static void
7317 set_default_size_callback (GtkWidget *widget,
7318                            gpointer   data)
7319 {
7320   gint w, h;
7321   
7322   get_ints (data, &w, &h);
7323
7324   gtk_window_set_default_size (g_object_get_data (data, "target"),
7325                                w, h);
7326 }
7327
7328 static void
7329 unset_size_request_callback (GtkWidget *widget,
7330                              gpointer   data)
7331 {
7332   gtk_widget_set_size_request (g_object_get_data (data, "target"),
7333                                -1, -1);
7334 }
7335
7336 static void
7337 set_size_request_callback (GtkWidget *widget,
7338                            gpointer   data)
7339 {
7340   gint w, h;
7341   
7342   get_ints (data, &w, &h);
7343
7344   gtk_widget_set_size_request (g_object_get_data (data, "target"),
7345                                w, h);
7346 }
7347
7348 static void
7349 set_location_callback (GtkWidget *widget,
7350                        gpointer   data)
7351 {
7352   gint x, y;
7353   
7354   get_ints (data, &x, &y);
7355
7356   gtk_window_move (g_object_get_data (data, "target"), x, y);
7357 }
7358
7359 static void
7360 move_to_position_callback (GtkWidget *widget,
7361                            gpointer   data)
7362 {
7363   gint x, y;
7364   GtkWindow *window;
7365
7366   window = g_object_get_data (data, "target");
7367   
7368   gtk_window_get_position (window, &x, &y);
7369
7370   gtk_window_move (window, x, y);
7371 }
7372
7373 static void
7374 set_geometry_callback (GtkWidget *entry,
7375                        gpointer   data)
7376 {
7377   gchar *text;
7378   GtkWindow *target;
7379
7380   target = GTK_WINDOW (g_object_get_data (G_OBJECT (data), "target"));
7381   
7382   text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
7383
7384   if (!gtk_window_parse_geometry (target, text))
7385     g_print ("Bad geometry string '%s'\n", text);
7386
7387   g_free (text);
7388 }
7389
7390 static void
7391 resizable_callback (GtkWidget *widget,
7392                      gpointer   data)
7393 {
7394   g_object_set (g_object_get_data (data, "target"),
7395                 "resizable", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)),
7396                 NULL);
7397 }
7398
7399 static void
7400 gravity_selected (GtkWidget *widget,
7401                   gpointer   data)
7402 {
7403   gtk_window_set_gravity (GTK_WINDOW (g_object_get_data (data, "target")),
7404                           gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) + GDK_GRAVITY_NORTH_WEST);
7405 }
7406
7407 static void
7408 pos_selected (GtkWidget *widget,
7409               gpointer   data)
7410 {
7411   gtk_window_set_position (GTK_WINDOW (g_object_get_data (data, "target")),
7412                            gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) + GTK_WIN_POS_NONE);
7413 }
7414
7415 static void
7416 move_gravity_window_to_current_position (GtkWidget *widget,
7417                                          gpointer   data)
7418 {
7419   gint x, y;
7420   GtkWindow *window;
7421
7422   window = GTK_WINDOW (data);    
7423   
7424   gtk_window_get_position (window, &x, &y);
7425
7426   gtk_window_move (window, x, y);
7427 }
7428
7429 static void
7430 get_screen_corner (GtkWindow *window,
7431                    gint      *x,
7432                    gint      *y)
7433 {
7434   int w, h;
7435   GdkScreen * screen = gtk_window_get_screen (window);
7436   
7437   gtk_window_get_size (GTK_WINDOW (window), &w, &h);
7438
7439   switch (gtk_window_get_gravity (window))
7440     {
7441     case GDK_GRAVITY_SOUTH_EAST:
7442       *x = gdk_screen_get_width (screen) - w;
7443       *y = gdk_screen_get_height (screen) - h;
7444       break;
7445
7446     case GDK_GRAVITY_NORTH_EAST:
7447       *x = gdk_screen_get_width (screen) - w;
7448       *y = 0;
7449       break;
7450
7451     case GDK_GRAVITY_SOUTH_WEST:
7452       *x = 0;
7453       *y = gdk_screen_get_height (screen) - h;
7454       break;
7455
7456     case GDK_GRAVITY_NORTH_WEST:
7457       *x = 0;
7458       *y = 0;
7459       break;
7460       
7461     case GDK_GRAVITY_SOUTH:
7462       *x = (gdk_screen_get_width (screen) - w) / 2;
7463       *y = gdk_screen_get_height (screen) - h;
7464       break;
7465
7466     case GDK_GRAVITY_NORTH:
7467       *x = (gdk_screen_get_width (screen) - w) / 2;
7468       *y = 0;
7469       break;
7470
7471     case GDK_GRAVITY_WEST:
7472       *x = 0;
7473       *y = (gdk_screen_get_height (screen) - h) / 2;
7474       break;
7475
7476     case GDK_GRAVITY_EAST:
7477       *x = gdk_screen_get_width (screen) - w;
7478       *y = (gdk_screen_get_height (screen) - h) / 2;
7479       break;
7480
7481     case GDK_GRAVITY_CENTER:
7482       *x = (gdk_screen_get_width (screen) - w) / 2;
7483       *y = (gdk_screen_get_height (screen) - h) / 2;
7484       break;
7485
7486     case GDK_GRAVITY_STATIC:
7487       /* pick some random numbers */
7488       *x = 350;
7489       *y = 350;
7490       break;
7491
7492     default:
7493       g_assert_not_reached ();
7494       break;
7495     }
7496 }
7497
7498 static void
7499 move_gravity_window_to_starting_position (GtkWidget *widget,
7500                                           gpointer   data)
7501 {
7502   gint x, y;
7503   GtkWindow *window;
7504
7505   window = GTK_WINDOW (data);    
7506   
7507   get_screen_corner (window,
7508                      &x, &y);
7509   
7510   gtk_window_move (window, x, y);
7511 }
7512
7513 static GtkWidget*
7514 make_gravity_window (GtkWidget   *destroy_with,
7515                      GdkGravity   gravity,
7516                      const gchar *title)
7517 {
7518   GtkWidget *window;
7519   GtkWidget *button;
7520   GtkWidget *vbox;
7521   int x, y;
7522   
7523   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7524
7525   gtk_window_set_screen (GTK_WINDOW (window),
7526                          gtk_widget_get_screen (destroy_with));
7527
7528   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
7529   gtk_widget_show (vbox);
7530   
7531   gtk_container_add (GTK_CONTAINER (window), vbox);
7532   gtk_window_set_title (GTK_WINDOW (window), title);
7533   gtk_window_set_gravity (GTK_WINDOW (window), gravity);
7534
7535   g_signal_connect_object (destroy_with,
7536                            "destroy",
7537                            G_CALLBACK (gtk_widget_destroy),
7538                            window,
7539                            G_CONNECT_SWAPPED);
7540
7541   
7542   button = gtk_button_new_with_mnemonic ("_Move to current position");
7543
7544   g_signal_connect (button, "clicked",
7545                     G_CALLBACK (move_gravity_window_to_current_position),
7546                     window);
7547
7548   gtk_container_add (GTK_CONTAINER (vbox), button);
7549   gtk_widget_show (button);
7550
7551   button = gtk_button_new_with_mnemonic ("Move to _starting position");
7552
7553   g_signal_connect (button, "clicked",
7554                     G_CALLBACK (move_gravity_window_to_starting_position),
7555                     window);
7556
7557   gtk_container_add (GTK_CONTAINER (vbox), button);
7558   gtk_widget_show (button);
7559   
7560   /* Pretend this is the result of --geometry.
7561    * DO NOT COPY THIS CODE unless you are setting --geometry results,
7562    * and in that case you probably should just use gtk_window_parse_geometry().
7563    * AGAIN, DO NOT SET GDK_HINT_USER_POS! It violates the ICCCM unless
7564    * you are parsing --geometry or equivalent.
7565    */
7566   gtk_window_set_geometry_hints (GTK_WINDOW (window),
7567                                  NULL, NULL,
7568                                  GDK_HINT_USER_POS);
7569
7570   gtk_window_set_default_size (GTK_WINDOW (window),
7571                                200, 200);
7572
7573   get_screen_corner (GTK_WINDOW (window), &x, &y);
7574   
7575   gtk_window_move (GTK_WINDOW (window),
7576                    x, y);
7577   
7578   return window;
7579 }
7580
7581 static void
7582 do_gravity_test (GtkWidget *widget,
7583                  gpointer   data)
7584 {
7585   GtkWidget *destroy_with = data;
7586   GtkWidget *window;
7587   
7588   /* We put a window at each gravity point on the screen. */
7589   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_WEST,
7590                                 "NorthWest");
7591   gtk_widget_show (window);
7592   
7593   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_EAST,
7594                                 "SouthEast");
7595   gtk_widget_show (window);
7596
7597   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_EAST,
7598                                 "NorthEast");
7599   gtk_widget_show (window);
7600
7601   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_WEST,
7602                                 "SouthWest");
7603   gtk_widget_show (window);
7604
7605   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH,
7606                                 "South");
7607   gtk_widget_show (window);
7608
7609   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH,
7610                                 "North");
7611   gtk_widget_show (window);
7612
7613   
7614   window = make_gravity_window (destroy_with, GDK_GRAVITY_WEST,
7615                                 "West");
7616   gtk_widget_show (window);
7617
7618     
7619   window = make_gravity_window (destroy_with, GDK_GRAVITY_EAST,
7620                                 "East");
7621   gtk_widget_show (window);
7622
7623   window = make_gravity_window (destroy_with, GDK_GRAVITY_CENTER,
7624                                 "Center");
7625   gtk_widget_show (window);
7626
7627   window = make_gravity_window (destroy_with, GDK_GRAVITY_STATIC,
7628                                 "Static");
7629   gtk_widget_show (window);
7630 }
7631
7632 static GtkWidget*
7633 window_controls (GtkWidget *window)
7634 {
7635   GtkWidget *control_window;
7636   GtkWidget *label;
7637   GtkWidget *vbox;
7638   GtkWidget *button;
7639   GtkWidget *spin;
7640   GtkAdjustment *adjustment;
7641   GtkWidget *entry;
7642   GtkWidget *om;
7643   gint i;
7644   
7645   control_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7646
7647   gtk_window_set_screen (GTK_WINDOW (control_window),
7648                          gtk_widget_get_screen (window));
7649
7650   gtk_window_set_title (GTK_WINDOW (control_window), "Size controls");
7651   
7652   g_object_set_data (G_OBJECT (control_window),
7653                      "target",
7654                      window);
7655   
7656   g_signal_connect_object (control_window,
7657                            "destroy",
7658                            G_CALLBACK (gtk_widget_destroy),
7659                            window,
7660                            G_CONNECT_SWAPPED);
7661
7662   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
7663   
7664   gtk_container_add (GTK_CONTAINER (control_window), vbox);
7665   
7666   label = gtk_label_new ("<no configure events>");
7667   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
7668   
7669   g_signal_connect (window,
7670                     "configure_event",
7671                     G_CALLBACK (configure_event_callback),
7672                     label);
7673
7674   adjustment = gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0, 5.0, 0.0);
7675   spin = gtk_spin_button_new (adjustment, 0, 0);
7676
7677   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
7678
7679   g_object_set_data (G_OBJECT (control_window), "spin1", spin);
7680
7681   adjustment = gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0, 5.0, 0.0);
7682   spin = gtk_spin_button_new (adjustment, 0, 0);
7683
7684   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
7685
7686   g_object_set_data (G_OBJECT (control_window), "spin2", spin);
7687
7688   entry = gtk_entry_new ();
7689   gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
7690
7691   g_signal_connect (entry, "changed",
7692                     G_CALLBACK (set_geometry_callback),
7693                     control_window);
7694
7695   button = gtk_button_new_with_label ("Show gravity test windows");
7696   g_signal_connect_swapped (button,
7697                             "clicked",
7698                             G_CALLBACK (do_gravity_test),
7699                             control_window);
7700   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7701
7702   button = gtk_button_new_with_label ("Reshow with initial size");
7703   g_signal_connect_object (button,
7704                            "clicked",
7705                            G_CALLBACK (gtk_window_reshow_with_initial_size),
7706                            window,
7707                            G_CONNECT_SWAPPED);
7708   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7709   
7710   button = gtk_button_new_with_label ("Queue resize");
7711   g_signal_connect_object (button,
7712                            "clicked",
7713                            G_CALLBACK (gtk_widget_queue_resize),
7714                            window,
7715                            G_CONNECT_SWAPPED);
7716   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7717   
7718   button = gtk_button_new_with_label ("Resize");
7719   g_signal_connect (button,
7720                     "clicked",
7721                     G_CALLBACK (set_size_callback),
7722                     control_window);
7723   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7724
7725   button = gtk_button_new_with_label ("Set default size");
7726   g_signal_connect (button,
7727                     "clicked",
7728                     G_CALLBACK (set_default_size_callback),
7729                     control_window);
7730   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7731
7732   button = gtk_button_new_with_label ("Unset default size");
7733   g_signal_connect (button,
7734                     "clicked",
7735                     G_CALLBACK (unset_default_size_callback),
7736                     control_window);
7737   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7738   
7739   button = gtk_button_new_with_label ("Set size request");
7740   g_signal_connect (button,
7741                     "clicked",
7742                     G_CALLBACK (set_size_request_callback),
7743                     control_window);
7744   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7745
7746   button = gtk_button_new_with_label ("Unset size request");
7747   g_signal_connect (button,
7748                     "clicked",
7749                     G_CALLBACK (unset_size_request_callback),
7750                     control_window);
7751   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7752   
7753   button = gtk_button_new_with_label ("Move");
7754   g_signal_connect (button,
7755                     "clicked",
7756                     G_CALLBACK (set_location_callback),
7757                     control_window);
7758   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7759
7760   button = gtk_button_new_with_label ("Move to current position");
7761   g_signal_connect (button,
7762                     "clicked",
7763                     G_CALLBACK (move_to_position_callback),
7764                     control_window);
7765   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7766
7767   button = gtk_check_button_new_with_label ("Allow resize");
7768   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
7769   g_signal_connect (button,
7770                     "toggled",
7771                     G_CALLBACK (resizable_callback),
7772                     control_window);
7773   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7774   
7775   button = gtk_button_new_with_mnemonic ("_Show");
7776   g_signal_connect_object (button,
7777                            "clicked",
7778                            G_CALLBACK (gtk_widget_show),
7779                            window,
7780                            G_CONNECT_SWAPPED);
7781   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7782
7783   button = gtk_button_new_with_mnemonic ("_Hide");
7784   g_signal_connect_object (button,
7785                            "clicked",
7786                            G_CALLBACK (gtk_widget_hide),
7787                            window,
7788                            G_CONNECT_SWAPPED);
7789   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7790
7791   om = gtk_combo_box_text_new ();
7792   i = 0;
7793   while (i < 10)
7794     {
7795       static gchar *names[] = {
7796         "GDK_GRAVITY_NORTH_WEST",
7797         "GDK_GRAVITY_NORTH",
7798         "GDK_GRAVITY_NORTH_EAST",
7799         "GDK_GRAVITY_WEST",
7800         "GDK_GRAVITY_CENTER",
7801         "GDK_GRAVITY_EAST",
7802         "GDK_GRAVITY_SOUTH_WEST",
7803         "GDK_GRAVITY_SOUTH",
7804         "GDK_GRAVITY_SOUTH_EAST",
7805         "GDK_GRAVITY_STATIC",
7806         NULL
7807       };
7808
7809       g_assert (names[i]);
7810       gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (om), names[i]);
7811
7812       ++i;
7813     }
7814   
7815   g_signal_connect (om,
7816                     "changed",
7817                     G_CALLBACK (gravity_selected),
7818                     control_window);
7819
7820   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
7821
7822
7823   om = gtk_combo_box_text_new ();
7824   i = 0;
7825   while (i < 5)
7826     {
7827       static gchar *names[] = {
7828         "GTK_WIN_POS_NONE",
7829         "GTK_WIN_POS_CENTER",
7830         "GTK_WIN_POS_MOUSE",
7831         "GTK_WIN_POS_CENTER_ALWAYS",
7832         "GTK_WIN_POS_CENTER_ON_PARENT",
7833         NULL
7834       };
7835
7836       g_assert (names[i]);
7837       gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (om), names[i]);
7838
7839       ++i;
7840     }
7841
7842   g_signal_connect (om,
7843                     "changed",
7844                     G_CALLBACK (pos_selected),
7845                     control_window);
7846
7847   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
7848   
7849   gtk_widget_show_all (vbox);
7850   
7851   return control_window;
7852 }
7853
7854 void
7855 create_window_sizing (GtkWidget *widget)
7856 {
7857   static GtkWidget *window = NULL;
7858   static GtkWidget *target_window = NULL;
7859
7860   if (!target_window)
7861     {
7862       GtkWidget *label;
7863       
7864       target_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7865       gtk_window_set_screen (GTK_WINDOW (target_window),
7866                              gtk_widget_get_screen (widget));
7867       label = gtk_label_new (NULL);
7868       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");
7869       gtk_container_add (GTK_CONTAINER (target_window), label);
7870       gtk_widget_show (label);
7871       
7872       g_signal_connect (target_window, "destroy",
7873                         G_CALLBACK (gtk_widget_destroyed),
7874                         &target_window);
7875
7876       window = window_controls (target_window);
7877       
7878       g_signal_connect (window, "destroy",
7879                         G_CALLBACK (gtk_widget_destroyed),
7880                         &window);
7881       
7882       gtk_window_set_title (GTK_WINDOW (target_window), "Window to size");
7883     }
7884
7885   /* don't show target window by default, we want to allow testing
7886    * of behavior on first show.
7887    */
7888   
7889   if (!gtk_widget_get_visible (window))
7890     gtk_widget_show (window);
7891   else
7892     gtk_widget_destroy (window);
7893 }
7894
7895 /*
7896  * GtkProgressBar
7897  */
7898
7899 typedef struct _ProgressData {
7900   GtkWidget *window;
7901   GtkWidget *pbar;
7902   GtkWidget *block_spin;
7903   GtkWidget *x_align_spin;
7904   GtkWidget *y_align_spin;
7905   GtkWidget *step_spin;
7906   GtkWidget *act_blocks_spin;
7907   GtkWidget *label;
7908   GtkWidget *omenu1;
7909   GtkWidget *elmenu;
7910   GtkWidget *omenu2;
7911   GtkWidget *entry;
7912   int timer;
7913   gboolean activity;
7914 } ProgressData;
7915
7916 gboolean
7917 progress_timeout (gpointer data)
7918 {
7919   ProgressData *pdata = data;
7920   gdouble new_val;
7921   gchar *text;
7922
7923   if (pdata->activity)
7924     {
7925       gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pdata->pbar));
7926
7927       text = g_strdup_printf ("%s", "???");
7928     }
7929   else
7930     {
7931       new_val = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (pdata->pbar)) + 0.01;
7932       if (new_val > 1.00)
7933         new_val = 0.00;
7934       gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pdata->pbar), new_val);
7935
7936       text = g_strdup_printf ("%.0f%%", 100 * new_val);
7937     }
7938
7939   gtk_label_set_text (GTK_LABEL (pdata->label), text);
7940   g_free (text);
7941
7942   return TRUE;
7943 }
7944
7945 static void
7946 destroy_progress (GtkWidget     *widget,
7947                   ProgressData **pdata)
7948 {
7949   if ((*pdata)->timer)
7950     {
7951       g_source_remove ((*pdata)->timer);
7952       (*pdata)->timer = 0;
7953     }
7954   (*pdata)->window = NULL;
7955   g_free (*pdata);
7956   *pdata = NULL;
7957 }
7958
7959 static void
7960 progressbar_toggle_orientation (GtkWidget *widget, gpointer data)
7961 {
7962   ProgressData *pdata;
7963   gint i;
7964
7965   pdata = (ProgressData *) data;
7966
7967   if (!gtk_widget_get_mapped (widget))
7968     return;
7969
7970   i = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
7971
7972   if (i == 0 || i == 1)
7973     gtk_orientable_set_orientation (GTK_ORIENTABLE (pdata->pbar), GTK_ORIENTATION_HORIZONTAL);
7974   else
7975     gtk_orientable_set_orientation (GTK_ORIENTABLE (pdata->pbar), GTK_ORIENTATION_VERTICAL);
7976  
7977   if (i == 1 || i == 2)
7978     gtk_progress_bar_set_inverted (GTK_PROGRESS_BAR (pdata->pbar), TRUE);
7979   else
7980     gtk_progress_bar_set_inverted (GTK_PROGRESS_BAR (pdata->pbar), FALSE);
7981 }
7982
7983 static void
7984 toggle_show_text (GtkWidget *widget, ProgressData *pdata)
7985 {
7986   gboolean active;
7987
7988   active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
7989   gtk_progress_bar_set_show_text (GTK_PROGRESS_BAR (pdata->pbar), active);
7990 }
7991
7992 static void
7993 progressbar_toggle_ellipsize (GtkWidget *widget,
7994                               gpointer   data)
7995 {
7996   ProgressData *pdata = data;
7997   if (gtk_widget_is_drawable (widget))
7998     {
7999       gint i = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
8000       gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (pdata->pbar), i);
8001     }
8002 }
8003
8004 static void
8005 toggle_activity_mode (GtkWidget *widget, ProgressData *pdata)
8006 {
8007   pdata->activity = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
8008 }
8009
8010 static void
8011 toggle_running (GtkWidget *widget, ProgressData *pdata)
8012 {
8013   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
8014     {
8015       if (pdata->timer == 0)
8016         pdata->timer = g_timeout_add (100, (GSourceFunc)progress_timeout, pdata);
8017     }
8018   else
8019     {
8020       if (pdata->timer != 0)
8021         {
8022           g_source_remove (pdata->timer);
8023           pdata->timer = 0;
8024         }
8025     }
8026 }
8027
8028 static void
8029 entry_changed (GtkWidget *widget, ProgressData *pdata)
8030 {
8031   gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata->pbar),
8032                           gtk_entry_get_text (GTK_ENTRY (pdata->entry)));
8033 }
8034
8035 void
8036 create_progress_bar (GtkWidget *widget)
8037 {
8038   GtkWidget *action_area, *content_area;
8039   GtkWidget *button;
8040   GtkWidget *vbox;
8041   GtkWidget *vbox2;
8042   GtkWidget *hbox;
8043   GtkWidget *check;
8044   GtkWidget *frame;
8045   GtkWidget *grid;
8046   GtkWidget *label;
8047   GtkWidget *align;
8048   static ProgressData *pdata = NULL;
8049
8050   static gchar *items1[] =
8051   {
8052     "Left-Right",
8053     "Right-Left",
8054     "Bottom-Top",
8055     "Top-Bottom"
8056   };
8057
8058     static char *ellipsize_items[] = {
8059     "None",     // PANGO_ELLIPSIZE_NONE,
8060     "Start",    // PANGO_ELLIPSIZE_START,
8061     "Middle",   // PANGO_ELLIPSIZE_MIDDLE,
8062     "End",      // PANGO_ELLIPSIZE_END
8063   };
8064   
8065   if (!pdata)
8066     pdata = g_new0 (ProgressData, 1);
8067
8068   if (!pdata->window)
8069     {
8070       pdata->window = gtk_dialog_new ();
8071
8072       gtk_window_set_screen (GTK_WINDOW (pdata->window),
8073                              gtk_widget_get_screen (widget));
8074
8075       gtk_window_set_resizable (GTK_WINDOW (pdata->window), TRUE);
8076
8077       g_signal_connect (pdata->window, "destroy",
8078                         G_CALLBACK (destroy_progress),
8079                         &pdata);
8080       pdata->timer = 0;
8081
8082       content_area = gtk_dialog_get_content_area (GTK_DIALOG (pdata->window));
8083       action_area = gtk_dialog_get_action_area (GTK_DIALOG (pdata->window));
8084
8085       gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
8086       gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);
8087
8088       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
8089       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
8090       gtk_box_pack_start (GTK_BOX (content_area), vbox, FALSE, TRUE, 0);
8091
8092       frame = gtk_frame_new ("Progress");
8093       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
8094
8095       vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
8096       gtk_container_add (GTK_CONTAINER (frame), vbox2);
8097
8098       align = gtk_alignment_new (0.5, 0.5, 0, 0);
8099       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
8100
8101       pdata->pbar = gtk_progress_bar_new ();
8102       gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (pdata->pbar),
8103                                       PANGO_ELLIPSIZE_MIDDLE);
8104
8105       gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
8106
8107       align = gtk_alignment_new (0.5, 0.5, 0, 0);
8108       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
8109
8110       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
8111       gtk_container_add (GTK_CONTAINER (align), hbox);
8112       label = gtk_label_new ("Label updated by user :"); 
8113       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
8114       pdata->label = gtk_label_new ("");
8115       gtk_box_pack_start (GTK_BOX (hbox), pdata->label, FALSE, TRUE, 0);
8116
8117       frame = gtk_frame_new ("Options");
8118       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
8119
8120       vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
8121       gtk_container_add (GTK_CONTAINER (frame), vbox2);
8122
8123       grid = gtk_grid_new ();
8124       gtk_grid_set_row_spacing (GTK_GRID (grid), 10);
8125       gtk_grid_set_column_spacing (GTK_GRID (grid), 10);
8126       gtk_box_pack_start (GTK_BOX (vbox2), grid, FALSE, TRUE, 0);
8127
8128       label = gtk_label_new ("Orientation :");
8129       gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
8130       gtk_widget_set_halign (label, GTK_ALIGN_START);
8131       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
8132
8133       pdata->omenu1 = build_option_menu (items1, 4, 0,
8134                                          progressbar_toggle_orientation,
8135                                          pdata);
8136       gtk_grid_attach (GTK_GRID (grid), pdata->omenu1, 1, 0, 1, 1);
8137       
8138       check = gtk_check_button_new_with_label ("Running");
8139       g_signal_connect (check, "toggled",
8140                         G_CALLBACK (toggle_running),
8141                         pdata);
8142       gtk_grid_attach (GTK_GRID (grid), check, 0, 1, 2, 1);
8143       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
8144
8145       check = gtk_check_button_new_with_label ("Show text");
8146       g_signal_connect (check, "clicked",
8147                         G_CALLBACK (toggle_show_text),
8148                         pdata);
8149       gtk_grid_attach (GTK_GRID (grid), check, 0, 2, 1, 1);
8150
8151       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
8152       gtk_grid_attach (GTK_GRID (grid), hbox, 1, 2, 1, 1);
8153
8154       label = gtk_label_new ("Text: ");
8155       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
8156
8157       pdata->entry = gtk_entry_new ();
8158       gtk_widget_set_hexpand (pdata->entry, TRUE);
8159       g_signal_connect (pdata->entry, "changed",
8160                         G_CALLBACK (entry_changed),
8161                         pdata);
8162       gtk_box_pack_start (GTK_BOX (hbox), pdata->entry, TRUE, TRUE, 0);
8163       gtk_widget_set_size_request (pdata->entry, 100, -1);
8164
8165       label = gtk_label_new ("Ellipsize text :");
8166       gtk_grid_attach (GTK_GRID (grid), label, 0, 10, 1, 1);
8167
8168       gtk_widget_set_halign (label, GTK_ALIGN_START);
8169       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
8170       pdata->elmenu = build_option_menu (ellipsize_items,
8171                                          sizeof (ellipsize_items) / sizeof (ellipsize_items[0]),
8172                                          2, // PANGO_ELLIPSIZE_MIDDLE
8173                                          progressbar_toggle_ellipsize,
8174                                          pdata);
8175       gtk_grid_attach (GTK_GRID (grid), pdata->elmenu, 1, 10, 1, 1);
8176
8177       check = gtk_check_button_new_with_label ("Activity mode");
8178       g_signal_connect (check, "clicked",
8179                         G_CALLBACK (toggle_activity_mode), pdata);
8180       gtk_grid_attach (GTK_GRID (grid), check, 0, 15, 1, 1);
8181
8182       button = gtk_button_new_with_label ("close");
8183       g_signal_connect_swapped (button, "clicked",
8184                                 G_CALLBACK (gtk_widget_destroy),
8185                                 pdata->window);
8186       gtk_widget_set_can_default (button, TRUE);
8187       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
8188       gtk_widget_grab_default (button);
8189     }
8190
8191   if (!gtk_widget_get_visible (pdata->window))
8192     gtk_widget_show_all (pdata->window);
8193   else
8194     gtk_widget_destroy (pdata->window);
8195 }
8196
8197 /*
8198  * Properties
8199  */
8200
8201 typedef struct {
8202   int x;
8203   int y;
8204   gboolean found;
8205   gboolean first;
8206   GtkWidget *res_widget;
8207 } FindWidgetData;
8208
8209 static void
8210 find_widget (GtkWidget *widget, FindWidgetData *data)
8211 {
8212   GtkAllocation new_allocation;
8213   gint x_offset = 0;
8214   gint y_offset = 0;
8215
8216   gtk_widget_get_allocation (widget, &new_allocation);
8217
8218   if (data->found || !gtk_widget_get_mapped (widget))
8219     return;
8220
8221   /* Note that in the following code, we only count the
8222    * position as being inside a WINDOW widget if it is inside
8223    * widget->window; points that are outside of widget->window
8224    * but within the allocation are not counted. This is consistent
8225    * with the way we highlight drag targets.
8226    */
8227   if (gtk_widget_get_has_window (widget))
8228     {
8229       new_allocation.x = 0;
8230       new_allocation.y = 0;
8231     }
8232
8233   if (gtk_widget_get_parent (widget) && !data->first)
8234     {
8235       GdkWindow *window = gtk_widget_get_window (widget);
8236       while (window != gtk_widget_get_window (gtk_widget_get_parent (widget)))
8237         {
8238           gint tx, ty, twidth, theight;
8239           
8240           twidth = gdk_window_get_width (window);
8241           theight = gdk_window_get_height (window);
8242
8243           if (new_allocation.x < 0)
8244             {
8245               new_allocation.width += new_allocation.x;
8246               new_allocation.x = 0;
8247             }
8248           if (new_allocation.y < 0)
8249             {
8250               new_allocation.height += new_allocation.y;
8251               new_allocation.y = 0;
8252             }
8253           if (new_allocation.x + new_allocation.width > twidth)
8254             new_allocation.width = twidth - new_allocation.x;
8255           if (new_allocation.y + new_allocation.height > theight)
8256             new_allocation.height = theight - new_allocation.y;
8257
8258           gdk_window_get_position (window, &tx, &ty);
8259           new_allocation.x += tx;
8260           x_offset += tx;
8261           new_allocation.y += ty;
8262           y_offset += ty;
8263
8264           window = gdk_window_get_parent (window);
8265         }
8266     }
8267
8268   if ((data->x >= new_allocation.x) && (data->y >= new_allocation.y) &&
8269       (data->x < new_allocation.x + new_allocation.width) && 
8270       (data->y < new_allocation.y + new_allocation.height))
8271     {
8272       /* First, check if the drag is in a valid drop site in
8273        * one of our children 
8274        */
8275       if (GTK_IS_CONTAINER (widget))
8276         {
8277           FindWidgetData new_data = *data;
8278           
8279           new_data.x -= x_offset;
8280           new_data.y -= y_offset;
8281           new_data.found = FALSE;
8282           new_data.first = FALSE;
8283           
8284           gtk_container_forall (GTK_CONTAINER (widget),
8285                                 (GtkCallback)find_widget,
8286                                 &new_data);
8287           
8288           data->found = new_data.found;
8289           if (data->found)
8290             data->res_widget = new_data.res_widget;
8291         }
8292
8293       /* If not, and this widget is registered as a drop site, check to
8294        * emit "drag_motion" to check if we are actually in
8295        * a drop site.
8296        */
8297       if (!data->found)
8298         {
8299           data->found = TRUE;
8300           data->res_widget = widget;
8301         }
8302     }
8303 }
8304
8305 static GtkWidget *
8306 find_widget_at_pointer (GdkDevice *device)
8307 {
8308   GtkWidget *widget = NULL;
8309   GdkWindow *pointer_window;
8310   gint x, y;
8311   FindWidgetData data;
8312  
8313  pointer_window = gdk_device_get_window_at_position (device, NULL, NULL);
8314  
8315  if (pointer_window)
8316    {
8317      gpointer widget_ptr;
8318
8319      gdk_window_get_user_data (pointer_window, &widget_ptr);
8320      widget = widget_ptr;
8321    }
8322
8323  if (widget)
8324    {
8325      gdk_window_get_device_position (gtk_widget_get_window (widget),
8326                                      device,
8327                                      &x, &y, NULL);
8328      
8329      data.x = x;
8330      data.y = y;
8331      data.found = FALSE;
8332      data.first = TRUE;
8333
8334      find_widget (widget, &data);
8335      if (data.found)
8336        return data.res_widget;
8337      return widget;
8338    }
8339  return NULL;
8340 }
8341
8342 struct PropertiesData {
8343   GtkWidget **window;
8344   GdkCursor *cursor;
8345   gboolean in_query;
8346   gulong handler;
8347 };
8348
8349 static void
8350 destroy_properties (GtkWidget             *widget,
8351                     struct PropertiesData *data)
8352 {
8353   if (data->window)
8354     {
8355       *data->window = NULL;
8356       data->window = NULL;
8357     }
8358
8359   if (data->cursor)
8360     {
8361       g_object_unref (data->cursor);
8362       data->cursor = NULL;
8363     }
8364
8365   if (data->handler)
8366     {
8367       g_signal_handler_disconnect (widget, data->handler);
8368       data->handler = 0;
8369     }
8370
8371   g_free (data);
8372 }
8373
8374 static gint
8375 property_query_event (GtkWidget             *widget,
8376                       GdkEvent              *event,
8377                       struct PropertiesData *data)
8378 {
8379   GtkWidget *res_widget = NULL;
8380
8381   if (!data->in_query)
8382     return FALSE;
8383
8384   if (event->type == GDK_BUTTON_RELEASE)
8385     {
8386       gtk_grab_remove (widget);
8387       gdk_device_ungrab (gdk_event_get_device (event), GDK_CURRENT_TIME);
8388
8389       res_widget = find_widget_at_pointer (gdk_event_get_device (event));
8390       if (res_widget)
8391         {
8392           g_object_set_data (G_OBJECT (res_widget), "prop-editor-screen",
8393                              gtk_widget_get_screen (widget));
8394           create_prop_editor (G_OBJECT (res_widget), 0);
8395         }
8396
8397       data->in_query = FALSE;
8398     }
8399   return FALSE;
8400 }
8401
8402
8403 static void
8404 query_properties (GtkButton *button,
8405                   struct PropertiesData *data)
8406 {
8407   GtkWidget *widget = GTK_WIDGET (button);
8408   GdkDisplay *display;
8409   GdkDeviceManager *device_manager;
8410   GdkDevice *device;
8411
8412   g_signal_connect (button, "event",
8413                     G_CALLBACK (property_query_event), data);
8414
8415   display = gtk_widget_get_display (widget);
8416
8417   if (!data->cursor)
8418     data->cursor = gdk_cursor_new_for_display (display, GDK_TARGET);
8419
8420   device_manager = gdk_display_get_device_manager (display);
8421   device = gdk_device_manager_get_client_pointer (device_manager);
8422   gdk_device_grab (device,
8423                    gtk_widget_get_window (widget),
8424                    GDK_OWNERSHIP_NONE,
8425                    TRUE,
8426                    GDK_BUTTON_RELEASE_MASK,
8427                    data->cursor,
8428                    GDK_CURRENT_TIME);
8429   gtk_grab_add (widget);
8430
8431   data->in_query = TRUE;
8432 }
8433
8434 static void
8435 create_properties (GtkWidget *widget)
8436 {
8437   static GtkWidget *window = NULL;
8438   GtkWidget *button;
8439   GtkWidget *vbox;
8440   GtkWidget *label;
8441   struct PropertiesData *data;
8442
8443   data = g_new (struct PropertiesData, 1);
8444   data->window = &window;
8445   data->in_query = FALSE;
8446   data->cursor = NULL;
8447   data->handler = 0;
8448
8449   if (!window)
8450     {
8451       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8452
8453       gtk_window_set_screen (GTK_WINDOW (window),
8454                              gtk_widget_get_screen (widget));      
8455
8456       data->handler = g_signal_connect (window, "destroy",
8457                                         G_CALLBACK (destroy_properties),
8458                                         data);
8459
8460       gtk_window_set_title (GTK_WINDOW (window), "test properties");
8461       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
8462
8463       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 1);
8464       gtk_container_add (GTK_CONTAINER (window), vbox);
8465             
8466       label = gtk_label_new ("This is just a dumb test to test properties.\nIf you need a generic module, get GLE.");
8467       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
8468       
8469       button = gtk_button_new_with_label ("Query properties");
8470       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
8471       g_signal_connect (button, "clicked",
8472                         G_CALLBACK (query_properties),
8473                         data);
8474     }
8475
8476   if (!gtk_widget_get_visible (window))
8477     gtk_widget_show_all (window);
8478   else
8479     gtk_widget_destroy (window);
8480   
8481 }
8482
8483 struct SnapshotData {
8484   GtkWidget *toplevel_button;
8485   GtkWidget **window;
8486   GdkCursor *cursor;
8487   gboolean in_query;
8488   gboolean is_toplevel;
8489   gint handler;
8490 };
8491
8492 static void
8493 destroy_snapshot_data (GtkWidget             *widget,
8494                        struct SnapshotData *data)
8495 {
8496   if (*data->window)
8497     *data->window = NULL;
8498   
8499   if (data->cursor)
8500     {
8501       g_object_unref (data->cursor);
8502       data->cursor = NULL;
8503     }
8504
8505   if (data->handler)
8506     {
8507       g_signal_handler_disconnect (widget, data->handler);
8508       data->handler = 0;
8509     }
8510
8511   g_free (data);
8512 }
8513
8514 static gint
8515 snapshot_widget_event (GtkWidget               *widget,
8516                        GdkEvent        *event,
8517                        struct SnapshotData *data)
8518 {
8519   GtkWidget *res_widget = NULL;
8520
8521   if (!data->in_query)
8522     return FALSE;
8523   
8524   if (event->type == GDK_BUTTON_RELEASE)
8525     {
8526       gtk_grab_remove (widget);
8527       gdk_device_ungrab (gdk_event_get_device (event),
8528                          GDK_CURRENT_TIME);
8529       
8530       res_widget = find_widget_at_pointer (gdk_event_get_device (event));
8531       if (data->is_toplevel && res_widget)
8532         res_widget = gtk_widget_get_toplevel (res_widget);
8533       if (res_widget)
8534         {
8535           cairo_surface_t *surface;
8536           GtkWidget *window, *image;
8537           GdkPixbuf *pixbuf;
8538           int width, height;
8539           cairo_t *cr;
8540
8541           width = gtk_widget_get_allocated_width (res_widget);
8542           height = gtk_widget_get_allocated_height (res_widget);
8543
8544           surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
8545
8546           cr = cairo_create (surface);
8547           gtk_widget_draw (res_widget, cr);
8548           cairo_destroy (cr);
8549
8550           pixbuf = gdk_pixbuf_get_from_surface (surface,
8551                                                 0, 0,
8552                                                 width, height);
8553           cairo_surface_destroy (surface);
8554
8555           window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8556           image = gtk_image_new_from_pixbuf (pixbuf);
8557           g_object_unref (pixbuf);
8558
8559           gtk_container_add (GTK_CONTAINER (window), image);
8560           gtk_widget_show_all (window);
8561         }
8562
8563       data->in_query = FALSE;
8564     }
8565   return FALSE;
8566 }
8567
8568
8569 static void
8570 snapshot_widget (GtkButton *button,
8571                  struct SnapshotData *data)
8572 {
8573   GtkWidget *widget = GTK_WIDGET (button);
8574   GdkDevice *device;
8575
8576   device = gtk_get_current_event_device ();
8577   if (device == NULL)
8578     return;
8579
8580   if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
8581     device = gdk_device_get_associated_device (device);
8582
8583   data->is_toplevel = widget == data->toplevel_button;
8584
8585   if (!data->cursor)
8586     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
8587                                                GDK_TARGET);
8588
8589   gdk_device_grab (device,
8590                    gtk_widget_get_window (widget),
8591                    GDK_OWNERSHIP_APPLICATION,
8592                    TRUE,
8593                    GDK_BUTTON_RELEASE_MASK,
8594                    data->cursor,
8595                    GDK_CURRENT_TIME);
8596
8597   g_signal_connect (button, "event",
8598                     G_CALLBACK (snapshot_widget_event), data);
8599
8600   gtk_grab_add (widget);
8601
8602   data->in_query = TRUE;
8603 }
8604
8605 static void
8606 create_snapshot (GtkWidget *widget)
8607 {
8608   static GtkWidget *window = NULL;
8609   GtkWidget *button;
8610   GtkWidget *vbox;
8611   struct SnapshotData *data;
8612
8613   data = g_new (struct SnapshotData, 1);
8614   data->window = &window;
8615   data->in_query = FALSE;
8616   data->cursor = NULL;
8617   data->handler = 0;
8618
8619   if (!window)
8620     {
8621       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8622
8623       gtk_window_set_screen (GTK_WINDOW (window),
8624                              gtk_widget_get_screen (widget));      
8625
8626       data->handler = g_signal_connect (window, "destroy",
8627                                         G_CALLBACK (destroy_snapshot_data),
8628                                         data);
8629
8630       gtk_window_set_title (GTK_WINDOW (window), "test snapshot");
8631       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
8632
8633       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 1);
8634       gtk_container_add (GTK_CONTAINER (window), vbox);
8635             
8636       button = gtk_button_new_with_label ("Snapshot widget");
8637       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
8638       g_signal_connect (button, "clicked",
8639                         G_CALLBACK (snapshot_widget),
8640                         data);
8641       
8642       button = gtk_button_new_with_label ("Snapshot toplevel");
8643       data->toplevel_button = button;
8644       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
8645       g_signal_connect (button, "clicked",
8646                         G_CALLBACK (snapshot_widget),
8647                         data);
8648     }
8649
8650   if (!gtk_widget_get_visible (window))
8651     gtk_widget_show_all (window);
8652   else
8653     gtk_widget_destroy (window);
8654   
8655 }
8656
8657 /*
8658  * Selection Test
8659  */
8660
8661 void
8662 selection_test_received (GtkWidget        *tree_view,
8663                          GtkSelectionData *selection_data)
8664 {
8665   GtkTreeModel *model;
8666   GtkListStore *store;
8667   GdkAtom *atoms;
8668   int i, l;
8669
8670   if (gtk_selection_data_get_length (selection_data) < 0)
8671     {
8672       g_print ("Selection retrieval failed\n");
8673       return;
8674     }
8675   if (gtk_selection_data_get_data_type (selection_data) != GDK_SELECTION_TYPE_ATOM)
8676     {
8677       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
8678       return;
8679     }
8680
8681   /* Clear out any current list items */
8682
8683   model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
8684   store = GTK_LIST_STORE (model);
8685   gtk_list_store_clear (store);
8686
8687   /* Add new items to list */
8688
8689   gtk_selection_data_get_targets (selection_data,
8690                                   &atoms, &l);
8691
8692   for (i = 0; i < l; i++)
8693     {
8694       char *name;
8695       GtkTreeIter iter;
8696
8697       name = gdk_atom_name (atoms[i]);
8698       if (name != NULL)
8699         {
8700           gtk_list_store_insert_with_values (store, &iter, i, 0, name, -1);
8701           g_free (name);
8702         }
8703       else
8704        gtk_list_store_insert_with_values (store, &iter, i, 0,  "(bad atom)", -1);
8705     }
8706
8707   return;
8708 }
8709
8710 void
8711 selection_test_get_targets (GtkWidget *widget, GtkWidget *tree_view)
8712 {
8713   static GdkAtom targets_atom = GDK_NONE;
8714
8715   if (targets_atom == GDK_NONE)
8716     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
8717
8718   gtk_selection_convert (tree_view, GDK_SELECTION_PRIMARY, targets_atom,
8719                          GDK_CURRENT_TIME);
8720 }
8721
8722 void
8723 create_selection_test (GtkWidget *widget)
8724 {
8725   static GtkWidget *window = NULL;
8726   GtkWidget *action_area, *content_area;
8727   GtkWidget *button;
8728   GtkWidget *vbox;
8729   GtkWidget *scrolled_win;
8730   GtkListStore* store;
8731   GtkWidget *tree_view;
8732   GtkTreeViewColumn *column;
8733   GtkCellRenderer *renderer;
8734   GtkWidget *label;
8735
8736   if (!window)
8737     {
8738       window = gtk_dialog_new ();
8739       
8740       gtk_window_set_screen (GTK_WINDOW (window),
8741                              gtk_widget_get_screen (widget));
8742
8743       g_signal_connect (window, "destroy",
8744                         G_CALLBACK (gtk_widget_destroyed),
8745                         &window);
8746
8747       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
8748       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
8749
8750       gtk_window_set_title (GTK_WINDOW (window), "Selection Test");
8751       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8752
8753       /* Create the list */
8754
8755       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
8756       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
8757       gtk_box_pack_start (GTK_BOX (content_area), vbox, TRUE, TRUE, 0);
8758
8759       label = gtk_label_new ("Gets available targets for current selection");
8760       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
8761
8762       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
8763       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
8764                                       GTK_POLICY_AUTOMATIC, 
8765                                       GTK_POLICY_AUTOMATIC);
8766       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
8767       gtk_widget_set_size_request (scrolled_win, 100, 200);
8768
8769       store = gtk_list_store_new (1, G_TYPE_STRING);
8770       tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
8771       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), tree_view);
8772
8773       renderer = gtk_cell_renderer_text_new ();
8774       column = gtk_tree_view_column_new_with_attributes ("Target", renderer,
8775                                                          "text", 0, NULL);
8776       gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
8777
8778       g_signal_connect (tree_view, "selection_received",
8779                         G_CALLBACK (selection_test_received), NULL);
8780
8781       /* .. And create some buttons */
8782       button = gtk_button_new_with_label ("Get Targets");
8783       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
8784
8785       g_signal_connect (button, "clicked",
8786                         G_CALLBACK (selection_test_get_targets), tree_view);
8787
8788       button = gtk_button_new_with_label ("Quit");
8789       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
8790
8791       g_signal_connect_swapped (button, "clicked",
8792                                 G_CALLBACK (gtk_widget_destroy),
8793                                 window);
8794     }
8795
8796   if (!gtk_widget_get_visible (window))
8797     gtk_widget_show_all (window);
8798   else
8799     gtk_widget_destroy (window);
8800 }
8801
8802 /*
8803  * Test scrolling
8804  */
8805
8806 static int scroll_test_pos = 0.0;
8807
8808 static gint
8809 scroll_test_draw (GtkWidget     *widget,
8810                   cairo_t       *cr,
8811                   GtkAdjustment *adjustment)
8812 {
8813   gint i,j;
8814   gint imin, imax, jmin, jmax;
8815   GdkRectangle clip;
8816   
8817   gdk_cairo_get_clip_rectangle (cr, &clip);
8818
8819   imin = (clip.x) / 10;
8820   imax = (clip.x + clip.width + 9) / 10;
8821
8822   jmin = ((int)gtk_adjustment_get_value (adjustment) + clip.y) / 10;
8823   jmax = ((int)gtk_adjustment_get_value (adjustment) + clip.y + clip.height + 9) / 10;
8824
8825   for (i=imin; i<imax; i++)
8826     for (j=jmin; j<jmax; j++)
8827       if ((i+j) % 2)
8828         cairo_rectangle (cr, 10*i, 10*j - (int)gtk_adjustment_get_value (adjustment), 1+i%10, 1+j%10);
8829
8830   cairo_fill (cr);
8831
8832   return TRUE;
8833 }
8834
8835 static gint
8836 scroll_test_scroll (GtkWidget *widget, GdkEventScroll *event,
8837                     GtkAdjustment *adjustment)
8838 {
8839   gdouble new_value = gtk_adjustment_get_value (adjustment) + ((event->direction == GDK_SCROLL_UP) ?
8840                                     -gtk_adjustment_get_page_increment (adjustment) / 2:
8841                                     gtk_adjustment_get_page_increment (adjustment) / 2);
8842   new_value = CLAMP (new_value, gtk_adjustment_get_lower (adjustment), gtk_adjustment_get_upper (adjustment) - gtk_adjustment_get_page_size (adjustment));
8843   gtk_adjustment_set_value (adjustment, new_value);  
8844   
8845   return TRUE;
8846 }
8847
8848 static void
8849 scroll_test_configure (GtkWidget *widget, GdkEventConfigure *event,
8850                        GtkAdjustment *adjustment)
8851 {
8852   GtkAllocation allocation;
8853
8854   gtk_widget_get_allocation (widget, &allocation);
8855   gtk_adjustment_configure (adjustment,
8856                             gtk_adjustment_get_value (adjustment),
8857                             gtk_adjustment_get_lower (adjustment),
8858                             gtk_adjustment_get_upper (adjustment),
8859                             0.1 * allocation.height,
8860                             0.9 * allocation.height,
8861                             allocation.height);
8862 }
8863
8864 static void
8865 scroll_test_adjustment_changed (GtkAdjustment *adjustment, GtkWidget *widget)
8866 {
8867   GdkWindow *window;
8868   gint dy;
8869
8870   dy = scroll_test_pos - (int)gtk_adjustment_get_value (adjustment);
8871   scroll_test_pos = gtk_adjustment_get_value (adjustment);
8872
8873   if (!gtk_widget_is_drawable (widget))
8874     return;
8875
8876   window = gtk_widget_get_window (widget);
8877   gdk_window_scroll (window, 0, dy);
8878   gdk_window_process_updates (window, FALSE);
8879 }
8880
8881
8882 void
8883 create_scroll_test (GtkWidget *widget)
8884 {
8885   static GtkWidget *window = NULL;
8886   GtkWidget *action_area, *content_area;
8887   GtkWidget *hbox;
8888   GtkWidget *drawing_area;
8889   GtkWidget *scrollbar;
8890   GtkWidget *button;
8891   GtkAdjustment *adjustment;
8892   GdkGeometry geometry;
8893   GdkWindowHints geometry_mask;
8894
8895   if (!window)
8896     {
8897       window = gtk_dialog_new ();
8898
8899       gtk_window_set_screen (GTK_WINDOW (window),
8900                              gtk_widget_get_screen (widget));
8901
8902       g_signal_connect (window, "destroy",
8903                         G_CALLBACK (gtk_widget_destroyed),
8904                         &window);
8905
8906       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
8907       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
8908
8909       gtk_window_set_title (GTK_WINDOW (window), "Scroll Test");
8910       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8911
8912       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
8913       gtk_box_pack_start (GTK_BOX (content_area), hbox, TRUE, TRUE, 0);
8914       gtk_widget_show (hbox);
8915
8916       drawing_area = gtk_drawing_area_new ();
8917       gtk_widget_set_size_request (drawing_area, 200, 200);
8918       gtk_box_pack_start (GTK_BOX (hbox), drawing_area, TRUE, TRUE, 0);
8919       gtk_widget_show (drawing_area);
8920
8921       gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK | GDK_SCROLL_MASK);
8922
8923       adjustment = gtk_adjustment_new (0.0, 0.0, 1000.0, 1.0, 180.0, 200.0);
8924       scroll_test_pos = 0.0;
8925
8926       scrollbar = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, adjustment);
8927       gtk_box_pack_start (GTK_BOX (hbox), scrollbar, FALSE, FALSE, 0);
8928       gtk_widget_show (scrollbar);
8929
8930       g_signal_connect (drawing_area, "draw",
8931                         G_CALLBACK (scroll_test_draw), adjustment);
8932       g_signal_connect (drawing_area, "configure_event",
8933                         G_CALLBACK (scroll_test_configure), adjustment);
8934       g_signal_connect (drawing_area, "scroll_event",
8935                         G_CALLBACK (scroll_test_scroll), adjustment);
8936       
8937       g_signal_connect (adjustment, "value_changed",
8938                         G_CALLBACK (scroll_test_adjustment_changed),
8939                         drawing_area);
8940       
8941       /* .. And create some buttons */
8942
8943       button = gtk_button_new_with_label ("Quit");
8944       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
8945
8946       g_signal_connect_swapped (button, "clicked",
8947                                 G_CALLBACK (gtk_widget_destroy),
8948                                 window);
8949       gtk_widget_show (button);
8950
8951       /* Set up gridded geometry */
8952
8953       geometry_mask = GDK_HINT_MIN_SIZE | 
8954                        GDK_HINT_BASE_SIZE | 
8955                        GDK_HINT_RESIZE_INC;
8956
8957       geometry.min_width = 20;
8958       geometry.min_height = 20;
8959       geometry.base_width = 0;
8960       geometry.base_height = 0;
8961       geometry.width_inc = 10;
8962       geometry.height_inc = 10;
8963       
8964       gtk_window_set_geometry_hints (GTK_WINDOW (window),
8965                                drawing_area, &geometry, geometry_mask);
8966     }
8967
8968   if (!gtk_widget_get_visible (window))
8969     gtk_widget_show (window);
8970   else
8971     gtk_widget_destroy (window);
8972 }
8973
8974 /*
8975  * Timeout Test
8976  */
8977
8978 static int timer = 0;
8979
8980 gint
8981 timeout_test (GtkWidget *label)
8982 {
8983   static int count = 0;
8984   static char buffer[32];
8985
8986   sprintf (buffer, "count: %d", ++count);
8987   gtk_label_set_text (GTK_LABEL (label), buffer);
8988
8989   return TRUE;
8990 }
8991
8992 void
8993 start_timeout_test (GtkWidget *widget,
8994                     GtkWidget *label)
8995 {
8996   if (!timer)
8997     {
8998       timer = g_timeout_add (100, (GSourceFunc)timeout_test, label);
8999     }
9000 }
9001
9002 void
9003 stop_timeout_test (GtkWidget *widget,
9004                    gpointer   data)
9005 {
9006   if (timer)
9007     {
9008       g_source_remove (timer);
9009       timer = 0;
9010     }
9011 }
9012
9013 void
9014 destroy_timeout_test (GtkWidget  *widget,
9015                       GtkWidget **window)
9016 {
9017   stop_timeout_test (NULL, NULL);
9018
9019   *window = NULL;
9020 }
9021
9022 void
9023 create_timeout_test (GtkWidget *widget)
9024 {
9025   static GtkWidget *window = NULL;
9026   GtkWidget *action_area, *content_area;
9027   GtkWidget *button;
9028   GtkWidget *label;
9029
9030   if (!window)
9031     {
9032       window = gtk_dialog_new ();
9033
9034       gtk_window_set_screen (GTK_WINDOW (window),
9035                              gtk_widget_get_screen (widget));
9036
9037       g_signal_connect (window, "destroy",
9038                         G_CALLBACK (destroy_timeout_test),
9039                         &window);
9040
9041       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9042       action_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9043
9044       gtk_window_set_title (GTK_WINDOW (window), "Timeout Test");
9045       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9046
9047       label = gtk_label_new ("count: 0");
9048       g_object_set (label, "margin", 10, NULL);
9049       gtk_box_pack_start (GTK_BOX (content_area), label, TRUE, TRUE, 0);
9050       gtk_widget_show (label);
9051
9052       button = gtk_button_new_with_label ("close");
9053       g_signal_connect_swapped (button, "clicked",
9054                                 G_CALLBACK (gtk_widget_destroy),
9055                                 window);
9056       gtk_widget_set_can_default (button, TRUE);
9057       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9058       gtk_widget_grab_default (button);
9059       gtk_widget_show (button);
9060
9061       button = gtk_button_new_with_label ("start");
9062       g_signal_connect (button, "clicked",
9063                         G_CALLBACK(start_timeout_test),
9064                         label);
9065       gtk_widget_set_can_default (button, TRUE);
9066       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9067       gtk_widget_show (button);
9068
9069       button = gtk_button_new_with_label ("stop");
9070       g_signal_connect (button, "clicked",
9071                         G_CALLBACK (stop_timeout_test),
9072                         NULL);
9073       gtk_widget_set_can_default (button, TRUE);
9074       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9075       gtk_widget_show (button);
9076     }
9077
9078   if (!gtk_widget_get_visible (window))
9079     gtk_widget_show (window);
9080   else
9081     gtk_widget_destroy (window);
9082 }
9083
9084 /*
9085  * Idle Test
9086  */
9087
9088 static int idle_id = 0;
9089
9090 static gint
9091 idle_test (GtkWidget *label)
9092 {
9093   static int count = 0;
9094   static char buffer[32];
9095
9096   sprintf (buffer, "count: %d", ++count);
9097   gtk_label_set_text (GTK_LABEL (label), buffer);
9098
9099   return TRUE;
9100 }
9101
9102 static void
9103 start_idle_test (GtkWidget *widget,
9104                  GtkWidget *label)
9105 {
9106   if (!idle_id)
9107     {
9108       idle_id = g_idle_add ((GSourceFunc) idle_test, label);
9109     }
9110 }
9111
9112 static void
9113 stop_idle_test (GtkWidget *widget,
9114                 gpointer   data)
9115 {
9116   if (idle_id)
9117     {
9118       g_source_remove (idle_id);
9119       idle_id = 0;
9120     }
9121 }
9122
9123 static void
9124 destroy_idle_test (GtkWidget  *widget,
9125                    GtkWidget **window)
9126 {
9127   stop_idle_test (NULL, NULL);
9128
9129   *window = NULL;
9130 }
9131
9132 static void
9133 toggle_idle_container (GObject *button,
9134                        GtkContainer *container)
9135 {
9136   gtk_container_set_resize_mode (container, GPOINTER_TO_INT (g_object_get_data (button, "user_data")));
9137 }
9138
9139 static void
9140 create_idle_test (GtkWidget *widget)
9141 {
9142   static GtkWidget *window = NULL;
9143   GtkWidget *button;
9144   GtkWidget *label;
9145   GtkWidget *container;
9146
9147   if (!window)
9148     {
9149       GtkWidget *action_area, *content_area;
9150       GtkWidget *button2;
9151       GtkWidget *frame;
9152       GtkWidget *box;
9153
9154       window = gtk_dialog_new ();
9155
9156       gtk_window_set_screen (GTK_WINDOW (window),
9157                              gtk_widget_get_screen (widget));
9158
9159       g_signal_connect (window, "destroy",
9160                         G_CALLBACK (destroy_idle_test),
9161                         &window);
9162
9163       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9164       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9165
9166       gtk_window_set_title (GTK_WINDOW (window), "Idle Test");
9167       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9168
9169       label = gtk_label_new ("count: 0");
9170       g_object_set (label, "margin", 10, NULL);
9171       gtk_widget_show (label);
9172       
9173       container =
9174         g_object_new (GTK_TYPE_BOX,
9175                         "visible", TRUE,
9176                         /* "GtkContainer::child", g_object_new (GTK_TYPE_HBOX,
9177                          * "GtkWidget::visible", TRUE,
9178                          */
9179                          "child", label,
9180                         /* NULL), */
9181                         NULL);
9182       gtk_box_pack_start (GTK_BOX (content_area), container, TRUE, TRUE, 0);
9183
9184       frame =
9185         g_object_new (GTK_TYPE_FRAME,
9186                         "border_width", 5,
9187                         "label", "Label Container",
9188                         "visible", TRUE,
9189                         "parent", content_area,
9190                         NULL);
9191       box =
9192         g_object_new (GTK_TYPE_BOX,
9193                         "visible", TRUE,
9194                         "parent", frame,
9195                         "orientation", GTK_ORIENTATION_VERTICAL,
9196                         NULL);
9197       button =
9198         g_object_connect (g_object_new (GTK_TYPE_RADIO_BUTTON,
9199                                           "label", "Resize-Parent",
9200                                           "user_data", (void*)GTK_RESIZE_PARENT,
9201                                           "visible", TRUE,
9202                                           "parent", box,
9203                                           NULL),
9204                           "signal::clicked", toggle_idle_container, container,
9205                           NULL);
9206       button = g_object_new (GTK_TYPE_RADIO_BUTTON,
9207                                "label", "Resize-Queue",
9208                                "user_data", (void*)GTK_RESIZE_QUEUE,
9209                                "group", button,
9210                                "visible", TRUE,
9211                                "parent", box,
9212                                NULL);
9213       g_object_connect (button,
9214                         "signal::clicked", toggle_idle_container, container,
9215                         NULL);
9216       button2 = g_object_new (GTK_TYPE_RADIO_BUTTON,
9217                                 "label", "Resize-Immediate",
9218                                 "user_data", (void*)GTK_RESIZE_IMMEDIATE,
9219                                 NULL);
9220       g_object_connect (button2,
9221                         "signal::clicked", toggle_idle_container, container,
9222                         NULL);
9223       g_object_set (button2,
9224                     "group", button,
9225                     "visible", TRUE,
9226                     "parent", box,
9227                     NULL);
9228
9229       button = gtk_button_new_with_label ("close");
9230       g_signal_connect_swapped (button, "clicked",
9231                                 G_CALLBACK (gtk_widget_destroy),
9232                                 window);
9233       gtk_widget_set_can_default (button, TRUE);
9234       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9235       gtk_widget_grab_default (button);
9236       gtk_widget_show (button);
9237
9238       button = gtk_button_new_with_label ("start");
9239       g_signal_connect (button, "clicked",
9240                         G_CALLBACK (start_idle_test),
9241                         label);
9242       gtk_widget_set_can_default (button, TRUE);
9243       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9244       gtk_widget_show (button);
9245
9246       button = gtk_button_new_with_label ("stop");
9247       g_signal_connect (button, "clicked",
9248                         G_CALLBACK (stop_idle_test),
9249                         NULL);
9250       gtk_widget_set_can_default (button, TRUE);
9251       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9252       gtk_widget_show (button);
9253     }
9254
9255   if (!gtk_widget_get_visible (window))
9256     gtk_widget_show (window);
9257   else
9258     gtk_widget_destroy (window);
9259 }
9260
9261 /*
9262  * rc file test
9263  */
9264
9265 void
9266 create_rc_file (GtkWidget *widget)
9267 {
9268   static GtkWidget *window = NULL;
9269   GtkWidget *action_area, *content_area;
9270   GtkWidget *button;
9271   GtkWidget *frame;
9272   GtkWidget *vbox;
9273   GtkWidget *label;
9274
9275   if (!window)
9276     {
9277       window = gtk_dialog_new ();
9278
9279       gtk_window_set_screen (GTK_WINDOW (window),
9280                              gtk_widget_get_screen (widget));
9281
9282       g_signal_connect (window, "destroy",
9283                         G_CALLBACK (gtk_widget_destroyed),
9284                         &window);
9285
9286       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9287       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9288
9289       frame = gtk_aspect_frame_new ("Testing RC file prioritization", 0.5, 0.5, 0.0, TRUE);
9290       gtk_box_pack_start (GTK_BOX (content_area), frame, FALSE, FALSE, 0);
9291
9292       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
9293       gtk_container_add (GTK_CONTAINER (frame), vbox);
9294       
9295       label = gtk_label_new ("This label should be red");
9296       gtk_widget_set_name (label, "testgtk-red-label");
9297       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9298
9299       label = gtk_label_new ("This label should be green");
9300       gtk_widget_set_name (label, "testgtk-green-label");
9301       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9302
9303       label = gtk_label_new ("This label should be blue");
9304       gtk_widget_set_name (label, "testgtk-blue-label");
9305       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9306
9307       gtk_window_set_title (GTK_WINDOW (window), "Reload Rc file");
9308       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9309
9310       button = gtk_button_new_with_label ("Reload");
9311       g_signal_connect_swapped (button, "clicked",
9312                                 G_CALLBACK (gtk_style_context_reset_widgets),
9313                                 gtk_widget_get_screen (button));
9314       gtk_widget_set_can_default (button, TRUE);
9315       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9316       gtk_widget_grab_default (button);
9317
9318       button = gtk_button_new_with_label ("Close");
9319       g_signal_connect_swapped (button, "clicked",
9320                                 G_CALLBACK (gtk_widget_destroy),
9321                                 window);
9322       gtk_widget_set_can_default (button, TRUE);
9323       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9324     }
9325
9326   if (!gtk_widget_get_visible (window))
9327     gtk_widget_show_all (window);
9328   else
9329     gtk_widget_destroy (window);
9330 }
9331
9332 /*
9333  * Test of recursive mainloop
9334  */
9335
9336 void
9337 mainloop_destroyed (GtkWidget *w, GtkWidget **window)
9338 {
9339   *window = NULL;
9340   gtk_main_quit ();
9341 }
9342
9343 void
9344 create_mainloop (GtkWidget *widget)
9345 {
9346   static GtkWidget *window = NULL;
9347   GtkWidget *action_area, *content_area;
9348   GtkWidget *label;
9349   GtkWidget *button;
9350
9351   if (!window)
9352     {
9353       window = gtk_dialog_new ();
9354
9355       gtk_window_set_screen (GTK_WINDOW (window),
9356                              gtk_widget_get_screen (widget));
9357
9358       gtk_window_set_title (GTK_WINDOW (window), "Test Main Loop");
9359
9360       g_signal_connect (window, "destroy",
9361                         G_CALLBACK (mainloop_destroyed),
9362                         &window);
9363
9364       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9365       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9366
9367       label = gtk_label_new ("In recursive main loop...");
9368       g_object_set (label, "margin", 20, NULL);
9369
9370       gtk_box_pack_start (GTK_BOX (content_area), label, TRUE, TRUE, 0);
9371       gtk_widget_show (label);
9372
9373       button = gtk_button_new_with_label ("Leave");
9374       gtk_box_pack_start (GTK_BOX (action_area), button, FALSE, TRUE, 0);
9375
9376       g_signal_connect_swapped (button, "clicked",
9377                                 G_CALLBACK (gtk_widget_destroy),
9378                                 window);
9379
9380       gtk_widget_set_can_default (button, TRUE);
9381       gtk_widget_grab_default (button);
9382
9383       gtk_widget_show (button);
9384     }
9385
9386   if (!gtk_widget_get_visible (window))
9387     {
9388       gtk_widget_show (window);
9389
9390       g_print ("create_mainloop: start\n");
9391       gtk_main ();
9392       g_print ("create_mainloop: done\n");
9393     }
9394   else
9395     gtk_widget_destroy (window);
9396 }
9397
9398 static gboolean
9399 layout_draw_handler (GtkWidget *widget, cairo_t *cr)
9400 {
9401   GtkLayout *layout;
9402   GdkWindow *bin_window;
9403   GdkRectangle clip;
9404   gint i,j,x,y;
9405   gint imin, imax, jmin, jmax;
9406
9407   layout = GTK_LAYOUT (widget);
9408   bin_window = gtk_layout_get_bin_window (layout);
9409
9410   if (!gtk_cairo_should_draw_window (cr, bin_window))
9411     return FALSE;
9412   
9413   gdk_window_get_position (bin_window, &x, &y);
9414   cairo_translate (cr, x, y);
9415
9416   gdk_cairo_get_clip_rectangle (cr, &clip);
9417
9418   imin = (clip.x) / 10;
9419   imax = (clip.x + clip.width + 9) / 10;
9420
9421   jmin = (clip.y) / 10;
9422   jmax = (clip.y + clip.height + 9) / 10;
9423
9424   for (i=imin; i<imax; i++)
9425     for (j=jmin; j<jmax; j++)
9426       if ((i+j) % 2)
9427         cairo_rectangle (cr,
9428                          10*i, 10*j, 
9429                          1+i%10, 1+j%10);
9430   
9431   cairo_fill (cr);
9432
9433   return FALSE;
9434 }
9435
9436 void create_layout (GtkWidget *widget)
9437 {
9438   GtkAdjustment *hadjustment, *vadjustment;
9439   GtkLayout *layout;
9440   static GtkWidget *window = NULL;
9441   GtkWidget *layout_widget;
9442   GtkWidget *scrolledwindow;
9443   GtkWidget *button;
9444
9445   if (!window)
9446     {
9447       gchar buf[16];
9448
9449       gint i, j;
9450       
9451       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9452       gtk_window_set_screen (GTK_WINDOW (window),
9453                              gtk_widget_get_screen (widget));
9454
9455       g_signal_connect (window, "destroy",
9456                         G_CALLBACK (gtk_widget_destroyed),
9457                         &window);
9458
9459       gtk_window_set_title (GTK_WINDOW (window), "Layout");
9460       gtk_widget_set_size_request (window, 200, 200);
9461
9462       scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
9463       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
9464                                            GTK_SHADOW_IN);
9465       gtk_scrolled_window_set_placement (GTK_SCROLLED_WINDOW (scrolledwindow),
9466                                          GTK_CORNER_TOP_RIGHT);
9467
9468       gtk_container_add (GTK_CONTAINER (window), scrolledwindow);
9469
9470       layout_widget = gtk_layout_new (NULL, NULL);
9471       layout = GTK_LAYOUT (layout_widget);
9472       gtk_container_add (GTK_CONTAINER (scrolledwindow), layout_widget);
9473
9474       /* We set step sizes here since GtkLayout does not set
9475        * them itself.
9476        */
9477       hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (layout));
9478       vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (layout));
9479       gtk_adjustment_set_step_increment (hadjustment, 10.0);
9480       gtk_adjustment_set_step_increment (vadjustment, 10.0);
9481       gtk_scrollable_set_hadjustment (GTK_SCROLLABLE (layout), hadjustment);
9482       gtk_scrollable_set_vadjustment (GTK_SCROLLABLE (layout), vadjustment);
9483
9484       gtk_widget_set_events (layout_widget, GDK_EXPOSURE_MASK);
9485       g_signal_connect (layout, "draw",
9486                         G_CALLBACK (layout_draw_handler), NULL);
9487
9488       gtk_layout_set_size (layout, 1600, 128000);
9489
9490       for (i=0 ; i < 16 ; i++)
9491         for (j=0 ; j < 16 ; j++)
9492           {
9493             sprintf(buf, "Button %d, %d", i, j);
9494             if ((i + j) % 2)
9495               button = gtk_button_new_with_label (buf);
9496             else
9497               button = gtk_label_new (buf);
9498
9499             gtk_layout_put (layout, button, j*100, i*100);
9500           }
9501
9502       for (i=16; i < 1280; i++)
9503         {
9504           sprintf(buf, "Button %d, %d", i, 0);
9505           if (i % 2)
9506             button = gtk_button_new_with_label (buf);
9507           else
9508             button = gtk_label_new (buf);
9509
9510           gtk_layout_put (layout, button, 0, i*100);
9511         }
9512     }
9513
9514   if (!gtk_widget_get_visible (window))
9515     gtk_widget_show_all (window);
9516   else
9517     gtk_widget_destroy (window);
9518 }
9519
9520 #if 0
9521 /* FIXME: need to completely redo this for GtkStyleContext */
9522 void
9523 create_styles (GtkWidget *widget)
9524 {
9525   static GtkWidget *window = NULL;
9526   GtkWidget *content_area, *action_area;
9527   GtkWidget *label;
9528   GtkWidget *button;
9529   GtkWidget *entry;
9530   GtkWidget *vbox;
9531   static GdkRGBA red =    { 1,0,0,1 };
9532   static GdkRGBA green =  { 0,1,0,1 };
9533   static GdkRGBA blue =   { 0,0,1,1 };
9534   static GdkRGBA yellow = { 1,1,0,1 };
9535   static GdkRGBA cyan =   { 0,1,1,1 };
9536   PangoFontDescription *font_desc;
9537
9538   GtkRcStyle *rc_style;
9539
9540   if (!window)
9541     {
9542       window = gtk_dialog_new ();
9543       gtk_window_set_screen (GTK_WINDOW (window),
9544                              gtk_widget_get_screen (widget));
9545      
9546       g_signal_connect (window, "destroy",
9547                         G_CALLBACK (gtk_widget_destroyed),
9548                         &window);
9549
9550       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9551       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9552
9553       button = gtk_button_new_with_label ("Close");
9554       g_signal_connect_swapped (button, "clicked",
9555                                 G_CALLBACK (gtk_widget_destroy),
9556                                 window);
9557       gtk_widget_set_can_default (button, TRUE);
9558       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9559       gtk_widget_show (button);
9560
9561       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
9562       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
9563       gtk_box_pack_start (GTK_BOX (content_area), vbox, FALSE, FALSE, 0);
9564       
9565       label = gtk_label_new ("Font:");
9566       gtk_widget_set_halign (label, GTK_ALIGN_START);
9567       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9568       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9569
9570       font_desc = pango_font_description_from_string ("Helvetica,Sans Oblique 18");
9571
9572       button = gtk_button_new_with_label ("Some Text");
9573       gtk_widget_override_font (gtk_bin_get_child (GTK_BIN (button)), font_desc);
9574       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9575
9576       label = gtk_label_new ("Foreground:");
9577       gtk_widget_set_halign (label, GTK_ALIGN_START);
9578       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9579       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9580
9581       button = gtk_button_new_with_label ("Some Text");
9582       gtk_widget_override_color (gtk_bin_get_child (GTK_BIN (button)), 0, &red);
9583       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9584
9585       label = gtk_label_new ("Background:");
9586       gtk_widget_set_halign (label, GTK_ALIGN_START);
9587       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9588       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9589
9590       button = gtk_button_new_with_label ("Some Text");
9591       gtk_widget_override_background_color (button, 0, &green);
9592       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9593
9594       label = gtk_label_new ("Text:");
9595       gtk_widget_set_halign (label, GTK_ALIGN_START);
9596       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9597       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9598
9599       entry = gtk_entry_new ();
9600       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
9601       gtk_widget_override_color (entry, 0, &blue);
9602       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
9603
9604       label = gtk_label_new ("Base:");
9605       gtk_widget_set_halign (label, GTK_ALIGN_START);
9606       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9607       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9608
9609       entry = gtk_entry_new ();
9610       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
9611       gtk_widget_override_background_color (entry, 0, &yellow);
9612       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
9613
9614       label = gtk_label_new ("Cursor:");
9615       gtk_widget_set_halign (label, GTK_ALIGN_START);
9616       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9617       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9618
9619       entry = gtk_entry_new ();
9620       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
9621       gtk_widget_modify_cursor (entry, &red, &red);
9622       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
9623
9624       label = gtk_label_new ("Multiple:");
9625       gtk_widget_set_halign (label, GTK_ALIGN_START);
9626       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9627       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9628
9629       button = gtk_button_new_with_label ("Some Text");
9630
9631       rc_style = gtk_rc_style_new ();
9632
9633       rc_style->font_desc = pango_font_description_copy (font_desc);
9634       rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG | GTK_RC_BG;
9635       rc_style->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_FG | GTK_RC_BG;
9636       rc_style->color_flags[GTK_STATE_ACTIVE] = GTK_RC_FG | GTK_RC_BG;
9637       rc_style->fg[GTK_STATE_NORMAL] = yellow;
9638       rc_style->bg[GTK_STATE_NORMAL] = blue;
9639       rc_style->fg[GTK_STATE_PRELIGHT] = blue;
9640       rc_style->bg[GTK_STATE_PRELIGHT] = yellow;
9641       rc_style->fg[GTK_STATE_ACTIVE] = red;
9642       rc_style->bg[GTK_STATE_ACTIVE] = cyan;
9643       rc_style->xthickness = 5;
9644       rc_style->ythickness = 5;
9645
9646       gtk_widget_modify_style (button, rc_style);
9647       gtk_widget_modify_style (gtk_bin_get_child (GTK_BIN (button)), rc_style);
9648
9649       g_object_unref (rc_style);
9650       
9651       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9652     }
9653   
9654   if (!gtk_widget_get_visible (window))
9655     gtk_widget_show_all (window);
9656   else
9657     gtk_widget_destroy (window);
9658 }
9659 #endif
9660
9661 /*
9662  * Main Window and Exit
9663  */
9664
9665 void
9666 do_exit (GtkWidget *widget, GtkWidget *window)
9667 {
9668   gtk_widget_destroy (window);
9669   gtk_main_quit ();
9670 }
9671
9672 struct {
9673   char *label;
9674   void (*func) (GtkWidget *widget);
9675   gboolean do_not_benchmark;
9676 } buttons[] =
9677 {
9678   { "alpha window", create_alpha_window },
9679   { "big windows", create_big_windows },
9680   { "button box", create_button_box },
9681   { "buttons", create_buttons },
9682   { "check buttons", create_check_buttons },
9683   { "color selection", create_color_selection },
9684   { "composited window", create_composited_window },
9685   { "cursors", create_cursors },
9686   { "dialog", create_dialog },
9687   { "display & screen", create_display_screen, TRUE },
9688   { "entry", create_entry },
9689   { "event box", create_event_box },
9690   { "event watcher", create_event_watcher },
9691   { "expander", create_expander },
9692   { "flipping", create_flipping },
9693   { "focus", create_focus },
9694   { "font selection", create_font_selection },
9695   { "image", create_image },
9696   { "key lookup", create_key_lookup },
9697   { "labels", create_labels },
9698   { "layout", create_layout },
9699   { "menus", create_menus },
9700   { "message dialog", create_message_dialog },
9701   { "modal window", create_modal_window, TRUE },
9702   { "notebook", create_notebook },
9703   { "panes", create_panes },
9704   { "paned keyboard", create_paned_keyboard_navigation },
9705   { "pixbuf", create_pixbuf },
9706   { "progress bar", create_progress_bar },
9707   { "properties", create_properties },
9708   { "radio buttons", create_radio_buttons },
9709   { "range controls", create_range_controls },
9710   { "rc file", create_rc_file },
9711   { "reparent", create_reparent },
9712   { "resize grips", create_resize_grips },
9713   { "rotated label", create_rotated_label },
9714   { "rotated text", create_rotated_text },
9715   { "saved position", create_saved_position },
9716   { "scrolled windows", create_scrolled_windows },
9717   { "shapes", create_shapes },
9718   { "size groups", create_size_groups },
9719   { "snapshot", create_snapshot },
9720   { "spinbutton", create_spins },
9721   { "statusbar", create_statusbar },
9722 #if 0
9723   { "styles", create_styles },
9724 #endif
9725   { "test idle", create_idle_test },
9726   { "test mainloop", create_mainloop, TRUE },
9727   { "test scrolling", create_scroll_test },
9728   { "test selection", create_selection_test },
9729   { "test timeout", create_timeout_test },
9730   { "toggle buttons", create_toggle_buttons },
9731   { "toolbar", create_toolbar },
9732   { "tooltips", create_tooltips },
9733   { "WM hints", create_wmhints },
9734   { "window sizing", create_window_sizing },
9735   { "window states", create_window_states }
9736 };
9737 int nbuttons = sizeof (buttons) / sizeof (buttons[0]);
9738
9739 void
9740 create_main_window (void)
9741 {
9742   GtkWidget *window;
9743   GtkWidget *box1;
9744   GtkWidget *box2;
9745   GtkWidget *scrolled_window;
9746   GtkWidget *button;
9747   GtkWidget *label;
9748   gchar buffer[64];
9749   GtkWidget *separator;
9750   GdkGeometry geometry;
9751   int i;
9752
9753   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9754   gtk_widget_set_name (window, "main_window");
9755   gtk_window_move (GTK_WINDOW (window), 50, 20);
9756   gtk_window_set_default_size (GTK_WINDOW (window), -1, 400);
9757
9758   geometry.min_width = -1;
9759   geometry.min_height = -1;
9760   geometry.max_width = -1;
9761   geometry.max_height = G_MAXSHORT;
9762   gtk_window_set_geometry_hints (GTK_WINDOW (window), NULL,
9763                                  &geometry,
9764                                  GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
9765
9766   g_signal_connect (window, "destroy",
9767                     G_CALLBACK (gtk_main_quit),
9768                     NULL);
9769   g_signal_connect (window, "delete-event",
9770                     G_CALLBACK (gtk_false),
9771                     NULL);
9772
9773   box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
9774   gtk_container_add (GTK_CONTAINER (window), box1);
9775
9776   if (gtk_micro_version > 0)
9777     sprintf (buffer,
9778              "Gtk+ v%d.%d.%d",
9779              gtk_get_major_version (),
9780              gtk_get_minor_version (),
9781              gtk_get_micro_version ());
9782   else
9783     sprintf (buffer,
9784              "Gtk+ v%d.%d",
9785              gtk_get_major_version (),
9786              gtk_get_minor_version ());
9787
9788   label = gtk_label_new (buffer);
9789   gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
9790   gtk_widget_set_name (label, "testgtk-version-label");
9791
9792   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
9793   gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
9794   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
9795                                   GTK_POLICY_NEVER, 
9796                                   GTK_POLICY_AUTOMATIC);
9797   gtk_box_pack_start (GTK_BOX (box1), scrolled_window, TRUE, TRUE, 0);
9798
9799   box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
9800   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9801   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), box2);
9802   gtk_container_set_focus_vadjustment (GTK_CONTAINER (box2),
9803                                        gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
9804   gtk_widget_show (box2);
9805
9806   for (i = 0; i < nbuttons; i++)
9807     {
9808       button = gtk_button_new_with_label (buttons[i].label);
9809       if (buttons[i].func)
9810         g_signal_connect (button, 
9811                           "clicked", 
9812                           G_CALLBACK(buttons[i].func),
9813                           NULL);
9814       else
9815         gtk_widget_set_sensitive (button, FALSE);
9816       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9817     }
9818
9819   separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
9820   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
9821
9822   box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
9823   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9824   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9825
9826   button = gtk_button_new_with_mnemonic ("_Close");
9827   g_signal_connect (button, "clicked",
9828                     G_CALLBACK (do_exit),
9829                     window);
9830   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9831   gtk_widget_set_can_default (button, TRUE);
9832   gtk_widget_grab_default (button);
9833
9834   gtk_widget_show_all (window);
9835 }
9836
9837 static void
9838 test_init (void)
9839 {
9840   if (g_file_test ("../modules/input/immodules.cache", G_FILE_TEST_EXISTS))
9841     g_setenv ("GTK_IM_MODULE_FILE", "../modules/input/immodules.cache", TRUE);
9842 }
9843
9844 static char *
9845 pad (const char *str, int to)
9846 {
9847   static char buf[256];
9848   int len = strlen (str);
9849   int i;
9850
9851   for (i = 0; i < to; i++)
9852     buf[i] = ' ';
9853
9854   buf[to] = '\0';
9855
9856   memcpy (buf, str, len);
9857
9858   return buf;
9859 }
9860
9861 static void
9862 bench_iteration (GtkWidget *widget, void (* fn) (GtkWidget *widget))
9863 {
9864   fn (widget); /* on */
9865   while (g_main_context_iteration (NULL, FALSE));
9866   fn (widget); /* off */
9867   while (g_main_context_iteration (NULL, FALSE));
9868 }
9869
9870 void
9871 do_real_bench (GtkWidget *widget, void (* fn) (GtkWidget *widget), char *name, int num)
9872 {
9873   GTimeVal tv0, tv1;
9874   double dt_first;
9875   double dt;
9876   int n;
9877   static gboolean printed_headers = FALSE;
9878
9879   if (!printed_headers) {
9880     g_print ("Test                 Iters      First      Other\n");
9881     g_print ("-------------------- ----- ---------- ----------\n");
9882     printed_headers = TRUE;
9883   }
9884
9885   g_get_current_time (&tv0);
9886   bench_iteration (widget, fn); 
9887   g_get_current_time (&tv1);
9888
9889   dt_first = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
9890         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
9891
9892   g_get_current_time (&tv0);
9893   for (n = 0; n < num - 1; n++)
9894     bench_iteration (widget, fn); 
9895   g_get_current_time (&tv1);
9896   dt = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
9897         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
9898
9899   g_print ("%s %5d ", pad (name, 20), num);
9900   if (num > 1)
9901     g_print ("%10.1f %10.1f\n", dt_first, dt/(num-1));
9902   else
9903     g_print ("%10.1f\n", dt_first);
9904 }
9905
9906 void
9907 do_bench (char* what, int num)
9908 {
9909   int i;
9910   GtkWidget *widget;
9911   void (* fn) (GtkWidget *widget);
9912   fn = NULL;
9913   widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9914
9915   if (g_ascii_strcasecmp (what, "ALL") == 0)
9916     {
9917       for (i = 0; i < nbuttons; i++)
9918         {
9919           if (!buttons[i].do_not_benchmark)
9920             do_real_bench (widget, buttons[i].func, buttons[i].label, num);
9921         }
9922
9923       return;
9924     }
9925   else
9926     {
9927       for (i = 0; i < nbuttons; i++)
9928         {
9929           if (strcmp (buttons[i].label, what) == 0)
9930             {
9931               fn = buttons[i].func;
9932               break;
9933             }
9934         }
9935       
9936       if (!fn)
9937         g_print ("Can't bench: \"%s\" not found.\n", what);
9938       else
9939         do_real_bench (widget, fn, buttons[i].label, num);
9940     }
9941 }
9942
9943 void 
9944 usage (void)
9945 {
9946   fprintf (stderr, "Usage: testgtk [--bench ALL|<bench>[:<count>]]\n");
9947   exit (1);
9948 }
9949
9950 int
9951 main (int argc, char *argv[])
9952 {
9953   GtkCssProvider *provider, *memory_provider;
9954   GdkDisplay *display;
9955   GdkScreen *screen;
9956   GtkBindingSet *binding_set;
9957   int i;
9958   gboolean done_benchmarks = FALSE;
9959
9960   srand (time (NULL));
9961
9962   test_init ();
9963
9964   g_set_application_name ("GTK+ Test Program");
9965
9966   gtk_init (&argc, &argv);
9967
9968   provider = gtk_css_provider_new ();
9969
9970   /* Check to see if we are being run from the correct
9971    * directory.
9972    */
9973   if (file_exists ("testgtk.css"))
9974     gtk_css_provider_load_from_path (provider, "testgtk.css", NULL);
9975   else if (file_exists ("tests/testgtk.css"))
9976     gtk_css_provider_load_from_path (provider, "tests/testgtk.css", NULL);
9977   else
9978     g_warning ("Couldn't find file \"testgtk.css\".");
9979
9980   display = gdk_display_get_default ();
9981   screen = gdk_display_get_default_screen (display);
9982
9983   gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER (provider),
9984                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
9985   g_object_unref (provider);
9986
9987   gtk_accelerator_set_default_mod_mask (GDK_SHIFT_MASK |
9988                                         GDK_CONTROL_MASK |
9989                                         GDK_MOD1_MASK | 
9990                                         GDK_META_MASK |
9991                                         GDK_SUPER_MASK |
9992                                         GDK_HYPER_MASK |
9993                                         GDK_MOD4_MASK);
9994   /*  benchmarking
9995    */
9996   for (i = 1; i < argc; i++)
9997     {
9998       if (strncmp (argv[i], "--bench", strlen("--bench")) == 0)
9999         {
10000           int num = 1;
10001           char *nextarg;
10002           char *what;
10003           char *count;
10004           
10005           nextarg = strchr (argv[i], '=');
10006           if (nextarg)
10007             nextarg++;
10008           else
10009             {
10010               i++;
10011               if (i == argc)
10012                 usage ();
10013               nextarg = argv[i];
10014             }
10015
10016           count = strchr (nextarg, ':');
10017           if (count)
10018             {
10019               what = g_strndup (nextarg, count - nextarg);
10020               count++;
10021               num = atoi (count);
10022               if (num <= 0)
10023                 usage ();
10024             }
10025           else
10026             what = g_strdup (nextarg);
10027
10028           do_bench (what, num ? num : 1);
10029           done_benchmarks = TRUE;
10030         }
10031       else
10032         usage ();
10033     }
10034   if (done_benchmarks)
10035     return 0;
10036
10037   /* bindings test
10038    */
10039   binding_set = gtk_binding_set_by_class (g_type_class_ref (GTK_TYPE_WIDGET));
10040   gtk_binding_entry_add_signal (binding_set,
10041                                 '9', GDK_CONTROL_MASK | GDK_RELEASE_MASK,
10042                                 "debug_msg",
10043                                 1,
10044                                 G_TYPE_STRING, "GtkWidgetClass <ctrl><release>9 test");
10045
10046   memory_provider = gtk_css_provider_new ();
10047   gtk_css_provider_load_from_data (memory_provider,
10048                                    "#testgtk-version-label {\n"
10049                                    "  color: #f00;\n"
10050                                    "  font: Sans 18;\n"
10051                                    "}",
10052                                    -1, NULL);
10053   gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER (memory_provider),
10054                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + 1);
10055
10056   create_main_window ();
10057
10058   gtk_main ();
10059
10060   if (1)
10061     {
10062       while (g_main_context_pending (NULL))
10063         g_main_context_iteration (NULL, FALSE);
10064 #if 0
10065       sleep (1);
10066       while (g_main_context_pending (NULL))
10067         g_main_context_iteration (NULL, FALSE);
10068 #endif
10069     }
10070   return 0;
10071 }