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