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