]> Pileus Git - ~andy/gtk/blob - tests/testwindows.c
Merge branch 'master' into client-side-windows
[~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 remove_window_clicked (GtkWidget *button, 
226                        gpointer data)
227 {
228   GList *l, *selected;
229
230   selected = get_selected_windows ();
231
232   for (l = selected; l != NULL; l = l->next)
233     gdk_window_destroy (l->data);
234
235   g_list_free (selected);
236
237   update_store ();
238 }
239
240 static void save_children (GString *s, GdkWindow *window);
241
242 static void
243 save_window (GString *s,
244              GdkWindow *window)
245 {
246   gint x, y, w, h;
247   GdkColor *color;
248
249   gdk_window_get_position (window, &x, &y);
250   gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
251   color = g_object_get_data (G_OBJECT (window), "color");
252   
253   g_string_append_printf (s, "%d,%d %dx%d (%d,%d,%d) %d %d\n",
254                           x, y, w, h,
255                           color->red, color->green, color->blue,
256                           window_has_impl (window),
257                           g_list_length (gdk_window_peek_children (window)));
258
259   save_children (s, window);
260 }
261
262
263 static void
264 save_children (GString *s,
265                GdkWindow *window)
266 {
267   GList *l;
268   GdkWindow *child;
269
270   for (l = g_list_reverse (gdk_window_peek_children (window));
271        l != NULL;
272        l = l->next)
273     {
274       child = l->data;
275
276       save_window (s, child);
277     }
278 }
279
280
281 static void
282 save_clicked (GtkWidget *button, 
283               gpointer data)
284 {
285   GString *s;
286   GtkWidget *dialog;
287   GFile *file;
288
289   s = g_string_new ("");
290
291   save_children (s, darea->window);
292
293   dialog = gtk_file_chooser_dialog_new ("Filename for window data",
294                                         NULL,
295                                         GTK_FILE_CHOOSER_ACTION_SAVE,
296                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
297                                         GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
298                                         NULL);
299   
300   gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
301   
302   if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
303     {
304       file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
305
306       g_file_replace_contents (file,
307                                s->str, s->len,
308                                NULL, FALSE,
309                                0, NULL, NULL, NULL);
310
311       g_object_unref (file);
312     }
313
314   gtk_widget_destroy (dialog);
315   g_string_free (s, TRUE);
316 }
317
318 static void
319 destroy_children (GdkWindow *window)
320 {
321   GList *l;
322   GdkWindow *child;
323
324   for (l = gdk_window_peek_children (window);
325        l != NULL;
326        l = l->next)
327     {
328       child = l->data;
329       
330       destroy_children (child);
331       gdk_window_destroy (child);
332     }
333 }
334
335 static char **
336 parse_window (GdkWindow *parent, char **lines)
337 {
338   int x, y, w, h, r, g, b, native, n_children;
339   GdkWindow *window;
340   GdkColor color;
341   int i;
342
343   if (*lines == NULL)
344     return lines;
345   
346   if (sscanf(*lines, "%d,%d %dx%d (%d,%d,%d) %d %d",
347              &x, &y, &w, &h, &r, &g, &b, &native, &n_children) == 9)
348     {
349       lines++;
350       color.red = r;
351       color.green = g;
352       color.blue = b;
353       window = create_window (parent, x, y, w, h, &color);
354       if (native)
355         gdk_window_set_has_native (window, TRUE);
356       
357       for (i = 0; i < n_children; i++)
358         lines = parse_window (window, lines);
359     }
360   else
361     lines++;
362   
363   return lines;
364 }
365   
366 static void
367 load_file (GFile *file)
368 {
369   char *data;
370   char **lines, **l;
371   
372   if (g_file_load_contents (file, NULL, &data, NULL, NULL, NULL))
373     {
374       destroy_children (darea->window);
375
376       lines = g_strsplit (data, "\n", -1);
377
378       l = lines;
379       while (*l != NULL)
380         l = parse_window (darea->window, l);
381     }
382
383   update_store ();
384 }
385
386 static void
387 move_window_clicked (GtkWidget *button, 
388                      gpointer data)
389 {
390   GdkWindow *window;
391   GtkDirectionType direction;
392   GList *selected, *l;
393   gint x, y;
394
395   direction = GPOINTER_TO_INT (data);
396     
397   selected = get_selected_windows ();
398
399   for (l = selected; l != NULL; l = l->next)
400     {
401       window = l->data;
402       
403       gdk_window_get_position (window, &x, &y);
404       
405       switch (direction) {
406       case GTK_DIR_UP:
407         y -= 10;
408         break;
409       case GTK_DIR_DOWN:
410         y += 10;
411         break;
412       case GTK_DIR_LEFT:
413         x -= 10;
414         break;
415       case GTK_DIR_RIGHT:
416         x += 10;
417         break;
418       default:
419         break;
420       }
421
422       gdk_window_move (window, x, y);
423     }
424
425   g_list_free (selected);
426 }
427
428 static void
429 manual_clicked (GtkWidget *button, 
430                 gpointer data)
431 {
432   GdkWindow *window;
433   GList *selected, *l;
434   int x, y, w, h;
435   GtkWidget *dialog, *table, *label, *xspin, *yspin, *wspin, *hspin;
436   
437
438   selected = get_selected_windows ();
439
440   if (selected == NULL)
441     return;
442
443   gdk_window_get_position (selected->data, &x, &y);
444   gdk_drawable_get_size (selected->data, &w, &h);
445
446   dialog = gtk_dialog_new_with_buttons ("Select new position and size",
447                                         GTK_WINDOW (main_window),
448                                         GTK_DIALOG_MODAL,
449                                         GTK_STOCK_OK, GTK_RESPONSE_OK,
450                                         NULL);
451   
452
453   table = gtk_table_new (2, 4, TRUE);
454   gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
455                       table,
456                       FALSE, FALSE,
457                       2);
458
459   
460   label = gtk_label_new ("x:");
461   gtk_table_attach_defaults (GTK_TABLE (table),
462                              label,
463                              0, 1,
464                              0, 1);
465   label = gtk_label_new ("y:");
466   gtk_table_attach_defaults (GTK_TABLE (table),
467                              label,
468                              0, 1,
469                              1, 2);
470   label = gtk_label_new ("width:");
471   gtk_table_attach_defaults (GTK_TABLE (table),
472                              label,
473                              0, 1,
474                              2, 3);
475   label = gtk_label_new ("height:");
476   gtk_table_attach_defaults (GTK_TABLE (table),
477                              label,
478                              0, 1,
479                              3, 4);
480
481   xspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
482   gtk_spin_button_set_value (GTK_SPIN_BUTTON (xspin), x);
483   gtk_table_attach_defaults (GTK_TABLE (table),
484                              xspin,
485                              1, 2,
486                              0, 1);
487   yspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
488   gtk_spin_button_set_value (GTK_SPIN_BUTTON (yspin), y);
489   gtk_table_attach_defaults (GTK_TABLE (table),
490                              yspin,
491                              1, 2,
492                              1, 2);
493   wspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
494   gtk_spin_button_set_value (GTK_SPIN_BUTTON (wspin), w);
495   gtk_table_attach_defaults (GTK_TABLE (table),
496                              wspin,
497                              1, 2,
498                              2, 3);
499   hspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
500   gtk_spin_button_set_value (GTK_SPIN_BUTTON (hspin), h);
501   gtk_table_attach_defaults (GTK_TABLE (table),
502                              hspin,
503                              1, 2,
504                              3, 4);
505   
506   gtk_widget_show_all (dialog);
507   
508   gtk_dialog_run (GTK_DIALOG (dialog));
509
510   x = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (xspin));
511   y = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (yspin));
512   w = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (wspin));
513   h = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (hspin));
514
515   gtk_widget_destroy (dialog);
516   
517   for (l = selected; l != NULL; l = l->next)
518     {
519       window = l->data;
520       
521       gdk_window_move_resize (window, x, y, w, h);
522     }
523
524   g_list_free (selected);
525 }
526
527 static void
528 scroll_window_clicked (GtkWidget *button, 
529                        gpointer data)
530 {
531   GdkWindow *window;
532   GtkDirectionType direction;
533   GList *selected, *l;
534   gint dx, dy;
535
536   direction = GPOINTER_TO_INT (data);
537     
538   selected = get_selected_windows ();
539
540   dx = 0; dy = 0;
541   switch (direction) {
542   case GTK_DIR_UP:
543     dy = 10;
544     break;
545   case GTK_DIR_DOWN:
546     dy = -10;
547     break;
548   case GTK_DIR_LEFT:
549     dx = 10;
550     break;
551   case GTK_DIR_RIGHT:
552     dx = -10;
553     break;
554   default:
555     break;
556   }
557   
558   for (l = selected; l != NULL; l = l->next)
559     {
560       window = l->data;
561
562       gdk_window_scroll (window, dx, dy);
563     }
564
565   g_list_free (selected);
566 }
567
568
569 static void
570 raise_window_clicked (GtkWidget *button, 
571                       gpointer data)
572 {
573   GList *selected, *l;
574   GdkWindow *window;
575     
576   selected = get_selected_windows ();
577
578   for (l = selected; l != NULL; l = l->next)
579     {
580       window = l->data;
581       
582       gdk_window_raise (window);
583     }
584
585   g_list_free (selected);
586   
587   update_store ();
588 }
589
590 static void
591 lower_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_lower (window);
604     }
605
606   g_list_free (selected);
607   
608   update_store ();
609 }
610
611
612 static void
613 smaller_window_clicked (GtkWidget *button, 
614                         gpointer data)
615 {
616   GList *selected, *l;
617   GdkWindow *window;
618   int w, h;
619
620   selected = get_selected_windows ();
621
622   for (l = selected; l != NULL; l = l->next)
623     {
624       window = l->data;
625       
626       gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
627       
628       w -= 10;
629       h -= 10;
630       if (w < 1)
631         w = 1;
632       if (h < 1)
633         h = 1;
634       
635       gdk_window_resize (window, w, h);
636     }
637
638   g_list_free (selected);
639 }
640
641 static void
642 larger_window_clicked (GtkWidget *button, 
643                         gpointer data)
644 {
645   GList *selected, *l;
646   GdkWindow *window;
647   int w, h;
648
649   selected = get_selected_windows ();
650
651   for (l = selected; l != NULL; l = l->next)
652     {
653       window = l->data;
654       
655       gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
656       
657       w += 10;
658       h += 10;
659       
660       gdk_window_resize (window, w, h);
661     }
662
663   g_list_free (selected);
664 }
665
666 static void
667 native_window_clicked (GtkWidget *button, 
668                         gpointer data)
669 {
670   GList *selected, *l;
671   GdkWindow *window;
672
673   selected = get_selected_windows ();
674
675   for (l = selected; l != NULL; l = l->next)
676     {
677       window = l->data;
678       
679       gdk_window_set_has_native (window, TRUE);
680     }
681   
682   g_list_free (selected);
683   
684   update_store ();
685 }
686
687 static gboolean
688 darea_button_release_event (GtkWidget *widget,
689                             GdkEventButton *event)
690 {
691   if ((event->state & GDK_CONTROL_MASK) != 0)
692     {
693       toggle_selection_window (event->window);
694     }
695   else
696     {
697       unselect_windows ();
698       select_window (event->window);
699     }
700     
701   return TRUE;
702 }
703
704 static void
705 render_window_cell (GtkTreeViewColumn *tree_column,
706                     GtkCellRenderer   *cell,
707                     GtkTreeModel      *tree_model,
708                     GtkTreeIter       *iter,
709                     gpointer           data)
710 {
711   GdkWindow *window;
712   char *name;
713
714   gtk_tree_model_get (GTK_TREE_MODEL (window_store),
715                       iter,
716                       0, &window,
717                       -1);
718
719   if (window_has_impl (window))
720       name = g_strdup_printf ("%p (native)", window);
721   else
722       name = g_strdup_printf ("%p", window);
723   g_object_set (cell,
724                 "text", name,
725                 "background-gdk", &((GdkWindowObject *)window)->bg_color,
726                 NULL);  
727 }
728
729 static void
730 add_children (GtkTreeStore *store,
731               GdkWindow *window,
732               GtkTreeIter *window_iter)
733 {
734   GList *l;
735   GtkTreeIter child_iter;
736
737   for (l = gdk_window_peek_children (window);
738        l != NULL;
739        l = l->next)
740     {
741       gtk_tree_store_append (store, &child_iter, window_iter);
742       gtk_tree_store_set (store, &child_iter,
743                           0, l->data,
744                           -1);
745
746       add_children (store, l->data, &child_iter);
747     }
748 }
749
750 static void
751 update_store (void)
752 {
753   GList *selected;
754
755   selected = get_selected_windows ();
756
757   gtk_tree_store_clear (window_store);
758
759   add_children (window_store, darea->window, NULL);
760   gtk_tree_view_expand_all (GTK_TREE_VIEW (treeview));
761
762   select_windows (selected);
763   g_list_free (selected);
764 }
765
766
767 int
768 main (int argc, char **argv)
769 {
770   GtkWidget *window, *vbox, *hbox, *frame;
771   GtkWidget *button, *scrolled, *table;
772   GtkTreeViewColumn *column;
773   GtkCellRenderer *renderer;
774   GdkColor black = {0};
775   GFile *file;
776   
777   gtk_init (&argc, &argv);
778
779   main_window = window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
780   gtk_container_set_border_width (GTK_CONTAINER (window), 0);
781
782   g_signal_connect (G_OBJECT (window), "delete-event", gtk_main_quit, NULL);
783
784   hbox = gtk_hbox_new (FALSE, 5);
785   gtk_container_add (GTK_CONTAINER (window), hbox);
786   gtk_widget_show (hbox);
787
788   frame = gtk_frame_new ("GdkWindows");
789   gtk_box_pack_start (GTK_BOX (hbox),
790                       frame,
791                       FALSE, FALSE,
792                       5);
793   gtk_widget_show (frame);
794
795   darea =  gtk_drawing_area_new ();
796   /*gtk_widget_set_double_buffered (darea, FALSE);*/
797   gtk_widget_add_events (darea, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
798   gtk_widget_set_size_request (darea, 500, 500);
799   g_signal_connect (darea, "button_release_event", 
800                     G_CALLBACK (darea_button_release_event), 
801                     NULL);
802
803   
804   gtk_container_add (GTK_CONTAINER (frame), darea);
805   gtk_widget_realize (darea);
806   gtk_widget_show (darea);
807   gtk_widget_modify_bg (darea, GTK_STATE_NORMAL,
808                         &black);
809                         
810   
811   vbox = gtk_vbox_new (FALSE, 5);
812   gtk_box_pack_start (GTK_BOX (hbox),
813                       vbox,
814                       FALSE, FALSE,
815                       5);
816   gtk_widget_show (vbox);
817
818   window_store = gtk_tree_store_new (1, GDK_TYPE_WINDOW);
819   
820   treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (window_store));
821   gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
822                                GTK_SELECTION_MULTIPLE);
823   column = gtk_tree_view_column_new ();
824   gtk_tree_view_column_set_title (column, "Window");
825   renderer = gtk_cell_renderer_text_new ();
826   gtk_tree_view_column_pack_start (column, renderer, TRUE);
827   gtk_tree_view_column_set_cell_data_func (column,
828                                            renderer,
829                                            render_window_cell,
830                                            NULL, NULL);
831
832   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
833
834
835   scrolled = gtk_scrolled_window_new (NULL, NULL);
836   gtk_widget_set_size_request (scrolled, 200, 400);
837   gtk_container_add (GTK_CONTAINER (scrolled), treeview);
838   gtk_box_pack_start (GTK_BOX (vbox),
839                       scrolled,
840                       FALSE, FALSE,
841                       5);
842   gtk_widget_show (scrolled);
843   gtk_widget_show (treeview);
844   
845   table = gtk_table_new (4, 4, TRUE);
846   gtk_box_pack_start (GTK_BOX (vbox),
847                       table,
848                       FALSE, FALSE,
849                       2);
850   gtk_widget_show (table);
851
852   button = gtk_button_new ();
853   gtk_button_set_image (GTK_BUTTON (button),
854                         gtk_image_new_from_stock (GTK_STOCK_GO_BACK,
855                                                   GTK_ICON_SIZE_BUTTON));
856   g_signal_connect (button, "clicked", 
857                     G_CALLBACK (move_window_clicked), 
858                     GINT_TO_POINTER (GTK_DIR_LEFT));
859   gtk_table_attach_defaults (GTK_TABLE (table),
860                              button,
861                              0, 1,
862                              1, 2);
863   gtk_widget_show (button);
864
865   button = gtk_button_new ();
866   gtk_button_set_image (GTK_BUTTON (button),
867                         gtk_image_new_from_stock (GTK_STOCK_GO_UP,
868                                                   GTK_ICON_SIZE_BUTTON));
869   g_signal_connect (button, "clicked", 
870                     G_CALLBACK (move_window_clicked), 
871                     GINT_TO_POINTER (GTK_DIR_UP));
872   gtk_table_attach_defaults (GTK_TABLE (table),
873                              button,
874                              1, 2,
875                              0, 1);
876   gtk_widget_show (button);
877
878   button = gtk_button_new ();
879   gtk_button_set_image (GTK_BUTTON (button),
880                         gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD,
881                                                   GTK_ICON_SIZE_BUTTON));
882   g_signal_connect (button, "clicked", 
883                     G_CALLBACK (move_window_clicked), 
884                     GINT_TO_POINTER (GTK_DIR_RIGHT));
885   gtk_table_attach_defaults (GTK_TABLE (table),
886                              button,
887                              2, 3,
888                              1, 2);
889   gtk_widget_show (button);
890
891   button = gtk_button_new ();
892   gtk_button_set_image (GTK_BUTTON (button),
893                         gtk_image_new_from_stock (GTK_STOCK_GO_DOWN,
894                                                   GTK_ICON_SIZE_BUTTON));
895   g_signal_connect (button, "clicked", 
896                     G_CALLBACK (move_window_clicked), 
897                     GINT_TO_POINTER (GTK_DIR_DOWN));
898   gtk_table_attach_defaults (GTK_TABLE (table),
899                              button,
900                              1, 2,
901                              2, 3);
902   gtk_widget_show (button);
903
904
905   button = gtk_button_new_with_label ("Raise");
906   g_signal_connect (button, "clicked", 
907                     G_CALLBACK (raise_window_clicked), 
908                     NULL);
909   gtk_table_attach_defaults (GTK_TABLE (table),
910                              button,
911                              0, 1,
912                              0, 1);
913   gtk_widget_show (button);
914
915   button = gtk_button_new_with_label ("Lower");
916   g_signal_connect (button, "clicked", 
917                     G_CALLBACK (lower_window_clicked), 
918                     NULL);
919   gtk_table_attach_defaults (GTK_TABLE (table),
920                              button,
921                              0, 1,
922                              2, 3);
923   gtk_widget_show (button);
924
925
926   button = gtk_button_new_with_label ("Smaller");
927   g_signal_connect (button, "clicked", 
928                     G_CALLBACK (smaller_window_clicked), 
929                     NULL);
930   gtk_table_attach_defaults (GTK_TABLE (table),
931                              button,
932                              2, 3,
933                              0, 1);
934   gtk_widget_show (button);
935
936   button = gtk_button_new_with_label ("Larger");
937   g_signal_connect (button, "clicked", 
938                     G_CALLBACK (larger_window_clicked), 
939                     NULL);
940   gtk_table_attach_defaults (GTK_TABLE (table),
941                              button,
942                              2, 3,
943                              2, 3);
944   gtk_widget_show (button);
945
946   button = gtk_button_new_with_label ("Native");
947   g_signal_connect (button, "clicked", 
948                     G_CALLBACK (native_window_clicked), 
949                     NULL);
950   gtk_table_attach_defaults (GTK_TABLE (table),
951                              button,
952                              1, 2,
953                              1, 2);
954   gtk_widget_show (button);
955
956
957   button = gtk_button_new_with_label ("scroll");
958   gtk_button_set_image (GTK_BUTTON (button),
959                         gtk_image_new_from_stock (GTK_STOCK_GO_UP,
960                                                   GTK_ICON_SIZE_BUTTON));
961   g_signal_connect (button, "clicked", 
962                     G_CALLBACK (scroll_window_clicked), 
963                     GINT_TO_POINTER (GTK_DIR_UP));
964   gtk_table_attach_defaults (GTK_TABLE (table),
965                              button,
966                              3, 4,
967                              0, 1);
968   gtk_widget_show (button);
969
970   button = gtk_button_new_with_label ("scroll");
971   gtk_button_set_image (GTK_BUTTON (button),
972                         gtk_image_new_from_stock (GTK_STOCK_GO_DOWN,
973                                                   GTK_ICON_SIZE_BUTTON));
974   g_signal_connect (button, "clicked", 
975                     G_CALLBACK (scroll_window_clicked), 
976                     GINT_TO_POINTER (GTK_DIR_DOWN));
977   gtk_table_attach_defaults (GTK_TABLE (table),
978                              button,
979                              3, 4,
980                              1, 2);
981   gtk_widget_show (button);
982
983   button = gtk_button_new_with_label ("Manual");
984   g_signal_connect (button, "clicked", 
985                     G_CALLBACK (manual_clicked),
986                     NULL);
987   gtk_table_attach_defaults (GTK_TABLE (table),
988                              button,
989                              3, 4,
990                              2, 3);
991   gtk_widget_show (button);
992
993   button = gtk_button_new_with_label ("Add window");
994   gtk_box_pack_start (GTK_BOX (vbox),
995                       button,
996                       FALSE, FALSE,
997                       2);
998   gtk_widget_show (button);
999   g_signal_connect (button, "clicked", 
1000                     G_CALLBACK (add_window_clicked), 
1001                     NULL);
1002   
1003   button = gtk_button_new_with_label ("Remove window");
1004   gtk_box_pack_start (GTK_BOX (vbox),
1005                       button,
1006                       FALSE, FALSE,
1007                       2);
1008   gtk_widget_show (button);
1009   g_signal_connect (button, "clicked", 
1010                     G_CALLBACK (remove_window_clicked), 
1011                     NULL);
1012
1013   button = gtk_button_new_with_label ("Save");
1014   gtk_box_pack_start (GTK_BOX (vbox),
1015                       button,
1016                       FALSE, FALSE,
1017                       2);
1018   gtk_widget_show (button);
1019   g_signal_connect (button, "clicked", 
1020                     G_CALLBACK (save_clicked), 
1021                     NULL);
1022
1023   gtk_widget_show (window);
1024
1025   if (argc == 2)
1026     {
1027       file = g_file_new_for_commandline_arg (argv[1]);
1028       load_file (file);
1029       g_object_unref (file);
1030     }
1031   
1032   gtk_main ();
1033
1034   return 0;
1035 }