]> Pileus Git - ~andy/gtk/blob - tests/testwindows.c
Updated Slovenian translation
[~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   GdkRGBA black = {0,0,0,1};
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_override_background_color (darea, 0, &black);
825
826
827   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
828   gtk_box_pack_start (GTK_BOX (hbox),
829                       vbox,
830                       FALSE, FALSE,
831                       5);
832   gtk_widget_show (vbox);
833
834   window_store = gtk_tree_store_new (1, GDK_TYPE_WINDOW);
835   
836   treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (window_store));
837   gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
838                                GTK_SELECTION_MULTIPLE);
839   column = gtk_tree_view_column_new ();
840   gtk_tree_view_column_set_title (column, "Window");
841   renderer = gtk_cell_renderer_text_new ();
842   gtk_tree_view_column_pack_start (column, renderer, TRUE);
843   gtk_tree_view_column_set_cell_data_func (column,
844                                            renderer,
845                                            render_window_cell,
846                                            NULL, NULL);
847
848   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
849
850
851   scrolled = gtk_scrolled_window_new (NULL, NULL);
852   gtk_widget_set_size_request (scrolled, 200, 400);
853   gtk_container_add (GTK_CONTAINER (scrolled), treeview);
854   gtk_box_pack_start (GTK_BOX (vbox),
855                       scrolled,
856                       FALSE, FALSE,
857                       5);
858   gtk_widget_show (scrolled);
859   gtk_widget_show (treeview);
860   
861   table = gtk_table_new (5, 4, TRUE);
862   gtk_box_pack_start (GTK_BOX (vbox),
863                       table,
864                       FALSE, FALSE,
865                       2);
866   gtk_widget_show (table);
867
868   button = gtk_button_new ();
869   gtk_button_set_image (GTK_BUTTON (button),
870                         gtk_image_new_from_stock (GTK_STOCK_GO_BACK,
871                                                   GTK_ICON_SIZE_BUTTON));
872   g_signal_connect (button, "clicked", 
873                     G_CALLBACK (move_window_clicked), 
874                     GINT_TO_POINTER (GTK_DIR_LEFT));
875   gtk_table_attach_defaults (GTK_TABLE (table),
876                              button,
877                              0, 1,
878                              1, 2);
879   gtk_widget_show (button);
880
881   button = gtk_button_new ();
882   gtk_button_set_image (GTK_BUTTON (button),
883                         gtk_image_new_from_stock (GTK_STOCK_GO_UP,
884                                                   GTK_ICON_SIZE_BUTTON));
885   g_signal_connect (button, "clicked", 
886                     G_CALLBACK (move_window_clicked), 
887                     GINT_TO_POINTER (GTK_DIR_UP));
888   gtk_table_attach_defaults (GTK_TABLE (table),
889                              button,
890                              1, 2,
891                              0, 1);
892   gtk_widget_show (button);
893
894   button = gtk_button_new ();
895   gtk_button_set_image (GTK_BUTTON (button),
896                         gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD,
897                                                   GTK_ICON_SIZE_BUTTON));
898   g_signal_connect (button, "clicked", 
899                     G_CALLBACK (move_window_clicked), 
900                     GINT_TO_POINTER (GTK_DIR_RIGHT));
901   gtk_table_attach_defaults (GTK_TABLE (table),
902                              button,
903                              2, 3,
904                              1, 2);
905   gtk_widget_show (button);
906
907   button = gtk_button_new ();
908   gtk_button_set_image (GTK_BUTTON (button),
909                         gtk_image_new_from_stock (GTK_STOCK_GO_DOWN,
910                                                   GTK_ICON_SIZE_BUTTON));
911   g_signal_connect (button, "clicked", 
912                     G_CALLBACK (move_window_clicked), 
913                     GINT_TO_POINTER (GTK_DIR_DOWN));
914   gtk_table_attach_defaults (GTK_TABLE (table),
915                              button,
916                              1, 2,
917                              2, 3);
918   gtk_widget_show (button);
919
920
921   button = gtk_button_new_with_label ("Raise");
922   g_signal_connect (button, "clicked", 
923                     G_CALLBACK (raise_window_clicked), 
924                     NULL);
925   gtk_table_attach_defaults (GTK_TABLE (table),
926                              button,
927                              0, 1,
928                              0, 1);
929   gtk_widget_show (button);
930
931   button = gtk_button_new_with_label ("Lower");
932   g_signal_connect (button, "clicked", 
933                     G_CALLBACK (lower_window_clicked), 
934                     NULL);
935   gtk_table_attach_defaults (GTK_TABLE (table),
936                              button,
937                              0, 1,
938                              2, 3);
939   gtk_widget_show (button);
940
941
942   button = gtk_button_new_with_label ("Smaller");
943   g_signal_connect (button, "clicked", 
944                     G_CALLBACK (smaller_window_clicked), 
945                     NULL);
946   gtk_table_attach_defaults (GTK_TABLE (table),
947                              button,
948                              2, 3,
949                              0, 1);
950   gtk_widget_show (button);
951
952   button = gtk_button_new_with_label ("Larger");
953   g_signal_connect (button, "clicked", 
954                     G_CALLBACK (larger_window_clicked), 
955                     NULL);
956   gtk_table_attach_defaults (GTK_TABLE (table),
957                              button,
958                              2, 3,
959                              2, 3);
960   gtk_widget_show (button);
961
962   button = gtk_button_new_with_label ("Native");
963   g_signal_connect (button, "clicked", 
964                     G_CALLBACK (native_window_clicked), 
965                     NULL);
966   gtk_table_attach_defaults (GTK_TABLE (table),
967                              button,
968                              1, 2,
969                              1, 2);
970   gtk_widget_show (button);
971
972
973   button = gtk_button_new_with_label ("scroll");
974   gtk_button_set_image (GTK_BUTTON (button),
975                         gtk_image_new_from_stock (GTK_STOCK_GO_UP,
976                                                   GTK_ICON_SIZE_BUTTON));
977   g_signal_connect (button, "clicked", 
978                     G_CALLBACK (scroll_window_clicked), 
979                     GINT_TO_POINTER (GTK_DIR_UP));
980   gtk_table_attach_defaults (GTK_TABLE (table),
981                              button,
982                              3, 4,
983                              0, 1);
984   gtk_widget_show (button);
985
986   button = gtk_button_new_with_label ("scroll");
987   gtk_button_set_image (GTK_BUTTON (button),
988                         gtk_image_new_from_stock (GTK_STOCK_GO_DOWN,
989                                                   GTK_ICON_SIZE_BUTTON));
990   g_signal_connect (button, "clicked", 
991                     G_CALLBACK (scroll_window_clicked), 
992                     GINT_TO_POINTER (GTK_DIR_DOWN));
993   gtk_table_attach_defaults (GTK_TABLE (table),
994                              button,
995                              3, 4,
996                              1, 2);
997   gtk_widget_show (button);
998
999   button = gtk_button_new_with_label ("Manual");
1000   g_signal_connect (button, "clicked", 
1001                     G_CALLBACK (manual_clicked),
1002                     NULL);
1003   gtk_table_attach_defaults (GTK_TABLE (table),
1004                              button,
1005                              3, 4,
1006                              2, 3);
1007   gtk_widget_show (button);
1008
1009   button = gtk_button_new_with_label ("Restack above");
1010   g_signal_connect (button, "clicked",
1011                     G_CALLBACK (restack_clicked),
1012                     GINT_TO_POINTER (1));
1013   gtk_table_attach_defaults (GTK_TABLE (table),
1014                              button,
1015                              2, 3,
1016                              3, 4);
1017   gtk_widget_show (button);
1018
1019   button = gtk_button_new_with_label ("Restack below");
1020   g_signal_connect (button, "clicked",
1021                     G_CALLBACK (restack_clicked),
1022                     0);
1023   gtk_table_attach_defaults (GTK_TABLE (table),
1024                              button,
1025                              3, 4,
1026                              3, 4);
1027   gtk_widget_show (button);
1028
1029   button = gtk_button_new_with_label ("Add window");
1030   gtk_box_pack_start (GTK_BOX (vbox),
1031                       button,
1032                       FALSE, FALSE,
1033                       2);
1034   gtk_widget_show (button);
1035   g_signal_connect (button, "clicked", 
1036                     G_CALLBACK (add_window_clicked), 
1037                     NULL);
1038   
1039   button = gtk_button_new_with_label ("Remove window");
1040   gtk_box_pack_start (GTK_BOX (vbox),
1041                       button,
1042                       FALSE, FALSE,
1043                       2);
1044   gtk_widget_show (button);
1045   g_signal_connect (button, "clicked", 
1046                     G_CALLBACK (remove_window_clicked), 
1047                     NULL);
1048
1049   button = gtk_button_new_with_label ("Save");
1050   gtk_box_pack_start (GTK_BOX (vbox),
1051                       button,
1052                       FALSE, FALSE,
1053                       2);
1054   gtk_widget_show (button);
1055   g_signal_connect (button, "clicked", 
1056                     G_CALLBACK (save_clicked), 
1057                     NULL);
1058
1059   gtk_widget_show (window);
1060
1061   if (argc == 2)
1062     {
1063       file = g_file_new_for_commandline_arg (argv[1]);
1064       load_file (file);
1065       g_object_unref (file);
1066     }
1067   
1068   gtk_main ();
1069
1070   return 0;
1071 }