4 static GtkWidget *darea;
5 static GtkTreeStore *window_store = NULL;
6 static GtkWidget *treeview;
8 static void update_store (void);
10 static GtkWidget *main_window;
13 window_has_impl (GdkWindow *window)
16 w = (GdkWindowObject *)window;
17 return w->parent == NULL || w->parent->impl != w->impl;
21 create_window (GdkWindow *parent,
22 int x, int y, int w, int h,
25 GdkWindowAttr attributes;
33 attributes.height = h;
34 attributes.window_type = GDK_WINDOW_CHILD;
35 attributes.event_mask = GDK_STRUCTURE_MASK
36 | GDK_BUTTON_MOTION_MASK
37 | GDK_BUTTON_PRESS_MASK
38 | GDK_BUTTON_RELEASE_MASK
40 | GDK_ENTER_NOTIFY_MASK
41 | GDK_LEAVE_NOTIFY_MASK;
42 attributes.wclass = GDK_INPUT_OUTPUT;
44 attributes_mask = GDK_WA_X | GDK_WA_Y;
46 window = gdk_window_new (parent, &attributes, attributes_mask);
47 gdk_window_set_user_data (window, darea);
49 bg = g_new (GdkColor, 1);
54 bg->red = g_random_int_range (0, 0xffff);
55 bg->blue = g_random_int_range (0, 0xffff);
56 bg->green = g_random_int_range (0, 0xffff);;
59 gdk_rgb_find_color (gtk_widget_get_colormap (darea), bg);
60 gdk_window_set_background (window, bg);
61 g_object_set_data_full (G_OBJECT (window), "color", bg, g_free);
63 gdk_window_show (window);
69 add_window_cb (GtkTreeModel *model,
74 GList **selected = data;
77 gtk_tree_model_get (GTK_TREE_MODEL (window_store),
82 *selected = g_list_prepend (*selected, window);
86 get_selected_windows (void)
88 GtkTreeSelection *sel;
91 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
94 gtk_tree_selection_selected_foreach (sel, add_window_cb, &selected);
100 find_window_helper (GtkTreeModel *model,
103 GtkTreeIter *selected_iter)
105 GtkTreeIter child_iter;
110 gtk_tree_model_get (model, iter,
115 *selected_iter = *iter;
119 if (gtk_tree_model_iter_children (model,
123 if (find_window_helper (model, window, &child_iter, selected_iter))
126 } while (gtk_tree_model_iter_next (model, iter));
132 find_window (GdkWindow *window,
133 GtkTreeIter *window_iter)
137 if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (window_store), &iter))
140 return find_window_helper (GTK_TREE_MODEL (window_store),
147 toggle_selection_window (GdkWindow *window)
149 GtkTreeSelection *selection;
152 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
154 if (window != NULL &&
155 find_window (window, &iter))
157 if (gtk_tree_selection_iter_is_selected (selection, &iter))
158 gtk_tree_selection_unselect_iter (selection, &iter);
160 gtk_tree_selection_select_iter (selection, &iter);
165 unselect_windows (void)
167 GtkTreeSelection *selection;
169 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
171 gtk_tree_selection_unselect_all (selection);
176 select_window (GdkWindow *window)
178 GtkTreeSelection *selection;
181 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
183 if (window != NULL &&
184 find_window (window, &iter))
185 gtk_tree_selection_select_iter (selection, &iter);
189 select_windows (GList *windows)
191 GtkTreeSelection *selection;
195 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
196 gtk_tree_selection_unselect_all (selection);
198 for (l = windows; l != NULL; l = l->next)
200 if (find_window (l->data, &iter))
201 gtk_tree_selection_select_iter (selection, &iter);
206 add_window_clicked (GtkWidget *button,
212 l = get_selected_windows ();
216 parent = darea->window;
220 create_window (parent, 10, 10, 100, 100, NULL);
225 remove_window_clicked (GtkWidget *button,
230 selected = get_selected_windows ();
232 for (l = selected; l != NULL; l = l->next)
233 gdk_window_destroy (l->data);
235 g_list_free (selected);
240 static void save_children (GString *s, GdkWindow *window);
243 save_window (GString *s,
249 gdk_window_get_position (window, &x, &y);
250 gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
251 color = g_object_get_data (G_OBJECT (window), "color");
253 g_string_append_printf (s, "%d,%d %dx%d (%d,%d,%d) %d %d\n",
255 color->red, color->green, color->blue,
256 window_has_impl (window),
257 g_list_length (gdk_window_peek_children (window)));
259 save_children (s, window);
264 save_children (GString *s,
270 for (l = g_list_reverse (gdk_window_peek_children (window));
276 save_window (s, child);
282 save_clicked (GtkWidget *button,
289 s = g_string_new ("");
291 save_children (s, darea->window);
293 dialog = gtk_file_chooser_dialog_new ("Filename for window data",
295 GTK_FILE_CHOOSER_ACTION_SAVE,
296 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
297 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
300 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
302 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
304 file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
306 g_file_replace_contents (file,
309 0, NULL, NULL, NULL);
311 g_object_unref (file);
314 gtk_widget_destroy (dialog);
315 g_string_free (s, TRUE);
319 destroy_children (GdkWindow *window)
324 for (l = gdk_window_peek_children (window);
330 destroy_children (child);
331 gdk_window_destroy (child);
336 parse_window (GdkWindow *parent, char **lines)
338 int x, y, w, h, r, g, b, native, n_children;
346 if (sscanf(*lines, "%d,%d %dx%d (%d,%d,%d) %d %d",
347 &x, &y, &w, &h, &r, &g, &b, &native, &n_children) == 9)
353 window = create_window (parent, x, y, w, h, &color);
355 gdk_window_set_has_native (window, TRUE);
357 for (i = 0; i < n_children; i++)
358 lines = parse_window (window, lines);
367 load_file (GFile *file)
372 if (g_file_load_contents (file, NULL, &data, NULL, NULL, NULL))
374 destroy_children (darea->window);
376 lines = g_strsplit (data, "\n", -1);
380 l = parse_window (darea->window, l);
387 move_window_clicked (GtkWidget *button,
391 GtkDirectionType direction;
395 direction = GPOINTER_TO_INT (data);
397 selected = get_selected_windows ();
399 for (l = selected; l != NULL; l = l->next)
403 gdk_window_get_position (window, &x, &y);
422 gdk_window_move (window, x, y);
425 g_list_free (selected);
429 manual_clicked (GtkWidget *button,
435 GtkWidget *dialog, *table, *label, *xspin, *yspin, *wspin, *hspin;
438 selected = get_selected_windows ();
440 if (selected == NULL)
443 gdk_window_get_position (selected->data, &x, &y);
444 gdk_drawable_get_size (selected->data, &w, &h);
446 dialog = gtk_dialog_new_with_buttons ("Select new position and size",
447 GTK_WINDOW (main_window),
449 GTK_STOCK_OK, GTK_RESPONSE_OK,
453 table = gtk_table_new (2, 4, TRUE);
454 gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
460 label = gtk_label_new ("x:");
461 gtk_table_attach_defaults (GTK_TABLE (table),
465 label = gtk_label_new ("y:");
466 gtk_table_attach_defaults (GTK_TABLE (table),
470 label = gtk_label_new ("width:");
471 gtk_table_attach_defaults (GTK_TABLE (table),
475 label = gtk_label_new ("height:");
476 gtk_table_attach_defaults (GTK_TABLE (table),
481 xspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
482 gtk_spin_button_set_value (GTK_SPIN_BUTTON (xspin), x);
483 gtk_table_attach_defaults (GTK_TABLE (table),
487 yspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
488 gtk_spin_button_set_value (GTK_SPIN_BUTTON (yspin), y);
489 gtk_table_attach_defaults (GTK_TABLE (table),
493 wspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
494 gtk_spin_button_set_value (GTK_SPIN_BUTTON (wspin), w);
495 gtk_table_attach_defaults (GTK_TABLE (table),
499 hspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
500 gtk_spin_button_set_value (GTK_SPIN_BUTTON (hspin), h);
501 gtk_table_attach_defaults (GTK_TABLE (table),
506 gtk_widget_show_all (dialog);
508 gtk_dialog_run (GTK_DIALOG (dialog));
510 x = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (xspin));
511 y = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (yspin));
512 w = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (wspin));
513 h = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (hspin));
515 gtk_widget_destroy (dialog);
517 for (l = selected; l != NULL; l = l->next)
521 gdk_window_move_resize (window, x, y, w, h);
524 g_list_free (selected);
528 scroll_window_clicked (GtkWidget *button,
532 GtkDirectionType direction;
536 direction = GPOINTER_TO_INT (data);
538 selected = get_selected_windows ();
558 for (l = selected; l != NULL; l = l->next)
562 gdk_window_scroll (window, dx, dy);
565 g_list_free (selected);
570 raise_window_clicked (GtkWidget *button,
576 selected = get_selected_windows ();
578 for (l = selected; l != NULL; l = l->next)
582 gdk_window_raise (window);
585 g_list_free (selected);
591 lower_window_clicked (GtkWidget *button,
597 selected = get_selected_windows ();
599 for (l = selected; l != NULL; l = l->next)
603 gdk_window_lower (window);
606 g_list_free (selected);
613 smaller_window_clicked (GtkWidget *button,
620 selected = get_selected_windows ();
622 for (l = selected; l != NULL; l = l->next)
626 gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
635 gdk_window_resize (window, w, h);
638 g_list_free (selected);
642 larger_window_clicked (GtkWidget *button,
649 selected = get_selected_windows ();
651 for (l = selected; l != NULL; l = l->next)
655 gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
660 gdk_window_resize (window, w, h);
663 g_list_free (selected);
667 native_window_clicked (GtkWidget *button,
673 selected = get_selected_windows ();
675 for (l = selected; l != NULL; l = l->next)
679 gdk_window_set_has_native (window, TRUE);
682 g_list_free (selected);
688 darea_button_release_event (GtkWidget *widget,
689 GdkEventButton *event)
691 if ((event->state & GDK_CONTROL_MASK) != 0)
693 toggle_selection_window (event->window);
698 select_window (event->window);
705 render_window_cell (GtkTreeViewColumn *tree_column,
706 GtkCellRenderer *cell,
707 GtkTreeModel *tree_model,
714 gtk_tree_model_get (GTK_TREE_MODEL (window_store),
719 if (window_has_impl (window))
720 name = g_strdup_printf ("%p (native)", window);
722 name = g_strdup_printf ("%p", window);
725 "background-gdk", &((GdkWindowObject *)window)->bg_color,
730 add_children (GtkTreeStore *store,
732 GtkTreeIter *window_iter)
735 GtkTreeIter child_iter;
737 for (l = gdk_window_peek_children (window);
741 gtk_tree_store_append (store, &child_iter, window_iter);
742 gtk_tree_store_set (store, &child_iter,
746 add_children (store, l->data, &child_iter);
755 selected = get_selected_windows ();
757 gtk_tree_store_clear (window_store);
759 add_children (window_store, darea->window, NULL);
760 gtk_tree_view_expand_all (GTK_TREE_VIEW (treeview));
762 select_windows (selected);
763 g_list_free (selected);
768 main (int argc, char **argv)
770 GtkWidget *window, *vbox, *hbox, *frame;
771 GtkWidget *button, *scrolled, *table;
772 GtkTreeViewColumn *column;
773 GtkCellRenderer *renderer;
774 GdkColor black = {0};
777 gtk_init (&argc, &argv);
779 main_window = window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
780 gtk_container_set_border_width (GTK_CONTAINER (window), 0);
782 g_signal_connect (G_OBJECT (window), "delete-event", gtk_main_quit, NULL);
784 hbox = gtk_hbox_new (FALSE, 5);
785 gtk_container_add (GTK_CONTAINER (window), hbox);
786 gtk_widget_show (hbox);
788 frame = gtk_frame_new ("GdkWindows");
789 gtk_box_pack_start (GTK_BOX (hbox),
793 gtk_widget_show (frame);
795 darea = gtk_drawing_area_new ();
796 /*gtk_widget_set_double_buffered (darea, FALSE);*/
797 gtk_widget_add_events (darea, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
798 gtk_widget_set_size_request (darea, 500, 500);
799 g_signal_connect (darea, "button_release_event",
800 G_CALLBACK (darea_button_release_event),
804 gtk_container_add (GTK_CONTAINER (frame), darea);
805 gtk_widget_realize (darea);
806 gtk_widget_show (darea);
807 gtk_widget_modify_bg (darea, GTK_STATE_NORMAL,
811 vbox = gtk_vbox_new (FALSE, 5);
812 gtk_box_pack_start (GTK_BOX (hbox),
816 gtk_widget_show (vbox);
818 window_store = gtk_tree_store_new (1, GDK_TYPE_WINDOW);
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,
832 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
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),
842 gtk_widget_show (scrolled);
843 gtk_widget_show (treeview);
845 table = gtk_table_new (4, 4, TRUE);
846 gtk_box_pack_start (GTK_BOX (vbox),
850 gtk_widget_show (table);
852 button = gtk_button_new ();
853 gtk_button_set_image (GTK_BUTTON (button),
854 gtk_image_new_from_stock (GTK_STOCK_GO_BACK,
855 GTK_ICON_SIZE_BUTTON));
856 g_signal_connect (button, "clicked",
857 G_CALLBACK (move_window_clicked),
858 GINT_TO_POINTER (GTK_DIR_LEFT));
859 gtk_table_attach_defaults (GTK_TABLE (table),
863 gtk_widget_show (button);
865 button = gtk_button_new ();
866 gtk_button_set_image (GTK_BUTTON (button),
867 gtk_image_new_from_stock (GTK_STOCK_GO_UP,
868 GTK_ICON_SIZE_BUTTON));
869 g_signal_connect (button, "clicked",
870 G_CALLBACK (move_window_clicked),
871 GINT_TO_POINTER (GTK_DIR_UP));
872 gtk_table_attach_defaults (GTK_TABLE (table),
876 gtk_widget_show (button);
878 button = gtk_button_new ();
879 gtk_button_set_image (GTK_BUTTON (button),
880 gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD,
881 GTK_ICON_SIZE_BUTTON));
882 g_signal_connect (button, "clicked",
883 G_CALLBACK (move_window_clicked),
884 GINT_TO_POINTER (GTK_DIR_RIGHT));
885 gtk_table_attach_defaults (GTK_TABLE (table),
889 gtk_widget_show (button);
891 button = gtk_button_new ();
892 gtk_button_set_image (GTK_BUTTON (button),
893 gtk_image_new_from_stock (GTK_STOCK_GO_DOWN,
894 GTK_ICON_SIZE_BUTTON));
895 g_signal_connect (button, "clicked",
896 G_CALLBACK (move_window_clicked),
897 GINT_TO_POINTER (GTK_DIR_DOWN));
898 gtk_table_attach_defaults (GTK_TABLE (table),
902 gtk_widget_show (button);
905 button = gtk_button_new_with_label ("Raise");
906 g_signal_connect (button, "clicked",
907 G_CALLBACK (raise_window_clicked),
909 gtk_table_attach_defaults (GTK_TABLE (table),
913 gtk_widget_show (button);
915 button = gtk_button_new_with_label ("Lower");
916 g_signal_connect (button, "clicked",
917 G_CALLBACK (lower_window_clicked),
919 gtk_table_attach_defaults (GTK_TABLE (table),
923 gtk_widget_show (button);
926 button = gtk_button_new_with_label ("Smaller");
927 g_signal_connect (button, "clicked",
928 G_CALLBACK (smaller_window_clicked),
930 gtk_table_attach_defaults (GTK_TABLE (table),
934 gtk_widget_show (button);
936 button = gtk_button_new_with_label ("Larger");
937 g_signal_connect (button, "clicked",
938 G_CALLBACK (larger_window_clicked),
940 gtk_table_attach_defaults (GTK_TABLE (table),
944 gtk_widget_show (button);
946 button = gtk_button_new_with_label ("Native");
947 g_signal_connect (button, "clicked",
948 G_CALLBACK (native_window_clicked),
950 gtk_table_attach_defaults (GTK_TABLE (table),
954 gtk_widget_show (button);
957 button = gtk_button_new_with_label ("scroll");
958 gtk_button_set_image (GTK_BUTTON (button),
959 gtk_image_new_from_stock (GTK_STOCK_GO_UP,
960 GTK_ICON_SIZE_BUTTON));
961 g_signal_connect (button, "clicked",
962 G_CALLBACK (scroll_window_clicked),
963 GINT_TO_POINTER (GTK_DIR_UP));
964 gtk_table_attach_defaults (GTK_TABLE (table),
968 gtk_widget_show (button);
970 button = gtk_button_new_with_label ("scroll");
971 gtk_button_set_image (GTK_BUTTON (button),
972 gtk_image_new_from_stock (GTK_STOCK_GO_DOWN,
973 GTK_ICON_SIZE_BUTTON));
974 g_signal_connect (button, "clicked",
975 G_CALLBACK (scroll_window_clicked),
976 GINT_TO_POINTER (GTK_DIR_DOWN));
977 gtk_table_attach_defaults (GTK_TABLE (table),
981 gtk_widget_show (button);
983 button = gtk_button_new_with_label ("Manual");
984 g_signal_connect (button, "clicked",
985 G_CALLBACK (manual_clicked),
987 gtk_table_attach_defaults (GTK_TABLE (table),
991 gtk_widget_show (button);
993 button = gtk_button_new_with_label ("Add window");
994 gtk_box_pack_start (GTK_BOX (vbox),
998 gtk_widget_show (button);
999 g_signal_connect (button, "clicked",
1000 G_CALLBACK (add_window_clicked),
1003 button = gtk_button_new_with_label ("Remove window");
1004 gtk_box_pack_start (GTK_BOX (vbox),
1008 gtk_widget_show (button);
1009 g_signal_connect (button, "clicked",
1010 G_CALLBACK (remove_window_clicked),
1013 button = gtk_button_new_with_label ("Save");
1014 gtk_box_pack_start (GTK_BOX (vbox),
1018 gtk_widget_show (button);
1019 g_signal_connect (button, "clicked",
1020 G_CALLBACK (save_clicked),
1023 gtk_widget_show (window);
1027 file = g_file_new_for_commandline_arg (argv[1]);
1029 g_object_unref (file);