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