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