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