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