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