Re: gnome canvas sluggish with GDK_MOTION_NOTIFY



Havoc Pennington <hp redhat com> writes:

> Andrej Andrejko <ai heavy-ind com> writes:
> > 
> > I am using the gnome canvas heavily to develop a georeferencing
> > application.  I have many nested groups on the canvas and I am
> > finding that mouse movement piles up events.  The more groups I
> > have the more sluggish the mouse movement becomes.  Are there any
> > tricks I can use to speed this up?  I anticipate having as many as
> > 100 groups on the canvas at one time.
> > 
> > I am using gnome-libs 1.2.4.
> > 
> 
> Read the "scribble" example in the GTK tutorial on www.gtk.org for how
> to avoid this. (use POINTER_MOTION_HINT_MASK instead of
> POINTER_MOTION_MASK.)

This *may* help, but I am not convinced about that being the problem.

Appended is a little program that generates a metric shitload of
canvas items, all grouped recursively.  Once it starts up and does the
first repaint, mouse movement is snappy and redraws are fast.

Are you sure your items are grouped properly?  If they are, the canvas
can take very good advantage of recursive bounding boxes.

  Federico


#include <math.h>
#include <gnome.h>

#define MAX_DEPTH 14

static void
destroy_cb (GtkWidget *widget, gpointer data)
{
	gtk_main_quit ();
}

static void
exit_cb (GtkWidget *widget, gpointer data)
{
	gtk_widget_destroy (data);
}

static GnomeUIInfo file_menu[] = {
	GNOMEUIINFO_MENU_EXIT_ITEM (exit_cb, NULL),
	GNOMEUIINFO_END
};

static GnomeUIInfo main_menu[] = {
	GNOMEUIINFO_MENU_FILE_TREE (file_menu),
	GNOMEUIINFO_END
};

static void
color_to_root (GnomeCanvasItem *item, char *color)
{
	GnomeCanvasGroup *group;
	GList *children;
	GnomeCanvasItem *i;

	group = GNOME_CANVAS_GROUP (item->parent);

	while (group) {
		for (children = group->item_list; children; children = children->next) {
			i = children->data;
			if (GTK_OBJECT_TYPE (i) == gnome_canvas_line_get_type ())
				gnome_canvas_item_set (i,
						       "fill_color", color,
						       NULL);
		}

		if (group->item.parent)
			group = GNOME_CANVAS_GROUP (group->item.parent);
		else
			group = NULL;
	}
}

static gint
event (GnomeCanvasItem *item, GdkEvent *event, gpointer data)
{
	static GnomeCanvasItem *old_item;

	switch (event->type) {
	case GDK_ENTER_NOTIFY:
		if (old_item)
			color_to_root (old_item, "black");

		color_to_root (item, "green");
		old_item = item;
		break;

	case GDK_LEAVE_NOTIFY:
/*  		color_to_root (item, "black"); */
		break;

	default:
		break;
	}

	return FALSE;
}

static void
gen_tree (GnomeCanvasGroup *parent, int depth, double *dir, double width)
{
	GnomeCanvasItem *group;
	GnomeCanvasItem *item;
	GnomeCanvasPoints *points;
	double new_dir[2];
	double new_width;

	if (depth == 0)
		return;

	/* Branch */

	points = gnome_canvas_points_new (2);
	points->coords[0] = 0.0;
	points->coords[1] = 0.0;
	points->coords[2] = dir[0];
	points->coords[3] = dir[1];

	item = gnome_canvas_item_new (parent,
				      gnome_canvas_line_get_type (),
				      "points", points,
				      "fill_color", "black",
				      "width_units", width,
				      NULL);
	gtk_signal_connect (GTK_OBJECT (item), "event",
			    (GtkSignalFunc) event,
			    NULL);
	gnome_canvas_points_free (points);

	/* Group for subtrees */

	group = gnome_canvas_item_new (parent,
				       gnome_canvas_group_get_type (),
				       "x", dir[0],
				       "y", dir[1],
				       NULL);

	/* Subtrees */

	new_width = width / sqrt (2.0);

	new_dir[0] = -dir[1] / sqrt (2.0);
	new_dir[1] = dir[0] / sqrt (2.0);
	gen_tree (GNOME_CANVAS_GROUP (group), depth - 1, new_dir, new_width);

	new_dir[0] = dir[1] / sqrt (2.0);
	new_dir[1] = -dir[0] / sqrt (2.0);
	gen_tree (GNOME_CANVAS_GROUP (group), depth - 1, new_dir, new_width);
}

int
main (int argc, char **argv)
{
	GtkWidget *app;
	GtkWidget *canvas;
	double dir[2];
	double x1, y1, x2, y2;
#if 0
	GnomeCanvasPoints *points;
#endif

	gnome_init ("canvas-demo", NULL, argc, argv);

	app = gnome_app_new ("canvas-demo", "Canvas Demo");
	gnome_app_create_menus_with_data (GNOME_APP (app), main_menu, app);
	gtk_signal_connect (GTK_OBJECT (app), "destroy",
			    (GtkSignalFunc) destroy_cb,
			    NULL);

	gdk_rgb_init ();
	canvas = gnome_canvas_new ();
	gnome_app_set_contents (GNOME_APP (app), canvas);

	dir[0] = 0.0;
	dir[1] = 300.0;
	gen_tree (gnome_canvas_root (GNOME_CANVAS (canvas)), MAX_DEPTH, dir, 30.0);

	gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (canvas)),
			       gnome_canvas_ellipse_get_type (),
			       "x1", -10.0,
			       "y1", -10.0,
			       "x2", 10.0,
			       "y2", 10.0,
			       "fill_color", "red",
			       "outline_color", "black",
			       "width_pixels", 1,
			       NULL);

	gnome_canvas_item_get_bounds (GNOME_CANVAS (canvas)->root, &x1, &y1, &x2, &y2);
	gnome_canvas_set_scroll_region (GNOME_CANVAS (canvas), x1, y1, x2, y2);
	gtk_widget_set_usize (canvas, x2 - x1, y2 - y1);

	printf ("Bounds: %g %g %g %g\n", x1, y1, x2, y2);
#if 0
	points = gnome_canvas_points_new (2);
	points->coords[0] = x1;
	points->coords[1] = y1;
	points->coords[2] = x2;
	points->coords[3] = y2;
	gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (canvas)),
			       gnome_canvas_line_get_type (),
			       "points", points,
			       "fill_color", "red",
			       "width_pixels", 3,
			       NULL);

	points->coords[0] = x2;
	points->coords[1] = y1;
	points->coords[2] = x1;
	points->coords[3] = y2;
	gnome_canvas_item_new (gnome_canvas_root (GNOME_CANVAS (canvas)),
			       gnome_canvas_line_get_type (),
			       "points", points,
			       "fill_color", "red",
			       "width_pixels", 3,
			       NULL);

	gnome_canvas_points_free (points);
#endif
	gtk_widget_show_all (app);
	gtk_main ();
	return 0;
}




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]