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