2 #ifdef GDK_WINDOWING_X11
6 static GtkWidget *darea;
7 static GtkTreeStore *window_store = NULL;
8 static GtkWidget *treeview;
10 static void update_store (void);
12 static GtkWidget *main_window;
16 create_window (GdkWindow *parent,
17 int x, int y, int w, int h,
20 GdkWindowAttr attributes;
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
35 | GDK_ENTER_NOTIFY_MASK
36 | GDK_LEAVE_NOTIFY_MASK;
37 attributes.wclass = GDK_INPUT_OUTPUT;
39 attributes_mask = GDK_WA_X | GDK_WA_Y;
41 window = gdk_window_new (parent, &attributes, attributes_mask);
42 gdk_window_set_user_data (window, darea);
44 bg = g_new (GdkColor, 1);
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);;
54 gdk_window_set_background (window, bg);
55 g_object_set_data_full (G_OBJECT (window), "color", bg, g_free);
57 gdk_window_show (window);
63 add_window_cb (GtkTreeModel *model,
68 GList **selected = data;
71 gtk_tree_model_get (GTK_TREE_MODEL (window_store),
76 *selected = g_list_prepend (*selected, window);
80 get_selected_windows (void)
82 GtkTreeSelection *sel;
85 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
88 gtk_tree_selection_selected_foreach (sel, add_window_cb, &selected);
94 find_window_helper (GtkTreeModel *model,
97 GtkTreeIter *selected_iter)
99 GtkTreeIter child_iter;
104 gtk_tree_model_get (model, iter,
109 *selected_iter = *iter;
113 if (gtk_tree_model_iter_children (model,
117 if (find_window_helper (model, window, &child_iter, selected_iter))
120 } while (gtk_tree_model_iter_next (model, iter));
126 find_window (GdkWindow *window,
127 GtkTreeIter *window_iter)
131 if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (window_store), &iter))
134 return find_window_helper (GTK_TREE_MODEL (window_store),
141 toggle_selection_window (GdkWindow *window)
143 GtkTreeSelection *selection;
146 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
148 if (window != NULL &&
149 find_window (window, &iter))
151 if (gtk_tree_selection_iter_is_selected (selection, &iter))
152 gtk_tree_selection_unselect_iter (selection, &iter);
154 gtk_tree_selection_select_iter (selection, &iter);
159 unselect_windows (void)
161 GtkTreeSelection *selection;
163 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
165 gtk_tree_selection_unselect_all (selection);
170 select_window (GdkWindow *window)
172 GtkTreeSelection *selection;
175 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
177 if (window != NULL &&
178 find_window (window, &iter))
179 gtk_tree_selection_select_iter (selection, &iter);
183 select_windows (GList *windows)
185 GtkTreeSelection *selection;
189 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
190 gtk_tree_selection_unselect_all (selection);
192 for (l = windows; l != NULL; l = l->next)
194 if (find_window (l->data, &iter))
195 gtk_tree_selection_select_iter (selection, &iter);
200 add_window_clicked (GtkWidget *button,
206 l = get_selected_windows ();
210 parent = gtk_widget_get_window (darea);
214 create_window (parent, 10, 10, 100, 100, NULL);
219 remove_window_clicked (GtkWidget *button,
224 selected = get_selected_windows ();
226 for (l = selected; l != NULL; l = l->next)
227 gdk_window_destroy (l->data);
229 g_list_free (selected);
234 static void save_children (GString *s, GdkWindow *window);
237 save_window (GString *s,
243 gdk_window_get_position (window, &x, &y);
244 color = g_object_get_data (G_OBJECT (window), "color");
246 g_string_append_printf (s, "%d,%d %dx%d (%d,%d,%d) %d %d\n",
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)));
254 save_children (s, window);
259 save_children (GString *s,
265 for (l = g_list_reverse (gdk_window_peek_children (window));
271 save_window (s, child);
277 save_clicked (GtkWidget *button,
284 s = g_string_new ("");
286 save_children (s, gtk_widget_get_window (darea));
288 dialog = gtk_file_chooser_dialog_new ("Filename for window data",
290 GTK_FILE_CHOOSER_ACTION_SAVE,
291 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
292 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
295 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
297 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
299 file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
301 g_file_replace_contents (file,
304 0, NULL, NULL, NULL);
306 g_object_unref (file);
309 gtk_widget_destroy (dialog);
310 g_string_free (s, TRUE);
314 destroy_children (GdkWindow *window)
319 for (l = gdk_window_peek_children (window);
325 destroy_children (child);
326 gdk_window_destroy (child);
331 parse_window (GdkWindow *parent, char **lines)
333 int x, y, w, h, r, g, b, native, n_children;
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)
348 window = create_window (parent, x, y, w, h, &color);
350 gdk_window_ensure_native (window);
352 for (i = 0; i < n_children; i++)
353 lines = parse_window (window, lines);
362 load_file (GFile *file)
368 if (g_file_load_contents (file, NULL, &data, NULL, NULL, NULL))
370 window = gtk_widget_get_window (darea);
372 destroy_children (window);
374 lines = g_strsplit (data, "\n", -1);
378 l = parse_window (window, l);
385 move_window_clicked (GtkWidget *button,
389 GtkDirectionType direction;
393 direction = GPOINTER_TO_INT (data);
395 selected = get_selected_windows ();
397 for (l = selected; l != NULL; l = l->next)
401 gdk_window_get_position (window, &x, &y);
420 gdk_window_move (window, x, y);
423 g_list_free (selected);
427 manual_clicked (GtkWidget *button,
433 GtkWidget *dialog, *grid, *label, *xspin, *yspin, *wspin, *hspin;
436 selected = get_selected_windows ();
438 if (selected == NULL)
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);
445 dialog = gtk_dialog_new_with_buttons ("Select new position and size",
446 GTK_WINDOW (main_window),
448 GTK_STOCK_OK, GTK_RESPONSE_OK,
452 grid = gtk_grid_new ();
453 gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
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);
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);
489 gtk_widget_show_all (dialog);
491 gtk_dialog_run (GTK_DIALOG (dialog));
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));
498 gtk_widget_destroy (dialog);
500 for (l = selected; l != NULL; l = l->next)
504 gdk_window_move_resize (window, x, y, w, h);
507 g_list_free (selected);
511 restack_clicked (GtkWidget *button,
516 selected = get_selected_windows ();
518 if (g_list_length (selected) != 2)
520 g_warning ("select two windows");
523 gdk_window_restack (selected->data,
524 selected->next->data,
525 GPOINTER_TO_INT (data));
527 g_list_free (selected);
533 scroll_window_clicked (GtkWidget *button,
537 GtkDirectionType direction;
541 direction = GPOINTER_TO_INT (data);
543 selected = get_selected_windows ();
563 for (l = selected; l != NULL; l = l->next)
567 gdk_window_scroll (window, dx, dy);
570 g_list_free (selected);
575 raise_window_clicked (GtkWidget *button,
581 selected = get_selected_windows ();
583 for (l = selected; l != NULL; l = l->next)
587 gdk_window_raise (window);
590 g_list_free (selected);
596 lower_window_clicked (GtkWidget *button,
602 selected = get_selected_windows ();
604 for (l = selected; l != NULL; l = l->next)
608 gdk_window_lower (window);
611 g_list_free (selected);
618 smaller_window_clicked (GtkWidget *button,
625 selected = get_selected_windows ();
627 for (l = selected; l != NULL; l = l->next)
631 w = gdk_window_get_width (window) - 10;
632 h = gdk_window_get_height (window) - 10;
638 gdk_window_resize (window, w, h);
641 g_list_free (selected);
645 larger_window_clicked (GtkWidget *button,
652 selected = get_selected_windows ();
654 for (l = selected; l != NULL; l = l->next)
658 w = gdk_window_get_width (window) + 10;
659 h = gdk_window_get_height (window) + 10;
661 gdk_window_resize (window, w, h);
664 g_list_free (selected);
668 native_window_clicked (GtkWidget *button,
674 selected = get_selected_windows ();
676 for (l = selected; l != NULL; l = l->next)
680 gdk_window_ensure_native (window);
683 g_list_free (selected);
689 darea_button_release_event (GtkWidget *widget,
690 GdkEventButton *event)
692 if ((event->state & GDK_CONTROL_MASK) != 0)
694 toggle_selection_window (event->window);
699 select_window (event->window);
706 render_window_cell (GtkTreeViewColumn *tree_column,
707 GtkCellRenderer *cell,
708 GtkTreeModel *tree_model,
715 gtk_tree_model_get (GTK_TREE_MODEL (window_store),
720 if (gdk_window_has_native (window))
721 name = g_strdup_printf ("%p (native)", window);
723 name = g_strdup_printf ("%p", window);
731 add_children (GtkTreeStore *store,
733 GtkTreeIter *window_iter)
736 GtkTreeIter child_iter;
738 for (l = gdk_window_peek_children (window);
742 gtk_tree_store_append (store, &child_iter, window_iter);
743 gtk_tree_store_set (store, &child_iter,
747 add_children (store, l->data, &child_iter);
756 selected = get_selected_windows ();
758 gtk_tree_store_clear (window_store);
760 add_children (window_store, gtk_widget_get_window (darea), NULL);
761 gtk_tree_view_expand_all (GTK_TREE_VIEW (treeview));
763 select_windows (selected);
764 g_list_free (selected);
769 main (int argc, char **argv)
771 GtkWidget *window, *vbox, *hbox, *frame;
772 GtkWidget *button, *scrolled, *grid;
773 GtkTreeViewColumn *column;
774 GtkCellRenderer *renderer;
775 GdkRGBA black = {0,0,0,1};
778 gtk_init (&argc, &argv);
780 main_window = window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
781 gtk_container_set_border_width (GTK_CONTAINER (window), 0);
783 g_signal_connect (G_OBJECT (window), "delete-event", gtk_main_quit, NULL);
785 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
786 gtk_container_add (GTK_CONTAINER (window), hbox);
787 gtk_widget_show (hbox);
789 frame = gtk_frame_new ("GdkWindows");
790 gtk_box_pack_start (GTK_BOX (hbox),
794 gtk_widget_show (frame);
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),
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);
811 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 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 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),
852 gtk_widget_show (grid);
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);
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);
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);
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);
895 button = gtk_button_new_with_label ("Raise");
896 g_signal_connect (button, "clicked",
897 G_CALLBACK (raise_window_clicked),
899 gtk_grid_attach (GTK_GRID (grid), button, 0, 0, 1, 1);
900 gtk_widget_show (button);
902 button = gtk_button_new_with_label ("Lower");
903 g_signal_connect (button, "clicked",
904 G_CALLBACK (lower_window_clicked),
906 gtk_grid_attach (GTK_GRID (grid), button, 0, 2, 1, 1);
907 gtk_widget_show (button);
910 button = gtk_button_new_with_label ("Smaller");
911 g_signal_connect (button, "clicked",
912 G_CALLBACK (smaller_window_clicked),
914 gtk_grid_attach (GTK_GRID (grid), button, 2, 0, 1, 1);
915 gtk_widget_show (button);
917 button = gtk_button_new_with_label ("Larger");
918 g_signal_connect (button, "clicked",
919 G_CALLBACK (larger_window_clicked),
921 gtk_grid_attach (GTK_GRID (grid), button, 2, 2, 1, 1);
922 gtk_widget_show (button);
924 button = gtk_button_new_with_label ("Native");
925 g_signal_connect (button, "clicked",
926 G_CALLBACK (native_window_clicked),
928 gtk_grid_attach (GTK_GRID (grid), button, 1, 1, 1, 1);
929 gtk_widget_show (button);
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);
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);
952 button = gtk_button_new_with_label ("Manual");
953 g_signal_connect (button, "clicked",
954 G_CALLBACK (manual_clicked),
956 gtk_grid_attach (GTK_GRID (grid), button, 3, 2, 1, 1);
957 gtk_widget_show (button);
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);
966 button = gtk_button_new_with_label ("Restack below");
967 g_signal_connect (button, "clicked",
968 G_CALLBACK (restack_clicked),
970 gtk_grid_attach (GTK_GRID (grid), button, 3, 3, 1, 1);
971 gtk_widget_show (button);
973 button = gtk_button_new_with_label ("Add window");
974 gtk_box_pack_start (GTK_BOX (vbox),
978 gtk_widget_show (button);
979 g_signal_connect (button, "clicked",
980 G_CALLBACK (add_window_clicked),
983 button = gtk_button_new_with_label ("Remove window");
984 gtk_box_pack_start (GTK_BOX (vbox),
988 gtk_widget_show (button);
989 g_signal_connect (button, "clicked",
990 G_CALLBACK (remove_window_clicked),
993 button = gtk_button_new_with_label ("Save");
994 gtk_box_pack_start (GTK_BOX (vbox),
998 gtk_widget_show (button);
999 g_signal_connect (button, "clicked",
1000 G_CALLBACK (save_clicked),
1003 gtk_widget_show (window);
1007 file = g_file_new_for_commandline_arg (argv[1]);
1009 g_object_unref (file);