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