]> Pileus Git - ~andy/gtk/blob - tests/testwindows.c
gtk: remove "gboolean homogeneous" from gtk_box_new()
[~andy/gtk] / tests / testwindows.c
1 #include <gtk/gtk.h>
2 #ifdef GDK_WINDOWING_X11
3 #include <X11/Xlib.h>
4 #endif
5
6 static GtkWidget *darea;
7 static GtkTreeStore *window_store = NULL;
8 static GtkWidget *treeview;
9
10 static void update_store (void);
11
12 static GtkWidget *main_window;
13
14
15 GdkWindow *
16 create_window (GdkWindow *parent,
17                int x, int y, int w, int h,
18                GdkColor *color)
19 {
20   GdkWindowAttr attributes;
21   gint attributes_mask;
22   GdkWindow *window;
23   GdkColor *bg;
24
25   attributes.x = x;
26   attributes.y = y;
27   attributes.width = w;
28   attributes.height = h;
29   attributes.window_type = GDK_WINDOW_CHILD;
30   attributes.event_mask = GDK_STRUCTURE_MASK
31                         | GDK_BUTTON_MOTION_MASK
32                         | GDK_BUTTON_PRESS_MASK
33                         | GDK_BUTTON_RELEASE_MASK
34                         | GDK_EXPOSURE_MASK
35                         | GDK_ENTER_NOTIFY_MASK
36                         | GDK_LEAVE_NOTIFY_MASK;
37   attributes.wclass = GDK_INPUT_OUTPUT;
38       
39   attributes_mask = GDK_WA_X | GDK_WA_Y;
40       
41   window = gdk_window_new (parent, &attributes, attributes_mask);
42   gdk_window_set_user_data (window, darea);
43
44   bg = g_new (GdkColor, 1);
45   if (color)
46     *bg = *color;
47   else
48     {
49       bg->red = g_random_int_range (0, 0xffff);
50       bg->blue = g_random_int_range (0, 0xffff);
51       bg->green = g_random_int_range (0, 0xffff);;
52     }
53   
54   gdk_window_set_background (window, bg);
55   g_object_set_data_full (G_OBJECT (window), "color", bg, g_free);
56   
57   gdk_window_show (window);
58   
59   return window;
60 }
61
62 static void
63 add_window_cb (GtkTreeModel      *model,
64                GtkTreePath       *path,
65                GtkTreeIter       *iter,
66                gpointer           data)
67 {
68   GList **selected = data;
69   GdkWindow *window;
70
71   gtk_tree_model_get (GTK_TREE_MODEL (window_store),
72                       iter,
73                       0, &window,
74                       -1);
75
76   *selected = g_list_prepend (*selected, window);
77 }
78
79 static GList *
80 get_selected_windows (void)
81 {
82   GtkTreeSelection *sel;
83   GList *selected;
84
85   sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
86
87   selected = NULL;
88   gtk_tree_selection_selected_foreach (sel, add_window_cb, &selected);
89   
90   return selected;
91 }
92
93 static gboolean
94 find_window_helper (GtkTreeModel *model,
95                     GdkWindow *window,
96                     GtkTreeIter *iter,
97                     GtkTreeIter *selected_iter)
98 {
99   GtkTreeIter child_iter;
100   GdkWindow *w;
101
102   do
103     {
104       gtk_tree_model_get (model, iter,
105                           0, &w,
106                           -1);
107       if (w == window)
108         {
109           *selected_iter = *iter;
110           return TRUE;
111         }
112       
113       if (gtk_tree_model_iter_children (model,
114                                         &child_iter,
115                                         iter))
116         {
117           if (find_window_helper (model, window, &child_iter, selected_iter))
118             return TRUE;
119         }
120     } while (gtk_tree_model_iter_next (model, iter));
121
122   return FALSE;
123 }
124
125 static gboolean
126 find_window (GdkWindow *window,
127              GtkTreeIter *window_iter)
128 {
129   GtkTreeIter iter;
130
131   if (!gtk_tree_model_get_iter_first  (GTK_TREE_MODEL (window_store), &iter))
132     return FALSE;
133
134   return find_window_helper (GTK_TREE_MODEL (window_store),
135                              window,
136                              &iter,
137                              window_iter);
138 }
139
140 static void
141 toggle_selection_window (GdkWindow *window)
142 {
143   GtkTreeSelection *selection;
144   GtkTreeIter iter;
145
146   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
147
148   if (window != NULL &&
149       find_window (window, &iter))
150     {
151       if (gtk_tree_selection_iter_is_selected (selection, &iter))
152         gtk_tree_selection_unselect_iter (selection,  &iter);
153       else
154         gtk_tree_selection_select_iter (selection,  &iter);
155     }
156 }
157
158 static void
159 unselect_windows (void)
160 {
161   GtkTreeSelection *selection;
162
163   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
164   
165   gtk_tree_selection_unselect_all (selection);
166 }
167
168
169 static void
170 select_window (GdkWindow *window)
171 {
172   GtkTreeSelection *selection;
173   GtkTreeIter iter;
174
175   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
176
177   if (window != NULL &&
178       find_window (window, &iter))
179     gtk_tree_selection_select_iter (selection,  &iter);
180 }
181
182 static void
183 select_windows (GList *windows)
184 {
185   GtkTreeSelection *selection;
186   GtkTreeIter iter;
187   GList *l;
188
189   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
190   gtk_tree_selection_unselect_all (selection);
191   
192   for (l = windows; l != NULL; l = l->next)
193     {
194       if (find_window (l->data, &iter))
195         gtk_tree_selection_select_iter (selection,  &iter);
196     }
197 }
198
199 static void
200 add_window_clicked (GtkWidget *button, 
201                     gpointer data)
202 {
203   GdkWindow *parent;
204   GList *l;
205
206   l = get_selected_windows ();
207   if (l != NULL)
208     parent = l->data;
209   else
210     parent = gtk_widget_get_window (darea);
211
212   g_list_free (l);
213   
214   create_window (parent, 10, 10, 100, 100, NULL);
215   update_store ();
216 }
217
218 static void
219 remove_window_clicked (GtkWidget *button, 
220                        gpointer data)
221 {
222   GList *l, *selected;
223
224   selected = get_selected_windows ();
225
226   for (l = selected; l != NULL; l = l->next)
227     gdk_window_destroy (l->data);
228
229   g_list_free (selected);
230
231   update_store ();
232 }
233
234 static void save_children (GString *s, GdkWindow *window);
235
236 static void
237 save_window (GString *s,
238              GdkWindow *window)
239 {
240   gint x, y;
241   GdkColor *color;
242
243   gdk_window_get_position (window, &x, &y);
244   color = g_object_get_data (G_OBJECT (window), "color");
245   
246   g_string_append_printf (s, "%d,%d %dx%d (%d,%d,%d) %d %d\n",
247                           x, y,
248                           gdk_window_get_width (window),
249                           gdk_window_get_height (window),
250                           color->red, color->green, color->blue,
251                           gdk_window_has_native (window),
252                           g_list_length (gdk_window_peek_children (window)));
253
254   save_children (s, window);
255 }
256
257
258 static void
259 save_children (GString *s,
260                GdkWindow *window)
261 {
262   GList *l;
263   GdkWindow *child;
264
265   for (l = g_list_reverse (gdk_window_peek_children (window));
266        l != NULL;
267        l = l->next)
268     {
269       child = l->data;
270
271       save_window (s, child);
272     }
273 }
274
275
276 static void
277 save_clicked (GtkWidget *button, 
278               gpointer data)
279 {
280   GString *s;
281   GtkWidget *dialog;
282   GFile *file;
283
284   s = g_string_new ("");
285
286   save_children (s, gtk_widget_get_window (darea));
287
288   dialog = gtk_file_chooser_dialog_new ("Filename for window data",
289                                         NULL,
290                                         GTK_FILE_CHOOSER_ACTION_SAVE,
291                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
292                                         GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
293                                         NULL);
294   
295   gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
296   
297   if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
298     {
299       file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
300
301       g_file_replace_contents (file,
302                                s->str, s->len,
303                                NULL, FALSE,
304                                0, NULL, NULL, NULL);
305
306       g_object_unref (file);
307     }
308
309   gtk_widget_destroy (dialog);
310   g_string_free (s, TRUE);
311 }
312
313 static void
314 destroy_children (GdkWindow *window)
315 {
316   GList *l;
317   GdkWindow *child;
318
319   for (l = gdk_window_peek_children (window);
320        l != NULL;
321        l = l->next)
322     {
323       child = l->data;
324       
325       destroy_children (child);
326       gdk_window_destroy (child);
327     }
328 }
329
330 static char **
331 parse_window (GdkWindow *parent, char **lines)
332 {
333   int x, y, w, h, r, g, b, native, n_children;
334   GdkWindow *window;
335   GdkColor color;
336   int i;
337
338   if (*lines == NULL)
339     return lines;
340   
341   if (sscanf(*lines, "%d,%d %dx%d (%d,%d,%d) %d %d",
342              &x, &y, &w, &h, &r, &g, &b, &native, &n_children) == 9)
343     {
344       lines++;
345       color.red = r;
346       color.green = g;
347       color.blue = b;
348       window = create_window (parent, x, y, w, h, &color);
349       if (native)
350         gdk_window_ensure_native (window);
351       
352       for (i = 0; i < n_children; i++)
353         lines = parse_window (window, lines);
354     }
355   else
356     lines++;
357   
358   return lines;
359 }
360   
361 static void
362 load_file (GFile *file)
363 {
364   GdkWindow *window;
365   char *data;
366   char **lines, **l;
367   
368   if (g_file_load_contents (file, NULL, &data, NULL, NULL, NULL))
369     {
370       window = gtk_widget_get_window (darea);
371
372       destroy_children (window);
373
374       lines = g_strsplit (data, "\n", -1);
375
376       l = lines;
377       while (*l != NULL)
378         l = parse_window (window, l);
379     }
380
381   update_store ();
382 }
383
384 static void
385 move_window_clicked (GtkWidget *button, 
386                      gpointer data)
387 {
388   GdkWindow *window;
389   GtkDirectionType direction;
390   GList *selected, *l;
391   gint x, y;
392
393   direction = GPOINTER_TO_INT (data);
394     
395   selected = get_selected_windows ();
396
397   for (l = selected; l != NULL; l = l->next)
398     {
399       window = l->data;
400       
401       gdk_window_get_position (window, &x, &y);
402       
403       switch (direction) {
404       case GTK_DIR_UP:
405         y -= 10;
406         break;
407       case GTK_DIR_DOWN:
408         y += 10;
409         break;
410       case GTK_DIR_LEFT:
411         x -= 10;
412         break;
413       case GTK_DIR_RIGHT:
414         x += 10;
415         break;
416       default:
417         break;
418       }
419
420       gdk_window_move (window, x, y);
421     }
422
423   g_list_free (selected);
424 }
425
426 static void
427 manual_clicked (GtkWidget *button, 
428                 gpointer data)
429 {
430   GdkWindow *window;
431   GList *selected, *l;
432   int x, y, w, h;
433   GtkWidget *dialog, *table, *label, *xspin, *yspin, *wspin, *hspin;
434   
435
436   selected = get_selected_windows ();
437
438   if (selected == NULL)
439     return;
440
441   gdk_window_get_position (selected->data, &x, &y);
442   w = gdk_window_get_width (selected->data);
443   h = gdk_window_get_height (selected->data);
444
445   dialog = gtk_dialog_new_with_buttons ("Select new position and size",
446                                         GTK_WINDOW (main_window),
447                                         GTK_DIALOG_MODAL,
448                                         GTK_STOCK_OK, GTK_RESPONSE_OK,
449                                         NULL);
450   
451
452   table = gtk_table_new (2, 4, TRUE);
453   gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
454                       table,
455                       FALSE, FALSE,
456                       2);
457
458   
459   label = gtk_label_new ("x:");
460   gtk_table_attach_defaults (GTK_TABLE (table),
461                              label,
462                              0, 1,
463                              0, 1);
464   label = gtk_label_new ("y:");
465   gtk_table_attach_defaults (GTK_TABLE (table),
466                              label,
467                              0, 1,
468                              1, 2);
469   label = gtk_label_new ("width:");
470   gtk_table_attach_defaults (GTK_TABLE (table),
471                              label,
472                              0, 1,
473                              2, 3);
474   label = gtk_label_new ("height:");
475   gtk_table_attach_defaults (GTK_TABLE (table),
476                              label,
477                              0, 1,
478                              3, 4);
479
480   xspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
481   gtk_spin_button_set_value (GTK_SPIN_BUTTON (xspin), x);
482   gtk_table_attach_defaults (GTK_TABLE (table),
483                              xspin,
484                              1, 2,
485                              0, 1);
486   yspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
487   gtk_spin_button_set_value (GTK_SPIN_BUTTON (yspin), y);
488   gtk_table_attach_defaults (GTK_TABLE (table),
489                              yspin,
490                              1, 2,
491                              1, 2);
492   wspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
493   gtk_spin_button_set_value (GTK_SPIN_BUTTON (wspin), w);
494   gtk_table_attach_defaults (GTK_TABLE (table),
495                              wspin,
496                              1, 2,
497                              2, 3);
498   hspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
499   gtk_spin_button_set_value (GTK_SPIN_BUTTON (hspin), h);
500   gtk_table_attach_defaults (GTK_TABLE (table),
501                              hspin,
502                              1, 2,
503                              3, 4);
504   
505   gtk_widget_show_all (dialog);
506   
507   gtk_dialog_run (GTK_DIALOG (dialog));
508
509   x = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (xspin));
510   y = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (yspin));
511   w = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (wspin));
512   h = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (hspin));
513
514   gtk_widget_destroy (dialog);
515   
516   for (l = selected; l != NULL; l = l->next)
517     {
518       window = l->data;
519       
520       gdk_window_move_resize (window, x, y, w, h);
521     }
522
523   g_list_free (selected);
524 }
525
526 static void
527 restack_clicked (GtkWidget *button,
528                  gpointer data)
529 {
530   GList *selected;
531
532   selected = get_selected_windows ();
533
534   if (g_list_length (selected) != 2)
535     {
536       g_warning ("select two windows");
537     }
538
539   gdk_window_restack (selected->data,
540                       selected->next->data,
541                       GPOINTER_TO_INT (data));
542
543   g_list_free (selected);
544
545   update_store ();
546 }
547
548 static void
549 scroll_window_clicked (GtkWidget *button, 
550                        gpointer data)
551 {
552   GdkWindow *window;
553   GtkDirectionType direction;
554   GList *selected, *l;
555   gint dx, dy;
556
557   direction = GPOINTER_TO_INT (data);
558     
559   selected = get_selected_windows ();
560
561   dx = 0; dy = 0;
562   switch (direction) {
563   case GTK_DIR_UP:
564     dy = 10;
565     break;
566   case GTK_DIR_DOWN:
567     dy = -10;
568     break;
569   case GTK_DIR_LEFT:
570     dx = 10;
571     break;
572   case GTK_DIR_RIGHT:
573     dx = -10;
574     break;
575   default:
576     break;
577   }
578   
579   for (l = selected; l != NULL; l = l->next)
580     {
581       window = l->data;
582
583       gdk_window_scroll (window, dx, dy);
584     }
585
586   g_list_free (selected);
587 }
588
589
590 static void
591 raise_window_clicked (GtkWidget *button, 
592                       gpointer data)
593 {
594   GList *selected, *l;
595   GdkWindow *window;
596     
597   selected = get_selected_windows ();
598
599   for (l = selected; l != NULL; l = l->next)
600     {
601       window = l->data;
602       
603       gdk_window_raise (window);
604     }
605
606   g_list_free (selected);
607   
608   update_store ();
609 }
610
611 static void
612 lower_window_clicked (GtkWidget *button, 
613                       gpointer data)
614 {
615   GList *selected, *l;
616   GdkWindow *window;
617     
618   selected = get_selected_windows ();
619
620   for (l = selected; l != NULL; l = l->next)
621     {
622       window = l->data;
623       
624       gdk_window_lower (window);
625     }
626
627   g_list_free (selected);
628   
629   update_store ();
630 }
631
632
633 static void
634 smaller_window_clicked (GtkWidget *button, 
635                         gpointer data)
636 {
637   GList *selected, *l;
638   GdkWindow *window;
639   int w, h;
640
641   selected = get_selected_windows ();
642
643   for (l = selected; l != NULL; l = l->next)
644     {
645       window = l->data;
646       
647       w = gdk_window_get_width (window) - 10;
648       h = gdk_window_get_height (window) - 10;
649       if (w < 1)
650         w = 1;
651       if (h < 1)
652         h = 1;
653       
654       gdk_window_resize (window, w, h);
655     }
656
657   g_list_free (selected);
658 }
659
660 static void
661 larger_window_clicked (GtkWidget *button, 
662                         gpointer data)
663 {
664   GList *selected, *l;
665   GdkWindow *window;
666   int w, h;
667
668   selected = get_selected_windows ();
669
670   for (l = selected; l != NULL; l = l->next)
671     {
672       window = l->data;
673       
674       w = gdk_window_get_width (window) + 10;
675       h = gdk_window_get_height (window) + 10;
676       
677       gdk_window_resize (window, w, h);
678     }
679
680   g_list_free (selected);
681 }
682
683 static void
684 native_window_clicked (GtkWidget *button, 
685                         gpointer data)
686 {
687   GList *selected, *l;
688   GdkWindow *window;
689
690   selected = get_selected_windows ();
691
692   for (l = selected; l != NULL; l = l->next)
693     {
694       window = l->data;
695       
696       gdk_window_ensure_native (window);
697     }
698   
699   g_list_free (selected);
700   
701   update_store ();
702 }
703
704 static gboolean
705 darea_button_release_event (GtkWidget *widget,
706                             GdkEventButton *event)
707 {
708   if ((event->state & GDK_CONTROL_MASK) != 0)
709     {
710       toggle_selection_window (event->window);
711     }
712   else
713     {
714       unselect_windows ();
715       select_window (event->window);
716     }
717     
718   return TRUE;
719 }
720
721 static void
722 render_window_cell (GtkTreeViewColumn *tree_column,
723                     GtkCellRenderer   *cell,
724                     GtkTreeModel      *tree_model,
725                     GtkTreeIter       *iter,
726                     gpointer           data)
727 {
728   GdkWindow *window;
729   char *name;
730
731   gtk_tree_model_get (GTK_TREE_MODEL (window_store),
732                       iter,
733                       0, &window,
734                       -1);
735
736   if (gdk_window_has_native (window))
737       name = g_strdup_printf ("%p (native)", window);
738   else
739       name = g_strdup_printf ("%p", window);
740
741   g_object_set (cell,
742                 "text", name,
743                 NULL);
744 }
745
746 static void
747 add_children (GtkTreeStore *store,
748               GdkWindow *window,
749               GtkTreeIter *window_iter)
750 {
751   GList *l;
752   GtkTreeIter child_iter;
753
754   for (l = gdk_window_peek_children (window);
755        l != NULL;
756        l = l->next)
757     {
758       gtk_tree_store_append (store, &child_iter, window_iter);
759       gtk_tree_store_set (store, &child_iter,
760                           0, l->data,
761                           -1);
762
763       add_children (store, l->data, &child_iter);
764     }
765 }
766
767 static void
768 update_store (void)
769 {
770   GList *selected;
771
772   selected = get_selected_windows ();
773
774   gtk_tree_store_clear (window_store);
775
776   add_children (window_store, gtk_widget_get_window (darea), NULL);
777   gtk_tree_view_expand_all (GTK_TREE_VIEW (treeview));
778
779   select_windows (selected);
780   g_list_free (selected);
781 }
782
783
784 int
785 main (int argc, char **argv)
786 {
787   GtkWidget *window, *vbox, *hbox, *frame;
788   GtkWidget *button, *scrolled, *table;
789   GtkTreeViewColumn *column;
790   GtkCellRenderer *renderer;
791   GdkColor black = {0};
792   GFile *file;
793   
794   gtk_init (&argc, &argv);
795
796   main_window = window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
797   gtk_container_set_border_width (GTK_CONTAINER (window), 0);
798
799   g_signal_connect (G_OBJECT (window), "delete-event", gtk_main_quit, NULL);
800
801   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
802   gtk_container_add (GTK_CONTAINER (window), hbox);
803   gtk_widget_show (hbox);
804
805   frame = gtk_frame_new ("GdkWindows");
806   gtk_box_pack_start (GTK_BOX (hbox),
807                       frame,
808                       FALSE, FALSE,
809                       5);
810   gtk_widget_show (frame);
811
812   darea =  gtk_drawing_area_new ();
813   /*gtk_widget_set_double_buffered (darea, FALSE);*/
814   gtk_widget_add_events (darea, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
815   gtk_widget_set_size_request (darea, 500, 500);
816   g_signal_connect (darea, "button_release_event", 
817                     G_CALLBACK (darea_button_release_event), 
818                     NULL);
819
820   
821   gtk_container_add (GTK_CONTAINER (frame), darea);
822   gtk_widget_realize (darea);
823   gtk_widget_show (darea);
824   gtk_widget_modify_bg (darea, GTK_STATE_NORMAL,
825                         &black);
826
827
828   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
829   gtk_box_pack_start (GTK_BOX (hbox),
830                       vbox,
831                       FALSE, FALSE,
832                       5);
833   gtk_widget_show (vbox);
834
835   window_store = gtk_tree_store_new (1, GDK_TYPE_WINDOW);
836   
837   treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (window_store));
838   gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
839                                GTK_SELECTION_MULTIPLE);
840   column = gtk_tree_view_column_new ();
841   gtk_tree_view_column_set_title (column, "Window");
842   renderer = gtk_cell_renderer_text_new ();
843   gtk_tree_view_column_pack_start (column, renderer, TRUE);
844   gtk_tree_view_column_set_cell_data_func (column,
845                                            renderer,
846                                            render_window_cell,
847                                            NULL, NULL);
848
849   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
850
851
852   scrolled = gtk_scrolled_window_new (NULL, NULL);
853   gtk_widget_set_size_request (scrolled, 200, 400);
854   gtk_container_add (GTK_CONTAINER (scrolled), treeview);
855   gtk_box_pack_start (GTK_BOX (vbox),
856                       scrolled,
857                       FALSE, FALSE,
858                       5);
859   gtk_widget_show (scrolled);
860   gtk_widget_show (treeview);
861   
862   table = gtk_table_new (5, 4, TRUE);
863   gtk_box_pack_start (GTK_BOX (vbox),
864                       table,
865                       FALSE, FALSE,
866                       2);
867   gtk_widget_show (table);
868
869   button = gtk_button_new ();
870   gtk_button_set_image (GTK_BUTTON (button),
871                         gtk_image_new_from_stock (GTK_STOCK_GO_BACK,
872                                                   GTK_ICON_SIZE_BUTTON));
873   g_signal_connect (button, "clicked", 
874                     G_CALLBACK (move_window_clicked), 
875                     GINT_TO_POINTER (GTK_DIR_LEFT));
876   gtk_table_attach_defaults (GTK_TABLE (table),
877                              button,
878                              0, 1,
879                              1, 2);
880   gtk_widget_show (button);
881
882   button = gtk_button_new ();
883   gtk_button_set_image (GTK_BUTTON (button),
884                         gtk_image_new_from_stock (GTK_STOCK_GO_UP,
885                                                   GTK_ICON_SIZE_BUTTON));
886   g_signal_connect (button, "clicked", 
887                     G_CALLBACK (move_window_clicked), 
888                     GINT_TO_POINTER (GTK_DIR_UP));
889   gtk_table_attach_defaults (GTK_TABLE (table),
890                              button,
891                              1, 2,
892                              0, 1);
893   gtk_widget_show (button);
894
895   button = gtk_button_new ();
896   gtk_button_set_image (GTK_BUTTON (button),
897                         gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD,
898                                                   GTK_ICON_SIZE_BUTTON));
899   g_signal_connect (button, "clicked", 
900                     G_CALLBACK (move_window_clicked), 
901                     GINT_TO_POINTER (GTK_DIR_RIGHT));
902   gtk_table_attach_defaults (GTK_TABLE (table),
903                              button,
904                              2, 3,
905                              1, 2);
906   gtk_widget_show (button);
907
908   button = gtk_button_new ();
909   gtk_button_set_image (GTK_BUTTON (button),
910                         gtk_image_new_from_stock (GTK_STOCK_GO_DOWN,
911                                                   GTK_ICON_SIZE_BUTTON));
912   g_signal_connect (button, "clicked", 
913                     G_CALLBACK (move_window_clicked), 
914                     GINT_TO_POINTER (GTK_DIR_DOWN));
915   gtk_table_attach_defaults (GTK_TABLE (table),
916                              button,
917                              1, 2,
918                              2, 3);
919   gtk_widget_show (button);
920
921
922   button = gtk_button_new_with_label ("Raise");
923   g_signal_connect (button, "clicked", 
924                     G_CALLBACK (raise_window_clicked), 
925                     NULL);
926   gtk_table_attach_defaults (GTK_TABLE (table),
927                              button,
928                              0, 1,
929                              0, 1);
930   gtk_widget_show (button);
931
932   button = gtk_button_new_with_label ("Lower");
933   g_signal_connect (button, "clicked", 
934                     G_CALLBACK (lower_window_clicked), 
935                     NULL);
936   gtk_table_attach_defaults (GTK_TABLE (table),
937                              button,
938                              0, 1,
939                              2, 3);
940   gtk_widget_show (button);
941
942
943   button = gtk_button_new_with_label ("Smaller");
944   g_signal_connect (button, "clicked", 
945                     G_CALLBACK (smaller_window_clicked), 
946                     NULL);
947   gtk_table_attach_defaults (GTK_TABLE (table),
948                              button,
949                              2, 3,
950                              0, 1);
951   gtk_widget_show (button);
952
953   button = gtk_button_new_with_label ("Larger");
954   g_signal_connect (button, "clicked", 
955                     G_CALLBACK (larger_window_clicked), 
956                     NULL);
957   gtk_table_attach_defaults (GTK_TABLE (table),
958                              button,
959                              2, 3,
960                              2, 3);
961   gtk_widget_show (button);
962
963   button = gtk_button_new_with_label ("Native");
964   g_signal_connect (button, "clicked", 
965                     G_CALLBACK (native_window_clicked), 
966                     NULL);
967   gtk_table_attach_defaults (GTK_TABLE (table),
968                              button,
969                              1, 2,
970                              1, 2);
971   gtk_widget_show (button);
972
973
974   button = gtk_button_new_with_label ("scroll");
975   gtk_button_set_image (GTK_BUTTON (button),
976                         gtk_image_new_from_stock (GTK_STOCK_GO_UP,
977                                                   GTK_ICON_SIZE_BUTTON));
978   g_signal_connect (button, "clicked", 
979                     G_CALLBACK (scroll_window_clicked), 
980                     GINT_TO_POINTER (GTK_DIR_UP));
981   gtk_table_attach_defaults (GTK_TABLE (table),
982                              button,
983                              3, 4,
984                              0, 1);
985   gtk_widget_show (button);
986
987   button = gtk_button_new_with_label ("scroll");
988   gtk_button_set_image (GTK_BUTTON (button),
989                         gtk_image_new_from_stock (GTK_STOCK_GO_DOWN,
990                                                   GTK_ICON_SIZE_BUTTON));
991   g_signal_connect (button, "clicked", 
992                     G_CALLBACK (scroll_window_clicked), 
993                     GINT_TO_POINTER (GTK_DIR_DOWN));
994   gtk_table_attach_defaults (GTK_TABLE (table),
995                              button,
996                              3, 4,
997                              1, 2);
998   gtk_widget_show (button);
999
1000   button = gtk_button_new_with_label ("Manual");
1001   g_signal_connect (button, "clicked", 
1002                     G_CALLBACK (manual_clicked),
1003                     NULL);
1004   gtk_table_attach_defaults (GTK_TABLE (table),
1005                              button,
1006                              3, 4,
1007                              2, 3);
1008   gtk_widget_show (button);
1009
1010   button = gtk_button_new_with_label ("Restack above");
1011   g_signal_connect (button, "clicked",
1012                     G_CALLBACK (restack_clicked),
1013                     GINT_TO_POINTER (1));
1014   gtk_table_attach_defaults (GTK_TABLE (table),
1015                              button,
1016                              2, 3,
1017                              3, 4);
1018   gtk_widget_show (button);
1019
1020   button = gtk_button_new_with_label ("Restack below");
1021   g_signal_connect (button, "clicked",
1022                     G_CALLBACK (restack_clicked),
1023                     0);
1024   gtk_table_attach_defaults (GTK_TABLE (table),
1025                              button,
1026                              3, 4,
1027                              3, 4);
1028   gtk_widget_show (button);
1029
1030   button = gtk_button_new_with_label ("Add window");
1031   gtk_box_pack_start (GTK_BOX (vbox),
1032                       button,
1033                       FALSE, FALSE,
1034                       2);
1035   gtk_widget_show (button);
1036   g_signal_connect (button, "clicked", 
1037                     G_CALLBACK (add_window_clicked), 
1038                     NULL);
1039   
1040   button = gtk_button_new_with_label ("Remove window");
1041   gtk_box_pack_start (GTK_BOX (vbox),
1042                       button,
1043                       FALSE, FALSE,
1044                       2);
1045   gtk_widget_show (button);
1046   g_signal_connect (button, "clicked", 
1047                     G_CALLBACK (remove_window_clicked), 
1048                     NULL);
1049
1050   button = gtk_button_new_with_label ("Save");
1051   gtk_box_pack_start (GTK_BOX (vbox),
1052                       button,
1053                       FALSE, FALSE,
1054                       2);
1055   gtk_widget_show (button);
1056   g_signal_connect (button, "clicked", 
1057                     G_CALLBACK (save_clicked), 
1058                     NULL);
1059
1060   gtk_widget_show (window);
1061
1062   if (argc == 2)
1063     {
1064       file = g_file_new_for_commandline_arg (argv[1]);
1065       load_file (file);
1066       g_object_unref (file);
1067     }
1068   
1069   gtk_main ();
1070
1071   return 0;
1072 }