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