]> Pileus Git - ~andy/gtk/blob - tests/testgtk.c
testgtk: Move paned example from GtkTable to GtkGrid
[~andy/gtk] / tests / testgtk.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27
28 #include "config.h"
29
30 #undef  G_LOG_DOMAIN
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <sys/stat.h>
36 #include <math.h>
37 #include <time.h>
38 #ifdef HAVE_UNISTD_H
39 #include <unistd.h>
40 #endif
41
42 #include "gtk/gtk.h"
43 #include "gdk/gdk.h"
44 #include "gdk/gdkkeysyms.h"
45
46 #ifdef G_OS_WIN32
47 #define sleep(n) _sleep(n)
48 #endif
49
50 #include "prop-editor.h"
51
52 #include "test.xpm"
53
54 gboolean
55 file_exists (const char *filename)
56 {
57   struct stat statbuf;
58
59   return stat (filename, &statbuf) == 0;
60 }
61
62 GtkWidget *
63 shape_create_icon (GdkScreen *screen,
64                    char      *xpm_file,
65                    gint       x,
66                    gint       y,
67                    gint       px,
68                    gint       py,
69                    gint       window_type);
70
71 static GtkWidget *
72 build_option_menu (gchar           *items[],
73                    gint             num_items,
74                    gint             history,
75                    void           (*func) (GtkWidget *widget, gpointer data),
76                    gpointer         data);
77
78 /* macro, structure and variables used by tree window demos */
79 #define DEFAULT_NUMBER_OF_ITEM  3
80 #define DEFAULT_RECURSION_LEVEL 3
81
82 struct {
83   GSList* selection_mode_group;
84   GtkWidget* single_button;
85   GtkWidget* browse_button;
86   GtkWidget* multiple_button;
87   GtkWidget* draw_line_button;
88   GtkWidget* view_line_button;
89   GtkWidget* no_root_item_button;
90   GtkWidget* nb_item_spinner;
91   GtkWidget* recursion_spinner;
92 } sTreeSampleSelection;
93
94 typedef struct sTreeButtons {
95   guint nb_item_add;
96   GtkWidget* add_button;
97   GtkWidget* remove_button;
98   GtkWidget* subtree_button;
99 } sTreeButtons;
100 /* end of tree section */
101
102 static GtkWidget *
103 build_option_menu (gchar           *items[],
104                    gint             num_items,
105                    gint             history,
106                    void           (*func)(GtkWidget *widget, gpointer data),
107                    gpointer         data)
108 {
109   GtkWidget *omenu;
110   gint i;
111
112   omenu = gtk_combo_box_text_new ();
113   g_signal_connect (omenu, "changed",
114                     G_CALLBACK (func), data);
115       
116   for (i = 0; i < num_items; i++)
117       gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (omenu), items[i]);
118
119   gtk_combo_box_set_active (GTK_COMBO_BOX (omenu), history);
120   
121   return omenu;
122 }
123
124 /*
125  * Windows with an alpha channel
126  */
127
128
129 static gboolean
130 on_alpha_window_draw (GtkWidget *widget,
131                       cairo_t   *cr)
132 {
133   cairo_pattern_t *pattern;
134   int radius, width, height;
135
136   width = gtk_widget_get_allocated_width (widget);
137   height = gtk_widget_get_allocated_height (widget);
138   radius = MIN (width, height) / 2;
139   pattern = cairo_pattern_create_radial (width / 2,
140                                          height / 2,
141                                          0.0,
142                                          width / 2,
143                                          height / 2,
144                                          radius * 1.33);
145
146   if (gdk_screen_get_rgba_visual (gtk_widget_get_screen (widget)) &&
147       gtk_widget_is_composited (widget))
148     cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0); /* transparent */
149   else
150     cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* opaque white */
151     
152   cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
153   cairo_paint (cr);
154   
155   cairo_pattern_add_color_stop_rgba (pattern, 0.0,
156                                      1.0, 0.75, 0.0, 1.0); /* solid orange */
157   cairo_pattern_add_color_stop_rgba (pattern, 1.0,
158                                      1.0, 0.75, 0.0, 0.0); /* transparent orange */
159
160   cairo_set_source (cr, pattern);
161   cairo_pattern_destroy (pattern);
162   
163   cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
164   cairo_paint (cr);
165
166   return FALSE;
167 }
168
169 static GtkWidget *
170 build_alpha_widgets (void)
171 {
172   GtkWidget *grid;
173   GtkWidget *radio_button;
174   GtkWidget *check_button;
175   GtkWidget *hbox;
176   GtkWidget *label;
177   GtkWidget *entry;
178
179   grid = gtk_grid_new ();
180
181   radio_button = gtk_radio_button_new_with_label (NULL, "Red");
182   gtk_widget_set_hexpand (radio_button, TRUE);
183   gtk_grid_attach (GTK_GRID (grid), radio_button, 0, 0, 1, 1);
184
185   radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Green");
186   gtk_widget_set_hexpand (radio_button, TRUE);
187   gtk_grid_attach (GTK_GRID (grid), radio_button, 0, 1, 1, 1);
188
189   radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Blue"),
190   gtk_widget_set_hexpand (radio_button, TRUE);
191   gtk_grid_attach (GTK_GRID (grid), radio_button, 0, 2, 1, 1);
192
193   check_button = gtk_check_button_new_with_label ("Sedentary"),
194   gtk_widget_set_hexpand (check_button, TRUE);
195   gtk_grid_attach (GTK_GRID (grid), check_button, 1, 0, 1, 1);
196
197   check_button = gtk_check_button_new_with_label ("Nocturnal"),
198   gtk_widget_set_hexpand (check_button, TRUE);
199   gtk_grid_attach (GTK_GRID (grid), check_button, 1, 1, 1, 1);
200
201   check_button = gtk_check_button_new_with_label ("Compulsive"),
202   gtk_widget_set_hexpand (check_button, TRUE);
203   gtk_grid_attach (GTK_GRID (grid), check_button, 1, 2, 1, 1);
204
205   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
206   label = gtk_label_new (NULL);
207   gtk_label_set_markup (GTK_LABEL (label), "<i>Entry: </i>");
208   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
209   entry = gtk_entry_new ();
210   gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
211   gtk_widget_set_hexpand (hbox, TRUE);
212   gtk_grid_attach (GTK_GRID (grid), hbox, 0, 3, 2, 1);
213   
214   return grid;
215 }
216
217 static void
218 on_alpha_screen_changed (GtkWindow *window,
219                          GdkScreen *old_screen,
220                          GtkWidget *label)
221 {
222   GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (window));
223   GdkVisual *visual = gdk_screen_get_rgba_visual (screen);
224
225   if (!visual)
226     {
227       visual = gdk_screen_get_system_visual (screen);
228       gtk_label_set_markup (GTK_LABEL (label), "<b>Screen doesn't support alpha</b>");
229     }
230   else
231     {
232       gtk_label_set_markup (GTK_LABEL (label), "<b>Screen supports alpha</b>");
233     }
234
235   gtk_widget_set_visual (GTK_WIDGET (window), visual);
236 }
237
238 static void
239 on_composited_changed (GtkWidget *window,
240                       GtkLabel *label)
241 {
242   gboolean is_composited = gtk_widget_is_composited (window);
243
244   if (is_composited)
245     gtk_label_set_text (label, "Composited");
246   else
247     gtk_label_set_text (label, "Not composited");
248 }
249
250 void
251 create_alpha_window (GtkWidget *widget)
252 {
253   static GtkWidget *window;
254
255   if (!window)
256     {
257       GtkWidget *content_area;
258       GtkWidget *vbox;
259       GtkWidget *label;
260       
261       window = gtk_dialog_new_with_buttons ("Alpha Window",
262                                             GTK_WINDOW (gtk_widget_get_toplevel (widget)), 0,
263                                             GTK_STOCK_CLOSE, 0,
264                                             NULL);
265
266       gtk_widget_set_app_paintable (window, TRUE);
267       g_signal_connect (window, "draw",
268                         G_CALLBACK (on_alpha_window_draw), NULL);
269
270       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
271       
272       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8);
273       gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
274       gtk_box_pack_start (GTK_BOX (content_area), vbox,
275                           TRUE, TRUE, 0);
276
277       label = gtk_label_new (NULL);
278       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
279       on_alpha_screen_changed (GTK_WINDOW (window), NULL, label);
280       g_signal_connect (window, "screen-changed",
281                         G_CALLBACK (on_alpha_screen_changed), label);
282       
283       label = gtk_label_new (NULL);
284       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
285       on_composited_changed (window, GTK_LABEL (label));
286       g_signal_connect (window, "composited_changed", G_CALLBACK (on_composited_changed), label);
287       
288       gtk_box_pack_start (GTK_BOX (vbox), build_alpha_widgets (), TRUE, TRUE, 0);
289
290       g_signal_connect (window, "destroy",
291                         G_CALLBACK (gtk_widget_destroyed),
292                         &window);
293       
294       g_signal_connect (window, "response",
295                         G_CALLBACK (gtk_widget_destroy),
296                         NULL); 
297     }
298
299   if (!gtk_widget_get_visible (window))
300     gtk_widget_show_all (window);
301   else
302     gtk_widget_destroy (window);
303 }
304
305 /*
306  * Composited non-toplevel window
307  */
308
309 /* The draw event handler for the event box.
310  *
311  * This function simply draws a transparency onto a widget on the area
312  * for which it receives expose events.  This is intended to give the
313  * event box a "transparent" background.
314  *
315  * In order for this to work properly, the widget must have an RGBA
316  * colourmap.  The widget should also be set as app-paintable since it
317  * doesn't make sense for GTK to draw a background if we are drawing it
318  * (and because GTK might actually replace our transparency with its
319  * default background colour).
320  */
321 static gboolean
322 transparent_draw (GtkWidget *widget,
323                   cairo_t   *cr)
324 {
325   cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
326   cairo_paint (cr);
327
328   return FALSE;
329 }
330
331 /* The expose event handler for the window.
332  *
333  * This function performs the actual compositing of the event box onto
334  * the already-existing background of the window at 50% normal opacity.
335  *
336  * In this case we do not want app-paintable to be set on the widget
337  * since we want it to draw its own (red) background.  Because of this,
338  * however, we must ensure that we use g_signal_register_after so that
339  * this handler is called after the red has been drawn.  If it was
340  * called before then GTK would just blindly paint over our work.
341  */
342 static gboolean
343 window_draw (GtkWidget *widget,
344              cairo_t   *cr)
345 {
346   GtkAllocation allocation;
347   GtkWidget *child;
348
349   /* get our child (in this case, the event box) */ 
350   child = gtk_bin_get_child (GTK_BIN (widget));
351
352   gtk_widget_get_allocation (child, &allocation);
353
354   /* the source data is the (composited) event box */
355   gdk_cairo_set_source_window (cr, gtk_widget_get_window (child),
356                                allocation.x,
357                                allocation.y);
358
359   /* composite, with a 50% opacity */
360   cairo_paint_with_alpha (cr, 0.5);
361
362   return FALSE;
363 }
364
365 void
366 create_composited_window (GtkWidget *widget)
367 {
368   static GtkWidget *window;
369
370   if (!window)
371     {
372       GtkWidget *event, *button;
373       GdkRGBA red;
374
375       /* make the widgets */
376       button = gtk_button_new_with_label ("A Button");
377       event = gtk_event_box_new ();
378       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
379
380       g_signal_connect (window, "destroy",
381                         G_CALLBACK (gtk_widget_destroyed),
382                         &window);
383
384       /* put a red background on the window */
385       gdk_rgba_parse (&red, "red");
386       gtk_widget_override_background_color (window, 0, &red);
387
388       /* set our event box to have a fully-transparent background
389        * drawn on it.  currently there is no way to simply tell gtk
390        * that "transparency" is the background colour for a widget.
391        */
392       gtk_widget_set_app_paintable (GTK_WIDGET (event), TRUE);
393       g_signal_connect (event, "draw",
394                         G_CALLBACK (transparent_draw), NULL);
395
396       /* put them inside one another */
397       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
398       gtk_container_add (GTK_CONTAINER (window), event);
399       gtk_container_add (GTK_CONTAINER (event), button);
400
401       /* realise and show everything */
402       gtk_widget_realize (button);
403
404       /* set the event box GdkWindow to be composited.
405        * obviously must be performed after event box is realised.
406        */
407       gdk_window_set_composited (gtk_widget_get_window (event),
408                                  TRUE);
409
410       /* set up the compositing handler.
411        * note that we do _after so that the normal (red) background is drawn
412        * by gtk before our compositing occurs.
413        */
414       g_signal_connect_after (window, "draw",
415                               G_CALLBACK (window_draw), NULL);
416     }
417
418   if (!gtk_widget_get_visible (window))
419     gtk_widget_show_all (window);
420   else
421     gtk_widget_destroy (window);
422 }
423
424 /*
425  * Big windows and guffaw scrolling
426  */
427
428 static void
429 pattern_set_bg (GtkWidget   *widget,
430                 GdkWindow   *child,
431                 gint         level)
432 {
433   static const GdkColor colors[] = {
434     { 0, 0x4444, 0x4444, 0xffff },
435     { 0, 0x8888, 0x8888, 0xffff },
436     { 0, 0xaaaa, 0xaaaa, 0xffff }
437   };
438     
439   gdk_window_set_user_data (child, widget);
440   gdk_window_set_background (child, &colors[level]);
441 }
442
443 static void
444 create_pattern (GtkWidget   *widget,
445                 GdkWindow   *parent,
446                 gint         level,
447                 gint         width,
448                 gint         height)
449 {
450   gint h = 1;
451   gint i = 0;
452     
453   GdkWindow *child;
454
455   while (2 * h <= height)
456     {
457       gint w = 1;
458       gint j = 0;
459       
460       while (2 * w <= width)
461         {
462           if ((i + j) % 2 == 0)
463             {
464               gint x = w  - 1;
465               gint y = h - 1;
466               
467               GdkWindowAttr attributes;
468
469               attributes.window_type = GDK_WINDOW_CHILD;
470               attributes.x = x;
471               attributes.y = y;
472               attributes.width = w;
473               attributes.height = h;
474               attributes.wclass = GDK_INPUT_OUTPUT;
475               attributes.event_mask = GDK_EXPOSURE_MASK;
476               attributes.visual = gtk_widget_get_visual (widget);
477               
478               child = gdk_window_new (parent, &attributes,
479                                       GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL);
480
481               pattern_set_bg (widget, child, level);
482
483               if (level < 2)
484                 create_pattern (widget, child, level + 1, w, h);
485
486               gdk_window_show (child);
487             }
488           j++;
489           w *= 2;
490         }
491       i++;
492       h *= 2;
493     }
494 }
495
496 #define PATTERN_SIZE (1 << 18)
497
498 static void
499 pattern_hadj_changed (GtkAdjustment *adjustment,
500                       GtkWidget     *darea)
501 {
502   gint *old_value = g_object_get_data (G_OBJECT (adjustment), "old-value");
503   gint new_value = gtk_adjustment_get_value (adjustment);
504
505   if (gtk_widget_get_realized (darea))
506     {
507       gdk_window_scroll (gtk_widget_get_window (darea),
508                          *old_value - new_value, 0);
509       *old_value = new_value;
510     }
511 }
512
513 static void
514 pattern_vadj_changed (GtkAdjustment *adjustment,
515                       GtkWidget *darea)
516 {
517   gint *old_value = g_object_get_data (G_OBJECT (adjustment), "old-value");
518   gint new_value = gtk_adjustment_get_value (adjustment);
519
520   if (gtk_widget_get_realized (darea))
521     {
522       gdk_window_scroll (gtk_widget_get_window (darea),
523                          0, *old_value - new_value);
524       *old_value = new_value;
525     }
526 }
527
528 static void
529 pattern_realize (GtkWidget *widget,
530                  gpointer   data)
531 {
532   GdkWindow *window;
533
534   window = gtk_widget_get_window (widget);
535   pattern_set_bg (widget, window, 0);
536   create_pattern (widget, window, 1, PATTERN_SIZE, PATTERN_SIZE);
537 }
538
539 static void 
540 create_big_windows (GtkWidget *widget)
541 {
542   static GtkWidget *window = NULL;
543   GtkWidget *content_area;
544   GtkWidget *darea, *grid, *scrollbar;
545   GtkWidget *eventbox;
546   GtkAdjustment *hadjustment;
547   GtkAdjustment *vadjustment;
548   static gint current_x;
549   static gint current_y;
550  
551   if (!window)
552     {
553       current_x = 0;
554       current_y = 0;
555       
556       window = gtk_dialog_new_with_buttons ("Big Windows",
557                                             NULL, 0,
558                                             GTK_STOCK_CLOSE,
559                                             GTK_RESPONSE_NONE,
560                                             NULL);
561  
562       gtk_window_set_screen (GTK_WINDOW (window),
563                              gtk_widget_get_screen (widget));
564
565       gtk_window_set_default_size (GTK_WINDOW (window), 200, 300);
566
567       g_signal_connect (window, "destroy",
568                         G_CALLBACK (gtk_widget_destroyed),
569                         &window);
570
571       g_signal_connect (window, "response",
572                         G_CALLBACK (gtk_widget_destroy),
573                         NULL);
574
575       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
576
577       grid = gtk_grid_new ();
578       gtk_box_pack_start (GTK_BOX (content_area), grid, TRUE, TRUE, 0);
579
580       darea = gtk_drawing_area_new ();
581
582       hadjustment = gtk_adjustment_new (0, 0, PATTERN_SIZE, 10, 100, 100);
583       g_signal_connect (hadjustment, "value_changed",
584                         G_CALLBACK (pattern_hadj_changed), darea);
585       g_object_set_data (G_OBJECT (hadjustment), "old-value", &current_x);
586
587       vadjustment = gtk_adjustment_new (0, 0, PATTERN_SIZE, 10, 100, 100);
588       g_signal_connect (vadjustment, "value_changed",
589                         G_CALLBACK (pattern_vadj_changed), darea);
590       g_object_set_data (G_OBJECT (vadjustment), "old-value", &current_y);
591       
592       g_signal_connect (darea, "realize",
593                         G_CALLBACK (pattern_realize),
594                         NULL);
595
596       eventbox = gtk_event_box_new ();
597       gtk_widget_set_hexpand (eventbox, TRUE);
598       gtk_widget_set_vexpand (eventbox, TRUE);
599       gtk_grid_attach (GTK_GRID (grid), eventbox, 0, 0, 1, 1);
600
601       gtk_container_add (GTK_CONTAINER (eventbox), darea);
602
603       scrollbar = gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL, hadjustment);
604       gtk_widget_set_hexpand (scrollbar, TRUE);
605       gtk_grid_attach (GTK_GRID (grid), scrollbar, 0, 1, 1, 1);
606
607       scrollbar = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, vadjustment);
608       gtk_widget_set_vexpand (scrollbar, TRUE);
609       gtk_grid_attach (GTK_GRID (grid), scrollbar, 1, 0, 1, 1);
610     }
611
612   if (!gtk_widget_get_visible (window))
613     gtk_widget_show_all (window);
614   else
615     gtk_widget_hide (window);
616 }
617
618 /*
619  * GtkButton
620  */
621
622 static void
623 button_window (GtkWidget *widget,
624                GtkWidget *button)
625 {
626   if (!gtk_widget_get_visible (button))
627     gtk_widget_show (button);
628   else
629     gtk_widget_hide (button);
630 }
631
632 static void
633 create_buttons (GtkWidget *widget)
634 {
635   static GtkWidget *window = NULL;
636   GtkWidget *box1;
637   GtkWidget *box2;
638   GtkWidget *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 *grid;
5254   gint i, j;
5255   
5256   grid = gtk_grid_new ();
5257
5258   gtk_grid_set_row_spacing (GTK_GRID (grid), 10);
5259   gtk_grid_set_column_spacing (GTK_GRID (grid), 10);
5260
5261   for (i = 0; i < 5; i++)
5262     {
5263       for (j = 0; j < 5; j++)
5264         {
5265           GtkWidget *widget;
5266           
5267           if ((i + j) % 2)
5268             widget = gtk_entry_new ();
5269           else
5270             widget = gtk_button_new_with_label ("Foo");
5271
5272           *list = g_list_prepend (*list, widget);
5273           
5274           gtk_widget_set_hexpand (widget, TRUE);
5275           gtk_widget_set_vexpand (widget, TRUE);
5276
5277           gtk_grid_attach (GTK_GRID (grid), widget, i, j, 1, 1);
5278         }
5279     }
5280
5281   *list = g_list_reverse (*list);
5282   
5283   return grid;
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 *grid, *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                          "type", GTK_WINDOW_TOPLEVEL,
5567                          "title", "Screen or Display selection",
5568                          "border_width",
5569                          10, NULL);
5570   g_signal_connect (window, "destroy", 
5571                     G_CALLBACK (gtk_widget_destroy), NULL);
5572
5573   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3);
5574   gtk_container_add (GTK_CONTAINER (window), vbox);
5575   
5576   frame = gtk_frame_new ("Select screen or display");
5577   gtk_container_add (GTK_CONTAINER (vbox), frame);
5578   
5579   grid = gtk_grid_new ();
5580   gtk_grid_set_row_spacing (GTK_GRID (grid), 3);
5581   gtk_grid_set_column_spacing (GTK_GRID (grid), 3);
5582
5583   gtk_container_add (GTK_CONTAINER (frame), grid);
5584
5585   radio_dpy = gtk_radio_button_new_with_label (NULL, "move to another X display");
5586   if (gdk_display_get_n_screens(display) > 1)
5587     radio_scr = gtk_radio_button_new_with_label 
5588     (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), "move to next screen");
5589   else
5590     {    
5591       radio_scr = gtk_radio_button_new_with_label 
5592         (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), 
5593          "only one screen on the current display");
5594       gtk_widget_set_sensitive (radio_scr, FALSE);
5595     }
5596   combo_dpy = gtk_combo_box_text_new_with_entry ();
5597   gtk_widget_set_hexpand (combo_dpy, TRUE);
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_grid_attach (GTK_GRID (grid), radio_dpy, 0, 0, 1, 1);
5603   gtk_grid_attach (GTK_GRID (grid), radio_scr, 0, 1, 1, 1);
5604   gtk_grid_attach (GTK_GRID (grid), combo_dpy, 1, 0, 1, 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 *grid1;
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   grid1 = gtk_grid_new ();
6529   gtk_container_add (GTK_CONTAINER (frame4), grid1);
6530   gtk_container_set_border_width (GTK_CONTAINER (grid1), 11);
6531
6532   button1 = gtk_button_new_with_label ("button1");
6533   gtk_grid_attach (GTK_GRID (grid1), button1, 0, 0, 1, 1);
6534
6535   button2 = gtk_button_new_with_label ("button2");
6536   gtk_grid_attach (GTK_GRID (grid1), button2, 1, 0, 1, 1);
6537
6538   button3 = gtk_button_new_with_label ("button3");
6539   gtk_grid_attach (GTK_GRID (grid1), button3, 0, 1, 1, 1);
6540
6541   button4 = gtk_button_new_with_label ("button4");
6542   gtk_grid_attach (GTK_GRID (grid1), button4, 1, 1, 1, 1);
6543
6544   return window1;
6545 }
6546
6547 static GtkWidget*
6548 paned_keyboard_window2 (GtkWidget *widget)
6549 {
6550   GtkWidget *window2;
6551   GtkWidget *hpaned2;
6552   GtkWidget *frame6;
6553   GtkWidget *button13;
6554   GtkWidget *hbox2;
6555   GtkWidget *vpaned2;
6556   GtkWidget *frame7;
6557   GtkWidget *button12;
6558   GtkWidget *frame8;
6559   GtkWidget *button11;
6560   GtkWidget *button10;
6561
6562   window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6563   gtk_window_set_title (GTK_WINDOW (window2), "\"button 10\" is not inside the horisontal pane");
6564
6565   gtk_window_set_screen (GTK_WINDOW (window2), 
6566                          gtk_widget_get_screen (widget));
6567
6568   hpaned2 = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6569   gtk_container_add (GTK_CONTAINER (window2), hpaned2);
6570
6571   frame6 = gtk_frame_new (NULL);
6572   gtk_paned_pack1 (GTK_PANED (hpaned2), frame6, FALSE, TRUE);
6573   gtk_frame_set_shadow_type (GTK_FRAME (frame6), GTK_SHADOW_IN);
6574
6575   button13 = gtk_button_new_with_label ("button13");
6576   gtk_container_add (GTK_CONTAINER (frame6), button13);
6577
6578   hbox2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
6579   gtk_paned_pack2 (GTK_PANED (hpaned2), hbox2, TRUE, TRUE);
6580
6581   vpaned2 = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6582   gtk_box_pack_start (GTK_BOX (hbox2), vpaned2, TRUE, TRUE, 0);
6583
6584   frame7 = gtk_frame_new (NULL);
6585   gtk_paned_pack1 (GTK_PANED (vpaned2), frame7, FALSE, TRUE);
6586   gtk_frame_set_shadow_type (GTK_FRAME (frame7), GTK_SHADOW_IN);
6587
6588   button12 = gtk_button_new_with_label ("button12");
6589   gtk_container_add (GTK_CONTAINER (frame7), button12);
6590
6591   frame8 = gtk_frame_new (NULL);
6592   gtk_paned_pack2 (GTK_PANED (vpaned2), frame8, TRUE, TRUE);
6593   gtk_frame_set_shadow_type (GTK_FRAME (frame8), GTK_SHADOW_IN);
6594
6595   button11 = gtk_button_new_with_label ("button11");
6596   gtk_container_add (GTK_CONTAINER (frame8), button11);
6597
6598   button10 = gtk_button_new_with_label ("button10");
6599   gtk_box_pack_start (GTK_BOX (hbox2), button10, FALSE, FALSE, 0);
6600
6601   return window2;
6602 }
6603
6604 static GtkWidget*
6605 paned_keyboard_window3 (GtkWidget *widget)
6606 {
6607   GtkWidget *window3;
6608   GtkWidget *vbox2;
6609   GtkWidget *label1;
6610   GtkWidget *hpaned3;
6611   GtkWidget *frame9;
6612   GtkWidget *button14;
6613   GtkWidget *hpaned4;
6614   GtkWidget *frame10;
6615   GtkWidget *button15;
6616   GtkWidget *hpaned5;
6617   GtkWidget *frame11;
6618   GtkWidget *button16;
6619   GtkWidget *frame12;
6620   GtkWidget *button17;
6621
6622   window3 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6623   g_object_set_data (G_OBJECT (window3), "window3", window3);
6624   gtk_window_set_title (GTK_WINDOW (window3), "Nested panes");
6625
6626   gtk_window_set_screen (GTK_WINDOW (window3), 
6627                          gtk_widget_get_screen (widget));
6628   
6629
6630   vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
6631   gtk_container_add (GTK_CONTAINER (window3), vbox2);
6632
6633   label1 = gtk_label_new ("Three panes nested inside each other");
6634   gtk_box_pack_start (GTK_BOX (vbox2), label1, FALSE, FALSE, 0);
6635
6636   hpaned3 = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6637   gtk_box_pack_start (GTK_BOX (vbox2), hpaned3, TRUE, TRUE, 0);
6638
6639   frame9 = gtk_frame_new (NULL);
6640   gtk_paned_pack1 (GTK_PANED (hpaned3), frame9, FALSE, TRUE);
6641   gtk_frame_set_shadow_type (GTK_FRAME (frame9), GTK_SHADOW_IN);
6642
6643   button14 = gtk_button_new_with_label ("button14");
6644   gtk_container_add (GTK_CONTAINER (frame9), button14);
6645
6646   hpaned4 = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6647   gtk_paned_pack2 (GTK_PANED (hpaned3), hpaned4, TRUE, TRUE);
6648
6649   frame10 = gtk_frame_new (NULL);
6650   gtk_paned_pack1 (GTK_PANED (hpaned4), frame10, FALSE, TRUE);
6651   gtk_frame_set_shadow_type (GTK_FRAME (frame10), GTK_SHADOW_IN);
6652
6653   button15 = gtk_button_new_with_label ("button15");
6654   gtk_container_add (GTK_CONTAINER (frame10), button15);
6655
6656   hpaned5 = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6657   gtk_paned_pack2 (GTK_PANED (hpaned4), hpaned5, TRUE, TRUE);
6658
6659   frame11 = gtk_frame_new (NULL);
6660   gtk_paned_pack1 (GTK_PANED (hpaned5), frame11, FALSE, TRUE);
6661   gtk_frame_set_shadow_type (GTK_FRAME (frame11), GTK_SHADOW_IN);
6662
6663   button16 = gtk_button_new_with_label ("button16");
6664   gtk_container_add (GTK_CONTAINER (frame11), button16);
6665
6666   frame12 = gtk_frame_new (NULL);
6667   gtk_paned_pack2 (GTK_PANED (hpaned5), frame12, TRUE, TRUE);
6668   gtk_frame_set_shadow_type (GTK_FRAME (frame12), GTK_SHADOW_IN);
6669
6670   button17 = gtk_button_new_with_label ("button17");
6671   gtk_container_add (GTK_CONTAINER (frame12), button17);
6672
6673   return window3;
6674 }
6675
6676 static GtkWidget*
6677 paned_keyboard_window4 (GtkWidget *widget)
6678 {
6679   GtkWidget *window4;
6680   GtkWidget *vbox3;
6681   GtkWidget *label2;
6682   GtkWidget *hpaned6;
6683   GtkWidget *vpaned3;
6684   GtkWidget *button19;
6685   GtkWidget *button18;
6686   GtkWidget *hbox3;
6687   GtkWidget *vpaned4;
6688   GtkWidget *button21;
6689   GtkWidget *button20;
6690   GtkWidget *vpaned5;
6691   GtkWidget *button23;
6692   GtkWidget *button22;
6693   GtkWidget *vpaned6;
6694   GtkWidget *button25;
6695   GtkWidget *button24;
6696
6697   window4 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6698   g_object_set_data (G_OBJECT (window4), "window4", window4);
6699   gtk_window_set_title (GTK_WINDOW (window4), "window4");
6700
6701   gtk_window_set_screen (GTK_WINDOW (window4), 
6702                          gtk_widget_get_screen (widget));
6703
6704   vbox3 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
6705   gtk_container_add (GTK_CONTAINER (window4), vbox3);
6706
6707   label2 = gtk_label_new ("Widget tree:\n\nhpaned \n - vpaned\n - hbox\n    - vpaned\n    - vpaned\n    - vpaned\n");
6708   gtk_box_pack_start (GTK_BOX (vbox3), label2, FALSE, FALSE, 0);
6709   gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_LEFT);
6710
6711   hpaned6 = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6712   gtk_box_pack_start (GTK_BOX (vbox3), hpaned6, TRUE, TRUE, 0);
6713
6714   vpaned3 = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6715   gtk_paned_pack1 (GTK_PANED (hpaned6), vpaned3, FALSE, TRUE);
6716
6717   button19 = gtk_button_new_with_label ("button19");
6718   gtk_paned_pack1 (GTK_PANED (vpaned3), button19, FALSE, TRUE);
6719
6720   button18 = gtk_button_new_with_label ("button18");
6721   gtk_paned_pack2 (GTK_PANED (vpaned3), button18, TRUE, TRUE);
6722
6723   hbox3 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
6724   gtk_paned_pack2 (GTK_PANED (hpaned6), hbox3, TRUE, TRUE);
6725
6726   vpaned4 = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6727   gtk_box_pack_start (GTK_BOX (hbox3), vpaned4, TRUE, TRUE, 0);
6728
6729   button21 = gtk_button_new_with_label ("button21");
6730   gtk_paned_pack1 (GTK_PANED (vpaned4), button21, FALSE, TRUE);
6731
6732   button20 = gtk_button_new_with_label ("button20");
6733   gtk_paned_pack2 (GTK_PANED (vpaned4), button20, TRUE, TRUE);
6734
6735   vpaned5 = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6736   gtk_box_pack_start (GTK_BOX (hbox3), vpaned5, TRUE, TRUE, 0);
6737
6738   button23 = gtk_button_new_with_label ("button23");
6739   gtk_paned_pack1 (GTK_PANED (vpaned5), button23, FALSE, TRUE);
6740
6741   button22 = gtk_button_new_with_label ("button22");
6742   gtk_paned_pack2 (GTK_PANED (vpaned5), button22, TRUE, TRUE);
6743
6744   vpaned6 = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6745   gtk_box_pack_start (GTK_BOX (hbox3), vpaned6, TRUE, TRUE, 0);
6746
6747   button25 = gtk_button_new_with_label ("button25");
6748   gtk_paned_pack1 (GTK_PANED (vpaned6), button25, FALSE, TRUE);
6749
6750   button24 = gtk_button_new_with_label ("button24");
6751   gtk_paned_pack2 (GTK_PANED (vpaned6), button24, TRUE, TRUE);
6752
6753   return window4;
6754 }
6755
6756 static void
6757 create_paned_keyboard_navigation (GtkWidget *widget)
6758 {
6759   static GtkWidget *window1 = NULL;
6760   static GtkWidget *window2 = NULL;
6761   static GtkWidget *window3 = NULL;
6762   static GtkWidget *window4 = NULL;
6763
6764   if (window1 && 
6765      (gtk_widget_get_screen (window1) != gtk_widget_get_screen (widget)))
6766     {
6767       gtk_widget_destroy (window1);
6768       gtk_widget_destroy (window2);
6769       gtk_widget_destroy (window3);
6770       gtk_widget_destroy (window4);
6771     }
6772   
6773   if (!window1)
6774     {
6775       window1 = paned_keyboard_window1 (widget);
6776       g_signal_connect (window1, "destroy",
6777                         G_CALLBACK (gtk_widget_destroyed),
6778                         &window1);
6779     }
6780
6781   if (!window2)
6782     {
6783       window2 = paned_keyboard_window2 (widget);
6784       g_signal_connect (window2, "destroy",
6785                         G_CALLBACK (gtk_widget_destroyed),
6786                         &window2);
6787     }
6788
6789   if (!window3)
6790     {
6791       window3 = paned_keyboard_window3 (widget);
6792       g_signal_connect (window3, "destroy",
6793                         G_CALLBACK (gtk_widget_destroyed),
6794                         &window3);
6795     }
6796
6797   if (!window4)
6798     {
6799       window4 = paned_keyboard_window4 (widget);
6800       g_signal_connect (window4, "destroy",
6801                         G_CALLBACK (gtk_widget_destroyed),
6802                         &window4);
6803     }
6804
6805   if (gtk_widget_get_visible (window1))
6806     gtk_widget_destroy (GTK_WIDGET (window1));
6807   else
6808     gtk_widget_show_all (GTK_WIDGET (window1));
6809
6810   if (gtk_widget_get_visible (window2))
6811     gtk_widget_destroy (GTK_WIDGET (window2));
6812   else
6813     gtk_widget_show_all (GTK_WIDGET (window2));
6814
6815   if (gtk_widget_get_visible (window3))
6816     gtk_widget_destroy (GTK_WIDGET (window3));
6817   else
6818     gtk_widget_show_all (GTK_WIDGET (window3));
6819
6820   if (gtk_widget_get_visible (window4))
6821     gtk_widget_destroy (GTK_WIDGET (window4));
6822   else
6823     gtk_widget_show_all (GTK_WIDGET (window4));
6824 }
6825
6826
6827 /*
6828  * Shaped Windows
6829  */
6830
6831 typedef struct _cursoroffset {gint x,y;} CursorOffset;
6832
6833 static void
6834 shape_pressed (GtkWidget *widget, GdkEventButton *event)
6835 {
6836   CursorOffset *p;
6837
6838   /* ignore double and triple click */
6839   if (event->type != GDK_BUTTON_PRESS)
6840     return;
6841
6842   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
6843   p->x = (int) event->x;
6844   p->y = (int) event->y;
6845
6846   gtk_grab_add (widget);
6847   gdk_device_grab (gdk_event_get_device ((GdkEvent*)event),
6848                    gtk_widget_get_window (widget),
6849                    GDK_OWNERSHIP_NONE,
6850                    TRUE,
6851                    GDK_BUTTON_RELEASE_MASK |
6852                    GDK_BUTTON_MOTION_MASK |
6853                    GDK_POINTER_MOTION_HINT_MASK,
6854                    NULL,
6855                    event->time);
6856 }
6857
6858 static void
6859 shape_released (GtkWidget      *widget,
6860                 GdkEventButton *event)
6861 {
6862   gtk_grab_remove (widget);
6863   gdk_device_ungrab (gdk_event_get_device ((GdkEvent*)event), event->time);
6864 }
6865
6866 static void
6867 shape_motion (GtkWidget      *widget,
6868               GdkEventMotion *event)
6869 {
6870   gint xp, yp;
6871   CursorOffset * p;
6872   GdkModifierType mask;
6873
6874   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
6875
6876   /*
6877    * Can't use event->x / event->y here 
6878    * because I need absolute coordinates.
6879    */
6880   gdk_window_get_pointer (NULL, &xp, &yp, &mask);
6881   gtk_window_move (GTK_WINDOW (widget), xp  - p->x, yp  - p->y);
6882 }
6883
6884 GtkWidget *
6885 shape_create_icon (GdkScreen *screen,
6886                    char      *xpm_file,
6887                    gint       x,
6888                    gint       y,
6889                    gint       px,
6890                    gint       py,
6891                    gint       window_type)
6892 {
6893   GtkWidget *window;
6894   GtkWidget *image;
6895   GtkWidget *fixed;
6896   CursorOffset* icon_pos;
6897   cairo_surface_t *mask;
6898   cairo_region_t *mask_region;
6899   GdkPixbuf *pixbuf;
6900   cairo_t *cr;
6901
6902   /*
6903    * GDK_WINDOW_TOPLEVEL works also, giving you a title border
6904    */
6905   window = gtk_window_new (window_type);
6906   gtk_window_set_screen (GTK_WINDOW (window), screen);
6907   
6908   fixed = gtk_fixed_new ();
6909   gtk_widget_set_size_request (fixed, 100, 100);
6910   gtk_container_add (GTK_CONTAINER (window), fixed);
6911   gtk_widget_show (fixed);
6912   
6913   gtk_widget_set_events (window, 
6914                          gtk_widget_get_events (window) |
6915                          GDK_BUTTON_MOTION_MASK |
6916                          GDK_POINTER_MOTION_HINT_MASK |
6917                          GDK_BUTTON_PRESS_MASK);
6918
6919   gtk_widget_realize (window);
6920
6921   pixbuf = gdk_pixbuf_new_from_file (xpm_file, NULL);
6922   g_assert (pixbuf); /* FIXME: error handling */
6923
6924   mask = cairo_image_surface_create (CAIRO_FORMAT_A1,
6925                                      gdk_pixbuf_get_width (pixbuf),
6926                                      gdk_pixbuf_get_height (pixbuf));
6927   cr = cairo_create (mask);
6928   gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
6929   cairo_paint (cr);
6930   cairo_destroy (cr);
6931
6932   mask_region = gdk_cairo_region_create_from_surface (mask);
6933                                                   
6934   cairo_region_translate (mask_region, px, py);
6935
6936   image = gtk_image_new_from_pixbuf (pixbuf);
6937   gtk_fixed_put (GTK_FIXED (fixed), image, px,py);
6938   gtk_widget_show (image);
6939   
6940   gtk_widget_shape_combine_region (window, mask_region);
6941   
6942   cairo_region_destroy (mask_region);
6943   cairo_surface_destroy (mask);
6944   g_object_unref (pixbuf);
6945
6946   g_signal_connect (window, "button_press_event",
6947                     G_CALLBACK (shape_pressed), NULL);
6948   g_signal_connect (window, "button_release_event",
6949                     G_CALLBACK (shape_released), NULL);
6950   g_signal_connect (window, "motion_notify_event",
6951                     G_CALLBACK (shape_motion), NULL);
6952
6953   icon_pos = g_new (CursorOffset, 1);
6954   g_object_set_data (G_OBJECT (window), "cursor_offset", icon_pos);
6955
6956   gtk_window_move (GTK_WINDOW (window), x, y);
6957   gtk_widget_show (window);
6958   
6959   return window;
6960 }
6961
6962 void 
6963 create_shapes (GtkWidget *widget)
6964 {
6965   /* Variables used by the Drag/Drop and Shape Window demos */
6966   static GtkWidget *modeller = NULL;
6967   static GtkWidget *sheets = NULL;
6968   static GtkWidget *rings = NULL;
6969   static GtkWidget *with_region = NULL;
6970   GdkScreen *screen = gtk_widget_get_screen (widget);
6971   
6972   if (!(file_exists ("Modeller.xpm") &&
6973         file_exists ("FilesQueue.xpm") &&
6974         file_exists ("3DRings.xpm")))
6975     return;
6976   
6977
6978   if (!modeller)
6979     {
6980       modeller = shape_create_icon (screen, "Modeller.xpm",
6981                                     440, 140, 0,0, GTK_WINDOW_POPUP);
6982
6983       g_signal_connect (modeller, "destroy",
6984                         G_CALLBACK (gtk_widget_destroyed),
6985                         &modeller);
6986     }
6987   else
6988     gtk_widget_destroy (modeller);
6989
6990   if (!sheets)
6991     {
6992       sheets = shape_create_icon (screen, "FilesQueue.xpm",
6993                                   580, 170, 0,0, GTK_WINDOW_POPUP);
6994
6995       g_signal_connect (sheets, "destroy",
6996                         G_CALLBACK (gtk_widget_destroyed),
6997                         &sheets);
6998
6999     }
7000   else
7001     gtk_widget_destroy (sheets);
7002
7003   if (!rings)
7004     {
7005       rings = shape_create_icon (screen, "3DRings.xpm",
7006                                  460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
7007
7008       g_signal_connect (rings, "destroy",
7009                         G_CALLBACK (gtk_widget_destroyed),
7010                         &rings);
7011     }
7012   else
7013     gtk_widget_destroy (rings);
7014
7015   if (!with_region)
7016     {
7017       cairo_region_t *region;
7018       gint x, y;
7019       
7020       with_region = shape_create_icon (screen, "3DRings.xpm",
7021                                        460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
7022
7023       gtk_window_set_decorated (GTK_WINDOW (with_region), FALSE);
7024       
7025       g_signal_connect (with_region, "destroy",
7026                         G_CALLBACK (gtk_widget_destroyed),
7027                         &with_region);
7028
7029       /* reset shape from mask to a region */
7030       x = 0;
7031       y = 0;
7032       region = cairo_region_create ();
7033
7034       while (x < 460)
7035         {
7036           while (y < 270)
7037             {
7038               GdkRectangle rect;
7039               rect.x = x;
7040               rect.y = y;
7041               rect.width = 10;
7042               rect.height = 10;
7043
7044               cairo_region_union_rectangle (region, &rect);
7045               
7046               y += 20;
7047             }
7048           y = 0;
7049           x += 20;
7050         }
7051
7052       gdk_window_shape_combine_region (gtk_widget_get_window (with_region),
7053                                        region,
7054                                        0, 0);
7055     }
7056   else
7057     gtk_widget_destroy (with_region);
7058 }
7059
7060 /*
7061  * WM Hints demo
7062  */
7063
7064 void
7065 create_wmhints (GtkWidget *widget)
7066 {
7067   static GtkWidget *window = NULL;
7068   GtkWidget *label;
7069   GtkWidget *separator;
7070   GtkWidget *button;
7071   GtkWidget *box1;
7072   GtkWidget *box2;
7073   GdkWindow *gdk_window;
7074   GdkPixbuf *pixbuf;
7075   GList *list;
7076
7077   if (!window)
7078     {
7079       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7080
7081       gtk_window_set_screen (GTK_WINDOW (window),
7082                              gtk_widget_get_screen (widget));
7083       
7084       g_signal_connect (window, "destroy",
7085                         G_CALLBACK (gtk_widget_destroyed),
7086                         &window);
7087
7088       gtk_window_set_title (GTK_WINDOW (window), "WM Hints");
7089       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7090
7091       gtk_widget_realize (window);
7092
7093       gdk_window = gtk_widget_get_window (window);
7094
7095       pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **) openfile);
7096       list = g_list_prepend (NULL, pixbuf);
7097
7098       gdk_window_set_icon_list (gdk_window, list);
7099       
7100       g_list_free (list);
7101       g_object_unref (pixbuf);
7102
7103       gdk_window_set_icon_name (gdk_window, "WMHints Test Icon");
7104   
7105       gdk_window_set_decorations (gdk_window, GDK_DECOR_ALL | GDK_DECOR_MENU);
7106       gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_RESIZE);
7107       
7108       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
7109       gtk_container_add (GTK_CONTAINER (window), box1);
7110       gtk_widget_show (box1);
7111
7112       label = gtk_label_new ("Try iconizing me!");
7113       gtk_widget_set_size_request (label, 150, 50);
7114       gtk_box_pack_start (GTK_BOX (box1), label, TRUE, TRUE, 0);
7115       gtk_widget_show (label);
7116
7117
7118       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
7119       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
7120       gtk_widget_show (separator);
7121
7122
7123       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
7124       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
7125       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
7126       gtk_widget_show (box2);
7127
7128
7129       button = gtk_button_new_with_label ("close");
7130
7131       g_signal_connect_swapped (button, "clicked",
7132                                 G_CALLBACK (gtk_widget_destroy),
7133                                 window);
7134
7135       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
7136       gtk_widget_set_can_default (button, TRUE);
7137       gtk_widget_grab_default (button);
7138       gtk_widget_show (button);
7139     }
7140
7141   if (!gtk_widget_get_visible (window))
7142     gtk_widget_show (window);
7143   else
7144     gtk_widget_destroy (window);
7145 }
7146
7147
7148 /*
7149  * Window state tracking
7150  */
7151
7152 static gint
7153 window_state_callback (GtkWidget *widget,
7154                        GdkEventWindowState *event,
7155                        gpointer data)
7156 {
7157   GtkWidget *label = data;
7158   gchar *msg;
7159
7160   msg = g_strconcat (gtk_window_get_title (GTK_WINDOW (widget)), ": ",
7161                      (event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) ?
7162                      "withdrawn" : "not withdrawn", ", ",
7163                      (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) ?
7164                      "iconified" : "not iconified", ", ",
7165                      (event->new_window_state & GDK_WINDOW_STATE_STICKY) ?
7166                      "sticky" : "not sticky", ", ",
7167                      (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) ?
7168                      "maximized" : "not maximized", ", ",
7169                      (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) ?
7170                      "fullscreen" : "not fullscreen",
7171                      (event->new_window_state & GDK_WINDOW_STATE_ABOVE) ?
7172                      "above" : "not above", ", ",
7173                      (event->new_window_state & GDK_WINDOW_STATE_BELOW) ?
7174                      "below" : "not below", ", ",
7175                      NULL);
7176   
7177   gtk_label_set_text (GTK_LABEL (label), msg);
7178
7179   g_free (msg);
7180
7181   return FALSE;
7182 }
7183
7184 static GtkWidget*
7185 tracking_label (GtkWidget *window)
7186 {
7187   GtkWidget *label;
7188   GtkWidget *hbox;
7189   GtkWidget *button;
7190
7191   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
7192
7193   g_signal_connect_object (hbox,
7194                            "destroy",
7195                            G_CALLBACK (gtk_widget_destroy),
7196                            window,
7197                            G_CONNECT_SWAPPED);
7198   
7199   label = gtk_label_new ("<no window state events received>");
7200   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
7201   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
7202   
7203   g_signal_connect (window,
7204                     "window_state_event",
7205                     G_CALLBACK (window_state_callback),
7206                     label);
7207
7208   button = gtk_button_new_with_label ("Deiconify");
7209   g_signal_connect_object (button,
7210                            "clicked",
7211                            G_CALLBACK (gtk_window_deiconify),
7212                            window,
7213                            G_CONNECT_SWAPPED);
7214   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7215
7216   button = gtk_button_new_with_label ("Iconify");
7217   g_signal_connect_object (button,
7218                            "clicked",
7219                            G_CALLBACK (gtk_window_iconify),
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 ("Fullscreen");
7225   g_signal_connect_object (button,
7226                            "clicked",
7227                            G_CALLBACK (gtk_window_fullscreen),
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 ("Unfullscreen");
7233   g_signal_connect_object (button,
7234                            "clicked",
7235                            G_CALLBACK (gtk_window_unfullscreen),
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 ("Present");
7241   g_signal_connect_object (button,
7242                            "clicked",
7243                            G_CALLBACK (gtk_window_present),
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 ("Show");
7249   g_signal_connect_object (button,
7250                            "clicked",
7251                            G_CALLBACK (gtk_widget_show),
7252                            window,
7253                            G_CONNECT_SWAPPED);
7254   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7255   
7256   gtk_widget_show_all (hbox);
7257   
7258   return hbox;
7259 }
7260
7261 void
7262 keep_window_above (GtkToggleButton *togglebutton, gpointer data)
7263 {
7264   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
7265
7266   gtk_window_set_keep_above (GTK_WINDOW (data),
7267                              gtk_toggle_button_get_active (togglebutton));
7268
7269   if (gtk_toggle_button_get_active (togglebutton))
7270     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
7271 }
7272
7273 void
7274 keep_window_below (GtkToggleButton *togglebutton, gpointer data)
7275 {
7276   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
7277
7278   gtk_window_set_keep_below (GTK_WINDOW (data),
7279                              gtk_toggle_button_get_active (togglebutton));
7280
7281   if (gtk_toggle_button_get_active (togglebutton))
7282     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
7283 }
7284
7285
7286 static GtkWidget*
7287 get_state_controls (GtkWidget *window)
7288 {
7289   GtkWidget *vbox;
7290   GtkWidget *button;
7291   GtkWidget *button_above;
7292   GtkWidget *button_below;
7293
7294   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
7295   
7296   button = gtk_button_new_with_label ("Stick");
7297   g_signal_connect_object (button,
7298                            "clicked",
7299                            G_CALLBACK (gtk_window_stick),
7300                            window,
7301                            G_CONNECT_SWAPPED);
7302   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7303
7304   button = gtk_button_new_with_label ("Unstick");
7305   g_signal_connect_object (button,
7306                            "clicked",
7307                            G_CALLBACK (gtk_window_unstick),
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 ("Maximize");
7313   g_signal_connect_object (button,
7314                            "clicked",
7315                            G_CALLBACK (gtk_window_maximize),
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 ("Unmaximize");
7321   g_signal_connect_object (button,
7322                            "clicked",
7323                            G_CALLBACK (gtk_window_unmaximize),
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 ("Iconify");
7329   g_signal_connect_object (button,
7330                            "clicked",
7331                            G_CALLBACK (gtk_window_iconify),
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 ("Fullscreen");
7337   g_signal_connect_object (button,
7338                            "clicked",
7339                            G_CALLBACK (gtk_window_fullscreen),
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 ("Unfullscreen");
7345   g_signal_connect_object (button,
7346                            "clicked",
7347                            G_CALLBACK (gtk_window_unfullscreen),
7348                            window,
7349                            G_CONNECT_SWAPPED);
7350   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7351
7352   button_above = gtk_toggle_button_new_with_label ("Keep above");
7353   g_signal_connect (button_above,
7354                     "toggled",
7355                     G_CALLBACK (keep_window_above),
7356                     window);
7357   gtk_box_pack_start (GTK_BOX (vbox), button_above, FALSE, FALSE, 0);
7358
7359   button_below = gtk_toggle_button_new_with_label ("Keep below");
7360   g_signal_connect (button_below,
7361                     "toggled",
7362                     G_CALLBACK (keep_window_below),
7363                     window);
7364   gtk_box_pack_start (GTK_BOX (vbox), button_below, FALSE, FALSE, 0);
7365
7366   g_object_set_data (G_OBJECT (button_above), "radio", button_below);
7367   g_object_set_data (G_OBJECT (button_below), "radio", button_above);
7368
7369   button = gtk_button_new_with_label ("Hide (withdraw)");
7370   g_signal_connect_object (button,
7371                            "clicked",
7372                            G_CALLBACK (gtk_widget_hide),
7373                            window,
7374                            G_CONNECT_SWAPPED);
7375   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7376   
7377   gtk_widget_show_all (vbox);
7378
7379   return vbox;
7380 }
7381
7382 void
7383 create_window_states (GtkWidget *widget)
7384 {
7385   static GtkWidget *window = NULL;
7386   GtkWidget *label;
7387   GtkWidget *box1;
7388   GtkWidget *iconified;
7389   GtkWidget *normal;
7390   GtkWidget *controls;
7391
7392   if (!window)
7393     {
7394       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7395       gtk_window_set_screen (GTK_WINDOW (window),
7396                              gtk_widget_get_screen (widget));
7397
7398       g_signal_connect (window, "destroy",
7399                         G_CALLBACK (gtk_widget_destroyed),
7400                         &window);
7401
7402       gtk_window_set_title (GTK_WINDOW (window), "Window states");
7403       
7404       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
7405       gtk_container_add (GTK_CONTAINER (window), box1);
7406
7407       iconified = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7408
7409       gtk_window_set_screen (GTK_WINDOW (iconified),
7410                              gtk_widget_get_screen (widget));
7411       
7412       g_signal_connect_object (iconified, "destroy",
7413                                G_CALLBACK (gtk_widget_destroy),
7414                                window,
7415                                G_CONNECT_SWAPPED);
7416       gtk_window_iconify (GTK_WINDOW (iconified));
7417       gtk_window_set_title (GTK_WINDOW (iconified), "Iconified initially");
7418       controls = get_state_controls (iconified);
7419       gtk_container_add (GTK_CONTAINER (iconified), controls);
7420       
7421       normal = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7422
7423       gtk_window_set_screen (GTK_WINDOW (normal),
7424                              gtk_widget_get_screen (widget));
7425       
7426       g_signal_connect_object (normal, "destroy",
7427                                G_CALLBACK (gtk_widget_destroy),
7428                                window,
7429                                G_CONNECT_SWAPPED);
7430       
7431       gtk_window_set_title (GTK_WINDOW (normal), "Deiconified initially");
7432       controls = get_state_controls (normal);
7433       gtk_container_add (GTK_CONTAINER (normal), controls);
7434       
7435       label = tracking_label (iconified);
7436       gtk_container_add (GTK_CONTAINER (box1), label);
7437
7438       label = tracking_label (normal);
7439       gtk_container_add (GTK_CONTAINER (box1), label);
7440
7441       gtk_widget_show_all (iconified);
7442       gtk_widget_show_all (normal);
7443       gtk_widget_show_all (box1);
7444     }
7445
7446   if (!gtk_widget_get_visible (window))
7447     gtk_widget_show (window);
7448   else
7449     gtk_widget_destroy (window);
7450 }
7451
7452 /*
7453  * Window sizing
7454  */
7455
7456 static gint
7457 configure_event_callback (GtkWidget *widget,
7458                           GdkEventConfigure *event,
7459                           gpointer data)
7460 {
7461   GtkWidget *label = data;
7462   gchar *msg;
7463   gint x, y;
7464   
7465   gtk_window_get_position (GTK_WINDOW (widget), &x, &y);
7466   
7467   msg = g_strdup_printf ("event: %d,%d  %d x %d\n"
7468                          "position: %d, %d",
7469                          event->x, event->y, event->width, event->height,
7470                          x, y);
7471   
7472   gtk_label_set_text (GTK_LABEL (label), msg);
7473
7474   g_free (msg);
7475
7476   return FALSE;
7477 }
7478
7479 static void
7480 get_ints (GtkWidget *window,
7481           gint      *a,
7482           gint      *b)
7483 {
7484   GtkWidget *spin1;
7485   GtkWidget *spin2;
7486
7487   spin1 = g_object_get_data (G_OBJECT (window), "spin1");
7488   spin2 = g_object_get_data (G_OBJECT (window), "spin2");
7489
7490   *a = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin1));
7491   *b = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin2));
7492 }
7493
7494 static void
7495 set_size_callback (GtkWidget *widget,
7496                    gpointer   data)
7497 {
7498   gint w, h;
7499   
7500   get_ints (data, &w, &h);
7501
7502   gtk_window_resize (GTK_WINDOW (g_object_get_data (data, "target")), w, h);
7503 }
7504
7505 static void
7506 unset_default_size_callback (GtkWidget *widget,
7507                              gpointer   data)
7508 {
7509   gtk_window_set_default_size (g_object_get_data (data, "target"),
7510                                -1, -1);
7511 }
7512
7513 static void
7514 set_default_size_callback (GtkWidget *widget,
7515                            gpointer   data)
7516 {
7517   gint w, h;
7518   
7519   get_ints (data, &w, &h);
7520
7521   gtk_window_set_default_size (g_object_get_data (data, "target"),
7522                                w, h);
7523 }
7524
7525 static void
7526 unset_size_request_callback (GtkWidget *widget,
7527                              gpointer   data)
7528 {
7529   gtk_widget_set_size_request (g_object_get_data (data, "target"),
7530                                -1, -1);
7531 }
7532
7533 static void
7534 set_size_request_callback (GtkWidget *widget,
7535                            gpointer   data)
7536 {
7537   gint w, h;
7538   
7539   get_ints (data, &w, &h);
7540
7541   gtk_widget_set_size_request (g_object_get_data (data, "target"),
7542                                w, h);
7543 }
7544
7545 static void
7546 set_location_callback (GtkWidget *widget,
7547                        gpointer   data)
7548 {
7549   gint x, y;
7550   
7551   get_ints (data, &x, &y);
7552
7553   gtk_window_move (g_object_get_data (data, "target"), x, y);
7554 }
7555
7556 static void
7557 move_to_position_callback (GtkWidget *widget,
7558                            gpointer   data)
7559 {
7560   gint x, y;
7561   GtkWindow *window;
7562
7563   window = g_object_get_data (data, "target");
7564   
7565   gtk_window_get_position (window, &x, &y);
7566
7567   gtk_window_move (window, x, y);
7568 }
7569
7570 static void
7571 set_geometry_callback (GtkWidget *entry,
7572                        gpointer   data)
7573 {
7574   gchar *text;
7575   GtkWindow *target;
7576
7577   target = GTK_WINDOW (g_object_get_data (G_OBJECT (data), "target"));
7578   
7579   text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
7580
7581   if (!gtk_window_parse_geometry (target, text))
7582     g_print ("Bad geometry string '%s'\n", text);
7583
7584   g_free (text);
7585 }
7586
7587 static void
7588 resizable_callback (GtkWidget *widget,
7589                      gpointer   data)
7590 {
7591   g_object_set (g_object_get_data (data, "target"),
7592                 "resizable", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)),
7593                 NULL);
7594 }
7595
7596 static void
7597 gravity_selected (GtkWidget *widget,
7598                   gpointer   data)
7599 {
7600   gtk_window_set_gravity (GTK_WINDOW (g_object_get_data (data, "target")),
7601                           gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) + GDK_GRAVITY_NORTH_WEST);
7602 }
7603
7604 static void
7605 pos_selected (GtkWidget *widget,
7606               gpointer   data)
7607 {
7608   gtk_window_set_position (GTK_WINDOW (g_object_get_data (data, "target")),
7609                            gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) + GTK_WIN_POS_NONE);
7610 }
7611
7612 static void
7613 move_gravity_window_to_current_position (GtkWidget *widget,
7614                                          gpointer   data)
7615 {
7616   gint x, y;
7617   GtkWindow *window;
7618
7619   window = GTK_WINDOW (data);    
7620   
7621   gtk_window_get_position (window, &x, &y);
7622
7623   gtk_window_move (window, x, y);
7624 }
7625
7626 static void
7627 get_screen_corner (GtkWindow *window,
7628                    gint      *x,
7629                    gint      *y)
7630 {
7631   int w, h;
7632   GdkScreen * screen = gtk_window_get_screen (window);
7633   
7634   gtk_window_get_size (GTK_WINDOW (window), &w, &h);
7635
7636   switch (gtk_window_get_gravity (window))
7637     {
7638     case GDK_GRAVITY_SOUTH_EAST:
7639       *x = gdk_screen_get_width (screen) - w;
7640       *y = gdk_screen_get_height (screen) - h;
7641       break;
7642
7643     case GDK_GRAVITY_NORTH_EAST:
7644       *x = gdk_screen_get_width (screen) - w;
7645       *y = 0;
7646       break;
7647
7648     case GDK_GRAVITY_SOUTH_WEST:
7649       *x = 0;
7650       *y = gdk_screen_get_height (screen) - h;
7651       break;
7652
7653     case GDK_GRAVITY_NORTH_WEST:
7654       *x = 0;
7655       *y = 0;
7656       break;
7657       
7658     case GDK_GRAVITY_SOUTH:
7659       *x = (gdk_screen_get_width (screen) - w) / 2;
7660       *y = gdk_screen_get_height (screen) - h;
7661       break;
7662
7663     case GDK_GRAVITY_NORTH:
7664       *x = (gdk_screen_get_width (screen) - w) / 2;
7665       *y = 0;
7666       break;
7667
7668     case GDK_GRAVITY_WEST:
7669       *x = 0;
7670       *y = (gdk_screen_get_height (screen) - h) / 2;
7671       break;
7672
7673     case GDK_GRAVITY_EAST:
7674       *x = gdk_screen_get_width (screen) - w;
7675       *y = (gdk_screen_get_height (screen) - h) / 2;
7676       break;
7677
7678     case GDK_GRAVITY_CENTER:
7679       *x = (gdk_screen_get_width (screen) - w) / 2;
7680       *y = (gdk_screen_get_height (screen) - h) / 2;
7681       break;
7682
7683     case GDK_GRAVITY_STATIC:
7684       /* pick some random numbers */
7685       *x = 350;
7686       *y = 350;
7687       break;
7688
7689     default:
7690       g_assert_not_reached ();
7691       break;
7692     }
7693 }
7694
7695 static void
7696 move_gravity_window_to_starting_position (GtkWidget *widget,
7697                                           gpointer   data)
7698 {
7699   gint x, y;
7700   GtkWindow *window;
7701
7702   window = GTK_WINDOW (data);    
7703   
7704   get_screen_corner (window,
7705                      &x, &y);
7706   
7707   gtk_window_move (window, x, y);
7708 }
7709
7710 static GtkWidget*
7711 make_gravity_window (GtkWidget   *destroy_with,
7712                      GdkGravity   gravity,
7713                      const gchar *title)
7714 {
7715   GtkWidget *window;
7716   GtkWidget *button;
7717   GtkWidget *vbox;
7718   int x, y;
7719   
7720   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7721
7722   gtk_window_set_screen (GTK_WINDOW (window),
7723                          gtk_widget_get_screen (destroy_with));
7724
7725   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
7726   gtk_widget_show (vbox);
7727   
7728   gtk_container_add (GTK_CONTAINER (window), vbox);
7729   gtk_window_set_title (GTK_WINDOW (window), title);
7730   gtk_window_set_gravity (GTK_WINDOW (window), gravity);
7731
7732   g_signal_connect_object (destroy_with,
7733                            "destroy",
7734                            G_CALLBACK (gtk_widget_destroy),
7735                            window,
7736                            G_CONNECT_SWAPPED);
7737
7738   
7739   button = gtk_button_new_with_mnemonic ("_Move to current position");
7740
7741   g_signal_connect (button, "clicked",
7742                     G_CALLBACK (move_gravity_window_to_current_position),
7743                     window);
7744
7745   gtk_container_add (GTK_CONTAINER (vbox), button);
7746   gtk_widget_show (button);
7747
7748   button = gtk_button_new_with_mnemonic ("Move to _starting position");
7749
7750   g_signal_connect (button, "clicked",
7751                     G_CALLBACK (move_gravity_window_to_starting_position),
7752                     window);
7753
7754   gtk_container_add (GTK_CONTAINER (vbox), button);
7755   gtk_widget_show (button);
7756   
7757   /* Pretend this is the result of --geometry.
7758    * DO NOT COPY THIS CODE unless you are setting --geometry results,
7759    * and in that case you probably should just use gtk_window_parse_geometry().
7760    * AGAIN, DO NOT SET GDK_HINT_USER_POS! It violates the ICCCM unless
7761    * you are parsing --geometry or equivalent.
7762    */
7763   gtk_window_set_geometry_hints (GTK_WINDOW (window),
7764                                  NULL, NULL,
7765                                  GDK_HINT_USER_POS);
7766
7767   gtk_window_set_default_size (GTK_WINDOW (window),
7768                                200, 200);
7769
7770   get_screen_corner (GTK_WINDOW (window), &x, &y);
7771   
7772   gtk_window_move (GTK_WINDOW (window),
7773                    x, y);
7774   
7775   return window;
7776 }
7777
7778 static void
7779 do_gravity_test (GtkWidget *widget,
7780                  gpointer   data)
7781 {
7782   GtkWidget *destroy_with = data;
7783   GtkWidget *window;
7784   
7785   /* We put a window at each gravity point on the screen. */
7786   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_WEST,
7787                                 "NorthWest");
7788   gtk_widget_show (window);
7789   
7790   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_EAST,
7791                                 "SouthEast");
7792   gtk_widget_show (window);
7793
7794   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_EAST,
7795                                 "NorthEast");
7796   gtk_widget_show (window);
7797
7798   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_WEST,
7799                                 "SouthWest");
7800   gtk_widget_show (window);
7801
7802   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH,
7803                                 "South");
7804   gtk_widget_show (window);
7805
7806   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH,
7807                                 "North");
7808   gtk_widget_show (window);
7809
7810   
7811   window = make_gravity_window (destroy_with, GDK_GRAVITY_WEST,
7812                                 "West");
7813   gtk_widget_show (window);
7814
7815     
7816   window = make_gravity_window (destroy_with, GDK_GRAVITY_EAST,
7817                                 "East");
7818   gtk_widget_show (window);
7819
7820   window = make_gravity_window (destroy_with, GDK_GRAVITY_CENTER,
7821                                 "Center");
7822   gtk_widget_show (window);
7823
7824   window = make_gravity_window (destroy_with, GDK_GRAVITY_STATIC,
7825                                 "Static");
7826   gtk_widget_show (window);
7827 }
7828
7829 static GtkWidget*
7830 window_controls (GtkWidget *window)
7831 {
7832   GtkWidget *control_window;
7833   GtkWidget *label;
7834   GtkWidget *vbox;
7835   GtkWidget *button;
7836   GtkWidget *spin;
7837   GtkAdjustment *adjustment;
7838   GtkWidget *entry;
7839   GtkWidget *om;
7840   gint i;
7841   
7842   control_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7843
7844   gtk_window_set_screen (GTK_WINDOW (control_window),
7845                          gtk_widget_get_screen (window));
7846
7847   gtk_window_set_title (GTK_WINDOW (control_window), "Size controls");
7848   
7849   g_object_set_data (G_OBJECT (control_window),
7850                      "target",
7851                      window);
7852   
7853   g_signal_connect_object (control_window,
7854                            "destroy",
7855                            G_CALLBACK (gtk_widget_destroy),
7856                            window,
7857                            G_CONNECT_SWAPPED);
7858
7859   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
7860   
7861   gtk_container_add (GTK_CONTAINER (control_window), vbox);
7862   
7863   label = gtk_label_new ("<no configure events>");
7864   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
7865   
7866   g_signal_connect (window,
7867                     "configure_event",
7868                     G_CALLBACK (configure_event_callback),
7869                     label);
7870
7871   adjustment = gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0, 5.0, 0.0);
7872   spin = gtk_spin_button_new (adjustment, 0, 0);
7873
7874   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
7875
7876   g_object_set_data (G_OBJECT (control_window), "spin1", spin);
7877
7878   adjustment = gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0, 5.0, 0.0);
7879   spin = gtk_spin_button_new (adjustment, 0, 0);
7880
7881   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
7882
7883   g_object_set_data (G_OBJECT (control_window), "spin2", spin);
7884
7885   entry = gtk_entry_new ();
7886   gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
7887
7888   g_signal_connect (entry, "changed",
7889                     G_CALLBACK (set_geometry_callback),
7890                     control_window);
7891
7892   button = gtk_button_new_with_label ("Show gravity test windows");
7893   g_signal_connect_swapped (button,
7894                             "clicked",
7895                             G_CALLBACK (do_gravity_test),
7896                             control_window);
7897   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7898
7899   button = gtk_button_new_with_label ("Reshow with initial size");
7900   g_signal_connect_object (button,
7901                            "clicked",
7902                            G_CALLBACK (gtk_window_reshow_with_initial_size),
7903                            window,
7904                            G_CONNECT_SWAPPED);
7905   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7906   
7907   button = gtk_button_new_with_label ("Queue resize");
7908   g_signal_connect_object (button,
7909                            "clicked",
7910                            G_CALLBACK (gtk_widget_queue_resize),
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 ("Resize");
7916   g_signal_connect (button,
7917                     "clicked",
7918                     G_CALLBACK (set_size_callback),
7919                     control_window);
7920   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7921
7922   button = gtk_button_new_with_label ("Set default size");
7923   g_signal_connect (button,
7924                     "clicked",
7925                     G_CALLBACK (set_default_size_callback),
7926                     control_window);
7927   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7928
7929   button = gtk_button_new_with_label ("Unset default size");
7930   g_signal_connect (button,
7931                     "clicked",
7932                     G_CALLBACK (unset_default_size_callback),
7933                     control_window);
7934   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7935   
7936   button = gtk_button_new_with_label ("Set size request");
7937   g_signal_connect (button,
7938                     "clicked",
7939                     G_CALLBACK (set_size_request_callback),
7940                     control_window);
7941   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7942
7943   button = gtk_button_new_with_label ("Unset size request");
7944   g_signal_connect (button,
7945                     "clicked",
7946                     G_CALLBACK (unset_size_request_callback),
7947                     control_window);
7948   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7949   
7950   button = gtk_button_new_with_label ("Move");
7951   g_signal_connect (button,
7952                     "clicked",
7953                     G_CALLBACK (set_location_callback),
7954                     control_window);
7955   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7956
7957   button = gtk_button_new_with_label ("Move to current position");
7958   g_signal_connect (button,
7959                     "clicked",
7960                     G_CALLBACK (move_to_position_callback),
7961                     control_window);
7962   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7963
7964   button = gtk_check_button_new_with_label ("Allow resize");
7965   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
7966   g_signal_connect (button,
7967                     "toggled",
7968                     G_CALLBACK (resizable_callback),
7969                     control_window);
7970   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7971   
7972   button = gtk_button_new_with_mnemonic ("_Show");
7973   g_signal_connect_object (button,
7974                            "clicked",
7975                            G_CALLBACK (gtk_widget_show),
7976                            window,
7977                            G_CONNECT_SWAPPED);
7978   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7979
7980   button = gtk_button_new_with_mnemonic ("_Hide");
7981   g_signal_connect_object (button,
7982                            "clicked",
7983                            G_CALLBACK (gtk_widget_hide),
7984                            window,
7985                            G_CONNECT_SWAPPED);
7986   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7987
7988   om = gtk_combo_box_text_new ();
7989   i = 0;
7990   while (i < 10)
7991     {
7992       static gchar *names[] = {
7993         "GDK_GRAVITY_NORTH_WEST",
7994         "GDK_GRAVITY_NORTH",
7995         "GDK_GRAVITY_NORTH_EAST",
7996         "GDK_GRAVITY_WEST",
7997         "GDK_GRAVITY_CENTER",
7998         "GDK_GRAVITY_EAST",
7999         "GDK_GRAVITY_SOUTH_WEST",
8000         "GDK_GRAVITY_SOUTH",
8001         "GDK_GRAVITY_SOUTH_EAST",
8002         "GDK_GRAVITY_STATIC",
8003         NULL
8004       };
8005
8006       g_assert (names[i]);
8007       gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (om), names[i]);
8008
8009       ++i;
8010     }
8011   
8012   g_signal_connect (om,
8013                     "changed",
8014                     G_CALLBACK (gravity_selected),
8015                     control_window);
8016
8017   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
8018
8019
8020   om = gtk_combo_box_text_new ();
8021   i = 0;
8022   while (i < 5)
8023     {
8024       static gchar *names[] = {
8025         "GTK_WIN_POS_NONE",
8026         "GTK_WIN_POS_CENTER",
8027         "GTK_WIN_POS_MOUSE",
8028         "GTK_WIN_POS_CENTER_ALWAYS",
8029         "GTK_WIN_POS_CENTER_ON_PARENT",
8030         NULL
8031       };
8032
8033       g_assert (names[i]);
8034       gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (om), names[i]);
8035
8036       ++i;
8037     }
8038
8039   g_signal_connect (om,
8040                     "changed",
8041                     G_CALLBACK (pos_selected),
8042                     control_window);
8043
8044   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
8045   
8046   gtk_widget_show_all (vbox);
8047   
8048   return control_window;
8049 }
8050
8051 void
8052 create_window_sizing (GtkWidget *widget)
8053 {
8054   static GtkWidget *window = NULL;
8055   static GtkWidget *target_window = NULL;
8056
8057   if (!target_window)
8058     {
8059       GtkWidget *label;
8060       
8061       target_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8062       gtk_window_set_screen (GTK_WINDOW (target_window),
8063                              gtk_widget_get_screen (widget));
8064       label = gtk_label_new (NULL);
8065       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");
8066       gtk_container_add (GTK_CONTAINER (target_window), label);
8067       gtk_widget_show (label);
8068       
8069       g_signal_connect (target_window, "destroy",
8070                         G_CALLBACK (gtk_widget_destroyed),
8071                         &target_window);
8072
8073       window = window_controls (target_window);
8074       
8075       g_signal_connect (window, "destroy",
8076                         G_CALLBACK (gtk_widget_destroyed),
8077                         &window);
8078       
8079       gtk_window_set_title (GTK_WINDOW (target_window), "Window to size");
8080     }
8081
8082   /* don't show target window by default, we want to allow testing
8083    * of behavior on first show.
8084    */
8085   
8086   if (!gtk_widget_get_visible (window))
8087     gtk_widget_show (window);
8088   else
8089     gtk_widget_destroy (window);
8090 }
8091
8092 /*
8093  * GtkProgressBar
8094  */
8095
8096 typedef struct _ProgressData {
8097   GtkWidget *window;
8098   GtkWidget *pbar;
8099   GtkWidget *block_spin;
8100   GtkWidget *x_align_spin;
8101   GtkWidget *y_align_spin;
8102   GtkWidget *step_spin;
8103   GtkWidget *act_blocks_spin;
8104   GtkWidget *label;
8105   GtkWidget *omenu1;
8106   GtkWidget *elmenu;
8107   GtkWidget *omenu2;
8108   GtkWidget *entry;
8109   int timer;
8110   gboolean activity;
8111 } ProgressData;
8112
8113 gboolean
8114 progress_timeout (gpointer data)
8115 {
8116   ProgressData *pdata = data;
8117   gdouble new_val;
8118   gchar *text;
8119
8120   if (pdata->activity)
8121     {
8122       gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pdata->pbar));
8123
8124       text = g_strdup_printf ("%s", "???");
8125     }
8126   else
8127     {
8128       new_val = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (pdata->pbar)) + 0.01;
8129       if (new_val > 1.00)
8130         new_val = 0.00;
8131       gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pdata->pbar), new_val);
8132
8133       text = g_strdup_printf ("%.0f%%", 100 * new_val);
8134     }
8135
8136   gtk_label_set_text (GTK_LABEL (pdata->label), text);
8137   g_free (text);
8138
8139   return TRUE;
8140 }
8141
8142 static void
8143 destroy_progress (GtkWidget     *widget,
8144                   ProgressData **pdata)
8145 {
8146   if ((*pdata)->timer)
8147     {
8148       g_source_remove ((*pdata)->timer);
8149       (*pdata)->timer = 0;
8150     }
8151   (*pdata)->window = NULL;
8152   g_free (*pdata);
8153   *pdata = NULL;
8154 }
8155
8156 static void
8157 progressbar_toggle_orientation (GtkWidget *widget, gpointer data)
8158 {
8159   ProgressData *pdata;
8160   gint i;
8161
8162   pdata = (ProgressData *) data;
8163
8164   if (!gtk_widget_get_mapped (widget))
8165     return;
8166
8167   i = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
8168
8169   if (i == 0 || i == 1)
8170     gtk_orientable_set_orientation (GTK_ORIENTABLE (pdata->pbar), GTK_ORIENTATION_HORIZONTAL);
8171   else
8172     gtk_orientable_set_orientation (GTK_ORIENTABLE (pdata->pbar), GTK_ORIENTATION_VERTICAL);
8173  
8174   if (i == 1 || i == 2)
8175     gtk_progress_bar_set_inverted (GTK_PROGRESS_BAR (pdata->pbar), TRUE);
8176   else
8177     gtk_progress_bar_set_inverted (GTK_PROGRESS_BAR (pdata->pbar), FALSE);
8178 }
8179
8180 static void
8181 toggle_show_text (GtkWidget *widget, ProgressData *pdata)
8182 {
8183   gboolean active;
8184
8185   active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
8186   gtk_progress_bar_set_show_text (GTK_PROGRESS_BAR (pdata->pbar), active);
8187 }
8188
8189 static void
8190 progressbar_toggle_ellipsize (GtkWidget *widget,
8191                               gpointer   data)
8192 {
8193   ProgressData *pdata = data;
8194   if (gtk_widget_is_drawable (widget))
8195     {
8196       gint i = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
8197       gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (pdata->pbar), i);
8198     }
8199 }
8200
8201 static void
8202 toggle_activity_mode (GtkWidget *widget, ProgressData *pdata)
8203 {
8204   pdata->activity = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
8205 }
8206
8207 static void
8208 toggle_running (GtkWidget *widget, ProgressData *pdata)
8209 {
8210   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
8211     {
8212       if (pdata->timer == 0)
8213         pdata->timer = g_timeout_add (100, (GSourceFunc)progress_timeout, pdata);
8214     }
8215   else
8216     {
8217       if (pdata->timer != 0)
8218         {
8219           g_source_remove (pdata->timer);
8220           pdata->timer = 0;
8221         }
8222     }
8223 }
8224
8225 static void
8226 entry_changed (GtkWidget *widget, ProgressData *pdata)
8227 {
8228   gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata->pbar),
8229                           gtk_entry_get_text (GTK_ENTRY (pdata->entry)));
8230 }
8231
8232 void
8233 create_progress_bar (GtkWidget *widget)
8234 {
8235   GtkWidget *action_area, *content_area;
8236   GtkWidget *button;
8237   GtkWidget *vbox;
8238   GtkWidget *vbox2;
8239   GtkWidget *hbox;
8240   GtkWidget *check;
8241   GtkWidget *frame;
8242   GtkWidget *tab;
8243   GtkWidget *label;
8244   GtkWidget *align;
8245   static ProgressData *pdata = NULL;
8246
8247   static gchar *items1[] =
8248   {
8249     "Left-Right",
8250     "Right-Left",
8251     "Bottom-Top",
8252     "Top-Bottom"
8253   };
8254
8255     static char *ellipsize_items[] = {
8256     "None",     // PANGO_ELLIPSIZE_NONE,
8257     "Start",    // PANGO_ELLIPSIZE_START,
8258     "Middle",   // PANGO_ELLIPSIZE_MIDDLE,
8259     "End",      // PANGO_ELLIPSIZE_END
8260   };
8261   
8262   if (!pdata)
8263     pdata = g_new0 (ProgressData, 1);
8264
8265   if (!pdata->window)
8266     {
8267       pdata->window = gtk_dialog_new ();
8268
8269       gtk_window_set_screen (GTK_WINDOW (pdata->window),
8270                              gtk_widget_get_screen (widget));
8271
8272       gtk_window_set_resizable (GTK_WINDOW (pdata->window), TRUE);
8273
8274       g_signal_connect (pdata->window, "destroy",
8275                         G_CALLBACK (destroy_progress),
8276                         &pdata);
8277       pdata->timer = 0;
8278
8279       content_area = gtk_dialog_get_content_area (GTK_DIALOG (pdata->window));
8280       action_area = gtk_dialog_get_action_area (GTK_DIALOG (pdata->window));
8281
8282       gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
8283       gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);
8284
8285       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
8286       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
8287       gtk_box_pack_start (GTK_BOX (content_area), vbox, FALSE, TRUE, 0);
8288
8289       frame = gtk_frame_new ("Progress");
8290       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
8291
8292       vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
8293       gtk_container_add (GTK_CONTAINER (frame), vbox2);
8294
8295       align = gtk_alignment_new (0.5, 0.5, 0, 0);
8296       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
8297
8298       pdata->pbar = gtk_progress_bar_new ();
8299       gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (pdata->pbar),
8300                                       PANGO_ELLIPSIZE_MIDDLE);
8301
8302       gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
8303
8304       align = gtk_alignment_new (0.5, 0.5, 0, 0);
8305       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
8306
8307       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
8308       gtk_container_add (GTK_CONTAINER (align), hbox);
8309       label = gtk_label_new ("Label updated by user :"); 
8310       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
8311       pdata->label = gtk_label_new ("");
8312       gtk_box_pack_start (GTK_BOX (hbox), pdata->label, FALSE, TRUE, 0);
8313
8314       frame = gtk_frame_new ("Options");
8315       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
8316
8317       vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
8318       gtk_container_add (GTK_CONTAINER (frame), vbox2);
8319
8320       tab = gtk_table_new (7, 2, FALSE);
8321       gtk_box_pack_start (GTK_BOX (vbox2), tab, FALSE, TRUE, 0);
8322
8323       label = gtk_label_new ("Orientation :");
8324       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 0, 1,
8325                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
8326                         5, 5);
8327       gtk_widget_set_halign (label, GTK_ALIGN_START);
8328       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
8329
8330       pdata->omenu1 = build_option_menu (items1, 4, 0,
8331                                          progressbar_toggle_orientation,
8332                                          pdata);
8333       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
8334       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 0, 1,
8335                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
8336                         5, 5);
8337       gtk_box_pack_start (GTK_BOX (hbox), pdata->omenu1, TRUE, TRUE, 0);
8338       
8339       check = gtk_check_button_new_with_label ("Running");
8340       g_signal_connect (check, "toggled",
8341                         G_CALLBACK (toggle_running),
8342                         pdata);
8343       gtk_table_attach (GTK_TABLE (tab), check, 0, 2, 1, 2,
8344                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
8345                         5, 5);
8346       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
8347
8348       check = gtk_check_button_new_with_label ("Show text");
8349       g_signal_connect (check, "clicked",
8350                         G_CALLBACK (toggle_show_text),
8351                         pdata);
8352       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 2, 3,
8353                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
8354                         5, 5);
8355
8356       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
8357       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 2, 3,
8358                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
8359                         5, 5);
8360
8361       label = gtk_label_new ("Text: ");
8362       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
8363
8364       pdata->entry = gtk_entry_new ();
8365       g_signal_connect (pdata->entry, "changed",
8366                         G_CALLBACK (entry_changed),
8367                         pdata);
8368       gtk_box_pack_start (GTK_BOX (hbox), pdata->entry, TRUE, TRUE, 0);
8369       gtk_widget_set_size_request (pdata->entry, 100, -1);
8370
8371       label = gtk_label_new ("Ellipsize text :");
8372       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 10, 11,
8373                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
8374                         5, 5);
8375       gtk_widget_set_halign (label, GTK_ALIGN_START);
8376       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
8377       pdata->elmenu = build_option_menu (ellipsize_items,
8378                                          sizeof (ellipsize_items) / sizeof (ellipsize_items[0]),
8379                                          2, // PANGO_ELLIPSIZE_MIDDLE
8380                                          progressbar_toggle_ellipsize,
8381                                          pdata);
8382       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
8383       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 10, 11,
8384                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
8385                         5, 5);
8386       gtk_box_pack_start (GTK_BOX (hbox), pdata->elmenu, TRUE, TRUE, 0);
8387
8388       check = gtk_check_button_new_with_label ("Activity mode");
8389       g_signal_connect (check, "clicked",
8390                         G_CALLBACK (toggle_activity_mode), pdata);
8391       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 15, 16,
8392                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
8393                         5, 5);
8394
8395       button = gtk_button_new_with_label ("close");
8396       g_signal_connect_swapped (button, "clicked",
8397                                 G_CALLBACK (gtk_widget_destroy),
8398                                 pdata->window);
8399       gtk_widget_set_can_default (button, TRUE);
8400       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
8401       gtk_widget_grab_default (button);
8402     }
8403
8404   if (!gtk_widget_get_visible (pdata->window))
8405     gtk_widget_show_all (pdata->window);
8406   else
8407     gtk_widget_destroy (pdata->window);
8408 }
8409
8410 /*
8411  * Properties
8412  */
8413
8414 typedef struct {
8415   int x;
8416   int y;
8417   gboolean found;
8418   gboolean first;
8419   GtkWidget *res_widget;
8420 } FindWidgetData;
8421
8422 static void
8423 find_widget (GtkWidget *widget, FindWidgetData *data)
8424 {
8425   GtkAllocation new_allocation;
8426   gint x_offset = 0;
8427   gint y_offset = 0;
8428
8429   gtk_widget_get_allocation (widget, &new_allocation);
8430
8431   if (data->found || !gtk_widget_get_mapped (widget))
8432     return;
8433
8434   /* Note that in the following code, we only count the
8435    * position as being inside a WINDOW widget if it is inside
8436    * widget->window; points that are outside of widget->window
8437    * but within the allocation are not counted. This is consistent
8438    * with the way we highlight drag targets.
8439    */
8440   if (gtk_widget_get_has_window (widget))
8441     {
8442       new_allocation.x = 0;
8443       new_allocation.y = 0;
8444     }
8445
8446   if (gtk_widget_get_parent (widget) && !data->first)
8447     {
8448       GdkWindow *window = gtk_widget_get_window (widget);
8449       while (window != gtk_widget_get_window (gtk_widget_get_parent (widget)))
8450         {
8451           gint tx, ty, twidth, theight;
8452           
8453           twidth = gdk_window_get_width (window);
8454           theight = gdk_window_get_height (window);
8455
8456           if (new_allocation.x < 0)
8457             {
8458               new_allocation.width += new_allocation.x;
8459               new_allocation.x = 0;
8460             }
8461           if (new_allocation.y < 0)
8462             {
8463               new_allocation.height += new_allocation.y;
8464               new_allocation.y = 0;
8465             }
8466           if (new_allocation.x + new_allocation.width > twidth)
8467             new_allocation.width = twidth - new_allocation.x;
8468           if (new_allocation.y + new_allocation.height > theight)
8469             new_allocation.height = theight - new_allocation.y;
8470
8471           gdk_window_get_position (window, &tx, &ty);
8472           new_allocation.x += tx;
8473           x_offset += tx;
8474           new_allocation.y += ty;
8475           y_offset += ty;
8476
8477           window = gdk_window_get_parent (window);
8478         }
8479     }
8480
8481   if ((data->x >= new_allocation.x) && (data->y >= new_allocation.y) &&
8482       (data->x < new_allocation.x + new_allocation.width) && 
8483       (data->y < new_allocation.y + new_allocation.height))
8484     {
8485       /* First, check if the drag is in a valid drop site in
8486        * one of our children 
8487        */
8488       if (GTK_IS_CONTAINER (widget))
8489         {
8490           FindWidgetData new_data = *data;
8491           
8492           new_data.x -= x_offset;
8493           new_data.y -= y_offset;
8494           new_data.found = FALSE;
8495           new_data.first = FALSE;
8496           
8497           gtk_container_forall (GTK_CONTAINER (widget),
8498                                 (GtkCallback)find_widget,
8499                                 &new_data);
8500           
8501           data->found = new_data.found;
8502           if (data->found)
8503             data->res_widget = new_data.res_widget;
8504         }
8505
8506       /* If not, and this widget is registered as a drop site, check to
8507        * emit "drag_motion" to check if we are actually in
8508        * a drop site.
8509        */
8510       if (!data->found)
8511         {
8512           data->found = TRUE;
8513           data->res_widget = widget;
8514         }
8515     }
8516 }
8517
8518 static GtkWidget *
8519 find_widget_at_pointer (GdkDevice *device)
8520 {
8521   GtkWidget *widget = NULL;
8522   GdkWindow *pointer_window;
8523   gint x, y;
8524   FindWidgetData data;
8525  
8526  pointer_window = gdk_device_get_window_at_position (device, NULL, NULL);
8527  
8528  if (pointer_window)
8529    {
8530      gpointer widget_ptr;
8531
8532      gdk_window_get_user_data (pointer_window, &widget_ptr);
8533      widget = widget_ptr;
8534    }
8535
8536  if (widget)
8537    {
8538      gdk_window_get_pointer (gtk_widget_get_window (widget),
8539                              &x, &y, NULL);
8540      
8541      data.x = x;
8542      data.y = y;
8543      data.found = FALSE;
8544      data.first = TRUE;
8545
8546      find_widget (widget, &data);
8547      if (data.found)
8548        return data.res_widget;
8549      return widget;
8550    }
8551  return NULL;
8552 }
8553
8554 struct PropertiesData {
8555   GtkWidget **window;
8556   GdkCursor *cursor;
8557   gboolean in_query;
8558   gulong handler;
8559 };
8560
8561 static void
8562 destroy_properties (GtkWidget             *widget,
8563                     struct PropertiesData *data)
8564 {
8565   if (data->window)
8566     {
8567       *data->window = NULL;
8568       data->window = NULL;
8569     }
8570
8571   if (data->cursor)
8572     {
8573       g_object_unref (data->cursor);
8574       data->cursor = NULL;
8575     }
8576
8577   if (data->handler)
8578     {
8579       g_signal_handler_disconnect (widget, data->handler);
8580       data->handler = 0;
8581     }
8582
8583   g_free (data);
8584 }
8585
8586 static gint
8587 property_query_event (GtkWidget             *widget,
8588                       GdkEvent              *event,
8589                       struct PropertiesData *data)
8590 {
8591   GtkWidget *res_widget = NULL;
8592
8593   if (!data->in_query)
8594     return FALSE;
8595
8596   if (event->type == GDK_BUTTON_RELEASE)
8597     {
8598       gtk_grab_remove (widget);
8599       gdk_device_ungrab (gdk_event_get_device (event), GDK_CURRENT_TIME);
8600
8601       res_widget = find_widget_at_pointer (gdk_event_get_device (event));
8602       if (res_widget)
8603         {
8604           g_object_set_data (G_OBJECT (res_widget), "prop-editor-screen",
8605                              gtk_widget_get_screen (widget));
8606           create_prop_editor (G_OBJECT (res_widget), 0);
8607         }
8608
8609       data->in_query = FALSE;
8610     }
8611   return FALSE;
8612 }
8613
8614
8615 static void
8616 query_properties (GtkButton *button,
8617                   struct PropertiesData *data)
8618 {
8619   GtkWidget *widget = GTK_WIDGET (button);
8620   GdkDisplay *display;
8621   GdkDeviceManager *device_manager;
8622   GdkDevice *device;
8623
8624   g_signal_connect (button, "event",
8625                     G_CALLBACK (property_query_event), data);
8626
8627   display = gtk_widget_get_display (widget);
8628
8629   if (!data->cursor)
8630     data->cursor = gdk_cursor_new_for_display (display, GDK_TARGET);
8631
8632   device_manager = gdk_display_get_device_manager (display);
8633   device = gdk_device_manager_get_client_pointer (device_manager);
8634   gdk_device_grab (device,
8635                    gtk_widget_get_window (widget),
8636                    GDK_OWNERSHIP_NONE,
8637                    TRUE,
8638                    GDK_BUTTON_RELEASE_MASK,
8639                    data->cursor,
8640                    GDK_CURRENT_TIME);
8641   gtk_grab_add (widget);
8642
8643   data->in_query = TRUE;
8644 }
8645
8646 static void
8647 create_properties (GtkWidget *widget)
8648 {
8649   static GtkWidget *window = NULL;
8650   GtkWidget *button;
8651   GtkWidget *vbox;
8652   GtkWidget *label;
8653   struct PropertiesData *data;
8654
8655   data = g_new (struct PropertiesData, 1);
8656   data->window = &window;
8657   data->in_query = FALSE;
8658   data->cursor = NULL;
8659   data->handler = 0;
8660
8661   if (!window)
8662     {
8663       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8664
8665       gtk_window_set_screen (GTK_WINDOW (window),
8666                              gtk_widget_get_screen (widget));      
8667
8668       data->handler = g_signal_connect (window, "destroy",
8669                                         G_CALLBACK (destroy_properties),
8670                                         data);
8671
8672       gtk_window_set_title (GTK_WINDOW (window), "test properties");
8673       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
8674
8675       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 1);
8676       gtk_container_add (GTK_CONTAINER (window), vbox);
8677             
8678       label = gtk_label_new ("This is just a dumb test to test properties.\nIf you need a generic module, get GLE.");
8679       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
8680       
8681       button = gtk_button_new_with_label ("Query properties");
8682       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
8683       g_signal_connect (button, "clicked",
8684                         G_CALLBACK (query_properties),
8685                         data);
8686     }
8687
8688   if (!gtk_widget_get_visible (window))
8689     gtk_widget_show_all (window);
8690   else
8691     gtk_widget_destroy (window);
8692   
8693 }
8694
8695 struct SnapshotData {
8696   GtkWidget *toplevel_button;
8697   GtkWidget **window;
8698   GdkCursor *cursor;
8699   gboolean in_query;
8700   gboolean is_toplevel;
8701   gint handler;
8702 };
8703
8704 static void
8705 destroy_snapshot_data (GtkWidget             *widget,
8706                        struct SnapshotData *data)
8707 {
8708   if (*data->window)
8709     *data->window = NULL;
8710   
8711   if (data->cursor)
8712     {
8713       g_object_unref (data->cursor);
8714       data->cursor = NULL;
8715     }
8716
8717   if (data->handler)
8718     {
8719       g_signal_handler_disconnect (widget, data->handler);
8720       data->handler = 0;
8721     }
8722
8723   g_free (data);
8724 }
8725
8726 static gint
8727 snapshot_widget_event (GtkWidget               *widget,
8728                        GdkEvent        *event,
8729                        struct SnapshotData *data)
8730 {
8731   GtkWidget *res_widget = NULL;
8732
8733   if (!data->in_query)
8734     return FALSE;
8735   
8736   if (event->type == GDK_BUTTON_RELEASE)
8737     {
8738       gtk_grab_remove (widget);
8739       gdk_device_ungrab (gdk_event_get_device (event),
8740                          GDK_CURRENT_TIME);
8741       
8742       res_widget = find_widget_at_pointer (gdk_event_get_device (event));
8743       if (data->is_toplevel && res_widget)
8744         res_widget = gtk_widget_get_toplevel (res_widget);
8745       if (res_widget)
8746         {
8747           cairo_surface_t *surface;
8748           GtkWidget *window, *image;
8749           GdkPixbuf *pixbuf;
8750           int width, height;
8751           cairo_t *cr;
8752
8753           width = gtk_widget_get_allocated_width (res_widget);
8754           height = gtk_widget_get_allocated_height (res_widget);
8755
8756           surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
8757
8758           cr = cairo_create (surface);
8759           gtk_widget_draw (res_widget, cr);
8760           cairo_destroy (cr);
8761
8762           pixbuf = gdk_pixbuf_get_from_surface (surface,
8763                                                 0, 0,
8764                                                 width, height);
8765           cairo_surface_destroy (surface);
8766
8767           window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8768           image = gtk_image_new_from_pixbuf (pixbuf);
8769           g_object_unref (pixbuf);
8770
8771           gtk_container_add (GTK_CONTAINER (window), image);
8772           gtk_widget_show_all (window);
8773         }
8774
8775       data->in_query = FALSE;
8776     }
8777   return FALSE;
8778 }
8779
8780
8781 static void
8782 snapshot_widget (GtkButton *button,
8783                  struct SnapshotData *data)
8784 {
8785   GtkWidget *widget = GTK_WIDGET (button);
8786   GdkDevice *device;
8787
8788   device = gtk_get_current_event_device ();
8789   if (device == NULL)
8790     return;
8791
8792   if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
8793     device = gdk_device_get_associated_device (device);
8794
8795   data->is_toplevel = widget == data->toplevel_button;
8796
8797   if (!data->cursor)
8798     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
8799                                                GDK_TARGET);
8800
8801   gdk_device_grab (device,
8802                    gtk_widget_get_window (widget),
8803                    GDK_OWNERSHIP_APPLICATION,
8804                    TRUE,
8805                    GDK_BUTTON_RELEASE_MASK,
8806                    data->cursor,
8807                    GDK_CURRENT_TIME);
8808
8809   g_signal_connect (button, "event",
8810                     G_CALLBACK (snapshot_widget_event), data);
8811
8812   gtk_grab_add (widget);
8813
8814   data->in_query = TRUE;
8815 }
8816
8817 static void
8818 create_snapshot (GtkWidget *widget)
8819 {
8820   static GtkWidget *window = NULL;
8821   GtkWidget *button;
8822   GtkWidget *vbox;
8823   struct SnapshotData *data;
8824
8825   data = g_new (struct SnapshotData, 1);
8826   data->window = &window;
8827   data->in_query = FALSE;
8828   data->cursor = NULL;
8829   data->handler = 0;
8830
8831   if (!window)
8832     {
8833       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8834
8835       gtk_window_set_screen (GTK_WINDOW (window),
8836                              gtk_widget_get_screen (widget));      
8837
8838       data->handler = g_signal_connect (window, "destroy",
8839                                         G_CALLBACK (destroy_snapshot_data),
8840                                         data);
8841
8842       gtk_window_set_title (GTK_WINDOW (window), "test snapshot");
8843       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
8844
8845       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 1);
8846       gtk_container_add (GTK_CONTAINER (window), vbox);
8847             
8848       button = gtk_button_new_with_label ("Snapshot widget");
8849       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
8850       g_signal_connect (button, "clicked",
8851                         G_CALLBACK (snapshot_widget),
8852                         data);
8853       
8854       button = gtk_button_new_with_label ("Snapshot toplevel");
8855       data->toplevel_button = button;
8856       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
8857       g_signal_connect (button, "clicked",
8858                         G_CALLBACK (snapshot_widget),
8859                         data);
8860     }
8861
8862   if (!gtk_widget_get_visible (window))
8863     gtk_widget_show_all (window);
8864   else
8865     gtk_widget_destroy (window);
8866   
8867 }
8868
8869 /*
8870  * Selection Test
8871  */
8872
8873 void
8874 selection_test_received (GtkWidget        *tree_view,
8875                          GtkSelectionData *selection_data)
8876 {
8877   GtkTreeModel *model;
8878   GtkListStore *store;
8879   GdkAtom *atoms;
8880   int i, l;
8881
8882   if (gtk_selection_data_get_length (selection_data) < 0)
8883     {
8884       g_print ("Selection retrieval failed\n");
8885       return;
8886     }
8887   if (gtk_selection_data_get_data_type (selection_data) != GDK_SELECTION_TYPE_ATOM)
8888     {
8889       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
8890       return;
8891     }
8892
8893   /* Clear out any current list items */
8894
8895   model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
8896   store = GTK_LIST_STORE (model);
8897   gtk_list_store_clear (store);
8898
8899   /* Add new items to list */
8900
8901   gtk_selection_data_get_targets (selection_data,
8902                                   &atoms, &l);
8903
8904   for (i = 0; i < l; i++)
8905     {
8906       char *name;
8907       GtkTreeIter iter;
8908
8909       name = gdk_atom_name (atoms[i]);
8910       if (name != NULL)
8911         {
8912           gtk_list_store_insert_with_values (store, &iter, i, 0, name, -1);
8913           g_free (name);
8914         }
8915       else
8916        gtk_list_store_insert_with_values (store, &iter, i, 0,  "(bad atom)", -1);
8917     }
8918
8919   return;
8920 }
8921
8922 void
8923 selection_test_get_targets (GtkWidget *widget, GtkWidget *tree_view)
8924 {
8925   static GdkAtom targets_atom = GDK_NONE;
8926
8927   if (targets_atom == GDK_NONE)
8928     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
8929
8930   gtk_selection_convert (tree_view, GDK_SELECTION_PRIMARY, targets_atom,
8931                          GDK_CURRENT_TIME);
8932 }
8933
8934 void
8935 create_selection_test (GtkWidget *widget)
8936 {
8937   static GtkWidget *window = NULL;
8938   GtkWidget *action_area, *content_area;
8939   GtkWidget *button;
8940   GtkWidget *vbox;
8941   GtkWidget *scrolled_win;
8942   GtkListStore* store;
8943   GtkWidget *tree_view;
8944   GtkTreeViewColumn *column;
8945   GtkCellRenderer *renderer;
8946   GtkWidget *label;
8947
8948   if (!window)
8949     {
8950       window = gtk_dialog_new ();
8951       
8952       gtk_window_set_screen (GTK_WINDOW (window),
8953                              gtk_widget_get_screen (widget));
8954
8955       g_signal_connect (window, "destroy",
8956                         G_CALLBACK (gtk_widget_destroyed),
8957                         &window);
8958
8959       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
8960       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
8961
8962       gtk_window_set_title (GTK_WINDOW (window), "Selection Test");
8963       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8964
8965       /* Create the list */
8966
8967       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
8968       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
8969       gtk_box_pack_start (GTK_BOX (content_area), vbox, TRUE, TRUE, 0);
8970
8971       label = gtk_label_new ("Gets available targets for current selection");
8972       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
8973
8974       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
8975       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
8976                                       GTK_POLICY_AUTOMATIC, 
8977                                       GTK_POLICY_AUTOMATIC);
8978       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
8979       gtk_widget_set_size_request (scrolled_win, 100, 200);
8980
8981       store = gtk_list_store_new (1, G_TYPE_STRING);
8982       tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
8983       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), tree_view);
8984
8985       renderer = gtk_cell_renderer_text_new ();
8986       column = gtk_tree_view_column_new_with_attributes ("Target", renderer,
8987                                                          "text", 0, NULL);
8988       gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
8989
8990       g_signal_connect (tree_view, "selection_received",
8991                         G_CALLBACK (selection_test_received), NULL);
8992
8993       /* .. And create some buttons */
8994       button = gtk_button_new_with_label ("Get Targets");
8995       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
8996
8997       g_signal_connect (button, "clicked",
8998                         G_CALLBACK (selection_test_get_targets), tree_view);
8999
9000       button = gtk_button_new_with_label ("Quit");
9001       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9002
9003       g_signal_connect_swapped (button, "clicked",
9004                                 G_CALLBACK (gtk_widget_destroy),
9005                                 window);
9006     }
9007
9008   if (!gtk_widget_get_visible (window))
9009     gtk_widget_show_all (window);
9010   else
9011     gtk_widget_destroy (window);
9012 }
9013
9014 /*
9015  * Test scrolling
9016  */
9017
9018 static int scroll_test_pos = 0.0;
9019
9020 static gint
9021 scroll_test_draw (GtkWidget     *widget,
9022                   cairo_t       *cr,
9023                   GtkAdjustment *adjustment)
9024 {
9025   gint i,j;
9026   gint imin, imax, jmin, jmax;
9027   GdkRectangle clip;
9028   
9029   gdk_cairo_get_clip_rectangle (cr, &clip);
9030
9031   imin = (clip.x) / 10;
9032   imax = (clip.x + clip.width + 9) / 10;
9033
9034   jmin = ((int)gtk_adjustment_get_value (adjustment) + clip.y) / 10;
9035   jmax = ((int)gtk_adjustment_get_value (adjustment) + clip.y + clip.height + 9) / 10;
9036
9037   for (i=imin; i<imax; i++)
9038     for (j=jmin; j<jmax; j++)
9039       if ((i+j) % 2)
9040         cairo_rectangle (cr, 10*i, 10*j - (int)gtk_adjustment_get_value (adjustment), 1+i%10, 1+j%10);
9041
9042   cairo_fill (cr);
9043
9044   return TRUE;
9045 }
9046
9047 static gint
9048 scroll_test_scroll (GtkWidget *widget, GdkEventScroll *event,
9049                     GtkAdjustment *adjustment)
9050 {
9051   gdouble new_value = gtk_adjustment_get_value (adjustment) + ((event->direction == GDK_SCROLL_UP) ?
9052                                     -gtk_adjustment_get_page_increment (adjustment) / 2:
9053                                     gtk_adjustment_get_page_increment (adjustment) / 2);
9054   new_value = CLAMP (new_value, gtk_adjustment_get_lower (adjustment), gtk_adjustment_get_upper (adjustment) - gtk_adjustment_get_page_size (adjustment));
9055   gtk_adjustment_set_value (adjustment, new_value);  
9056   
9057   return TRUE;
9058 }
9059
9060 static void
9061 scroll_test_configure (GtkWidget *widget, GdkEventConfigure *event,
9062                        GtkAdjustment *adjustment)
9063 {
9064   GtkAllocation allocation;
9065
9066   gtk_widget_get_allocation (widget, &allocation);
9067   gtk_adjustment_configure (adjustment,
9068                             gtk_adjustment_get_value (adjustment),
9069                             gtk_adjustment_get_lower (adjustment),
9070                             gtk_adjustment_get_upper (adjustment),
9071                             0.1 * allocation.height,
9072                             0.9 * allocation.height,
9073                             allocation.height);
9074 }
9075
9076 static void
9077 scroll_test_adjustment_changed (GtkAdjustment *adjustment, GtkWidget *widget)
9078 {
9079   GdkWindow *window;
9080   gint dy;
9081
9082   dy = scroll_test_pos - (int)gtk_adjustment_get_value (adjustment);
9083   scroll_test_pos = gtk_adjustment_get_value (adjustment);
9084
9085   if (!gtk_widget_is_drawable (widget))
9086     return;
9087
9088   window = gtk_widget_get_window (widget);
9089   gdk_window_scroll (window, 0, dy);
9090   gdk_window_process_updates (window, FALSE);
9091 }
9092
9093
9094 void
9095 create_scroll_test (GtkWidget *widget)
9096 {
9097   static GtkWidget *window = NULL;
9098   GtkWidget *action_area, *content_area;
9099   GtkWidget *hbox;
9100   GtkWidget *drawing_area;
9101   GtkWidget *scrollbar;
9102   GtkWidget *button;
9103   GtkAdjustment *adjustment;
9104   GdkGeometry geometry;
9105   GdkWindowHints geometry_mask;
9106
9107   if (!window)
9108     {
9109       window = gtk_dialog_new ();
9110
9111       gtk_window_set_screen (GTK_WINDOW (window),
9112                              gtk_widget_get_screen (widget));
9113
9114       g_signal_connect (window, "destroy",
9115                         G_CALLBACK (gtk_widget_destroyed),
9116                         &window);
9117
9118       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9119       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9120
9121       gtk_window_set_title (GTK_WINDOW (window), "Scroll Test");
9122       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9123
9124       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
9125       gtk_box_pack_start (GTK_BOX (content_area), hbox, TRUE, TRUE, 0);
9126       gtk_widget_show (hbox);
9127
9128       drawing_area = gtk_drawing_area_new ();
9129       gtk_widget_set_size_request (drawing_area, 200, 200);
9130       gtk_box_pack_start (GTK_BOX (hbox), drawing_area, TRUE, TRUE, 0);
9131       gtk_widget_show (drawing_area);
9132
9133       gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK | GDK_SCROLL_MASK);
9134
9135       adjustment = gtk_adjustment_new (0.0, 0.0, 1000.0, 1.0, 180.0, 200.0);
9136       scroll_test_pos = 0.0;
9137
9138       scrollbar = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, adjustment);
9139       gtk_box_pack_start (GTK_BOX (hbox), scrollbar, FALSE, FALSE, 0);
9140       gtk_widget_show (scrollbar);
9141
9142       g_signal_connect (drawing_area, "draw",
9143                         G_CALLBACK (scroll_test_draw), adjustment);
9144       g_signal_connect (drawing_area, "configure_event",
9145                         G_CALLBACK (scroll_test_configure), adjustment);
9146       g_signal_connect (drawing_area, "scroll_event",
9147                         G_CALLBACK (scroll_test_scroll), adjustment);
9148       
9149       g_signal_connect (adjustment, "value_changed",
9150                         G_CALLBACK (scroll_test_adjustment_changed),
9151                         drawing_area);
9152       
9153       /* .. And create some buttons */
9154
9155       button = gtk_button_new_with_label ("Quit");
9156       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9157
9158       g_signal_connect_swapped (button, "clicked",
9159                                 G_CALLBACK (gtk_widget_destroy),
9160                                 window);
9161       gtk_widget_show (button);
9162
9163       /* Set up gridded geometry */
9164
9165       geometry_mask = GDK_HINT_MIN_SIZE | 
9166                        GDK_HINT_BASE_SIZE | 
9167                        GDK_HINT_RESIZE_INC;
9168
9169       geometry.min_width = 20;
9170       geometry.min_height = 20;
9171       geometry.base_width = 0;
9172       geometry.base_height = 0;
9173       geometry.width_inc = 10;
9174       geometry.height_inc = 10;
9175       
9176       gtk_window_set_geometry_hints (GTK_WINDOW (window),
9177                                drawing_area, &geometry, geometry_mask);
9178     }
9179
9180   if (!gtk_widget_get_visible (window))
9181     gtk_widget_show (window);
9182   else
9183     gtk_widget_destroy (window);
9184 }
9185
9186 /*
9187  * Timeout Test
9188  */
9189
9190 static int timer = 0;
9191
9192 gint
9193 timeout_test (GtkWidget *label)
9194 {
9195   static int count = 0;
9196   static char buffer[32];
9197
9198   sprintf (buffer, "count: %d", ++count);
9199   gtk_label_set_text (GTK_LABEL (label), buffer);
9200
9201   return TRUE;
9202 }
9203
9204 void
9205 start_timeout_test (GtkWidget *widget,
9206                     GtkWidget *label)
9207 {
9208   if (!timer)
9209     {
9210       timer = g_timeout_add (100, (GSourceFunc)timeout_test, label);
9211     }
9212 }
9213
9214 void
9215 stop_timeout_test (GtkWidget *widget,
9216                    gpointer   data)
9217 {
9218   if (timer)
9219     {
9220       g_source_remove (timer);
9221       timer = 0;
9222     }
9223 }
9224
9225 void
9226 destroy_timeout_test (GtkWidget  *widget,
9227                       GtkWidget **window)
9228 {
9229   stop_timeout_test (NULL, NULL);
9230
9231   *window = NULL;
9232 }
9233
9234 void
9235 create_timeout_test (GtkWidget *widget)
9236 {
9237   static GtkWidget *window = NULL;
9238   GtkWidget *action_area, *content_area;
9239   GtkWidget *button;
9240   GtkWidget *label;
9241
9242   if (!window)
9243     {
9244       window = gtk_dialog_new ();
9245
9246       gtk_window_set_screen (GTK_WINDOW (window),
9247                              gtk_widget_get_screen (widget));
9248
9249       g_signal_connect (window, "destroy",
9250                         G_CALLBACK (destroy_timeout_test),
9251                         &window);
9252
9253       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9254       action_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9255
9256       gtk_window_set_title (GTK_WINDOW (window), "Timeout Test");
9257       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9258
9259       label = gtk_label_new ("count: 0");
9260       g_object_set (label, "margin", 10, NULL);
9261       gtk_box_pack_start (GTK_BOX (content_area), label, TRUE, TRUE, 0);
9262       gtk_widget_show (label);
9263
9264       button = gtk_button_new_with_label ("close");
9265       g_signal_connect_swapped (button, "clicked",
9266                                 G_CALLBACK (gtk_widget_destroy),
9267                                 window);
9268       gtk_widget_set_can_default (button, TRUE);
9269       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9270       gtk_widget_grab_default (button);
9271       gtk_widget_show (button);
9272
9273       button = gtk_button_new_with_label ("start");
9274       g_signal_connect (button, "clicked",
9275                         G_CALLBACK(start_timeout_test),
9276                         label);
9277       gtk_widget_set_can_default (button, TRUE);
9278       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9279       gtk_widget_show (button);
9280
9281       button = gtk_button_new_with_label ("stop");
9282       g_signal_connect (button, "clicked",
9283                         G_CALLBACK (stop_timeout_test),
9284                         NULL);
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
9290   if (!gtk_widget_get_visible (window))
9291     gtk_widget_show (window);
9292   else
9293     gtk_widget_destroy (window);
9294 }
9295
9296 /*
9297  * Idle Test
9298  */
9299
9300 static int idle_id = 0;
9301
9302 static gint
9303 idle_test (GtkWidget *label)
9304 {
9305   static int count = 0;
9306   static char buffer[32];
9307
9308   sprintf (buffer, "count: %d", ++count);
9309   gtk_label_set_text (GTK_LABEL (label), buffer);
9310
9311   return TRUE;
9312 }
9313
9314 static void
9315 start_idle_test (GtkWidget *widget,
9316                  GtkWidget *label)
9317 {
9318   if (!idle_id)
9319     {
9320       idle_id = g_idle_add ((GSourceFunc) idle_test, label);
9321     }
9322 }
9323
9324 static void
9325 stop_idle_test (GtkWidget *widget,
9326                 gpointer   data)
9327 {
9328   if (idle_id)
9329     {
9330       g_source_remove (idle_id);
9331       idle_id = 0;
9332     }
9333 }
9334
9335 static void
9336 destroy_idle_test (GtkWidget  *widget,
9337                    GtkWidget **window)
9338 {
9339   stop_idle_test (NULL, NULL);
9340
9341   *window = NULL;
9342 }
9343
9344 static void
9345 toggle_idle_container (GObject *button,
9346                        GtkContainer *container)
9347 {
9348   gtk_container_set_resize_mode (container, GPOINTER_TO_INT (g_object_get_data (button, "user_data")));
9349 }
9350
9351 static void
9352 create_idle_test (GtkWidget *widget)
9353 {
9354   static GtkWidget *window = NULL;
9355   GtkWidget *button;
9356   GtkWidget *label;
9357   GtkWidget *container;
9358
9359   if (!window)
9360     {
9361       GtkWidget *action_area, *content_area;
9362       GtkWidget *button2;
9363       GtkWidget *frame;
9364       GtkWidget *box;
9365
9366       window = gtk_dialog_new ();
9367
9368       gtk_window_set_screen (GTK_WINDOW (window),
9369                              gtk_widget_get_screen (widget));
9370
9371       g_signal_connect (window, "destroy",
9372                         G_CALLBACK (destroy_idle_test),
9373                         &window);
9374
9375       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9376       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9377
9378       gtk_window_set_title (GTK_WINDOW (window), "Idle Test");
9379       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9380
9381       label = gtk_label_new ("count: 0");
9382       g_object_set (label, "margin", 10, NULL);
9383       gtk_widget_show (label);
9384       
9385       container =
9386         g_object_new (GTK_TYPE_BOX,
9387                         "visible", TRUE,
9388                         /* "GtkContainer::child", g_object_new (GTK_TYPE_HBOX,
9389                          * "GtkWidget::visible", TRUE,
9390                          */
9391                          "child", label,
9392                         /* NULL), */
9393                         NULL);
9394       gtk_box_pack_start (GTK_BOX (content_area), container, TRUE, TRUE, 0);
9395
9396       frame =
9397         g_object_new (GTK_TYPE_FRAME,
9398                         "border_width", 5,
9399                         "label", "Label Container",
9400                         "visible", TRUE,
9401                         "parent", content_area,
9402                         NULL);
9403       box =
9404         g_object_new (GTK_TYPE_BOX,
9405                         "visible", TRUE,
9406                         "parent", frame,
9407                         "orientation", GTK_ORIENTATION_VERTICAL,
9408                         NULL);
9409       button =
9410         g_object_connect (g_object_new (GTK_TYPE_RADIO_BUTTON,
9411                                           "label", "Resize-Parent",
9412                                           "user_data", (void*)GTK_RESIZE_PARENT,
9413                                           "visible", TRUE,
9414                                           "parent", box,
9415                                           NULL),
9416                           "signal::clicked", toggle_idle_container, container,
9417                           NULL);
9418       button = g_object_new (GTK_TYPE_RADIO_BUTTON,
9419                                "label", "Resize-Queue",
9420                                "user_data", (void*)GTK_RESIZE_QUEUE,
9421                                "group", button,
9422                                "visible", TRUE,
9423                                "parent", box,
9424                                NULL);
9425       g_object_connect (button,
9426                         "signal::clicked", toggle_idle_container, container,
9427                         NULL);
9428       button2 = g_object_new (GTK_TYPE_RADIO_BUTTON,
9429                                 "label", "Resize-Immediate",
9430                                 "user_data", (void*)GTK_RESIZE_IMMEDIATE,
9431                                 NULL);
9432       g_object_connect (button2,
9433                         "signal::clicked", toggle_idle_container, container,
9434                         NULL);
9435       g_object_set (button2,
9436                     "group", button,
9437                     "visible", TRUE,
9438                     "parent", box,
9439                     NULL);
9440
9441       button = gtk_button_new_with_label ("close");
9442       g_signal_connect_swapped (button, "clicked",
9443                                 G_CALLBACK (gtk_widget_destroy),
9444                                 window);
9445       gtk_widget_set_can_default (button, TRUE);
9446       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9447       gtk_widget_grab_default (button);
9448       gtk_widget_show (button);
9449
9450       button = gtk_button_new_with_label ("start");
9451       g_signal_connect (button, "clicked",
9452                         G_CALLBACK (start_idle_test),
9453                         label);
9454       gtk_widget_set_can_default (button, TRUE);
9455       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9456       gtk_widget_show (button);
9457
9458       button = gtk_button_new_with_label ("stop");
9459       g_signal_connect (button, "clicked",
9460                         G_CALLBACK (stop_idle_test),
9461                         NULL);
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
9467   if (!gtk_widget_get_visible (window))
9468     gtk_widget_show (window);
9469   else
9470     gtk_widget_destroy (window);
9471 }
9472
9473 /*
9474  * rc file test
9475  */
9476
9477 void
9478 create_rc_file (GtkWidget *widget)
9479 {
9480   static GtkWidget *window = NULL;
9481   GtkWidget *action_area, *content_area;
9482   GtkWidget *button;
9483   GtkWidget *frame;
9484   GtkWidget *vbox;
9485   GtkWidget *label;
9486
9487   if (!window)
9488     {
9489       window = gtk_dialog_new ();
9490
9491       gtk_window_set_screen (GTK_WINDOW (window),
9492                              gtk_widget_get_screen (widget));
9493
9494       g_signal_connect (window, "destroy",
9495                         G_CALLBACK (gtk_widget_destroyed),
9496                         &window);
9497
9498       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9499       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9500
9501       frame = gtk_aspect_frame_new ("Testing RC file prioritization", 0.5, 0.5, 0.0, TRUE);
9502       gtk_box_pack_start (GTK_BOX (content_area), frame, FALSE, FALSE, 0);
9503
9504       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
9505       gtk_container_add (GTK_CONTAINER (frame), vbox);
9506       
9507       label = gtk_label_new ("This label should be red");
9508       gtk_widget_set_name (label, "testgtk-red-label");
9509       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9510
9511       label = gtk_label_new ("This label should be green");
9512       gtk_widget_set_name (label, "testgtk-green-label");
9513       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9514
9515       label = gtk_label_new ("This label should be blue");
9516       gtk_widget_set_name (label, "testgtk-blue-label");
9517       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9518
9519       gtk_window_set_title (GTK_WINDOW (window), "Reload Rc file");
9520       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9521
9522       button = gtk_button_new_with_label ("Reload");
9523       g_signal_connect_swapped (button, "clicked",
9524                                 G_CALLBACK (gtk_style_context_reset_widgets),
9525                                 gtk_widget_get_screen (button));
9526       gtk_widget_set_can_default (button, TRUE);
9527       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9528       gtk_widget_grab_default (button);
9529
9530       button = gtk_button_new_with_label ("Close");
9531       g_signal_connect_swapped (button, "clicked",
9532                                 G_CALLBACK (gtk_widget_destroy),
9533                                 window);
9534       gtk_widget_set_can_default (button, TRUE);
9535       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9536     }
9537
9538   if (!gtk_widget_get_visible (window))
9539     gtk_widget_show_all (window);
9540   else
9541     gtk_widget_destroy (window);
9542 }
9543
9544 /*
9545  * Test of recursive mainloop
9546  */
9547
9548 void
9549 mainloop_destroyed (GtkWidget *w, GtkWidget **window)
9550 {
9551   *window = NULL;
9552   gtk_main_quit ();
9553 }
9554
9555 void
9556 create_mainloop (GtkWidget *widget)
9557 {
9558   static GtkWidget *window = NULL;
9559   GtkWidget *action_area, *content_area;
9560   GtkWidget *label;
9561   GtkWidget *button;
9562
9563   if (!window)
9564     {
9565       window = gtk_dialog_new ();
9566
9567       gtk_window_set_screen (GTK_WINDOW (window),
9568                              gtk_widget_get_screen (widget));
9569
9570       gtk_window_set_title (GTK_WINDOW (window), "Test Main Loop");
9571
9572       g_signal_connect (window, "destroy",
9573                         G_CALLBACK (mainloop_destroyed),
9574                         &window);
9575
9576       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9577       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9578
9579       label = gtk_label_new ("In recursive main loop...");
9580       g_object_set (label, "margin", 20, NULL);
9581
9582       gtk_box_pack_start (GTK_BOX (content_area), label, TRUE, TRUE, 0);
9583       gtk_widget_show (label);
9584
9585       button = gtk_button_new_with_label ("Leave");
9586       gtk_box_pack_start (GTK_BOX (action_area), button, FALSE, TRUE, 0);
9587
9588       g_signal_connect_swapped (button, "clicked",
9589                                 G_CALLBACK (gtk_widget_destroy),
9590                                 window);
9591
9592       gtk_widget_set_can_default (button, TRUE);
9593       gtk_widget_grab_default (button);
9594
9595       gtk_widget_show (button);
9596     }
9597
9598   if (!gtk_widget_get_visible (window))
9599     {
9600       gtk_widget_show (window);
9601
9602       g_print ("create_mainloop: start\n");
9603       gtk_main ();
9604       g_print ("create_mainloop: done\n");
9605     }
9606   else
9607     gtk_widget_destroy (window);
9608 }
9609
9610 static gboolean
9611 layout_draw_handler (GtkWidget *widget, cairo_t *cr)
9612 {
9613   GtkLayout *layout;
9614   GdkWindow *bin_window;
9615   GdkRectangle clip;
9616   gint i,j,x,y;
9617   gint imin, imax, jmin, jmax;
9618
9619   layout = GTK_LAYOUT (widget);
9620   bin_window = gtk_layout_get_bin_window (layout);
9621
9622   if (!gtk_cairo_should_draw_window (cr, bin_window))
9623     return FALSE;
9624   
9625   gdk_window_get_position (bin_window, &x, &y);
9626   cairo_translate (cr, x, y);
9627
9628   gdk_cairo_get_clip_rectangle (cr, &clip);
9629
9630   imin = (clip.x) / 10;
9631   imax = (clip.x + clip.width + 9) / 10;
9632
9633   jmin = (clip.y) / 10;
9634   jmax = (clip.y + clip.height + 9) / 10;
9635
9636   for (i=imin; i<imax; i++)
9637     for (j=jmin; j<jmax; j++)
9638       if ((i+j) % 2)
9639         cairo_rectangle (cr,
9640                          10*i, 10*j, 
9641                          1+i%10, 1+j%10);
9642   
9643   cairo_fill (cr);
9644
9645   return FALSE;
9646 }
9647
9648 void create_layout (GtkWidget *widget)
9649 {
9650   GtkAdjustment *hadjustment, *vadjustment;
9651   GtkLayout *layout;
9652   static GtkWidget *window = NULL;
9653   GtkWidget *layout_widget;
9654   GtkWidget *scrolledwindow;
9655   GtkWidget *button;
9656
9657   if (!window)
9658     {
9659       gchar buf[16];
9660
9661       gint i, j;
9662       
9663       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9664       gtk_window_set_screen (GTK_WINDOW (window),
9665                              gtk_widget_get_screen (widget));
9666
9667       g_signal_connect (window, "destroy",
9668                         G_CALLBACK (gtk_widget_destroyed),
9669                         &window);
9670
9671       gtk_window_set_title (GTK_WINDOW (window), "Layout");
9672       gtk_widget_set_size_request (window, 200, 200);
9673
9674       scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
9675       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
9676                                            GTK_SHADOW_IN);
9677       gtk_scrolled_window_set_placement (GTK_SCROLLED_WINDOW (scrolledwindow),
9678                                          GTK_CORNER_TOP_RIGHT);
9679
9680       gtk_container_add (GTK_CONTAINER (window), scrolledwindow);
9681
9682       layout_widget = gtk_layout_new (NULL, NULL);
9683       layout = GTK_LAYOUT (layout_widget);
9684       gtk_container_add (GTK_CONTAINER (scrolledwindow), layout_widget);
9685
9686       /* We set step sizes here since GtkLayout does not set
9687        * them itself.
9688        */
9689       hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (layout));
9690       vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (layout));
9691       gtk_adjustment_set_step_increment (hadjustment, 10.0);
9692       gtk_adjustment_set_step_increment (vadjustment, 10.0);
9693       gtk_scrollable_set_hadjustment (GTK_SCROLLABLE (layout), hadjustment);
9694       gtk_scrollable_set_vadjustment (GTK_SCROLLABLE (layout), vadjustment);
9695
9696       gtk_widget_set_events (layout_widget, GDK_EXPOSURE_MASK);
9697       g_signal_connect (layout, "draw",
9698                         G_CALLBACK (layout_draw_handler), NULL);
9699
9700       gtk_layout_set_size (layout, 1600, 128000);
9701
9702       for (i=0 ; i < 16 ; i++)
9703         for (j=0 ; j < 16 ; j++)
9704           {
9705             sprintf(buf, "Button %d, %d", i, j);
9706             if ((i + j) % 2)
9707               button = gtk_button_new_with_label (buf);
9708             else
9709               button = gtk_label_new (buf);
9710
9711             gtk_layout_put (layout, button, j*100, i*100);
9712           }
9713
9714       for (i=16; i < 1280; i++)
9715         {
9716           sprintf(buf, "Button %d, %d", i, 0);
9717           if (i % 2)
9718             button = gtk_button_new_with_label (buf);
9719           else
9720             button = gtk_label_new (buf);
9721
9722           gtk_layout_put (layout, button, 0, i*100);
9723         }
9724     }
9725
9726   if (!gtk_widget_get_visible (window))
9727     gtk_widget_show_all (window);
9728   else
9729     gtk_widget_destroy (window);
9730 }
9731
9732 #if 0
9733 /* FIXME: need to completely redo this for GtkStyleContext */
9734 void
9735 create_styles (GtkWidget *widget)
9736 {
9737   static GtkWidget *window = NULL;
9738   GtkWidget *content_area, *action_area;
9739   GtkWidget *label;
9740   GtkWidget *button;
9741   GtkWidget *entry;
9742   GtkWidget *vbox;
9743   static GdkRGBA red =    { 1,0,0,1 };
9744   static GdkRGBA green =  { 0,1,0,1 };
9745   static GdkRGBA blue =   { 0,0,1,1 };
9746   static GdkRGBA yellow = { 1,1,0,1 };
9747   static GdkRGBA cyan =   { 0,1,1,1 };
9748   PangoFontDescription *font_desc;
9749
9750   GtkRcStyle *rc_style;
9751
9752   if (!window)
9753     {
9754       window = gtk_dialog_new ();
9755       gtk_window_set_screen (GTK_WINDOW (window),
9756                              gtk_widget_get_screen (widget));
9757      
9758       g_signal_connect (window, "destroy",
9759                         G_CALLBACK (gtk_widget_destroyed),
9760                         &window);
9761
9762       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9763       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9764
9765       button = gtk_button_new_with_label ("Close");
9766       g_signal_connect_swapped (button, "clicked",
9767                                 G_CALLBACK (gtk_widget_destroy),
9768                                 window);
9769       gtk_widget_set_can_default (button, TRUE);
9770       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9771       gtk_widget_show (button);
9772
9773       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
9774       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
9775       gtk_box_pack_start (GTK_BOX (content_area), vbox, FALSE, FALSE, 0);
9776       
9777       label = gtk_label_new ("Font:");
9778       gtk_widget_set_halign (label, GTK_ALIGN_START);
9779       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9780       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9781
9782       font_desc = pango_font_description_from_string ("Helvetica,Sans Oblique 18");
9783
9784       button = gtk_button_new_with_label ("Some Text");
9785       gtk_widget_override_font (gtk_bin_get_child (GTK_BIN (button)), font_desc);
9786       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9787
9788       label = gtk_label_new ("Foreground:");
9789       gtk_widget_set_halign (label, GTK_ALIGN_START);
9790       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9791       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9792
9793       button = gtk_button_new_with_label ("Some Text");
9794       gtk_widget_override_color (gtk_bin_get_child (GTK_BIN (button)), 0, &red);
9795       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9796
9797       label = gtk_label_new ("Background:");
9798       gtk_widget_set_halign (label, GTK_ALIGN_START);
9799       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9800       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9801
9802       button = gtk_button_new_with_label ("Some Text");
9803       gtk_widget_override_background_color (button, 0, &green);
9804       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9805
9806       label = gtk_label_new ("Text:");
9807       gtk_widget_set_halign (label, GTK_ALIGN_START);
9808       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9809       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9810
9811       entry = gtk_entry_new ();
9812       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
9813       gtk_widget_override_color (entry, 0, &blue);
9814       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
9815
9816       label = gtk_label_new ("Base:");
9817       gtk_widget_set_halign (label, GTK_ALIGN_START);
9818       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9819       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9820
9821       entry = gtk_entry_new ();
9822       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
9823       gtk_widget_override_background_color (entry, 0, &yellow);
9824       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
9825
9826       label = gtk_label_new ("Cursor:");
9827       gtk_widget_set_halign (label, GTK_ALIGN_START);
9828       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9829       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9830
9831       entry = gtk_entry_new ();
9832       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
9833       gtk_widget_modify_cursor (entry, &red, &red);
9834       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
9835
9836       label = gtk_label_new ("Multiple:");
9837       gtk_widget_set_halign (label, GTK_ALIGN_START);
9838       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9839       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9840
9841       button = gtk_button_new_with_label ("Some Text");
9842
9843       rc_style = gtk_rc_style_new ();
9844
9845       rc_style->font_desc = pango_font_description_copy (font_desc);
9846       rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG | GTK_RC_BG;
9847       rc_style->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_FG | GTK_RC_BG;
9848       rc_style->color_flags[GTK_STATE_ACTIVE] = GTK_RC_FG | GTK_RC_BG;
9849       rc_style->fg[GTK_STATE_NORMAL] = yellow;
9850       rc_style->bg[GTK_STATE_NORMAL] = blue;
9851       rc_style->fg[GTK_STATE_PRELIGHT] = blue;
9852       rc_style->bg[GTK_STATE_PRELIGHT] = yellow;
9853       rc_style->fg[GTK_STATE_ACTIVE] = red;
9854       rc_style->bg[GTK_STATE_ACTIVE] = cyan;
9855       rc_style->xthickness = 5;
9856       rc_style->ythickness = 5;
9857
9858       gtk_widget_modify_style (button, rc_style);
9859       gtk_widget_modify_style (gtk_bin_get_child (GTK_BIN (button)), rc_style);
9860
9861       g_object_unref (rc_style);
9862       
9863       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9864     }
9865   
9866   if (!gtk_widget_get_visible (window))
9867     gtk_widget_show_all (window);
9868   else
9869     gtk_widget_destroy (window);
9870 }
9871 #endif
9872
9873 /*
9874  * Main Window and Exit
9875  */
9876
9877 void
9878 do_exit (GtkWidget *widget, GtkWidget *window)
9879 {
9880   gtk_widget_destroy (window);
9881   gtk_main_quit ();
9882 }
9883
9884 struct {
9885   char *label;
9886   void (*func) (GtkWidget *widget);
9887   gboolean do_not_benchmark;
9888 } buttons[] =
9889 {
9890   { "alpha window", create_alpha_window },
9891   { "big windows", create_big_windows },
9892   { "button box", create_button_box },
9893   { "buttons", create_buttons },
9894   { "check buttons", create_check_buttons },
9895   { "color selection", create_color_selection },
9896   { "composited window", create_composited_window },
9897   { "cursors", create_cursors },
9898   { "dialog", create_dialog },
9899   { "display & screen", create_display_screen, TRUE },
9900   { "entry", create_entry },
9901   { "event box", create_event_box },
9902   { "event watcher", create_event_watcher },
9903   { "expander", create_expander },
9904   { "flipping", create_flipping },
9905   { "focus", create_focus },
9906   { "font selection", create_font_selection },
9907   { "handle box", create_handle_box },
9908   { "image", create_image },
9909   { "key lookup", create_key_lookup },
9910   { "labels", create_labels },
9911   { "layout", create_layout },
9912   { "menus", create_menus },
9913   { "message dialog", create_message_dialog },
9914   { "modal window", create_modal_window, TRUE },
9915   { "notebook", create_notebook },
9916   { "panes", create_panes },
9917   { "paned keyboard", create_paned_keyboard_navigation },
9918   { "pixbuf", create_pixbuf },
9919   { "progress bar", create_progress_bar },
9920   { "properties", create_properties },
9921   { "radio buttons", create_radio_buttons },
9922   { "range controls", create_range_controls },
9923   { "rc file", create_rc_file },
9924   { "reparent", create_reparent },
9925   { "resize grips", create_resize_grips },
9926   { "rotated label", create_rotated_label },
9927   { "rotated text", create_rotated_text },
9928   { "saved position", create_saved_position },
9929   { "scrolled windows", create_scrolled_windows },
9930   { "shapes", create_shapes },
9931   { "size groups", create_size_groups },
9932   { "snapshot", create_snapshot },
9933   { "spinbutton", create_spins },
9934   { "statusbar", create_statusbar },
9935 #if 0
9936   { "styles", create_styles },
9937 #endif
9938   { "test idle", create_idle_test },
9939   { "test mainloop", create_mainloop, TRUE },
9940   { "test scrolling", create_scroll_test },
9941   { "test selection", create_selection_test },
9942   { "test timeout", create_timeout_test },
9943   { "toggle buttons", create_toggle_buttons },
9944   { "toolbar", create_toolbar },
9945   { "tooltips", create_tooltips },
9946   { "WM hints", create_wmhints },
9947   { "window sizing", create_window_sizing },
9948   { "window states", create_window_states }
9949 };
9950 int nbuttons = sizeof (buttons) / sizeof (buttons[0]);
9951
9952 void
9953 create_main_window (void)
9954 {
9955   GtkWidget *window;
9956   GtkWidget *box1;
9957   GtkWidget *box2;
9958   GtkWidget *scrolled_window;
9959   GtkWidget *button;
9960   GtkWidget *label;
9961   gchar buffer[64];
9962   GtkWidget *separator;
9963   GdkGeometry geometry;
9964   int i;
9965
9966   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9967   gtk_widget_set_name (window, "main_window");
9968   gtk_window_move (GTK_WINDOW (window), 50, 20);
9969   gtk_window_set_default_size (GTK_WINDOW (window), -1, 400);
9970
9971   geometry.min_width = -1;
9972   geometry.min_height = -1;
9973   geometry.max_width = -1;
9974   geometry.max_height = G_MAXSHORT;
9975   gtk_window_set_geometry_hints (GTK_WINDOW (window), NULL,
9976                                  &geometry,
9977                                  GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
9978
9979   g_signal_connect (window, "destroy",
9980                     G_CALLBACK (gtk_main_quit),
9981                     NULL);
9982   g_signal_connect (window, "delete-event",
9983                     G_CALLBACK (gtk_false),
9984                     NULL);
9985
9986   box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
9987   gtk_container_add (GTK_CONTAINER (window), box1);
9988
9989   if (gtk_micro_version > 0)
9990     sprintf (buffer,
9991              "Gtk+ v%d.%d.%d",
9992              gtk_get_major_version (),
9993              gtk_get_minor_version (),
9994              gtk_get_micro_version ());
9995   else
9996     sprintf (buffer,
9997              "Gtk+ v%d.%d",
9998              gtk_get_major_version (),
9999              gtk_get_minor_version ());
10000
10001   label = gtk_label_new (buffer);
10002   gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
10003   gtk_widget_set_name (label, "testgtk-version-label");
10004
10005   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
10006   gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
10007   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
10008                                   GTK_POLICY_NEVER, 
10009                                   GTK_POLICY_AUTOMATIC);
10010   gtk_box_pack_start (GTK_BOX (box1), scrolled_window, TRUE, TRUE, 0);
10011
10012   box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
10013   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10014   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), box2);
10015   gtk_container_set_focus_vadjustment (GTK_CONTAINER (box2),
10016                                        gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
10017   gtk_widget_show (box2);
10018
10019   for (i = 0; i < nbuttons; i++)
10020     {
10021       button = gtk_button_new_with_label (buttons[i].label);
10022       if (buttons[i].func)
10023         g_signal_connect (button, 
10024                           "clicked", 
10025                           G_CALLBACK(buttons[i].func),
10026                           NULL);
10027       else
10028         gtk_widget_set_sensitive (button, FALSE);
10029       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10030     }
10031
10032   separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
10033   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
10034
10035   box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
10036   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10037   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
10038
10039   button = gtk_button_new_with_mnemonic ("_Close");
10040   g_signal_connect (button, "clicked",
10041                     G_CALLBACK (do_exit),
10042                     window);
10043   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10044   gtk_widget_set_can_default (button, TRUE);
10045   gtk_widget_grab_default (button);
10046
10047   gtk_widget_show_all (window);
10048 }
10049
10050 static void
10051 test_init (void)
10052 {
10053   if (g_file_test ("../modules/input/immodules.cache", G_FILE_TEST_EXISTS))
10054     g_setenv ("GTK_IM_MODULE_FILE", "../modules/input/immodules.cache", TRUE);
10055 }
10056
10057 static char *
10058 pad (const char *str, int to)
10059 {
10060   static char buf[256];
10061   int len = strlen (str);
10062   int i;
10063
10064   for (i = 0; i < to; i++)
10065     buf[i] = ' ';
10066
10067   buf[to] = '\0';
10068
10069   memcpy (buf, str, len);
10070
10071   return buf;
10072 }
10073
10074 static void
10075 bench_iteration (GtkWidget *widget, void (* fn) (GtkWidget *widget))
10076 {
10077   fn (widget); /* on */
10078   while (g_main_context_iteration (NULL, FALSE));
10079   fn (widget); /* off */
10080   while (g_main_context_iteration (NULL, FALSE));
10081 }
10082
10083 void
10084 do_real_bench (GtkWidget *widget, void (* fn) (GtkWidget *widget), char *name, int num)
10085 {
10086   GTimeVal tv0, tv1;
10087   double dt_first;
10088   double dt;
10089   int n;
10090   static gboolean printed_headers = FALSE;
10091
10092   if (!printed_headers) {
10093     g_print ("Test                 Iters      First      Other\n");
10094     g_print ("-------------------- ----- ---------- ----------\n");
10095     printed_headers = TRUE;
10096   }
10097
10098   g_get_current_time (&tv0);
10099   bench_iteration (widget, fn); 
10100   g_get_current_time (&tv1);
10101
10102   dt_first = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
10103         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
10104
10105   g_get_current_time (&tv0);
10106   for (n = 0; n < num - 1; n++)
10107     bench_iteration (widget, fn); 
10108   g_get_current_time (&tv1);
10109   dt = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
10110         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
10111
10112   g_print ("%s %5d ", pad (name, 20), num);
10113   if (num > 1)
10114     g_print ("%10.1f %10.1f\n", dt_first, dt/(num-1));
10115   else
10116     g_print ("%10.1f\n", dt_first);
10117 }
10118
10119 void
10120 do_bench (char* what, int num)
10121 {
10122   int i;
10123   GtkWidget *widget;
10124   void (* fn) (GtkWidget *widget);
10125   fn = NULL;
10126   widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10127
10128   if (g_ascii_strcasecmp (what, "ALL") == 0)
10129     {
10130       for (i = 0; i < nbuttons; i++)
10131         {
10132           if (!buttons[i].do_not_benchmark)
10133             do_real_bench (widget, buttons[i].func, buttons[i].label, num);
10134         }
10135
10136       return;
10137     }
10138   else
10139     {
10140       for (i = 0; i < nbuttons; i++)
10141         {
10142           if (strcmp (buttons[i].label, what) == 0)
10143             {
10144               fn = buttons[i].func;
10145               break;
10146             }
10147         }
10148       
10149       if (!fn)
10150         g_print ("Can't bench: \"%s\" not found.\n", what);
10151       else
10152         do_real_bench (widget, fn, buttons[i].label, num);
10153     }
10154 }
10155
10156 void 
10157 usage (void)
10158 {
10159   fprintf (stderr, "Usage: testgtk [--bench ALL|<bench>[:<count>]]\n");
10160   exit (1);
10161 }
10162
10163 int
10164 main (int argc, char *argv[])
10165 {
10166   GtkCssProvider *provider, *memory_provider;
10167   GdkDisplay *display;
10168   GdkScreen *screen;
10169   GtkBindingSet *binding_set;
10170   int i;
10171   gboolean done_benchmarks = FALSE;
10172
10173   srand (time (NULL));
10174
10175   test_init ();
10176
10177   g_set_application_name ("GTK+ Test Program");
10178
10179   gtk_init (&argc, &argv);
10180
10181   provider = gtk_css_provider_new ();
10182
10183   /* Check to see if we are being run from the correct
10184    * directory.
10185    */
10186   if (file_exists ("testgtk.css"))
10187     gtk_css_provider_load_from_path (provider, "testgtk.css", NULL);
10188   else if (file_exists ("tests/testgtk.css"))
10189     gtk_css_provider_load_from_path (provider, "tests/testgtk.css", NULL);
10190   else
10191     g_warning ("Couldn't find file \"testgtk.css\".");
10192
10193   display = gdk_display_get_default ();
10194   screen = gdk_display_get_default_screen (display);
10195
10196   gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER (provider),
10197                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
10198   g_object_unref (provider);
10199
10200   gtk_accelerator_set_default_mod_mask (GDK_SHIFT_MASK |
10201                                         GDK_CONTROL_MASK |
10202                                         GDK_MOD1_MASK | 
10203                                         GDK_META_MASK |
10204                                         GDK_SUPER_MASK |
10205                                         GDK_HYPER_MASK |
10206                                         GDK_MOD4_MASK);
10207   /*  benchmarking
10208    */
10209   for (i = 1; i < argc; i++)
10210     {
10211       if (strncmp (argv[i], "--bench", strlen("--bench")) == 0)
10212         {
10213           int num = 1;
10214           char *nextarg;
10215           char *what;
10216           char *count;
10217           
10218           nextarg = strchr (argv[i], '=');
10219           if (nextarg)
10220             nextarg++;
10221           else
10222             {
10223               i++;
10224               if (i == argc)
10225                 usage ();
10226               nextarg = argv[i];
10227             }
10228
10229           count = strchr (nextarg, ':');
10230           if (count)
10231             {
10232               what = g_strndup (nextarg, count - nextarg);
10233               count++;
10234               num = atoi (count);
10235               if (num <= 0)
10236                 usage ();
10237             }
10238           else
10239             what = g_strdup (nextarg);
10240
10241           do_bench (what, num ? num : 1);
10242           done_benchmarks = TRUE;
10243         }
10244       else
10245         usage ();
10246     }
10247   if (done_benchmarks)
10248     return 0;
10249
10250   /* bindings test
10251    */
10252   binding_set = gtk_binding_set_by_class (g_type_class_ref (GTK_TYPE_WIDGET));
10253   gtk_binding_entry_add_signal (binding_set,
10254                                 '9', GDK_CONTROL_MASK | GDK_RELEASE_MASK,
10255                                 "debug_msg",
10256                                 1,
10257                                 G_TYPE_STRING, "GtkWidgetClass <ctrl><release>9 test");
10258
10259   memory_provider = gtk_css_provider_new ();
10260   gtk_css_provider_load_from_data (memory_provider,
10261                                    "#testgtk-version-label {\n"
10262                                    "  color: #f00;\n"
10263                                    "  font: Sans 18;\n"
10264                                    "}",
10265                                    -1, NULL);
10266   gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER (memory_provider),
10267                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + 1);
10268
10269   create_main_window ();
10270
10271   gtk_main ();
10272
10273   if (1)
10274     {
10275       while (g_main_context_pending (NULL))
10276         g_main_context_iteration (NULL, FALSE);
10277 #if 0
10278       sleep (1);
10279       while (g_main_context_pending (NULL))
10280         g_main_context_iteration (NULL, FALSE);
10281 #endif
10282     }
10283   return 0;
10284 }