]> Pileus Git - ~andy/gtk/blob - tests/testgtk.c
tests: avoid boxed structs copying where possible
[~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_background_color (context, GTK_STATE_FLAG_NORMAL, &bg);
4850   gdk_cairo_set_source_rgba (cr, &bg);
4851   cairo_rectangle (cr, width / 3, height / 3, width / 3, height / 3);
4852   cairo_fill (cr);
4853
4854   return TRUE;
4855 }
4856
4857 static void
4858 set_cursor (GtkWidget *spinner,
4859             GtkWidget *widget)
4860 {
4861   guint c;
4862   GdkCursor *cursor;
4863   GtkWidget *label;
4864   GEnumClass *class;
4865   GEnumValue *vals;
4866
4867   c = CLAMP (gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spinner)), 0, 152);
4868   c &= 0xfe;
4869
4870   label = g_object_get_data (G_OBJECT (spinner), "user_data");
4871   
4872   class = g_type_class_ref (GDK_TYPE_CURSOR_TYPE);
4873   vals = class->values;
4874
4875   while (vals && vals->value != c)
4876     vals++;
4877   if (vals)
4878     gtk_label_set_text (GTK_LABEL (label), vals->value_nick);
4879   else
4880     gtk_label_set_text (GTK_LABEL (label), "<unknown>");
4881
4882   g_type_class_unref (class);
4883
4884   cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), c);
4885   gdk_window_set_cursor (gtk_widget_get_window (widget),
4886                          cursor);
4887   g_object_unref (cursor);
4888 }
4889
4890 static gint
4891 cursor_event (GtkWidget          *widget,
4892               GdkEvent           *event,
4893               GtkSpinButton      *spinner)
4894 {
4895   if ((event->type == GDK_BUTTON_PRESS) &&
4896       ((event->button.button == 1) ||
4897        (event->button.button == 3)))
4898     {
4899       gtk_spin_button_spin (spinner, event->button.button == 1 ?
4900                             GTK_SPIN_STEP_FORWARD : GTK_SPIN_STEP_BACKWARD, 0);
4901       return TRUE;
4902     }
4903
4904   return FALSE;
4905 }
4906
4907 #ifdef GDK_WINDOWING_X11
4908 #include "x11/gdkx.h"
4909
4910 static void
4911 change_cursor_theme (GtkWidget *widget,
4912                      gpointer   data)
4913 {
4914   const gchar *theme;
4915   gint size;
4916   GList *children;
4917
4918   children = gtk_container_get_children (GTK_CONTAINER (data));
4919
4920   theme = gtk_entry_get_text (GTK_ENTRY (children->next->data));
4921   size = (gint) gtk_spin_button_get_value (GTK_SPIN_BUTTON (children->next->next->data));
4922
4923   g_list_free (children);
4924
4925   gdk_x11_display_set_cursor_theme (gtk_widget_get_display (widget),
4926                                     theme, size);
4927 }
4928 #endif
4929
4930
4931 static void
4932 create_cursors (GtkWidget *widget)
4933 {
4934   static GtkWidget *window = NULL;
4935   GtkWidget *frame;
4936   GtkWidget *hbox;
4937   GtkWidget *main_vbox;
4938   GtkWidget *vbox;
4939   GtkWidget *darea;
4940   GtkWidget *spinner;
4941   GtkWidget *button;
4942   GtkWidget *label;
4943   GtkWidget *any;
4944   GtkAdjustment *adjustment;
4945   GtkWidget *entry;
4946   GtkWidget *size;  
4947
4948   if (!window)
4949     {
4950       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4951       gtk_window_set_screen (GTK_WINDOW (window), 
4952                              gtk_widget_get_screen (widget));
4953       
4954       g_signal_connect (window, "destroy",
4955                         G_CALLBACK (gtk_widget_destroyed),
4956                         &window);
4957       
4958       gtk_window_set_title (GTK_WINDOW (window), "Cursors");
4959       
4960       main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
4961       gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 0);
4962       gtk_container_add (GTK_CONTAINER (window), main_vbox);
4963
4964       vbox =
4965         g_object_new (GTK_TYPE_BOX,
4966                       "orientation", GTK_ORIENTATION_VERTICAL,
4967                         "GtkBox::homogeneous", FALSE,
4968                         "GtkBox::spacing", 5,
4969                         "GtkContainer::border_width", 10,
4970                         "GtkWidget::parent", main_vbox,
4971                         "GtkWidget::visible", TRUE,
4972                         NULL);
4973
4974 #ifdef GDK_WINDOWING_X11
4975       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
4976       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
4977       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
4978
4979       label = gtk_label_new ("Cursor Theme : ");
4980       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
4981       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
4982
4983       entry = gtk_entry_new ();
4984       gtk_entry_set_text (GTK_ENTRY (entry), "default");
4985       gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, TRUE, 0);
4986
4987       size = gtk_spin_button_new_with_range (1.0, 64.0, 1.0);
4988       gtk_spin_button_set_value (GTK_SPIN_BUTTON (size), 24.0);
4989       gtk_box_pack_start (GTK_BOX (hbox), size, TRUE, TRUE, 0);
4990       
4991       g_signal_connect (entry, "changed", 
4992                         G_CALLBACK (change_cursor_theme), hbox);
4993       g_signal_connect (size, "changed", 
4994                         G_CALLBACK (change_cursor_theme), hbox);
4995 #endif
4996
4997       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
4998       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
4999       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
5000
5001       label = gtk_label_new ("Cursor Value : ");
5002       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5003       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
5004
5005       adjustment = gtk_adjustment_new (0,
5006                                 0, 152,
5007                                 2,
5008                                 10, 0);
5009       spinner = gtk_spin_button_new (adjustment, 0, 0);
5010       gtk_box_pack_start (GTK_BOX (hbox), spinner, TRUE, TRUE, 0);
5011
5012       frame =
5013         g_object_new (gtk_frame_get_type (),
5014                         "GtkFrame::label_xalign", 0.5,
5015                         "GtkFrame::label", "Cursor Area",
5016                         "GtkContainer::border_width", 10,
5017                         "GtkWidget::parent", vbox,
5018                         "GtkWidget::visible", TRUE,
5019                         NULL);
5020
5021       darea = gtk_drawing_area_new ();
5022       gtk_widget_set_size_request (darea, 80, 80);
5023       gtk_container_add (GTK_CONTAINER (frame), darea);
5024       g_signal_connect (darea,
5025                         "draw",
5026                         G_CALLBACK (cursor_draw),
5027                         NULL);
5028       gtk_widget_set_events (darea, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
5029       g_signal_connect (darea,
5030                         "button_press_event",
5031                         G_CALLBACK (cursor_event),
5032                         spinner);
5033       gtk_widget_show (darea);
5034
5035       g_signal_connect (spinner, "changed",
5036                         G_CALLBACK (set_cursor),
5037                         darea);
5038
5039       label = g_object_new (GTK_TYPE_LABEL,
5040                               "visible", TRUE,
5041                               "label", "XXX",
5042                               "parent", vbox,
5043                               NULL);
5044       gtk_container_child_set (GTK_CONTAINER (vbox), label,
5045                                "expand", FALSE,
5046                                NULL);
5047       g_object_set_data (G_OBJECT (spinner), "user_data", label);
5048
5049       any =
5050         g_object_new (gtk_hseparator_get_type (),
5051                         "GtkWidget::visible", TRUE,
5052                         NULL);
5053       gtk_box_pack_start (GTK_BOX (main_vbox), any, FALSE, TRUE, 0);
5054   
5055       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
5056       gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
5057       gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
5058
5059       button = gtk_button_new_with_label ("Close");
5060       g_signal_connect_swapped (button, "clicked",
5061                                 G_CALLBACK (gtk_widget_destroy),
5062                                 window);
5063       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5064
5065       gtk_widget_show_all (window);
5066
5067       set_cursor (spinner, darea);
5068     }
5069   else
5070     gtk_widget_destroy (window);
5071 }
5072
5073 /*
5074  * GtkColorSelection
5075  */
5076
5077 void
5078 color_selection_ok (GtkWidget               *w,
5079                     GtkColorSelectionDialog *cs)
5080 {
5081   GtkWidget *colorsel;
5082   GdkColor color;
5083
5084   colorsel = gtk_color_selection_dialog_get_color_selection (cs);
5085
5086   gtk_color_selection_get_current_color (GTK_COLOR_SELECTION (colorsel), &color);
5087   gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (colorsel), &color);
5088 }
5089
5090 void
5091 color_selection_changed (GtkWidget *w,
5092                          GtkColorSelectionDialog *cs)
5093 {
5094   GtkWidget *colorsel;
5095   GdkColor color;
5096
5097   colorsel = gtk_color_selection_dialog_get_color_selection (cs);
5098   gtk_color_selection_get_current_color (GTK_COLOR_SELECTION (colorsel), &color);
5099   gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (colorsel), &color);
5100 }
5101
5102 #if 0 /* unused */
5103 static void
5104 opacity_toggled_cb (GtkWidget *w,
5105                     GtkColorSelectionDialog *cs)
5106 {
5107   GtkColorSelection *colorsel;
5108
5109   colorsel = GTK_COLOR_SELECTION (cs->colorsel);
5110   gtk_color_selection_set_has_opacity_control (colorsel,
5111                                                gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
5112 }
5113
5114 static void
5115 palette_toggled_cb (GtkWidget *w,
5116                     GtkColorSelectionDialog *cs)
5117 {
5118   GtkColorSelection *colorsel;
5119
5120   colorsel = GTK_COLOR_SELECTION (cs->colorsel);
5121   gtk_color_selection_set_has_palette (colorsel,
5122                                        gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
5123 }
5124 #endif
5125
5126 void
5127 create_color_selection (GtkWidget *widget)
5128 {
5129   static GtkWidget *window = NULL;
5130
5131   if (!window)
5132     {
5133       GtkWidget *picker;
5134       GtkWidget *hbox;
5135       GtkWidget *label;
5136       GtkWidget *button;
5137       
5138       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5139       gtk_window_set_screen (GTK_WINDOW (window), 
5140                              gtk_widget_get_screen (widget));
5141                              
5142       g_signal_connect (window, "destroy",
5143                         G_CALLBACK (gtk_widget_destroyed),
5144                         &window);
5145
5146       gtk_window_set_title (GTK_WINDOW (window), "GtkColorButton");
5147       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5148
5149       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
5150       gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
5151       gtk_container_add (GTK_CONTAINER (window), hbox);
5152       
5153       label = gtk_label_new ("Pick a color");
5154       gtk_container_add (GTK_CONTAINER (hbox), label);
5155
5156       picker = gtk_color_button_new ();
5157       gtk_color_button_set_use_alpha (GTK_COLOR_BUTTON (picker), TRUE);
5158       gtk_container_add (GTK_CONTAINER (hbox), picker);
5159
5160       button = gtk_button_new_with_mnemonic ("_Props");
5161       gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
5162       g_signal_connect (button, "clicked",
5163                         G_CALLBACK (props_clicked),
5164                         picker);
5165     }
5166
5167   if (!gtk_widget_get_visible (window))
5168     gtk_widget_show_all (window);
5169   else
5170     gtk_widget_destroy (window);
5171 }
5172
5173 void
5174 flipping_toggled_cb (GtkWidget *widget, gpointer data)
5175 {
5176   int state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
5177   int new_direction = state ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
5178
5179   gtk_widget_set_default_direction (new_direction);
5180 }
5181
5182 static void
5183 orientable_toggle_orientation (GtkOrientable *orientable)
5184 {
5185   GtkOrientation orientation;
5186
5187   orientation = gtk_orientable_get_orientation (orientable);
5188   gtk_orientable_set_orientation (orientable,
5189                                   orientation == GTK_ORIENTATION_HORIZONTAL ?
5190                                   GTK_ORIENTATION_VERTICAL :
5191                                   GTK_ORIENTATION_HORIZONTAL);
5192
5193   if (GTK_IS_CONTAINER (orientable))
5194     {
5195       GList *children;
5196       GList *child;
5197
5198       children = gtk_container_get_children (GTK_CONTAINER (orientable));
5199
5200       for (child = children; child; child = child->next)
5201         {
5202           if (GTK_IS_ORIENTABLE (child->data))
5203             orientable_toggle_orientation (child->data);
5204         }
5205
5206       g_list_free (children);
5207     }
5208 }
5209
5210 void
5211 flipping_orientation_toggled_cb (GtkWidget *widget, gpointer data)
5212 {
5213   GtkWidget *content_area;
5214   GtkWidget *toplevel;
5215
5216   toplevel = gtk_widget_get_toplevel (widget);
5217   content_area = gtk_dialog_get_content_area (GTK_DIALOG (toplevel));
5218   orientable_toggle_orientation (GTK_ORIENTABLE (content_area));
5219 }
5220
5221 static void
5222 set_direction_recurse (GtkWidget *widget,
5223                        gpointer   data)
5224 {
5225   GtkTextDirection *dir = data;
5226   
5227   gtk_widget_set_direction (widget, *dir);
5228   if (GTK_IS_CONTAINER (widget))
5229     gtk_container_foreach (GTK_CONTAINER (widget),
5230                            set_direction_recurse,
5231                            data);
5232 }
5233
5234 static GtkWidget *
5235 create_forward_back (const char       *title,
5236                      GtkTextDirection  text_dir)
5237 {
5238   GtkWidget *frame = gtk_frame_new (title);
5239   GtkWidget *bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
5240   GtkWidget *back_button = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
5241   GtkWidget *forward_button = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
5242
5243   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
5244   
5245   gtk_container_add (GTK_CONTAINER (frame), bbox);
5246   gtk_container_add (GTK_CONTAINER (bbox), back_button);
5247   gtk_container_add (GTK_CONTAINER (bbox), forward_button);
5248
5249   set_direction_recurse (frame, &text_dir);
5250
5251   return frame;
5252 }
5253
5254 void
5255 create_flipping (GtkWidget *widget)
5256 {
5257   static GtkWidget *window = NULL;
5258   GtkWidget *check_button, *button;
5259   GtkWidget *action_area, *content_area;
5260
5261   if (!window)
5262     {
5263       window = gtk_dialog_new ();
5264
5265       gtk_window_set_screen (GTK_WINDOW (window),
5266                              gtk_widget_get_screen (widget));
5267
5268       g_signal_connect (window, "destroy",
5269                         G_CALLBACK (gtk_widget_destroyed),
5270                         &window);
5271
5272       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
5273       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
5274
5275       gtk_window_set_title (GTK_WINDOW (window), "Bidirectional Flipping");
5276
5277       check_button = gtk_check_button_new_with_label ("Right-to-left global direction");
5278       gtk_container_set_border_width (GTK_CONTAINER (check_button), 10);
5279       gtk_box_pack_start (GTK_BOX (content_area), check_button, TRUE, TRUE, 0);
5280
5281       if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL)
5282         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button), TRUE);
5283
5284       g_signal_connect (check_button, "toggled",
5285                         G_CALLBACK (flipping_toggled_cb), NULL);
5286
5287       check_button = gtk_check_button_new_with_label ("Toggle orientation of all boxes");
5288       gtk_container_set_border_width (GTK_CONTAINER (check_button), 10);
5289       gtk_box_pack_start (GTK_BOX (content_area), check_button, TRUE, TRUE, 0);
5290
5291       g_signal_connect (check_button, "toggled",
5292                         G_CALLBACK (flipping_orientation_toggled_cb), NULL);
5293
5294       gtk_box_pack_start (GTK_BOX (content_area),
5295                           create_forward_back ("Default", GTK_TEXT_DIR_NONE),
5296                           TRUE, TRUE, 0);
5297
5298       gtk_box_pack_start (GTK_BOX (content_area),
5299                           create_forward_back ("Left-to-Right", GTK_TEXT_DIR_LTR),
5300                           TRUE, TRUE, 0);
5301
5302       gtk_box_pack_start (GTK_BOX (content_area),
5303                           create_forward_back ("Right-to-Left", GTK_TEXT_DIR_RTL),
5304                           TRUE, TRUE, 0);
5305
5306       button = gtk_button_new_with_label ("Close");
5307       g_signal_connect_swapped (button, "clicked",
5308                                 G_CALLBACK (gtk_widget_destroy), window);
5309       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
5310     }
5311   
5312   if (!gtk_widget_get_visible (window))
5313     gtk_widget_show_all (window);
5314   else
5315     gtk_widget_destroy (window);
5316 }
5317
5318 /*
5319  * Focus test
5320  */
5321
5322 static GtkWidget*
5323 make_focus_table (GList **list)
5324 {
5325   GtkWidget *table;
5326   gint i, j;
5327   
5328   table = gtk_table_new (5, 5, FALSE);
5329
5330   i = 0;
5331   j = 0;
5332
5333   while (i < 5)
5334     {
5335       j = 0;
5336       while (j < 5)
5337         {
5338           GtkWidget *widget;
5339           
5340           if ((i + j) % 2)
5341             widget = gtk_entry_new ();
5342           else
5343             widget = gtk_button_new_with_label ("Foo");
5344
5345           *list = g_list_prepend (*list, widget);
5346           
5347           gtk_table_attach (GTK_TABLE (table),
5348                             widget,
5349                             i, i + 1,
5350                             j, j + 1,
5351                             GTK_EXPAND | GTK_FILL,
5352                             GTK_EXPAND | GTK_FILL,
5353                             5, 5);
5354           
5355           ++j;
5356         }
5357
5358       ++i;
5359     }
5360
5361   *list = g_list_reverse (*list);
5362   
5363   return table;
5364 }
5365
5366 static void
5367 create_focus (GtkWidget *widget)
5368 {
5369   static GtkWidget *window = NULL;
5370   
5371   if (!window)
5372     {
5373       GtkWidget *content_area;
5374       GtkWidget *table;
5375       GtkWidget *frame;
5376       GList *list = NULL;
5377       
5378       window = gtk_dialog_new_with_buttons ("Keyboard focus navigation",
5379                                             NULL, 0,
5380                                             GTK_STOCK_CLOSE,
5381                                             GTK_RESPONSE_NONE,
5382                                             NULL);
5383
5384       gtk_window_set_screen (GTK_WINDOW (window),
5385                              gtk_widget_get_screen (widget));
5386
5387       g_signal_connect (window, "destroy",
5388                         G_CALLBACK (gtk_widget_destroyed),
5389                         &window);
5390
5391       g_signal_connect (window, "response",
5392                         G_CALLBACK (gtk_widget_destroy),
5393                         NULL);
5394
5395       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
5396       
5397       gtk_window_set_title (GTK_WINDOW (window), "Keyboard Focus Navigation");
5398
5399       frame = gtk_frame_new ("Weird tab focus chain");
5400
5401       gtk_box_pack_start (GTK_BOX (content_area), frame, TRUE, TRUE, 0);
5402       
5403       table = make_focus_table (&list);
5404
5405       gtk_container_add (GTK_CONTAINER (frame), table);
5406
5407       gtk_container_set_focus_chain (GTK_CONTAINER (table),
5408                                      list);
5409
5410       g_list_free (list);
5411       
5412       frame = gtk_frame_new ("Default tab focus chain");
5413
5414       gtk_box_pack_start (GTK_BOX (content_area), frame, TRUE, TRUE, 0);
5415
5416       list = NULL;
5417       table = make_focus_table (&list);
5418
5419       g_list_free (list);
5420       
5421       gtk_container_add (GTK_CONTAINER (frame), table);      
5422     }
5423   
5424   if (!gtk_widget_get_visible (window))
5425     gtk_widget_show_all (window);
5426   else
5427     gtk_widget_destroy (window);
5428 }
5429
5430 /*
5431  * GtkFontSelection
5432  */
5433
5434 void
5435 font_selection_ok (GtkWidget              *w,
5436                    GtkFontSelectionDialog *fs)
5437 {
5438   gchar *s = gtk_font_selection_dialog_get_font_name (fs);
5439
5440   g_print ("%s\n", s);
5441   g_free (s);
5442   gtk_widget_destroy (GTK_WIDGET (fs));
5443 }
5444
5445 void
5446 create_font_selection (GtkWidget *widget)
5447 {
5448   static GtkWidget *window = NULL;
5449
5450   if (!window)
5451     {
5452       GtkWidget *picker;
5453       GtkWidget *hbox;
5454       GtkWidget *label;
5455       
5456       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5457       gtk_window_set_screen (GTK_WINDOW (window),
5458                              gtk_widget_get_screen (widget));
5459
5460       g_signal_connect (window, "destroy",
5461                         G_CALLBACK (gtk_widget_destroyed),
5462                         &window);
5463
5464       gtk_window_set_title (GTK_WINDOW (window), "GtkFontButton");
5465       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5466
5467       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
5468       gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
5469       gtk_container_add (GTK_CONTAINER (window), hbox);
5470       
5471       label = gtk_label_new ("Pick a font");
5472       gtk_container_add (GTK_CONTAINER (hbox), label);
5473
5474       picker = gtk_font_button_new ();
5475       gtk_font_button_set_use_font (GTK_FONT_BUTTON (picker), TRUE);
5476       gtk_container_add (GTK_CONTAINER (hbox), picker);
5477     }
5478   
5479   if (!gtk_widget_get_visible (window))
5480     gtk_widget_show_all (window);
5481   else
5482     gtk_widget_destroy (window);
5483 }
5484
5485 /*
5486  * GtkDialog
5487  */
5488
5489 static GtkWidget *dialog_window = NULL;
5490
5491 static void
5492 label_toggle (GtkWidget  *widget,
5493               GtkWidget **label)
5494 {
5495   if (!(*label))
5496     {
5497       *label = gtk_label_new ("Dialog Test");
5498       g_signal_connect (*label,
5499                         "destroy",
5500                         G_CALLBACK (gtk_widget_destroyed),
5501                         label);
5502       gtk_misc_set_padding (GTK_MISC (*label), 10, 10);
5503       gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog_window))),
5504                           *label, TRUE, TRUE, 0);
5505       gtk_widget_show (*label);
5506     }
5507   else
5508     gtk_widget_destroy (*label);
5509 }
5510
5511 static void
5512 create_dialog (GtkWidget *widget)
5513 {
5514   static GtkWidget *label;
5515   GtkWidget *action_area;
5516   GtkWidget *button;
5517
5518   if (!dialog_window)
5519     {
5520       /* This is a terrible example; it's much simpler to create
5521        * dialogs than this. Don't use testgtk for example code,
5522        * use gtk-demo ;-)
5523        */
5524       
5525       dialog_window = gtk_dialog_new ();
5526       gtk_window_set_screen (GTK_WINDOW (dialog_window),
5527                              gtk_widget_get_screen (widget));
5528
5529       g_signal_connect (dialog_window, "destroy",
5530                         G_CALLBACK (gtk_widget_destroyed),
5531                         &dialog_window);
5532
5533       action_area = gtk_dialog_get_action_area (GTK_DIALOG (dialog_window));
5534
5535       gtk_window_set_title (GTK_WINDOW (dialog_window), "GtkDialog");
5536       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
5537
5538       button = gtk_button_new_with_label ("OK");
5539       gtk_widget_set_can_default (button, TRUE);
5540       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
5541       gtk_widget_grab_default (button);
5542       gtk_widget_show (button);
5543
5544       button = gtk_button_new_with_label ("Toggle");
5545       g_signal_connect (button, "clicked",
5546                         G_CALLBACK (label_toggle),
5547                         &label);
5548       gtk_widget_set_can_default (button, TRUE);
5549       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
5550       gtk_widget_show (button);
5551
5552       label = NULL;
5553     }
5554
5555   if (!gtk_widget_get_visible (dialog_window))
5556     gtk_widget_show (dialog_window);
5557   else
5558     gtk_widget_destroy (dialog_window);
5559 }
5560
5561 /* Display & Screen test 
5562  */
5563
5564 typedef struct
5565 {
5566   GtkWidget *combo;
5567   GtkWidget *entry;
5568   GtkWidget *radio_dpy;
5569   GtkWidget *toplevel;
5570   GtkWidget *dialog_window;
5571 } ScreenDisplaySelection;
5572
5573 static void
5574 screen_display_check (GtkWidget *widget, ScreenDisplaySelection *data)
5575 {
5576   const gchar *display_name;
5577   GdkDisplay *display = gtk_widget_get_display (widget);
5578   GtkWidget *dialog;
5579   GdkScreen *new_screen = NULL;
5580   GdkScreen *current_screen = gtk_widget_get_screen (widget);
5581   
5582   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->radio_dpy)))
5583     {
5584       display_name = gtk_entry_get_text (GTK_ENTRY (data->entry));
5585       display = gdk_display_open (display_name);
5586       
5587       if (!display)
5588         {
5589           dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (widget)),
5590                                            GTK_DIALOG_DESTROY_WITH_PARENT,
5591                                            GTK_MESSAGE_ERROR,
5592                                            GTK_BUTTONS_OK,
5593                                            "The display :\n%s\ncannot be opened",
5594                                            display_name);
5595           gtk_window_set_screen (GTK_WINDOW (dialog), current_screen);
5596           gtk_widget_show (dialog);
5597           g_signal_connect (dialog, "response",
5598                             G_CALLBACK (gtk_widget_destroy),
5599                             NULL);
5600         }
5601       else
5602         {
5603           GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX (data->combo));
5604           gint i = 0;
5605           GtkTreeIter iter;
5606           gboolean found = FALSE;
5607           while (gtk_tree_model_iter_nth_child (model, &iter, NULL, i++))
5608             {
5609               gchar *name;
5610               gtk_tree_model_get (model, &iter, 0, &name, -1);
5611               found = !g_ascii_strcasecmp (display_name, name);
5612               g_free (name);
5613
5614               if (found)
5615                 break;
5616             }
5617           if (!found)
5618             gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (data->combo), display_name);
5619           new_screen = gdk_display_get_default_screen (display);
5620         }
5621     }
5622   else
5623     {
5624       gint number_of_screens = gdk_display_get_n_screens (display);
5625       gint screen_num = gdk_screen_get_number (current_screen);
5626       if ((screen_num +1) < number_of_screens)
5627         new_screen = gdk_display_get_screen (display, screen_num + 1);
5628       else
5629         new_screen = gdk_display_get_screen (display, 0);
5630     }
5631   
5632   if (new_screen) 
5633     {
5634       gtk_window_set_screen (GTK_WINDOW (data->toplevel), new_screen);
5635       gtk_widget_destroy (data->dialog_window);
5636     }
5637 }
5638
5639 void
5640 screen_display_destroy_diag (GtkWidget *widget, GtkWidget *data)
5641 {
5642   gtk_widget_destroy (data);
5643 }
5644
5645 void
5646 create_display_screen (GtkWidget *widget)
5647 {
5648   GtkWidget *table, *frame, *window, *combo_dpy, *vbox;
5649   GtkWidget *radio_dpy, *radio_scr, *applyb, *cancelb;
5650   GtkWidget *bbox;
5651   ScreenDisplaySelection *scr_dpy_data;
5652   GdkScreen *screen = gtk_widget_get_screen (widget);
5653   GdkDisplay *display = gdk_screen_get_display (screen);
5654
5655   window = g_object_new (gtk_window_get_type (),
5656                            "screen", screen,
5657                            "user_data", NULL,
5658                            "type", GTK_WINDOW_TOPLEVEL,
5659                            "title",
5660                            "Screen or Display selection",
5661                            "border_width", 10, NULL);
5662   g_signal_connect (window, "destroy", 
5663                     G_CALLBACK (gtk_widget_destroy), NULL);
5664
5665   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3);
5666   gtk_container_add (GTK_CONTAINER (window), vbox);
5667   
5668   frame = gtk_frame_new ("Select screen or display");
5669   gtk_container_add (GTK_CONTAINER (vbox), frame);
5670   
5671   table = gtk_table_new (2, 2, TRUE);
5672   gtk_table_set_row_spacings (GTK_TABLE (table), 3);
5673   gtk_table_set_col_spacings (GTK_TABLE (table), 3);
5674
5675   gtk_container_add (GTK_CONTAINER (frame), table);
5676
5677   radio_dpy = gtk_radio_button_new_with_label (NULL, "move to another X display");
5678   if (gdk_display_get_n_screens(display) > 1)
5679     radio_scr = gtk_radio_button_new_with_label 
5680     (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), "move to next screen");
5681   else
5682     {    
5683       radio_scr = gtk_radio_button_new_with_label 
5684         (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), 
5685          "only one screen on the current display");
5686       gtk_widget_set_sensitive (radio_scr, FALSE);
5687     }
5688   combo_dpy = gtk_combo_box_text_new_with_entry ();
5689   gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_dpy), "diabolo:0.0");
5690   gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (combo_dpy))),
5691                       "<hostname>:<X Server Num>.<Screen Num>");
5692
5693   gtk_table_attach_defaults (GTK_TABLE (table), radio_dpy, 0, 1, 0, 1);
5694   gtk_table_attach_defaults (GTK_TABLE (table), radio_scr, 0, 1, 1, 2);
5695   gtk_table_attach_defaults (GTK_TABLE (table), combo_dpy, 1, 2, 0, 1);
5696
5697   bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
5698   applyb = gtk_button_new_from_stock (GTK_STOCK_APPLY);
5699   cancelb = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
5700   
5701   gtk_container_add (GTK_CONTAINER (vbox), bbox);
5702
5703   gtk_container_add (GTK_CONTAINER (bbox), applyb);
5704   gtk_container_add (GTK_CONTAINER (bbox), cancelb);
5705
5706   scr_dpy_data = g_new0 (ScreenDisplaySelection, 1);
5707
5708   scr_dpy_data->entry = gtk_bin_get_child (GTK_BIN (combo_dpy));
5709   scr_dpy_data->radio_dpy = radio_dpy;
5710   scr_dpy_data->toplevel = gtk_widget_get_toplevel (widget);
5711   scr_dpy_data->dialog_window = window;
5712
5713   g_signal_connect (cancelb, "clicked", 
5714                     G_CALLBACK (screen_display_destroy_diag), window);
5715   g_signal_connect (applyb, "clicked", 
5716                     G_CALLBACK (screen_display_check), scr_dpy_data);
5717   gtk_widget_show_all (window);
5718 }
5719
5720 /* Event Watcher
5721  */
5722 static gulong event_watcher_enter_id = 0;
5723 static gulong event_watcher_leave_id = 0;
5724
5725 static gboolean
5726 event_watcher (GSignalInvocationHint *ihint,
5727                guint                  n_param_values,
5728                const GValue          *param_values,
5729                gpointer               data)
5730 {
5731   g_print ("Watch: \"%s\" emitted for %s\n",
5732            g_signal_name (ihint->signal_id),
5733            G_OBJECT_TYPE_NAME (g_value_get_object (param_values + 0)));
5734
5735   return TRUE;
5736 }
5737
5738 static void
5739 event_watcher_down (void)
5740 {
5741   if (event_watcher_enter_id)
5742     {
5743       guint signal_id;
5744
5745       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
5746       g_signal_remove_emission_hook (signal_id, event_watcher_enter_id);
5747       event_watcher_enter_id = 0;
5748       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
5749       g_signal_remove_emission_hook (signal_id, event_watcher_leave_id);
5750       event_watcher_leave_id = 0;
5751     }
5752 }
5753
5754 static void
5755 event_watcher_toggle (void)
5756 {
5757   if (event_watcher_enter_id)
5758     event_watcher_down ();
5759   else
5760     {
5761       guint signal_id;
5762
5763       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
5764       event_watcher_enter_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
5765       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
5766       event_watcher_leave_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
5767     }
5768 }
5769
5770 static void
5771 create_event_watcher (GtkWidget *widget)
5772 {
5773   GtkWidget *action_area, *content_area;
5774   GtkWidget *button;
5775
5776   if (!dialog_window)
5777     {
5778       dialog_window = gtk_dialog_new ();
5779       gtk_window_set_screen (GTK_WINDOW (dialog_window),
5780                              gtk_widget_get_screen (widget));
5781
5782       g_signal_connect (dialog_window, "destroy",
5783                         G_CALLBACK (gtk_widget_destroyed),
5784                         &dialog_window);
5785       g_signal_connect (dialog_window, "destroy",
5786                         G_CALLBACK (event_watcher_down),
5787                         NULL);
5788
5789       content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog_window));
5790       action_area = gtk_dialog_get_action_area (GTK_DIALOG (dialog_window));
5791
5792       gtk_window_set_title (GTK_WINDOW (dialog_window), "Event Watcher");
5793       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
5794       gtk_widget_set_size_request (dialog_window, 200, 110);
5795
5796       button = gtk_toggle_button_new_with_label ("Activate Watch");
5797       g_signal_connect (button, "clicked",
5798                         G_CALLBACK (event_watcher_toggle),
5799                         NULL);
5800       gtk_container_set_border_width (GTK_CONTAINER (button), 10);
5801       gtk_box_pack_start (GTK_BOX (content_area), button, TRUE, TRUE, 0);
5802       gtk_widget_show (button);
5803
5804       button = gtk_button_new_with_label ("Close");
5805       g_signal_connect_swapped (button, "clicked",
5806                                 G_CALLBACK (gtk_widget_destroy),
5807                                 dialog_window);
5808       gtk_widget_set_can_default (button, TRUE);
5809       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
5810       gtk_widget_grab_default (button);
5811       gtk_widget_show (button);
5812     }
5813
5814   if (!gtk_widget_get_visible (dialog_window))
5815     gtk_widget_show (dialog_window);
5816   else
5817     gtk_widget_destroy (dialog_window);
5818 }
5819
5820 /*
5821  * GtkRange
5822  */
5823
5824 static gchar*
5825 reformat_value (GtkScale *scale,
5826                 gdouble   value)
5827 {
5828   return g_strdup_printf ("-->%0.*g<--",
5829                           gtk_scale_get_digits (scale), value);
5830 }
5831
5832 static void
5833 create_range_controls (GtkWidget *widget)
5834 {
5835   static GtkWidget *window = NULL;
5836   GtkWidget *box1;
5837   GtkWidget *box2;
5838   GtkWidget *button;
5839   GtkWidget *scrollbar;
5840   GtkWidget *scale;
5841   GtkWidget *separator;
5842   GtkAdjustment *adjustment;
5843   GtkWidget *hbox;
5844
5845   if (!window)
5846     {
5847       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5848
5849       gtk_window_set_screen (GTK_WINDOW (window),
5850                              gtk_widget_get_screen (widget));
5851
5852       g_signal_connect (window, "destroy",
5853                         G_CALLBACK (gtk_widget_destroyed),
5854                         &window);
5855
5856       gtk_window_set_title (GTK_WINDOW (window), "range controls");
5857       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5858
5859
5860       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
5861       gtk_container_add (GTK_CONTAINER (window), box1);
5862       gtk_widget_show (box1);
5863
5864
5865       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
5866       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
5867       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
5868       gtk_widget_show (box2);
5869
5870
5871       adjustment = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
5872
5873       scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (adjustment));
5874       gtk_widget_set_size_request (GTK_WIDGET (scale), 150, -1);
5875       gtk_scale_set_digits (GTK_SCALE (scale), 1);
5876       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
5877       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
5878       gtk_widget_show (scale);
5879
5880       scrollbar = gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (adjustment));
5881       gtk_box_pack_start (GTK_BOX (box2), scrollbar, TRUE, TRUE, 0);
5882       gtk_widget_show (scrollbar);
5883
5884       scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (adjustment));
5885       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
5886       g_signal_connect (scale,
5887                         "format_value",
5888                         G_CALLBACK (reformat_value),
5889                         NULL);
5890       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
5891       gtk_widget_show (scale);
5892       
5893       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
5894
5895       scale = gtk_scale_new (GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT (adjustment));
5896       gtk_widget_set_size_request (scale, -1, 200);
5897       gtk_scale_set_digits (GTK_SCALE (scale), 2);
5898       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
5899       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
5900       gtk_widget_show (scale);
5901
5902       scale = gtk_scale_new (GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT (adjustment));
5903       gtk_widget_set_size_request (scale, -1, 200);
5904       gtk_scale_set_digits (GTK_SCALE (scale), 2);
5905       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
5906       gtk_range_set_inverted (GTK_RANGE (scale), TRUE);
5907       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
5908       gtk_widget_show (scale);
5909
5910       scale = gtk_scale_new (GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT (adjustment));
5911       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
5912       g_signal_connect (scale,
5913                         "format_value",
5914                         G_CALLBACK (reformat_value),
5915                         NULL);
5916       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
5917       gtk_widget_show (scale);
5918
5919       
5920       gtk_box_pack_start (GTK_BOX (box2), hbox, TRUE, TRUE, 0);
5921       gtk_widget_show (hbox);
5922       
5923       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
5924       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
5925       gtk_widget_show (separator);
5926
5927
5928       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
5929       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
5930       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
5931       gtk_widget_show (box2);
5932
5933
5934       button = gtk_button_new_with_label ("close");
5935       g_signal_connect_swapped (button, "clicked",
5936                                 G_CALLBACK (gtk_widget_destroy),
5937                                 window);
5938       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
5939       gtk_widget_set_can_default (button, TRUE);
5940       gtk_widget_grab_default (button);
5941       gtk_widget_show (button);
5942     }
5943
5944   if (!gtk_widget_get_visible (window))
5945     gtk_widget_show (window);
5946   else
5947     gtk_widget_destroy (window);
5948 }
5949
5950 struct {
5951   GdkColor color;
5952   gchar *name;
5953 } text_colors[] = {
5954  { { 0, 0x0000, 0x0000, 0x0000 }, "black" },
5955  { { 0, 0xFFFF, 0xFFFF, 0xFFFF }, "white" },
5956  { { 0, 0xFFFF, 0x0000, 0x0000 }, "red" },
5957  { { 0, 0x0000, 0xFFFF, 0x0000 }, "green" },
5958  { { 0, 0x0000, 0x0000, 0xFFFF }, "blue" }, 
5959  { { 0, 0x0000, 0xFFFF, 0xFFFF }, "cyan" },
5960  { { 0, 0xFFFF, 0x0000, 0xFFFF }, "magenta" },
5961  { { 0, 0xFFFF, 0xFFFF, 0x0000 }, "yellow" }
5962 };
5963
5964 int ntext_colors = sizeof(text_colors) / sizeof(text_colors[0]);
5965
5966 /*
5967  * GtkNotebook
5968  */
5969
5970 static const char * book_open_xpm[] = {
5971 "16 16 4 1",
5972 "       c None s None",
5973 ".      c black",
5974 "X      c #808080",
5975 "o      c white",
5976 "                ",
5977 "  ..            ",
5978 " .Xo.    ...    ",
5979 " .Xoo. ..oo.    ",
5980 " .Xooo.Xooo...  ",
5981 " .Xooo.oooo.X.  ",
5982 " .Xooo.Xooo.X.  ",
5983 " .Xooo.oooo.X.  ",
5984 " .Xooo.Xooo.X.  ",
5985 " .Xooo.oooo.X.  ",
5986 "  .Xoo.Xoo..X.  ",
5987 "   .Xo.o..ooX.  ",
5988 "    .X..XXXXX.  ",
5989 "    ..X.......  ",
5990 "     ..         ",
5991 "                "};
5992
5993 static const char * book_closed_xpm[] = {
5994 "16 16 6 1",
5995 "       c None s None",
5996 ".      c black",
5997 "X      c red",
5998 "o      c yellow",
5999 "O      c #808080",
6000 "#      c white",
6001 "                ",
6002 "       ..       ",
6003 "     ..XX.      ",
6004 "   ..XXXXX.     ",
6005 " ..XXXXXXXX.    ",
6006 ".ooXXXXXXXXX.   ",
6007 "..ooXXXXXXXXX.  ",
6008 ".X.ooXXXXXXXXX. ",
6009 ".XX.ooXXXXXX..  ",
6010 " .XX.ooXXX..#O  ",
6011 "  .XX.oo..##OO. ",
6012 "   .XX..##OO..  ",
6013 "    .X.#OO..    ",
6014 "     ..O..      ",
6015 "      ..        ",
6016 "                "};
6017
6018 GdkPixbuf *book_open;
6019 GdkPixbuf *book_closed;
6020 GtkWidget *sample_notebook;
6021
6022 static void
6023 set_page_image (GtkNotebook *notebook, gint page_num, GdkPixbuf *pixbuf)
6024 {
6025   GtkWidget *page_widget;
6026   GtkWidget *pixwid;
6027
6028   page_widget = gtk_notebook_get_nth_page (notebook, page_num);
6029
6030   pixwid = g_object_get_data (G_OBJECT (page_widget), "tab_pixmap");
6031   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
6032   
6033   pixwid = g_object_get_data (G_OBJECT (page_widget), "menu_pixmap");
6034   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
6035 }
6036
6037 static void
6038 page_switch (GtkWidget *widget, gpointer *page, gint page_num)
6039 {
6040   GtkNotebook *notebook = GTK_NOTEBOOK (widget);
6041   gint old_page_num = gtk_notebook_get_current_page (notebook);
6042  
6043   if (page_num == old_page_num)
6044     return;
6045
6046   set_page_image (notebook, page_num, book_open);
6047
6048   if (old_page_num != -1)
6049     set_page_image (notebook, old_page_num, book_closed);
6050 }
6051
6052 static void
6053 tab_fill (GtkToggleButton *button, GtkWidget *child)
6054 {
6055   gtk_container_child_set (GTK_CONTAINER (sample_notebook), child,
6056                            "tab-fill", gtk_toggle_button_get_active (button),
6057                            NULL);
6058 }
6059
6060 static void
6061 tab_expand (GtkToggleButton *button, GtkWidget *child)
6062 {
6063   gtk_container_child_set (GTK_CONTAINER (sample_notebook), child,
6064                            "tab-expand", gtk_toggle_button_get_active (button),
6065                            NULL);
6066 }
6067
6068 static void
6069 create_pages (GtkNotebook *notebook, gint start, gint end)
6070 {
6071   GtkWidget *child = NULL;
6072   GtkWidget *button;
6073   GtkWidget *label;
6074   GtkWidget *hbox;
6075   GtkWidget *vbox;
6076   GtkWidget *label_box;
6077   GtkWidget *menu_box;
6078   GtkWidget *pixwid;
6079   gint i;
6080   char buffer[32];
6081   char accel_buffer[32];
6082
6083   for (i = start; i <= end; i++)
6084     {
6085       sprintf (buffer, "Page %d", i);
6086       sprintf (accel_buffer, "Page _%d", i);
6087
6088       child = gtk_frame_new (buffer);
6089       gtk_container_set_border_width (GTK_CONTAINER (child), 10);
6090
6091       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
6092       gtk_box_set_homogeneous (GTK_BOX (vbox), TRUE);
6093       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
6094       gtk_container_add (GTK_CONTAINER (child), vbox);
6095
6096       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
6097       gtk_box_set_homogeneous (GTK_BOX (hbox), TRUE);
6098       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
6099
6100       button = gtk_check_button_new_with_label ("Fill Tab");
6101       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6102       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
6103       g_signal_connect (button, "toggled",
6104                         G_CALLBACK (tab_fill), child);
6105
6106       button = gtk_check_button_new_with_label ("Expand Tab");
6107       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6108       g_signal_connect (button, "toggled",
6109                         G_CALLBACK (tab_expand), child);
6110
6111       button = gtk_button_new_with_label ("Hide Page");
6112       gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 5);
6113       g_signal_connect_swapped (button, "clicked",
6114                                 G_CALLBACK (gtk_widget_hide),
6115                                 child);
6116
6117       gtk_widget_show_all (child);
6118
6119       label_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
6120       pixwid = gtk_image_new_from_pixbuf (book_closed);
6121       g_object_set_data (G_OBJECT (child), "tab_pixmap", pixwid);
6122                            
6123       gtk_box_pack_start (GTK_BOX (label_box), pixwid, FALSE, TRUE, 0);
6124       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
6125       label = gtk_label_new_with_mnemonic (accel_buffer);
6126       gtk_box_pack_start (GTK_BOX (label_box), label, FALSE, TRUE, 0);
6127       gtk_widget_show_all (label_box);
6128       
6129                                        
6130       menu_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
6131       pixwid = gtk_image_new_from_pixbuf (book_closed);
6132       g_object_set_data (G_OBJECT (child), "menu_pixmap", pixwid);
6133       
6134       gtk_box_pack_start (GTK_BOX (menu_box), pixwid, FALSE, TRUE, 0);
6135       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
6136       label = gtk_label_new (buffer);
6137       gtk_box_pack_start (GTK_BOX (menu_box), label, FALSE, TRUE, 0);
6138       gtk_widget_show_all (menu_box);
6139
6140       gtk_notebook_append_page_menu (notebook, child, label_box, menu_box);
6141     }
6142 }
6143
6144 static void
6145 rotate_notebook (GtkButton   *button,
6146                  GtkNotebook *notebook)
6147 {
6148   gtk_notebook_set_tab_pos (notebook, (gtk_notebook_get_tab_pos (notebook) + 1) % 4);
6149 }
6150
6151 static void
6152 show_all_pages (GtkButton   *button,
6153                 GtkNotebook *notebook)
6154 {  
6155   gtk_container_foreach (GTK_CONTAINER (notebook),
6156                          (GtkCallback) gtk_widget_show, NULL);
6157 }
6158
6159 static void
6160 notebook_type_changed (GtkWidget *optionmenu,
6161                        gpointer   data)
6162 {
6163   GtkNotebook *notebook;
6164   gint i, c;
6165
6166   enum {
6167     STANDARD,
6168     NOTABS,
6169     BORDERLESS,
6170     SCROLLABLE
6171   };
6172
6173   notebook = GTK_NOTEBOOK (data);
6174
6175   c = gtk_combo_box_get_active (GTK_COMBO_BOX (optionmenu));
6176
6177   switch (c)
6178     {
6179     case STANDARD:
6180       /* standard notebook */
6181       gtk_notebook_set_show_tabs (notebook, TRUE);
6182       gtk_notebook_set_show_border (notebook, TRUE);
6183       gtk_notebook_set_scrollable (notebook, FALSE);
6184       break;
6185
6186     case NOTABS:
6187       /* notabs notebook */
6188       gtk_notebook_set_show_tabs (notebook, FALSE);
6189       gtk_notebook_set_show_border (notebook, TRUE);
6190       break;
6191
6192     case BORDERLESS:
6193       /* borderless */
6194       gtk_notebook_set_show_tabs (notebook, FALSE);
6195       gtk_notebook_set_show_border (notebook, FALSE);
6196       break;
6197
6198     case SCROLLABLE:  
6199       /* scrollable */
6200       gtk_notebook_set_show_tabs (notebook, TRUE);
6201       gtk_notebook_set_show_border (notebook, TRUE);
6202       gtk_notebook_set_scrollable (notebook, TRUE);
6203       if (gtk_notebook_get_n_pages (notebook) == 5)
6204         create_pages (notebook, 6, 15);
6205
6206       return;
6207       break;
6208     }
6209
6210   if (gtk_notebook_get_n_pages (notebook) == 15)
6211     for (i = 0; i < 10; i++)
6212       gtk_notebook_remove_page (notebook, 5);
6213 }
6214
6215 static void
6216 notebook_popup (GtkToggleButton *button,
6217                 GtkNotebook     *notebook)
6218 {
6219   if (gtk_toggle_button_get_active (button))
6220     gtk_notebook_popup_enable (notebook);
6221   else
6222     gtk_notebook_popup_disable (notebook);
6223 }
6224
6225 static void
6226 create_notebook (GtkWidget *widget)
6227 {
6228   static GtkWidget *window = NULL;
6229   GtkWidget *box1;
6230   GtkWidget *box2;
6231   GtkWidget *button;
6232   GtkWidget *separator;
6233   GtkWidget *omenu;
6234   GtkWidget *label;
6235
6236   static gchar *items[] =
6237   {
6238     "Standard",
6239     "No tabs",
6240     "Borderless",
6241     "Scrollable"
6242   };
6243   
6244   if (!window)
6245     {
6246       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6247       gtk_window_set_screen (GTK_WINDOW (window),
6248                              gtk_widget_get_screen (widget));
6249
6250       g_signal_connect (window, "destroy",
6251                         G_CALLBACK (gtk_widget_destroyed),
6252                         &window);
6253
6254       gtk_window_set_title (GTK_WINDOW (window), "notebook");
6255       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6256
6257       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
6258       gtk_container_add (GTK_CONTAINER (window), box1);
6259
6260       sample_notebook = gtk_notebook_new ();
6261       g_signal_connect (sample_notebook, "switch_page",
6262                         G_CALLBACK (page_switch), NULL);
6263       gtk_notebook_set_tab_pos (GTK_NOTEBOOK (sample_notebook), GTK_POS_TOP);
6264       gtk_box_pack_start (GTK_BOX (box1), sample_notebook, TRUE, TRUE, 0);
6265       gtk_container_set_border_width (GTK_CONTAINER (sample_notebook), 10);
6266
6267       gtk_widget_realize (sample_notebook);
6268
6269       if (!book_open)
6270         book_open = gdk_pixbuf_new_from_xpm_data (book_open_xpm);
6271                                                   
6272       if (!book_closed)
6273         book_closed = gdk_pixbuf_new_from_xpm_data (book_closed_xpm);
6274
6275       create_pages (GTK_NOTEBOOK (sample_notebook), 1, 5);
6276
6277       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
6278       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 10);
6279       
6280       box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
6281       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6282       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
6283
6284       button = gtk_check_button_new_with_label ("popup menu");
6285       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
6286       g_signal_connect (button, "clicked",
6287                         G_CALLBACK (notebook_popup),
6288                         sample_notebook);
6289
6290       box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
6291       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6292       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
6293
6294       label = gtk_label_new ("Notebook Style :");
6295       gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0);
6296
6297       omenu = build_option_menu (items, G_N_ELEMENTS (items), 0,
6298                                  notebook_type_changed,
6299                                  sample_notebook);
6300       gtk_box_pack_start (GTK_BOX (box2), omenu, FALSE, TRUE, 0);
6301
6302       button = gtk_button_new_with_label ("Show all Pages");
6303       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, TRUE, 0);
6304       g_signal_connect (button, "clicked",
6305                         G_CALLBACK (show_all_pages), sample_notebook);
6306
6307       box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
6308       gtk_box_set_homogeneous (GTK_BOX (box2), TRUE);
6309       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6310       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
6311
6312       button = gtk_button_new_with_label ("prev");
6313       g_signal_connect_swapped (button, "clicked",
6314                                 G_CALLBACK (gtk_notebook_prev_page),
6315                                 sample_notebook);
6316       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
6317
6318       button = gtk_button_new_with_label ("next");
6319       g_signal_connect_swapped (button, "clicked",
6320                                 G_CALLBACK (gtk_notebook_next_page),
6321                                 sample_notebook);
6322       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
6323
6324       button = gtk_button_new_with_label ("rotate");
6325       g_signal_connect (button, "clicked",
6326                         G_CALLBACK (rotate_notebook), sample_notebook);
6327       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
6328
6329       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
6330       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
6331
6332       button = gtk_button_new_with_label ("close");
6333       gtk_container_set_border_width (GTK_CONTAINER (button), 5);
6334       g_signal_connect_swapped (button, "clicked",
6335                                 G_CALLBACK (gtk_widget_destroy),
6336                                 window);
6337       gtk_box_pack_start (GTK_BOX (box1), button, FALSE, FALSE, 0);
6338       gtk_widget_set_can_default (button, TRUE);
6339       gtk_widget_grab_default (button);
6340     }
6341
6342   if (!gtk_widget_get_visible (window))
6343     gtk_widget_show_all (window);
6344   else
6345     gtk_widget_destroy (window);
6346 }
6347
6348 /*
6349  * GtkPanes
6350  */
6351
6352 void
6353 toggle_resize (GtkWidget *widget, GtkWidget *child)
6354 {
6355   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
6356   GValue value = { 0, };
6357   g_value_init (&value, G_TYPE_BOOLEAN);
6358   gtk_container_child_get_property (container, child, "resize", &value);
6359   g_value_set_boolean (&value, !g_value_get_boolean (&value));
6360   gtk_container_child_set_property (container, child, "resize", &value);
6361 }
6362
6363 void
6364 toggle_shrink (GtkWidget *widget, GtkWidget *child)
6365 {
6366   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
6367   GValue value = { 0, };
6368   g_value_init (&value, G_TYPE_BOOLEAN);
6369   gtk_container_child_get_property (container, child, "shrink", &value);
6370   g_value_set_boolean (&value, !g_value_get_boolean (&value));
6371   gtk_container_child_set_property (container, child, "shrink", &value);
6372 }
6373
6374 static void
6375 paned_props_clicked (GtkWidget *button,
6376                      GObject   *paned)
6377 {
6378   GtkWidget *window = create_prop_editor (paned, GTK_TYPE_PANED);
6379   
6380   gtk_window_set_title (GTK_WINDOW (window), "Paned Properties");
6381 }
6382
6383 GtkWidget *
6384 create_pane_options (GtkPaned    *paned,
6385                      const gchar *frame_label,
6386                      const gchar *label1,
6387                      const gchar *label2)
6388 {
6389   GtkWidget *child1, *child2;
6390   GtkWidget *frame;
6391   GtkWidget *table;
6392   GtkWidget *label;
6393   GtkWidget *button;
6394   GtkWidget *check_button;
6395
6396   child1 = gtk_paned_get_child1 (paned);
6397   child2 = gtk_paned_get_child2 (paned);
6398
6399   frame = gtk_frame_new (frame_label);
6400   gtk_container_set_border_width (GTK_CONTAINER (frame), 4);
6401   
6402   table = gtk_table_new (4, 2, 4);
6403   gtk_container_add (GTK_CONTAINER (frame), table);
6404   
6405   label = gtk_label_new (label1);
6406   gtk_table_attach_defaults (GTK_TABLE (table), label,
6407                              0, 1, 0, 1);
6408   
6409   check_button = gtk_check_button_new_with_label ("Resize");
6410   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
6411                              0, 1, 1, 2);
6412   g_signal_connect (check_button, "toggled",
6413                     G_CALLBACK (toggle_resize),
6414                     child1);
6415
6416   check_button = gtk_check_button_new_with_label ("Shrink");
6417   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
6418                              0, 1, 2, 3);
6419   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
6420                                TRUE);
6421   g_signal_connect (check_button, "toggled",
6422                     G_CALLBACK (toggle_shrink),
6423                     child1);
6424
6425   label = gtk_label_new (label2);
6426   gtk_table_attach_defaults (GTK_TABLE (table), label,
6427                              1, 2, 0, 1);
6428   
6429   check_button = gtk_check_button_new_with_label ("Resize");
6430   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
6431                              1, 2, 1, 2);
6432   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
6433                                TRUE);
6434   g_signal_connect (check_button, "toggled",
6435                     G_CALLBACK (toggle_resize),
6436                     child2);
6437
6438   check_button = gtk_check_button_new_with_label ("Shrink");
6439   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
6440                              1, 2, 2, 3);
6441   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
6442                                TRUE);
6443   g_signal_connect (check_button, "toggled",
6444                     G_CALLBACK (toggle_shrink),
6445                     child2);
6446
6447   button = gtk_button_new_with_mnemonic ("_Properties");
6448   gtk_table_attach_defaults (GTK_TABLE (table), button,
6449                              0, 2, 3, 4);
6450   g_signal_connect (button, "clicked",
6451                     G_CALLBACK (paned_props_clicked),
6452                     paned);
6453
6454   return frame;
6455 }
6456
6457 void
6458 create_panes (GtkWidget *widget)
6459 {
6460   static GtkWidget *window = NULL;
6461   GtkWidget *frame;
6462   GtkWidget *hpaned;
6463   GtkWidget *vpaned;
6464   GtkWidget *button;
6465   GtkWidget *vbox;
6466
6467   if (!window)
6468     {
6469       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6470
6471       gtk_window_set_screen (GTK_WINDOW (window),
6472                              gtk_widget_get_screen (widget));
6473       
6474       g_signal_connect (window, "destroy",
6475                         G_CALLBACK (gtk_widget_destroyed),
6476                         &window);
6477
6478       gtk_window_set_title (GTK_WINDOW (window), "Panes");
6479       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6480
6481       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
6482       gtk_container_add (GTK_CONTAINER (window), vbox);
6483       
6484       vpaned = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6485       gtk_box_pack_start (GTK_BOX (vbox), vpaned, TRUE, TRUE, 0);
6486       gtk_container_set_border_width (GTK_CONTAINER(vpaned), 5);
6487
6488       hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6489       gtk_paned_add1 (GTK_PANED (vpaned), hpaned);
6490
6491       frame = gtk_frame_new (NULL);
6492       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
6493       gtk_widget_set_size_request (frame, 60, 60);
6494       gtk_paned_add1 (GTK_PANED (hpaned), frame);
6495       
6496       button = gtk_button_new_with_label ("Hi there");
6497       gtk_container_add (GTK_CONTAINER(frame), button);
6498
6499       frame = gtk_frame_new (NULL);
6500       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
6501       gtk_widget_set_size_request (frame, 80, 60);
6502       gtk_paned_add2 (GTK_PANED (hpaned), frame);
6503
6504       frame = gtk_frame_new (NULL);
6505       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
6506       gtk_widget_set_size_request (frame, 60, 80);
6507       gtk_paned_add2 (GTK_PANED (vpaned), frame);
6508
6509       /* Now create toggle buttons to control sizing */
6510
6511       gtk_box_pack_start (GTK_BOX (vbox),
6512                           create_pane_options (GTK_PANED (hpaned),
6513                                                "Horizontal",
6514                                                "Left",
6515                                                "Right"),
6516                           FALSE, FALSE, 0);
6517
6518       gtk_box_pack_start (GTK_BOX (vbox),
6519                           create_pane_options (GTK_PANED (vpaned),
6520                                                "Vertical",
6521                                                "Top",
6522                                                "Bottom"),
6523                           FALSE, FALSE, 0);
6524
6525       gtk_widget_show_all (vbox);
6526     }
6527
6528   if (!gtk_widget_get_visible (window))
6529     gtk_widget_show (window);
6530   else
6531     gtk_widget_destroy (window);
6532 }
6533
6534 /*
6535  * Paned keyboard navigation
6536  */
6537
6538 static GtkWidget*
6539 paned_keyboard_window1 (GtkWidget *widget)
6540 {
6541   GtkWidget *window1;
6542   GtkWidget *hpaned1;
6543   GtkWidget *frame1;
6544   GtkWidget *vbox1;
6545   GtkWidget *button7;
6546   GtkWidget *button8;
6547   GtkWidget *button9;
6548   GtkWidget *vpaned1;
6549   GtkWidget *frame2;
6550   GtkWidget *frame5;
6551   GtkWidget *hbox1;
6552   GtkWidget *button5;
6553   GtkWidget *button6;
6554   GtkWidget *frame3;
6555   GtkWidget *frame4;
6556   GtkWidget *table1;
6557   GtkWidget *button1;
6558   GtkWidget *button2;
6559   GtkWidget *button3;
6560   GtkWidget *button4;
6561
6562   window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6563   gtk_window_set_title (GTK_WINDOW (window1), "Basic paned navigation");
6564   gtk_window_set_screen (GTK_WINDOW (window1), 
6565                          gtk_widget_get_screen (widget));
6566
6567   hpaned1 = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6568   gtk_container_add (GTK_CONTAINER (window1), hpaned1);
6569
6570   frame1 = gtk_frame_new (NULL);
6571   gtk_paned_pack1 (GTK_PANED (hpaned1), frame1, FALSE, TRUE);
6572   gtk_frame_set_shadow_type (GTK_FRAME (frame1), GTK_SHADOW_IN);
6573
6574   vbox1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
6575   gtk_container_add (GTK_CONTAINER (frame1), vbox1);
6576
6577   button7 = gtk_button_new_with_label ("button7");
6578   gtk_box_pack_start (GTK_BOX (vbox1), button7, FALSE, FALSE, 0);
6579
6580   button8 = gtk_button_new_with_label ("button8");
6581   gtk_box_pack_start (GTK_BOX (vbox1), button8, FALSE, FALSE, 0);
6582
6583   button9 = gtk_button_new_with_label ("button9");
6584   gtk_box_pack_start (GTK_BOX (vbox1), button9, FALSE, FALSE, 0);
6585
6586   vpaned1 = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6587   gtk_paned_pack2 (GTK_PANED (hpaned1), vpaned1, TRUE, TRUE);
6588
6589   frame2 = gtk_frame_new (NULL);
6590   gtk_paned_pack1 (GTK_PANED (vpaned1), frame2, FALSE, TRUE);
6591   gtk_frame_set_shadow_type (GTK_FRAME (frame2), GTK_SHADOW_IN);
6592
6593   frame5 = gtk_frame_new (NULL);
6594   gtk_container_add (GTK_CONTAINER (frame2), frame5);
6595
6596   hbox1 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
6597   gtk_container_add (GTK_CONTAINER (frame5), hbox1);
6598
6599   button5 = gtk_button_new_with_label ("button5");
6600   gtk_box_pack_start (GTK_BOX (hbox1), button5, FALSE, FALSE, 0);
6601
6602   button6 = gtk_button_new_with_label ("button6");
6603   gtk_box_pack_start (GTK_BOX (hbox1), button6, FALSE, FALSE, 0);
6604
6605   frame3 = gtk_frame_new (NULL);
6606   gtk_paned_pack2 (GTK_PANED (vpaned1), frame3, TRUE, TRUE);
6607   gtk_frame_set_shadow_type (GTK_FRAME (frame3), GTK_SHADOW_IN);
6608
6609   frame4 = gtk_frame_new ("Buttons");
6610   gtk_container_add (GTK_CONTAINER (frame3), frame4);
6611   gtk_container_set_border_width (GTK_CONTAINER (frame4), 15);
6612
6613   table1 = gtk_table_new (2, 2, FALSE);
6614   gtk_container_add (GTK_CONTAINER (frame4), table1);
6615   gtk_container_set_border_width (GTK_CONTAINER (table1), 11);
6616
6617   button1 = gtk_button_new_with_label ("button1");
6618   gtk_table_attach (GTK_TABLE (table1), button1, 0, 1, 0, 1,
6619                     (GtkAttachOptions) (GTK_FILL),
6620                     (GtkAttachOptions) (0), 0, 0);
6621
6622   button2 = gtk_button_new_with_label ("button2");
6623   gtk_table_attach (GTK_TABLE (table1), button2, 1, 2, 0, 1,
6624                     (GtkAttachOptions) (GTK_FILL),
6625                     (GtkAttachOptions) (0), 0, 0);
6626
6627   button3 = gtk_button_new_with_label ("button3");
6628   gtk_table_attach (GTK_TABLE (table1), button3, 0, 1, 1, 2,
6629                     (GtkAttachOptions) (GTK_FILL),
6630                     (GtkAttachOptions) (0), 0, 0);
6631
6632   button4 = gtk_button_new_with_label ("button4");
6633   gtk_table_attach (GTK_TABLE (table1), button4, 1, 2, 1, 2,
6634                     (GtkAttachOptions) (GTK_FILL),
6635                     (GtkAttachOptions) (0), 0, 0);
6636
6637   return window1;
6638 }
6639
6640 static GtkWidget*
6641 paned_keyboard_window2 (GtkWidget *widget)
6642 {
6643   GtkWidget *window2;
6644   GtkWidget *hpaned2;
6645   GtkWidget *frame6;
6646   GtkWidget *button13;
6647   GtkWidget *hbox2;
6648   GtkWidget *vpaned2;
6649   GtkWidget *frame7;
6650   GtkWidget *button12;
6651   GtkWidget *frame8;
6652   GtkWidget *button11;
6653   GtkWidget *button10;
6654
6655   window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6656   gtk_window_set_title (GTK_WINDOW (window2), "\"button 10\" is not inside the horisontal pane");
6657
6658   gtk_window_set_screen (GTK_WINDOW (window2), 
6659                          gtk_widget_get_screen (widget));
6660
6661   hpaned2 = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6662   gtk_container_add (GTK_CONTAINER (window2), hpaned2);
6663
6664   frame6 = gtk_frame_new (NULL);
6665   gtk_paned_pack1 (GTK_PANED (hpaned2), frame6, FALSE, TRUE);
6666   gtk_frame_set_shadow_type (GTK_FRAME (frame6), GTK_SHADOW_IN);
6667
6668   button13 = gtk_button_new_with_label ("button13");
6669   gtk_container_add (GTK_CONTAINER (frame6), button13);
6670
6671   hbox2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
6672   gtk_paned_pack2 (GTK_PANED (hpaned2), hbox2, TRUE, TRUE);
6673
6674   vpaned2 = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6675   gtk_box_pack_start (GTK_BOX (hbox2), vpaned2, TRUE, TRUE, 0);
6676
6677   frame7 = gtk_frame_new (NULL);
6678   gtk_paned_pack1 (GTK_PANED (vpaned2), frame7, FALSE, TRUE);
6679   gtk_frame_set_shadow_type (GTK_FRAME (frame7), GTK_SHADOW_IN);
6680
6681   button12 = gtk_button_new_with_label ("button12");
6682   gtk_container_add (GTK_CONTAINER (frame7), button12);
6683
6684   frame8 = gtk_frame_new (NULL);
6685   gtk_paned_pack2 (GTK_PANED (vpaned2), frame8, TRUE, TRUE);
6686   gtk_frame_set_shadow_type (GTK_FRAME (frame8), GTK_SHADOW_IN);
6687
6688   button11 = gtk_button_new_with_label ("button11");
6689   gtk_container_add (GTK_CONTAINER (frame8), button11);
6690
6691   button10 = gtk_button_new_with_label ("button10");
6692   gtk_box_pack_start (GTK_BOX (hbox2), button10, FALSE, FALSE, 0);
6693
6694   return window2;
6695 }
6696
6697 static GtkWidget*
6698 paned_keyboard_window3 (GtkWidget *widget)
6699 {
6700   GtkWidget *window3;
6701   GtkWidget *vbox2;
6702   GtkWidget *label1;
6703   GtkWidget *hpaned3;
6704   GtkWidget *frame9;
6705   GtkWidget *button14;
6706   GtkWidget *hpaned4;
6707   GtkWidget *frame10;
6708   GtkWidget *button15;
6709   GtkWidget *hpaned5;
6710   GtkWidget *frame11;
6711   GtkWidget *button16;
6712   GtkWidget *frame12;
6713   GtkWidget *button17;
6714
6715   window3 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6716   g_object_set_data (G_OBJECT (window3), "window3", window3);
6717   gtk_window_set_title (GTK_WINDOW (window3), "Nested panes");
6718
6719   gtk_window_set_screen (GTK_WINDOW (window3), 
6720                          gtk_widget_get_screen (widget));
6721   
6722
6723   vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
6724   gtk_container_add (GTK_CONTAINER (window3), vbox2);
6725
6726   label1 = gtk_label_new ("Three panes nested inside each other");
6727   gtk_box_pack_start (GTK_BOX (vbox2), label1, FALSE, FALSE, 0);
6728
6729   hpaned3 = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6730   gtk_box_pack_start (GTK_BOX (vbox2), hpaned3, TRUE, TRUE, 0);
6731
6732   frame9 = gtk_frame_new (NULL);
6733   gtk_paned_pack1 (GTK_PANED (hpaned3), frame9, FALSE, TRUE);
6734   gtk_frame_set_shadow_type (GTK_FRAME (frame9), GTK_SHADOW_IN);
6735
6736   button14 = gtk_button_new_with_label ("button14");
6737   gtk_container_add (GTK_CONTAINER (frame9), button14);
6738
6739   hpaned4 = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6740   gtk_paned_pack2 (GTK_PANED (hpaned3), hpaned4, TRUE, TRUE);
6741
6742   frame10 = gtk_frame_new (NULL);
6743   gtk_paned_pack1 (GTK_PANED (hpaned4), frame10, FALSE, TRUE);
6744   gtk_frame_set_shadow_type (GTK_FRAME (frame10), GTK_SHADOW_IN);
6745
6746   button15 = gtk_button_new_with_label ("button15");
6747   gtk_container_add (GTK_CONTAINER (frame10), button15);
6748
6749   hpaned5 = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6750   gtk_paned_pack2 (GTK_PANED (hpaned4), hpaned5, TRUE, TRUE);
6751
6752   frame11 = gtk_frame_new (NULL);
6753   gtk_paned_pack1 (GTK_PANED (hpaned5), frame11, FALSE, TRUE);
6754   gtk_frame_set_shadow_type (GTK_FRAME (frame11), GTK_SHADOW_IN);
6755
6756   button16 = gtk_button_new_with_label ("button16");
6757   gtk_container_add (GTK_CONTAINER (frame11), button16);
6758
6759   frame12 = gtk_frame_new (NULL);
6760   gtk_paned_pack2 (GTK_PANED (hpaned5), frame12, TRUE, TRUE);
6761   gtk_frame_set_shadow_type (GTK_FRAME (frame12), GTK_SHADOW_IN);
6762
6763   button17 = gtk_button_new_with_label ("button17");
6764   gtk_container_add (GTK_CONTAINER (frame12), button17);
6765
6766   return window3;
6767 }
6768
6769 static GtkWidget*
6770 paned_keyboard_window4 (GtkWidget *widget)
6771 {
6772   GtkWidget *window4;
6773   GtkWidget *vbox3;
6774   GtkWidget *label2;
6775   GtkWidget *hpaned6;
6776   GtkWidget *vpaned3;
6777   GtkWidget *button19;
6778   GtkWidget *button18;
6779   GtkWidget *hbox3;
6780   GtkWidget *vpaned4;
6781   GtkWidget *button21;
6782   GtkWidget *button20;
6783   GtkWidget *vpaned5;
6784   GtkWidget *button23;
6785   GtkWidget *button22;
6786   GtkWidget *vpaned6;
6787   GtkWidget *button25;
6788   GtkWidget *button24;
6789
6790   window4 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6791   g_object_set_data (G_OBJECT (window4), "window4", window4);
6792   gtk_window_set_title (GTK_WINDOW (window4), "window4");
6793
6794   gtk_window_set_screen (GTK_WINDOW (window4), 
6795                          gtk_widget_get_screen (widget));
6796
6797   vbox3 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
6798   gtk_container_add (GTK_CONTAINER (window4), vbox3);
6799
6800   label2 = gtk_label_new ("Widget tree:\n\nhpaned \n - vpaned\n - hbox\n    - vpaned\n    - vpaned\n    - vpaned\n");
6801   gtk_box_pack_start (GTK_BOX (vbox3), label2, FALSE, FALSE, 0);
6802   gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_LEFT);
6803
6804   hpaned6 = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6805   gtk_box_pack_start (GTK_BOX (vbox3), hpaned6, TRUE, TRUE, 0);
6806
6807   vpaned3 = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6808   gtk_paned_pack1 (GTK_PANED (hpaned6), vpaned3, FALSE, TRUE);
6809
6810   button19 = gtk_button_new_with_label ("button19");
6811   gtk_paned_pack1 (GTK_PANED (vpaned3), button19, FALSE, TRUE);
6812
6813   button18 = gtk_button_new_with_label ("button18");
6814   gtk_paned_pack2 (GTK_PANED (vpaned3), button18, TRUE, TRUE);
6815
6816   hbox3 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
6817   gtk_paned_pack2 (GTK_PANED (hpaned6), hbox3, TRUE, TRUE);
6818
6819   vpaned4 = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6820   gtk_box_pack_start (GTK_BOX (hbox3), vpaned4, TRUE, TRUE, 0);
6821
6822   button21 = gtk_button_new_with_label ("button21");
6823   gtk_paned_pack1 (GTK_PANED (vpaned4), button21, FALSE, TRUE);
6824
6825   button20 = gtk_button_new_with_label ("button20");
6826   gtk_paned_pack2 (GTK_PANED (vpaned4), button20, TRUE, TRUE);
6827
6828   vpaned5 = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6829   gtk_box_pack_start (GTK_BOX (hbox3), vpaned5, TRUE, TRUE, 0);
6830
6831   button23 = gtk_button_new_with_label ("button23");
6832   gtk_paned_pack1 (GTK_PANED (vpaned5), button23, FALSE, TRUE);
6833
6834   button22 = gtk_button_new_with_label ("button22");
6835   gtk_paned_pack2 (GTK_PANED (vpaned5), button22, TRUE, TRUE);
6836
6837   vpaned6 = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6838   gtk_box_pack_start (GTK_BOX (hbox3), vpaned6, TRUE, TRUE, 0);
6839
6840   button25 = gtk_button_new_with_label ("button25");
6841   gtk_paned_pack1 (GTK_PANED (vpaned6), button25, FALSE, TRUE);
6842
6843   button24 = gtk_button_new_with_label ("button24");
6844   gtk_paned_pack2 (GTK_PANED (vpaned6), button24, TRUE, TRUE);
6845
6846   return window4;
6847 }
6848
6849 static void
6850 create_paned_keyboard_navigation (GtkWidget *widget)
6851 {
6852   static GtkWidget *window1 = NULL;
6853   static GtkWidget *window2 = NULL;
6854   static GtkWidget *window3 = NULL;
6855   static GtkWidget *window4 = NULL;
6856
6857   if (window1 && 
6858      (gtk_widget_get_screen (window1) != gtk_widget_get_screen (widget)))
6859     {
6860       gtk_widget_destroy (window1);
6861       gtk_widget_destroy (window2);
6862       gtk_widget_destroy (window3);
6863       gtk_widget_destroy (window4);
6864     }
6865   
6866   if (!window1)
6867     {
6868       window1 = paned_keyboard_window1 (widget);
6869       g_signal_connect (window1, "destroy",
6870                         G_CALLBACK (gtk_widget_destroyed),
6871                         &window1);
6872     }
6873
6874   if (!window2)
6875     {
6876       window2 = paned_keyboard_window2 (widget);
6877       g_signal_connect (window2, "destroy",
6878                         G_CALLBACK (gtk_widget_destroyed),
6879                         &window2);
6880     }
6881
6882   if (!window3)
6883     {
6884       window3 = paned_keyboard_window3 (widget);
6885       g_signal_connect (window3, "destroy",
6886                         G_CALLBACK (gtk_widget_destroyed),
6887                         &window3);
6888     }
6889
6890   if (!window4)
6891     {
6892       window4 = paned_keyboard_window4 (widget);
6893       g_signal_connect (window4, "destroy",
6894                         G_CALLBACK (gtk_widget_destroyed),
6895                         &window4);
6896     }
6897
6898   if (gtk_widget_get_visible (window1))
6899     gtk_widget_destroy (GTK_WIDGET (window1));
6900   else
6901     gtk_widget_show_all (GTK_WIDGET (window1));
6902
6903   if (gtk_widget_get_visible (window2))
6904     gtk_widget_destroy (GTK_WIDGET (window2));
6905   else
6906     gtk_widget_show_all (GTK_WIDGET (window2));
6907
6908   if (gtk_widget_get_visible (window3))
6909     gtk_widget_destroy (GTK_WIDGET (window3));
6910   else
6911     gtk_widget_show_all (GTK_WIDGET (window3));
6912
6913   if (gtk_widget_get_visible (window4))
6914     gtk_widget_destroy (GTK_WIDGET (window4));
6915   else
6916     gtk_widget_show_all (GTK_WIDGET (window4));
6917 }
6918
6919
6920 /*
6921  * Shaped Windows
6922  */
6923
6924 typedef struct _cursoroffset {gint x,y;} CursorOffset;
6925
6926 static void
6927 shape_pressed (GtkWidget *widget, GdkEventButton *event)
6928 {
6929   CursorOffset *p;
6930
6931   /* ignore double and triple click */
6932   if (event->type != GDK_BUTTON_PRESS)
6933     return;
6934
6935   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
6936   p->x = (int) event->x;
6937   p->y = (int) event->y;
6938
6939   gtk_grab_add (widget);
6940   gdk_device_grab (gdk_event_get_device ((GdkEvent*)event),
6941                    gtk_widget_get_window (widget),
6942                    GDK_OWNERSHIP_NONE,
6943                    TRUE,
6944                    GDK_BUTTON_RELEASE_MASK |
6945                    GDK_BUTTON_MOTION_MASK |
6946                    GDK_POINTER_MOTION_HINT_MASK,
6947                    NULL,
6948                    event->time);
6949 }
6950
6951 static void
6952 shape_released (GtkWidget      *widget,
6953                 GdkEventButton *event)
6954 {
6955   gtk_grab_remove (widget);
6956   gdk_device_ungrab (gdk_event_get_device ((GdkEvent*)event), event->time);
6957 }
6958
6959 static void
6960 shape_motion (GtkWidget      *widget,
6961               GdkEventMotion *event)
6962 {
6963   gint xp, yp;
6964   CursorOffset * p;
6965   GdkModifierType mask;
6966
6967   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
6968
6969   /*
6970    * Can't use event->x / event->y here 
6971    * because I need absolute coordinates.
6972    */
6973   gdk_window_get_pointer (NULL, &xp, &yp, &mask);
6974   gtk_window_move (GTK_WINDOW (widget), xp  - p->x, yp  - p->y);
6975 }
6976
6977 GtkWidget *
6978 shape_create_icon (GdkScreen *screen,
6979                    char      *xpm_file,
6980                    gint       x,
6981                    gint       y,
6982                    gint       px,
6983                    gint       py,
6984                    gint       window_type)
6985 {
6986   GtkWidget *window;
6987   GtkWidget *image;
6988   GtkWidget *fixed;
6989   CursorOffset* icon_pos;
6990   cairo_surface_t *mask;
6991   cairo_region_t *mask_region;
6992   GdkPixbuf *pixbuf;
6993   cairo_t *cr;
6994
6995   /*
6996    * GDK_WINDOW_TOPLEVEL works also, giving you a title border
6997    */
6998   window = gtk_window_new (window_type);
6999   gtk_window_set_screen (GTK_WINDOW (window), screen);
7000   
7001   fixed = gtk_fixed_new ();
7002   gtk_widget_set_size_request (fixed, 100, 100);
7003   gtk_container_add (GTK_CONTAINER (window), fixed);
7004   gtk_widget_show (fixed);
7005   
7006   gtk_widget_set_events (window, 
7007                          gtk_widget_get_events (window) |
7008                          GDK_BUTTON_MOTION_MASK |
7009                          GDK_POINTER_MOTION_HINT_MASK |
7010                          GDK_BUTTON_PRESS_MASK);
7011
7012   gtk_widget_realize (window);
7013
7014   pixbuf = gdk_pixbuf_new_from_file (xpm_file, NULL);
7015   g_assert (pixbuf); /* FIXME: error handling */
7016
7017   mask = cairo_image_surface_create (CAIRO_FORMAT_A1,
7018                                      gdk_pixbuf_get_width (pixbuf),
7019                                      gdk_pixbuf_get_height (pixbuf));
7020   cr = cairo_create (mask);
7021   gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
7022   cairo_paint (cr);
7023   cairo_destroy (cr);
7024
7025   mask_region = gdk_cairo_region_create_from_surface (mask);
7026                                                   
7027   cairo_region_translate (mask_region, px, py);
7028
7029   image = gtk_image_new_from_pixbuf (pixbuf);
7030   gtk_fixed_put (GTK_FIXED (fixed), image, px,py);
7031   gtk_widget_show (image);
7032   
7033   gtk_widget_shape_combine_region (window, mask_region);
7034   
7035   cairo_region_destroy (mask_region);
7036   cairo_surface_destroy (mask);
7037   g_object_unref (pixbuf);
7038
7039   g_signal_connect (window, "button_press_event",
7040                     G_CALLBACK (shape_pressed), NULL);
7041   g_signal_connect (window, "button_release_event",
7042                     G_CALLBACK (shape_released), NULL);
7043   g_signal_connect (window, "motion_notify_event",
7044                     G_CALLBACK (shape_motion), NULL);
7045
7046   icon_pos = g_new (CursorOffset, 1);
7047   g_object_set_data (G_OBJECT (window), "cursor_offset", icon_pos);
7048
7049   gtk_window_move (GTK_WINDOW (window), x, y);
7050   gtk_widget_show (window);
7051   
7052   return window;
7053 }
7054
7055 void 
7056 create_shapes (GtkWidget *widget)
7057 {
7058   /* Variables used by the Drag/Drop and Shape Window demos */
7059   static GtkWidget *modeller = NULL;
7060   static GtkWidget *sheets = NULL;
7061   static GtkWidget *rings = NULL;
7062   static GtkWidget *with_region = NULL;
7063   GdkScreen *screen = gtk_widget_get_screen (widget);
7064   
7065   if (!(file_exists ("Modeller.xpm") &&
7066         file_exists ("FilesQueue.xpm") &&
7067         file_exists ("3DRings.xpm")))
7068     return;
7069   
7070
7071   if (!modeller)
7072     {
7073       modeller = shape_create_icon (screen, "Modeller.xpm",
7074                                     440, 140, 0,0, GTK_WINDOW_POPUP);
7075
7076       g_signal_connect (modeller, "destroy",
7077                         G_CALLBACK (gtk_widget_destroyed),
7078                         &modeller);
7079     }
7080   else
7081     gtk_widget_destroy (modeller);
7082
7083   if (!sheets)
7084     {
7085       sheets = shape_create_icon (screen, "FilesQueue.xpm",
7086                                   580, 170, 0,0, GTK_WINDOW_POPUP);
7087
7088       g_signal_connect (sheets, "destroy",
7089                         G_CALLBACK (gtk_widget_destroyed),
7090                         &sheets);
7091
7092     }
7093   else
7094     gtk_widget_destroy (sheets);
7095
7096   if (!rings)
7097     {
7098       rings = shape_create_icon (screen, "3DRings.xpm",
7099                                  460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
7100
7101       g_signal_connect (rings, "destroy",
7102                         G_CALLBACK (gtk_widget_destroyed),
7103                         &rings);
7104     }
7105   else
7106     gtk_widget_destroy (rings);
7107
7108   if (!with_region)
7109     {
7110       cairo_region_t *region;
7111       gint x, y;
7112       
7113       with_region = shape_create_icon (screen, "3DRings.xpm",
7114                                        460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
7115
7116       gtk_window_set_decorated (GTK_WINDOW (with_region), FALSE);
7117       
7118       g_signal_connect (with_region, "destroy",
7119                         G_CALLBACK (gtk_widget_destroyed),
7120                         &with_region);
7121
7122       /* reset shape from mask to a region */
7123       x = 0;
7124       y = 0;
7125       region = cairo_region_create ();
7126
7127       while (x < 460)
7128         {
7129           while (y < 270)
7130             {
7131               GdkRectangle rect;
7132               rect.x = x;
7133               rect.y = y;
7134               rect.width = 10;
7135               rect.height = 10;
7136
7137               cairo_region_union_rectangle (region, &rect);
7138               
7139               y += 20;
7140             }
7141           y = 0;
7142           x += 20;
7143         }
7144
7145       gdk_window_shape_combine_region (gtk_widget_get_window (with_region),
7146                                        region,
7147                                        0, 0);
7148     }
7149   else
7150     gtk_widget_destroy (with_region);
7151 }
7152
7153 /*
7154  * WM Hints demo
7155  */
7156
7157 void
7158 create_wmhints (GtkWidget *widget)
7159 {
7160   static GtkWidget *window = NULL;
7161   GtkWidget *label;
7162   GtkWidget *separator;
7163   GtkWidget *button;
7164   GtkWidget *box1;
7165   GtkWidget *box2;
7166   GdkWindow *gdk_window;
7167   GdkPixbuf *pixbuf;
7168   GList *list;
7169
7170   if (!window)
7171     {
7172       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7173
7174       gtk_window_set_screen (GTK_WINDOW (window),
7175                              gtk_widget_get_screen (widget));
7176       
7177       g_signal_connect (window, "destroy",
7178                         G_CALLBACK (gtk_widget_destroyed),
7179                         &window);
7180
7181       gtk_window_set_title (GTK_WINDOW (window), "WM Hints");
7182       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7183
7184       gtk_widget_realize (window);
7185
7186       gdk_window = gtk_widget_get_window (window);
7187
7188       pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **) openfile);
7189       list = g_list_prepend (NULL, pixbuf);
7190
7191       gdk_window_set_icon_list (gdk_window, list);
7192       
7193       g_list_free (list);
7194       g_object_unref (pixbuf);
7195
7196       gdk_window_set_icon_name (gdk_window, "WMHints Test Icon");
7197   
7198       gdk_window_set_decorations (gdk_window, GDK_DECOR_ALL | GDK_DECOR_MENU);
7199       gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_RESIZE);
7200       
7201       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
7202       gtk_container_add (GTK_CONTAINER (window), box1);
7203       gtk_widget_show (box1);
7204
7205       label = gtk_label_new ("Try iconizing me!");
7206       gtk_widget_set_size_request (label, 150, 50);
7207       gtk_box_pack_start (GTK_BOX (box1), label, TRUE, TRUE, 0);
7208       gtk_widget_show (label);
7209
7210
7211       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
7212       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
7213       gtk_widget_show (separator);
7214
7215
7216       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
7217       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
7218       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
7219       gtk_widget_show (box2);
7220
7221
7222       button = gtk_button_new_with_label ("close");
7223
7224       g_signal_connect_swapped (button, "clicked",
7225                                 G_CALLBACK (gtk_widget_destroy),
7226                                 window);
7227
7228       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
7229       gtk_widget_set_can_default (button, TRUE);
7230       gtk_widget_grab_default (button);
7231       gtk_widget_show (button);
7232     }
7233
7234   if (!gtk_widget_get_visible (window))
7235     gtk_widget_show (window);
7236   else
7237     gtk_widget_destroy (window);
7238 }
7239
7240
7241 /*
7242  * Window state tracking
7243  */
7244
7245 static gint
7246 window_state_callback (GtkWidget *widget,
7247                        GdkEventWindowState *event,
7248                        gpointer data)
7249 {
7250   GtkWidget *label = data;
7251   gchar *msg;
7252
7253   msg = g_strconcat (gtk_window_get_title (GTK_WINDOW (widget)), ": ",
7254                      (event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) ?
7255                      "withdrawn" : "not withdrawn", ", ",
7256                      (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) ?
7257                      "iconified" : "not iconified", ", ",
7258                      (event->new_window_state & GDK_WINDOW_STATE_STICKY) ?
7259                      "sticky" : "not sticky", ", ",
7260                      (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) ?
7261                      "maximized" : "not maximized", ", ",
7262                      (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) ?
7263                      "fullscreen" : "not fullscreen",
7264                      (event->new_window_state & GDK_WINDOW_STATE_ABOVE) ?
7265                      "above" : "not above", ", ",
7266                      (event->new_window_state & GDK_WINDOW_STATE_BELOW) ?
7267                      "below" : "not below", ", ",
7268                      NULL);
7269   
7270   gtk_label_set_text (GTK_LABEL (label), msg);
7271
7272   g_free (msg);
7273
7274   return FALSE;
7275 }
7276
7277 static GtkWidget*
7278 tracking_label (GtkWidget *window)
7279 {
7280   GtkWidget *label;
7281   GtkWidget *hbox;
7282   GtkWidget *button;
7283
7284   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
7285
7286   g_signal_connect_object (hbox,
7287                            "destroy",
7288                            G_CALLBACK (gtk_widget_destroy),
7289                            window,
7290                            G_CONNECT_SWAPPED);
7291   
7292   label = gtk_label_new ("<no window state events received>");
7293   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
7294   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
7295   
7296   g_signal_connect (window,
7297                     "window_state_event",
7298                     G_CALLBACK (window_state_callback),
7299                     label);
7300
7301   button = gtk_button_new_with_label ("Deiconify");
7302   g_signal_connect_object (button,
7303                            "clicked",
7304                            G_CALLBACK (gtk_window_deiconify),
7305                            window,
7306                            G_CONNECT_SWAPPED);
7307   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7308
7309   button = gtk_button_new_with_label ("Iconify");
7310   g_signal_connect_object (button,
7311                            "clicked",
7312                            G_CALLBACK (gtk_window_iconify),
7313                            window,
7314                            G_CONNECT_SWAPPED);
7315   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7316
7317   button = gtk_button_new_with_label ("Fullscreen");
7318   g_signal_connect_object (button,
7319                            "clicked",
7320                            G_CALLBACK (gtk_window_fullscreen),
7321                            window,
7322                            G_CONNECT_SWAPPED);
7323   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7324
7325   button = gtk_button_new_with_label ("Unfullscreen");
7326   g_signal_connect_object (button,
7327                            "clicked",
7328                            G_CALLBACK (gtk_window_unfullscreen),
7329                            window,
7330                            G_CONNECT_SWAPPED);
7331   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7332   
7333   button = gtk_button_new_with_label ("Present");
7334   g_signal_connect_object (button,
7335                            "clicked",
7336                            G_CALLBACK (gtk_window_present),
7337                            window,
7338                            G_CONNECT_SWAPPED);
7339   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7340
7341   button = gtk_button_new_with_label ("Show");
7342   g_signal_connect_object (button,
7343                            "clicked",
7344                            G_CALLBACK (gtk_widget_show),
7345                            window,
7346                            G_CONNECT_SWAPPED);
7347   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7348   
7349   gtk_widget_show_all (hbox);
7350   
7351   return hbox;
7352 }
7353
7354 void
7355 keep_window_above (GtkToggleButton *togglebutton, gpointer data)
7356 {
7357   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
7358
7359   gtk_window_set_keep_above (GTK_WINDOW (data),
7360                              gtk_toggle_button_get_active (togglebutton));
7361
7362   if (gtk_toggle_button_get_active (togglebutton))
7363     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
7364 }
7365
7366 void
7367 keep_window_below (GtkToggleButton *togglebutton, gpointer data)
7368 {
7369   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
7370
7371   gtk_window_set_keep_below (GTK_WINDOW (data),
7372                              gtk_toggle_button_get_active (togglebutton));
7373
7374   if (gtk_toggle_button_get_active (togglebutton))
7375     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
7376 }
7377
7378
7379 static GtkWidget*
7380 get_state_controls (GtkWidget *window)
7381 {
7382   GtkWidget *vbox;
7383   GtkWidget *button;
7384   GtkWidget *button_above;
7385   GtkWidget *button_below;
7386
7387   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
7388   
7389   button = gtk_button_new_with_label ("Stick");
7390   g_signal_connect_object (button,
7391                            "clicked",
7392                            G_CALLBACK (gtk_window_stick),
7393                            window,
7394                            G_CONNECT_SWAPPED);
7395   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7396
7397   button = gtk_button_new_with_label ("Unstick");
7398   g_signal_connect_object (button,
7399                            "clicked",
7400                            G_CALLBACK (gtk_window_unstick),
7401                            window,
7402                            G_CONNECT_SWAPPED);
7403   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7404   
7405   button = gtk_button_new_with_label ("Maximize");
7406   g_signal_connect_object (button,
7407                            "clicked",
7408                            G_CALLBACK (gtk_window_maximize),
7409                            window,
7410                            G_CONNECT_SWAPPED);
7411   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7412
7413   button = gtk_button_new_with_label ("Unmaximize");
7414   g_signal_connect_object (button,
7415                            "clicked",
7416                            G_CALLBACK (gtk_window_unmaximize),
7417                            window,
7418                            G_CONNECT_SWAPPED);
7419   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7420
7421   button = gtk_button_new_with_label ("Iconify");
7422   g_signal_connect_object (button,
7423                            "clicked",
7424                            G_CALLBACK (gtk_window_iconify),
7425                            window,
7426                            G_CONNECT_SWAPPED);
7427   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7428
7429   button = gtk_button_new_with_label ("Fullscreen");
7430   g_signal_connect_object (button,
7431                            "clicked",
7432                            G_CALLBACK (gtk_window_fullscreen),
7433                            window,
7434                            G_CONNECT_SWAPPED);
7435   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7436
7437   button = gtk_button_new_with_label ("Unfullscreen");
7438   g_signal_connect_object (button,
7439                            "clicked",
7440                            G_CALLBACK (gtk_window_unfullscreen),
7441                            window,
7442                            G_CONNECT_SWAPPED);
7443   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7444
7445   button_above = gtk_toggle_button_new_with_label ("Keep above");
7446   g_signal_connect (button_above,
7447                     "toggled",
7448                     G_CALLBACK (keep_window_above),
7449                     window);
7450   gtk_box_pack_start (GTK_BOX (vbox), button_above, FALSE, FALSE, 0);
7451
7452   button_below = gtk_toggle_button_new_with_label ("Keep below");
7453   g_signal_connect (button_below,
7454                     "toggled",
7455                     G_CALLBACK (keep_window_below),
7456                     window);
7457   gtk_box_pack_start (GTK_BOX (vbox), button_below, FALSE, FALSE, 0);
7458
7459   g_object_set_data (G_OBJECT (button_above), "radio", button_below);
7460   g_object_set_data (G_OBJECT (button_below), "radio", button_above);
7461
7462   button = gtk_button_new_with_label ("Hide (withdraw)");
7463   g_signal_connect_object (button,
7464                            "clicked",
7465                            G_CALLBACK (gtk_widget_hide),
7466                            window,
7467                            G_CONNECT_SWAPPED);
7468   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7469   
7470   gtk_widget_show_all (vbox);
7471
7472   return vbox;
7473 }
7474
7475 void
7476 create_window_states (GtkWidget *widget)
7477 {
7478   static GtkWidget *window = NULL;
7479   GtkWidget *label;
7480   GtkWidget *box1;
7481   GtkWidget *iconified;
7482   GtkWidget *normal;
7483   GtkWidget *controls;
7484
7485   if (!window)
7486     {
7487       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7488       gtk_window_set_screen (GTK_WINDOW (window),
7489                              gtk_widget_get_screen (widget));
7490
7491       g_signal_connect (window, "destroy",
7492                         G_CALLBACK (gtk_widget_destroyed),
7493                         &window);
7494
7495       gtk_window_set_title (GTK_WINDOW (window), "Window states");
7496       
7497       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
7498       gtk_container_add (GTK_CONTAINER (window), box1);
7499
7500       iconified = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7501
7502       gtk_window_set_screen (GTK_WINDOW (iconified),
7503                              gtk_widget_get_screen (widget));
7504       
7505       g_signal_connect_object (iconified, "destroy",
7506                                G_CALLBACK (gtk_widget_destroy),
7507                                window,
7508                                G_CONNECT_SWAPPED);
7509       gtk_window_iconify (GTK_WINDOW (iconified));
7510       gtk_window_set_title (GTK_WINDOW (iconified), "Iconified initially");
7511       controls = get_state_controls (iconified);
7512       gtk_container_add (GTK_CONTAINER (iconified), controls);
7513       
7514       normal = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7515
7516       gtk_window_set_screen (GTK_WINDOW (normal),
7517                              gtk_widget_get_screen (widget));
7518       
7519       g_signal_connect_object (normal, "destroy",
7520                                G_CALLBACK (gtk_widget_destroy),
7521                                window,
7522                                G_CONNECT_SWAPPED);
7523       
7524       gtk_window_set_title (GTK_WINDOW (normal), "Deiconified initially");
7525       controls = get_state_controls (normal);
7526       gtk_container_add (GTK_CONTAINER (normal), controls);
7527       
7528       label = tracking_label (iconified);
7529       gtk_container_add (GTK_CONTAINER (box1), label);
7530
7531       label = tracking_label (normal);
7532       gtk_container_add (GTK_CONTAINER (box1), label);
7533
7534       gtk_widget_show_all (iconified);
7535       gtk_widget_show_all (normal);
7536       gtk_widget_show_all (box1);
7537     }
7538
7539   if (!gtk_widget_get_visible (window))
7540     gtk_widget_show (window);
7541   else
7542     gtk_widget_destroy (window);
7543 }
7544
7545 /*
7546  * Window sizing
7547  */
7548
7549 static gint
7550 configure_event_callback (GtkWidget *widget,
7551                           GdkEventConfigure *event,
7552                           gpointer data)
7553 {
7554   GtkWidget *label = data;
7555   gchar *msg;
7556   gint x, y;
7557   
7558   gtk_window_get_position (GTK_WINDOW (widget), &x, &y);
7559   
7560   msg = g_strdup_printf ("event: %d,%d  %d x %d\n"
7561                          "position: %d, %d",
7562                          event->x, event->y, event->width, event->height,
7563                          x, y);
7564   
7565   gtk_label_set_text (GTK_LABEL (label), msg);
7566
7567   g_free (msg);
7568
7569   return FALSE;
7570 }
7571
7572 static void
7573 get_ints (GtkWidget *window,
7574           gint      *a,
7575           gint      *b)
7576 {
7577   GtkWidget *spin1;
7578   GtkWidget *spin2;
7579
7580   spin1 = g_object_get_data (G_OBJECT (window), "spin1");
7581   spin2 = g_object_get_data (G_OBJECT (window), "spin2");
7582
7583   *a = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin1));
7584   *b = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin2));
7585 }
7586
7587 static void
7588 set_size_callback (GtkWidget *widget,
7589                    gpointer   data)
7590 {
7591   gint w, h;
7592   
7593   get_ints (data, &w, &h);
7594
7595   gtk_window_resize (GTK_WINDOW (g_object_get_data (data, "target")), w, h);
7596 }
7597
7598 static void
7599 unset_default_size_callback (GtkWidget *widget,
7600                              gpointer   data)
7601 {
7602   gtk_window_set_default_size (g_object_get_data (data, "target"),
7603                                -1, -1);
7604 }
7605
7606 static void
7607 set_default_size_callback (GtkWidget *widget,
7608                            gpointer   data)
7609 {
7610   gint w, h;
7611   
7612   get_ints (data, &w, &h);
7613
7614   gtk_window_set_default_size (g_object_get_data (data, "target"),
7615                                w, h);
7616 }
7617
7618 static void
7619 unset_size_request_callback (GtkWidget *widget,
7620                              gpointer   data)
7621 {
7622   gtk_widget_set_size_request (g_object_get_data (data, "target"),
7623                                -1, -1);
7624 }
7625
7626 static void
7627 set_size_request_callback (GtkWidget *widget,
7628                            gpointer   data)
7629 {
7630   gint w, h;
7631   
7632   get_ints (data, &w, &h);
7633
7634   gtk_widget_set_size_request (g_object_get_data (data, "target"),
7635                                w, h);
7636 }
7637
7638 static void
7639 set_location_callback (GtkWidget *widget,
7640                        gpointer   data)
7641 {
7642   gint x, y;
7643   
7644   get_ints (data, &x, &y);
7645
7646   gtk_window_move (g_object_get_data (data, "target"), x, y);
7647 }
7648
7649 static void
7650 move_to_position_callback (GtkWidget *widget,
7651                            gpointer   data)
7652 {
7653   gint x, y;
7654   GtkWindow *window;
7655
7656   window = g_object_get_data (data, "target");
7657   
7658   gtk_window_get_position (window, &x, &y);
7659
7660   gtk_window_move (window, x, y);
7661 }
7662
7663 static void
7664 set_geometry_callback (GtkWidget *entry,
7665                        gpointer   data)
7666 {
7667   gchar *text;
7668   GtkWindow *target;
7669
7670   target = GTK_WINDOW (g_object_get_data (G_OBJECT (data), "target"));
7671   
7672   text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
7673
7674   if (!gtk_window_parse_geometry (target, text))
7675     g_print ("Bad geometry string '%s'\n", text);
7676
7677   g_free (text);
7678 }
7679
7680 static void
7681 resizable_callback (GtkWidget *widget,
7682                      gpointer   data)
7683 {
7684   g_object_set (g_object_get_data (data, "target"),
7685                 "resizable", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)),
7686                 NULL);
7687 }
7688
7689 static void
7690 gravity_selected (GtkWidget *widget,
7691                   gpointer   data)
7692 {
7693   gtk_window_set_gravity (GTK_WINDOW (g_object_get_data (data, "target")),
7694                           gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) + GDK_GRAVITY_NORTH_WEST);
7695 }
7696
7697 static void
7698 pos_selected (GtkWidget *widget,
7699               gpointer   data)
7700 {
7701   gtk_window_set_position (GTK_WINDOW (g_object_get_data (data, "target")),
7702                            gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) + GTK_WIN_POS_NONE);
7703 }
7704
7705 static void
7706 move_gravity_window_to_current_position (GtkWidget *widget,
7707                                          gpointer   data)
7708 {
7709   gint x, y;
7710   GtkWindow *window;
7711
7712   window = GTK_WINDOW (data);    
7713   
7714   gtk_window_get_position (window, &x, &y);
7715
7716   gtk_window_move (window, x, y);
7717 }
7718
7719 static void
7720 get_screen_corner (GtkWindow *window,
7721                    gint      *x,
7722                    gint      *y)
7723 {
7724   int w, h;
7725   GdkScreen * screen = gtk_window_get_screen (window);
7726   
7727   gtk_window_get_size (GTK_WINDOW (window), &w, &h);
7728
7729   switch (gtk_window_get_gravity (window))
7730     {
7731     case GDK_GRAVITY_SOUTH_EAST:
7732       *x = gdk_screen_get_width (screen) - w;
7733       *y = gdk_screen_get_height (screen) - h;
7734       break;
7735
7736     case GDK_GRAVITY_NORTH_EAST:
7737       *x = gdk_screen_get_width (screen) - w;
7738       *y = 0;
7739       break;
7740
7741     case GDK_GRAVITY_SOUTH_WEST:
7742       *x = 0;
7743       *y = gdk_screen_get_height (screen) - h;
7744       break;
7745
7746     case GDK_GRAVITY_NORTH_WEST:
7747       *x = 0;
7748       *y = 0;
7749       break;
7750       
7751     case GDK_GRAVITY_SOUTH:
7752       *x = (gdk_screen_get_width (screen) - w) / 2;
7753       *y = gdk_screen_get_height (screen) - h;
7754       break;
7755
7756     case GDK_GRAVITY_NORTH:
7757       *x = (gdk_screen_get_width (screen) - w) / 2;
7758       *y = 0;
7759       break;
7760
7761     case GDK_GRAVITY_WEST:
7762       *x = 0;
7763       *y = (gdk_screen_get_height (screen) - h) / 2;
7764       break;
7765
7766     case GDK_GRAVITY_EAST:
7767       *x = gdk_screen_get_width (screen) - w;
7768       *y = (gdk_screen_get_height (screen) - h) / 2;
7769       break;
7770
7771     case GDK_GRAVITY_CENTER:
7772       *x = (gdk_screen_get_width (screen) - w) / 2;
7773       *y = (gdk_screen_get_height (screen) - h) / 2;
7774       break;
7775
7776     case GDK_GRAVITY_STATIC:
7777       /* pick some random numbers */
7778       *x = 350;
7779       *y = 350;
7780       break;
7781
7782     default:
7783       g_assert_not_reached ();
7784       break;
7785     }
7786 }
7787
7788 static void
7789 move_gravity_window_to_starting_position (GtkWidget *widget,
7790                                           gpointer   data)
7791 {
7792   gint x, y;
7793   GtkWindow *window;
7794
7795   window = GTK_WINDOW (data);    
7796   
7797   get_screen_corner (window,
7798                      &x, &y);
7799   
7800   gtk_window_move (window, x, y);
7801 }
7802
7803 static GtkWidget*
7804 make_gravity_window (GtkWidget   *destroy_with,
7805                      GdkGravity   gravity,
7806                      const gchar *title)
7807 {
7808   GtkWidget *window;
7809   GtkWidget *button;
7810   GtkWidget *vbox;
7811   int x, y;
7812   
7813   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7814
7815   gtk_window_set_screen (GTK_WINDOW (window),
7816                          gtk_widget_get_screen (destroy_with));
7817
7818   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
7819   gtk_widget_show (vbox);
7820   
7821   gtk_container_add (GTK_CONTAINER (window), vbox);
7822   gtk_window_set_title (GTK_WINDOW (window), title);
7823   gtk_window_set_gravity (GTK_WINDOW (window), gravity);
7824
7825   g_signal_connect_object (destroy_with,
7826                            "destroy",
7827                            G_CALLBACK (gtk_widget_destroy),
7828                            window,
7829                            G_CONNECT_SWAPPED);
7830
7831   
7832   button = gtk_button_new_with_mnemonic ("_Move to current position");
7833
7834   g_signal_connect (button, "clicked",
7835                     G_CALLBACK (move_gravity_window_to_current_position),
7836                     window);
7837
7838   gtk_container_add (GTK_CONTAINER (vbox), button);
7839   gtk_widget_show (button);
7840
7841   button = gtk_button_new_with_mnemonic ("Move to _starting position");
7842
7843   g_signal_connect (button, "clicked",
7844                     G_CALLBACK (move_gravity_window_to_starting_position),
7845                     window);
7846
7847   gtk_container_add (GTK_CONTAINER (vbox), button);
7848   gtk_widget_show (button);
7849   
7850   /* Pretend this is the result of --geometry.
7851    * DO NOT COPY THIS CODE unless you are setting --geometry results,
7852    * and in that case you probably should just use gtk_window_parse_geometry().
7853    * AGAIN, DO NOT SET GDK_HINT_USER_POS! It violates the ICCCM unless
7854    * you are parsing --geometry or equivalent.
7855    */
7856   gtk_window_set_geometry_hints (GTK_WINDOW (window),
7857                                  NULL, NULL,
7858                                  GDK_HINT_USER_POS);
7859
7860   gtk_window_set_default_size (GTK_WINDOW (window),
7861                                200, 200);
7862
7863   get_screen_corner (GTK_WINDOW (window), &x, &y);
7864   
7865   gtk_window_move (GTK_WINDOW (window),
7866                    x, y);
7867   
7868   return window;
7869 }
7870
7871 static void
7872 do_gravity_test (GtkWidget *widget,
7873                  gpointer   data)
7874 {
7875   GtkWidget *destroy_with = data;
7876   GtkWidget *window;
7877   
7878   /* We put a window at each gravity point on the screen. */
7879   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_WEST,
7880                                 "NorthWest");
7881   gtk_widget_show (window);
7882   
7883   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_EAST,
7884                                 "SouthEast");
7885   gtk_widget_show (window);
7886
7887   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_EAST,
7888                                 "NorthEast");
7889   gtk_widget_show (window);
7890
7891   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_WEST,
7892                                 "SouthWest");
7893   gtk_widget_show (window);
7894
7895   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH,
7896                                 "South");
7897   gtk_widget_show (window);
7898
7899   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH,
7900                                 "North");
7901   gtk_widget_show (window);
7902
7903   
7904   window = make_gravity_window (destroy_with, GDK_GRAVITY_WEST,
7905                                 "West");
7906   gtk_widget_show (window);
7907
7908     
7909   window = make_gravity_window (destroy_with, GDK_GRAVITY_EAST,
7910                                 "East");
7911   gtk_widget_show (window);
7912
7913   window = make_gravity_window (destroy_with, GDK_GRAVITY_CENTER,
7914                                 "Center");
7915   gtk_widget_show (window);
7916
7917   window = make_gravity_window (destroy_with, GDK_GRAVITY_STATIC,
7918                                 "Static");
7919   gtk_widget_show (window);
7920 }
7921
7922 static GtkWidget*
7923 window_controls (GtkWidget *window)
7924 {
7925   GtkWidget *control_window;
7926   GtkWidget *label;
7927   GtkWidget *vbox;
7928   GtkWidget *button;
7929   GtkWidget *spin;
7930   GtkAdjustment *adjustment;
7931   GtkWidget *entry;
7932   GtkWidget *om;
7933   gint i;
7934   
7935   control_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7936
7937   gtk_window_set_screen (GTK_WINDOW (control_window),
7938                          gtk_widget_get_screen (window));
7939
7940   gtk_window_set_title (GTK_WINDOW (control_window), "Size controls");
7941   
7942   g_object_set_data (G_OBJECT (control_window),
7943                      "target",
7944                      window);
7945   
7946   g_signal_connect_object (control_window,
7947                            "destroy",
7948                            G_CALLBACK (gtk_widget_destroy),
7949                            window,
7950                            G_CONNECT_SWAPPED);
7951
7952   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
7953   
7954   gtk_container_add (GTK_CONTAINER (control_window), vbox);
7955   
7956   label = gtk_label_new ("<no configure events>");
7957   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
7958   
7959   g_signal_connect (window,
7960                     "configure_event",
7961                     G_CALLBACK (configure_event_callback),
7962                     label);
7963
7964   adjustment = gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0, 5.0, 0.0);
7965   spin = gtk_spin_button_new (adjustment, 0, 0);
7966
7967   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
7968
7969   g_object_set_data (G_OBJECT (control_window), "spin1", spin);
7970
7971   adjustment = gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0, 5.0, 0.0);
7972   spin = gtk_spin_button_new (adjustment, 0, 0);
7973
7974   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
7975
7976   g_object_set_data (G_OBJECT (control_window), "spin2", spin);
7977
7978   entry = gtk_entry_new ();
7979   gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
7980
7981   g_signal_connect (entry, "changed",
7982                     G_CALLBACK (set_geometry_callback),
7983                     control_window);
7984
7985   button = gtk_button_new_with_label ("Show gravity test windows");
7986   g_signal_connect_swapped (button,
7987                             "clicked",
7988                             G_CALLBACK (do_gravity_test),
7989                             control_window);
7990   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7991
7992   button = gtk_button_new_with_label ("Reshow with initial size");
7993   g_signal_connect_object (button,
7994                            "clicked",
7995                            G_CALLBACK (gtk_window_reshow_with_initial_size),
7996                            window,
7997                            G_CONNECT_SWAPPED);
7998   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7999   
8000   button = gtk_button_new_with_label ("Queue resize");
8001   g_signal_connect_object (button,
8002                            "clicked",
8003                            G_CALLBACK (gtk_widget_queue_resize),
8004                            window,
8005                            G_CONNECT_SWAPPED);
8006   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8007   
8008   button = gtk_button_new_with_label ("Resize");
8009   g_signal_connect (button,
8010                     "clicked",
8011                     G_CALLBACK (set_size_callback),
8012                     control_window);
8013   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8014
8015   button = gtk_button_new_with_label ("Set default size");
8016   g_signal_connect (button,
8017                     "clicked",
8018                     G_CALLBACK (set_default_size_callback),
8019                     control_window);
8020   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8021
8022   button = gtk_button_new_with_label ("Unset default size");
8023   g_signal_connect (button,
8024                     "clicked",
8025                     G_CALLBACK (unset_default_size_callback),
8026                     control_window);
8027   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8028   
8029   button = gtk_button_new_with_label ("Set size request");
8030   g_signal_connect (button,
8031                     "clicked",
8032                     G_CALLBACK (set_size_request_callback),
8033                     control_window);
8034   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8035
8036   button = gtk_button_new_with_label ("Unset size request");
8037   g_signal_connect (button,
8038                     "clicked",
8039                     G_CALLBACK (unset_size_request_callback),
8040                     control_window);
8041   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8042   
8043   button = gtk_button_new_with_label ("Move");
8044   g_signal_connect (button,
8045                     "clicked",
8046                     G_CALLBACK (set_location_callback),
8047                     control_window);
8048   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8049
8050   button = gtk_button_new_with_label ("Move to current position");
8051   g_signal_connect (button,
8052                     "clicked",
8053                     G_CALLBACK (move_to_position_callback),
8054                     control_window);
8055   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8056
8057   button = gtk_check_button_new_with_label ("Allow resize");
8058   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
8059   g_signal_connect (button,
8060                     "toggled",
8061                     G_CALLBACK (resizable_callback),
8062                     control_window);
8063   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8064   
8065   button = gtk_button_new_with_mnemonic ("_Show");
8066   g_signal_connect_object (button,
8067                            "clicked",
8068                            G_CALLBACK (gtk_widget_show),
8069                            window,
8070                            G_CONNECT_SWAPPED);
8071   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8072
8073   button = gtk_button_new_with_mnemonic ("_Hide");
8074   g_signal_connect_object (button,
8075                            "clicked",
8076                            G_CALLBACK (gtk_widget_hide),
8077                            window,
8078                            G_CONNECT_SWAPPED);
8079   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8080
8081   om = gtk_combo_box_text_new ();
8082   i = 0;
8083   while (i < 10)
8084     {
8085       static gchar *names[] = {
8086         "GDK_GRAVITY_NORTH_WEST",
8087         "GDK_GRAVITY_NORTH",
8088         "GDK_GRAVITY_NORTH_EAST",
8089         "GDK_GRAVITY_WEST",
8090         "GDK_GRAVITY_CENTER",
8091         "GDK_GRAVITY_EAST",
8092         "GDK_GRAVITY_SOUTH_WEST",
8093         "GDK_GRAVITY_SOUTH",
8094         "GDK_GRAVITY_SOUTH_EAST",
8095         "GDK_GRAVITY_STATIC",
8096         NULL
8097       };
8098
8099       g_assert (names[i]);
8100       gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (om), names[i]);
8101
8102       ++i;
8103     }
8104   
8105   g_signal_connect (om,
8106                     "changed",
8107                     G_CALLBACK (gravity_selected),
8108                     control_window);
8109
8110   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
8111
8112
8113   om = gtk_combo_box_text_new ();
8114   i = 0;
8115   while (i < 5)
8116     {
8117       static gchar *names[] = {
8118         "GTK_WIN_POS_NONE",
8119         "GTK_WIN_POS_CENTER",
8120         "GTK_WIN_POS_MOUSE",
8121         "GTK_WIN_POS_CENTER_ALWAYS",
8122         "GTK_WIN_POS_CENTER_ON_PARENT",
8123         NULL
8124       };
8125
8126       g_assert (names[i]);
8127       gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (om), names[i]);
8128
8129       ++i;
8130     }
8131
8132   g_signal_connect (om,
8133                     "changed",
8134                     G_CALLBACK (pos_selected),
8135                     control_window);
8136
8137   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
8138   
8139   gtk_widget_show_all (vbox);
8140   
8141   return control_window;
8142 }
8143
8144 void
8145 create_window_sizing (GtkWidget *widget)
8146 {
8147   static GtkWidget *window = NULL;
8148   static GtkWidget *target_window = NULL;
8149
8150   if (!target_window)
8151     {
8152       GtkWidget *label;
8153       
8154       target_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8155       gtk_window_set_screen (GTK_WINDOW (target_window),
8156                              gtk_widget_get_screen (widget));
8157       label = gtk_label_new (NULL);
8158       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");
8159       gtk_container_add (GTK_CONTAINER (target_window), label);
8160       gtk_widget_show (label);
8161       
8162       g_signal_connect (target_window, "destroy",
8163                         G_CALLBACK (gtk_widget_destroyed),
8164                         &target_window);
8165
8166       window = window_controls (target_window);
8167       
8168       g_signal_connect (window, "destroy",
8169                         G_CALLBACK (gtk_widget_destroyed),
8170                         &window);
8171       
8172       gtk_window_set_title (GTK_WINDOW (target_window), "Window to size");
8173     }
8174
8175   /* don't show target window by default, we want to allow testing
8176    * of behavior on first show.
8177    */
8178   
8179   if (!gtk_widget_get_visible (window))
8180     gtk_widget_show (window);
8181   else
8182     gtk_widget_destroy (window);
8183 }
8184
8185 /*
8186  * GtkProgressBar
8187  */
8188
8189 typedef struct _ProgressData {
8190   GtkWidget *window;
8191   GtkWidget *pbar;
8192   GtkWidget *block_spin;
8193   GtkWidget *x_align_spin;
8194   GtkWidget *y_align_spin;
8195   GtkWidget *step_spin;
8196   GtkWidget *act_blocks_spin;
8197   GtkWidget *label;
8198   GtkWidget *omenu1;
8199   GtkWidget *elmenu;
8200   GtkWidget *omenu2;
8201   GtkWidget *entry;
8202   int timer;
8203   gboolean activity;
8204 } ProgressData;
8205
8206 gboolean
8207 progress_timeout (gpointer data)
8208 {
8209   ProgressData *pdata = data;
8210   gdouble new_val;
8211   gchar *text;
8212
8213   if (pdata->activity)
8214     {
8215       gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pdata->pbar));
8216
8217       text = g_strdup_printf ("%s", "???");
8218     }
8219   else
8220     {
8221       new_val = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (pdata->pbar)) + 0.01;
8222       if (new_val > 1.00)
8223         new_val = 0.00;
8224       gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pdata->pbar), new_val);
8225
8226       text = g_strdup_printf ("%.0f%%", 100 * new_val);
8227     }
8228
8229   gtk_label_set_text (GTK_LABEL (pdata->label), text);
8230   g_free (text);
8231
8232   return TRUE;
8233 }
8234
8235 static void
8236 destroy_progress (GtkWidget     *widget,
8237                   ProgressData **pdata)
8238 {
8239   if ((*pdata)->timer)
8240     {
8241       g_source_remove ((*pdata)->timer);
8242       (*pdata)->timer = 0;
8243     }
8244   (*pdata)->window = NULL;
8245   g_free (*pdata);
8246   *pdata = NULL;
8247 }
8248
8249 static void
8250 progressbar_toggle_orientation (GtkWidget *widget, gpointer data)
8251 {
8252   ProgressData *pdata;
8253   gint i;
8254
8255   pdata = (ProgressData *) data;
8256
8257   if (!gtk_widget_get_mapped (widget))
8258     return;
8259
8260   i = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
8261
8262   if (i == 0 || i == 1)
8263     gtk_orientable_set_orientation (GTK_ORIENTABLE (pdata->pbar), GTK_ORIENTATION_HORIZONTAL);
8264   else
8265     gtk_orientable_set_orientation (GTK_ORIENTABLE (pdata->pbar), GTK_ORIENTATION_VERTICAL);
8266  
8267   if (i == 1 || i == 2)
8268     gtk_progress_bar_set_inverted (GTK_PROGRESS_BAR (pdata->pbar), TRUE);
8269   else
8270     gtk_progress_bar_set_inverted (GTK_PROGRESS_BAR (pdata->pbar), FALSE);
8271 }
8272
8273 static void
8274 toggle_show_text (GtkWidget *widget, ProgressData *pdata)
8275 {
8276   gboolean active;
8277
8278   active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
8279   gtk_progress_bar_set_show_text (GTK_PROGRESS_BAR (pdata->pbar), active);
8280 }
8281
8282 static void
8283 progressbar_toggle_ellipsize (GtkWidget *widget,
8284                               gpointer   data)
8285 {
8286   ProgressData *pdata = data;
8287   if (gtk_widget_is_drawable (widget))
8288     {
8289       gint i = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
8290       gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (pdata->pbar), i);
8291     }
8292 }
8293
8294 static void
8295 toggle_activity_mode (GtkWidget *widget, ProgressData *pdata)
8296 {
8297   pdata->activity = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
8298 }
8299
8300 static void
8301 toggle_running (GtkWidget *widget, ProgressData *pdata)
8302 {
8303   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
8304     {
8305       if (pdata->timer == 0)
8306         pdata->timer = g_timeout_add (100, (GSourceFunc)progress_timeout, pdata);
8307     }
8308   else
8309     {
8310       if (pdata->timer != 0)
8311         {
8312           g_source_remove (pdata->timer);
8313           pdata->timer = 0;
8314         }
8315     }
8316 }
8317
8318 static void
8319 entry_changed (GtkWidget *widget, ProgressData *pdata)
8320 {
8321   gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata->pbar),
8322                           gtk_entry_get_text (GTK_ENTRY (pdata->entry)));
8323 }
8324
8325 void
8326 create_progress_bar (GtkWidget *widget)
8327 {
8328   GtkWidget *action_area, *content_area;
8329   GtkWidget *button;
8330   GtkWidget *vbox;
8331   GtkWidget *vbox2;
8332   GtkWidget *hbox;
8333   GtkWidget *check;
8334   GtkWidget *frame;
8335   GtkWidget *tab;
8336   GtkWidget *label;
8337   GtkWidget *align;
8338   static ProgressData *pdata = NULL;
8339
8340   static gchar *items1[] =
8341   {
8342     "Left-Right",
8343     "Right-Left",
8344     "Bottom-Top",
8345     "Top-Bottom"
8346   };
8347
8348     static char *ellipsize_items[] = {
8349     "None",     // PANGO_ELLIPSIZE_NONE,
8350     "Start",    // PANGO_ELLIPSIZE_START,
8351     "Middle",   // PANGO_ELLIPSIZE_MIDDLE,
8352     "End",      // PANGO_ELLIPSIZE_END
8353   };
8354   
8355   if (!pdata)
8356     pdata = g_new0 (ProgressData, 1);
8357
8358   if (!pdata->window)
8359     {
8360       pdata->window = gtk_dialog_new ();
8361
8362       gtk_window_set_screen (GTK_WINDOW (pdata->window),
8363                              gtk_widget_get_screen (widget));
8364
8365       gtk_window_set_resizable (GTK_WINDOW (pdata->window), TRUE);
8366
8367       g_signal_connect (pdata->window, "destroy",
8368                         G_CALLBACK (destroy_progress),
8369                         &pdata);
8370       pdata->timer = 0;
8371
8372       content_area = gtk_dialog_get_content_area (GTK_DIALOG (pdata->window));
8373       action_area = gtk_dialog_get_action_area (GTK_DIALOG (pdata->window));
8374
8375       gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
8376       gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);
8377
8378       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
8379       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
8380       gtk_box_pack_start (GTK_BOX (content_area), vbox, FALSE, TRUE, 0);
8381
8382       frame = gtk_frame_new ("Progress");
8383       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
8384
8385       vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
8386       gtk_container_add (GTK_CONTAINER (frame), vbox2);
8387
8388       align = gtk_alignment_new (0.5, 0.5, 0, 0);
8389       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
8390
8391       pdata->pbar = gtk_progress_bar_new ();
8392       gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (pdata->pbar),
8393                                       PANGO_ELLIPSIZE_MIDDLE);
8394
8395       gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
8396
8397       align = gtk_alignment_new (0.5, 0.5, 0, 0);
8398       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
8399
8400       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
8401       gtk_container_add (GTK_CONTAINER (align), hbox);
8402       label = gtk_label_new ("Label updated by user :"); 
8403       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
8404       pdata->label = gtk_label_new ("");
8405       gtk_box_pack_start (GTK_BOX (hbox), pdata->label, FALSE, TRUE, 0);
8406
8407       frame = gtk_frame_new ("Options");
8408       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
8409
8410       vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
8411       gtk_container_add (GTK_CONTAINER (frame), vbox2);
8412
8413       tab = gtk_table_new (7, 2, FALSE);
8414       gtk_box_pack_start (GTK_BOX (vbox2), tab, FALSE, TRUE, 0);
8415
8416       label = gtk_label_new ("Orientation :");
8417       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 0, 1,
8418                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
8419                         5, 5);
8420       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
8421
8422       pdata->omenu1 = build_option_menu (items1, 4, 0,
8423                                          progressbar_toggle_orientation,
8424                                          pdata);
8425       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
8426       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 0, 1,
8427                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
8428                         5, 5);
8429       gtk_box_pack_start (GTK_BOX (hbox), pdata->omenu1, TRUE, TRUE, 0);
8430       
8431       check = gtk_check_button_new_with_label ("Running");
8432       g_signal_connect (check, "toggled",
8433                         G_CALLBACK (toggle_running),
8434                         pdata);
8435       gtk_table_attach (GTK_TABLE (tab), check, 0, 2, 1, 2,
8436                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
8437                         5, 5);
8438       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
8439
8440       check = gtk_check_button_new_with_label ("Show text");
8441       g_signal_connect (check, "clicked",
8442                         G_CALLBACK (toggle_show_text),
8443                         pdata);
8444       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 2, 3,
8445                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
8446                         5, 5);
8447
8448       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
8449       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 2, 3,
8450                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
8451                         5, 5);
8452
8453       label = gtk_label_new ("Text: ");
8454       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
8455
8456       pdata->entry = gtk_entry_new ();
8457       g_signal_connect (pdata->entry, "changed",
8458                         G_CALLBACK (entry_changed),
8459                         pdata);
8460       gtk_box_pack_start (GTK_BOX (hbox), pdata->entry, TRUE, TRUE, 0);
8461       gtk_widget_set_size_request (pdata->entry, 100, -1);
8462
8463       label = gtk_label_new ("Ellipsize text :");
8464       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 10, 11,
8465                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
8466                         5, 5);
8467       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
8468       pdata->elmenu = build_option_menu (ellipsize_items,
8469                                          sizeof (ellipsize_items) / sizeof (ellipsize_items[0]),
8470                                          2, // PANGO_ELLIPSIZE_MIDDLE
8471                                          progressbar_toggle_ellipsize,
8472                                          pdata);
8473       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
8474       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 10, 11,
8475                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
8476                         5, 5);
8477       gtk_box_pack_start (GTK_BOX (hbox), pdata->elmenu, TRUE, TRUE, 0);
8478
8479       check = gtk_check_button_new_with_label ("Activity mode");
8480       g_signal_connect (check, "clicked",
8481                         G_CALLBACK (toggle_activity_mode), pdata);
8482       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 15, 16,
8483                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
8484                         5, 5);
8485
8486       button = gtk_button_new_with_label ("close");
8487       g_signal_connect_swapped (button, "clicked",
8488                                 G_CALLBACK (gtk_widget_destroy),
8489                                 pdata->window);
8490       gtk_widget_set_can_default (button, TRUE);
8491       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
8492       gtk_widget_grab_default (button);
8493     }
8494
8495   if (!gtk_widget_get_visible (pdata->window))
8496     gtk_widget_show_all (pdata->window);
8497   else
8498     gtk_widget_destroy (pdata->window);
8499 }
8500
8501 /*
8502  * Properties
8503  */
8504
8505 typedef struct {
8506   int x;
8507   int y;
8508   gboolean found;
8509   gboolean first;
8510   GtkWidget *res_widget;
8511 } FindWidgetData;
8512
8513 static void
8514 find_widget (GtkWidget *widget, FindWidgetData *data)
8515 {
8516   GtkAllocation new_allocation;
8517   gint x_offset = 0;
8518   gint y_offset = 0;
8519
8520   gtk_widget_get_allocation (widget, &new_allocation);
8521
8522   if (data->found || !gtk_widget_get_mapped (widget))
8523     return;
8524
8525   /* Note that in the following code, we only count the
8526    * position as being inside a WINDOW widget if it is inside
8527    * widget->window; points that are outside of widget->window
8528    * but within the allocation are not counted. This is consistent
8529    * with the way we highlight drag targets.
8530    */
8531   if (gtk_widget_get_has_window (widget))
8532     {
8533       new_allocation.x = 0;
8534       new_allocation.y = 0;
8535     }
8536
8537   if (gtk_widget_get_parent (widget) && !data->first)
8538     {
8539       GdkWindow *window = gtk_widget_get_window (widget);
8540       while (window != gtk_widget_get_window (gtk_widget_get_parent (widget)))
8541         {
8542           gint tx, ty, twidth, theight;
8543           
8544           twidth = gdk_window_get_width (window);
8545           theight = gdk_window_get_height (window);
8546
8547           if (new_allocation.x < 0)
8548             {
8549               new_allocation.width += new_allocation.x;
8550               new_allocation.x = 0;
8551             }
8552           if (new_allocation.y < 0)
8553             {
8554               new_allocation.height += new_allocation.y;
8555               new_allocation.y = 0;
8556             }
8557           if (new_allocation.x + new_allocation.width > twidth)
8558             new_allocation.width = twidth - new_allocation.x;
8559           if (new_allocation.y + new_allocation.height > theight)
8560             new_allocation.height = theight - new_allocation.y;
8561
8562           gdk_window_get_position (window, &tx, &ty);
8563           new_allocation.x += tx;
8564           x_offset += tx;
8565           new_allocation.y += ty;
8566           y_offset += ty;
8567
8568           window = gdk_window_get_parent (window);
8569         }
8570     }
8571
8572   if ((data->x >= new_allocation.x) && (data->y >= new_allocation.y) &&
8573       (data->x < new_allocation.x + new_allocation.width) && 
8574       (data->y < new_allocation.y + new_allocation.height))
8575     {
8576       /* First, check if the drag is in a valid drop site in
8577        * one of our children 
8578        */
8579       if (GTK_IS_CONTAINER (widget))
8580         {
8581           FindWidgetData new_data = *data;
8582           
8583           new_data.x -= x_offset;
8584           new_data.y -= y_offset;
8585           new_data.found = FALSE;
8586           new_data.first = FALSE;
8587           
8588           gtk_container_forall (GTK_CONTAINER (widget),
8589                                 (GtkCallback)find_widget,
8590                                 &new_data);
8591           
8592           data->found = new_data.found;
8593           if (data->found)
8594             data->res_widget = new_data.res_widget;
8595         }
8596
8597       /* If not, and this widget is registered as a drop site, check to
8598        * emit "drag_motion" to check if we are actually in
8599        * a drop site.
8600        */
8601       if (!data->found)
8602         {
8603           data->found = TRUE;
8604           data->res_widget = widget;
8605         }
8606     }
8607 }
8608
8609 static GtkWidget *
8610 find_widget_at_pointer (GdkDevice *device)
8611 {
8612   GtkWidget *widget = NULL;
8613   GdkWindow *pointer_window;
8614   gint x, y;
8615   FindWidgetData data;
8616  
8617  pointer_window = gdk_device_get_window_at_position (device, NULL, NULL);
8618  
8619  if (pointer_window)
8620    {
8621      gpointer widget_ptr;
8622
8623      gdk_window_get_user_data (pointer_window, &widget_ptr);
8624      widget = widget_ptr;
8625    }
8626
8627  if (widget)
8628    {
8629      gdk_window_get_pointer (gtk_widget_get_window (widget),
8630                              &x, &y, NULL);
8631      
8632      data.x = x;
8633      data.y = y;
8634      data.found = FALSE;
8635      data.first = TRUE;
8636
8637      find_widget (widget, &data);
8638      if (data.found)
8639        return data.res_widget;
8640      return widget;
8641    }
8642  return NULL;
8643 }
8644
8645 struct PropertiesData {
8646   GtkWidget **window;
8647   GdkCursor *cursor;
8648   gboolean in_query;
8649   gulong handler;
8650 };
8651
8652 static void
8653 destroy_properties (GtkWidget             *widget,
8654                     struct PropertiesData *data)
8655 {
8656   if (data->window)
8657     {
8658       *data->window = NULL;
8659       data->window = NULL;
8660     }
8661
8662   if (data->cursor)
8663     {
8664       g_object_unref (data->cursor);
8665       data->cursor = NULL;
8666     }
8667
8668   if (data->handler)
8669     {
8670       g_signal_handler_disconnect (widget, data->handler);
8671       data->handler = 0;
8672     }
8673
8674   g_free (data);
8675 }
8676
8677 static gint
8678 property_query_event (GtkWidget             *widget,
8679                       GdkEvent              *event,
8680                       struct PropertiesData *data)
8681 {
8682   GtkWidget *res_widget = NULL;
8683
8684   if (!data->in_query)
8685     return FALSE;
8686
8687   if (event->type == GDK_BUTTON_RELEASE)
8688     {
8689       gtk_grab_remove (widget);
8690       gdk_device_ungrab (gdk_event_get_device (event), GDK_CURRENT_TIME);
8691
8692       res_widget = find_widget_at_pointer (gdk_event_get_device (event));
8693       if (res_widget)
8694         {
8695           g_object_set_data (G_OBJECT (res_widget), "prop-editor-screen",
8696                              gtk_widget_get_screen (widget));
8697           create_prop_editor (G_OBJECT (res_widget), 0);
8698         }
8699
8700       data->in_query = FALSE;
8701     }
8702   return FALSE;
8703 }
8704
8705
8706 static void
8707 query_properties (GtkButton *button,
8708                   struct PropertiesData *data)
8709 {
8710   GtkWidget *widget = GTK_WIDGET (button);
8711   GdkDisplay *display;
8712   GdkDeviceManager *device_manager;
8713   GdkDevice *device;
8714
8715   g_signal_connect (button, "event",
8716                     G_CALLBACK (property_query_event), data);
8717
8718   display = gtk_widget_get_display (widget);
8719
8720   if (!data->cursor)
8721     data->cursor = gdk_cursor_new_for_display (display, GDK_TARGET);
8722
8723   device_manager = gdk_display_get_device_manager (display);
8724   device = gdk_device_manager_get_client_pointer (device_manager);
8725   gdk_device_grab (device,
8726                    gtk_widget_get_window (widget),
8727                    GDK_OWNERSHIP_NONE,
8728                    TRUE,
8729                    GDK_BUTTON_RELEASE_MASK,
8730                    data->cursor,
8731                    GDK_CURRENT_TIME);
8732   gtk_grab_add (widget);
8733
8734   data->in_query = TRUE;
8735 }
8736
8737 static void
8738 create_properties (GtkWidget *widget)
8739 {
8740   static GtkWidget *window = NULL;
8741   GtkWidget *button;
8742   GtkWidget *vbox;
8743   GtkWidget *label;
8744   struct PropertiesData *data;
8745
8746   data = g_new (struct PropertiesData, 1);
8747   data->window = &window;
8748   data->in_query = FALSE;
8749   data->cursor = NULL;
8750   data->handler = 0;
8751
8752   if (!window)
8753     {
8754       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8755
8756       gtk_window_set_screen (GTK_WINDOW (window),
8757                              gtk_widget_get_screen (widget));      
8758
8759       data->handler = g_signal_connect (window, "destroy",
8760                                         G_CALLBACK (destroy_properties),
8761                                         data);
8762
8763       gtk_window_set_title (GTK_WINDOW (window), "test properties");
8764       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
8765
8766       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 1);
8767       gtk_container_add (GTK_CONTAINER (window), vbox);
8768             
8769       label = gtk_label_new ("This is just a dumb test to test properties.\nIf you need a generic module, get GLE.");
8770       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
8771       
8772       button = gtk_button_new_with_label ("Query properties");
8773       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
8774       g_signal_connect (button, "clicked",
8775                         G_CALLBACK (query_properties),
8776                         data);
8777     }
8778
8779   if (!gtk_widget_get_visible (window))
8780     gtk_widget_show_all (window);
8781   else
8782     gtk_widget_destroy (window);
8783   
8784 }
8785
8786 struct SnapshotData {
8787   GtkWidget *toplevel_button;
8788   GtkWidget **window;
8789   GdkCursor *cursor;
8790   gboolean in_query;
8791   gboolean is_toplevel;
8792   gint handler;
8793 };
8794
8795 static void
8796 destroy_snapshot_data (GtkWidget             *widget,
8797                        struct SnapshotData *data)
8798 {
8799   if (*data->window)
8800     *data->window = NULL;
8801   
8802   if (data->cursor)
8803     {
8804       g_object_unref (data->cursor);
8805       data->cursor = NULL;
8806     }
8807
8808   if (data->handler)
8809     {
8810       g_signal_handler_disconnect (widget, data->handler);
8811       data->handler = 0;
8812     }
8813
8814   g_free (data);
8815 }
8816
8817 static gint
8818 snapshot_widget_event (GtkWidget               *widget,
8819                        GdkEvent        *event,
8820                        struct SnapshotData *data)
8821 {
8822   GtkWidget *res_widget = NULL;
8823
8824   if (!data->in_query)
8825     return FALSE;
8826   
8827   if (event->type == GDK_BUTTON_RELEASE)
8828     {
8829       gtk_grab_remove (widget);
8830       gdk_device_ungrab (gdk_event_get_device (event),
8831                          GDK_CURRENT_TIME);
8832       
8833       res_widget = find_widget_at_pointer (gdk_event_get_device (event));
8834       if (data->is_toplevel && res_widget)
8835         res_widget = gtk_widget_get_toplevel (res_widget);
8836       if (res_widget)
8837         {
8838           cairo_surface_t *surface;
8839           GtkWidget *window, *image;
8840           GdkPixbuf *pixbuf;
8841           int width, height;
8842           cairo_t *cr;
8843
8844           width = gtk_widget_get_allocated_width (res_widget);
8845           height = gtk_widget_get_allocated_height (res_widget);
8846
8847           surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
8848
8849           cr = cairo_create (surface);
8850           gtk_widget_draw (res_widget, cr);
8851           cairo_destroy (cr);
8852
8853           pixbuf = gdk_pixbuf_get_from_surface (surface,
8854                                                 0, 0,
8855                                                 width, height);
8856           cairo_surface_destroy (surface);
8857
8858           window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8859           image = gtk_image_new_from_pixbuf (pixbuf);
8860           g_object_unref (pixbuf);
8861
8862           gtk_container_add (GTK_CONTAINER (window), image);
8863           gtk_widget_show_all (window);
8864         }
8865
8866       data->in_query = FALSE;
8867     }
8868   return FALSE;
8869 }
8870
8871
8872 static void
8873 snapshot_widget (GtkButton *button,
8874                  struct SnapshotData *data)
8875 {
8876   GtkWidget *widget = GTK_WIDGET (button);
8877   GdkDevice *device;
8878
8879   device = gtk_get_current_event_device ();
8880   if (device == NULL)
8881     return;
8882
8883   if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
8884     device = gdk_device_get_associated_device (device);
8885
8886   data->is_toplevel = widget == data->toplevel_button;
8887
8888   if (!data->cursor)
8889     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
8890                                                GDK_TARGET);
8891
8892   gdk_device_grab (device,
8893                    gtk_widget_get_window (widget),
8894                    GDK_OWNERSHIP_APPLICATION,
8895                    TRUE,
8896                    GDK_BUTTON_RELEASE_MASK,
8897                    data->cursor,
8898                    GDK_CURRENT_TIME);
8899
8900   g_signal_connect (button, "event",
8901                     G_CALLBACK (snapshot_widget_event), data);
8902
8903   gtk_grab_add (widget);
8904
8905   data->in_query = TRUE;
8906 }
8907
8908 static void
8909 create_snapshot (GtkWidget *widget)
8910 {
8911   static GtkWidget *window = NULL;
8912   GtkWidget *button;
8913   GtkWidget *vbox;
8914   struct SnapshotData *data;
8915
8916   data = g_new (struct SnapshotData, 1);
8917   data->window = &window;
8918   data->in_query = FALSE;
8919   data->cursor = NULL;
8920   data->handler = 0;
8921
8922   if (!window)
8923     {
8924       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8925
8926       gtk_window_set_screen (GTK_WINDOW (window),
8927                              gtk_widget_get_screen (widget));      
8928
8929       data->handler = g_signal_connect (window, "destroy",
8930                                         G_CALLBACK (destroy_snapshot_data),
8931                                         data);
8932
8933       gtk_window_set_title (GTK_WINDOW (window), "test snapshot");
8934       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
8935
8936       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 1);
8937       gtk_container_add (GTK_CONTAINER (window), vbox);
8938             
8939       button = gtk_button_new_with_label ("Snapshot widget");
8940       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
8941       g_signal_connect (button, "clicked",
8942                         G_CALLBACK (snapshot_widget),
8943                         data);
8944       
8945       button = gtk_button_new_with_label ("Snapshot toplevel");
8946       data->toplevel_button = button;
8947       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
8948       g_signal_connect (button, "clicked",
8949                         G_CALLBACK (snapshot_widget),
8950                         data);
8951     }
8952
8953   if (!gtk_widget_get_visible (window))
8954     gtk_widget_show_all (window);
8955   else
8956     gtk_widget_destroy (window);
8957   
8958 }
8959
8960 /*
8961  * Selection Test
8962  */
8963
8964 void
8965 selection_test_received (GtkWidget        *tree_view,
8966                          GtkSelectionData *selection_data)
8967 {
8968   GtkTreeModel *model;
8969   GtkListStore *store;
8970   GdkAtom *atoms;
8971   int i, l;
8972
8973   if (gtk_selection_data_get_length (selection_data) < 0)
8974     {
8975       g_print ("Selection retrieval failed\n");
8976       return;
8977     }
8978   if (gtk_selection_data_get_data_type (selection_data) != GDK_SELECTION_TYPE_ATOM)
8979     {
8980       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
8981       return;
8982     }
8983
8984   /* Clear out any current list items */
8985
8986   model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
8987   store = GTK_LIST_STORE (model);
8988   gtk_list_store_clear (store);
8989
8990   /* Add new items to list */
8991
8992   gtk_selection_data_get_targets (selection_data,
8993                                   &atoms, &l);
8994
8995   for (i = 0; i < l; i++)
8996     {
8997       char *name;
8998       GtkTreeIter iter;
8999
9000       name = gdk_atom_name (atoms[i]);
9001       if (name != NULL)
9002         {
9003           gtk_list_store_insert_with_values (store, &iter, i, 0, name, -1);
9004           g_free (name);
9005         }
9006       else
9007        gtk_list_store_insert_with_values (store, &iter, i, 0,  "(bad atom)", -1);
9008     }
9009
9010   return;
9011 }
9012
9013 void
9014 selection_test_get_targets (GtkWidget *widget, GtkWidget *tree_view)
9015 {
9016   static GdkAtom targets_atom = GDK_NONE;
9017
9018   if (targets_atom == GDK_NONE)
9019     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
9020
9021   gtk_selection_convert (tree_view, GDK_SELECTION_PRIMARY, targets_atom,
9022                          GDK_CURRENT_TIME);
9023 }
9024
9025 void
9026 create_selection_test (GtkWidget *widget)
9027 {
9028   static GtkWidget *window = NULL;
9029   GtkWidget *action_area, *content_area;
9030   GtkWidget *button;
9031   GtkWidget *vbox;
9032   GtkWidget *scrolled_win;
9033   GtkListStore* store;
9034   GtkWidget *tree_view;
9035   GtkTreeViewColumn *column;
9036   GtkCellRenderer *renderer;
9037   GtkWidget *label;
9038
9039   if (!window)
9040     {
9041       window = gtk_dialog_new ();
9042       
9043       gtk_window_set_screen (GTK_WINDOW (window),
9044                              gtk_widget_get_screen (widget));
9045
9046       g_signal_connect (window, "destroy",
9047                         G_CALLBACK (gtk_widget_destroyed),
9048                         &window);
9049
9050       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9051       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9052
9053       gtk_window_set_title (GTK_WINDOW (window), "Selection Test");
9054       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9055
9056       /* Create the list */
9057
9058       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
9059       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
9060       gtk_box_pack_start (GTK_BOX (content_area), vbox, TRUE, TRUE, 0);
9061
9062       label = gtk_label_new ("Gets available targets for current selection");
9063       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9064
9065       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
9066       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
9067                                       GTK_POLICY_AUTOMATIC, 
9068                                       GTK_POLICY_AUTOMATIC);
9069       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
9070       gtk_widget_set_size_request (scrolled_win, 100, 200);
9071
9072       store = gtk_list_store_new (1, G_TYPE_STRING);
9073       tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
9074       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), tree_view);
9075
9076       renderer = gtk_cell_renderer_text_new ();
9077       column = gtk_tree_view_column_new_with_attributes ("Target", renderer,
9078                                                          "text", 0, NULL);
9079       gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
9080
9081       g_signal_connect (tree_view, "selection_received",
9082                         G_CALLBACK (selection_test_received), NULL);
9083
9084       /* .. And create some buttons */
9085       button = gtk_button_new_with_label ("Get Targets");
9086       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9087
9088       g_signal_connect (button, "clicked",
9089                         G_CALLBACK (selection_test_get_targets), tree_view);
9090
9091       button = gtk_button_new_with_label ("Quit");
9092       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9093
9094       g_signal_connect_swapped (button, "clicked",
9095                                 G_CALLBACK (gtk_widget_destroy),
9096                                 window);
9097     }
9098
9099   if (!gtk_widget_get_visible (window))
9100     gtk_widget_show_all (window);
9101   else
9102     gtk_widget_destroy (window);
9103 }
9104
9105 /*
9106  * Test scrolling
9107  */
9108
9109 static int scroll_test_pos = 0.0;
9110
9111 static gint
9112 scroll_test_draw (GtkWidget     *widget,
9113                   cairo_t       *cr,
9114                   GtkAdjustment *adjustment)
9115 {
9116   gint i,j;
9117   gint imin, imax, jmin, jmax;
9118   GdkRectangle clip;
9119   
9120   gdk_cairo_get_clip_rectangle (cr, &clip);
9121
9122   imin = (clip.x) / 10;
9123   imax = (clip.x + clip.width + 9) / 10;
9124
9125   jmin = ((int)gtk_adjustment_get_value (adjustment) + clip.y) / 10;
9126   jmax = ((int)gtk_adjustment_get_value (adjustment) + clip.y + clip.height + 9) / 10;
9127
9128   for (i=imin; i<imax; i++)
9129     for (j=jmin; j<jmax; j++)
9130       if ((i+j) % 2)
9131         cairo_rectangle (cr, 10*i, 10*j - (int)gtk_adjustment_get_value (adjustment), 1+i%10, 1+j%10);
9132
9133   cairo_fill (cr);
9134
9135   return TRUE;
9136 }
9137
9138 static gint
9139 scroll_test_scroll (GtkWidget *widget, GdkEventScroll *event,
9140                     GtkAdjustment *adjustment)
9141 {
9142   gdouble new_value = gtk_adjustment_get_value (adjustment) + ((event->direction == GDK_SCROLL_UP) ?
9143                                     -gtk_adjustment_get_page_increment (adjustment) / 2:
9144                                     gtk_adjustment_get_page_increment (adjustment) / 2);
9145   new_value = CLAMP (new_value, gtk_adjustment_get_lower (adjustment), gtk_adjustment_get_upper (adjustment) - gtk_adjustment_get_page_size (adjustment));
9146   gtk_adjustment_set_value (adjustment, new_value);  
9147   
9148   return TRUE;
9149 }
9150
9151 static void
9152 scroll_test_configure (GtkWidget *widget, GdkEventConfigure *event,
9153                        GtkAdjustment *adjustment)
9154 {
9155   GtkAllocation allocation;
9156
9157   gtk_widget_get_allocation (widget, &allocation);
9158   gtk_adjustment_configure (adjustment,
9159                             gtk_adjustment_get_value (adjustment),
9160                             gtk_adjustment_get_lower (adjustment),
9161                             gtk_adjustment_get_upper (adjustment),
9162                             0.1 * allocation.height,
9163                             0.9 * allocation.height,
9164                             allocation.height);
9165 }
9166
9167 static void
9168 scroll_test_adjustment_changed (GtkAdjustment *adjustment, GtkWidget *widget)
9169 {
9170   GdkWindow *window;
9171   gint dy;
9172
9173   dy = scroll_test_pos - (int)gtk_adjustment_get_value (adjustment);
9174   scroll_test_pos = gtk_adjustment_get_value (adjustment);
9175
9176   if (!gtk_widget_is_drawable (widget))
9177     return;
9178
9179   window = gtk_widget_get_window (widget);
9180   gdk_window_scroll (window, 0, dy);
9181   gdk_window_process_updates (window, FALSE);
9182 }
9183
9184
9185 void
9186 create_scroll_test (GtkWidget *widget)
9187 {
9188   static GtkWidget *window = NULL;
9189   GtkWidget *action_area, *content_area;
9190   GtkWidget *hbox;
9191   GtkWidget *drawing_area;
9192   GtkWidget *scrollbar;
9193   GtkWidget *button;
9194   GtkAdjustment *adjustment;
9195   GdkGeometry geometry;
9196   GdkWindowHints geometry_mask;
9197
9198   if (!window)
9199     {
9200       window = gtk_dialog_new ();
9201
9202       gtk_window_set_screen (GTK_WINDOW (window),
9203                              gtk_widget_get_screen (widget));
9204
9205       g_signal_connect (window, "destroy",
9206                         G_CALLBACK (gtk_widget_destroyed),
9207                         &window);
9208
9209       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9210       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9211
9212       gtk_window_set_title (GTK_WINDOW (window), "Scroll Test");
9213       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9214
9215       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
9216       gtk_box_pack_start (GTK_BOX (content_area), hbox, TRUE, TRUE, 0);
9217       gtk_widget_show (hbox);
9218
9219       drawing_area = gtk_drawing_area_new ();
9220       gtk_widget_set_size_request (drawing_area, 200, 200);
9221       gtk_box_pack_start (GTK_BOX (hbox), drawing_area, TRUE, TRUE, 0);
9222       gtk_widget_show (drawing_area);
9223
9224       gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK | GDK_SCROLL_MASK);
9225
9226       adjustment = gtk_adjustment_new (0.0, 0.0, 1000.0, 1.0, 180.0, 200.0);
9227       scroll_test_pos = 0.0;
9228
9229       scrollbar = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, adjustment);
9230       gtk_box_pack_start (GTK_BOX (hbox), scrollbar, FALSE, FALSE, 0);
9231       gtk_widget_show (scrollbar);
9232
9233       g_signal_connect (drawing_area, "draw",
9234                         G_CALLBACK (scroll_test_draw), adjustment);
9235       g_signal_connect (drawing_area, "configure_event",
9236                         G_CALLBACK (scroll_test_configure), adjustment);
9237       g_signal_connect (drawing_area, "scroll_event",
9238                         G_CALLBACK (scroll_test_scroll), adjustment);
9239       
9240       g_signal_connect (adjustment, "value_changed",
9241                         G_CALLBACK (scroll_test_adjustment_changed),
9242                         drawing_area);
9243       
9244       /* .. And create some buttons */
9245
9246       button = gtk_button_new_with_label ("Quit");
9247       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9248
9249       g_signal_connect_swapped (button, "clicked",
9250                                 G_CALLBACK (gtk_widget_destroy),
9251                                 window);
9252       gtk_widget_show (button);
9253
9254       /* Set up gridded geometry */
9255
9256       geometry_mask = GDK_HINT_MIN_SIZE | 
9257                        GDK_HINT_BASE_SIZE | 
9258                        GDK_HINT_RESIZE_INC;
9259
9260       geometry.min_width = 20;
9261       geometry.min_height = 20;
9262       geometry.base_width = 0;
9263       geometry.base_height = 0;
9264       geometry.width_inc = 10;
9265       geometry.height_inc = 10;
9266       
9267       gtk_window_set_geometry_hints (GTK_WINDOW (window),
9268                                drawing_area, &geometry, geometry_mask);
9269     }
9270
9271   if (!gtk_widget_get_visible (window))
9272     gtk_widget_show (window);
9273   else
9274     gtk_widget_destroy (window);
9275 }
9276
9277 /*
9278  * Timeout Test
9279  */
9280
9281 static int timer = 0;
9282
9283 gint
9284 timeout_test (GtkWidget *label)
9285 {
9286   static int count = 0;
9287   static char buffer[32];
9288
9289   sprintf (buffer, "count: %d", ++count);
9290   gtk_label_set_text (GTK_LABEL (label), buffer);
9291
9292   return TRUE;
9293 }
9294
9295 void
9296 start_timeout_test (GtkWidget *widget,
9297                     GtkWidget *label)
9298 {
9299   if (!timer)
9300     {
9301       timer = g_timeout_add (100, (GSourceFunc)timeout_test, label);
9302     }
9303 }
9304
9305 void
9306 stop_timeout_test (GtkWidget *widget,
9307                    gpointer   data)
9308 {
9309   if (timer)
9310     {
9311       g_source_remove (timer);
9312       timer = 0;
9313     }
9314 }
9315
9316 void
9317 destroy_timeout_test (GtkWidget  *widget,
9318                       GtkWidget **window)
9319 {
9320   stop_timeout_test (NULL, NULL);
9321
9322   *window = NULL;
9323 }
9324
9325 void
9326 create_timeout_test (GtkWidget *widget)
9327 {
9328   static GtkWidget *window = NULL;
9329   GtkWidget *action_area, *content_area;
9330   GtkWidget *button;
9331   GtkWidget *label;
9332
9333   if (!window)
9334     {
9335       window = gtk_dialog_new ();
9336
9337       gtk_window_set_screen (GTK_WINDOW (window),
9338                              gtk_widget_get_screen (widget));
9339
9340       g_signal_connect (window, "destroy",
9341                         G_CALLBACK (destroy_timeout_test),
9342                         &window);
9343
9344       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9345       action_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9346
9347       gtk_window_set_title (GTK_WINDOW (window), "Timeout Test");
9348       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9349
9350       label = gtk_label_new ("count: 0");
9351       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
9352       gtk_box_pack_start (GTK_BOX (content_area), label, TRUE, TRUE, 0);
9353       gtk_widget_show (label);
9354
9355       button = gtk_button_new_with_label ("close");
9356       g_signal_connect_swapped (button, "clicked",
9357                                 G_CALLBACK (gtk_widget_destroy),
9358                                 window);
9359       gtk_widget_set_can_default (button, TRUE);
9360       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9361       gtk_widget_grab_default (button);
9362       gtk_widget_show (button);
9363
9364       button = gtk_button_new_with_label ("start");
9365       g_signal_connect (button, "clicked",
9366                         G_CALLBACK(start_timeout_test),
9367                         label);
9368       gtk_widget_set_can_default (button, TRUE);
9369       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9370       gtk_widget_show (button);
9371
9372       button = gtk_button_new_with_label ("stop");
9373       g_signal_connect (button, "clicked",
9374                         G_CALLBACK (stop_timeout_test),
9375                         NULL);
9376       gtk_widget_set_can_default (button, TRUE);
9377       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9378       gtk_widget_show (button);
9379     }
9380
9381   if (!gtk_widget_get_visible (window))
9382     gtk_widget_show (window);
9383   else
9384     gtk_widget_destroy (window);
9385 }
9386
9387 /*
9388  * Idle Test
9389  */
9390
9391 static int idle_id = 0;
9392
9393 static gint
9394 idle_test (GtkWidget *label)
9395 {
9396   static int count = 0;
9397   static char buffer[32];
9398
9399   sprintf (buffer, "count: %d", ++count);
9400   gtk_label_set_text (GTK_LABEL (label), buffer);
9401
9402   return TRUE;
9403 }
9404
9405 static void
9406 start_idle_test (GtkWidget *widget,
9407                  GtkWidget *label)
9408 {
9409   if (!idle_id)
9410     {
9411       idle_id = g_idle_add ((GSourceFunc) idle_test, label);
9412     }
9413 }
9414
9415 static void
9416 stop_idle_test (GtkWidget *widget,
9417                 gpointer   data)
9418 {
9419   if (idle_id)
9420     {
9421       g_source_remove (idle_id);
9422       idle_id = 0;
9423     }
9424 }
9425
9426 static void
9427 destroy_idle_test (GtkWidget  *widget,
9428                    GtkWidget **window)
9429 {
9430   stop_idle_test (NULL, NULL);
9431
9432   *window = NULL;
9433 }
9434
9435 static void
9436 toggle_idle_container (GObject *button,
9437                        GtkContainer *container)
9438 {
9439   gtk_container_set_resize_mode (container, GPOINTER_TO_INT (g_object_get_data (button, "user_data")));
9440 }
9441
9442 static void
9443 create_idle_test (GtkWidget *widget)
9444 {
9445   static GtkWidget *window = NULL;
9446   GtkWidget *button;
9447   GtkWidget *label;
9448   GtkWidget *container;
9449
9450   if (!window)
9451     {
9452       GtkWidget *action_area, *content_area;
9453       GtkWidget *button2;
9454       GtkWidget *frame;
9455       GtkWidget *box;
9456
9457       window = gtk_dialog_new ();
9458
9459       gtk_window_set_screen (GTK_WINDOW (window),
9460                              gtk_widget_get_screen (widget));
9461
9462       g_signal_connect (window, "destroy",
9463                         G_CALLBACK (destroy_idle_test),
9464                         &window);
9465
9466       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9467       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9468
9469       gtk_window_set_title (GTK_WINDOW (window), "Idle Test");
9470       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9471
9472       label = gtk_label_new ("count: 0");
9473       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
9474       gtk_widget_show (label);
9475       
9476       container =
9477         g_object_new (GTK_TYPE_HBOX,
9478                         "visible", TRUE,
9479                         /* "GtkContainer::child", g_object_new (GTK_TYPE_HBOX,
9480                          * "GtkWidget::visible", TRUE,
9481                          */
9482                          "child", label,
9483                         /* NULL), */
9484                         NULL);
9485       gtk_box_pack_start (GTK_BOX (content_area), container, TRUE, TRUE, 0);
9486
9487       frame =
9488         g_object_new (GTK_TYPE_FRAME,
9489                         "border_width", 5,
9490                         "label", "Label Container",
9491                         "visible", TRUE,
9492                         "parent", content_area,
9493                         NULL);
9494       box =
9495         g_object_new (GTK_TYPE_VBOX,
9496                         "visible", TRUE,
9497                         "parent", frame,
9498                         NULL);
9499       button =
9500         g_object_connect (g_object_new (GTK_TYPE_RADIO_BUTTON,
9501                                           "label", "Resize-Parent",
9502                                           "user_data", (void*)GTK_RESIZE_PARENT,
9503                                           "visible", TRUE,
9504                                           "parent", box,
9505                                           NULL),
9506                           "signal::clicked", toggle_idle_container, container,
9507                           NULL);
9508       button = g_object_new (GTK_TYPE_RADIO_BUTTON,
9509                                "label", "Resize-Queue",
9510                                "user_data", (void*)GTK_RESIZE_QUEUE,
9511                                "group", button,
9512                                "visible", TRUE,
9513                                "parent", box,
9514                                NULL);
9515       g_object_connect (button,
9516                         "signal::clicked", toggle_idle_container, container,
9517                         NULL);
9518       button2 = g_object_new (GTK_TYPE_RADIO_BUTTON,
9519                                 "label", "Resize-Immediate",
9520                                 "user_data", (void*)GTK_RESIZE_IMMEDIATE,
9521                                 NULL);
9522       g_object_connect (button2,
9523                         "signal::clicked", toggle_idle_container, container,
9524                         NULL);
9525       g_object_set (button2,
9526                     "group", button,
9527                     "visible", TRUE,
9528                     "parent", box,
9529                     NULL);
9530
9531       button = gtk_button_new_with_label ("close");
9532       g_signal_connect_swapped (button, "clicked",
9533                                 G_CALLBACK (gtk_widget_destroy),
9534                                 window);
9535       gtk_widget_set_can_default (button, TRUE);
9536       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9537       gtk_widget_grab_default (button);
9538       gtk_widget_show (button);
9539
9540       button = gtk_button_new_with_label ("start");
9541       g_signal_connect (button, "clicked",
9542                         G_CALLBACK (start_idle_test),
9543                         label);
9544       gtk_widget_set_can_default (button, TRUE);
9545       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9546       gtk_widget_show (button);
9547
9548       button = gtk_button_new_with_label ("stop");
9549       g_signal_connect (button, "clicked",
9550                         G_CALLBACK (stop_idle_test),
9551                         NULL);
9552       gtk_widget_set_can_default (button, TRUE);
9553       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9554       gtk_widget_show (button);
9555     }
9556
9557   if (!gtk_widget_get_visible (window))
9558     gtk_widget_show (window);
9559   else
9560     gtk_widget_destroy (window);
9561 }
9562
9563 /*
9564  * rc file test
9565  */
9566
9567 void
9568 create_rc_file (GtkWidget *widget)
9569 {
9570   static GtkWidget *window = NULL;
9571   GtkWidget *action_area, *content_area;
9572   GtkWidget *button;
9573   GtkWidget *frame;
9574   GtkWidget *vbox;
9575   GtkWidget *label;
9576
9577   if (!window)
9578     {
9579       window = gtk_dialog_new ();
9580
9581       gtk_window_set_screen (GTK_WINDOW (window),
9582                              gtk_widget_get_screen (widget));
9583
9584       g_signal_connect (window, "destroy",
9585                         G_CALLBACK (gtk_widget_destroyed),
9586                         &window);
9587
9588       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9589       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9590
9591       frame = gtk_aspect_frame_new ("Testing RC file prioritization", 0.5, 0.5, 0.0, TRUE);
9592       gtk_box_pack_start (GTK_BOX (content_area), frame, FALSE, FALSE, 0);
9593
9594       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
9595       gtk_container_add (GTK_CONTAINER (frame), vbox);
9596       
9597       label = gtk_label_new ("This label should be red");
9598       gtk_widget_set_name (label, "testgtk-red-label");
9599       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9600
9601       label = gtk_label_new ("This label should be green");
9602       gtk_widget_set_name (label, "testgtk-green-label");
9603       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9604
9605       label = gtk_label_new ("This label should be blue");
9606       gtk_widget_set_name (label, "testgtk-blue-label");
9607       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9608
9609       gtk_window_set_title (GTK_WINDOW (window), "Reload Rc file");
9610       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9611
9612       button = gtk_button_new_with_label ("Reload");
9613       g_signal_connect_swapped (button, "clicked",
9614                                 G_CALLBACK (gtk_style_context_reset_widgets),
9615                                 gtk_widget_get_screen (button));
9616       gtk_widget_set_can_default (button, TRUE);
9617       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9618       gtk_widget_grab_default (button);
9619
9620       button = gtk_button_new_with_label ("Close");
9621       g_signal_connect_swapped (button, "clicked",
9622                                 G_CALLBACK (gtk_widget_destroy),
9623                                 window);
9624       gtk_widget_set_can_default (button, TRUE);
9625       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9626     }
9627
9628   if (!gtk_widget_get_visible (window))
9629     gtk_widget_show_all (window);
9630   else
9631     gtk_widget_destroy (window);
9632 }
9633
9634 /*
9635  * Test of recursive mainloop
9636  */
9637
9638 void
9639 mainloop_destroyed (GtkWidget *w, GtkWidget **window)
9640 {
9641   *window = NULL;
9642   gtk_main_quit ();
9643 }
9644
9645 void
9646 create_mainloop (GtkWidget *widget)
9647 {
9648   static GtkWidget *window = NULL;
9649   GtkWidget *action_area, *content_area;
9650   GtkWidget *label;
9651   GtkWidget *button;
9652
9653   if (!window)
9654     {
9655       window = gtk_dialog_new ();
9656
9657       gtk_window_set_screen (GTK_WINDOW (window),
9658                              gtk_widget_get_screen (widget));
9659
9660       gtk_window_set_title (GTK_WINDOW (window), "Test Main Loop");
9661
9662       g_signal_connect (window, "destroy",
9663                         G_CALLBACK (mainloop_destroyed),
9664                         &window);
9665
9666       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9667       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9668
9669       label = gtk_label_new ("In recursive main loop...");
9670       gtk_misc_set_padding (GTK_MISC(label), 20, 20);
9671
9672       gtk_box_pack_start (GTK_BOX (content_area), label, TRUE, TRUE, 0);
9673       gtk_widget_show (label);
9674
9675       button = gtk_button_new_with_label ("Leave");
9676       gtk_box_pack_start (GTK_BOX (action_area), button, FALSE, TRUE, 0);
9677
9678       g_signal_connect_swapped (button, "clicked",
9679                                 G_CALLBACK (gtk_widget_destroy),
9680                                 window);
9681
9682       gtk_widget_set_can_default (button, TRUE);
9683       gtk_widget_grab_default (button);
9684
9685       gtk_widget_show (button);
9686     }
9687
9688   if (!gtk_widget_get_visible (window))
9689     {
9690       gtk_widget_show (window);
9691
9692       g_print ("create_mainloop: start\n");
9693       gtk_main ();
9694       g_print ("create_mainloop: done\n");
9695     }
9696   else
9697     gtk_widget_destroy (window);
9698 }
9699
9700 static gboolean
9701 layout_draw_handler (GtkWidget *widget, cairo_t *cr)
9702 {
9703   GtkLayout *layout;
9704   GdkWindow *bin_window;
9705   GdkRectangle clip;
9706   gint i,j,x,y;
9707   gint imin, imax, jmin, jmax;
9708
9709   layout = GTK_LAYOUT (widget);
9710   bin_window = gtk_layout_get_bin_window (layout);
9711
9712   if (!gtk_cairo_should_draw_window (cr, bin_window))
9713     return FALSE;
9714   
9715   gdk_window_get_position (bin_window, &x, &y);
9716   cairo_translate (cr, x, y);
9717
9718   gdk_cairo_get_clip_rectangle (cr, &clip);
9719
9720   imin = (clip.x) / 10;
9721   imax = (clip.x + clip.width + 9) / 10;
9722
9723   jmin = (clip.y) / 10;
9724   jmax = (clip.y + clip.height + 9) / 10;
9725
9726   for (i=imin; i<imax; i++)
9727     for (j=jmin; j<jmax; j++)
9728       if ((i+j) % 2)
9729         cairo_rectangle (cr,
9730                          10*i, 10*j, 
9731                          1+i%10, 1+j%10);
9732   
9733   cairo_fill (cr);
9734
9735   return FALSE;
9736 }
9737
9738 void create_layout (GtkWidget *widget)
9739 {
9740   GtkAdjustment *hadjustment, *vadjustment;
9741   GtkLayout *layout;
9742   static GtkWidget *window = NULL;
9743   GtkWidget *layout_widget;
9744   GtkWidget *scrolledwindow;
9745   GtkWidget *button;
9746
9747   if (!window)
9748     {
9749       gchar buf[16];
9750
9751       gint i, j;
9752       
9753       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9754       gtk_window_set_screen (GTK_WINDOW (window),
9755                              gtk_widget_get_screen (widget));
9756
9757       g_signal_connect (window, "destroy",
9758                         G_CALLBACK (gtk_widget_destroyed),
9759                         &window);
9760
9761       gtk_window_set_title (GTK_WINDOW (window), "Layout");
9762       gtk_widget_set_size_request (window, 200, 200);
9763
9764       scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
9765       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
9766                                            GTK_SHADOW_IN);
9767       gtk_scrolled_window_set_placement (GTK_SCROLLED_WINDOW (scrolledwindow),
9768                                          GTK_CORNER_TOP_RIGHT);
9769
9770       gtk_container_add (GTK_CONTAINER (window), scrolledwindow);
9771
9772       layout_widget = gtk_layout_new (NULL, NULL);
9773       layout = GTK_LAYOUT (layout_widget);
9774       gtk_container_add (GTK_CONTAINER (scrolledwindow), layout_widget);
9775
9776       /* We set step sizes here since GtkLayout does not set
9777        * them itself.
9778        */
9779       hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (layout));
9780       vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (layout));
9781       gtk_adjustment_set_step_increment (hadjustment, 10.0);
9782       gtk_adjustment_set_step_increment (vadjustment, 10.0);
9783       gtk_scrollable_set_hadjustment (GTK_SCROLLABLE (layout), hadjustment);
9784       gtk_scrollable_set_vadjustment (GTK_SCROLLABLE (layout), vadjustment);
9785
9786       gtk_widget_set_events (layout_widget, GDK_EXPOSURE_MASK);
9787       g_signal_connect (layout, "draw",
9788                         G_CALLBACK (layout_draw_handler), NULL);
9789
9790       gtk_layout_set_size (layout, 1600, 128000);
9791
9792       for (i=0 ; i < 16 ; i++)
9793         for (j=0 ; j < 16 ; j++)
9794           {
9795             sprintf(buf, "Button %d, %d", i, j);
9796             if ((i + j) % 2)
9797               button = gtk_button_new_with_label (buf);
9798             else
9799               button = gtk_label_new (buf);
9800
9801             gtk_layout_put (layout, button, j*100, i*100);
9802           }
9803
9804       for (i=16; i < 1280; i++)
9805         {
9806           sprintf(buf, "Button %d, %d", i, 0);
9807           if (i % 2)
9808             button = gtk_button_new_with_label (buf);
9809           else
9810             button = gtk_label_new (buf);
9811
9812           gtk_layout_put (layout, button, 0, i*100);
9813         }
9814     }
9815
9816   if (!gtk_widget_get_visible (window))
9817     gtk_widget_show_all (window);
9818   else
9819     gtk_widget_destroy (window);
9820 }
9821
9822 #if 0
9823 /* FIXME: need to completely redo this for GtkStyleContext */
9824 void
9825 create_styles (GtkWidget *widget)
9826 {
9827   static GtkWidget *window = NULL;
9828   GtkWidget *content_area, *action_area;
9829   GtkWidget *label;
9830   GtkWidget *button;
9831   GtkWidget *entry;
9832   GtkWidget *vbox;
9833   static GdkRGBA red =    { 1,0,0,1 };
9834   static GdkRGBA green =  { 0,1,0,1 };
9835   static GdkRGBA blue =   { 0,0,1,1 };
9836   static GdkRGBA yellow = { 1,1,0,1 };
9837   static GdkRGBA cyan =   { 0,1,1,1 };
9838   PangoFontDescription *font_desc;
9839
9840   GtkRcStyle *rc_style;
9841
9842   if (!window)
9843     {
9844       window = gtk_dialog_new ();
9845       gtk_window_set_screen (GTK_WINDOW (window),
9846                              gtk_widget_get_screen (widget));
9847      
9848       g_signal_connect (window, "destroy",
9849                         G_CALLBACK (gtk_widget_destroyed),
9850                         &window);
9851
9852       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9853       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9854
9855       button = gtk_button_new_with_label ("Close");
9856       g_signal_connect_swapped (button, "clicked",
9857                                 G_CALLBACK (gtk_widget_destroy),
9858                                 window);
9859       gtk_widget_set_can_default (button, TRUE);
9860       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9861       gtk_widget_show (button);
9862
9863       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
9864       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
9865       gtk_box_pack_start (GTK_BOX (content_area), vbox, FALSE, FALSE, 0);
9866       
9867       label = gtk_label_new ("Font:");
9868       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
9869       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9870
9871       font_desc = pango_font_description_from_string ("Helvetica,Sans Oblique 18");
9872
9873       button = gtk_button_new_with_label ("Some Text");
9874       gtk_widget_override_font (gtk_bin_get_child (GTK_BIN (button)), font_desc);
9875       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9876
9877       label = gtk_label_new ("Foreground:");
9878       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
9879       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9880
9881       button = gtk_button_new_with_label ("Some Text");
9882       gtk_widget_override_color (gtk_bin_get_child (GTK_BIN (button)), 0, &red);
9883       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9884
9885       label = gtk_label_new ("Background:");
9886       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
9887       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9888
9889       button = gtk_button_new_with_label ("Some Text");
9890       gtk_widget_override_background_color (button, 0, &green);
9891       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9892
9893       label = gtk_label_new ("Text:");
9894       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
9895       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9896
9897       entry = gtk_entry_new ();
9898       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
9899       gtk_widget_override_color (entry, 0, &blue);
9900       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
9901
9902       label = gtk_label_new ("Base:");
9903       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
9904       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9905
9906       entry = gtk_entry_new ();
9907       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
9908       gtk_widget_override_background_color (entry, 0, &yellow);
9909       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
9910
9911       label = gtk_label_new ("Cursor:");
9912       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
9913       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9914
9915       entry = gtk_entry_new ();
9916       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
9917       gtk_widget_modify_cursor (entry, &red, &red);
9918       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
9919
9920       label = gtk_label_new ("Multiple:");
9921       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
9922       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9923
9924       button = gtk_button_new_with_label ("Some Text");
9925
9926       rc_style = gtk_rc_style_new ();
9927
9928       rc_style->font_desc = pango_font_description_copy (font_desc);
9929       rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG | GTK_RC_BG;
9930       rc_style->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_FG | GTK_RC_BG;
9931       rc_style->color_flags[GTK_STATE_ACTIVE] = GTK_RC_FG | GTK_RC_BG;
9932       rc_style->fg[GTK_STATE_NORMAL] = yellow;
9933       rc_style->bg[GTK_STATE_NORMAL] = blue;
9934       rc_style->fg[GTK_STATE_PRELIGHT] = blue;
9935       rc_style->bg[GTK_STATE_PRELIGHT] = yellow;
9936       rc_style->fg[GTK_STATE_ACTIVE] = red;
9937       rc_style->bg[GTK_STATE_ACTIVE] = cyan;
9938       rc_style->xthickness = 5;
9939       rc_style->ythickness = 5;
9940
9941       gtk_widget_modify_style (button, rc_style);
9942       gtk_widget_modify_style (gtk_bin_get_child (GTK_BIN (button)), rc_style);
9943
9944       g_object_unref (rc_style);
9945       
9946       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9947     }
9948   
9949   if (!gtk_widget_get_visible (window))
9950     gtk_widget_show_all (window);
9951   else
9952     gtk_widget_destroy (window);
9953 }
9954 #endif
9955
9956 /*
9957  * Main Window and Exit
9958  */
9959
9960 void
9961 do_exit (GtkWidget *widget, GtkWidget *window)
9962 {
9963   gtk_widget_destroy (window);
9964   gtk_main_quit ();
9965 }
9966
9967 struct {
9968   char *label;
9969   void (*func) (GtkWidget *widget);
9970   gboolean do_not_benchmark;
9971 } buttons[] =
9972 {
9973   { "alpha window", create_alpha_window },
9974   { "big windows", create_big_windows },
9975   { "button box", create_button_box },
9976   { "buttons", create_buttons },
9977   { "check buttons", create_check_buttons },
9978   { "color selection", create_color_selection },
9979   { "composited window", create_composited_window },
9980   { "cursors", create_cursors },
9981   { "dialog", create_dialog },
9982   { "display & screen", create_display_screen, TRUE },
9983   { "entry", create_entry },
9984   { "event box", create_event_box },
9985   { "event watcher", create_event_watcher },
9986   { "expander", create_expander },
9987   { "flipping", create_flipping },
9988   { "focus", create_focus },
9989   { "font selection", create_font_selection },
9990   { "handle box", create_handle_box },
9991   { "image", create_image },
9992   { "key lookup", create_key_lookup },
9993   { "labels", create_labels },
9994   { "layout", create_layout },
9995   { "menus", create_menus },
9996   { "message dialog", create_message_dialog },
9997   { "modal window", create_modal_window, TRUE },
9998   { "notebook", create_notebook },
9999   { "panes", create_panes },
10000   { "paned keyboard", create_paned_keyboard_navigation },
10001   { "pixbuf", create_pixbuf },
10002   { "progress bar", create_progress_bar },
10003   { "properties", create_properties },
10004   { "radio buttons", create_radio_buttons },
10005   { "range controls", create_range_controls },
10006   { "rc file", create_rc_file },
10007   { "reparent", create_reparent },
10008   { "resize grips", create_resize_grips },
10009   { "rotated label", create_rotated_label },
10010   { "rotated text", create_rotated_text },
10011   { "saved position", create_saved_position },
10012   { "scrolled windows", create_scrolled_windows },
10013   { "shapes", create_shapes },
10014   { "size groups", create_size_groups },
10015   { "snapshot", create_snapshot },
10016   { "spinbutton", create_spins },
10017   { "statusbar", create_statusbar },
10018 #if 0
10019   { "styles", create_styles },
10020 #endif
10021   { "test idle", create_idle_test },
10022   { "test mainloop", create_mainloop, TRUE },
10023   { "test scrolling", create_scroll_test },
10024   { "test selection", create_selection_test },
10025   { "test timeout", create_timeout_test },
10026   { "toggle buttons", create_toggle_buttons },
10027   { "toolbar", create_toolbar },
10028   { "tooltips", create_tooltips },
10029   { "WM hints", create_wmhints },
10030   { "window sizing", create_window_sizing },
10031   { "window states", create_window_states }
10032 };
10033 int nbuttons = sizeof (buttons) / sizeof (buttons[0]);
10034
10035 void
10036 create_main_window (void)
10037 {
10038   GtkWidget *window;
10039   GtkWidget *box1;
10040   GtkWidget *box2;
10041   GtkWidget *scrolled_window;
10042   GtkWidget *button;
10043   GtkWidget *label;
10044   gchar buffer[64];
10045   GtkWidget *separator;
10046   GdkGeometry geometry;
10047   int i;
10048
10049   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10050   gtk_widget_set_name (window, "main_window");
10051   gtk_window_move (GTK_WINDOW (window), 50, 20);
10052   gtk_window_set_default_size (GTK_WINDOW (window), -1, 400);
10053
10054   geometry.min_width = -1;
10055   geometry.min_height = -1;
10056   geometry.max_width = -1;
10057   geometry.max_height = G_MAXSHORT;
10058   gtk_window_set_geometry_hints (GTK_WINDOW (window), NULL,
10059                                  &geometry,
10060                                  GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
10061
10062   g_signal_connect (window, "destroy",
10063                     G_CALLBACK (gtk_main_quit),
10064                     NULL);
10065   g_signal_connect (window, "delete-event",
10066                     G_CALLBACK (gtk_false),
10067                     NULL);
10068
10069   box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
10070   gtk_container_add (GTK_CONTAINER (window), box1);
10071
10072   if (gtk_micro_version > 0)
10073     sprintf (buffer,
10074              "Gtk+ v%d.%d.%d",
10075              gtk_get_major_version (),
10076              gtk_get_minor_version (),
10077              gtk_get_micro_version ());
10078   else
10079     sprintf (buffer,
10080              "Gtk+ v%d.%d",
10081              gtk_get_major_version (),
10082              gtk_get_minor_version ());
10083
10084   label = gtk_label_new (buffer);
10085   gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
10086   gtk_widget_set_name (label, "testgtk-version-label");
10087
10088   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
10089   gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
10090   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
10091                                   GTK_POLICY_NEVER, 
10092                                   GTK_POLICY_AUTOMATIC);
10093   gtk_box_pack_start (GTK_BOX (box1), scrolled_window, TRUE, TRUE, 0);
10094
10095   box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
10096   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10097   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), box2);
10098   gtk_container_set_focus_vadjustment (GTK_CONTAINER (box2),
10099                                        gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
10100   gtk_widget_show (box2);
10101
10102   for (i = 0; i < nbuttons; i++)
10103     {
10104       button = gtk_button_new_with_label (buttons[i].label);
10105       if (buttons[i].func)
10106         g_signal_connect (button, 
10107                           "clicked", 
10108                           G_CALLBACK(buttons[i].func),
10109                           NULL);
10110       else
10111         gtk_widget_set_sensitive (button, FALSE);
10112       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10113     }
10114
10115   separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
10116   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
10117
10118   box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
10119   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10120   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
10121
10122   button = gtk_button_new_with_mnemonic ("_Close");
10123   g_signal_connect (button, "clicked",
10124                     G_CALLBACK (do_exit),
10125                     window);
10126   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10127   gtk_widget_set_can_default (button, TRUE);
10128   gtk_widget_grab_default (button);
10129
10130   gtk_widget_show_all (window);
10131 }
10132
10133 static void
10134 test_init (void)
10135 {
10136   if (g_file_test ("../modules/input/immodules.cache", G_FILE_TEST_EXISTS))
10137     g_setenv ("GTK_IM_MODULE_FILE", "../modules/input/immodules.cache", TRUE);
10138 }
10139
10140 static char *
10141 pad (const char *str, int to)
10142 {
10143   static char buf[256];
10144   int len = strlen (str);
10145   int i;
10146
10147   for (i = 0; i < to; i++)
10148     buf[i] = ' ';
10149
10150   buf[to] = '\0';
10151
10152   memcpy (buf, str, len);
10153
10154   return buf;
10155 }
10156
10157 static void
10158 bench_iteration (GtkWidget *widget, void (* fn) (GtkWidget *widget))
10159 {
10160   fn (widget); /* on */
10161   while (g_main_context_iteration (NULL, FALSE));
10162   fn (widget); /* off */
10163   while (g_main_context_iteration (NULL, FALSE));
10164 }
10165
10166 void
10167 do_real_bench (GtkWidget *widget, void (* fn) (GtkWidget *widget), char *name, int num)
10168 {
10169   GTimeVal tv0, tv1;
10170   double dt_first;
10171   double dt;
10172   int n;
10173   static gboolean printed_headers = FALSE;
10174
10175   if (!printed_headers) {
10176     g_print ("Test                 Iters      First      Other\n");
10177     g_print ("-------------------- ----- ---------- ----------\n");
10178     printed_headers = TRUE;
10179   }
10180
10181   g_get_current_time (&tv0);
10182   bench_iteration (widget, fn); 
10183   g_get_current_time (&tv1);
10184
10185   dt_first = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
10186         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
10187
10188   g_get_current_time (&tv0);
10189   for (n = 0; n < num - 1; n++)
10190     bench_iteration (widget, fn); 
10191   g_get_current_time (&tv1);
10192   dt = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
10193         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
10194
10195   g_print ("%s %5d ", pad (name, 20), num);
10196   if (num > 1)
10197     g_print ("%10.1f %10.1f\n", dt_first, dt/(num-1));
10198   else
10199     g_print ("%10.1f\n", dt_first);
10200 }
10201
10202 void
10203 do_bench (char* what, int num)
10204 {
10205   int i;
10206   GtkWidget *widget;
10207   void (* fn) (GtkWidget *widget);
10208   fn = NULL;
10209   widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10210
10211   if (g_ascii_strcasecmp (what, "ALL") == 0)
10212     {
10213       for (i = 0; i < nbuttons; i++)
10214         {
10215           if (!buttons[i].do_not_benchmark)
10216             do_real_bench (widget, buttons[i].func, buttons[i].label, num);
10217         }
10218
10219       return;
10220     }
10221   else
10222     {
10223       for (i = 0; i < nbuttons; i++)
10224         {
10225           if (strcmp (buttons[i].label, what) == 0)
10226             {
10227               fn = buttons[i].func;
10228               break;
10229             }
10230         }
10231       
10232       if (!fn)
10233         g_print ("Can't bench: \"%s\" not found.\n", what);
10234       else
10235         do_real_bench (widget, fn, buttons[i].label, num);
10236     }
10237 }
10238
10239 void 
10240 usage (void)
10241 {
10242   fprintf (stderr, "Usage: testgtk [--bench ALL|<bench>[:<count>]]\n");
10243   exit (1);
10244 }
10245
10246 int
10247 main (int argc, char *argv[])
10248 {
10249   GtkCssProvider *provider, *memory_provider;
10250   GdkDisplay *display;
10251   GdkScreen *screen;
10252   GtkBindingSet *binding_set;
10253   int i;
10254   gboolean done_benchmarks = FALSE;
10255
10256   srand (time (NULL));
10257
10258   test_init ();
10259
10260   g_set_application_name ("GTK+ Test Program");
10261
10262   gtk_init (&argc, &argv);
10263
10264   provider = gtk_css_provider_new ();
10265
10266   /* Check to see if we are being run from the correct
10267    * directory.
10268    */
10269   if (file_exists ("testgtk.css"))
10270     gtk_css_provider_load_from_path (provider, "testgtk.css", NULL);
10271   else if (file_exists ("tests/testgtk.css"))
10272     gtk_css_provider_load_from_path (provider, "tests/testgtk.css", NULL);
10273   else
10274     g_warning ("Couldn't find file \"testgtk.css\".");
10275
10276   display = gdk_display_get_default ();
10277   screen = gdk_display_get_default_screen (display);
10278
10279   gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER (provider),
10280                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
10281   g_object_unref (provider);
10282
10283   gtk_accelerator_set_default_mod_mask (GDK_SHIFT_MASK |
10284                                         GDK_CONTROL_MASK |
10285                                         GDK_MOD1_MASK | 
10286                                         GDK_META_MASK |
10287                                         GDK_SUPER_MASK |
10288                                         GDK_HYPER_MASK |
10289                                         GDK_MOD4_MASK);
10290   /*  benchmarking
10291    */
10292   for (i = 1; i < argc; i++)
10293     {
10294       if (strncmp (argv[i], "--bench", strlen("--bench")) == 0)
10295         {
10296           int num = 1;
10297           char *nextarg;
10298           char *what;
10299           char *count;
10300           
10301           nextarg = strchr (argv[i], '=');
10302           if (nextarg)
10303             nextarg++;
10304           else
10305             {
10306               i++;
10307               if (i == argc)
10308                 usage ();
10309               nextarg = argv[i];
10310             }
10311
10312           count = strchr (nextarg, ':');
10313           if (count)
10314             {
10315               what = g_strndup (nextarg, count - nextarg);
10316               count++;
10317               num = atoi (count);
10318               if (num <= 0)
10319                 usage ();
10320             }
10321           else
10322             what = g_strdup (nextarg);
10323
10324           do_bench (what, num ? num : 1);
10325           done_benchmarks = TRUE;
10326         }
10327       else
10328         usage ();
10329     }
10330   if (done_benchmarks)
10331     return 0;
10332
10333   /* bindings test
10334    */
10335   binding_set = gtk_binding_set_by_class (g_type_class_ref (GTK_TYPE_WIDGET));
10336   gtk_binding_entry_add_signal (binding_set,
10337                                 '9', GDK_CONTROL_MASK | GDK_RELEASE_MASK,
10338                                 "debug_msg",
10339                                 1,
10340                                 G_TYPE_STRING, "GtkWidgetClass <ctrl><release>9 test");
10341
10342   memory_provider = gtk_css_provider_new ();
10343   gtk_css_provider_load_from_data (memory_provider,
10344                                    "#testgtk-version-label {\n"
10345                                    "  color: #f00;\n"
10346                                    "  font: Sans 18;\n"
10347                                    "}",
10348                                    -1, NULL);
10349   gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER (memory_provider),
10350                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + 1);
10351
10352   create_main_window ();
10353
10354   gtk_main ();
10355
10356   if (1)
10357     {
10358       while (g_main_context_pending (NULL))
10359         g_main_context_iteration (NULL, FALSE);
10360 #if 0
10361       sleep (1);
10362       while (g_main_context_pending (NULL))
10363         g_main_context_iteration (NULL, FALSE);
10364 #endif
10365     }
10366   return 0;
10367 }