]> Pileus Git - ~andy/gtk/blob - tests/testwindows.c
tests/testwindows.c: Use accessor functions to access GtkWidget
[~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   if (!gdk_colormap_alloc_color (gtk_widget_get_colormap (darea), bg, FALSE, TRUE))
55     g_assert_not_reached ();
56   gdk_window_set_background (window, bg);
57   g_object_set_data_full (G_OBJECT (window), "color", bg, g_free);
58   
59   gdk_window_show (window);
60   
61   return window;
62 }
63
64 static void
65 add_window_cb (GtkTreeModel      *model,
66                GtkTreePath       *path,
67                GtkTreeIter       *iter,
68                gpointer           data)
69 {
70   GList **selected = data;
71   GdkWindow *window;
72
73   gtk_tree_model_get (GTK_TREE_MODEL (window_store),
74                       iter,
75                       0, &window,
76                       -1);
77
78   *selected = g_list_prepend (*selected, window);
79 }
80
81 static GList *
82 get_selected_windows (void)
83 {
84   GtkTreeSelection *sel;
85   GList *selected;
86
87   sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
88
89   selected = NULL;
90   gtk_tree_selection_selected_foreach (sel, add_window_cb, &selected);
91   
92   return selected;
93 }
94
95 static gboolean
96 find_window_helper (GtkTreeModel *model,
97                     GdkWindow *window,
98                     GtkTreeIter *iter,
99                     GtkTreeIter *selected_iter)
100 {
101   GtkTreeIter child_iter;
102   GdkWindow *w;
103
104   do
105     {
106       gtk_tree_model_get (model, iter,
107                           0, &w,
108                           -1);
109       if (w == window)
110         {
111           *selected_iter = *iter;
112           return TRUE;
113         }
114       
115       if (gtk_tree_model_iter_children (model,
116                                         &child_iter,
117                                         iter))
118         {
119           if (find_window_helper (model, window, &child_iter, selected_iter))
120             return TRUE;
121         }
122     } while (gtk_tree_model_iter_next (model, iter));
123
124   return FALSE;
125 }
126
127 static gboolean
128 find_window (GdkWindow *window,
129              GtkTreeIter *window_iter)
130 {
131   GtkTreeIter iter;
132
133   if (!gtk_tree_model_get_iter_first  (GTK_TREE_MODEL (window_store), &iter))
134     return FALSE;
135
136   return find_window_helper (GTK_TREE_MODEL (window_store),
137                              window,
138                              &iter,
139                              window_iter);
140 }
141
142 static void
143 toggle_selection_window (GdkWindow *window)
144 {
145   GtkTreeSelection *selection;
146   GtkTreeIter iter;
147
148   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
149
150   if (window != NULL &&
151       find_window (window, &iter))
152     {
153       if (gtk_tree_selection_iter_is_selected (selection, &iter))
154         gtk_tree_selection_unselect_iter (selection,  &iter);
155       else
156         gtk_tree_selection_select_iter (selection,  &iter);
157     }
158 }
159
160 static void
161 unselect_windows (void)
162 {
163   GtkTreeSelection *selection;
164
165   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
166   
167   gtk_tree_selection_unselect_all (selection);
168 }
169
170
171 static void
172 select_window (GdkWindow *window)
173 {
174   GtkTreeSelection *selection;
175   GtkTreeIter iter;
176
177   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
178
179   if (window != NULL &&
180       find_window (window, &iter))
181     gtk_tree_selection_select_iter (selection,  &iter);
182 }
183
184 static void
185 select_windows (GList *windows)
186 {
187   GtkTreeSelection *selection;
188   GtkTreeIter iter;
189   GList *l;
190
191   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
192   gtk_tree_selection_unselect_all (selection);
193   
194   for (l = windows; l != NULL; l = l->next)
195     {
196       if (find_window (l->data, &iter))
197         gtk_tree_selection_select_iter (selection,  &iter);
198     }
199 }
200
201 static void
202 add_window_clicked (GtkWidget *button, 
203                     gpointer data)
204 {
205   GdkWindow *parent;
206   GList *l;
207
208   l = get_selected_windows ();
209   if (l != NULL)
210     parent = l->data;
211   else
212     parent = gtk_widget_get_window (darea);
213
214   g_list_free (l);
215   
216   create_window (parent, 10, 10, 100, 100, NULL);
217   update_store ();
218 }
219
220 static void
221 remove_window_clicked (GtkWidget *button, 
222                        gpointer data)
223 {
224   GList *l, *selected;
225
226   selected = get_selected_windows ();
227
228   for (l = selected; l != NULL; l = l->next)
229     gdk_window_destroy (l->data);
230
231   g_list_free (selected);
232
233   update_store ();
234 }
235
236 static void save_children (GString *s, GdkWindow *window);
237
238 static void
239 save_window (GString *s,
240              GdkWindow *window)
241 {
242   gint x, y, w, h;
243   GdkColor *color;
244
245   gdk_window_get_position (window, &x, &y);
246   gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
247   color = g_object_get_data (G_OBJECT (window), "color");
248   
249   g_string_append_printf (s, "%d,%d %dx%d (%d,%d,%d) %d %d\n",
250                           x, y, w, h,
251                           color->red, color->green, color->blue,
252                           gdk_window_has_native (window),
253                           g_list_length (gdk_window_peek_children (window)));
254
255   save_children (s, window);
256 }
257
258
259 static void
260 save_children (GString *s,
261                GdkWindow *window)
262 {
263   GList *l;
264   GdkWindow *child;
265
266   for (l = g_list_reverse (gdk_window_peek_children (window));
267        l != NULL;
268        l = l->next)
269     {
270       child = l->data;
271
272       save_window (s, child);
273     }
274 }
275
276
277 static void
278 save_clicked (GtkWidget *button, 
279               gpointer data)
280 {
281   GString *s;
282   GtkWidget *dialog;
283   GFile *file;
284
285   s = g_string_new ("");
286
287   save_children (s, gtk_widget_get_window (darea));
288
289   dialog = gtk_file_chooser_dialog_new ("Filename for window data",
290                                         NULL,
291                                         GTK_FILE_CHOOSER_ACTION_SAVE,
292                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
293                                         GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
294                                         NULL);
295   
296   gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
297   
298   if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
299     {
300       file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
301
302       g_file_replace_contents (file,
303                                s->str, s->len,
304                                NULL, FALSE,
305                                0, NULL, NULL, NULL);
306
307       g_object_unref (file);
308     }
309
310   gtk_widget_destroy (dialog);
311   g_string_free (s, TRUE);
312 }
313
314 static void
315 destroy_children (GdkWindow *window)
316 {
317   GList *l;
318   GdkWindow *child;
319
320   for (l = gdk_window_peek_children (window);
321        l != NULL;
322        l = l->next)
323     {
324       child = l->data;
325       
326       destroy_children (child);
327       gdk_window_destroy (child);
328     }
329 }
330
331 static char **
332 parse_window (GdkWindow *parent, char **lines)
333 {
334   int x, y, w, h, r, g, b, native, n_children;
335   GdkWindow *window;
336   GdkColor color;
337   int i;
338
339   if (*lines == NULL)
340     return lines;
341   
342   if (sscanf(*lines, "%d,%d %dx%d (%d,%d,%d) %d %d",
343              &x, &y, &w, &h, &r, &g, &b, &native, &n_children) == 9)
344     {
345       lines++;
346       color.red = r;
347       color.green = g;
348       color.blue = b;
349       window = create_window (parent, x, y, w, h, &color);
350       if (native)
351         gdk_window_ensure_native (window);
352       
353       for (i = 0; i < n_children; i++)
354         lines = parse_window (window, lines);
355     }
356   else
357     lines++;
358   
359   return lines;
360 }
361   
362 static void
363 load_file (GFile *file)
364 {
365   GdkWindow *window;
366   char *data;
367   char **lines, **l;
368   
369   if (g_file_load_contents (file, NULL, &data, NULL, NULL, NULL))
370     {
371       window = gtk_widget_get_window (darea);
372
373       destroy_children (window);
374
375       lines = g_strsplit (data, "\n", -1);
376
377       l = lines;
378       while (*l != NULL)
379         l = parse_window (window, l);
380     }
381
382   update_store ();
383 }
384
385 static void
386 move_window_clicked (GtkWidget *button, 
387                      gpointer data)
388 {
389   GdkWindow *window;
390   GtkDirectionType direction;
391   GList *selected, *l;
392   gint x, y;
393
394   direction = GPOINTER_TO_INT (data);
395     
396   selected = get_selected_windows ();
397
398   for (l = selected; l != NULL; l = l->next)
399     {
400       window = l->data;
401       
402       gdk_window_get_position (window, &x, &y);
403       
404       switch (direction) {
405       case GTK_DIR_UP:
406         y -= 10;
407         break;
408       case GTK_DIR_DOWN:
409         y += 10;
410         break;
411       case GTK_DIR_LEFT:
412         x -= 10;
413         break;
414       case GTK_DIR_RIGHT:
415         x += 10;
416         break;
417       default:
418         break;
419       }
420
421       gdk_window_move (window, x, y);
422     }
423
424   g_list_free (selected);
425 }
426
427 static void
428 manual_clicked (GtkWidget *button, 
429                 gpointer data)
430 {
431   GdkWindow *window;
432   GList *selected, *l;
433   int x, y, w, h;
434   GtkWidget *dialog, *table, *label, *xspin, *yspin, *wspin, *hspin;
435   
436
437   selected = get_selected_windows ();
438
439   if (selected == NULL)
440     return;
441
442   gdk_window_get_position (selected->data, &x, &y);
443   gdk_drawable_get_size (selected->data, &w, &h);
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       gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
648       
649       w -= 10;
650       h -= 10;
651       if (w < 1)
652         w = 1;
653       if (h < 1)
654         h = 1;
655       
656       gdk_window_resize (window, w, h);
657     }
658
659   g_list_free (selected);
660 }
661
662 static void
663 larger_window_clicked (GtkWidget *button, 
664                         gpointer data)
665 {
666   GList *selected, *l;
667   GdkWindow *window;
668   int w, h;
669
670   selected = get_selected_windows ();
671
672   for (l = selected; l != NULL; l = l->next)
673     {
674       window = l->data;
675       
676       gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
677       
678       w += 10;
679       h += 10;
680       
681       gdk_window_resize (window, w, h);
682     }
683
684   g_list_free (selected);
685 }
686
687 static void
688 native_window_clicked (GtkWidget *button, 
689                         gpointer data)
690 {
691   GList *selected, *l;
692   GdkWindow *window;
693
694   selected = get_selected_windows ();
695
696   for (l = selected; l != NULL; l = l->next)
697     {
698       window = l->data;
699       
700       gdk_window_ensure_native (window);
701     }
702   
703   g_list_free (selected);
704   
705   update_store ();
706 }
707
708 static gboolean
709 darea_button_release_event (GtkWidget *widget,
710                             GdkEventButton *event)
711 {
712   if ((event->state & GDK_CONTROL_MASK) != 0)
713     {
714       toggle_selection_window (event->window);
715     }
716   else
717     {
718       unselect_windows ();
719       select_window (event->window);
720     }
721     
722   return TRUE;
723 }
724
725 static void
726 render_window_cell (GtkTreeViewColumn *tree_column,
727                     GtkCellRenderer   *cell,
728                     GtkTreeModel      *tree_model,
729                     GtkTreeIter       *iter,
730                     gpointer           data)
731 {
732   GdkWindow *window;
733   char *name;
734
735   gtk_tree_model_get (GTK_TREE_MODEL (window_store),
736                       iter,
737                       0, &window,
738                       -1);
739
740   if (gdk_window_has_native (window))
741       name = g_strdup_printf ("%p (native)", window);
742   else
743       name = g_strdup_printf ("%p", window);
744
745   g_object_set (cell,
746                 "text", name,
747                 NULL);
748 }
749
750 static void
751 add_children (GtkTreeStore *store,
752               GdkWindow *window,
753               GtkTreeIter *window_iter)
754 {
755   GList *l;
756   GtkTreeIter child_iter;
757
758   for (l = gdk_window_peek_children (window);
759        l != NULL;
760        l = l->next)
761     {
762       gtk_tree_store_append (store, &child_iter, window_iter);
763       gtk_tree_store_set (store, &child_iter,
764                           0, l->data,
765                           -1);
766
767       add_children (store, l->data, &child_iter);
768     }
769 }
770
771 static void
772 update_store (void)
773 {
774   GList *selected;
775
776   selected = get_selected_windows ();
777
778   gtk_tree_store_clear (window_store);
779
780   add_children (window_store, gtk_widget_get_window (darea), NULL);
781   gtk_tree_view_expand_all (GTK_TREE_VIEW (treeview));
782
783   select_windows (selected);
784   g_list_free (selected);
785 }
786
787
788 int
789 main (int argc, char **argv)
790 {
791   GtkWidget *window, *vbox, *hbox, *frame;
792   GtkWidget *button, *scrolled, *table;
793   GtkTreeViewColumn *column;
794   GtkCellRenderer *renderer;
795   GdkColor black = {0};
796   GFile *file;
797   
798   gtk_init (&argc, &argv);
799
800   main_window = window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
801   gtk_container_set_border_width (GTK_CONTAINER (window), 0);
802
803   g_signal_connect (G_OBJECT (window), "delete-event", gtk_main_quit, NULL);
804
805   hbox = gtk_hbox_new (FALSE, 5);
806   gtk_container_add (GTK_CONTAINER (window), hbox);
807   gtk_widget_show (hbox);
808
809   frame = gtk_frame_new ("GdkWindows");
810   gtk_box_pack_start (GTK_BOX (hbox),
811                       frame,
812                       FALSE, FALSE,
813                       5);
814   gtk_widget_show (frame);
815
816   darea =  gtk_drawing_area_new ();
817   /*gtk_widget_set_double_buffered (darea, FALSE);*/
818   gtk_widget_add_events (darea, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
819   gtk_widget_set_size_request (darea, 500, 500);
820   g_signal_connect (darea, "button_release_event", 
821                     G_CALLBACK (darea_button_release_event), 
822                     NULL);
823
824   
825   gtk_container_add (GTK_CONTAINER (frame), darea);
826   gtk_widget_realize (darea);
827   gtk_widget_show (darea);
828   gtk_widget_modify_bg (darea, GTK_STATE_NORMAL,
829                         &black);
830                         
831   
832   vbox = gtk_vbox_new (FALSE, 5);
833   gtk_box_pack_start (GTK_BOX (hbox),
834                       vbox,
835                       FALSE, FALSE,
836                       5);
837   gtk_widget_show (vbox);
838
839   window_store = gtk_tree_store_new (1, GDK_TYPE_WINDOW);
840   
841   treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (window_store));
842   gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
843                                GTK_SELECTION_MULTIPLE);
844   column = gtk_tree_view_column_new ();
845   gtk_tree_view_column_set_title (column, "Window");
846   renderer = gtk_cell_renderer_text_new ();
847   gtk_tree_view_column_pack_start (column, renderer, TRUE);
848   gtk_tree_view_column_set_cell_data_func (column,
849                                            renderer,
850                                            render_window_cell,
851                                            NULL, NULL);
852
853   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
854
855
856   scrolled = gtk_scrolled_window_new (NULL, NULL);
857   gtk_widget_set_size_request (scrolled, 200, 400);
858   gtk_container_add (GTK_CONTAINER (scrolled), treeview);
859   gtk_box_pack_start (GTK_BOX (vbox),
860                       scrolled,
861                       FALSE, FALSE,
862                       5);
863   gtk_widget_show (scrolled);
864   gtk_widget_show (treeview);
865   
866   table = gtk_table_new (5, 4, TRUE);
867   gtk_box_pack_start (GTK_BOX (vbox),
868                       table,
869                       FALSE, FALSE,
870                       2);
871   gtk_widget_show (table);
872
873   button = gtk_button_new ();
874   gtk_button_set_image (GTK_BUTTON (button),
875                         gtk_image_new_from_stock (GTK_STOCK_GO_BACK,
876                                                   GTK_ICON_SIZE_BUTTON));
877   g_signal_connect (button, "clicked", 
878                     G_CALLBACK (move_window_clicked), 
879                     GINT_TO_POINTER (GTK_DIR_LEFT));
880   gtk_table_attach_defaults (GTK_TABLE (table),
881                              button,
882                              0, 1,
883                              1, 2);
884   gtk_widget_show (button);
885
886   button = gtk_button_new ();
887   gtk_button_set_image (GTK_BUTTON (button),
888                         gtk_image_new_from_stock (GTK_STOCK_GO_UP,
889                                                   GTK_ICON_SIZE_BUTTON));
890   g_signal_connect (button, "clicked", 
891                     G_CALLBACK (move_window_clicked), 
892                     GINT_TO_POINTER (GTK_DIR_UP));
893   gtk_table_attach_defaults (GTK_TABLE (table),
894                              button,
895                              1, 2,
896                              0, 1);
897   gtk_widget_show (button);
898
899   button = gtk_button_new ();
900   gtk_button_set_image (GTK_BUTTON (button),
901                         gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD,
902                                                   GTK_ICON_SIZE_BUTTON));
903   g_signal_connect (button, "clicked", 
904                     G_CALLBACK (move_window_clicked), 
905                     GINT_TO_POINTER (GTK_DIR_RIGHT));
906   gtk_table_attach_defaults (GTK_TABLE (table),
907                              button,
908                              2, 3,
909                              1, 2);
910   gtk_widget_show (button);
911
912   button = gtk_button_new ();
913   gtk_button_set_image (GTK_BUTTON (button),
914                         gtk_image_new_from_stock (GTK_STOCK_GO_DOWN,
915                                                   GTK_ICON_SIZE_BUTTON));
916   g_signal_connect (button, "clicked", 
917                     G_CALLBACK (move_window_clicked), 
918                     GINT_TO_POINTER (GTK_DIR_DOWN));
919   gtk_table_attach_defaults (GTK_TABLE (table),
920                              button,
921                              1, 2,
922                              2, 3);
923   gtk_widget_show (button);
924
925
926   button = gtk_button_new_with_label ("Raise");
927   g_signal_connect (button, "clicked", 
928                     G_CALLBACK (raise_window_clicked), 
929                     NULL);
930   gtk_table_attach_defaults (GTK_TABLE (table),
931                              button,
932                              0, 1,
933                              0, 1);
934   gtk_widget_show (button);
935
936   button = gtk_button_new_with_label ("Lower");
937   g_signal_connect (button, "clicked", 
938                     G_CALLBACK (lower_window_clicked), 
939                     NULL);
940   gtk_table_attach_defaults (GTK_TABLE (table),
941                              button,
942                              0, 1,
943                              2, 3);
944   gtk_widget_show (button);
945
946
947   button = gtk_button_new_with_label ("Smaller");
948   g_signal_connect (button, "clicked", 
949                     G_CALLBACK (smaller_window_clicked), 
950                     NULL);
951   gtk_table_attach_defaults (GTK_TABLE (table),
952                              button,
953                              2, 3,
954                              0, 1);
955   gtk_widget_show (button);
956
957   button = gtk_button_new_with_label ("Larger");
958   g_signal_connect (button, "clicked", 
959                     G_CALLBACK (larger_window_clicked), 
960                     NULL);
961   gtk_table_attach_defaults (GTK_TABLE (table),
962                              button,
963                              2, 3,
964                              2, 3);
965   gtk_widget_show (button);
966
967   button = gtk_button_new_with_label ("Native");
968   g_signal_connect (button, "clicked", 
969                     G_CALLBACK (native_window_clicked), 
970                     NULL);
971   gtk_table_attach_defaults (GTK_TABLE (table),
972                              button,
973                              1, 2,
974                              1, 2);
975   gtk_widget_show (button);
976
977
978   button = gtk_button_new_with_label ("scroll");
979   gtk_button_set_image (GTK_BUTTON (button),
980                         gtk_image_new_from_stock (GTK_STOCK_GO_UP,
981                                                   GTK_ICON_SIZE_BUTTON));
982   g_signal_connect (button, "clicked", 
983                     G_CALLBACK (scroll_window_clicked), 
984                     GINT_TO_POINTER (GTK_DIR_UP));
985   gtk_table_attach_defaults (GTK_TABLE (table),
986                              button,
987                              3, 4,
988                              0, 1);
989   gtk_widget_show (button);
990
991   button = gtk_button_new_with_label ("scroll");
992   gtk_button_set_image (GTK_BUTTON (button),
993                         gtk_image_new_from_stock (GTK_STOCK_GO_DOWN,
994                                                   GTK_ICON_SIZE_BUTTON));
995   g_signal_connect (button, "clicked", 
996                     G_CALLBACK (scroll_window_clicked), 
997                     GINT_TO_POINTER (GTK_DIR_DOWN));
998   gtk_table_attach_defaults (GTK_TABLE (table),
999                              button,
1000                              3, 4,
1001                              1, 2);
1002   gtk_widget_show (button);
1003
1004   button = gtk_button_new_with_label ("Manual");
1005   g_signal_connect (button, "clicked", 
1006                     G_CALLBACK (manual_clicked),
1007                     NULL);
1008   gtk_table_attach_defaults (GTK_TABLE (table),
1009                              button,
1010                              3, 4,
1011                              2, 3);
1012   gtk_widget_show (button);
1013
1014   button = gtk_button_new_with_label ("Restack above");
1015   g_signal_connect (button, "clicked",
1016                     G_CALLBACK (restack_clicked),
1017                     GINT_TO_POINTER (1));
1018   gtk_table_attach_defaults (GTK_TABLE (table),
1019                              button,
1020                              2, 3,
1021                              3, 4);
1022   gtk_widget_show (button);
1023
1024   button = gtk_button_new_with_label ("Restack below");
1025   g_signal_connect (button, "clicked",
1026                     G_CALLBACK (restack_clicked),
1027                     0);
1028   gtk_table_attach_defaults (GTK_TABLE (table),
1029                              button,
1030                              3, 4,
1031                              3, 4);
1032   gtk_widget_show (button);
1033
1034   button = gtk_button_new_with_label ("Add window");
1035   gtk_box_pack_start (GTK_BOX (vbox),
1036                       button,
1037                       FALSE, FALSE,
1038                       2);
1039   gtk_widget_show (button);
1040   g_signal_connect (button, "clicked", 
1041                     G_CALLBACK (add_window_clicked), 
1042                     NULL);
1043   
1044   button = gtk_button_new_with_label ("Remove window");
1045   gtk_box_pack_start (GTK_BOX (vbox),
1046                       button,
1047                       FALSE, FALSE,
1048                       2);
1049   gtk_widget_show (button);
1050   g_signal_connect (button, "clicked", 
1051                     G_CALLBACK (remove_window_clicked), 
1052                     NULL);
1053
1054   button = gtk_button_new_with_label ("Save");
1055   gtk_box_pack_start (GTK_BOX (vbox),
1056                       button,
1057                       FALSE, FALSE,
1058                       2);
1059   gtk_widget_show (button);
1060   g_signal_connect (button, "clicked", 
1061                     G_CALLBACK (save_clicked), 
1062                     NULL);
1063
1064   gtk_widget_show (window);
1065
1066   if (argc == 2)
1067     {
1068       file = g_file_new_for_commandline_arg (argv[1]);
1069       load_file (file);
1070       g_object_unref (file);
1071     }
1072   
1073   gtk_main ();
1074
1075   return 0;
1076 }