+#undef GDK_DISABLE_DEPRECATED
#include <gtk/gtk.h>
+#ifdef GDK_WINDOWING_X11
#include <X11/Xlib.h>
+#endif
static GtkWidget *darea;
static GtkTreeStore *window_store = NULL;
static void update_store (void);
+static GtkWidget *main_window;
+
static gboolean
window_has_impl (GdkWindow *window)
{
return window;
}
-static GdkWindow *
-get_selected_window (void)
+static void
+add_window_cb (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
{
- GtkTreeSelection *sel;
- GtkTreeIter iter;
+ GList **selected = data;
GdkWindow *window;
-
- sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
- if (!gtk_tree_selection_get_selected (sel, NULL, &iter))
- return NULL;
gtk_tree_model_get (GTK_TREE_MODEL (window_store),
- &iter,
+ iter,
0, &window,
-1);
- return window;
+
+ *selected = g_list_prepend (*selected, window);
+}
+
+static GList *
+get_selected_windows (void)
+{
+ GtkTreeSelection *sel;
+ GList *selected;
+
+ sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+ selected = NULL;
+ gtk_tree_selection_selected_foreach (sel, add_window_cb, &selected);
+
+ return selected;
}
static gboolean
}
static void
-select_window (GdkWindow *window)
+toggle_selection_window (GdkWindow *window)
{
+ GtkTreeSelection *selection;
GtkTreeIter iter;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+ if (window != NULL &&
+ find_window (window, &iter))
+ {
+ if (gtk_tree_selection_iter_is_selected (selection, &iter))
+ gtk_tree_selection_unselect_iter (selection, &iter);
+ else
+ gtk_tree_selection_select_iter (selection, &iter);
+ }
+}
+
+static void
+unselect_windows (void)
+{
GtkTreeSelection *selection;
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+ gtk_tree_selection_unselect_all (selection);
+}
+
+
+static void
+select_window (GdkWindow *window)
+{
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
if (window != NULL &&
find_window (window, &iter))
gtk_tree_selection_select_iter (selection, &iter);
- else
- gtk_tree_selection_unselect_all (selection);
+}
+
+static void
+select_windows (GList *windows)
+{
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ GList *l;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+ gtk_tree_selection_unselect_all (selection);
+
+ for (l = windows; l != NULL; l = l->next)
+ {
+ if (find_window (l->data, &iter))
+ gtk_tree_selection_select_iter (selection, &iter);
+ }
}
static void
gpointer data)
{
GdkWindow *parent;
+ GList *l;
- parent = get_selected_window ();
- if (parent == NULL)
+ l = get_selected_windows ();
+ if (l != NULL)
+ parent = l->data;
+ else
parent = darea->window;
+
+ g_list_free (l);
create_window (parent, 10, 10, 100, 100, NULL);
update_store ();
}
+static void
+draw_drawable_clicked (GtkWidget *button,
+ gpointer data)
+{
+ GdkGC *gc;
+ gc = gdk_gc_new (darea->window);
+ gdk_draw_drawable (darea->window,
+ gc,
+ darea->window,
+ -15, -15,
+ 40, 70,
+ 100, 100);
+ g_object_unref (gc);
+}
+
+
static void
remove_window_clicked (GtkWidget *button,
gpointer data)
{
- GdkWindow *window;
+ GList *l, *selected;
- window = get_selected_window ();
- if (window == NULL)
- return;
+ selected = get_selected_windows ();
+
+ for (l = selected; l != NULL; l = l->next)
+ gdk_window_destroy (l->data);
+
+ g_list_free (selected);
- gdk_window_destroy (window);
+ update_store ();
}
static void save_children (GString *s, GdkWindow *window);
color.blue = b;
window = create_window (parent, x, y, w, h, &color);
if (native)
- gdk_window_set_has_native (window, TRUE);
+ gdk_window_ensure_native (window);
for (i = 0; i < n_children; i++)
lines = parse_window (window, lines);
{
GdkWindow *window;
GtkDirectionType direction;
+ GList *selected, *l;
gint x, y;
direction = GPOINTER_TO_INT (data);
- window = get_selected_window ();
+ selected = get_selected_windows ();
+
+ for (l = selected; l != NULL; l = l->next)
+ {
+ window = l->data;
+
+ gdk_window_get_position (window, &x, &y);
+
+ switch (direction) {
+ case GTK_DIR_UP:
+ y -= 10;
+ break;
+ case GTK_DIR_DOWN:
+ y += 10;
+ break;
+ case GTK_DIR_LEFT:
+ x -= 10;
+ break;
+ case GTK_DIR_RIGHT:
+ x += 10;
+ break;
+ default:
+ break;
+ }
+
+ gdk_window_move (window, x, y);
+ }
+
+ g_list_free (selected);
+}
+
+static void
+manual_clicked (GtkWidget *button,
+ gpointer data)
+{
+ GdkWindow *window;
+ GList *selected, *l;
+ int x, y, w, h;
+ GtkWidget *dialog, *table, *label, *xspin, *yspin, *wspin, *hspin;
- if (window == NULL)
+
+ selected = get_selected_windows ();
+
+ if (selected == NULL)
return;
- gdk_window_get_position (window, &x, &y);
+ gdk_window_get_position (selected->data, &x, &y);
+ gdk_drawable_get_size (selected->data, &w, &h);
+
+ dialog = gtk_dialog_new_with_buttons ("Select new position and size",
+ GTK_WINDOW (main_window),
+ GTK_DIALOG_MODAL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL);
+
+
+ table = gtk_table_new (2, 4, TRUE);
+ gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
+ table,
+ FALSE, FALSE,
+ 2);
+
+ label = gtk_label_new ("x:");
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ label,
+ 0, 1,
+ 0, 1);
+ label = gtk_label_new ("y:");
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ label,
+ 0, 1,
+ 1, 2);
+ label = gtk_label_new ("width:");
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ label,
+ 0, 1,
+ 2, 3);
+ label = gtk_label_new ("height:");
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ label,
+ 0, 1,
+ 3, 4);
+
+ xspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (xspin), x);
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ xspin,
+ 1, 2,
+ 0, 1);
+ yspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (yspin), y);
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ yspin,
+ 1, 2,
+ 1, 2);
+ wspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (wspin), w);
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ wspin,
+ 1, 2,
+ 2, 3);
+ hspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (hspin), h);
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ hspin,
+ 1, 2,
+ 3, 4);
+
+ gtk_widget_show_all (dialog);
+
+ gtk_dialog_run (GTK_DIALOG (dialog));
+
+ x = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (xspin));
+ y = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (yspin));
+ w = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (wspin));
+ h = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (hspin));
+
+ gtk_widget_destroy (dialog);
+
+ for (l = selected; l != NULL; l = l->next)
+ {
+ window = l->data;
+
+ gdk_window_move_resize (window, x, y, w, h);
+ }
+
+ g_list_free (selected);
+}
+
+static void
+restack_clicked (GtkWidget *button,
+ gpointer data)
+{
+ GList *selected;
+
+ selected = get_selected_windows ();
+
+ if (g_list_length (selected) != 2)
+ {
+ g_warning ("select two windows");
+ }
+
+ gdk_window_restack (selected->data,
+ selected->next->data,
+ GPOINTER_TO_INT (data));
+
+ g_list_free (selected);
+
+ update_store ();
+}
+
+static void
+scroll_window_clicked (GtkWidget *button,
+ gpointer data)
+{
+ GdkWindow *window;
+ GtkDirectionType direction;
+ GList *selected, *l;
+ gint dx, dy;
+
+ direction = GPOINTER_TO_INT (data);
+
+ selected = get_selected_windows ();
+
+ dx = 0; dy = 0;
switch (direction) {
case GTK_DIR_UP:
- y -= 10;
+ dy = 10;
break;
case GTK_DIR_DOWN:
- y += 10;
+ dy = -10;
break;
case GTK_DIR_LEFT:
- x -= 10;
+ dx = 10;
break;
case GTK_DIR_RIGHT:
- x += 10;
+ dx = -10;
break;
default:
break;
}
+
+ for (l = selected; l != NULL; l = l->next)
+ {
+ window = l->data;
- gdk_window_move (window, x, y);
+ gdk_window_scroll (window, dx, dy);
+ }
+
+ g_list_free (selected);
}
+
static void
raise_window_clicked (GtkWidget *button,
gpointer data)
{
+ GList *selected, *l;
GdkWindow *window;
- window = get_selected_window ();
- if (window == NULL)
- return;
+ selected = get_selected_windows ();
+
+ for (l = selected; l != NULL; l = l->next)
+ {
+ window = l->data;
+
+ gdk_window_raise (window);
+ }
- gdk_window_raise (window);
+ g_list_free (selected);
+
update_store ();
}
lower_window_clicked (GtkWidget *button,
gpointer data)
{
+ GList *selected, *l;
GdkWindow *window;
- window = get_selected_window ();
- if (window == NULL)
- return;
+ selected = get_selected_windows ();
- gdk_window_lower (window);
+ for (l = selected; l != NULL; l = l->next)
+ {
+ window = l->data;
+
+ gdk_window_lower (window);
+ }
+
+ g_list_free (selected);
+
update_store ();
}
smaller_window_clicked (GtkWidget *button,
gpointer data)
{
+ GList *selected, *l;
GdkWindow *window;
int w, h;
- window = get_selected_window ();
- if (window == NULL)
- return;
-
- gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
+ selected = get_selected_windows ();
- w -= 10;
- h -= 10;
- if (w < 1)
- w = 1;
- if (h < 1)
- h = 1;
+ for (l = selected; l != NULL; l = l->next)
+ {
+ window = l->data;
+
+ gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
+
+ w -= 10;
+ h -= 10;
+ if (w < 1)
+ w = 1;
+ if (h < 1)
+ h = 1;
+
+ gdk_window_resize (window, w, h);
+ }
- gdk_window_resize (window, w, h);
+ g_list_free (selected);
}
static void
larger_window_clicked (GtkWidget *button,
gpointer data)
{
+ GList *selected, *l;
GdkWindow *window;
int w, h;
- window = get_selected_window ();
- if (window == NULL)
- return;
-
- gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
+ selected = get_selected_windows ();
- w += 10;
- h += 10;
+ for (l = selected; l != NULL; l = l->next)
+ {
+ window = l->data;
+
+ gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
+
+ w += 10;
+ h += 10;
+
+ gdk_window_resize (window, w, h);
+ }
- gdk_window_resize (window, w, h);
+ g_list_free (selected);
}
static void
native_window_clicked (GtkWidget *button,
gpointer data)
{
+ GList *selected, *l;
GdkWindow *window;
- window = get_selected_window ();
- if (window == NULL)
- return;
+ selected = get_selected_windows ();
- gdk_window_set_has_native (window, TRUE);
+ for (l = selected; l != NULL; l = l->next)
+ {
+ window = l->data;
+
+ gdk_window_ensure_native (window);
+ }
+
+ g_list_free (selected);
+
update_store ();
}
darea_button_release_event (GtkWidget *widget,
GdkEventButton *event)
{
- select_window (event->window);
+ if ((event->state & GDK_CONTROL_MASK) != 0)
+ {
+ toggle_selection_window (event->window);
+ }
+ else
+ {
+ unselect_windows ();
+ select_window (event->window);
+ }
+
return TRUE;
}
static void
update_store (void)
{
- GdkWindow *selected;
+ GList *selected;
- selected = get_selected_window ();
+ selected = get_selected_windows ();
gtk_tree_store_clear (window_store);
add_children (window_store, darea->window, NULL);
gtk_tree_view_expand_all (GTK_TREE_VIEW (treeview));
- select_window (selected);
+ select_windows (selected);
+ g_list_free (selected);
}
gtk_init (&argc, &argv);
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ main_window = window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_container_set_border_width (GTK_CONTAINER (window), 0);
g_signal_connect (G_OBJECT (window), "delete-event", gtk_main_quit, NULL);
treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (window_store));
gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
- GTK_SELECTION_SINGLE);
+ GTK_SELECTION_MULTIPLE);
column = gtk_tree_view_column_new ();
gtk_tree_view_column_set_title (column, "Window");
renderer = gtk_cell_renderer_text_new ();
gtk_widget_show (scrolled);
gtk_widget_show (treeview);
- table = gtk_table_new (3, 3, TRUE);
+ table = gtk_table_new (5, 4, TRUE);
gtk_box_pack_start (GTK_BOX (vbox),
table,
FALSE, FALSE,
gtk_widget_show (button);
+ button = gtk_button_new_with_label ("scroll");
+ gtk_button_set_image (GTK_BUTTON (button),
+ gtk_image_new_from_stock (GTK_STOCK_GO_UP,
+ GTK_ICON_SIZE_BUTTON));
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (scroll_window_clicked),
+ GINT_TO_POINTER (GTK_DIR_UP));
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ button,
+ 3, 4,
+ 0, 1);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("scroll");
+ gtk_button_set_image (GTK_BUTTON (button),
+ gtk_image_new_from_stock (GTK_STOCK_GO_DOWN,
+ GTK_ICON_SIZE_BUTTON));
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (scroll_window_clicked),
+ GINT_TO_POINTER (GTK_DIR_DOWN));
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ button,
+ 3, 4,
+ 1, 2);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Manual");
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (manual_clicked),
+ NULL);
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ button,
+ 3, 4,
+ 2, 3);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Restack above");
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (restack_clicked),
+ GINT_TO_POINTER (1));
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ button,
+ 2, 3,
+ 3, 4);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Restack below");
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (restack_clicked),
+ 0);
+ gtk_table_attach_defaults (GTK_TABLE (table),
+ button,
+ 3, 4,
+ 3, 4);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("draw drawable");
+ gtk_box_pack_start (GTK_BOX (vbox),
+ button,
+ FALSE, FALSE,
+ 2);
+ gtk_widget_show (button);
+ g_signal_connect (button, "clicked",
+ G_CALLBACK (draw_drawable_clicked),
+ NULL);
+
button = gtk_button_new_with_label ("Add window");
gtk_box_pack_start (GTK_BOX (vbox),
button,