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 (GdkRGBA, 1);
49 bg->red = g_random_double ();
50 bg->blue = g_random_double ();
51 bg->green = g_random_double ();
55 gdk_window_set_background_rgba (window, bg);
56 g_object_set_data_full (G_OBJECT (window), "color", bg, g_free);
58 gdk_window_show (window);
64 add_window_cb (GtkTreeModel *model,
69 GList **selected = data;
72 gtk_tree_model_get (GTK_TREE_MODEL (window_store),
77 *selected = g_list_prepend (*selected, window);
81 get_selected_windows (void)
83 GtkTreeSelection *sel;
86 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
89 gtk_tree_selection_selected_foreach (sel, add_window_cb, &selected);
95 find_window_helper (GtkTreeModel *model,
98 GtkTreeIter *selected_iter)
100 GtkTreeIter child_iter;
105 gtk_tree_model_get (model, iter,
110 *selected_iter = *iter;
114 if (gtk_tree_model_iter_children (model,
118 if (find_window_helper (model, window, &child_iter, selected_iter))
121 } while (gtk_tree_model_iter_next (model, iter));
127 find_window (GdkWindow *window,
128 GtkTreeIter *window_iter)
132 if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (window_store), &iter))
135 return find_window_helper (GTK_TREE_MODEL (window_store),
142 toggle_selection_window (GdkWindow *window)
144 GtkTreeSelection *selection;
147 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
149 if (window != NULL &&
150 find_window (window, &iter))
152 if (gtk_tree_selection_iter_is_selected (selection, &iter))
153 gtk_tree_selection_unselect_iter (selection, &iter);
155 gtk_tree_selection_select_iter (selection, &iter);
160 unselect_windows (void)
162 GtkTreeSelection *selection;
164 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
166 gtk_tree_selection_unselect_all (selection);
171 select_window (GdkWindow *window)
173 GtkTreeSelection *selection;
176 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
178 if (window != NULL &&
179 find_window (window, &iter))
180 gtk_tree_selection_select_iter (selection, &iter);
184 select_windows (GList *windows)
186 GtkTreeSelection *selection;
190 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
191 gtk_tree_selection_unselect_all (selection);
193 for (l = windows; l != NULL; l = l->next)
195 if (find_window (l->data, &iter))
196 gtk_tree_selection_select_iter (selection, &iter);
201 add_window_clicked (GtkWidget *button,
207 l = get_selected_windows ();
211 parent = gtk_widget_get_window (darea);
215 create_window (parent, 10, 10, 100, 100, NULL);
220 remove_window_clicked (GtkWidget *button,
225 selected = get_selected_windows ();
227 for (l = selected; l != NULL; l = l->next)
228 gdk_window_destroy (l->data);
230 g_list_free (selected);
235 static void save_children (GString *s, GdkWindow *window);
238 save_window (GString *s,
244 gdk_window_get_position (window, &x, &y);
245 color = g_object_get_data (G_OBJECT (window), "color");
247 g_string_append_printf (s, "%d,%d %dx%d (%f,%f,%f,%f) %d %d\n",
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)));
255 save_children (s, window);
260 save_children (GString *s,
266 for (l = g_list_reverse (gdk_window_peek_children (window));
272 save_window (s, child);
278 refresh_clicked (GtkWidget *button,
281 gtk_widget_queue_draw (darea);
285 save_clicked (GtkWidget *button,
292 s = g_string_new ("");
294 save_children (s, gtk_widget_get_window (darea));
296 dialog = gtk_file_chooser_dialog_new ("Filename for window data",
298 GTK_FILE_CHOOSER_ACTION_SAVE,
299 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
300 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
303 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
305 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
307 file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
309 g_file_replace_contents (file,
312 0, NULL, NULL, NULL);
314 g_object_unref (file);
317 gtk_widget_destroy (dialog);
318 g_string_free (s, TRUE);
322 destroy_children (GdkWindow *window)
327 for (l = gdk_window_peek_children (window);
333 destroy_children (child);
334 gdk_window_destroy (child);
339 parse_window (GdkWindow *parent, char **lines)
341 int x, y, w, h, native, n_children;
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)
358 window = create_window (parent, x, y, w, h, &color);
360 gdk_window_ensure_native (window);
362 for (i = 0; i < n_children; i++)
363 lines = parse_window (window, lines);
372 load_file (GFile *file)
378 if (g_file_load_contents (file, NULL, &data, NULL, NULL, NULL))
380 window = gtk_widget_get_window (darea);
382 destroy_children (window);
384 lines = g_strsplit (data, "\n", -1);
388 l = parse_window (window, l);
395 move_window_clicked (GtkWidget *button,
399 GtkDirectionType direction;
403 direction = GPOINTER_TO_INT (data);
405 selected = get_selected_windows ();
407 for (l = selected; l != NULL; l = l->next)
411 gdk_window_get_position (window, &x, &y);
430 gdk_window_move (window, x, y);
433 g_list_free (selected);
437 manual_clicked (GtkWidget *button,
443 GtkWidget *dialog, *grid, *label, *xspin, *yspin, *wspin, *hspin;
446 selected = get_selected_windows ();
448 if (selected == NULL)
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);
455 dialog = gtk_dialog_new_with_buttons ("Select new position and size",
456 GTK_WINDOW (main_window),
458 GTK_STOCK_OK, GTK_RESPONSE_OK,
462 grid = gtk_grid_new ();
463 gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
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);
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);
499 gtk_widget_show_all (dialog);
501 gtk_dialog_run (GTK_DIALOG (dialog));
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));
508 gtk_widget_destroy (dialog);
510 for (l = selected; l != NULL; l = l->next)
514 gdk_window_move_resize (window, x, y, w, h);
517 g_list_free (selected);
521 restack_clicked (GtkWidget *button,
526 selected = get_selected_windows ();
528 if (g_list_length (selected) != 2)
530 g_warning ("select two windows");
533 gdk_window_restack (selected->data,
534 selected->next->data,
535 GPOINTER_TO_INT (data));
537 g_list_free (selected);
543 scroll_window_clicked (GtkWidget *button,
547 GtkDirectionType direction;
551 direction = GPOINTER_TO_INT (data);
553 selected = get_selected_windows ();
573 for (l = selected; l != NULL; l = l->next)
577 gdk_window_scroll (window, dx, dy);
580 g_list_free (selected);
585 raise_window_clicked (GtkWidget *button,
591 selected = get_selected_windows ();
593 for (l = selected; l != NULL; l = l->next)
597 gdk_window_raise (window);
600 g_list_free (selected);
606 lower_window_clicked (GtkWidget *button,
612 selected = get_selected_windows ();
614 for (l = selected; l != NULL; l = l->next)
618 gdk_window_lower (window);
621 g_list_free (selected);
628 smaller_window_clicked (GtkWidget *button,
635 selected = get_selected_windows ();
637 for (l = selected; l != NULL; l = l->next)
641 w = gdk_window_get_width (window) - 10;
642 h = gdk_window_get_height (window) - 10;
648 gdk_window_resize (window, w, h);
651 g_list_free (selected);
655 larger_window_clicked (GtkWidget *button,
662 selected = get_selected_windows ();
664 for (l = selected; l != NULL; l = l->next)
668 w = gdk_window_get_width (window) + 10;
669 h = gdk_window_get_height (window) + 10;
671 gdk_window_resize (window, w, h);
674 g_list_free (selected);
678 native_window_clicked (GtkWidget *button,
684 selected = get_selected_windows ();
686 for (l = selected; l != NULL; l = l->next)
690 gdk_window_ensure_native (window);
693 g_list_free (selected);
699 alpha_clicked (GtkWidget *button,
706 selected = get_selected_windows ();
708 for (l = selected; l != NULL; l = l->next)
712 color = g_object_get_data (G_OBJECT (window), "color");
713 if (GPOINTER_TO_INT(data) > 0)
718 if (color->alpha < 0)
720 if (color->alpha > 1)
723 gdk_window_set_background_rgba (window, color);
726 g_list_free (selected);
732 darea_button_release_event (GtkWidget *widget,
733 GdkEventButton *event)
735 if ((event->state & GDK_CONTROL_MASK) != 0)
737 toggle_selection_window (event->window);
742 select_window (event->window);
749 render_window_cell (GtkTreeViewColumn *tree_column,
750 GtkCellRenderer *cell,
751 GtkTreeModel *tree_model,
758 gtk_tree_model_get (GTK_TREE_MODEL (window_store),
763 if (gdk_window_has_native (window))
764 name = g_strdup_printf ("%p (native)", window);
766 name = g_strdup_printf ("%p", window);
774 add_children (GtkTreeStore *store,
776 GtkTreeIter *window_iter)
779 GtkTreeIter child_iter;
781 for (l = gdk_window_peek_children (window);
785 gtk_tree_store_append (store, &child_iter, window_iter);
786 gtk_tree_store_set (store, &child_iter,
790 add_children (store, l->data, &child_iter);
799 selected = get_selected_windows ();
801 gtk_tree_store_clear (window_store);
803 add_children (window_store, gtk_widget_get_window (darea), NULL);
804 gtk_tree_view_expand_all (GTK_TREE_VIEW (treeview));
806 select_windows (selected);
807 g_list_free (selected);
812 main (int argc, char **argv)
814 GtkWidget *window, *vbox, *hbox, *frame;
815 GtkWidget *button, *scrolled, *grid;
816 GtkTreeViewColumn *column;
817 GtkCellRenderer *renderer;
818 GdkRGBA black = {0,0,0,1};
821 gtk_init (&argc, &argv);
823 main_window = window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
824 gtk_container_set_border_width (GTK_CONTAINER (window), 0);
826 g_signal_connect (G_OBJECT (window), "delete-event", gtk_main_quit, NULL);
828 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
829 gtk_container_add (GTK_CONTAINER (window), hbox);
830 gtk_widget_show (hbox);
832 frame = gtk_frame_new ("GdkWindows");
833 gtk_box_pack_start (GTK_BOX (hbox),
837 gtk_widget_show (frame);
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),
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);
854 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
855 gtk_box_pack_start (GTK_BOX (hbox),
859 gtk_widget_show (vbox);
861 window_store = gtk_tree_store_new (1, GDK_TYPE_WINDOW);
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,
875 gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
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),
885 gtk_widget_show (scrolled);
886 gtk_widget_show (treeview);
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),
895 gtk_widget_show (grid);
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);
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);
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);
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);
938 button = gtk_button_new_with_label ("Raise");
939 g_signal_connect (button, "clicked",
940 G_CALLBACK (raise_window_clicked),
942 gtk_grid_attach (GTK_GRID (grid), button, 0, 0, 1, 1);
943 gtk_widget_show (button);
945 button = gtk_button_new_with_label ("Lower");
946 g_signal_connect (button, "clicked",
947 G_CALLBACK (lower_window_clicked),
949 gtk_grid_attach (GTK_GRID (grid), button, 0, 2, 1, 1);
950 gtk_widget_show (button);
953 button = gtk_button_new_with_label ("Smaller");
954 g_signal_connect (button, "clicked",
955 G_CALLBACK (smaller_window_clicked),
957 gtk_grid_attach (GTK_GRID (grid), button, 2, 0, 1, 1);
958 gtk_widget_show (button);
960 button = gtk_button_new_with_label ("Larger");
961 g_signal_connect (button, "clicked",
962 G_CALLBACK (larger_window_clicked),
964 gtk_grid_attach (GTK_GRID (grid), button, 2, 2, 1, 1);
965 gtk_widget_show (button);
967 button = gtk_button_new_with_label ("Native");
968 g_signal_connect (button, "clicked",
969 G_CALLBACK (native_window_clicked),
971 gtk_grid_attach (GTK_GRID (grid), button, 1, 1, 1, 1);
972 gtk_widget_show (button);
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);
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);
995 button = gtk_button_new_with_label ("Manual");
996 g_signal_connect (button, "clicked",
997 G_CALLBACK (manual_clicked),
999 gtk_grid_attach (GTK_GRID (grid), button, 3, 2, 1, 1);
1000 gtk_widget_show (button);
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);
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);
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);
1023 button = gtk_button_new_with_label ("Restack below");
1024 g_signal_connect (button, "clicked",
1025 G_CALLBACK (restack_clicked),
1027 gtk_grid_attach (GTK_GRID (grid), button, 3, 3, 1, 1);
1028 gtk_widget_show (button);
1030 button = gtk_button_new_with_label ("Add window");
1031 gtk_box_pack_start (GTK_BOX (vbox),
1035 gtk_widget_show (button);
1036 g_signal_connect (button, "clicked",
1037 G_CALLBACK (add_window_clicked),
1040 button = gtk_button_new_with_label ("Remove window");
1041 gtk_box_pack_start (GTK_BOX (vbox),
1045 gtk_widget_show (button);
1046 g_signal_connect (button, "clicked",
1047 G_CALLBACK (remove_window_clicked),
1050 button = gtk_button_new_with_label ("Save");
1051 gtk_box_pack_start (GTK_BOX (vbox),
1055 gtk_widget_show (button);
1056 g_signal_connect (button, "clicked",
1057 G_CALLBACK (save_clicked),
1060 button = gtk_button_new_with_label ("Refresh");
1061 gtk_box_pack_start (GTK_BOX (vbox),
1065 gtk_widget_show (button);
1066 g_signal_connect (button, "clicked",
1067 G_CALLBACK (refresh_clicked),
1071 gtk_widget_show (window);
1075 file = g_file_new_for_commandline_arg (argv[1]);
1077 g_object_unref (file);