diff -up gnome-desktop-2.28.1/libgnome-desktop/gnome-bg.c.per-monitor-background gnome-desktop-2.28.1/libgnome-desktop/gnome-bg.c --- gnome-desktop-2.28.1/libgnome-desktop/gnome-bg.c.per-monitor-background 2009-08-19 11:51:03.000000000 -0400 +++ gnome-desktop-2.28.1/libgnome-desktop/gnome-bg.c 2009-11-09 17:05:49.839583495 -0500 @@ -168,6 +168,9 @@ static gboolean get_thumb_annotations int *orig_height); /* Cache */ +static GdkPixbuf *get_pixbuf_for_size (GnomeBG *bg, + int width, + int height); static GdkPixbuf *get_pixbuf (GnomeBG *bg); static void clear_cache (GnomeBG *bg); static gboolean is_different (GnomeBG *bg, @@ -685,12 +688,13 @@ get_scaled_pixbuf (GnomeBGPlacement plac } static void -draw_image (GnomeBGPlacement placement, - GdkPixbuf *pixbuf, - GdkPixbuf *dest) +draw_image_region (GnomeBGPlacement placement, + GdkPixbuf *pixbuf, + GdkPixbuf *dest, + GdkRectangle *region) { - int dest_width = gdk_pixbuf_get_width (dest); - int dest_height = gdk_pixbuf_get_height (dest); + int dest_width = region->width; + int dest_height = region->height; int x, y, w, h; GdkPixbuf *scaled; @@ -708,7 +712,7 @@ draw_image (GnomeBGPlacement placement, case GNOME_BG_PLACEMENT_CENTERED: case GNOME_BG_PLACEMENT_FILL_SCREEN: case GNOME_BG_PLACEMENT_SCALED: - pixbuf_blend (scaled, dest, 0, 0, w, h, x, y, 1.0); + pixbuf_blend (scaled, dest, 0, 0, w, h, x + region->x, y + region->y, 1.0); break; default: g_assert_not_reached (); @@ -718,15 +722,62 @@ draw_image (GnomeBGPlacement placement, g_object_unref (scaled); } -void -gnome_bg_draw (GnomeBG *bg, GdkPixbuf *dest) +static void +draw_image (GnomeBGPlacement placement, + GdkPixbuf *pixbuf, + GdkPixbuf *dest) +{ + GdkRectangle rect; + + rect.x = 0; + rect.y = 0; + rect.width = gdk_pixbuf_get_width (dest); + rect.height = gdk_pixbuf_get_height (dest); + + draw_image_region (placement, pixbuf, dest, &rect); +} + +static void +draw_on_monitor (GnomeBG *bg, GdkPixbuf *dest, GdkRectangle *region) +{ + draw_image_region (bg->placement, get_pixbuf_for_size (bg, region->width, region->height), dest, region); +} + +static void +draw_each_monitor (GnomeBG *bg, GdkPixbuf *dest, GdkScreen *screen) +{ + if (bg->placement == GNOME_BG_PLACEMENT_TILED) { + /* don't worry about aligning on every monitor */ + draw_image (bg->placement, get_pixbuf (bg), dest); + } else { + gint num_monitors; + GdkRectangle rect; + int monitor; + + num_monitors = gdk_screen_get_n_monitors (screen); + + for (monitor = 0; monitor < num_monitors; monitor++) { + gdk_screen_get_monitor_geometry (screen, monitor, &rect); + draw_on_monitor (bg, dest, &rect); + } + } +} + +static void +draw_on_screen (GnomeBG *bg, GdkPixbuf *dest, GdkScreen *screen) { if (!bg) return; draw_color (bg, dest); - draw_image (bg->placement, get_pixbuf (bg), dest); + draw_each_monitor (bg, dest, screen); +} + +void +gnome_bg_draw (GnomeBG *bg, GdkPixbuf *dest) +{ + draw_on_screen (bg, dest, gdk_screen_get_default ()); } gboolean @@ -883,7 +934,7 @@ gnome_bg_create_pixmap (GnomeBG *bg, pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height); - gnome_bg_draw (bg, pixbuf); + draw_on_screen (bg, pixbuf, gdk_drawable_get_screen (GDK_DRAWABLE (window))); gdk_draw_pixbuf (pixmap, NULL, pixbuf, 0, 0, 0, 0, width, height, @@ -1880,13 +1931,16 @@ find_best_size (GSList *sizes, gint widt } static GdkPixbuf * -get_pixbuf (GnomeBG *bg) +get_pixbuf_for_size (GnomeBG *bg, gint best_width, gint best_height) { /* FIXME: this ref=TRUE/FALSE stuff is crazy */ - + gint width, height; guint time_until_next_change; gboolean ref = FALSE; - + + width = (best_width > 0) ? best_width : bg->last_pixmap_width; + height = (best_height > 0) ? best_height : bg->last_pixmap_height; + if (!bg->pixbuf_cache && bg->filename) { ref = TRUE; bg->file_mtime = get_mtime (bg->filename); @@ -1906,15 +1960,15 @@ get_pixbuf (GnomeBG *bg) time_until_next_change = (guint)get_slide_timeout (slide); if (slide->fixed) { FileSize *size; - size = find_best_size (slide->file1, bg->last_pixmap_width, bg->last_pixmap_height); + size = find_best_size (slide->file1, width, height); bg->pixbuf_cache = get_as_pixbuf (bg, size->file); } else { FileSize *size; GdkPixbuf *p1, *p2; - size = find_best_size (slide->file1, bg->last_pixmap_width, bg->last_pixmap_height); + size = find_best_size (slide->file1, width, height); p1 = get_as_pixbuf (bg, size->file); - size = find_best_size (slide->file2, bg->last_pixmap_width, bg->last_pixmap_height); + size = find_best_size (slide->file2, width, height); p2 = get_as_pixbuf (bg, size->file); @@ -1943,6 +1997,22 @@ get_pixbuf (GnomeBG *bg) return bg->pixbuf_cache; } +static GdkPixbuf * +get_pixbuf (GnomeBG *bg) +{ + GdkPixbuf *pixbuf; + GdkScreen *screen; + GdkRectangle rect; + + screen = gdk_screen_get_default (); + + /* default to caching the primary monitor */ + gdk_screen_get_monitor_geometry (screen, 0, &rect); + pixbuf = get_pixbuf_for_size (bg, rect.width, rect.height); + + return pixbuf; +} + static gboolean is_different (GnomeBG *bg, const char *filename)