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