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