[goocanvas] 2010-10-24 Damon Chaplin <damon gnome org>
- From: Damon Chaplin <damon src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [goocanvas] 2010-10-24 Damon Chaplin <damon gnome org>
- Date: Sun, 24 Oct 2010 14:06:44 +0000 (UTC)
commit 33649ba71d519946ff57459848b97515a98af605
Author: Damon Chaplin <damon gnome org>
Date: Sun Oct 24 14:53:52 2010 +0100
2010-10-24 Damon Chaplin <damon gnome org>
* src/goocanvas.c: updated the drawing code to work with GTK+ 3.
It seems to work now, but it still flickers when zooming in & out,
since we can't use our old trick of mapping a temporary window with
no background over it while changing the scale.
ChangeLog | 7 +++
src/goocanvas.c | 151 ++++++++++++++++++++++++++++++------------------------
2 files changed, 91 insertions(+), 67 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 8c9f7c9..fa0f8d1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2010-10-24 Damon Chaplin <damon gnome org>
+
+ * src/goocanvas.c: updated the drawing code to work with GTK+ 3.
+ It seems to work now, but it still flickers when zooming in & out,
+ since we can't use our old trick of mapping a temporary window with
+ no background over it while changing the scale.
+
2010-10-01 Damon Chaplin <damon gnome org>
* demo/*.c
diff --git a/src/goocanvas.c b/src/goocanvas.c
index ab7b0ee..749cc8c 100644
--- a/src/goocanvas.c
+++ b/src/goocanvas.c
@@ -113,6 +113,7 @@ struct _GooCanvasPrivate {
GooCanvasItem *static_root_item;
GooCanvasItemModel *static_root_item_model;
gint window_x, window_y;
+ gint static_window_x, static_window_y;
};
@@ -219,6 +220,9 @@ static void reconfigure_canvas (GooCanvas *canvas,
gboolean redraw_if_needed);
static void goo_canvas_update_automatic_bounds (GooCanvas *canvas);
+static void goo_canvas_convert_from_window_pixels (GooCanvas *canvas,
+ gdouble *x,
+ gdouble *y);
static void goo_canvas_convert_to_static_item_space (GooCanvas *canvas,
gdouble *x,
gdouble *y);
@@ -526,8 +530,8 @@ goo_canvas_init (GooCanvas *canvas)
goo_canvas_item_set_is_static (priv->static_root_item, TRUE);
priv->static_root_item_model = NULL;
- priv->window_x = 0;
- priv->window_y = 0;
+ priv->window_x = priv->static_window_x = 0;
+ priv->window_y = priv->static_window_y = 0;
}
@@ -1488,8 +1492,8 @@ goo_canvas_realize (GtkWidget *widget)
| GDK_FOCUS_CHANGE_MASK
| gtk_widget_get_events (widget);
- priv->window_x = attributes.x;
- priv->window_y = attributes.y;
+ priv->window_x = priv->static_window_x = attributes.x;
+ priv->window_y = priv->static_window_y = attributes.y;
canvas->canvas_window = gdk_window_new (window,
&attributes, attributes_mask);
@@ -1510,11 +1514,12 @@ goo_canvas_realize (GtkWidget *widget)
/* Make sure the window backgrounds aren't set, to avoid flicker when
scrolling (due to the delay between X clearing the background and
GooCanvas painting it). */
- /* TODO: Do this with GTK+ 3 too?
- gdk_window_set_back_pixmap (window, NULL, FALSE);
- gdk_window_set_back_pixmap (canvas->canvas_window, NULL, FALSE);
- gdk_window_set_back_pixmap (canvas->tmp_window, NULL, FALSE);
- */
+ /* TODO: Do this with GTK+ 3 too? */
+#if 0
+ gdk_window_set_background_pattern (window, NULL);
+ gdk_window_set_background_pattern (canvas->canvas_window, NULL);
+ gdk_window_set_background_pattern (canvas->tmp_window, NULL);
+#endif
/* Set the parent window of all the child widget items. */
tmp_list = canvas->widget_items;
@@ -1595,10 +1600,11 @@ goo_canvas_style_set (GtkWidget *widget,
/* Make sure the window backgrounds aren't set, to avoid flicker when
scrolling (due to the delay between X clearing the background and
GooCanvas painting it). */
- /* TODO: Do this with GTK+ 3 too?
- gdk_window_set_back_pixmap (gtk_widget_get_window (widget), NULL, FALSE);
- gdk_window_set_back_pixmap (GOO_CANVAS (widget)->canvas_window, NULL, FALSE);
- */
+ /* TODO: Do this with GTK+ 3 too? */
+#if 0
+ gdk_window_set_background_pattern (gtk_widget_get_window (widget), NULL);
+ gdk_window_set_background_pattern (GOO_CANVAS (widget)->canvas_window, NULL);
+#endif
}
}
@@ -1745,6 +1751,10 @@ request_static_redraw (GooCanvas *canvas,
rect.width = (double) bounds->x2 - priv->window_x - rect.x + 2 + 1;
rect.height = (double) bounds->y2 - priv->window_y - rect.y + 2 + 1;
+#if 0
+ g_print ("Invalidating rect: %i,%i %ix%i\n",
+ rect.x, rect.y, rect.width, rect.height);
+#endif
gdk_window_invalidate_rect (canvas->canvas_window, &rect, FALSE);
}
@@ -1766,8 +1776,8 @@ redraw_static_items_at_position (GooCanvas *canvas,
if (!priv->static_root_item)
return;
- window_x_copy = priv->window_x;
- window_y_copy = priv->window_y;
+ window_x_copy = priv->static_window_x;
+ window_y_copy = priv->static_window_y;
n_children = goo_canvas_item_get_n_children (priv->static_root_item);
for (i = 0; i < n_children; i++)
@@ -1781,14 +1791,14 @@ redraw_static_items_at_position (GooCanvas *canvas,
request_static_redraw (canvas, &bounds);
/* Redraw the item in its new position. */
- priv->window_x = x;
- priv->window_y = y;
+ priv->static_window_x = x;
+ priv->static_window_y = y;
gdk_window_process_updates (canvas->canvas_window, TRUE);
/* Now reset the window position. */
- priv->window_x = window_x_copy;
- priv->window_y = window_y_copy;
+ priv->static_window_x = window_x_copy;
+ priv->static_window_y = window_y_copy;
}
}
@@ -2005,9 +2015,14 @@ goo_canvas_adjustment_value_changed (GtkAdjustment *adjustment,
{
GooCanvasPrivate *priv = GOO_CANVAS_GET_PRIVATE (canvas);
AtkObject *accessible;
+ int new_window_x, new_window_y;
if (!canvas->freeze_count && gtk_widget_get_realized (GTK_WIDGET(canvas)))
{
+ /* These get truncated to ints. */
+ new_window_x = -gtk_adjustment_get_value (canvas->hadjustment);
+ new_window_y = -gtk_adjustment_get_value (canvas->vadjustment);
+
if (canvas->redraw_when_scrolled)
{
/* Map the temporary window to stop the canvas window being scrolled.
@@ -2020,18 +2035,14 @@ goo_canvas_adjustment_value_changed (GtkAdjustment *adjustment,
/* Redraw the area currently occupied by the static items. But
draw the static items in their new position. This stops them
from being "dragged" when the window is scrolled. */
- redraw_static_items_at_position (canvas,
- -gtk_adjustment_get_value (canvas->hadjustment),
- -gtk_adjustment_get_value (canvas->vadjustment));
-
- /* Move the static items to the new position. */
- priv->window_x = -gtk_adjustment_get_value (canvas->hadjustment);
- priv->window_y = -gtk_adjustment_get_value (canvas->vadjustment);
+ redraw_static_items_at_position (canvas, new_window_x, new_window_y);
}
- gdk_window_move (canvas->canvas_window,
- - gtk_adjustment_get_value (canvas->hadjustment),
- - gtk_adjustment_get_value (canvas->vadjustment));
+ /* Move the window to the new position. */
+ priv->window_x = priv->static_window_x = new_window_x;
+ priv->window_y = priv->static_window_y = new_window_y;
+
+ gdk_window_move (canvas->canvas_window, new_window_x, new_window_y);
if (canvas->redraw_when_scrolled)
{
@@ -2325,8 +2336,10 @@ goo_canvas_set_scale_internal (GooCanvas *canvas,
scrolling is unnecessary and really ugly.
FIXME: There is a possible issue with keyboard focus/input methods here,
since hidden windows can't have the keyboard focus. */
+#if 0
if (gtk_widget_get_mapped (GTK_WIDGET (canvas)))
gdk_window_show (canvas->tmp_window);
+#endif
canvas->freeze_count++;
@@ -2347,8 +2360,11 @@ goo_canvas_set_scale_internal (GooCanvas *canvas,
/* Now hide the temporary window, so the canvas window will get a draw
signal. */
+#if 0
if (gtk_widget_get_mapped (GTK_WIDGET (canvas)))
gdk_window_hide (canvas->tmp_window);
+#endif
+ gtk_widget_queue_draw (GTK_WIDGET (canvas));
}
@@ -2657,47 +2673,32 @@ goo_canvas_request_item_redraw (GooCanvas *canvas,
static void
-paint_static_items (GooCanvas *canvas,
- cairo_t *cr)
+paint_static_items (GooCanvas *canvas,
+ cairo_t *cr,
+ GooCanvasBounds *clip_bounds)
{
GooCanvasPrivate *priv = GOO_CANVAS_GET_PRIVATE (canvas);
- GooCanvasBounds static_bounds;
- double static_x_offset, static_y_offset;
- GtkWidget* widget = GTK_WIDGET (canvas);
- /* TODO: Try to use cairo's clip rect? */
- const int area_x = 0;
- const int area_y = 0;
- const int area_width = gtk_widget_get_allocated_width (widget);
- const int area_height = gtk_widget_get_allocated_height (widget);
cairo_save (cr);
cairo_identity_matrix (cr);
- static_x_offset = floor (gtk_adjustment_get_value (canvas->hadjustment));
- static_y_offset = floor (gtk_adjustment_get_value (canvas->vadjustment));
- cairo_translate (cr, static_x_offset, static_y_offset);
+ cairo_translate (cr, -priv->static_window_x, -priv->static_window_y);
/* FIXME: Uses pixels at present - use canvas units instead? */
- static_bounds.x1 = area_x - static_x_offset;
- static_bounds.y1 = area_y - static_y_offset;
- static_bounds.x2 = area_width + static_bounds.x1;
- static_bounds.y2 = area_height + static_bounds.y1;
- goo_canvas_item_paint (priv->static_root_item, cr, &static_bounds, 1.0);
+ goo_canvas_item_paint (priv->static_root_item, cr, clip_bounds, 1.0);
cairo_restore (cr);
}
static gboolean
goo_canvas_draw (GtkWidget *widget,
- cairo_t *cr)
+ cairo_t *cr)
{
GooCanvas *canvas = GOO_CANVAS (widget);
- /* TODO: Try to use cairo's clip rect? */
- const int area_x = 0;
- const int area_y = 0;
- const int area_width = gtk_widget_get_allocated_width (widget);
- const int area_height = gtk_widget_get_allocated_height (widget);
- GooCanvasBounds bounds, root_item_bounds;
+ GooCanvasBounds clip_bounds, bounds, root_item_bounds;
double x1, y1, x2, y2;
+ if (!gtk_cairo_should_draw_window (cr, canvas->canvas_window))
+ return FALSE;
+
if (!canvas->root_item)
{
canvas->before_initial_draw = FALSE;
@@ -2706,6 +2707,17 @@ goo_canvas_draw (GtkWidget *widget,
/* TODO: Need to worry about child widgets? */
+ /* The clip extents tell us which parts of the window need to be drawn,
+ in pixels, where (0,0) is the top-left of the widget window (not the
+ entire canvas window as was the case with the expose_event signal). */
+ cairo_clip_extents (cr, &clip_bounds.x1, &clip_bounds.y1,
+ &clip_bounds.x2, &clip_bounds.y2);
+
+ cairo_save (cr);
+
+ /* Get rid of the translation passed in by GTK+. We use our own. */
+ cairo_identity_matrix (cr);
+
/* Set our default drawing settins - antialias, line width. */
goo_canvas_setup_cairo_context (canvas, cr);
@@ -2719,17 +2731,16 @@ goo_canvas_draw (GtkWidget *widget,
cairo_set_source_rgb (cr, 0, 0, 0);
}
- cairo_save (cr);
-
if (canvas->need_update)
goo_canvas_update_internal (canvas, cr);
- bounds.x1 = ((area_x - canvas->canvas_x_offset) / canvas->device_to_pixels_x)
- + canvas->bounds.x1;
- bounds.y1 = ((area_y - canvas->canvas_y_offset) / canvas->device_to_pixels_y)
- + canvas->bounds.y1;
- bounds.x2 = (area_width / canvas->device_to_pixels_x) + bounds.x1;
- bounds.y2 = (area_height / canvas->device_to_pixels_y) + bounds.y1;
+ bounds = clip_bounds;
+ goo_canvas_convert_from_window_pixels (canvas, &bounds.x1, &bounds.y1);
+ goo_canvas_convert_from_window_pixels (canvas, &bounds.x2, &bounds.y2);
+
+ /* Get rid of the current clip, as it uses the wrong coordinate space.
+ FIXME: Maybe we should always set a clip with the new GTK+ drawing code. */
+ cairo_reset_clip (cr);
/* Translate it to use the canvas pixel offsets (used when the canvas is
smaller than the window and the anchor isn't set to NORTH_WEST). */
@@ -2771,11 +2782,15 @@ goo_canvas_draw (GtkWidget *widget,
cairo_clip (cr);
}
+#if 0
+ g_print ("Painting bounds: %g, %g - %g, %g\n", bounds.x1, bounds.y1,
+ bounds.x2, bounds.y2);
+#endif
goo_canvas_item_paint (canvas->root_item, cr, &bounds, canvas->scale);
cairo_restore (cr);
- paint_static_items (canvas, cr);
+ paint_static_items (canvas, cr, &clip_bounds);
GTK_WIDGET_CLASS (goo_canvas_parent_class)->draw (widget, cr);
@@ -3632,8 +3647,9 @@ goo_canvas_convert_from_window_pixels (GooCanvas *canvas,
gdouble *x,
gdouble *y)
{
- *x += gtk_adjustment_get_value (canvas->hadjustment);
- *y += gtk_adjustment_get_value (canvas->vadjustment);
+ GooCanvasPrivate *priv = GOO_CANVAS_GET_PRIVATE (canvas);
+ *x -= priv->window_x;
+ *y -= priv->window_y;
goo_canvas_convert_from_pixels (canvas, x, y);
}
@@ -3645,10 +3661,11 @@ goo_canvas_convert_to_static_item_space (GooCanvas *canvas,
gdouble *x,
gdouble *y)
{
+ GooCanvasPrivate *priv = GOO_CANVAS_GET_PRIVATE (canvas);
*x = ((*x - canvas->bounds.x1) * canvas->device_to_pixels_x)
- + canvas->canvas_x_offset - gtk_adjustment_get_value (canvas->hadjustment);
+ + canvas->canvas_x_offset + priv->window_x;
*y = ((*y - canvas->bounds.y1) * canvas->device_to_pixels_y)
- + canvas->canvas_y_offset - gtk_adjustment_get_value (canvas->vadjustment);
+ + canvas->canvas_y_offset + priv->window_y;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]