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