From 6944c71d201e4b5448d292131128ceb826f1bcc4 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Sat, 25 Aug 2007 17:07:50 +0000 Subject: [PATCH] - Apply patch from Federico Mena Quintero to avoid tearing during scrolls and such (See http://mail.gnome.org/archives/desktop-devel-list/2007-August/msg00159. html) --- libgnomecanvas-2.19.2-avoid-tearing.patch | 304 ++++++++++++++++++++++ libgnomecanvas.spec | 11 +- 2 files changed, 314 insertions(+), 1 deletion(-) create mode 100644 libgnomecanvas-2.19.2-avoid-tearing.patch diff --git a/libgnomecanvas-2.19.2-avoid-tearing.patch b/libgnomecanvas-2.19.2-avoid-tearing.patch new file mode 100644 index 0000000..a3b9938 --- /dev/null +++ b/libgnomecanvas-2.19.2-avoid-tearing.patch @@ -0,0 +1,304 @@ +diff -up libgnomecanvas-2.19.2/libgnomecanvas/gnome-canvas.c.avoid-tearing libgnomecanvas-2.19.2/libgnomecanvas/gnome-canvas.c +--- libgnomecanvas-2.19.2/libgnomecanvas/gnome-canvas.c.avoid-tearing 2007-08-01 09:56:16.000000000 -0400 ++++ libgnomecanvas-2.19.2/libgnomecanvas/gnome-canvas.c 2007-08-25 13:03:36.000000000 -0400 +@@ -2904,11 +2904,7 @@ gnome_canvas_focus_out (GtkWidget *widge + return FALSE; + } + +-#define IMAGE_WIDTH 512 +-#define IMAGE_HEIGHT 512 +- +-#define IMAGE_WIDTH_AA 256 +-#define IMAGE_HEIGHT_AA 64 ++#define REDRAW_QUANTUM_SIZE 512 + + static void + gnome_canvas_paint_rect (GnomeCanvas *canvas, gint x0, gint y0, gint x1, gint y1) +@@ -2916,9 +2912,7 @@ gnome_canvas_paint_rect (GnomeCanvas *ca + GtkWidget *widget; + gint draw_x1, draw_y1; + gint draw_x2, draw_y2; +- gint xblock, yblock; +- guchar *px; +- GdkPixmap *pixmap; ++ gint draw_width, draw_height; + + g_return_if_fail (!canvas->need_update); + +@@ -2929,94 +2923,91 @@ gnome_canvas_paint_rect (GnomeCanvas *ca + draw_x2 = MIN (draw_x1 + GTK_WIDGET (canvas)->allocation.width, x1); + draw_y2 = MIN (draw_y1 + GTK_WIDGET (canvas)->allocation.height, y1); + +- /* As we can come from expose, we have to tile here */ +- xblock = (canvas->aa) ? IMAGE_WIDTH_AA : IMAGE_WIDTH; +- yblock = (canvas->aa) ? IMAGE_HEIGHT_AA : IMAGE_HEIGHT; +- +- px = NULL; +- pixmap = NULL; +- +- for (y0 = draw_y1; y0 < draw_y2; y0 += yblock) { +- y1 = MIN (y0 + yblock, draw_y2); +- for (x0 = draw_x1; x0 < draw_x2; x0 += xblock) { +- x1 = MIN (x0 + xblock, draw_x2); +- +- canvas->redraw_x1 = x0; +- canvas->redraw_y1 = y0; +- canvas->redraw_x2 = x1; +- canvas->redraw_y2 = y1; +- canvas->draw_xofs = x0; +- canvas->draw_yofs = y0; +- +- if (canvas->aa) { +- GnomeCanvasBuf buf; +- GdkColor *color; +- +- if (!px) px = g_new (guchar, IMAGE_WIDTH_AA * IMAGE_HEIGHT_AA * 3); +- +- buf.buf = px; +- buf.buf_rowstride = IMAGE_WIDTH_AA * 3; +- buf.rect.x0 = x0; +- buf.rect.y0 = y0; +- buf.rect.x1 = x1; +- buf.rect.y1 = y1; +- color = &widget->style->bg[GTK_STATE_NORMAL]; +- buf.bg_color = (((color->red & 0xff00) << 8) | (color->green & 0xff00) | (color->blue >> 8)); +- buf.is_bg = 1; +- buf.is_buf = 0; +- +- g_signal_emit (G_OBJECT (canvas), canvas_signals[RENDER_BACKGROUND], 0, &buf); +- +- if (canvas->root->object.flags & GNOME_CANVAS_ITEM_VISIBLE) +- (* GNOME_CANVAS_ITEM_GET_CLASS (canvas->root)->render) (canvas->root, &buf); +- +- if (buf.is_bg) { +- gdk_rgb_gc_set_foreground (canvas->pixmap_gc, buf.bg_color); +- gdk_draw_rectangle (canvas->layout.bin_window, +- canvas->pixmap_gc, +- TRUE, +- (x0 + canvas->zoom_xofs), +- (y0 + canvas->zoom_yofs), +- x1 - x0, y1 - y0); +- } else { +- gdk_draw_rgb_image_dithalign (canvas->layout.bin_window, +- canvas->pixmap_gc, +- (x0 + canvas->zoom_xofs), +- (y0 + canvas->zoom_yofs), +- x1 - x0, y1 - y0, +- canvas->dither, +- buf.buf, +- IMAGE_WIDTH_AA * 3, +- x0, y0); +- } +- } else { +- if (!pixmap) pixmap = gdk_pixmap_new (canvas->layout.bin_window, IMAGE_WIDTH, IMAGE_HEIGHT, +- gtk_widget_get_visual (widget)->depth); +- +- g_signal_emit (G_OBJECT (canvas), canvas_signals[DRAW_BACKGROUND], 0, pixmap, +- x0, y0, x1 - x0, y1 - y0); +- +- if (canvas->root->object.flags & GNOME_CANVAS_ITEM_VISIBLE) +- (* GNOME_CANVAS_ITEM_GET_CLASS ( +- canvas->root)->draw) ( +- canvas->root, pixmap, +- x0, y0, +- x1 - x0, y1 - y0); +- /* Copy the pixmap to the window and clean up */ +- +- gdk_draw_pixmap (canvas->layout.bin_window, +- canvas->pixmap_gc, +- pixmap, +- 0, 0, +- x0 + canvas->zoom_xofs, +- y0 + canvas->zoom_yofs, +- x1 - x0, y1 - y0); +- } ++ draw_width = draw_x2 - draw_x1; ++ draw_height = draw_y2 - draw_y1; ++ ++ if (draw_width < 1 || draw_height < 1) ++ return; ++ ++ canvas->redraw_x1 = draw_x1; ++ canvas->redraw_y1 = draw_y1; ++ canvas->redraw_x2 = draw_x2; ++ canvas->redraw_y2 = draw_y2; ++ canvas->draw_xofs = draw_x1; ++ canvas->draw_yofs = draw_y1; ++ ++ if (canvas->aa) { ++ GnomeCanvasBuf buf; ++ guchar *px; ++ GdkColor *color; ++ ++ px = g_new (guchar, draw_width * 3 * draw_height); ++ ++ buf.buf = px; ++ buf.buf_rowstride = draw_width * 3; ++ buf.rect.x0 = draw_x1; ++ buf.rect.y0 = draw_y1; ++ buf.rect.x1 = draw_x2; ++ buf.rect.y1 = draw_y2; ++ color = &widget->style->bg[GTK_STATE_NORMAL]; ++ buf.bg_color = (((color->red & 0xff00) << 8) | (color->green & 0xff00) | (color->blue >> 8)); ++ buf.is_bg = 1; ++ buf.is_buf = 0; ++ ++ g_signal_emit (G_OBJECT (canvas), canvas_signals[RENDER_BACKGROUND], 0, &buf); ++ ++ if (canvas->root->object.flags & GNOME_CANVAS_ITEM_VISIBLE) ++ (* GNOME_CANVAS_ITEM_GET_CLASS (canvas->root)->render) (canvas->root, &buf); ++ ++ if (buf.is_bg) { ++ gdk_rgb_gc_set_foreground (canvas->pixmap_gc, buf.bg_color); ++ gdk_draw_rectangle (canvas->layout.bin_window, ++ canvas->pixmap_gc, ++ TRUE, ++ (draw_x1 + canvas->zoom_xofs), ++ (draw_y1 + canvas->zoom_yofs), ++ draw_width, draw_height); ++ } else { ++ gdk_draw_rgb_image_dithalign (canvas->layout.bin_window, ++ canvas->pixmap_gc, ++ (draw_x1 + canvas->zoom_xofs), ++ (draw_y1 + canvas->zoom_yofs), ++ draw_width, draw_height, ++ canvas->dither, ++ buf.buf, ++ buf.buf_rowstride, ++ draw_x1, draw_y1); + } +- } + +- if (px) g_free (px); +- if (pixmap) gdk_pixmap_unref (pixmap); ++ g_free (px); ++ } else { ++ GdkPixmap *pixmap; ++ ++ pixmap = gdk_pixmap_new (canvas->layout.bin_window, ++ draw_width, draw_height, ++ gtk_widget_get_visual (widget)->depth); ++ ++ g_signal_emit (G_OBJECT (canvas), canvas_signals[DRAW_BACKGROUND], 0, pixmap, ++ draw_x1, draw_y1, draw_width, draw_height); ++ ++ if (canvas->root->object.flags & GNOME_CANVAS_ITEM_VISIBLE) ++ (* GNOME_CANVAS_ITEM_GET_CLASS (canvas->root)->draw) ( ++ canvas->root, pixmap, ++ draw_x1, draw_y1, ++ draw_width, draw_height); ++ ++ /* Copy the pixmap to the window and clean up */ ++ ++ gdk_draw_pixmap (canvas->layout.bin_window, ++ canvas->pixmap_gc, ++ pixmap, ++ 0, 0, ++ draw_x1 + canvas->zoom_xofs, ++ draw_y1 + canvas->zoom_yofs, ++ draw_width, draw_height); ++ ++ gdk_pixmap_unref (pixmap); ++ } + } + + /* Expose handler for the canvas */ +@@ -3074,48 +3065,68 @@ paint (GnomeCanvas *canvas) + { + ArtIRect *rects; + gint n_rects, i; +- +- if (canvas->aa) +- rects = art_rect_list_from_uta (canvas->redraw_area, +- IMAGE_WIDTH_AA, IMAGE_HEIGHT_AA, +- &n_rects); +- else +- rects = art_rect_list_from_uta (canvas->redraw_area, +- IMAGE_WIDTH, IMAGE_HEIGHT, +- &n_rects); ++ ArtIRect visible_rect; ++ GdkRegion *region; ++ GdkEventExpose expose_event; ++ GdkRectangle region_area; ++ ++ /* Extract big rectangles from the microtile array */ ++ ++ rects = art_rect_list_from_uta (canvas->redraw_area, ++ REDRAW_QUANTUM_SIZE, REDRAW_QUANTUM_SIZE, ++ &n_rects); + + art_uta_free (canvas->redraw_area); + canvas->redraw_area = NULL; + canvas->need_redraw = FALSE; + +- /* Send synthetic expose events */ ++ /* Turn those rectangles into a GdkRegion for exposing */ ++ ++ visible_rect.x0 = canvas->layout.hadjustment->value; ++ visible_rect.y0 = canvas->layout.vadjustment->value; ++ visible_rect.x1 = visible_rect.x0 + GTK_WIDGET (canvas)->allocation.width; ++ visible_rect.y1 = visible_rect.y0 + GTK_WIDGET (canvas)->allocation.height; ++ ++ region = gdk_region_new (); ++ + for (i = 0; i < n_rects; i++) { +- GdkEventExpose ex; +- gint x0, y0, x1, y1; ++ ArtIRect clipped; + +- x0 = MAX (canvas->layout.hadjustment->value - canvas->zoom_xofs, rects[i].x0); +- y0 = MAX (canvas->layout.vadjustment->value - canvas->zoom_yofs, rects[i].y0); +- x1 = MIN (x0 + GTK_WIDGET (canvas)->allocation.width, rects[i].x1); +- y1 = MIN (y0 + GTK_WIDGET (canvas)->allocation.height, rects[i].y1); +- +- if ((x0 < x1) && (y0 < y1)) { +- /* Here we are - whatever type is canvas, we have to send synthetic expose to layout (Lauris) */ +- ex.type = GDK_EXPOSE; +- ex.window = canvas->layout.bin_window; +- ex.send_event = TRUE; +- ex.area.x = x0 + canvas->zoom_xofs; +- ex.area.y = y0 + canvas->zoom_yofs; +- ex.area.width = x1 - x0; +- ex.area.height = y1 - y0; +- ex.region = gdk_region_rectangle (&ex.area); +- ex.count = 0; +- gtk_widget_send_expose (GTK_WIDGET (canvas), (GdkEvent *) &ex); +- gdk_region_destroy (ex.region); ++ art_irect_intersect (&clipped, &visible_rect, rects + i); ++ if (!art_irect_empty (&clipped)) { ++ GdkRectangle gdkrect; ++ ++ gdkrect.x = clipped.x0; ++ gdkrect.y = clipped.y0; ++ gdkrect.width = clipped.x1 - clipped.x0; ++ gdkrect.height = clipped.y1 - clipped.y0; ++ ++ gdk_region_union_with_rect (region, &gdkrect); + } + } + + art_free (rects); + ++ /* Expose! */ ++ ++ gdk_region_get_clipbox (region, ®ion_area); ++ ++ expose_event.type = GDK_EXPOSE; ++ expose_event.window = canvas->layout.bin_window; ++ expose_event.send_event = TRUE; ++ expose_event.area.x = region_area.x; ++ expose_event.area.y = region_area.y; ++ expose_event.area.width = region_area.width; ++ expose_event.area.height = region_area.height; ++ expose_event.region = region; ++ expose_event.count = 0; ++ ++ gdk_window_begin_paint_region (canvas->layout.bin_window, region); ++ gtk_widget_send_expose (GTK_WIDGET (canvas), (GdkEvent *) &expose_event); ++ gdk_window_end_paint (canvas->layout.bin_window); ++ ++ gdk_region_destroy (region); ++ + canvas->redraw_x1 = 0; + canvas->redraw_y1 = 0; + canvas->redraw_x2 = 0; diff --git a/libgnomecanvas.spec b/libgnomecanvas.spec index b029d79..afbf5e0 100644 --- a/libgnomecanvas.spec +++ b/libgnomecanvas.spec @@ -8,7 +8,7 @@ Summary: GnomeCanvas widget Name: libgnomecanvas Version: 2.19.2 -Release: 1%{?dist} +Release: 2%{?dist} URL: http://www.gnome.org/ Source0: http://download.gnome.org/sources/libgnomecanvas/2.19/%{name}-%{version}.tar.bz2 License: LGPLv2+ @@ -22,6 +22,9 @@ BuildRequires: gail-devel >= %{gail_version} BuildRequires: libtool gettext BuildRequires: perl(XML::Parser) +# http://mail.gnome.org/archives/desktop-devel-list/2007-August/msg00159.html +Patch0: libgnomecanvas-2.19.2-avoid-tearing.patch + %description The canvas widget allows you to create custom displays using stock items such as circles, lines, text, and so on. It was originally a port of the @@ -47,6 +50,7 @@ Tk canvas widget but has evolved quite a bit over time. %prep %setup -q +%patch0 -p1 -b .avoid-tearing %build export CFLAGS=$(echo $RPM_OPT_FLAGS |sed -e 's/O2/O1/g') @@ -87,6 +91,11 @@ rm -rf %{buildroot} %{_datadir}/gtk-doc/html/libgnomecanvas %changelog +* Sat Aug 25 2007 Ray Strode - 2.19.2-2 +- Apply patch from Federico Mena Quintero to avoid + tearing during scrolls and such + (See http://mail.gnome.org/archives/desktop-devel-list/2007-August/msg00159.html) + * Tue Aug 14 2007 Matthias Clasen - 2.19.2-1 - Update to 2.19.2