Mercurial > geeqie.yaz
changeset 104:8d358a53146e
Wed Nov 8 16:59:14 2006 John Ellis <johne@verizon.net>
* pixbuf-renderer.[ch]: Give image overlays their own child GdkWindow,
and use a buffer when drawing to those windows to avoid flicker.
Scrolling with the info [I] visible in full screen is now much
smoother. Only one regression that will be fixed later: overlapping
overlays are now ugly.
author | gqview |
---|---|
date | Wed, 08 Nov 2006 22:07:26 +0000 |
parents | 61e57ef42cf8 |
children | de64a683d5d0 |
files | ChangeLog src/pixbuf-renderer.c src/pixbuf-renderer.h |
diffstat | 3 files changed, 170 insertions(+), 71 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Wed Nov 08 16:48:36 2006 +0000 +++ b/ChangeLog Wed Nov 08 22:07:26 2006 +0000 @@ -1,3 +1,11 @@ +Wed Nov 8 16:59:14 2006 John Ellis <johne@verizon.net> + + * pixbuf-renderer.[ch]: Give image overlays their own child GdkWindow, + and use a buffer when drawing to those windows to avoid flicker. + Scrolling with the info [I] visible in full screen is now much + smoother. Only one regression that will be fixed later: overlapping + overlays are now ugly. + Wed Nov 8 11:36:58 2006 John Ellis <johne@verizon.net> * format_nikon.h: For the pentax test, use tiff make instead of a magic
--- a/src/pixbuf-renderer.c Wed Nov 08 16:48:36 2006 +0000 +++ b/src/pixbuf-renderer.c Wed Nov 08 22:07:26 2006 +0000 @@ -1,6 +1,6 @@ /* * GQview - * (C) 2005 John Ellis + * (C) 2006 John Ellis * * Author: John Ellis * @@ -122,13 +122,13 @@ gint id; GdkPixbuf *pixbuf; + GdkWindow *window; gint x; gint y; gint relative; /* x,y coordinates are relative, negative values start bottom right */ - gint visible; - gint always; /* hide temporarily when scrolling */ + gint always; /* hide temporarily when scrolling (not yet implemented) */ }; enum { @@ -611,7 +611,22 @@ { if (!GTK_WIDGET_NO_WINDOW(widget)) { - pixbuf_renderer_paint(PIXBUF_RENDERER(widget), &event->area); + if (event->window != widget->window) + { + GdkRectangle area; + + gdk_window_get_position(event->window, &area.x, &area.y); + + area.x += event->area.x; + area.y += event->area.y; + area.width = event->area.width; + area.height = event->area.height; + pixbuf_renderer_paint(PIXBUF_RENDERER(widget), &area); + } + else + { + pixbuf_renderer_paint(PIXBUF_RENDERER(widget), &event->area); + } } } @@ -742,7 +757,30 @@ *------------------------------------------------------------------- */ -static void pr_overlay_draw(PixbufRenderer *pr, gint x, gint y, gint w, gint h) +static void pr_overlay_get_position(PixbufRenderer *pr, OverlayData *od, + gint *x, gint *y, gint *w, gint *h) +{ + gint px, py, pw, ph; + + pw = gdk_pixbuf_get_width(od->pixbuf); + ph = gdk_pixbuf_get_height(od->pixbuf); + px = od->x; + py = od->y; + + if (od->relative) + { + if (px < 0) px = pr->window_width - pw + px; + if (py < 0) py = pr->window_height - ph + py; + } + + if (x) *x = px; + if (y) *y = py; + if (w) *w = pw; + if (h) *h = ph; +} + +static void pr_overlay_draw(PixbufRenderer *pr, gint x, gint y, gint w, gint h, + ImageTile *it) { GtkWidget *box; GList *work; @@ -759,56 +797,75 @@ od = work->data; work = work->next; - if (!od->visible) continue; - - pw = gdk_pixbuf_get_width(od->pixbuf); - ph = gdk_pixbuf_get_height(od->pixbuf); - px = od->x; - py = od->y; - - if (od->relative) - { - if (px < 0) px = pr->window_width - pw + px; - if (py < 0) py = pr->window_height - ph + py; - } - + pr_overlay_get_position(pr, od, &px, &py, &pw, &ph); if (pr_clip_region(x, y, w, h, px, py, pw, ph, &rx, &ry, &rw, &rh)) { - gdk_draw_pixbuf(box->window, - box->style->fg_gc[GTK_WIDGET_STATE(box)], - od->pixbuf, - rx - px, ry - py, - rx, ry, rw, rh, - pr->dither_quality, rx, ry); + if (!pr->overlay_buffer) + { + pr->overlay_buffer = gdk_pixmap_new(((GtkWidget *)pr)->window, pr->tile_width, pr->tile_height, -1); + } + + if (it) + { + gdk_draw_drawable(pr->overlay_buffer, box->style->fg_gc[GTK_WIDGET_STATE(box)], + it->pixmap, + rx - (pr->x_offset + (it->x - pr->x_scroll)), + ry - (pr->y_offset + (it->y - pr->y_scroll)), + 0, 0, rw, rh); + gdk_draw_pixbuf(pr->overlay_buffer, + box->style->fg_gc[GTK_WIDGET_STATE(box)], + od->pixbuf, + rx - px, ry - py, + 0, 0, rw, rh, + pr->dither_quality, rx, ry); + gdk_draw_drawable(od->window, box->style->fg_gc[GTK_WIDGET_STATE(box)], + pr->overlay_buffer, + 0, 0, + rx - px, ry - py, rw, rh); + } + else + { + /* no ImageTile means region may be larger than our scratch buffer */ + gint sx, sy; + + for (sx = rx; sx < rx + rw; sx += pr->tile_width) + for(sy = ry; sy < ry + rh; sy += pr->tile_height) + { + gint sw, sh; + + sw = MIN(rx + rw - sx, pr->tile_width); + sh = MIN(ry + rh - sy, pr->tile_height); + + gdk_draw_rectangle(pr->overlay_buffer, + box->style->bg_gc[GTK_WIDGET_STATE(box)], TRUE, + 0, 0, sw, sh); + gdk_draw_pixbuf(pr->overlay_buffer, + box->style->fg_gc[GTK_WIDGET_STATE(box)], + od->pixbuf, + sx - px, sy - py, + 0, 0, sw, sh, + pr->dither_quality, sx, sy); + gdk_draw_drawable(od->window, box->style->fg_gc[GTK_WIDGET_STATE(box)], + pr->overlay_buffer, + 0, 0, + sx - px, sy - py, sw, sh); + } + } } } } -static void pr_overlay_queue_draw(PixbufRenderer *pr, OverlayData *od, gint hidden) +static void pr_overlay_queue_draw(PixbufRenderer *pr, OverlayData *od) { gint x, y, w, h; - gint old_vis; - - w = gdk_pixbuf_get_width(od->pixbuf); - h = gdk_pixbuf_get_height(od->pixbuf); - x = od->x; - y = od->y; - - if (od->relative) - { - if (x < 0) x = pr->window_width - w + x; - if (y < 0) y = pr->window_height - h + y; - } - + + pr_overlay_get_position(pr, od, &x, &y, &w, &h); pr_queue(pr, pr->x_scroll - pr->x_offset + x, pr->y_scroll - pr->y_offset + y, w, h, FALSE, TILE_RENDER_ALL, FALSE, FALSE); - old_vis = od->visible; - if (hidden) od->visible = FALSE; pr_border_draw(pr, x, y, w, h); - od->visible = old_vis; } static void pr_overlay_queue_all(PixbufRenderer *pr) @@ -821,7 +878,27 @@ OverlayData *od = work->data; work = work->next; - pr_overlay_queue_draw(pr, od, FALSE); + pr_overlay_queue_draw(pr, od); + } +} + +static void pr_overlay_update_sizes(PixbufRenderer *pr) +{ + GList *work; + + work = pr->overlay_list; + while (work) + { + OverlayData *od = work->data; + work = work->next; + + if (od->relative && od->window) + { + gint x, y, w, h; + + pr_overlay_get_position(pr, od, &x, &y, &w, &h); + gdk_window_move_resize(od->window, x, y, w, h); + } } } @@ -846,6 +923,9 @@ { OverlayData *od; gint id; + gint px, py, pw, ph; + GdkWindowAttr attributes; + gint attributes_mask; g_return_val_if_fail(IS_PIXBUF_RENDERER(pr), -1); g_return_val_if_fail(pixbuf != NULL, -1); @@ -860,12 +940,25 @@ od->x = x; od->y = y; od->relative = relative; - od->visible = TRUE; od->always = always; + pr_overlay_get_position(pr, od, &px, &py, &pw, &ph); + + attributes.window_type = GDK_WINDOW_CHILD; + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.width = pw; + attributes.height = ph; + attributes.event_mask = GDK_EXPOSURE_MASK; + attributes_mask = 0; + + od->window = gdk_window_new(GTK_WIDGET(pr)->window, &attributes, attributes_mask); + gdk_window_set_user_data (od->window, pr); + gdk_window_move(od->window, px, py); + gdk_window_show(od->window); + pr->overlay_list = g_list_append(pr->overlay_list, od); - pr_overlay_queue_draw(pr, od, FALSE); + pr_overlay_queue_draw(pr, od); return od->id; } @@ -875,7 +968,14 @@ pr->overlay_list = g_list_remove(pr->overlay_list, od); if (od->pixbuf) g_object_unref(G_OBJECT(od->pixbuf)); + if (od->window) gdk_window_destroy(od->window); g_free(od); + + if (!pr->overlay_list && pr->overlay_buffer) + { + g_object_unref(pr->overlay_buffer); + pr->overlay_buffer = NULL; + } } static void pr_overlay_list_clear(PixbufRenderer *pr) @@ -900,7 +1000,7 @@ if (pixbuf) { - pr_overlay_queue_draw(pr, od, TRUE); + gint px, py, pw, ph; g_object_ref(G_OBJECT(pixbuf)); g_object_unref(G_OBJECT(od->pixbuf)); @@ -909,11 +1009,13 @@ od->x = x; od->y = y; - pr_overlay_queue_draw(pr, od, FALSE); + pr_overlay_queue_draw(pr, od); + pr_overlay_get_position(pr, od, &px, &py, &pw, &ph); + gdk_window_move_resize(od->window, px, py, pw, ph); } else { - pr_overlay_queue_draw(pr, od, TRUE); + pr_overlay_queue_draw(pr, od); pr_overlay_free(pr, od); } } @@ -1109,7 +1211,7 @@ &rx, &ry, &rw, &rh)) { gdk_window_clear_area(box->window, rx, ry, rw, rh); - pr_overlay_draw(pr, rx, ry, rw, rh); + pr_overlay_draw(pr, rx, ry, rw, rh, NULL); } return; } @@ -1123,7 +1225,7 @@ &rx, &ry, &rw, &rh)) { gdk_window_clear_area(box->window, rx, ry, rw, rh); - pr_overlay_draw(pr, rx, ry, rw, rh); + pr_overlay_draw(pr, rx, ry, rw, rh, NULL); } if (pr->window_width - pr->vis_width - pr->x_offset > 0 && pr_clip_region(x, y, w, h, @@ -1132,7 +1234,7 @@ &rx, &ry, &rw, &rh)) { gdk_window_clear_area(box->window, rx, ry, rw, rh); - pr_overlay_draw(pr, rx, ry, rw, rh); + pr_overlay_draw(pr, rx, ry, rw, rh, NULL); } } if (pr->vis_height < pr->window_height) @@ -1144,7 +1246,7 @@ &rx, &ry, &rw, &rh)) { gdk_window_clear_area(box->window, rx, ry, rw, rh); - pr_overlay_draw(pr, rx, ry, rw, rh); + pr_overlay_draw(pr, rx, ry, rw, rh, NULL); } if (pr->window_height - pr->vis_height - pr->y_offset > 0 && pr_clip_region(x, y, w, h, @@ -1153,7 +1255,7 @@ &rx, &ry, &rw, &rh)) { gdk_window_clear_area(box->window, rx, ry, rw, rh); - pr_overlay_draw(pr, rx, ry, rw, rh); + pr_overlay_draw(pr, rx, ry, rw, rh, NULL); } } } @@ -2036,7 +2138,8 @@ { pr_overlay_draw(pr, pr->x_offset + (it->x - pr->x_scroll) + x, pr->y_offset + (it->y - pr->y_scroll) + y, - w, h); + w, h, + it); } } @@ -2655,6 +2758,8 @@ pr_size_clamp(pr); pr_scroll_clamp(pr); + pr_overlay_update_sizes(pr); + /* ensure scroller remains visible */ if (pr->scroller_overlay != -1) { @@ -2745,21 +2850,6 @@ pr_scroll_notify_signal(pr); - if (pr->overlay_list) - { - gint new_x, new_y; - - new_x = pr->x_scroll; - new_y = pr->y_scroll; - pr->x_scroll = old_x; - pr->y_scroll = old_y; - - pr_overlay_queue_all(pr); - - pr->x_scroll = new_x; - pr->y_scroll = new_y; - } - x_off = pr->x_scroll - old_x; y_off = pr->y_scroll - old_y; @@ -3060,7 +3150,7 @@ if (GTK_WIDGET_REALIZED(box)) { gdk_window_clear(box->window); - pr_overlay_draw(pr, 0, 0, pr->window_width, pr->window_height); + pr_overlay_draw(pr, 0, 0, pr->window_width, pr->window_height, NULL); } pr_update_signal(pr);
--- a/src/pixbuf-renderer.h Wed Nov 08 16:48:36 2006 +0000 +++ b/src/pixbuf-renderer.h Wed Nov 08 22:07:26 2006 +0000 @@ -1,6 +1,6 @@ /* * GQview - * (C) 2005 John Ellis + * (C) 2006 John Ellis * * Author: John Ellis * @@ -128,7 +128,8 @@ gint scroller_xinc; gint scroller_yinc; - GList *overlay_list; + GList *overlay_list; + GdkPixmap *overlay_buffer; }; struct _PixbufRendererClass