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