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