]> Pileus Git - ~andy/gtk/blob - tests/testgtk.c
testgtk: Convert panes 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 *grid;
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   grid = gtk_grid_new ();
4247   gtk_box_pack_start (GTK_BOX (content_area), grid, TRUE, TRUE, 0);
4248
4249   gtk_grid_set_row_spacing (GTK_GRID (grid), 5);
4250   gtk_grid_set_column_spacing (GTK_GRID (grid), 5);
4251   gtk_container_set_border_width (GTK_CONTAINER (grid), 5);
4252   gtk_widget_set_size_request (grid, 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   gtk_widget_set_hexpand (main_button, TRUE);
4261   gtk_widget_set_vexpand (main_button, TRUE);
4262   gtk_widget_set_halign (main_button, GTK_ALIGN_CENTER);
4263   gtk_widget_set_valign (main_button, GTK_ALIGN_CENTER);
4264   gtk_grid_attach (GTK_GRID (grid), main_button, 0, 0, 1, 1);
4265   
4266   gtk_size_group_add_widget (master_size_group, main_button);
4267   gtk_size_group_add_widget (hgroup1, main_button);
4268   gtk_size_group_add_widget (vgroup1, main_button);
4269   gtk_widget_set_size_request (gtk_bin_get_child (GTK_BIN (main_button)),
4270                                SIZE_GROUP_INITIAL_SIZE,
4271                                SIZE_GROUP_INITIAL_SIZE);
4272
4273   button = gtk_button_new ();
4274   gtk_widget_set_hexpand (button, TRUE);
4275   gtk_widget_set_vexpand (button, TRUE);
4276   gtk_widget_set_halign (button, GTK_ALIGN_CENTER);
4277   gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
4278   gtk_grid_attach (GTK_GRID (grid), button, 1, 0, 1, 1);
4279
4280   gtk_size_group_add_widget (vgroup1, button);
4281   gtk_size_group_add_widget (vgroup2, button);
4282
4283   button = gtk_button_new ();
4284   gtk_widget_set_hexpand (button, TRUE);
4285   gtk_widget_set_vexpand (button, TRUE);
4286   gtk_widget_set_halign (button, GTK_ALIGN_CENTER);
4287   gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
4288   gtk_grid_attach (GTK_GRID (grid), button, 0, 1, 1, 1);
4289
4290   gtk_size_group_add_widget (hgroup1, button);
4291   gtk_size_group_add_widget (hgroup2, button);
4292
4293   button = gtk_button_new ();
4294   gtk_widget_set_hexpand (button, TRUE);
4295   gtk_widget_set_vexpand (button, TRUE);
4296   gtk_widget_set_halign (button, GTK_ALIGN_CENTER);
4297   gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
4298   gtk_grid_attach (GTK_GRID (grid), button, 1, 1, 1, 1);
4299
4300   gtk_size_group_add_widget (hgroup2, button);
4301   gtk_size_group_add_widget (vgroup2, button);
4302
4303   g_object_unref (hgroup1);
4304   g_object_unref (hgroup2);
4305   g_object_unref (vgroup1);
4306   g_object_unref (vgroup2);
4307   
4308   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
4309   gtk_box_pack_start (GTK_BOX (content_area), hbox, FALSE, FALSE, 0);
4310   
4311   spin_button = gtk_spin_button_new_with_range (1, 100, 1);
4312   gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_button), SIZE_GROUP_INITIAL_SIZE);
4313   gtk_box_pack_start (GTK_BOX (hbox), spin_button, TRUE, TRUE, 0);
4314   g_signal_connect (spin_button, "value_changed",
4315                     G_CALLBACK (size_group_hsize_changed), main_button);
4316
4317   spin_button = gtk_spin_button_new_with_range (1, 100, 1);
4318   gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_button), SIZE_GROUP_INITIAL_SIZE);
4319   gtk_box_pack_start (GTK_BOX (hbox), spin_button, TRUE, TRUE, 0);
4320   g_signal_connect (spin_button, "value_changed",
4321                     G_CALLBACK (size_group_vsize_changed), main_button);
4322
4323   return window;
4324 }
4325
4326 static void
4327 create_size_groups (GtkWidget *widget)
4328 {
4329   static GtkWidget *window1 = NULL;
4330   static GtkWidget *window2 = NULL;
4331   static GtkSizeGroup *master_size_group;
4332
4333   if (!master_size_group)
4334     master_size_group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
4335
4336   if (!window1)
4337     {
4338       window1 = create_size_group_window (gtk_widget_get_screen (widget),
4339                                           master_size_group);
4340
4341       g_signal_connect (window1, "destroy",
4342                         G_CALLBACK (gtk_widget_destroyed),
4343                         &window1);
4344     }
4345
4346   if (!window2)
4347     {
4348       window2 = create_size_group_window (gtk_widget_get_screen (widget),
4349                                           master_size_group);
4350
4351       g_signal_connect (window2, "destroy",
4352                         G_CALLBACK (gtk_widget_destroyed),
4353                         &window2);
4354     }
4355
4356   if (gtk_widget_get_visible (window1) && gtk_widget_get_visible (window2))
4357     {
4358       gtk_widget_destroy (window1);
4359       gtk_widget_destroy (window2);
4360     }
4361   else
4362     {
4363       if (!gtk_widget_get_visible (window1))
4364         gtk_widget_show_all (window1);
4365       if (!gtk_widget_get_visible (window2))
4366         gtk_widget_show_all (window2);
4367     }
4368 }
4369
4370 /*
4371  * GtkSpinButton
4372  */
4373
4374 static GtkWidget *spinner1;
4375
4376 static void
4377 toggle_snap (GtkWidget *widget, GtkSpinButton *spin)
4378 {
4379   gtk_spin_button_set_snap_to_ticks (spin,
4380                                      gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)));
4381 }
4382
4383 static void
4384 toggle_numeric (GtkWidget *widget, GtkSpinButton *spin)
4385 {
4386   gtk_spin_button_set_numeric (spin,
4387                                gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)));
4388 }
4389
4390 static void
4391 change_digits (GtkWidget *widget, GtkSpinButton *spin)
4392 {
4393   gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinner1),
4394                               gtk_spin_button_get_value_as_int (spin));
4395 }
4396
4397 static void
4398 get_value (GtkWidget *widget, gpointer data)
4399 {
4400   gchar buf[32];
4401   GtkLabel *label;
4402   GtkSpinButton *spin;
4403
4404   spin = GTK_SPIN_BUTTON (spinner1);
4405   label = GTK_LABEL (g_object_get_data (G_OBJECT (widget), "user_data"));
4406   if (GPOINTER_TO_INT (data) == 1)
4407     sprintf (buf, "%d", gtk_spin_button_get_value_as_int (spin));
4408   else
4409     sprintf (buf, "%0.*f",
4410              gtk_spin_button_get_digits (spin),
4411              gtk_spin_button_get_value (spin));
4412
4413   gtk_label_set_text (label, buf);
4414 }
4415
4416 static void
4417 get_spin_value (GtkWidget *widget, gpointer data)
4418 {
4419   gchar *buffer;
4420   GtkLabel *label;
4421   GtkSpinButton *spin;
4422
4423   spin = GTK_SPIN_BUTTON (widget);
4424   label = GTK_LABEL (data);
4425
4426   buffer = g_strdup_printf ("%0.*f",
4427                             gtk_spin_button_get_digits (spin),
4428                             gtk_spin_button_get_value (spin));
4429   gtk_label_set_text (label, buffer);
4430
4431   g_free (buffer);
4432 }
4433
4434 static gint
4435 spin_button_time_output_func (GtkSpinButton *spin_button)
4436 {
4437   GtkAdjustment *adjustment;
4438   static gchar buf[6];
4439   gdouble hours;
4440   gdouble minutes;
4441
4442   adjustment = gtk_spin_button_get_adjustment (spin_button);
4443   hours = gtk_adjustment_get_value (adjustment) / 60.0;
4444   minutes = (fabs(floor (hours) - hours) < 1e-5) ? 0.0 : 30;
4445   sprintf (buf, "%02.0f:%02.0f", floor (hours), minutes);
4446   if (strcmp (buf, gtk_entry_get_text (GTK_ENTRY (spin_button))))
4447     gtk_entry_set_text (GTK_ENTRY (spin_button), buf);
4448   return TRUE;
4449 }
4450
4451 static gint
4452 spin_button_month_input_func (GtkSpinButton *spin_button,
4453                               gdouble       *new_val)
4454 {
4455   gint i;
4456   static gchar *month[12] = { "January", "February", "March", "April",
4457                               "May", "June", "July", "August",
4458                               "September", "October", "November", "December" };
4459   gchar *tmp1, *tmp2;
4460   gboolean found = FALSE;
4461
4462   for (i = 1; i <= 12; i++)
4463     {
4464       tmp1 = g_ascii_strup (month[i - 1], -1);
4465       tmp2 = g_ascii_strup (gtk_entry_get_text (GTK_ENTRY (spin_button)), -1);
4466       if (strstr (tmp1, tmp2) == tmp1)
4467         found = TRUE;
4468       g_free (tmp1);
4469       g_free (tmp2);
4470       if (found)
4471         break;
4472     }
4473   if (!found)
4474     {
4475       *new_val = 0.0;
4476       return GTK_INPUT_ERROR;
4477     }
4478   *new_val = (gdouble) i;
4479   return TRUE;
4480 }
4481
4482 static gint
4483 spin_button_month_output_func (GtkSpinButton *spin_button)
4484 {
4485   GtkAdjustment *adjustment;
4486   gdouble value;
4487   gint i;
4488   static gchar *month[12] = { "January", "February", "March", "April",
4489                               "May", "June", "July", "August", "September",
4490                               "October", "November", "December" };
4491
4492   adjustment = gtk_spin_button_get_adjustment (spin_button);
4493   value = gtk_adjustment_get_value (adjustment);
4494   for (i = 1; i <= 12; i++)
4495     if (fabs (value - (double)i) < 1e-5)
4496       {
4497         if (strcmp (month[i-1], gtk_entry_get_text (GTK_ENTRY (spin_button))))
4498           gtk_entry_set_text (GTK_ENTRY (spin_button), month[i-1]);
4499       }
4500   return TRUE;
4501 }
4502
4503 static gint
4504 spin_button_hex_input_func (GtkSpinButton *spin_button,
4505                             gdouble       *new_val)
4506 {
4507   const gchar *buf;
4508   gchar *err;
4509   gdouble res;
4510
4511   buf = gtk_entry_get_text (GTK_ENTRY (spin_button));
4512   res = strtol(buf, &err, 16);
4513   *new_val = res;
4514   if (*err)
4515     return GTK_INPUT_ERROR;
4516   else
4517     return TRUE;
4518 }
4519
4520 static gint
4521 spin_button_hex_output_func (GtkSpinButton *spin_button)
4522 {
4523   GtkAdjustment *adjustment;
4524   static gchar buf[7];
4525   gint val;
4526
4527   adjustment = gtk_spin_button_get_adjustment (spin_button);
4528   val = (gint) gtk_adjustment_get_value (adjustment);
4529   if (fabs (val) < 1e-5)
4530     sprintf (buf, "0x00");
4531   else
4532     sprintf (buf, "0x%.2X", val);
4533   if (strcmp (buf, gtk_entry_get_text (GTK_ENTRY (spin_button))))
4534     gtk_entry_set_text (GTK_ENTRY (spin_button), buf);
4535   return TRUE;
4536 }
4537
4538 static void
4539 create_spins (GtkWidget *widget)
4540 {
4541   static GtkWidget *window = NULL;
4542   GtkWidget *frame;
4543   GtkWidget *hbox;
4544   GtkWidget *main_vbox;
4545   GtkWidget *vbox;
4546   GtkWidget *vbox2;
4547   GtkWidget *spinner2;
4548   GtkWidget *spinner;
4549   GtkWidget *button;
4550   GtkWidget *label;
4551   GtkWidget *val_label;
4552   GtkAdjustment *adjustment;
4553
4554   if (!window)
4555     {
4556       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4557       gtk_window_set_screen (GTK_WINDOW (window),
4558                              gtk_widget_get_screen (widget));
4559       
4560       g_signal_connect (window, "destroy",
4561                         G_CALLBACK (gtk_widget_destroyed),
4562                         &window);
4563       
4564       gtk_window_set_title (GTK_WINDOW (window), "GtkSpinButton");
4565       
4566       main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
4567       gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 10);
4568       gtk_container_add (GTK_CONTAINER (window), main_vbox);
4569       
4570       frame = gtk_frame_new ("Not accelerated");
4571       gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
4572       
4573       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
4574       gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
4575       gtk_container_add (GTK_CONTAINER (frame), vbox);
4576       
4577       /* Time, month, hex spinners */
4578       
4579       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
4580       gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 5);
4581       
4582       vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
4583       gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
4584       
4585       label = gtk_label_new ("Time :");
4586       gtk_widget_set_halign (label, GTK_ALIGN_START);
4587       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
4588       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
4589
4590       adjustment = gtk_adjustment_new (0, 0, 1410, 30, 60, 0);
4591       spinner = gtk_spin_button_new (adjustment, 0, 0);
4592       gtk_editable_set_editable (GTK_EDITABLE (spinner), FALSE);
4593       g_signal_connect (spinner,
4594                         "output",
4595                         G_CALLBACK (spin_button_time_output_func),
4596                         NULL);
4597       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
4598       gtk_entry_set_width_chars (GTK_ENTRY (spinner), 5);
4599       gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
4600
4601       vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
4602       gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
4603       
4604       label = gtk_label_new ("Month :");
4605       gtk_widget_set_halign (label, GTK_ALIGN_START);
4606       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
4607       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
4608
4609       adjustment = gtk_adjustment_new (1.0, 1.0, 12.0, 1.0,
4610                                                   5.0, 0.0);
4611       spinner = gtk_spin_button_new (adjustment, 0, 0);
4612       gtk_spin_button_set_update_policy (GTK_SPIN_BUTTON (spinner),
4613                                          GTK_UPDATE_IF_VALID);
4614       g_signal_connect (spinner,
4615                         "input",
4616                         G_CALLBACK (spin_button_month_input_func),
4617                         NULL);
4618       g_signal_connect (spinner,
4619                         "output",
4620                         G_CALLBACK (spin_button_month_output_func),
4621                         NULL);
4622       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
4623       gtk_entry_set_width_chars (GTK_ENTRY (spinner), 9);
4624       gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
4625       
4626       vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
4627       gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
4628
4629       label = gtk_label_new ("Hex :");
4630       gtk_widget_set_halign (label, GTK_ALIGN_START);
4631       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
4632       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
4633
4634       adjustment = gtk_adjustment_new (0, 0, 255, 1, 16, 0);
4635       spinner = gtk_spin_button_new (adjustment, 0, 0);
4636       gtk_editable_set_editable (GTK_EDITABLE (spinner), TRUE);
4637       g_signal_connect (spinner,
4638                         "input",
4639                         G_CALLBACK (spin_button_hex_input_func),
4640                         NULL);
4641       g_signal_connect (spinner,
4642                         "output",
4643                         G_CALLBACK (spin_button_hex_output_func),
4644                         NULL);
4645       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
4646       gtk_entry_set_width_chars (GTK_ENTRY (spinner), 4);
4647       gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
4648
4649       frame = gtk_frame_new ("Accelerated");
4650       gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
4651   
4652       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
4653       gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
4654       gtk_container_add (GTK_CONTAINER (frame), vbox);
4655       
4656       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
4657       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
4658       
4659       vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
4660       gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 5);
4661       
4662       label = gtk_label_new ("Value :");
4663       gtk_widget_set_halign (label, GTK_ALIGN_START);
4664       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
4665       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
4666
4667       adjustment = gtk_adjustment_new (0.0, -10000.0, 10000.0,
4668                                                   0.5, 100.0, 0.0);
4669       spinner1 = gtk_spin_button_new (adjustment, 1.0, 2);
4670       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner1), TRUE);
4671       gtk_box_pack_start (GTK_BOX (vbox2), spinner1, FALSE, TRUE, 0);
4672
4673       vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
4674       gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 5);
4675
4676       label = gtk_label_new ("Digits :");
4677       gtk_widget_set_halign (label, GTK_ALIGN_START);
4678       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
4679       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
4680
4681       adjustment = gtk_adjustment_new (2, 1, 15, 1, 1, 0);
4682       spinner2 = gtk_spin_button_new (adjustment, 0.0, 0);
4683       g_signal_connect (adjustment, "value_changed",
4684                         G_CALLBACK (change_digits),
4685                         spinner2);
4686       gtk_box_pack_start (GTK_BOX (vbox2), spinner2, FALSE, TRUE, 0);
4687
4688       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
4689       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 5);
4690
4691       button = gtk_check_button_new_with_label ("Snap to 0.5-ticks");
4692       g_signal_connect (button, "clicked",
4693                         G_CALLBACK (toggle_snap),
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       button = gtk_check_button_new_with_label ("Numeric only input mode");
4699       g_signal_connect (button, "clicked",
4700                         G_CALLBACK (toggle_numeric),
4701                         spinner1);
4702       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
4703       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
4704
4705       val_label = gtk_label_new ("");
4706
4707       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
4708       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
4709
4710       button = gtk_button_new_with_label ("Value as Int");
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 (1));
4715       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
4716
4717       button = gtk_button_new_with_label ("Value as Float");
4718       g_object_set_data (G_OBJECT (button), "user_data", val_label);
4719       g_signal_connect (button, "clicked",
4720                         G_CALLBACK (get_value),
4721                         GINT_TO_POINTER (2));
4722       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
4723
4724       gtk_box_pack_start (GTK_BOX (vbox), val_label, TRUE, TRUE, 0);
4725       gtk_label_set_text (GTK_LABEL (val_label), "0");
4726
4727       frame = gtk_frame_new ("Using Convenience Constructor");
4728       gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
4729   
4730       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
4731       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
4732       gtk_container_add (GTK_CONTAINER (frame), hbox);
4733       
4734       val_label = gtk_label_new ("0.0");
4735
4736       spinner = gtk_spin_button_new_with_range (0.0, 10.0, 0.009);
4737       gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinner), 0.0);
4738       g_signal_connect (spinner, "value_changed",
4739                         G_CALLBACK (get_spin_value), val_label);
4740       gtk_box_pack_start (GTK_BOX (hbox), spinner, TRUE, TRUE, 5);
4741       gtk_box_pack_start (GTK_BOX (hbox), val_label, TRUE, TRUE, 5);
4742
4743       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
4744       gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
4745   
4746       button = gtk_button_new_with_label ("Close");
4747       g_signal_connect_swapped (button, "clicked",
4748                                 G_CALLBACK (gtk_widget_destroy),
4749                                 window);
4750       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
4751     }
4752
4753   if (!gtk_widget_get_visible (window))
4754     gtk_widget_show_all (window);
4755   else
4756     gtk_widget_destroy (window);
4757 }
4758
4759
4760 /*
4761  * Cursors
4762  */
4763
4764 static gint
4765 cursor_draw (GtkWidget *widget,
4766              cairo_t   *cr,
4767              gpointer   user_data)
4768 {
4769   int width, height;
4770   GtkStyleContext *context;
4771   GdkRGBA bg;
4772
4773   width = gtk_widget_get_allocated_width (widget);
4774   height = gtk_widget_get_allocated_height (widget);
4775
4776   cairo_set_source_rgb (cr, 1, 1, 1);
4777   cairo_rectangle (cr, 0, 0, width, height / 2);
4778   cairo_fill (cr);
4779
4780   cairo_set_source_rgb (cr, 0, 0, 0);
4781   cairo_rectangle (cr, 0, height / 2, width, height / 2);
4782   cairo_fill (cr);
4783
4784   context = gtk_widget_get_style_context (widget);
4785   gtk_style_context_get_background_color (context, GTK_STATE_FLAG_NORMAL, &bg);
4786   gdk_cairo_set_source_rgba (cr, &bg);
4787   cairo_rectangle (cr, width / 3, height / 3, width / 3, height / 3);
4788   cairo_fill (cr);
4789
4790   return TRUE;
4791 }
4792
4793 static void
4794 set_cursor (GtkWidget *spinner,
4795             GtkWidget *widget)
4796 {
4797   guint c;
4798   GdkCursor *cursor;
4799   GtkWidget *label;
4800   GEnumClass *class;
4801   GEnumValue *vals;
4802
4803   c = CLAMP (gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spinner)), 0, 152);
4804   c &= 0xfe;
4805
4806   label = g_object_get_data (G_OBJECT (spinner), "user_data");
4807   
4808   class = g_type_class_ref (GDK_TYPE_CURSOR_TYPE);
4809   vals = class->values;
4810
4811   while (vals && vals->value != c)
4812     vals++;
4813   if (vals)
4814     gtk_label_set_text (GTK_LABEL (label), vals->value_nick);
4815   else
4816     gtk_label_set_text (GTK_LABEL (label), "<unknown>");
4817
4818   g_type_class_unref (class);
4819
4820   cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), c);
4821   gdk_window_set_cursor (gtk_widget_get_window (widget),
4822                          cursor);
4823   g_object_unref (cursor);
4824 }
4825
4826 static gint
4827 cursor_event (GtkWidget          *widget,
4828               GdkEvent           *event,
4829               GtkSpinButton      *spinner)
4830 {
4831   if ((event->type == GDK_BUTTON_PRESS) &&
4832       ((event->button.button == 1) ||
4833        (event->button.button == 3)))
4834     {
4835       gtk_spin_button_spin (spinner, event->button.button == 1 ?
4836                             GTK_SPIN_STEP_FORWARD : GTK_SPIN_STEP_BACKWARD, 0);
4837       return TRUE;
4838     }
4839
4840   return FALSE;
4841 }
4842
4843 #ifdef GDK_WINDOWING_X11
4844 #include "x11/gdkx.h"
4845
4846 static void
4847 change_cursor_theme (GtkWidget *widget,
4848                      gpointer   data)
4849 {
4850   const gchar *theme;
4851   gint size;
4852   GList *children;
4853
4854   children = gtk_container_get_children (GTK_CONTAINER (data));
4855
4856   theme = gtk_entry_get_text (GTK_ENTRY (children->next->data));
4857   size = (gint) gtk_spin_button_get_value (GTK_SPIN_BUTTON (children->next->next->data));
4858
4859   g_list_free (children);
4860
4861   gdk_x11_display_set_cursor_theme (gtk_widget_get_display (widget),
4862                                     theme, size);
4863 }
4864 #endif
4865
4866
4867 static void
4868 create_cursors (GtkWidget *widget)
4869 {
4870   static GtkWidget *window = NULL;
4871   GtkWidget *frame;
4872   GtkWidget *hbox;
4873   GtkWidget *main_vbox;
4874   GtkWidget *vbox;
4875   GtkWidget *darea;
4876   GtkWidget *spinner;
4877   GtkWidget *button;
4878   GtkWidget *label;
4879   GtkWidget *any;
4880   GtkAdjustment *adjustment;
4881   GtkWidget *entry;
4882   GtkWidget *size;  
4883
4884   if (!window)
4885     {
4886       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4887       gtk_window_set_screen (GTK_WINDOW (window), 
4888                              gtk_widget_get_screen (widget));
4889       
4890       g_signal_connect (window, "destroy",
4891                         G_CALLBACK (gtk_widget_destroyed),
4892                         &window);
4893       
4894       gtk_window_set_title (GTK_WINDOW (window), "Cursors");
4895       
4896       main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
4897       gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 0);
4898       gtk_container_add (GTK_CONTAINER (window), main_vbox);
4899
4900       vbox =
4901         g_object_new (GTK_TYPE_BOX,
4902                       "orientation", GTK_ORIENTATION_VERTICAL,
4903                         "GtkBox::homogeneous", FALSE,
4904                         "GtkBox::spacing", 5,
4905                         "GtkContainer::border_width", 10,
4906                         "GtkWidget::parent", main_vbox,
4907                         "GtkWidget::visible", TRUE,
4908                         NULL);
4909
4910 #ifdef GDK_WINDOWING_X11
4911       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
4912       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
4913       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
4914
4915       label = gtk_label_new ("Cursor Theme : ");
4916       gtk_widget_set_halign (label, GTK_ALIGN_START);
4917       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
4918       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
4919
4920       entry = gtk_entry_new ();
4921       gtk_entry_set_text (GTK_ENTRY (entry), "default");
4922       gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, TRUE, 0);
4923
4924       size = gtk_spin_button_new_with_range (1.0, 64.0, 1.0);
4925       gtk_spin_button_set_value (GTK_SPIN_BUTTON (size), 24.0);
4926       gtk_box_pack_start (GTK_BOX (hbox), size, TRUE, TRUE, 0);
4927       
4928       g_signal_connect (entry, "changed", 
4929                         G_CALLBACK (change_cursor_theme), hbox);
4930       g_signal_connect (size, "changed", 
4931                         G_CALLBACK (change_cursor_theme), hbox);
4932 #endif
4933
4934       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
4935       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
4936       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
4937
4938       label = gtk_label_new ("Cursor Value : ");
4939       gtk_widget_set_halign (label, GTK_ALIGN_START);
4940       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
4941       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
4942
4943       adjustment = gtk_adjustment_new (0,
4944                                 0, 152,
4945                                 2,
4946                                 10, 0);
4947       spinner = gtk_spin_button_new (adjustment, 0, 0);
4948       gtk_box_pack_start (GTK_BOX (hbox), spinner, TRUE, TRUE, 0);
4949
4950       frame =
4951         g_object_new (gtk_frame_get_type (),
4952                         "GtkFrame::label_xalign", 0.5,
4953                         "GtkFrame::label", "Cursor Area",
4954                         "GtkContainer::border_width", 10,
4955                         "GtkWidget::parent", vbox,
4956                         "GtkWidget::visible", TRUE,
4957                         NULL);
4958
4959       darea = gtk_drawing_area_new ();
4960       gtk_widget_set_size_request (darea, 80, 80);
4961       gtk_container_add (GTK_CONTAINER (frame), darea);
4962       g_signal_connect (darea,
4963                         "draw",
4964                         G_CALLBACK (cursor_draw),
4965                         NULL);
4966       gtk_widget_set_events (darea, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
4967       g_signal_connect (darea,
4968                         "button_press_event",
4969                         G_CALLBACK (cursor_event),
4970                         spinner);
4971       gtk_widget_show (darea);
4972
4973       g_signal_connect (spinner, "changed",
4974                         G_CALLBACK (set_cursor),
4975                         darea);
4976
4977       label = g_object_new (GTK_TYPE_LABEL,
4978                               "visible", TRUE,
4979                               "label", "XXX",
4980                               "parent", vbox,
4981                               NULL);
4982       gtk_container_child_set (GTK_CONTAINER (vbox), label,
4983                                "expand", FALSE,
4984                                NULL);
4985       g_object_set_data (G_OBJECT (spinner), "user_data", label);
4986
4987       any = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
4988       gtk_box_pack_start (GTK_BOX (main_vbox), any, FALSE, TRUE, 0);
4989   
4990       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
4991       gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
4992       gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
4993
4994       button = gtk_button_new_with_label ("Close");
4995       g_signal_connect_swapped (button, "clicked",
4996                                 G_CALLBACK (gtk_widget_destroy),
4997                                 window);
4998       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
4999
5000       gtk_widget_show_all (window);
5001
5002       set_cursor (spinner, darea);
5003     }
5004   else
5005     gtk_widget_destroy (window);
5006 }
5007
5008 /*
5009  * GtkColorSelection
5010  */
5011
5012 void
5013 color_selection_ok (GtkWidget               *w,
5014                     GtkColorSelectionDialog *cs)
5015 {
5016   GtkWidget *colorsel;
5017   GdkColor color;
5018
5019   colorsel = gtk_color_selection_dialog_get_color_selection (cs);
5020
5021   gtk_color_selection_get_current_color (GTK_COLOR_SELECTION (colorsel), &color);
5022   gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (colorsel), &color);
5023 }
5024
5025 void
5026 color_selection_changed (GtkWidget *w,
5027                          GtkColorSelectionDialog *cs)
5028 {
5029   GtkWidget *colorsel;
5030   GdkColor color;
5031
5032   colorsel = gtk_color_selection_dialog_get_color_selection (cs);
5033   gtk_color_selection_get_current_color (GTK_COLOR_SELECTION (colorsel), &color);
5034   gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (colorsel), &color);
5035 }
5036
5037 #if 0 /* unused */
5038 static void
5039 opacity_toggled_cb (GtkWidget *w,
5040                     GtkColorSelectionDialog *cs)
5041 {
5042   GtkColorSelection *colorsel;
5043
5044   colorsel = GTK_COLOR_SELECTION (cs->colorsel);
5045   gtk_color_selection_set_has_opacity_control (colorsel,
5046                                                gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
5047 }
5048
5049 static void
5050 palette_toggled_cb (GtkWidget *w,
5051                     GtkColorSelectionDialog *cs)
5052 {
5053   GtkColorSelection *colorsel;
5054
5055   colorsel = GTK_COLOR_SELECTION (cs->colorsel);
5056   gtk_color_selection_set_has_palette (colorsel,
5057                                        gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
5058 }
5059 #endif
5060
5061 void
5062 create_color_selection (GtkWidget *widget)
5063 {
5064   static GtkWidget *window = NULL;
5065
5066   if (!window)
5067     {
5068       GtkWidget *picker;
5069       GtkWidget *hbox;
5070       GtkWidget *label;
5071       GtkWidget *button;
5072       
5073       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5074       gtk_window_set_screen (GTK_WINDOW (window), 
5075                              gtk_widget_get_screen (widget));
5076                              
5077       g_signal_connect (window, "destroy",
5078                         G_CALLBACK (gtk_widget_destroyed),
5079                         &window);
5080
5081       gtk_window_set_title (GTK_WINDOW (window), "GtkColorButton");
5082       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5083
5084       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
5085       gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
5086       gtk_container_add (GTK_CONTAINER (window), hbox);
5087       
5088       label = gtk_label_new ("Pick a color");
5089       gtk_container_add (GTK_CONTAINER (hbox), label);
5090
5091       picker = gtk_color_button_new ();
5092       gtk_color_button_set_use_alpha (GTK_COLOR_BUTTON (picker), TRUE);
5093       gtk_container_add (GTK_CONTAINER (hbox), picker);
5094
5095       button = gtk_button_new_with_mnemonic ("_Props");
5096       gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
5097       g_signal_connect (button, "clicked",
5098                         G_CALLBACK (props_clicked),
5099                         picker);
5100     }
5101
5102   if (!gtk_widget_get_visible (window))
5103     gtk_widget_show_all (window);
5104   else
5105     gtk_widget_destroy (window);
5106 }
5107
5108 void
5109 flipping_toggled_cb (GtkWidget *widget, gpointer data)
5110 {
5111   int state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
5112   int new_direction = state ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
5113
5114   gtk_widget_set_default_direction (new_direction);
5115 }
5116
5117 static void
5118 orientable_toggle_orientation (GtkOrientable *orientable)
5119 {
5120   GtkOrientation orientation;
5121
5122   orientation = gtk_orientable_get_orientation (orientable);
5123   gtk_orientable_set_orientation (orientable,
5124                                   orientation == GTK_ORIENTATION_HORIZONTAL ?
5125                                   GTK_ORIENTATION_VERTICAL :
5126                                   GTK_ORIENTATION_HORIZONTAL);
5127
5128   if (GTK_IS_CONTAINER (orientable))
5129     {
5130       GList *children;
5131       GList *child;
5132
5133       children = gtk_container_get_children (GTK_CONTAINER (orientable));
5134
5135       for (child = children; child; child = child->next)
5136         {
5137           if (GTK_IS_ORIENTABLE (child->data))
5138             orientable_toggle_orientation (child->data);
5139         }
5140
5141       g_list_free (children);
5142     }
5143 }
5144
5145 void
5146 flipping_orientation_toggled_cb (GtkWidget *widget, gpointer data)
5147 {
5148   GtkWidget *content_area;
5149   GtkWidget *toplevel;
5150
5151   toplevel = gtk_widget_get_toplevel (widget);
5152   content_area = gtk_dialog_get_content_area (GTK_DIALOG (toplevel));
5153   orientable_toggle_orientation (GTK_ORIENTABLE (content_area));
5154 }
5155
5156 static void
5157 set_direction_recurse (GtkWidget *widget,
5158                        gpointer   data)
5159 {
5160   GtkTextDirection *dir = data;
5161   
5162   gtk_widget_set_direction (widget, *dir);
5163   if (GTK_IS_CONTAINER (widget))
5164     gtk_container_foreach (GTK_CONTAINER (widget),
5165                            set_direction_recurse,
5166                            data);
5167 }
5168
5169 static GtkWidget *
5170 create_forward_back (const char       *title,
5171                      GtkTextDirection  text_dir)
5172 {
5173   GtkWidget *frame = gtk_frame_new (title);
5174   GtkWidget *bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
5175   GtkWidget *back_button = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
5176   GtkWidget *forward_button = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
5177
5178   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
5179   
5180   gtk_container_add (GTK_CONTAINER (frame), bbox);
5181   gtk_container_add (GTK_CONTAINER (bbox), back_button);
5182   gtk_container_add (GTK_CONTAINER (bbox), forward_button);
5183
5184   set_direction_recurse (frame, &text_dir);
5185
5186   return frame;
5187 }
5188
5189 void
5190 create_flipping (GtkWidget *widget)
5191 {
5192   static GtkWidget *window = NULL;
5193   GtkWidget *check_button, *button;
5194   GtkWidget *action_area, *content_area;
5195
5196   if (!window)
5197     {
5198       window = gtk_dialog_new ();
5199
5200       gtk_window_set_screen (GTK_WINDOW (window),
5201                              gtk_widget_get_screen (widget));
5202
5203       g_signal_connect (window, "destroy",
5204                         G_CALLBACK (gtk_widget_destroyed),
5205                         &window);
5206
5207       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
5208       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
5209
5210       gtk_window_set_title (GTK_WINDOW (window), "Bidirectional Flipping");
5211
5212       check_button = gtk_check_button_new_with_label ("Right-to-left global direction");
5213       gtk_container_set_border_width (GTK_CONTAINER (check_button), 10);
5214       gtk_box_pack_start (GTK_BOX (content_area), check_button, TRUE, TRUE, 0);
5215
5216       if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL)
5217         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button), TRUE);
5218
5219       g_signal_connect (check_button, "toggled",
5220                         G_CALLBACK (flipping_toggled_cb), NULL);
5221
5222       check_button = gtk_check_button_new_with_label ("Toggle orientation of all boxes");
5223       gtk_container_set_border_width (GTK_CONTAINER (check_button), 10);
5224       gtk_box_pack_start (GTK_BOX (content_area), check_button, TRUE, TRUE, 0);
5225
5226       g_signal_connect (check_button, "toggled",
5227                         G_CALLBACK (flipping_orientation_toggled_cb), NULL);
5228
5229       gtk_box_pack_start (GTK_BOX (content_area),
5230                           create_forward_back ("Default", GTK_TEXT_DIR_NONE),
5231                           TRUE, TRUE, 0);
5232
5233       gtk_box_pack_start (GTK_BOX (content_area),
5234                           create_forward_back ("Left-to-Right", GTK_TEXT_DIR_LTR),
5235                           TRUE, TRUE, 0);
5236
5237       gtk_box_pack_start (GTK_BOX (content_area),
5238                           create_forward_back ("Right-to-Left", GTK_TEXT_DIR_RTL),
5239                           TRUE, TRUE, 0);
5240
5241       button = gtk_button_new_with_label ("Close");
5242       g_signal_connect_swapped (button, "clicked",
5243                                 G_CALLBACK (gtk_widget_destroy), window);
5244       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
5245     }
5246   
5247   if (!gtk_widget_get_visible (window))
5248     gtk_widget_show_all (window);
5249   else
5250     gtk_widget_destroy (window);
5251 }
5252
5253 /*
5254  * Focus test
5255  */
5256
5257 static GtkWidget*
5258 make_focus_table (GList **list)
5259 {
5260   GtkWidget *grid;
5261   gint i, j;
5262   
5263   grid = gtk_grid_new ();
5264
5265   gtk_grid_set_row_spacing (GTK_GRID (grid), 10);
5266   gtk_grid_set_column_spacing (GTK_GRID (grid), 10);
5267
5268   for (i = 0; i < 5; i++)
5269     {
5270       for (j = 0; j < 5; j++)
5271         {
5272           GtkWidget *widget;
5273           
5274           if ((i + j) % 2)
5275             widget = gtk_entry_new ();
5276           else
5277             widget = gtk_button_new_with_label ("Foo");
5278
5279           *list = g_list_prepend (*list, widget);
5280           
5281           gtk_widget_set_hexpand (widget, TRUE);
5282           gtk_widget_set_vexpand (widget, TRUE);
5283
5284           gtk_grid_attach (GTK_GRID (grid), widget, i, j, 1, 1);
5285         }
5286     }
5287
5288   *list = g_list_reverse (*list);
5289   
5290   return grid;
5291 }
5292
5293 static void
5294 create_focus (GtkWidget *widget)
5295 {
5296   static GtkWidget *window = NULL;
5297   
5298   if (!window)
5299     {
5300       GtkWidget *content_area;
5301       GtkWidget *table;
5302       GtkWidget *frame;
5303       GList *list = NULL;
5304       
5305       window = gtk_dialog_new_with_buttons ("Keyboard focus navigation",
5306                                             NULL, 0,
5307                                             GTK_STOCK_CLOSE,
5308                                             GTK_RESPONSE_NONE,
5309                                             NULL);
5310
5311       gtk_window_set_screen (GTK_WINDOW (window),
5312                              gtk_widget_get_screen (widget));
5313
5314       g_signal_connect (window, "destroy",
5315                         G_CALLBACK (gtk_widget_destroyed),
5316                         &window);
5317
5318       g_signal_connect (window, "response",
5319                         G_CALLBACK (gtk_widget_destroy),
5320                         NULL);
5321
5322       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
5323       
5324       gtk_window_set_title (GTK_WINDOW (window), "Keyboard Focus Navigation");
5325
5326       frame = gtk_frame_new ("Weird tab focus chain");
5327
5328       gtk_box_pack_start (GTK_BOX (content_area), frame, TRUE, TRUE, 0);
5329       
5330       table = make_focus_table (&list);
5331
5332       gtk_container_add (GTK_CONTAINER (frame), table);
5333
5334       gtk_container_set_focus_chain (GTK_CONTAINER (table),
5335                                      list);
5336
5337       g_list_free (list);
5338       
5339       frame = gtk_frame_new ("Default tab focus chain");
5340
5341       gtk_box_pack_start (GTK_BOX (content_area), frame, TRUE, TRUE, 0);
5342
5343       list = NULL;
5344       table = make_focus_table (&list);
5345
5346       g_list_free (list);
5347       
5348       gtk_container_add (GTK_CONTAINER (frame), table);      
5349     }
5350   
5351   if (!gtk_widget_get_visible (window))
5352     gtk_widget_show_all (window);
5353   else
5354     gtk_widget_destroy (window);
5355 }
5356
5357 /*
5358  * GtkFontSelection
5359  */
5360
5361 void
5362 create_font_selection (GtkWidget *widget)
5363 {
5364   static GtkWidget *window = NULL;
5365
5366   if (!window)
5367     {
5368       GtkWidget *picker;
5369       GtkWidget *hbox;
5370       GtkWidget *label;
5371       
5372       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5373       gtk_window_set_screen (GTK_WINDOW (window),
5374                              gtk_widget_get_screen (widget));
5375
5376       g_signal_connect (window, "destroy",
5377                         G_CALLBACK (gtk_widget_destroyed),
5378                         &window);
5379
5380       gtk_window_set_title (GTK_WINDOW (window), "GtkFontButton");
5381       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5382
5383       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
5384       gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
5385       gtk_container_add (GTK_CONTAINER (window), hbox);
5386       
5387       label = gtk_label_new ("Pick a font");
5388       gtk_container_add (GTK_CONTAINER (hbox), label);
5389
5390       picker = gtk_font_button_new ();
5391       gtk_font_button_set_use_font (GTK_FONT_BUTTON (picker), TRUE);
5392       gtk_container_add (GTK_CONTAINER (hbox), picker);
5393     }
5394   
5395   if (!gtk_widget_get_visible (window))
5396     gtk_widget_show_all (window);
5397   else
5398     gtk_widget_destroy (window);
5399 }
5400
5401 /*
5402  * GtkDialog
5403  */
5404
5405 static GtkWidget *dialog_window = NULL;
5406
5407 static void
5408 label_toggle (GtkWidget  *widget,
5409               GtkWidget **label)
5410 {
5411   if (!(*label))
5412     {
5413       *label = gtk_label_new ("Dialog Test");
5414       g_signal_connect (*label,
5415                         "destroy",
5416                         G_CALLBACK (gtk_widget_destroyed),
5417                         label);
5418       g_object_set (*label, "margin", 10, NULL);
5419       gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog_window))),
5420                           *label, TRUE, TRUE, 0);
5421       gtk_widget_show (*label);
5422     }
5423   else
5424     gtk_widget_destroy (*label);
5425 }
5426
5427 static void
5428 create_dialog (GtkWidget *widget)
5429 {
5430   static GtkWidget *label;
5431   GtkWidget *action_area;
5432   GtkWidget *button;
5433
5434   if (!dialog_window)
5435     {
5436       /* This is a terrible example; it's much simpler to create
5437        * dialogs than this. Don't use testgtk for example code,
5438        * use gtk-demo ;-)
5439        */
5440       
5441       dialog_window = gtk_dialog_new ();
5442       gtk_window_set_screen (GTK_WINDOW (dialog_window),
5443                              gtk_widget_get_screen (widget));
5444
5445       g_signal_connect (dialog_window, "destroy",
5446                         G_CALLBACK (gtk_widget_destroyed),
5447                         &dialog_window);
5448
5449       action_area = gtk_dialog_get_action_area (GTK_DIALOG (dialog_window));
5450
5451       gtk_window_set_title (GTK_WINDOW (dialog_window), "GtkDialog");
5452       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
5453
5454       button = gtk_button_new_with_label ("OK");
5455       gtk_widget_set_can_default (button, TRUE);
5456       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
5457       gtk_widget_grab_default (button);
5458       gtk_widget_show (button);
5459
5460       button = gtk_button_new_with_label ("Toggle");
5461       g_signal_connect (button, "clicked",
5462                         G_CALLBACK (label_toggle),
5463                         &label);
5464       gtk_widget_set_can_default (button, TRUE);
5465       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
5466       gtk_widget_show (button);
5467
5468       label = NULL;
5469     }
5470
5471   if (!gtk_widget_get_visible (dialog_window))
5472     gtk_widget_show (dialog_window);
5473   else
5474     gtk_widget_destroy (dialog_window);
5475 }
5476
5477 /* Display & Screen test 
5478  */
5479
5480 typedef struct
5481 {
5482   GtkWidget *combo;
5483   GtkWidget *entry;
5484   GtkWidget *radio_dpy;
5485   GtkWidget *toplevel;
5486   GtkWidget *dialog_window;
5487 } ScreenDisplaySelection;
5488
5489 static void
5490 screen_display_check (GtkWidget *widget, ScreenDisplaySelection *data)
5491 {
5492   const gchar *display_name;
5493   GdkDisplay *display = gtk_widget_get_display (widget);
5494   GtkWidget *dialog;
5495   GdkScreen *new_screen = NULL;
5496   GdkScreen *current_screen = gtk_widget_get_screen (widget);
5497   
5498   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->radio_dpy)))
5499     {
5500       display_name = gtk_entry_get_text (GTK_ENTRY (data->entry));
5501       display = gdk_display_open (display_name);
5502       
5503       if (!display)
5504         {
5505           dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (widget)),
5506                                            GTK_DIALOG_DESTROY_WITH_PARENT,
5507                                            GTK_MESSAGE_ERROR,
5508                                            GTK_BUTTONS_OK,
5509                                            "The display :\n%s\ncannot be opened",
5510                                            display_name);
5511           gtk_window_set_screen (GTK_WINDOW (dialog), current_screen);
5512           gtk_widget_show (dialog);
5513           g_signal_connect (dialog, "response",
5514                             G_CALLBACK (gtk_widget_destroy),
5515                             NULL);
5516         }
5517       else
5518         {
5519           GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX (data->combo));
5520           gint i = 0;
5521           GtkTreeIter iter;
5522           gboolean found = FALSE;
5523           while (gtk_tree_model_iter_nth_child (model, &iter, NULL, i++))
5524             {
5525               gchar *name;
5526               gtk_tree_model_get (model, &iter, 0, &name, -1);
5527               found = !g_ascii_strcasecmp (display_name, name);
5528               g_free (name);
5529
5530               if (found)
5531                 break;
5532             }
5533           if (!found)
5534             gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (data->combo), display_name);
5535           new_screen = gdk_display_get_default_screen (display);
5536         }
5537     }
5538   else
5539     {
5540       gint number_of_screens = gdk_display_get_n_screens (display);
5541       gint screen_num = gdk_screen_get_number (current_screen);
5542       if ((screen_num +1) < number_of_screens)
5543         new_screen = gdk_display_get_screen (display, screen_num + 1);
5544       else
5545         new_screen = gdk_display_get_screen (display, 0);
5546     }
5547   
5548   if (new_screen) 
5549     {
5550       gtk_window_set_screen (GTK_WINDOW (data->toplevel), new_screen);
5551       gtk_widget_destroy (data->dialog_window);
5552     }
5553 }
5554
5555 void
5556 screen_display_destroy_diag (GtkWidget *widget, GtkWidget *data)
5557 {
5558   gtk_widget_destroy (data);
5559 }
5560
5561 void
5562 create_display_screen (GtkWidget *widget)
5563 {
5564   GtkWidget *grid, *frame, *window, *combo_dpy, *vbox;
5565   GtkWidget *radio_dpy, *radio_scr, *applyb, *cancelb;
5566   GtkWidget *bbox;
5567   ScreenDisplaySelection *scr_dpy_data;
5568   GdkScreen *screen = gtk_widget_get_screen (widget);
5569   GdkDisplay *display = gdk_screen_get_display (screen);
5570
5571   window = g_object_new (gtk_window_get_type (),
5572                          "screen", screen,
5573                          "type", GTK_WINDOW_TOPLEVEL,
5574                          "title", "Screen or Display selection",
5575                          "border_width",
5576                          10, NULL);
5577   g_signal_connect (window, "destroy", 
5578                     G_CALLBACK (gtk_widget_destroy), NULL);
5579
5580   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3);
5581   gtk_container_add (GTK_CONTAINER (window), vbox);
5582   
5583   frame = gtk_frame_new ("Select screen or display");
5584   gtk_container_add (GTK_CONTAINER (vbox), frame);
5585   
5586   grid = gtk_grid_new ();
5587   gtk_grid_set_row_spacing (GTK_GRID (grid), 3);
5588   gtk_grid_set_column_spacing (GTK_GRID (grid), 3);
5589
5590   gtk_container_add (GTK_CONTAINER (frame), grid);
5591
5592   radio_dpy = gtk_radio_button_new_with_label (NULL, "move to another X display");
5593   if (gdk_display_get_n_screens(display) > 1)
5594     radio_scr = gtk_radio_button_new_with_label 
5595     (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), "move to next screen");
5596   else
5597     {    
5598       radio_scr = gtk_radio_button_new_with_label 
5599         (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), 
5600          "only one screen on the current display");
5601       gtk_widget_set_sensitive (radio_scr, FALSE);
5602     }
5603   combo_dpy = gtk_combo_box_text_new_with_entry ();
5604   gtk_widget_set_hexpand (combo_dpy, TRUE);
5605   gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_dpy), "diabolo:0.0");
5606   gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (combo_dpy))),
5607                       "<hostname>:<X Server Num>.<Screen Num>");
5608
5609   gtk_grid_attach (GTK_GRID (grid), radio_dpy, 0, 0, 1, 1);
5610   gtk_grid_attach (GTK_GRID (grid), radio_scr, 0, 1, 1, 1);
5611   gtk_grid_attach (GTK_GRID (grid), combo_dpy, 1, 0, 1, 1);
5612
5613   bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
5614   applyb = gtk_button_new_from_stock (GTK_STOCK_APPLY);
5615   cancelb = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
5616   
5617   gtk_container_add (GTK_CONTAINER (vbox), bbox);
5618
5619   gtk_container_add (GTK_CONTAINER (bbox), applyb);
5620   gtk_container_add (GTK_CONTAINER (bbox), cancelb);
5621
5622   scr_dpy_data = g_new0 (ScreenDisplaySelection, 1);
5623
5624   scr_dpy_data->entry = gtk_bin_get_child (GTK_BIN (combo_dpy));
5625   scr_dpy_data->radio_dpy = radio_dpy;
5626   scr_dpy_data->toplevel = gtk_widget_get_toplevel (widget);
5627   scr_dpy_data->dialog_window = window;
5628
5629   g_signal_connect (cancelb, "clicked", 
5630                     G_CALLBACK (screen_display_destroy_diag), window);
5631   g_signal_connect (applyb, "clicked", 
5632                     G_CALLBACK (screen_display_check), scr_dpy_data);
5633   gtk_widget_show_all (window);
5634 }
5635
5636 /* Event Watcher
5637  */
5638 static gulong event_watcher_enter_id = 0;
5639 static gulong event_watcher_leave_id = 0;
5640
5641 static gboolean
5642 event_watcher (GSignalInvocationHint *ihint,
5643                guint                  n_param_values,
5644                const GValue          *param_values,
5645                gpointer               data)
5646 {
5647   g_print ("Watch: \"%s\" emitted for %s\n",
5648            g_signal_name (ihint->signal_id),
5649            G_OBJECT_TYPE_NAME (g_value_get_object (param_values + 0)));
5650
5651   return TRUE;
5652 }
5653
5654 static void
5655 event_watcher_down (void)
5656 {
5657   if (event_watcher_enter_id)
5658     {
5659       guint signal_id;
5660
5661       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
5662       g_signal_remove_emission_hook (signal_id, event_watcher_enter_id);
5663       event_watcher_enter_id = 0;
5664       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
5665       g_signal_remove_emission_hook (signal_id, event_watcher_leave_id);
5666       event_watcher_leave_id = 0;
5667     }
5668 }
5669
5670 static void
5671 event_watcher_toggle (void)
5672 {
5673   if (event_watcher_enter_id)
5674     event_watcher_down ();
5675   else
5676     {
5677       guint signal_id;
5678
5679       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
5680       event_watcher_enter_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
5681       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
5682       event_watcher_leave_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
5683     }
5684 }
5685
5686 static void
5687 create_event_watcher (GtkWidget *widget)
5688 {
5689   GtkWidget *action_area, *content_area;
5690   GtkWidget *button;
5691
5692   if (!dialog_window)
5693     {
5694       dialog_window = gtk_dialog_new ();
5695       gtk_window_set_screen (GTK_WINDOW (dialog_window),
5696                              gtk_widget_get_screen (widget));
5697
5698       g_signal_connect (dialog_window, "destroy",
5699                         G_CALLBACK (gtk_widget_destroyed),
5700                         &dialog_window);
5701       g_signal_connect (dialog_window, "destroy",
5702                         G_CALLBACK (event_watcher_down),
5703                         NULL);
5704
5705       content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog_window));
5706       action_area = gtk_dialog_get_action_area (GTK_DIALOG (dialog_window));
5707
5708       gtk_window_set_title (GTK_WINDOW (dialog_window), "Event Watcher");
5709       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
5710       gtk_widget_set_size_request (dialog_window, 200, 110);
5711
5712       button = gtk_toggle_button_new_with_label ("Activate Watch");
5713       g_signal_connect (button, "clicked",
5714                         G_CALLBACK (event_watcher_toggle),
5715                         NULL);
5716       gtk_container_set_border_width (GTK_CONTAINER (button), 10);
5717       gtk_box_pack_start (GTK_BOX (content_area), button, TRUE, TRUE, 0);
5718       gtk_widget_show (button);
5719
5720       button = gtk_button_new_with_label ("Close");
5721       g_signal_connect_swapped (button, "clicked",
5722                                 G_CALLBACK (gtk_widget_destroy),
5723                                 dialog_window);
5724       gtk_widget_set_can_default (button, TRUE);
5725       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
5726       gtk_widget_grab_default (button);
5727       gtk_widget_show (button);
5728     }
5729
5730   if (!gtk_widget_get_visible (dialog_window))
5731     gtk_widget_show (dialog_window);
5732   else
5733     gtk_widget_destroy (dialog_window);
5734 }
5735
5736 /*
5737  * GtkRange
5738  */
5739
5740 static gchar*
5741 reformat_value (GtkScale *scale,
5742                 gdouble   value)
5743 {
5744   return g_strdup_printf ("-->%0.*g<--",
5745                           gtk_scale_get_digits (scale), value);
5746 }
5747
5748 static void
5749 create_range_controls (GtkWidget *widget)
5750 {
5751   static GtkWidget *window = NULL;
5752   GtkWidget *box1;
5753   GtkWidget *box2;
5754   GtkWidget *button;
5755   GtkWidget *scrollbar;
5756   GtkWidget *scale;
5757   GtkWidget *separator;
5758   GtkAdjustment *adjustment;
5759   GtkWidget *hbox;
5760
5761   if (!window)
5762     {
5763       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5764
5765       gtk_window_set_screen (GTK_WINDOW (window),
5766                              gtk_widget_get_screen (widget));
5767
5768       g_signal_connect (window, "destroy",
5769                         G_CALLBACK (gtk_widget_destroyed),
5770                         &window);
5771
5772       gtk_window_set_title (GTK_WINDOW (window), "range controls");
5773       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5774
5775
5776       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
5777       gtk_container_add (GTK_CONTAINER (window), box1);
5778       gtk_widget_show (box1);
5779
5780
5781       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
5782       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
5783       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
5784       gtk_widget_show (box2);
5785
5786
5787       adjustment = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
5788
5789       scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (adjustment));
5790       gtk_widget_set_size_request (GTK_WIDGET (scale), 150, -1);
5791       gtk_scale_set_digits (GTK_SCALE (scale), 1);
5792       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
5793       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
5794       gtk_widget_show (scale);
5795
5796       scrollbar = gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (adjustment));
5797       gtk_box_pack_start (GTK_BOX (box2), scrollbar, TRUE, TRUE, 0);
5798       gtk_widget_show (scrollbar);
5799
5800       scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, GTK_ADJUSTMENT (adjustment));
5801       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
5802       g_signal_connect (scale,
5803                         "format_value",
5804                         G_CALLBACK (reformat_value),
5805                         NULL);
5806       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
5807       gtk_widget_show (scale);
5808       
5809       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
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_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
5816       gtk_widget_show (scale);
5817
5818       scale = gtk_scale_new (GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT (adjustment));
5819       gtk_widget_set_size_request (scale, -1, 200);
5820       gtk_scale_set_digits (GTK_SCALE (scale), 2);
5821       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
5822       gtk_range_set_inverted (GTK_RANGE (scale), TRUE);
5823       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
5824       gtk_widget_show (scale);
5825
5826       scale = gtk_scale_new (GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT (adjustment));
5827       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
5828       g_signal_connect (scale,
5829                         "format_value",
5830                         G_CALLBACK (reformat_value),
5831                         NULL);
5832       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
5833       gtk_widget_show (scale);
5834
5835       
5836       gtk_box_pack_start (GTK_BOX (box2), hbox, TRUE, TRUE, 0);
5837       gtk_widget_show (hbox);
5838       
5839       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
5840       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
5841       gtk_widget_show (separator);
5842
5843
5844       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
5845       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
5846       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
5847       gtk_widget_show (box2);
5848
5849
5850       button = gtk_button_new_with_label ("close");
5851       g_signal_connect_swapped (button, "clicked",
5852                                 G_CALLBACK (gtk_widget_destroy),
5853                                 window);
5854       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
5855       gtk_widget_set_can_default (button, TRUE);
5856       gtk_widget_grab_default (button);
5857       gtk_widget_show (button);
5858     }
5859
5860   if (!gtk_widget_get_visible (window))
5861     gtk_widget_show (window);
5862   else
5863     gtk_widget_destroy (window);
5864 }
5865
5866 struct {
5867   GdkColor color;
5868   gchar *name;
5869 } text_colors[] = {
5870  { { 0, 0x0000, 0x0000, 0x0000 }, "black" },
5871  { { 0, 0xFFFF, 0xFFFF, 0xFFFF }, "white" },
5872  { { 0, 0xFFFF, 0x0000, 0x0000 }, "red" },
5873  { { 0, 0x0000, 0xFFFF, 0x0000 }, "green" },
5874  { { 0, 0x0000, 0x0000, 0xFFFF }, "blue" }, 
5875  { { 0, 0x0000, 0xFFFF, 0xFFFF }, "cyan" },
5876  { { 0, 0xFFFF, 0x0000, 0xFFFF }, "magenta" },
5877  { { 0, 0xFFFF, 0xFFFF, 0x0000 }, "yellow" }
5878 };
5879
5880 int ntext_colors = sizeof(text_colors) / sizeof(text_colors[0]);
5881
5882 /*
5883  * GtkNotebook
5884  */
5885
5886 static const char * book_open_xpm[] = {
5887 "16 16 4 1",
5888 "       c None s None",
5889 ".      c black",
5890 "X      c #808080",
5891 "o      c white",
5892 "                ",
5893 "  ..            ",
5894 " .Xo.    ...    ",
5895 " .Xoo. ..oo.    ",
5896 " .Xooo.Xooo...  ",
5897 " .Xooo.oooo.X.  ",
5898 " .Xooo.Xooo.X.  ",
5899 " .Xooo.oooo.X.  ",
5900 " .Xooo.Xooo.X.  ",
5901 " .Xooo.oooo.X.  ",
5902 "  .Xoo.Xoo..X.  ",
5903 "   .Xo.o..ooX.  ",
5904 "    .X..XXXXX.  ",
5905 "    ..X.......  ",
5906 "     ..         ",
5907 "                "};
5908
5909 static const char * book_closed_xpm[] = {
5910 "16 16 6 1",
5911 "       c None s None",
5912 ".      c black",
5913 "X      c red",
5914 "o      c yellow",
5915 "O      c #808080",
5916 "#      c white",
5917 "                ",
5918 "       ..       ",
5919 "     ..XX.      ",
5920 "   ..XXXXX.     ",
5921 " ..XXXXXXXX.    ",
5922 ".ooXXXXXXXXX.   ",
5923 "..ooXXXXXXXXX.  ",
5924 ".X.ooXXXXXXXXX. ",
5925 ".XX.ooXXXXXX..  ",
5926 " .XX.ooXXX..#O  ",
5927 "  .XX.oo..##OO. ",
5928 "   .XX..##OO..  ",
5929 "    .X.#OO..    ",
5930 "     ..O..      ",
5931 "      ..        ",
5932 "                "};
5933
5934 GdkPixbuf *book_open;
5935 GdkPixbuf *book_closed;
5936 GtkWidget *sample_notebook;
5937
5938 static void
5939 set_page_image (GtkNotebook *notebook, gint page_num, GdkPixbuf *pixbuf)
5940 {
5941   GtkWidget *page_widget;
5942   GtkWidget *pixwid;
5943
5944   page_widget = gtk_notebook_get_nth_page (notebook, page_num);
5945
5946   pixwid = g_object_get_data (G_OBJECT (page_widget), "tab_pixmap");
5947   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
5948   
5949   pixwid = g_object_get_data (G_OBJECT (page_widget), "menu_pixmap");
5950   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
5951 }
5952
5953 static void
5954 page_switch (GtkWidget *widget, gpointer *page, gint page_num)
5955 {
5956   GtkNotebook *notebook = GTK_NOTEBOOK (widget);
5957   gint old_page_num = gtk_notebook_get_current_page (notebook);
5958  
5959   if (page_num == old_page_num)
5960     return;
5961
5962   set_page_image (notebook, page_num, book_open);
5963
5964   if (old_page_num != -1)
5965     set_page_image (notebook, old_page_num, book_closed);
5966 }
5967
5968 static void
5969 tab_fill (GtkToggleButton *button, GtkWidget *child)
5970 {
5971   gtk_container_child_set (GTK_CONTAINER (sample_notebook), child,
5972                            "tab-fill", gtk_toggle_button_get_active (button),
5973                            NULL);
5974 }
5975
5976 static void
5977 tab_expand (GtkToggleButton *button, GtkWidget *child)
5978 {
5979   gtk_container_child_set (GTK_CONTAINER (sample_notebook), child,
5980                            "tab-expand", gtk_toggle_button_get_active (button),
5981                            NULL);
5982 }
5983
5984 static void
5985 create_pages (GtkNotebook *notebook, gint start, gint end)
5986 {
5987   GtkWidget *child = NULL;
5988   GtkWidget *button;
5989   GtkWidget *label;
5990   GtkWidget *hbox;
5991   GtkWidget *vbox;
5992   GtkWidget *label_box;
5993   GtkWidget *menu_box;
5994   GtkWidget *pixwid;
5995   gint i;
5996   char buffer[32];
5997   char accel_buffer[32];
5998
5999   for (i = start; i <= end; i++)
6000     {
6001       sprintf (buffer, "Page %d", i);
6002       sprintf (accel_buffer, "Page _%d", i);
6003
6004       child = gtk_frame_new (buffer);
6005       gtk_container_set_border_width (GTK_CONTAINER (child), 10);
6006
6007       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
6008       gtk_box_set_homogeneous (GTK_BOX (vbox), TRUE);
6009       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
6010       gtk_container_add (GTK_CONTAINER (child), vbox);
6011
6012       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
6013       gtk_box_set_homogeneous (GTK_BOX (hbox), TRUE);
6014       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
6015
6016       button = gtk_check_button_new_with_label ("Fill Tab");
6017       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6018       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
6019       g_signal_connect (button, "toggled",
6020                         G_CALLBACK (tab_fill), child);
6021
6022       button = gtk_check_button_new_with_label ("Expand Tab");
6023       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6024       g_signal_connect (button, "toggled",
6025                         G_CALLBACK (tab_expand), child);
6026
6027       button = gtk_button_new_with_label ("Hide Page");
6028       gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 5);
6029       g_signal_connect_swapped (button, "clicked",
6030                                 G_CALLBACK (gtk_widget_hide),
6031                                 child);
6032
6033       gtk_widget_show_all (child);
6034
6035       label_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
6036       pixwid = gtk_image_new_from_pixbuf (book_closed);
6037       g_object_set_data (G_OBJECT (child), "tab_pixmap", pixwid);
6038                            
6039       gtk_box_pack_start (GTK_BOX (label_box), pixwid, FALSE, TRUE, 0);
6040       gtk_widget_set_margin_left (pixwid, 3);
6041       gtk_widget_set_margin_right (pixwid, 3);
6042       gtk_widget_set_margin_bottom (pixwid, 1);
6043       gtk_widget_set_margin_top (pixwid, 1);
6044       label = gtk_label_new_with_mnemonic (accel_buffer);
6045       gtk_box_pack_start (GTK_BOX (label_box), label, FALSE, TRUE, 0);
6046       gtk_widget_show_all (label_box);
6047       
6048                                        
6049       menu_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
6050       pixwid = gtk_image_new_from_pixbuf (book_closed);
6051       g_object_set_data (G_OBJECT (child), "menu_pixmap", pixwid);
6052       
6053       gtk_box_pack_start (GTK_BOX (menu_box), pixwid, FALSE, TRUE, 0);
6054       gtk_widget_set_margin_left (pixwid, 3);
6055       gtk_widget_set_margin_right (pixwid, 3);
6056       gtk_widget_set_margin_bottom (pixwid, 1);
6057       gtk_widget_set_margin_top (pixwid, 1);
6058       label = gtk_label_new (buffer);
6059       gtk_box_pack_start (GTK_BOX (menu_box), label, FALSE, TRUE, 0);
6060       gtk_widget_show_all (menu_box);
6061
6062       gtk_notebook_append_page_menu (notebook, child, label_box, menu_box);
6063     }
6064 }
6065
6066 static void
6067 rotate_notebook (GtkButton   *button,
6068                  GtkNotebook *notebook)
6069 {
6070   gtk_notebook_set_tab_pos (notebook, (gtk_notebook_get_tab_pos (notebook) + 1) % 4);
6071 }
6072
6073 static void
6074 show_all_pages (GtkButton   *button,
6075                 GtkNotebook *notebook)
6076 {  
6077   gtk_container_foreach (GTK_CONTAINER (notebook),
6078                          (GtkCallback) gtk_widget_show, NULL);
6079 }
6080
6081 static void
6082 notebook_type_changed (GtkWidget *optionmenu,
6083                        gpointer   data)
6084 {
6085   GtkNotebook *notebook;
6086   gint i, c;
6087
6088   enum {
6089     STANDARD,
6090     NOTABS,
6091     BORDERLESS,
6092     SCROLLABLE
6093   };
6094
6095   notebook = GTK_NOTEBOOK (data);
6096
6097   c = gtk_combo_box_get_active (GTK_COMBO_BOX (optionmenu));
6098
6099   switch (c)
6100     {
6101     case STANDARD:
6102       /* standard notebook */
6103       gtk_notebook_set_show_tabs (notebook, TRUE);
6104       gtk_notebook_set_show_border (notebook, TRUE);
6105       gtk_notebook_set_scrollable (notebook, FALSE);
6106       break;
6107
6108     case NOTABS:
6109       /* notabs notebook */
6110       gtk_notebook_set_show_tabs (notebook, FALSE);
6111       gtk_notebook_set_show_border (notebook, TRUE);
6112       break;
6113
6114     case BORDERLESS:
6115       /* borderless */
6116       gtk_notebook_set_show_tabs (notebook, FALSE);
6117       gtk_notebook_set_show_border (notebook, FALSE);
6118       break;
6119
6120     case SCROLLABLE:  
6121       /* scrollable */
6122       gtk_notebook_set_show_tabs (notebook, TRUE);
6123       gtk_notebook_set_show_border (notebook, TRUE);
6124       gtk_notebook_set_scrollable (notebook, TRUE);
6125       if (gtk_notebook_get_n_pages (notebook) == 5)
6126         create_pages (notebook, 6, 15);
6127
6128       return;
6129       break;
6130     }
6131
6132   if (gtk_notebook_get_n_pages (notebook) == 15)
6133     for (i = 0; i < 10; i++)
6134       gtk_notebook_remove_page (notebook, 5);
6135 }
6136
6137 static void
6138 notebook_popup (GtkToggleButton *button,
6139                 GtkNotebook     *notebook)
6140 {
6141   if (gtk_toggle_button_get_active (button))
6142     gtk_notebook_popup_enable (notebook);
6143   else
6144     gtk_notebook_popup_disable (notebook);
6145 }
6146
6147 static void
6148 create_notebook (GtkWidget *widget)
6149 {
6150   static GtkWidget *window = NULL;
6151   GtkWidget *box1;
6152   GtkWidget *box2;
6153   GtkWidget *button;
6154   GtkWidget *separator;
6155   GtkWidget *omenu;
6156   GtkWidget *label;
6157
6158   static gchar *items[] =
6159   {
6160     "Standard",
6161     "No tabs",
6162     "Borderless",
6163     "Scrollable"
6164   };
6165   
6166   if (!window)
6167     {
6168       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6169       gtk_window_set_screen (GTK_WINDOW (window),
6170                              gtk_widget_get_screen (widget));
6171
6172       g_signal_connect (window, "destroy",
6173                         G_CALLBACK (gtk_widget_destroyed),
6174                         &window);
6175
6176       gtk_window_set_title (GTK_WINDOW (window), "notebook");
6177       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6178
6179       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
6180       gtk_container_add (GTK_CONTAINER (window), box1);
6181
6182       sample_notebook = gtk_notebook_new ();
6183       g_signal_connect (sample_notebook, "switch_page",
6184                         G_CALLBACK (page_switch), NULL);
6185       gtk_notebook_set_tab_pos (GTK_NOTEBOOK (sample_notebook), GTK_POS_TOP);
6186       gtk_box_pack_start (GTK_BOX (box1), sample_notebook, TRUE, TRUE, 0);
6187       gtk_container_set_border_width (GTK_CONTAINER (sample_notebook), 10);
6188
6189       gtk_widget_realize (sample_notebook);
6190
6191       if (!book_open)
6192         book_open = gdk_pixbuf_new_from_xpm_data (book_open_xpm);
6193                                                   
6194       if (!book_closed)
6195         book_closed = gdk_pixbuf_new_from_xpm_data (book_closed_xpm);
6196
6197       create_pages (GTK_NOTEBOOK (sample_notebook), 1, 5);
6198
6199       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
6200       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 10);
6201       
6202       box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
6203       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6204       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
6205
6206       button = gtk_check_button_new_with_label ("popup menu");
6207       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
6208       g_signal_connect (button, "clicked",
6209                         G_CALLBACK (notebook_popup),
6210                         sample_notebook);
6211
6212       box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
6213       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6214       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
6215
6216       label = gtk_label_new ("Notebook Style :");
6217       gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0);
6218
6219       omenu = build_option_menu (items, G_N_ELEMENTS (items), 0,
6220                                  notebook_type_changed,
6221                                  sample_notebook);
6222       gtk_box_pack_start (GTK_BOX (box2), omenu, FALSE, TRUE, 0);
6223
6224       button = gtk_button_new_with_label ("Show all Pages");
6225       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, TRUE, 0);
6226       g_signal_connect (button, "clicked",
6227                         G_CALLBACK (show_all_pages), sample_notebook);
6228
6229       box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
6230       gtk_box_set_homogeneous (GTK_BOX (box2), TRUE);
6231       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6232       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
6233
6234       button = gtk_button_new_with_label ("prev");
6235       g_signal_connect_swapped (button, "clicked",
6236                                 G_CALLBACK (gtk_notebook_prev_page),
6237                                 sample_notebook);
6238       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
6239
6240       button = gtk_button_new_with_label ("next");
6241       g_signal_connect_swapped (button, "clicked",
6242                                 G_CALLBACK (gtk_notebook_next_page),
6243                                 sample_notebook);
6244       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
6245
6246       button = gtk_button_new_with_label ("rotate");
6247       g_signal_connect (button, "clicked",
6248                         G_CALLBACK (rotate_notebook), sample_notebook);
6249       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
6250
6251       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
6252       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
6253
6254       button = gtk_button_new_with_label ("close");
6255       gtk_container_set_border_width (GTK_CONTAINER (button), 5);
6256       g_signal_connect_swapped (button, "clicked",
6257                                 G_CALLBACK (gtk_widget_destroy),
6258                                 window);
6259       gtk_box_pack_start (GTK_BOX (box1), button, FALSE, FALSE, 0);
6260       gtk_widget_set_can_default (button, TRUE);
6261       gtk_widget_grab_default (button);
6262     }
6263
6264   if (!gtk_widget_get_visible (window))
6265     gtk_widget_show_all (window);
6266   else
6267     gtk_widget_destroy (window);
6268 }
6269
6270 /*
6271  * GtkPanes
6272  */
6273
6274 void
6275 toggle_resize (GtkWidget *widget, GtkWidget *child)
6276 {
6277   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
6278   GValue value = { 0, };
6279   g_value_init (&value, G_TYPE_BOOLEAN);
6280   gtk_container_child_get_property (container, child, "resize", &value);
6281   g_value_set_boolean (&value, !g_value_get_boolean (&value));
6282   gtk_container_child_set_property (container, child, "resize", &value);
6283 }
6284
6285 void
6286 toggle_shrink (GtkWidget *widget, GtkWidget *child)
6287 {
6288   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
6289   GValue value = { 0, };
6290   g_value_init (&value, G_TYPE_BOOLEAN);
6291   gtk_container_child_get_property (container, child, "shrink", &value);
6292   g_value_set_boolean (&value, !g_value_get_boolean (&value));
6293   gtk_container_child_set_property (container, child, "shrink", &value);
6294 }
6295
6296 static void
6297 paned_props_clicked (GtkWidget *button,
6298                      GObject   *paned)
6299 {
6300   GtkWidget *window = create_prop_editor (paned, GTK_TYPE_PANED);
6301   
6302   gtk_window_set_title (GTK_WINDOW (window), "Paned Properties");
6303 }
6304
6305 GtkWidget *
6306 create_pane_options (GtkPaned    *paned,
6307                      const gchar *frame_label,
6308                      const gchar *label1,
6309                      const gchar *label2)
6310 {
6311   GtkWidget *child1, *child2;
6312   GtkWidget *frame;
6313   GtkWidget *grid;
6314   GtkWidget *label;
6315   GtkWidget *button;
6316   GtkWidget *check_button;
6317
6318   child1 = gtk_paned_get_child1 (paned);
6319   child2 = gtk_paned_get_child2 (paned);
6320
6321   frame = gtk_frame_new (frame_label);
6322   gtk_container_set_border_width (GTK_CONTAINER (frame), 4);
6323   
6324   grid = gtk_grid_new ();
6325   gtk_container_add (GTK_CONTAINER (frame), grid);
6326   
6327   label = gtk_label_new (label1);
6328   gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
6329   
6330   check_button = gtk_check_button_new_with_label ("Resize");
6331   gtk_grid_attach (GTK_GRID (grid), check_button, 0, 1, 1, 1);
6332   g_signal_connect (check_button, "toggled",
6333                     G_CALLBACK (toggle_resize),
6334                     child1);
6335
6336   check_button = gtk_check_button_new_with_label ("Shrink");
6337   gtk_grid_attach (GTK_GRID (grid), check_button, 0, 2, 1, 1);
6338   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
6339                                TRUE);
6340   g_signal_connect (check_button, "toggled",
6341                     G_CALLBACK (toggle_shrink),
6342                     child1);
6343
6344   label = gtk_label_new (label2);
6345   gtk_grid_attach (GTK_GRID (grid), label, 1, 0, 1, 1);
6346   
6347   check_button = gtk_check_button_new_with_label ("Resize");
6348   gtk_grid_attach (GTK_GRID (grid), check_button, 1, 1, 1, 1);
6349   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
6350                                TRUE);
6351   g_signal_connect (check_button, "toggled",
6352                     G_CALLBACK (toggle_resize),
6353                     child2);
6354
6355   check_button = gtk_check_button_new_with_label ("Shrink");
6356   gtk_grid_attach (GTK_GRID (grid), check_button, 1, 2, 1, 1);
6357   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
6358                                TRUE);
6359   g_signal_connect (check_button, "toggled",
6360                     G_CALLBACK (toggle_shrink),
6361                     child2);
6362
6363   button = gtk_button_new_with_mnemonic ("_Properties");
6364   gtk_grid_attach (GTK_GRID (grid), button, 0, 3, 2, 1);
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 *grid;
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       grid = gtk_grid_new ();
8321       gtk_grid_set_row_spacing (GTK_GRID (grid), 10);
8322       gtk_grid_set_column_spacing (GTK_GRID (grid), 10);
8323       gtk_box_pack_start (GTK_BOX (vbox2), grid, FALSE, TRUE, 0);
8324
8325       label = gtk_label_new ("Orientation :");
8326       gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
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       gtk_grid_attach (GTK_GRID (grid), pdata->omenu1, 1, 0, 1, 1);
8334       
8335       check = gtk_check_button_new_with_label ("Running");
8336       g_signal_connect (check, "toggled",
8337                         G_CALLBACK (toggle_running),
8338                         pdata);
8339       gtk_grid_attach (GTK_GRID (grid), check, 0, 1, 2, 1);
8340       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
8341
8342       check = gtk_check_button_new_with_label ("Show text");
8343       g_signal_connect (check, "clicked",
8344                         G_CALLBACK (toggle_show_text),
8345                         pdata);
8346       gtk_grid_attach (GTK_GRID (grid), check, 0, 2, 1, 1);
8347
8348       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
8349       gtk_grid_attach (GTK_GRID (grid), hbox, 1, 2, 1, 1);
8350
8351       label = gtk_label_new ("Text: ");
8352       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
8353
8354       pdata->entry = gtk_entry_new ();
8355       gtk_widget_set_hexpand (pdata->entry, TRUE);
8356       g_signal_connect (pdata->entry, "changed",
8357                         G_CALLBACK (entry_changed),
8358                         pdata);
8359       gtk_box_pack_start (GTK_BOX (hbox), pdata->entry, TRUE, TRUE, 0);
8360       gtk_widget_set_size_request (pdata->entry, 100, -1);
8361
8362       label = gtk_label_new ("Ellipsize text :");
8363       gtk_grid_attach (GTK_GRID (grid), label, 0, 10, 1, 1);
8364
8365       gtk_widget_set_halign (label, GTK_ALIGN_START);
8366       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
8367       pdata->elmenu = build_option_menu (ellipsize_items,
8368                                          sizeof (ellipsize_items) / sizeof (ellipsize_items[0]),
8369                                          2, // PANGO_ELLIPSIZE_MIDDLE
8370                                          progressbar_toggle_ellipsize,
8371                                          pdata);
8372       gtk_grid_attach (GTK_GRID (grid), pdata->elmenu, 1, 10, 1, 1);
8373
8374       check = gtk_check_button_new_with_label ("Activity mode");
8375       g_signal_connect (check, "clicked",
8376                         G_CALLBACK (toggle_activity_mode), pdata);
8377       gtk_grid_attach (GTK_GRID (grid), check, 0, 15, 1, 1);
8378
8379       button = gtk_button_new_with_label ("close");
8380       g_signal_connect_swapped (button, "clicked",
8381                                 G_CALLBACK (gtk_widget_destroy),
8382                                 pdata->window);
8383       gtk_widget_set_can_default (button, TRUE);
8384       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
8385       gtk_widget_grab_default (button);
8386     }
8387
8388   if (!gtk_widget_get_visible (pdata->window))
8389     gtk_widget_show_all (pdata->window);
8390   else
8391     gtk_widget_destroy (pdata->window);
8392 }
8393
8394 /*
8395  * Properties
8396  */
8397
8398 typedef struct {
8399   int x;
8400   int y;
8401   gboolean found;
8402   gboolean first;
8403   GtkWidget *res_widget;
8404 } FindWidgetData;
8405
8406 static void
8407 find_widget (GtkWidget *widget, FindWidgetData *data)
8408 {
8409   GtkAllocation new_allocation;
8410   gint x_offset = 0;
8411   gint y_offset = 0;
8412
8413   gtk_widget_get_allocation (widget, &new_allocation);
8414
8415   if (data->found || !gtk_widget_get_mapped (widget))
8416     return;
8417
8418   /* Note that in the following code, we only count the
8419    * position as being inside a WINDOW widget if it is inside
8420    * widget->window; points that are outside of widget->window
8421    * but within the allocation are not counted. This is consistent
8422    * with the way we highlight drag targets.
8423    */
8424   if (gtk_widget_get_has_window (widget))
8425     {
8426       new_allocation.x = 0;
8427       new_allocation.y = 0;
8428     }
8429
8430   if (gtk_widget_get_parent (widget) && !data->first)
8431     {
8432       GdkWindow *window = gtk_widget_get_window (widget);
8433       while (window != gtk_widget_get_window (gtk_widget_get_parent (widget)))
8434         {
8435           gint tx, ty, twidth, theight;
8436           
8437           twidth = gdk_window_get_width (window);
8438           theight = gdk_window_get_height (window);
8439
8440           if (new_allocation.x < 0)
8441             {
8442               new_allocation.width += new_allocation.x;
8443               new_allocation.x = 0;
8444             }
8445           if (new_allocation.y < 0)
8446             {
8447               new_allocation.height += new_allocation.y;
8448               new_allocation.y = 0;
8449             }
8450           if (new_allocation.x + new_allocation.width > twidth)
8451             new_allocation.width = twidth - new_allocation.x;
8452           if (new_allocation.y + new_allocation.height > theight)
8453             new_allocation.height = theight - new_allocation.y;
8454
8455           gdk_window_get_position (window, &tx, &ty);
8456           new_allocation.x += tx;
8457           x_offset += tx;
8458           new_allocation.y += ty;
8459           y_offset += ty;
8460
8461           window = gdk_window_get_parent (window);
8462         }
8463     }
8464
8465   if ((data->x >= new_allocation.x) && (data->y >= new_allocation.y) &&
8466       (data->x < new_allocation.x + new_allocation.width) && 
8467       (data->y < new_allocation.y + new_allocation.height))
8468     {
8469       /* First, check if the drag is in a valid drop site in
8470        * one of our children 
8471        */
8472       if (GTK_IS_CONTAINER (widget))
8473         {
8474           FindWidgetData new_data = *data;
8475           
8476           new_data.x -= x_offset;
8477           new_data.y -= y_offset;
8478           new_data.found = FALSE;
8479           new_data.first = FALSE;
8480           
8481           gtk_container_forall (GTK_CONTAINER (widget),
8482                                 (GtkCallback)find_widget,
8483                                 &new_data);
8484           
8485           data->found = new_data.found;
8486           if (data->found)
8487             data->res_widget = new_data.res_widget;
8488         }
8489
8490       /* If not, and this widget is registered as a drop site, check to
8491        * emit "drag_motion" to check if we are actually in
8492        * a drop site.
8493        */
8494       if (!data->found)
8495         {
8496           data->found = TRUE;
8497           data->res_widget = widget;
8498         }
8499     }
8500 }
8501
8502 static GtkWidget *
8503 find_widget_at_pointer (GdkDevice *device)
8504 {
8505   GtkWidget *widget = NULL;
8506   GdkWindow *pointer_window;
8507   gint x, y;
8508   FindWidgetData data;
8509  
8510  pointer_window = gdk_device_get_window_at_position (device, NULL, NULL);
8511  
8512  if (pointer_window)
8513    {
8514      gpointer widget_ptr;
8515
8516      gdk_window_get_user_data (pointer_window, &widget_ptr);
8517      widget = widget_ptr;
8518    }
8519
8520  if (widget)
8521    {
8522      gdk_window_get_pointer (gtk_widget_get_window (widget),
8523                              &x, &y, NULL);
8524      
8525      data.x = x;
8526      data.y = y;
8527      data.found = FALSE;
8528      data.first = TRUE;
8529
8530      find_widget (widget, &data);
8531      if (data.found)
8532        return data.res_widget;
8533      return widget;
8534    }
8535  return NULL;
8536 }
8537
8538 struct PropertiesData {
8539   GtkWidget **window;
8540   GdkCursor *cursor;
8541   gboolean in_query;
8542   gulong handler;
8543 };
8544
8545 static void
8546 destroy_properties (GtkWidget             *widget,
8547                     struct PropertiesData *data)
8548 {
8549   if (data->window)
8550     {
8551       *data->window = NULL;
8552       data->window = NULL;
8553     }
8554
8555   if (data->cursor)
8556     {
8557       g_object_unref (data->cursor);
8558       data->cursor = NULL;
8559     }
8560
8561   if (data->handler)
8562     {
8563       g_signal_handler_disconnect (widget, data->handler);
8564       data->handler = 0;
8565     }
8566
8567   g_free (data);
8568 }
8569
8570 static gint
8571 property_query_event (GtkWidget             *widget,
8572                       GdkEvent              *event,
8573                       struct PropertiesData *data)
8574 {
8575   GtkWidget *res_widget = NULL;
8576
8577   if (!data->in_query)
8578     return FALSE;
8579
8580   if (event->type == GDK_BUTTON_RELEASE)
8581     {
8582       gtk_grab_remove (widget);
8583       gdk_device_ungrab (gdk_event_get_device (event), GDK_CURRENT_TIME);
8584
8585       res_widget = find_widget_at_pointer (gdk_event_get_device (event));
8586       if (res_widget)
8587         {
8588           g_object_set_data (G_OBJECT (res_widget), "prop-editor-screen",
8589                              gtk_widget_get_screen (widget));
8590           create_prop_editor (G_OBJECT (res_widget), 0);
8591         }
8592
8593       data->in_query = FALSE;
8594     }
8595   return FALSE;
8596 }
8597
8598
8599 static void
8600 query_properties (GtkButton *button,
8601                   struct PropertiesData *data)
8602 {
8603   GtkWidget *widget = GTK_WIDGET (button);
8604   GdkDisplay *display;
8605   GdkDeviceManager *device_manager;
8606   GdkDevice *device;
8607
8608   g_signal_connect (button, "event",
8609                     G_CALLBACK (property_query_event), data);
8610
8611   display = gtk_widget_get_display (widget);
8612
8613   if (!data->cursor)
8614     data->cursor = gdk_cursor_new_for_display (display, GDK_TARGET);
8615
8616   device_manager = gdk_display_get_device_manager (display);
8617   device = gdk_device_manager_get_client_pointer (device_manager);
8618   gdk_device_grab (device,
8619                    gtk_widget_get_window (widget),
8620                    GDK_OWNERSHIP_NONE,
8621                    TRUE,
8622                    GDK_BUTTON_RELEASE_MASK,
8623                    data->cursor,
8624                    GDK_CURRENT_TIME);
8625   gtk_grab_add (widget);
8626
8627   data->in_query = TRUE;
8628 }
8629
8630 static void
8631 create_properties (GtkWidget *widget)
8632 {
8633   static GtkWidget *window = NULL;
8634   GtkWidget *button;
8635   GtkWidget *vbox;
8636   GtkWidget *label;
8637   struct PropertiesData *data;
8638
8639   data = g_new (struct PropertiesData, 1);
8640   data->window = &window;
8641   data->in_query = FALSE;
8642   data->cursor = NULL;
8643   data->handler = 0;
8644
8645   if (!window)
8646     {
8647       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8648
8649       gtk_window_set_screen (GTK_WINDOW (window),
8650                              gtk_widget_get_screen (widget));      
8651
8652       data->handler = g_signal_connect (window, "destroy",
8653                                         G_CALLBACK (destroy_properties),
8654                                         data);
8655
8656       gtk_window_set_title (GTK_WINDOW (window), "test properties");
8657       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
8658
8659       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 1);
8660       gtk_container_add (GTK_CONTAINER (window), vbox);
8661             
8662       label = gtk_label_new ("This is just a dumb test to test properties.\nIf you need a generic module, get GLE.");
8663       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
8664       
8665       button = gtk_button_new_with_label ("Query properties");
8666       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
8667       g_signal_connect (button, "clicked",
8668                         G_CALLBACK (query_properties),
8669                         data);
8670     }
8671
8672   if (!gtk_widget_get_visible (window))
8673     gtk_widget_show_all (window);
8674   else
8675     gtk_widget_destroy (window);
8676   
8677 }
8678
8679 struct SnapshotData {
8680   GtkWidget *toplevel_button;
8681   GtkWidget **window;
8682   GdkCursor *cursor;
8683   gboolean in_query;
8684   gboolean is_toplevel;
8685   gint handler;
8686 };
8687
8688 static void
8689 destroy_snapshot_data (GtkWidget             *widget,
8690                        struct SnapshotData *data)
8691 {
8692   if (*data->window)
8693     *data->window = NULL;
8694   
8695   if (data->cursor)
8696     {
8697       g_object_unref (data->cursor);
8698       data->cursor = NULL;
8699     }
8700
8701   if (data->handler)
8702     {
8703       g_signal_handler_disconnect (widget, data->handler);
8704       data->handler = 0;
8705     }
8706
8707   g_free (data);
8708 }
8709
8710 static gint
8711 snapshot_widget_event (GtkWidget               *widget,
8712                        GdkEvent        *event,
8713                        struct SnapshotData *data)
8714 {
8715   GtkWidget *res_widget = NULL;
8716
8717   if (!data->in_query)
8718     return FALSE;
8719   
8720   if (event->type == GDK_BUTTON_RELEASE)
8721     {
8722       gtk_grab_remove (widget);
8723       gdk_device_ungrab (gdk_event_get_device (event),
8724                          GDK_CURRENT_TIME);
8725       
8726       res_widget = find_widget_at_pointer (gdk_event_get_device (event));
8727       if (data->is_toplevel && res_widget)
8728         res_widget = gtk_widget_get_toplevel (res_widget);
8729       if (res_widget)
8730         {
8731           cairo_surface_t *surface;
8732           GtkWidget *window, *image;
8733           GdkPixbuf *pixbuf;
8734           int width, height;
8735           cairo_t *cr;
8736
8737           width = gtk_widget_get_allocated_width (res_widget);
8738           height = gtk_widget_get_allocated_height (res_widget);
8739
8740           surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
8741
8742           cr = cairo_create (surface);
8743           gtk_widget_draw (res_widget, cr);
8744           cairo_destroy (cr);
8745
8746           pixbuf = gdk_pixbuf_get_from_surface (surface,
8747                                                 0, 0,
8748                                                 width, height);
8749           cairo_surface_destroy (surface);
8750
8751           window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8752           image = gtk_image_new_from_pixbuf (pixbuf);
8753           g_object_unref (pixbuf);
8754
8755           gtk_container_add (GTK_CONTAINER (window), image);
8756           gtk_widget_show_all (window);
8757         }
8758
8759       data->in_query = FALSE;
8760     }
8761   return FALSE;
8762 }
8763
8764
8765 static void
8766 snapshot_widget (GtkButton *button,
8767                  struct SnapshotData *data)
8768 {
8769   GtkWidget *widget = GTK_WIDGET (button);
8770   GdkDevice *device;
8771
8772   device = gtk_get_current_event_device ();
8773   if (device == NULL)
8774     return;
8775
8776   if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
8777     device = gdk_device_get_associated_device (device);
8778
8779   data->is_toplevel = widget == data->toplevel_button;
8780
8781   if (!data->cursor)
8782     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
8783                                                GDK_TARGET);
8784
8785   gdk_device_grab (device,
8786                    gtk_widget_get_window (widget),
8787                    GDK_OWNERSHIP_APPLICATION,
8788                    TRUE,
8789                    GDK_BUTTON_RELEASE_MASK,
8790                    data->cursor,
8791                    GDK_CURRENT_TIME);
8792
8793   g_signal_connect (button, "event",
8794                     G_CALLBACK (snapshot_widget_event), data);
8795
8796   gtk_grab_add (widget);
8797
8798   data->in_query = TRUE;
8799 }
8800
8801 static void
8802 create_snapshot (GtkWidget *widget)
8803 {
8804   static GtkWidget *window = NULL;
8805   GtkWidget *button;
8806   GtkWidget *vbox;
8807   struct SnapshotData *data;
8808
8809   data = g_new (struct SnapshotData, 1);
8810   data->window = &window;
8811   data->in_query = FALSE;
8812   data->cursor = NULL;
8813   data->handler = 0;
8814
8815   if (!window)
8816     {
8817       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8818
8819       gtk_window_set_screen (GTK_WINDOW (window),
8820                              gtk_widget_get_screen (widget));      
8821
8822       data->handler = g_signal_connect (window, "destroy",
8823                                         G_CALLBACK (destroy_snapshot_data),
8824                                         data);
8825
8826       gtk_window_set_title (GTK_WINDOW (window), "test snapshot");
8827       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
8828
8829       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 1);
8830       gtk_container_add (GTK_CONTAINER (window), vbox);
8831             
8832       button = gtk_button_new_with_label ("Snapshot widget");
8833       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
8834       g_signal_connect (button, "clicked",
8835                         G_CALLBACK (snapshot_widget),
8836                         data);
8837       
8838       button = gtk_button_new_with_label ("Snapshot toplevel");
8839       data->toplevel_button = button;
8840       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
8841       g_signal_connect (button, "clicked",
8842                         G_CALLBACK (snapshot_widget),
8843                         data);
8844     }
8845
8846   if (!gtk_widget_get_visible (window))
8847     gtk_widget_show_all (window);
8848   else
8849     gtk_widget_destroy (window);
8850   
8851 }
8852
8853 /*
8854  * Selection Test
8855  */
8856
8857 void
8858 selection_test_received (GtkWidget        *tree_view,
8859                          GtkSelectionData *selection_data)
8860 {
8861   GtkTreeModel *model;
8862   GtkListStore *store;
8863   GdkAtom *atoms;
8864   int i, l;
8865
8866   if (gtk_selection_data_get_length (selection_data) < 0)
8867     {
8868       g_print ("Selection retrieval failed\n");
8869       return;
8870     }
8871   if (gtk_selection_data_get_data_type (selection_data) != GDK_SELECTION_TYPE_ATOM)
8872     {
8873       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
8874       return;
8875     }
8876
8877   /* Clear out any current list items */
8878
8879   model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
8880   store = GTK_LIST_STORE (model);
8881   gtk_list_store_clear (store);
8882
8883   /* Add new items to list */
8884
8885   gtk_selection_data_get_targets (selection_data,
8886                                   &atoms, &l);
8887
8888   for (i = 0; i < l; i++)
8889     {
8890       char *name;
8891       GtkTreeIter iter;
8892
8893       name = gdk_atom_name (atoms[i]);
8894       if (name != NULL)
8895         {
8896           gtk_list_store_insert_with_values (store, &iter, i, 0, name, -1);
8897           g_free (name);
8898         }
8899       else
8900        gtk_list_store_insert_with_values (store, &iter, i, 0,  "(bad atom)", -1);
8901     }
8902
8903   return;
8904 }
8905
8906 void
8907 selection_test_get_targets (GtkWidget *widget, GtkWidget *tree_view)
8908 {
8909   static GdkAtom targets_atom = GDK_NONE;
8910
8911   if (targets_atom == GDK_NONE)
8912     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
8913
8914   gtk_selection_convert (tree_view, GDK_SELECTION_PRIMARY, targets_atom,
8915                          GDK_CURRENT_TIME);
8916 }
8917
8918 void
8919 create_selection_test (GtkWidget *widget)
8920 {
8921   static GtkWidget *window = NULL;
8922   GtkWidget *action_area, *content_area;
8923   GtkWidget *button;
8924   GtkWidget *vbox;
8925   GtkWidget *scrolled_win;
8926   GtkListStore* store;
8927   GtkWidget *tree_view;
8928   GtkTreeViewColumn *column;
8929   GtkCellRenderer *renderer;
8930   GtkWidget *label;
8931
8932   if (!window)
8933     {
8934       window = gtk_dialog_new ();
8935       
8936       gtk_window_set_screen (GTK_WINDOW (window),
8937                              gtk_widget_get_screen (widget));
8938
8939       g_signal_connect (window, "destroy",
8940                         G_CALLBACK (gtk_widget_destroyed),
8941                         &window);
8942
8943       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
8944       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
8945
8946       gtk_window_set_title (GTK_WINDOW (window), "Selection Test");
8947       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8948
8949       /* Create the list */
8950
8951       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
8952       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
8953       gtk_box_pack_start (GTK_BOX (content_area), vbox, TRUE, TRUE, 0);
8954
8955       label = gtk_label_new ("Gets available targets for current selection");
8956       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
8957
8958       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
8959       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
8960                                       GTK_POLICY_AUTOMATIC, 
8961                                       GTK_POLICY_AUTOMATIC);
8962       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
8963       gtk_widget_set_size_request (scrolled_win, 100, 200);
8964
8965       store = gtk_list_store_new (1, G_TYPE_STRING);
8966       tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
8967       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), tree_view);
8968
8969       renderer = gtk_cell_renderer_text_new ();
8970       column = gtk_tree_view_column_new_with_attributes ("Target", renderer,
8971                                                          "text", 0, NULL);
8972       gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
8973
8974       g_signal_connect (tree_view, "selection_received",
8975                         G_CALLBACK (selection_test_received), NULL);
8976
8977       /* .. And create some buttons */
8978       button = gtk_button_new_with_label ("Get Targets");
8979       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
8980
8981       g_signal_connect (button, "clicked",
8982                         G_CALLBACK (selection_test_get_targets), tree_view);
8983
8984       button = gtk_button_new_with_label ("Quit");
8985       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
8986
8987       g_signal_connect_swapped (button, "clicked",
8988                                 G_CALLBACK (gtk_widget_destroy),
8989                                 window);
8990     }
8991
8992   if (!gtk_widget_get_visible (window))
8993     gtk_widget_show_all (window);
8994   else
8995     gtk_widget_destroy (window);
8996 }
8997
8998 /*
8999  * Test scrolling
9000  */
9001
9002 static int scroll_test_pos = 0.0;
9003
9004 static gint
9005 scroll_test_draw (GtkWidget     *widget,
9006                   cairo_t       *cr,
9007                   GtkAdjustment *adjustment)
9008 {
9009   gint i,j;
9010   gint imin, imax, jmin, jmax;
9011   GdkRectangle clip;
9012   
9013   gdk_cairo_get_clip_rectangle (cr, &clip);
9014
9015   imin = (clip.x) / 10;
9016   imax = (clip.x + clip.width + 9) / 10;
9017
9018   jmin = ((int)gtk_adjustment_get_value (adjustment) + clip.y) / 10;
9019   jmax = ((int)gtk_adjustment_get_value (adjustment) + clip.y + clip.height + 9) / 10;
9020
9021   for (i=imin; i<imax; i++)
9022     for (j=jmin; j<jmax; j++)
9023       if ((i+j) % 2)
9024         cairo_rectangle (cr, 10*i, 10*j - (int)gtk_adjustment_get_value (adjustment), 1+i%10, 1+j%10);
9025
9026   cairo_fill (cr);
9027
9028   return TRUE;
9029 }
9030
9031 static gint
9032 scroll_test_scroll (GtkWidget *widget, GdkEventScroll *event,
9033                     GtkAdjustment *adjustment)
9034 {
9035   gdouble new_value = gtk_adjustment_get_value (adjustment) + ((event->direction == GDK_SCROLL_UP) ?
9036                                     -gtk_adjustment_get_page_increment (adjustment) / 2:
9037                                     gtk_adjustment_get_page_increment (adjustment) / 2);
9038   new_value = CLAMP (new_value, gtk_adjustment_get_lower (adjustment), gtk_adjustment_get_upper (adjustment) - gtk_adjustment_get_page_size (adjustment));
9039   gtk_adjustment_set_value (adjustment, new_value);  
9040   
9041   return TRUE;
9042 }
9043
9044 static void
9045 scroll_test_configure (GtkWidget *widget, GdkEventConfigure *event,
9046                        GtkAdjustment *adjustment)
9047 {
9048   GtkAllocation allocation;
9049
9050   gtk_widget_get_allocation (widget, &allocation);
9051   gtk_adjustment_configure (adjustment,
9052                             gtk_adjustment_get_value (adjustment),
9053                             gtk_adjustment_get_lower (adjustment),
9054                             gtk_adjustment_get_upper (adjustment),
9055                             0.1 * allocation.height,
9056                             0.9 * allocation.height,
9057                             allocation.height);
9058 }
9059
9060 static void
9061 scroll_test_adjustment_changed (GtkAdjustment *adjustment, GtkWidget *widget)
9062 {
9063   GdkWindow *window;
9064   gint dy;
9065
9066   dy = scroll_test_pos - (int)gtk_adjustment_get_value (adjustment);
9067   scroll_test_pos = gtk_adjustment_get_value (adjustment);
9068
9069   if (!gtk_widget_is_drawable (widget))
9070     return;
9071
9072   window = gtk_widget_get_window (widget);
9073   gdk_window_scroll (window, 0, dy);
9074   gdk_window_process_updates (window, FALSE);
9075 }
9076
9077
9078 void
9079 create_scroll_test (GtkWidget *widget)
9080 {
9081   static GtkWidget *window = NULL;
9082   GtkWidget *action_area, *content_area;
9083   GtkWidget *hbox;
9084   GtkWidget *drawing_area;
9085   GtkWidget *scrollbar;
9086   GtkWidget *button;
9087   GtkAdjustment *adjustment;
9088   GdkGeometry geometry;
9089   GdkWindowHints geometry_mask;
9090
9091   if (!window)
9092     {
9093       window = gtk_dialog_new ();
9094
9095       gtk_window_set_screen (GTK_WINDOW (window),
9096                              gtk_widget_get_screen (widget));
9097
9098       g_signal_connect (window, "destroy",
9099                         G_CALLBACK (gtk_widget_destroyed),
9100                         &window);
9101
9102       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9103       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9104
9105       gtk_window_set_title (GTK_WINDOW (window), "Scroll Test");
9106       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9107
9108       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
9109       gtk_box_pack_start (GTK_BOX (content_area), hbox, TRUE, TRUE, 0);
9110       gtk_widget_show (hbox);
9111
9112       drawing_area = gtk_drawing_area_new ();
9113       gtk_widget_set_size_request (drawing_area, 200, 200);
9114       gtk_box_pack_start (GTK_BOX (hbox), drawing_area, TRUE, TRUE, 0);
9115       gtk_widget_show (drawing_area);
9116
9117       gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK | GDK_SCROLL_MASK);
9118
9119       adjustment = gtk_adjustment_new (0.0, 0.0, 1000.0, 1.0, 180.0, 200.0);
9120       scroll_test_pos = 0.0;
9121
9122       scrollbar = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, adjustment);
9123       gtk_box_pack_start (GTK_BOX (hbox), scrollbar, FALSE, FALSE, 0);
9124       gtk_widget_show (scrollbar);
9125
9126       g_signal_connect (drawing_area, "draw",
9127                         G_CALLBACK (scroll_test_draw), adjustment);
9128       g_signal_connect (drawing_area, "configure_event",
9129                         G_CALLBACK (scroll_test_configure), adjustment);
9130       g_signal_connect (drawing_area, "scroll_event",
9131                         G_CALLBACK (scroll_test_scroll), adjustment);
9132       
9133       g_signal_connect (adjustment, "value_changed",
9134                         G_CALLBACK (scroll_test_adjustment_changed),
9135                         drawing_area);
9136       
9137       /* .. And create some buttons */
9138
9139       button = gtk_button_new_with_label ("Quit");
9140       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9141
9142       g_signal_connect_swapped (button, "clicked",
9143                                 G_CALLBACK (gtk_widget_destroy),
9144                                 window);
9145       gtk_widget_show (button);
9146
9147       /* Set up gridded geometry */
9148
9149       geometry_mask = GDK_HINT_MIN_SIZE | 
9150                        GDK_HINT_BASE_SIZE | 
9151                        GDK_HINT_RESIZE_INC;
9152
9153       geometry.min_width = 20;
9154       geometry.min_height = 20;
9155       geometry.base_width = 0;
9156       geometry.base_height = 0;
9157       geometry.width_inc = 10;
9158       geometry.height_inc = 10;
9159       
9160       gtk_window_set_geometry_hints (GTK_WINDOW (window),
9161                                drawing_area, &geometry, geometry_mask);
9162     }
9163
9164   if (!gtk_widget_get_visible (window))
9165     gtk_widget_show (window);
9166   else
9167     gtk_widget_destroy (window);
9168 }
9169
9170 /*
9171  * Timeout Test
9172  */
9173
9174 static int timer = 0;
9175
9176 gint
9177 timeout_test (GtkWidget *label)
9178 {
9179   static int count = 0;
9180   static char buffer[32];
9181
9182   sprintf (buffer, "count: %d", ++count);
9183   gtk_label_set_text (GTK_LABEL (label), buffer);
9184
9185   return TRUE;
9186 }
9187
9188 void
9189 start_timeout_test (GtkWidget *widget,
9190                     GtkWidget *label)
9191 {
9192   if (!timer)
9193     {
9194       timer = g_timeout_add (100, (GSourceFunc)timeout_test, label);
9195     }
9196 }
9197
9198 void
9199 stop_timeout_test (GtkWidget *widget,
9200                    gpointer   data)
9201 {
9202   if (timer)
9203     {
9204       g_source_remove (timer);
9205       timer = 0;
9206     }
9207 }
9208
9209 void
9210 destroy_timeout_test (GtkWidget  *widget,
9211                       GtkWidget **window)
9212 {
9213   stop_timeout_test (NULL, NULL);
9214
9215   *window = NULL;
9216 }
9217
9218 void
9219 create_timeout_test (GtkWidget *widget)
9220 {
9221   static GtkWidget *window = NULL;
9222   GtkWidget *action_area, *content_area;
9223   GtkWidget *button;
9224   GtkWidget *label;
9225
9226   if (!window)
9227     {
9228       window = gtk_dialog_new ();
9229
9230       gtk_window_set_screen (GTK_WINDOW (window),
9231                              gtk_widget_get_screen (widget));
9232
9233       g_signal_connect (window, "destroy",
9234                         G_CALLBACK (destroy_timeout_test),
9235                         &window);
9236
9237       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9238       action_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9239
9240       gtk_window_set_title (GTK_WINDOW (window), "Timeout Test");
9241       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9242
9243       label = gtk_label_new ("count: 0");
9244       g_object_set (label, "margin", 10, NULL);
9245       gtk_box_pack_start (GTK_BOX (content_area), label, TRUE, TRUE, 0);
9246       gtk_widget_show (label);
9247
9248       button = gtk_button_new_with_label ("close");
9249       g_signal_connect_swapped (button, "clicked",
9250                                 G_CALLBACK (gtk_widget_destroy),
9251                                 window);
9252       gtk_widget_set_can_default (button, TRUE);
9253       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9254       gtk_widget_grab_default (button);
9255       gtk_widget_show (button);
9256
9257       button = gtk_button_new_with_label ("start");
9258       g_signal_connect (button, "clicked",
9259                         G_CALLBACK(start_timeout_test),
9260                         label);
9261       gtk_widget_set_can_default (button, TRUE);
9262       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9263       gtk_widget_show (button);
9264
9265       button = gtk_button_new_with_label ("stop");
9266       g_signal_connect (button, "clicked",
9267                         G_CALLBACK (stop_timeout_test),
9268                         NULL);
9269       gtk_widget_set_can_default (button, TRUE);
9270       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9271       gtk_widget_show (button);
9272     }
9273
9274   if (!gtk_widget_get_visible (window))
9275     gtk_widget_show (window);
9276   else
9277     gtk_widget_destroy (window);
9278 }
9279
9280 /*
9281  * Idle Test
9282  */
9283
9284 static int idle_id = 0;
9285
9286 static gint
9287 idle_test (GtkWidget *label)
9288 {
9289   static int count = 0;
9290   static char buffer[32];
9291
9292   sprintf (buffer, "count: %d", ++count);
9293   gtk_label_set_text (GTK_LABEL (label), buffer);
9294
9295   return TRUE;
9296 }
9297
9298 static void
9299 start_idle_test (GtkWidget *widget,
9300                  GtkWidget *label)
9301 {
9302   if (!idle_id)
9303     {
9304       idle_id = g_idle_add ((GSourceFunc) idle_test, label);
9305     }
9306 }
9307
9308 static void
9309 stop_idle_test (GtkWidget *widget,
9310                 gpointer   data)
9311 {
9312   if (idle_id)
9313     {
9314       g_source_remove (idle_id);
9315       idle_id = 0;
9316     }
9317 }
9318
9319 static void
9320 destroy_idle_test (GtkWidget  *widget,
9321                    GtkWidget **window)
9322 {
9323   stop_idle_test (NULL, NULL);
9324
9325   *window = NULL;
9326 }
9327
9328 static void
9329 toggle_idle_container (GObject *button,
9330                        GtkContainer *container)
9331 {
9332   gtk_container_set_resize_mode (container, GPOINTER_TO_INT (g_object_get_data (button, "user_data")));
9333 }
9334
9335 static void
9336 create_idle_test (GtkWidget *widget)
9337 {
9338   static GtkWidget *window = NULL;
9339   GtkWidget *button;
9340   GtkWidget *label;
9341   GtkWidget *container;
9342
9343   if (!window)
9344     {
9345       GtkWidget *action_area, *content_area;
9346       GtkWidget *button2;
9347       GtkWidget *frame;
9348       GtkWidget *box;
9349
9350       window = gtk_dialog_new ();
9351
9352       gtk_window_set_screen (GTK_WINDOW (window),
9353                              gtk_widget_get_screen (widget));
9354
9355       g_signal_connect (window, "destroy",
9356                         G_CALLBACK (destroy_idle_test),
9357                         &window);
9358
9359       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9360       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9361
9362       gtk_window_set_title (GTK_WINDOW (window), "Idle Test");
9363       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9364
9365       label = gtk_label_new ("count: 0");
9366       g_object_set (label, "margin", 10, NULL);
9367       gtk_widget_show (label);
9368       
9369       container =
9370         g_object_new (GTK_TYPE_BOX,
9371                         "visible", TRUE,
9372                         /* "GtkContainer::child", g_object_new (GTK_TYPE_HBOX,
9373                          * "GtkWidget::visible", TRUE,
9374                          */
9375                          "child", label,
9376                         /* NULL), */
9377                         NULL);
9378       gtk_box_pack_start (GTK_BOX (content_area), container, TRUE, TRUE, 0);
9379
9380       frame =
9381         g_object_new (GTK_TYPE_FRAME,
9382                         "border_width", 5,
9383                         "label", "Label Container",
9384                         "visible", TRUE,
9385                         "parent", content_area,
9386                         NULL);
9387       box =
9388         g_object_new (GTK_TYPE_BOX,
9389                         "visible", TRUE,
9390                         "parent", frame,
9391                         "orientation", GTK_ORIENTATION_VERTICAL,
9392                         NULL);
9393       button =
9394         g_object_connect (g_object_new (GTK_TYPE_RADIO_BUTTON,
9395                                           "label", "Resize-Parent",
9396                                           "user_data", (void*)GTK_RESIZE_PARENT,
9397                                           "visible", TRUE,
9398                                           "parent", box,
9399                                           NULL),
9400                           "signal::clicked", toggle_idle_container, container,
9401                           NULL);
9402       button = g_object_new (GTK_TYPE_RADIO_BUTTON,
9403                                "label", "Resize-Queue",
9404                                "user_data", (void*)GTK_RESIZE_QUEUE,
9405                                "group", button,
9406                                "visible", TRUE,
9407                                "parent", box,
9408                                NULL);
9409       g_object_connect (button,
9410                         "signal::clicked", toggle_idle_container, container,
9411                         NULL);
9412       button2 = g_object_new (GTK_TYPE_RADIO_BUTTON,
9413                                 "label", "Resize-Immediate",
9414                                 "user_data", (void*)GTK_RESIZE_IMMEDIATE,
9415                                 NULL);
9416       g_object_connect (button2,
9417                         "signal::clicked", toggle_idle_container, container,
9418                         NULL);
9419       g_object_set (button2,
9420                     "group", button,
9421                     "visible", TRUE,
9422                     "parent", box,
9423                     NULL);
9424
9425       button = gtk_button_new_with_label ("close");
9426       g_signal_connect_swapped (button, "clicked",
9427                                 G_CALLBACK (gtk_widget_destroy),
9428                                 window);
9429       gtk_widget_set_can_default (button, TRUE);
9430       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9431       gtk_widget_grab_default (button);
9432       gtk_widget_show (button);
9433
9434       button = gtk_button_new_with_label ("start");
9435       g_signal_connect (button, "clicked",
9436                         G_CALLBACK (start_idle_test),
9437                         label);
9438       gtk_widget_set_can_default (button, TRUE);
9439       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9440       gtk_widget_show (button);
9441
9442       button = gtk_button_new_with_label ("stop");
9443       g_signal_connect (button, "clicked",
9444                         G_CALLBACK (stop_idle_test),
9445                         NULL);
9446       gtk_widget_set_can_default (button, TRUE);
9447       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9448       gtk_widget_show (button);
9449     }
9450
9451   if (!gtk_widget_get_visible (window))
9452     gtk_widget_show (window);
9453   else
9454     gtk_widget_destroy (window);
9455 }
9456
9457 /*
9458  * rc file test
9459  */
9460
9461 void
9462 create_rc_file (GtkWidget *widget)
9463 {
9464   static GtkWidget *window = NULL;
9465   GtkWidget *action_area, *content_area;
9466   GtkWidget *button;
9467   GtkWidget *frame;
9468   GtkWidget *vbox;
9469   GtkWidget *label;
9470
9471   if (!window)
9472     {
9473       window = gtk_dialog_new ();
9474
9475       gtk_window_set_screen (GTK_WINDOW (window),
9476                              gtk_widget_get_screen (widget));
9477
9478       g_signal_connect (window, "destroy",
9479                         G_CALLBACK (gtk_widget_destroyed),
9480                         &window);
9481
9482       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9483       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9484
9485       frame = gtk_aspect_frame_new ("Testing RC file prioritization", 0.5, 0.5, 0.0, TRUE);
9486       gtk_box_pack_start (GTK_BOX (content_area), frame, FALSE, FALSE, 0);
9487
9488       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
9489       gtk_container_add (GTK_CONTAINER (frame), vbox);
9490       
9491       label = gtk_label_new ("This label should be red");
9492       gtk_widget_set_name (label, "testgtk-red-label");
9493       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9494
9495       label = gtk_label_new ("This label should be green");
9496       gtk_widget_set_name (label, "testgtk-green-label");
9497       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9498
9499       label = gtk_label_new ("This label should be blue");
9500       gtk_widget_set_name (label, "testgtk-blue-label");
9501       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9502
9503       gtk_window_set_title (GTK_WINDOW (window), "Reload Rc file");
9504       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9505
9506       button = gtk_button_new_with_label ("Reload");
9507       g_signal_connect_swapped (button, "clicked",
9508                                 G_CALLBACK (gtk_style_context_reset_widgets),
9509                                 gtk_widget_get_screen (button));
9510       gtk_widget_set_can_default (button, TRUE);
9511       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9512       gtk_widget_grab_default (button);
9513
9514       button = gtk_button_new_with_label ("Close");
9515       g_signal_connect_swapped (button, "clicked",
9516                                 G_CALLBACK (gtk_widget_destroy),
9517                                 window);
9518       gtk_widget_set_can_default (button, TRUE);
9519       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9520     }
9521
9522   if (!gtk_widget_get_visible (window))
9523     gtk_widget_show_all (window);
9524   else
9525     gtk_widget_destroy (window);
9526 }
9527
9528 /*
9529  * Test of recursive mainloop
9530  */
9531
9532 void
9533 mainloop_destroyed (GtkWidget *w, GtkWidget **window)
9534 {
9535   *window = NULL;
9536   gtk_main_quit ();
9537 }
9538
9539 void
9540 create_mainloop (GtkWidget *widget)
9541 {
9542   static GtkWidget *window = NULL;
9543   GtkWidget *action_area, *content_area;
9544   GtkWidget *label;
9545   GtkWidget *button;
9546
9547   if (!window)
9548     {
9549       window = gtk_dialog_new ();
9550
9551       gtk_window_set_screen (GTK_WINDOW (window),
9552                              gtk_widget_get_screen (widget));
9553
9554       gtk_window_set_title (GTK_WINDOW (window), "Test Main Loop");
9555
9556       g_signal_connect (window, "destroy",
9557                         G_CALLBACK (mainloop_destroyed),
9558                         &window);
9559
9560       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9561       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9562
9563       label = gtk_label_new ("In recursive main loop...");
9564       g_object_set (label, "margin", 20, NULL);
9565
9566       gtk_box_pack_start (GTK_BOX (content_area), label, TRUE, TRUE, 0);
9567       gtk_widget_show (label);
9568
9569       button = gtk_button_new_with_label ("Leave");
9570       gtk_box_pack_start (GTK_BOX (action_area), button, FALSE, TRUE, 0);
9571
9572       g_signal_connect_swapped (button, "clicked",
9573                                 G_CALLBACK (gtk_widget_destroy),
9574                                 window);
9575
9576       gtk_widget_set_can_default (button, TRUE);
9577       gtk_widget_grab_default (button);
9578
9579       gtk_widget_show (button);
9580     }
9581
9582   if (!gtk_widget_get_visible (window))
9583     {
9584       gtk_widget_show (window);
9585
9586       g_print ("create_mainloop: start\n");
9587       gtk_main ();
9588       g_print ("create_mainloop: done\n");
9589     }
9590   else
9591     gtk_widget_destroy (window);
9592 }
9593
9594 static gboolean
9595 layout_draw_handler (GtkWidget *widget, cairo_t *cr)
9596 {
9597   GtkLayout *layout;
9598   GdkWindow *bin_window;
9599   GdkRectangle clip;
9600   gint i,j,x,y;
9601   gint imin, imax, jmin, jmax;
9602
9603   layout = GTK_LAYOUT (widget);
9604   bin_window = gtk_layout_get_bin_window (layout);
9605
9606   if (!gtk_cairo_should_draw_window (cr, bin_window))
9607     return FALSE;
9608   
9609   gdk_window_get_position (bin_window, &x, &y);
9610   cairo_translate (cr, x, y);
9611
9612   gdk_cairo_get_clip_rectangle (cr, &clip);
9613
9614   imin = (clip.x) / 10;
9615   imax = (clip.x + clip.width + 9) / 10;
9616
9617   jmin = (clip.y) / 10;
9618   jmax = (clip.y + clip.height + 9) / 10;
9619
9620   for (i=imin; i<imax; i++)
9621     for (j=jmin; j<jmax; j++)
9622       if ((i+j) % 2)
9623         cairo_rectangle (cr,
9624                          10*i, 10*j, 
9625                          1+i%10, 1+j%10);
9626   
9627   cairo_fill (cr);
9628
9629   return FALSE;
9630 }
9631
9632 void create_layout (GtkWidget *widget)
9633 {
9634   GtkAdjustment *hadjustment, *vadjustment;
9635   GtkLayout *layout;
9636   static GtkWidget *window = NULL;
9637   GtkWidget *layout_widget;
9638   GtkWidget *scrolledwindow;
9639   GtkWidget *button;
9640
9641   if (!window)
9642     {
9643       gchar buf[16];
9644
9645       gint i, j;
9646       
9647       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9648       gtk_window_set_screen (GTK_WINDOW (window),
9649                              gtk_widget_get_screen (widget));
9650
9651       g_signal_connect (window, "destroy",
9652                         G_CALLBACK (gtk_widget_destroyed),
9653                         &window);
9654
9655       gtk_window_set_title (GTK_WINDOW (window), "Layout");
9656       gtk_widget_set_size_request (window, 200, 200);
9657
9658       scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
9659       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
9660                                            GTK_SHADOW_IN);
9661       gtk_scrolled_window_set_placement (GTK_SCROLLED_WINDOW (scrolledwindow),
9662                                          GTK_CORNER_TOP_RIGHT);
9663
9664       gtk_container_add (GTK_CONTAINER (window), scrolledwindow);
9665
9666       layout_widget = gtk_layout_new (NULL, NULL);
9667       layout = GTK_LAYOUT (layout_widget);
9668       gtk_container_add (GTK_CONTAINER (scrolledwindow), layout_widget);
9669
9670       /* We set step sizes here since GtkLayout does not set
9671        * them itself.
9672        */
9673       hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (layout));
9674       vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (layout));
9675       gtk_adjustment_set_step_increment (hadjustment, 10.0);
9676       gtk_adjustment_set_step_increment (vadjustment, 10.0);
9677       gtk_scrollable_set_hadjustment (GTK_SCROLLABLE (layout), hadjustment);
9678       gtk_scrollable_set_vadjustment (GTK_SCROLLABLE (layout), vadjustment);
9679
9680       gtk_widget_set_events (layout_widget, GDK_EXPOSURE_MASK);
9681       g_signal_connect (layout, "draw",
9682                         G_CALLBACK (layout_draw_handler), NULL);
9683
9684       gtk_layout_set_size (layout, 1600, 128000);
9685
9686       for (i=0 ; i < 16 ; i++)
9687         for (j=0 ; j < 16 ; j++)
9688           {
9689             sprintf(buf, "Button %d, %d", i, j);
9690             if ((i + j) % 2)
9691               button = gtk_button_new_with_label (buf);
9692             else
9693               button = gtk_label_new (buf);
9694
9695             gtk_layout_put (layout, button, j*100, i*100);
9696           }
9697
9698       for (i=16; i < 1280; i++)
9699         {
9700           sprintf(buf, "Button %d, %d", i, 0);
9701           if (i % 2)
9702             button = gtk_button_new_with_label (buf);
9703           else
9704             button = gtk_label_new (buf);
9705
9706           gtk_layout_put (layout, button, 0, i*100);
9707         }
9708     }
9709
9710   if (!gtk_widget_get_visible (window))
9711     gtk_widget_show_all (window);
9712   else
9713     gtk_widget_destroy (window);
9714 }
9715
9716 #if 0
9717 /* FIXME: need to completely redo this for GtkStyleContext */
9718 void
9719 create_styles (GtkWidget *widget)
9720 {
9721   static GtkWidget *window = NULL;
9722   GtkWidget *content_area, *action_area;
9723   GtkWidget *label;
9724   GtkWidget *button;
9725   GtkWidget *entry;
9726   GtkWidget *vbox;
9727   static GdkRGBA red =    { 1,0,0,1 };
9728   static GdkRGBA green =  { 0,1,0,1 };
9729   static GdkRGBA blue =   { 0,0,1,1 };
9730   static GdkRGBA yellow = { 1,1,0,1 };
9731   static GdkRGBA cyan =   { 0,1,1,1 };
9732   PangoFontDescription *font_desc;
9733
9734   GtkRcStyle *rc_style;
9735
9736   if (!window)
9737     {
9738       window = gtk_dialog_new ();
9739       gtk_window_set_screen (GTK_WINDOW (window),
9740                              gtk_widget_get_screen (widget));
9741      
9742       g_signal_connect (window, "destroy",
9743                         G_CALLBACK (gtk_widget_destroyed),
9744                         &window);
9745
9746       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9747       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9748
9749       button = gtk_button_new_with_label ("Close");
9750       g_signal_connect_swapped (button, "clicked",
9751                                 G_CALLBACK (gtk_widget_destroy),
9752                                 window);
9753       gtk_widget_set_can_default (button, TRUE);
9754       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9755       gtk_widget_show (button);
9756
9757       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
9758       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
9759       gtk_box_pack_start (GTK_BOX (content_area), vbox, FALSE, FALSE, 0);
9760       
9761       label = gtk_label_new ("Font:");
9762       gtk_widget_set_halign (label, GTK_ALIGN_START);
9763       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9764       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9765
9766       font_desc = pango_font_description_from_string ("Helvetica,Sans Oblique 18");
9767
9768       button = gtk_button_new_with_label ("Some Text");
9769       gtk_widget_override_font (gtk_bin_get_child (GTK_BIN (button)), font_desc);
9770       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9771
9772       label = gtk_label_new ("Foreground:");
9773       gtk_widget_set_halign (label, GTK_ALIGN_START);
9774       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9775       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9776
9777       button = gtk_button_new_with_label ("Some Text");
9778       gtk_widget_override_color (gtk_bin_get_child (GTK_BIN (button)), 0, &red);
9779       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9780
9781       label = gtk_label_new ("Background:");
9782       gtk_widget_set_halign (label, GTK_ALIGN_START);
9783       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9784       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9785
9786       button = gtk_button_new_with_label ("Some Text");
9787       gtk_widget_override_background_color (button, 0, &green);
9788       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9789
9790       label = gtk_label_new ("Text:");
9791       gtk_widget_set_halign (label, GTK_ALIGN_START);
9792       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9793       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9794
9795       entry = gtk_entry_new ();
9796       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
9797       gtk_widget_override_color (entry, 0, &blue);
9798       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
9799
9800       label = gtk_label_new ("Base:");
9801       gtk_widget_set_halign (label, GTK_ALIGN_START);
9802       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9803       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9804
9805       entry = gtk_entry_new ();
9806       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
9807       gtk_widget_override_background_color (entry, 0, &yellow);
9808       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
9809
9810       label = gtk_label_new ("Cursor:");
9811       gtk_widget_set_halign (label, GTK_ALIGN_START);
9812       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9813       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9814
9815       entry = gtk_entry_new ();
9816       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
9817       gtk_widget_modify_cursor (entry, &red, &red);
9818       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
9819
9820       label = gtk_label_new ("Multiple:");
9821       gtk_widget_set_halign (label, GTK_ALIGN_START);
9822       gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
9823       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9824
9825       button = gtk_button_new_with_label ("Some Text");
9826
9827       rc_style = gtk_rc_style_new ();
9828
9829       rc_style->font_desc = pango_font_description_copy (font_desc);
9830       rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG | GTK_RC_BG;
9831       rc_style->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_FG | GTK_RC_BG;
9832       rc_style->color_flags[GTK_STATE_ACTIVE] = GTK_RC_FG | GTK_RC_BG;
9833       rc_style->fg[GTK_STATE_NORMAL] = yellow;
9834       rc_style->bg[GTK_STATE_NORMAL] = blue;
9835       rc_style->fg[GTK_STATE_PRELIGHT] = blue;
9836       rc_style->bg[GTK_STATE_PRELIGHT] = yellow;
9837       rc_style->fg[GTK_STATE_ACTIVE] = red;
9838       rc_style->bg[GTK_STATE_ACTIVE] = cyan;
9839       rc_style->xthickness = 5;
9840       rc_style->ythickness = 5;
9841
9842       gtk_widget_modify_style (button, rc_style);
9843       gtk_widget_modify_style (gtk_bin_get_child (GTK_BIN (button)), rc_style);
9844
9845       g_object_unref (rc_style);
9846       
9847       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9848     }
9849   
9850   if (!gtk_widget_get_visible (window))
9851     gtk_widget_show_all (window);
9852   else
9853     gtk_widget_destroy (window);
9854 }
9855 #endif
9856
9857 /*
9858  * Main Window and Exit
9859  */
9860
9861 void
9862 do_exit (GtkWidget *widget, GtkWidget *window)
9863 {
9864   gtk_widget_destroy (window);
9865   gtk_main_quit ();
9866 }
9867
9868 struct {
9869   char *label;
9870   void (*func) (GtkWidget *widget);
9871   gboolean do_not_benchmark;
9872 } buttons[] =
9873 {
9874   { "alpha window", create_alpha_window },
9875   { "big windows", create_big_windows },
9876   { "button box", create_button_box },
9877   { "buttons", create_buttons },
9878   { "check buttons", create_check_buttons },
9879   { "color selection", create_color_selection },
9880   { "composited window", create_composited_window },
9881   { "cursors", create_cursors },
9882   { "dialog", create_dialog },
9883   { "display & screen", create_display_screen, TRUE },
9884   { "entry", create_entry },
9885   { "event box", create_event_box },
9886   { "event watcher", create_event_watcher },
9887   { "expander", create_expander },
9888   { "flipping", create_flipping },
9889   { "focus", create_focus },
9890   { "font selection", create_font_selection },
9891   { "handle box", create_handle_box },
9892   { "image", create_image },
9893   { "key lookup", create_key_lookup },
9894   { "labels", create_labels },
9895   { "layout", create_layout },
9896   { "menus", create_menus },
9897   { "message dialog", create_message_dialog },
9898   { "modal window", create_modal_window, TRUE },
9899   { "notebook", create_notebook },
9900   { "panes", create_panes },
9901   { "paned keyboard", create_paned_keyboard_navigation },
9902   { "pixbuf", create_pixbuf },
9903   { "progress bar", create_progress_bar },
9904   { "properties", create_properties },
9905   { "radio buttons", create_radio_buttons },
9906   { "range controls", create_range_controls },
9907   { "rc file", create_rc_file },
9908   { "reparent", create_reparent },
9909   { "resize grips", create_resize_grips },
9910   { "rotated label", create_rotated_label },
9911   { "rotated text", create_rotated_text },
9912   { "saved position", create_saved_position },
9913   { "scrolled windows", create_scrolled_windows },
9914   { "shapes", create_shapes },
9915   { "size groups", create_size_groups },
9916   { "snapshot", create_snapshot },
9917   { "spinbutton", create_spins },
9918   { "statusbar", create_statusbar },
9919 #if 0
9920   { "styles", create_styles },
9921 #endif
9922   { "test idle", create_idle_test },
9923   { "test mainloop", create_mainloop, TRUE },
9924   { "test scrolling", create_scroll_test },
9925   { "test selection", create_selection_test },
9926   { "test timeout", create_timeout_test },
9927   { "toggle buttons", create_toggle_buttons },
9928   { "toolbar", create_toolbar },
9929   { "tooltips", create_tooltips },
9930   { "WM hints", create_wmhints },
9931   { "window sizing", create_window_sizing },
9932   { "window states", create_window_states }
9933 };
9934 int nbuttons = sizeof (buttons) / sizeof (buttons[0]);
9935
9936 void
9937 create_main_window (void)
9938 {
9939   GtkWidget *window;
9940   GtkWidget *box1;
9941   GtkWidget *box2;
9942   GtkWidget *scrolled_window;
9943   GtkWidget *button;
9944   GtkWidget *label;
9945   gchar buffer[64];
9946   GtkWidget *separator;
9947   GdkGeometry geometry;
9948   int i;
9949
9950   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9951   gtk_widget_set_name (window, "main_window");
9952   gtk_window_move (GTK_WINDOW (window), 50, 20);
9953   gtk_window_set_default_size (GTK_WINDOW (window), -1, 400);
9954
9955   geometry.min_width = -1;
9956   geometry.min_height = -1;
9957   geometry.max_width = -1;
9958   geometry.max_height = G_MAXSHORT;
9959   gtk_window_set_geometry_hints (GTK_WINDOW (window), NULL,
9960                                  &geometry,
9961                                  GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
9962
9963   g_signal_connect (window, "destroy",
9964                     G_CALLBACK (gtk_main_quit),
9965                     NULL);
9966   g_signal_connect (window, "delete-event",
9967                     G_CALLBACK (gtk_false),
9968                     NULL);
9969
9970   box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
9971   gtk_container_add (GTK_CONTAINER (window), box1);
9972
9973   if (gtk_micro_version > 0)
9974     sprintf (buffer,
9975              "Gtk+ v%d.%d.%d",
9976              gtk_get_major_version (),
9977              gtk_get_minor_version (),
9978              gtk_get_micro_version ());
9979   else
9980     sprintf (buffer,
9981              "Gtk+ v%d.%d",
9982              gtk_get_major_version (),
9983              gtk_get_minor_version ());
9984
9985   label = gtk_label_new (buffer);
9986   gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
9987   gtk_widget_set_name (label, "testgtk-version-label");
9988
9989   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
9990   gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
9991   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
9992                                   GTK_POLICY_NEVER, 
9993                                   GTK_POLICY_AUTOMATIC);
9994   gtk_box_pack_start (GTK_BOX (box1), scrolled_window, TRUE, TRUE, 0);
9995
9996   box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
9997   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9998   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), box2);
9999   gtk_container_set_focus_vadjustment (GTK_CONTAINER (box2),
10000                                        gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
10001   gtk_widget_show (box2);
10002
10003   for (i = 0; i < nbuttons; i++)
10004     {
10005       button = gtk_button_new_with_label (buttons[i].label);
10006       if (buttons[i].func)
10007         g_signal_connect (button, 
10008                           "clicked", 
10009                           G_CALLBACK(buttons[i].func),
10010                           NULL);
10011       else
10012         gtk_widget_set_sensitive (button, FALSE);
10013       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10014     }
10015
10016   separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
10017   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
10018
10019   box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
10020   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10021   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
10022
10023   button = gtk_button_new_with_mnemonic ("_Close");
10024   g_signal_connect (button, "clicked",
10025                     G_CALLBACK (do_exit),
10026                     window);
10027   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10028   gtk_widget_set_can_default (button, TRUE);
10029   gtk_widget_grab_default (button);
10030
10031   gtk_widget_show_all (window);
10032 }
10033
10034 static void
10035 test_init (void)
10036 {
10037   if (g_file_test ("../modules/input/immodules.cache", G_FILE_TEST_EXISTS))
10038     g_setenv ("GTK_IM_MODULE_FILE", "../modules/input/immodules.cache", TRUE);
10039 }
10040
10041 static char *
10042 pad (const char *str, int to)
10043 {
10044   static char buf[256];
10045   int len = strlen (str);
10046   int i;
10047
10048   for (i = 0; i < to; i++)
10049     buf[i] = ' ';
10050
10051   buf[to] = '\0';
10052
10053   memcpy (buf, str, len);
10054
10055   return buf;
10056 }
10057
10058 static void
10059 bench_iteration (GtkWidget *widget, void (* fn) (GtkWidget *widget))
10060 {
10061   fn (widget); /* on */
10062   while (g_main_context_iteration (NULL, FALSE));
10063   fn (widget); /* off */
10064   while (g_main_context_iteration (NULL, FALSE));
10065 }
10066
10067 void
10068 do_real_bench (GtkWidget *widget, void (* fn) (GtkWidget *widget), char *name, int num)
10069 {
10070   GTimeVal tv0, tv1;
10071   double dt_first;
10072   double dt;
10073   int n;
10074   static gboolean printed_headers = FALSE;
10075
10076   if (!printed_headers) {
10077     g_print ("Test                 Iters      First      Other\n");
10078     g_print ("-------------------- ----- ---------- ----------\n");
10079     printed_headers = TRUE;
10080   }
10081
10082   g_get_current_time (&tv0);
10083   bench_iteration (widget, fn); 
10084   g_get_current_time (&tv1);
10085
10086   dt_first = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
10087         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
10088
10089   g_get_current_time (&tv0);
10090   for (n = 0; n < num - 1; n++)
10091     bench_iteration (widget, fn); 
10092   g_get_current_time (&tv1);
10093   dt = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
10094         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
10095
10096   g_print ("%s %5d ", pad (name, 20), num);
10097   if (num > 1)
10098     g_print ("%10.1f %10.1f\n", dt_first, dt/(num-1));
10099   else
10100     g_print ("%10.1f\n", dt_first);
10101 }
10102
10103 void
10104 do_bench (char* what, int num)
10105 {
10106   int i;
10107   GtkWidget *widget;
10108   void (* fn) (GtkWidget *widget);
10109   fn = NULL;
10110   widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10111
10112   if (g_ascii_strcasecmp (what, "ALL") == 0)
10113     {
10114       for (i = 0; i < nbuttons; i++)
10115         {
10116           if (!buttons[i].do_not_benchmark)
10117             do_real_bench (widget, buttons[i].func, buttons[i].label, num);
10118         }
10119
10120       return;
10121     }
10122   else
10123     {
10124       for (i = 0; i < nbuttons; i++)
10125         {
10126           if (strcmp (buttons[i].label, what) == 0)
10127             {
10128               fn = buttons[i].func;
10129               break;
10130             }
10131         }
10132       
10133       if (!fn)
10134         g_print ("Can't bench: \"%s\" not found.\n", what);
10135       else
10136         do_real_bench (widget, fn, buttons[i].label, num);
10137     }
10138 }
10139
10140 void 
10141 usage (void)
10142 {
10143   fprintf (stderr, "Usage: testgtk [--bench ALL|<bench>[:<count>]]\n");
10144   exit (1);
10145 }
10146
10147 int
10148 main (int argc, char *argv[])
10149 {
10150   GtkCssProvider *provider, *memory_provider;
10151   GdkDisplay *display;
10152   GdkScreen *screen;
10153   GtkBindingSet *binding_set;
10154   int i;
10155   gboolean done_benchmarks = FALSE;
10156
10157   srand (time (NULL));
10158
10159   test_init ();
10160
10161   g_set_application_name ("GTK+ Test Program");
10162
10163   gtk_init (&argc, &argv);
10164
10165   provider = gtk_css_provider_new ();
10166
10167   /* Check to see if we are being run from the correct
10168    * directory.
10169    */
10170   if (file_exists ("testgtk.css"))
10171     gtk_css_provider_load_from_path (provider, "testgtk.css", NULL);
10172   else if (file_exists ("tests/testgtk.css"))
10173     gtk_css_provider_load_from_path (provider, "tests/testgtk.css", NULL);
10174   else
10175     g_warning ("Couldn't find file \"testgtk.css\".");
10176
10177   display = gdk_display_get_default ();
10178   screen = gdk_display_get_default_screen (display);
10179
10180   gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER (provider),
10181                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
10182   g_object_unref (provider);
10183
10184   gtk_accelerator_set_default_mod_mask (GDK_SHIFT_MASK |
10185                                         GDK_CONTROL_MASK |
10186                                         GDK_MOD1_MASK | 
10187                                         GDK_META_MASK |
10188                                         GDK_SUPER_MASK |
10189                                         GDK_HYPER_MASK |
10190                                         GDK_MOD4_MASK);
10191   /*  benchmarking
10192    */
10193   for (i = 1; i < argc; i++)
10194     {
10195       if (strncmp (argv[i], "--bench", strlen("--bench")) == 0)
10196         {
10197           int num = 1;
10198           char *nextarg;
10199           char *what;
10200           char *count;
10201           
10202           nextarg = strchr (argv[i], '=');
10203           if (nextarg)
10204             nextarg++;
10205           else
10206             {
10207               i++;
10208               if (i == argc)
10209                 usage ();
10210               nextarg = argv[i];
10211             }
10212
10213           count = strchr (nextarg, ':');
10214           if (count)
10215             {
10216               what = g_strndup (nextarg, count - nextarg);
10217               count++;
10218               num = atoi (count);
10219               if (num <= 0)
10220                 usage ();
10221             }
10222           else
10223             what = g_strdup (nextarg);
10224
10225           do_bench (what, num ? num : 1);
10226           done_benchmarks = TRUE;
10227         }
10228       else
10229         usage ();
10230     }
10231   if (done_benchmarks)
10232     return 0;
10233
10234   /* bindings test
10235    */
10236   binding_set = gtk_binding_set_by_class (g_type_class_ref (GTK_TYPE_WIDGET));
10237   gtk_binding_entry_add_signal (binding_set,
10238                                 '9', GDK_CONTROL_MASK | GDK_RELEASE_MASK,
10239                                 "debug_msg",
10240                                 1,
10241                                 G_TYPE_STRING, "GtkWidgetClass <ctrl><release>9 test");
10242
10243   memory_provider = gtk_css_provider_new ();
10244   gtk_css_provider_load_from_data (memory_provider,
10245                                    "#testgtk-version-label {\n"
10246                                    "  color: #f00;\n"
10247                                    "  font: Sans 18;\n"
10248                                    "}",
10249                                    -1, NULL);
10250   gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER (memory_provider),
10251                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + 1);
10252
10253   create_main_window ();
10254
10255   gtk_main ();
10256
10257   if (1)
10258     {
10259       while (g_main_context_pending (NULL))
10260         g_main_context_iteration (NULL, FALSE);
10261 #if 0
10262       sleep (1);
10263       while (g_main_context_pending (NULL))
10264         g_main_context_iteration (NULL, FALSE);
10265 #endif
10266     }
10267   return 0;
10268 }