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