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