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