diff options
author | Bastien Nocera <hadess@hadess.net> | 2020-04-03 16:46:56 +0200 |
---|---|---|
committer | Bastien Nocera <hadess@hadess.net> | 2020-04-03 16:46:56 +0200 |
commit | 1d82461f1701c286cb8b199b5860a88dc7d9974d (patch) | |
tree | 81352b2af3c72bc7146d88ebb255ba9e4cec9934 | |
parent | 1eb198b9c5fc1e92cf5aa83cae2ab1a50762358f (diff) | |
download | gnome-desktop-wip/hadess/remove-gnome-bg.tar.gz |
Remove gnome-bgwip/hadess/remove-gnome-bg
It's now moved to libgnome-bg.
-rw-r--r-- | docs/reference/gnome-desktop3/gnome-desktop3-docs.sgml | 5 | ||||
-rw-r--r-- | docs/reference/gnome-desktop3/gnome-desktop3-sections.txt | 82 | ||||
-rw-r--r-- | docs/reference/gnome-desktop3/gnome-desktop3.types | 2 | ||||
-rw-r--r-- | libgnome-desktop/gnome-bg-crossfade.c | 543 | ||||
-rw-r--r-- | libgnome-desktop/gnome-bg-crossfade.h | 76 | ||||
-rw-r--r-- | libgnome-desktop/gnome-bg-slide-show.c | 839 | ||||
-rw-r--r-- | libgnome-desktop/gnome-bg-slide-show.h | 96 | ||||
-rw-r--r-- | libgnome-desktop/gnome-bg.c | 2317 | ||||
-rw-r--r-- | libgnome-desktop/gnome-bg.h | 109 | ||||
-rw-r--r-- | libgnome-desktop/meson.build | 6 |
10 files changed, 0 insertions, 4075 deletions
diff --git a/docs/reference/gnome-desktop3/gnome-desktop3-docs.sgml b/docs/reference/gnome-desktop3/gnome-desktop3-docs.sgml index e6e111e4..6ae73d3e 100644 --- a/docs/reference/gnome-desktop3/gnome-desktop3-docs.sgml +++ b/docs/reference/gnome-desktop3/gnome-desktop3-docs.sgml @@ -15,11 +15,6 @@ The libgnome-desktop library contains APIs that can be useful for a few applicat </partintro> </part> - <part id="background"> - <title>Desktop Background</title> - <xi:include href="xml/gnome-bg.xml"/> - </part> - <part id="randr"> <title>Monitor Configuration</title> <xi:include href="xml/gnome-rr.xml"/> diff --git a/docs/reference/gnome-desktop3/gnome-desktop3-sections.txt b/docs/reference/gnome-desktop3/gnome-desktop3-sections.txt index 4f189fcd..4ae40996 100644 --- a/docs/reference/gnome-desktop3/gnome-desktop3-sections.txt +++ b/docs/reference/gnome-desktop3/gnome-desktop3-sections.txt @@ -1,38 +1,4 @@ <SECTION> -<FILE>gnome-bg</FILE> -gnome_bg_new -gnome_bg_load_from_preferences -gnome_bg_save_to_preferences -gnome_bg_set_filename -gnome_bg_set_placement -gnome_bg_set_rgba -gnome_bg_get_placement -gnome_bg_get_rgba -gnome_bg_get_filename -gnome_bg_draw -gnome_bg_create_surface -gnome_bg_get_image_size -gnome_bg_create_thumbnail -gnome_bg_is_dark -gnome_bg_has_multiple_sizes -gnome_bg_changes_with_time -gnome_bg_create_frame_thumbnail -gnome_bg_set_surface_as_root -gnome_bg_set_surface_as_root_with_crossfade -gnome_bg_get_surface_from_root -GnomeBG -GnomeBGClass -<SUBSECTION Standard> -GNOME_BG -GNOME_IS_BG -GNOME_TYPE_BG -gnome_bg_get_type -GNOME_BG_CLASS -GNOME_IS_BG_CLASS -GNOME_BG_GET_CLASS -</SECTION> - -<SECTION> <FILE>gnome-desktop-thumbnail</FILE> <TITLE>GnomeDesktopThumbnailFactory</TITLE> GnomeDesktopThumbnailSize @@ -61,54 +27,6 @@ GNOME_DESKTOP_IS_THUMBNAIL_FACTORY_CLASS </SECTION> <SECTION> -<FILE>gnome-bg-crossfade</FILE> -<TITLE>GnomeBGCrossfade</TITLE> -GnomeBGCrossfade -GnomeBGCrossfadeClass -gnome_bg_crossfade_new -gnome_bg_crossfade_set_start_surface -gnome_bg_crossfade_set_end_surface -gnome_bg_crossfade_start -gnome_bg_crossfade_is_started -gnome_bg_crossfade_stop -GnomeBGCrossfadePrivate -<SUBSECTION Standard> -GNOME_BG_CROSSFADE -GNOME_IS_BG_CROSSFADE -GNOME_TYPE_BG_CROSSFADE -gnome_bg_crossfade_get_type -GNOME_BG_CROSSFADE_CLASS -GNOME_IS_BG_CROSSFADE_CLASS -GNOME_BG_CROSSFADE_GET_CLASS -</SECTION> - -<SECTION> -<FILE>gnome-bg-slide-show</FILE> -<TITLE>GnomeBGSlideShow</TITLE> -GnomeBGSlideShow -GnomeBGSlideShowClass -gnome_bg_slide_show_new -gnome_bg_slide_show_load -gnome_bg_slide_show_load_async -gnome_bg_slide_show_get_current_slide -gnome_bg_slide_show_get_has_multiple_sizes -gnome_bg_slide_show_get_num_slides -gnome_bg_slide_show_get_slide -gnome_bg_slide_show_get_start_time -gnome_bg_slide_show_get_total_duration -<SUBSECTION Standard> -GNOME_BG_SLIDE_SHOW -GNOME_BG_IS_SLIDE_SHOW -GNOME_BG_TYPE_SLIDE_SHOW -GNOME_BG_SLIDE_SHOW_CLASS -GNOME_BG_IS_SLIDE_SHOW_CLASS -GNOME_BG_SLIDE_SHOW_GET_CLASS -<SUBSECTION Private> -GnomeBGSlideShowPrivate -gnome_bg_slide_show_get_type -</SECTION> - -<SECTION> <FILE>gnome-idle-monitor</FILE> <TITLE>GnomeIdleMonitor</TITLE> GnomeIdleMonitor diff --git a/docs/reference/gnome-desktop3/gnome-desktop3.types b/docs/reference/gnome-desktop3/gnome-desktop3.types index dad5c940..11cd7085 100644 --- a/docs/reference/gnome-desktop3/gnome-desktop3.types +++ b/docs/reference/gnome-desktop3/gnome-desktop3.types @@ -1,5 +1,3 @@ -gnome_bg_crossfade_get_type -gnome_bg_get_type gnome_desktop_thumbnail_factory_get_type gnome_idle_monitor_get_type gnome_pnp_ids_get_type diff --git a/libgnome-desktop/gnome-bg-crossfade.c b/libgnome-desktop/gnome-bg-crossfade.c deleted file mode 100644 index f254b313..00000000 --- a/libgnome-desktop/gnome-bg-crossfade.c +++ /dev/null @@ -1,543 +0,0 @@ -/* gnome-bg-crossfade.h - fade window background between two surfaces - * - * Copyright (C) 2008 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - * Author: Ray Strode <rstrode@redhat.com> -*/ - -#include <string.h> -#include <math.h> -#include <stdarg.h> - -#include <gio/gio.h> - -#include <gdk/gdk.h> -#include <gtk/gtk.h> - -#include <cairo.h> - -#define GNOME_DESKTOP_USE_UNSTABLE_API -#include "gnome-bg.h" -#include "gnome-bg-crossfade.h" - -struct _GnomeBGCrossfadePrivate -{ - GdkWindow *window; - int width; - int height; - cairo_surface_t *fading_surface; - cairo_surface_t *end_surface; - gdouble start_time; - gdouble total_duration; - guint timeout_id; - guint is_first_frame : 1; -}; - -enum { - PROP_0, - PROP_WIDTH, - PROP_HEIGHT, -}; - -enum { - FINISHED, - NUMBER_OF_SIGNALS -}; - -static guint signals[NUMBER_OF_SIGNALS] = { 0 }; - -G_DEFINE_TYPE_WITH_PRIVATE (GnomeBGCrossfade, gnome_bg_crossfade, G_TYPE_OBJECT) - -static void -gnome_bg_crossfade_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - GnomeBGCrossfade *fade; - - g_assert (GNOME_IS_BG_CROSSFADE (object)); - - fade = GNOME_BG_CROSSFADE (object); - - switch (property_id) - { - case PROP_WIDTH: - fade->priv->width = g_value_get_int (value); - break; - case PROP_HEIGHT: - fade->priv->height = g_value_get_int (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -gnome_bg_crossfade_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - GnomeBGCrossfade *fade; - - g_assert (GNOME_IS_BG_CROSSFADE (object)); - - fade = GNOME_BG_CROSSFADE (object); - - switch (property_id) - { - case PROP_WIDTH: - g_value_set_int (value, fade->priv->width); - break; - case PROP_HEIGHT: - g_value_set_int (value, fade->priv->height); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -gnome_bg_crossfade_finalize (GObject *object) -{ - GnomeBGCrossfade *fade; - - fade = GNOME_BG_CROSSFADE (object); - - gnome_bg_crossfade_stop (fade); - - if (fade->priv->fading_surface != NULL) { - cairo_surface_destroy (fade->priv->fading_surface); - fade->priv->fading_surface = NULL; - } - - if (fade->priv->end_surface != NULL) { - g_object_unref (fade->priv->end_surface); - fade->priv->end_surface = NULL; - } -} - -static void -gnome_bg_crossfade_class_init (GnomeBGCrossfadeClass *fade_class) -{ - GObjectClass *gobject_class; - - gobject_class = G_OBJECT_CLASS (fade_class); - - gobject_class->get_property = gnome_bg_crossfade_get_property; - gobject_class->set_property = gnome_bg_crossfade_set_property; - gobject_class->finalize = gnome_bg_crossfade_finalize; - - /** - * GnomeBGCrossfade:width: - * - * When a crossfade is running, this is width of the fading - * surface. - */ - g_object_class_install_property (gobject_class, - PROP_WIDTH, - g_param_spec_int ("width", - "Window Width", - "Width of window to fade", - 0, G_MAXINT, 0, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); - - /** - * GnomeBGCrossfade:height: - * - * When a crossfade is running, this is height of the fading - * surface. - */ - g_object_class_install_property (gobject_class, - PROP_HEIGHT, - g_param_spec_int ("height", "Window Height", - "Height of window to fade on", - 0, G_MAXINT, 0, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); - - /** - * GnomeBGCrossfade::finished: - * @fade: the #GnomeBGCrossfade that received the signal - * @window: the #GdkWindow the crossfade happend on. - * - * When a crossfade finishes, @window will have a copy - * of the end surface as its background, and this signal will - * get emitted. - */ - signals[FINISHED] = g_signal_new ("finished", - G_OBJECT_CLASS_TYPE (gobject_class), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, G_TYPE_OBJECT); -} - -static void -gnome_bg_crossfade_init (GnomeBGCrossfade *fade) -{ - fade->priv = gnome_bg_crossfade_get_instance_private (fade); - - fade->priv->fading_surface = NULL; - fade->priv->end_surface = NULL; - fade->priv->timeout_id = 0; -} - -/** - * gnome_bg_crossfade_new: - * @width: The width of the crossfading window - * @height: The height of the crossfading window - * - * Creates a new object to manage crossfading a - * window background between two #cairo_surface_ts. - * - * Return value: the new #GnomeBGCrossfade - **/ -GnomeBGCrossfade * -gnome_bg_crossfade_new (int width, - int height) -{ - GObject *object; - - object = g_object_new (GNOME_TYPE_BG_CROSSFADE, - "width", width, - "height", height, NULL); - - return (GnomeBGCrossfade *) object; -} - -static cairo_surface_t * -tile_surface (cairo_surface_t *surface, - int width, - int height) -{ - cairo_surface_t *copy; - cairo_t *cr; - - if (surface == NULL) { - copy = gdk_window_create_similar_surface (gdk_get_default_root_window (), - CAIRO_CONTENT_COLOR, - width, height); - } else { - copy = cairo_surface_create_similar (surface, - cairo_surface_get_content (surface), - width, height); - } - - cr = cairo_create (copy); - - if (surface != NULL) { - cairo_pattern_t *pattern; - cairo_set_source_surface (cr, surface, 0.0, 0.0); - pattern = cairo_get_source (cr); - cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT); - } else { - GtkStyle *style; - style = gtk_widget_get_default_style (); - gdk_cairo_set_source_color (cr, &style->bg[GTK_STATE_NORMAL]); - } - - cairo_paint (cr); - - if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) { - cairo_surface_destroy (copy); - copy = NULL; - } - cairo_destroy (cr); - - return copy; -} - -/** - * gnome_bg_crossfade_set_start_surface: - * @fade: a #GnomeBGCrossfade - * @surface: The cairo surface to fade from - * - * Before initiating a crossfade with gnome_bg_crossfade_start() - * a start and end surface have to be set. This function sets - * the surface shown at the beginning of the crossfade effect. - * - * Return value: %TRUE if successful, or %FALSE if the surface - * could not be copied. - **/ -gboolean -gnome_bg_crossfade_set_start_surface (GnomeBGCrossfade *fade, - cairo_surface_t *surface) -{ - g_return_val_if_fail (GNOME_IS_BG_CROSSFADE (fade), FALSE); - - if (fade->priv->fading_surface != NULL) { - cairo_surface_destroy (fade->priv->fading_surface); - fade->priv->fading_surface = NULL; - } - - fade->priv->fading_surface = tile_surface (surface, - fade->priv->width, - fade->priv->height); - - return fade->priv->fading_surface != NULL; -} - -static gdouble -get_current_time (void) -{ - const double microseconds_per_second = (double) G_USEC_PER_SEC; - double timestamp; - GTimeVal now; - - g_get_current_time (&now); - - timestamp = ((microseconds_per_second * now.tv_sec) + now.tv_usec) / - microseconds_per_second; - - return timestamp; -} - -/** - * gnome_bg_crossfade_set_end_surface: - * @fade: a #GnomeBGCrossfade - * @surface: The cairo surface to fade to - * - * Before initiating a crossfade with gnome_bg_crossfade_start() - * a start and end surface have to be set. This function sets - * the surface shown at the end of the crossfade effect. - * - * Return value: %TRUE if successful, or %FALSE if the surface - * could not be copied. - **/ -gboolean -gnome_bg_crossfade_set_end_surface (GnomeBGCrossfade *fade, - cairo_surface_t *surface) -{ - g_return_val_if_fail (GNOME_IS_BG_CROSSFADE (fade), FALSE); - - if (fade->priv->end_surface != NULL) { - cairo_surface_destroy (fade->priv->end_surface); - fade->priv->end_surface = NULL; - } - - fade->priv->end_surface = tile_surface (surface, - fade->priv->width, - fade->priv->height); - - /* Reset timer in case we're called while animating - */ - fade->priv->start_time = get_current_time (); - return fade->priv->end_surface != NULL; -} - -static gboolean -animations_are_disabled (GnomeBGCrossfade *fade) -{ - GtkSettings *settings; - GdkScreen *screen; - gboolean are_enabled; - - g_assert (fade->priv->window != NULL); - - screen = gdk_window_get_screen (fade->priv->window); - - settings = gtk_settings_get_for_screen (screen); - - g_object_get (settings, "gtk-enable-animations", &are_enabled, NULL); - - return !are_enabled; -} - -static void -draw_background (GnomeBGCrossfade *fade) -{ - if (gdk_window_get_window_type (fade->priv->window) == GDK_WINDOW_ROOT) { - g_warning ("Crossfade is not supported on ROOT window!"); - } else { - gdk_window_invalidate_rect (fade->priv->window, NULL, FALSE); - gdk_window_process_updates (fade->priv->window, FALSE); - } -} - -static gboolean -on_tick (GnomeBGCrossfade *fade) -{ - gdouble now, percent_done; - cairo_t *cr; - cairo_status_t status; - - g_return_val_if_fail (GNOME_IS_BG_CROSSFADE (fade), FALSE); - - now = get_current_time (); - - percent_done = (now - fade->priv->start_time) / fade->priv->total_duration; - percent_done = CLAMP (percent_done, 0.0, 1.0); - - /* If it's taking a long time to get to the first frame, - * then lengthen the duration, so the user will get to see - * the effect. - */ - if (fade->priv->is_first_frame && percent_done > .33) { - fade->priv->is_first_frame = FALSE; - fade->priv->total_duration *= 1.5; - return on_tick (fade); - } - - if (fade->priv->fading_surface == NULL) { - return FALSE; - } - - if (animations_are_disabled (fade)) { - return FALSE; - } - - /* We accumulate the results in place for performance reasons. - * - * This means 1) The fade is exponential, not linear (looks good!) - * 2) The rate of fade is not independent of frame rate. Slower machines - * will get a slower fade (but never longer than .75 seconds), and - * even the fastest machines will get *some* fade because the framerate - * is capped. - */ - cr = cairo_create (fade->priv->fading_surface); - - cairo_set_source_surface (cr, fade->priv->end_surface, - 0.0, 0.0); - cairo_paint_with_alpha (cr, percent_done); - - status = cairo_status (cr); - cairo_destroy (cr); - - if (status == CAIRO_STATUS_SUCCESS) { - draw_background (fade); - } - return percent_done <= .99; -} - -static void -on_finished (GnomeBGCrossfade *fade) -{ - cairo_pattern_t *pattern; - - if (fade->priv->timeout_id == 0) - return; - - g_assert (fade->priv->end_surface != NULL); - - pattern = cairo_pattern_create_for_surface (fade->priv->end_surface); - gdk_window_set_background_pattern (fade->priv->window, pattern); - cairo_pattern_destroy (pattern); - - draw_background (fade); - - cairo_surface_destroy (fade->priv->end_surface); - fade->priv->end_surface = NULL; - - g_assert (fade->priv->fading_surface != NULL); - - cairo_surface_destroy (fade->priv->fading_surface); - fade->priv->fading_surface = NULL; - - fade->priv->timeout_id = 0; - g_signal_emit (fade, signals[FINISHED], 0, fade->priv->window); -} - -/** - * gnome_bg_crossfade_start: - * @fade: a #GnomeBGCrossfade - * @window: The #GdkWindow to draw crossfade on - * - * This function initiates a quick crossfade between two surfaces on - * the background of @window. Before initiating the crossfade both - * gnome_bg_crossfade_start() and gnome_bg_crossfade_end() need to - * be called. If animations are disabled, the crossfade is skipped, - * and the window background is set immediately to the end surface. - **/ -void -gnome_bg_crossfade_start (GnomeBGCrossfade *fade, - GdkWindow *window) -{ - GSource *source; - GMainContext *context; - cairo_pattern_t *pattern; - - g_return_if_fail (GNOME_IS_BG_CROSSFADE (fade)); - g_return_if_fail (window != NULL); - g_return_if_fail (fade->priv->fading_surface != NULL); - g_return_if_fail (fade->priv->end_surface != NULL); - g_return_if_fail (!gnome_bg_crossfade_is_started (fade)); - g_return_if_fail (gdk_window_get_window_type (window) != GDK_WINDOW_FOREIGN); - - source = g_timeout_source_new (1000 / 60.0); - g_source_set_callback (source, - (GSourceFunc) on_tick, - fade, - (GDestroyNotify) on_finished); - context = g_main_context_default (); - fade->priv->timeout_id = g_source_attach (source, context); - g_source_unref (source); - - fade->priv->window = window; - pattern = cairo_pattern_create_for_surface (fade->priv->fading_surface); - gdk_window_set_background_pattern (fade->priv->window, pattern); - cairo_pattern_destroy (pattern); - - draw_background (fade); - - fade->priv->is_first_frame = TRUE; - fade->priv->total_duration = .75; - fade->priv->start_time = get_current_time (); -} - - -/** - * gnome_bg_crossfade_is_started: - * @fade: a #GnomeBGCrossfade - * - * This function reveals whether or not @fade is currently - * running on a window. See gnome_bg_crossfade_start() for - * information on how to initiate a crossfade. - * - * Return value: %TRUE if fading, or %FALSE if not fading - **/ -gboolean -gnome_bg_crossfade_is_started (GnomeBGCrossfade *fade) -{ - g_return_val_if_fail (GNOME_IS_BG_CROSSFADE (fade), FALSE); - - return fade->priv->timeout_id != 0; -} - -/** - * gnome_bg_crossfade_stop: - * @fade: a #GnomeBGCrossfade - * - * This function stops any in progress crossfades that may be - * happening. It's harmless to call this function if @fade is - * already stopped. - **/ -void -gnome_bg_crossfade_stop (GnomeBGCrossfade *fade) -{ - g_return_if_fail (GNOME_IS_BG_CROSSFADE (fade)); - - if (!gnome_bg_crossfade_is_started (fade)) - return; - - g_assert (fade->priv->timeout_id != 0); - g_source_remove (fade->priv->timeout_id); - fade->priv->timeout_id = 0; -} diff --git a/libgnome-desktop/gnome-bg-crossfade.h b/libgnome-desktop/gnome-bg-crossfade.h deleted file mode 100644 index 119047da..00000000 --- a/libgnome-desktop/gnome-bg-crossfade.h +++ /dev/null @@ -1,76 +0,0 @@ -/* gnome-bg-crossfade.h - fade window background between two surfaces - - Copyright 2008, Red Hat, Inc. - - This file is part of the Gnome Library. - - The Gnome Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The Gnome Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the Gnome Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - Author: Ray Strode <rstrode@redhat.com> -*/ - -#ifndef __GNOME_BG_CROSSFADE_H__ -#define __GNOME_BG_CROSSFADE_H__ - -#ifndef GNOME_DESKTOP_USE_UNSTABLE_API -#error GnomeBGCrossfade is unstable API. You must define GNOME_DESKTOP_USE_UNSTABLE_API before including gnome-bg-crossfade.h -#endif - -#include <gdk/gdk.h> - -G_BEGIN_DECLS - -#define GNOME_TYPE_BG_CROSSFADE (gnome_bg_crossfade_get_type ()) -#define GNOME_BG_CROSSFADE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNOME_TYPE_BG_CROSSFADE, GnomeBGCrossfade)) -#define GNOME_BG_CROSSFADE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNOME_TYPE_BG_CROSSFADE, GnomeBGCrossfadeClass)) -#define GNOME_IS_BG_CROSSFADE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNOME_TYPE_BG_CROSSFADE)) -#define GNOME_IS_BG_CROSSFADE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNOME_TYPE_BG_CROSSFADE)) -#define GNOME_BG_CROSSFADE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNOME_TYPE_BG_CROSSFADE, GnomeBGCrossfadeClass)) - -typedef struct _GnomeBGCrossfadePrivate GnomeBGCrossfadePrivate; -typedef struct _GnomeBGCrossfade GnomeBGCrossfade; -typedef struct _GnomeBGCrossfadeClass GnomeBGCrossfadeClass; - -struct _GnomeBGCrossfade -{ - GObject parent_object; - - GnomeBGCrossfadePrivate *priv; -}; - -struct _GnomeBGCrossfadeClass -{ - GObjectClass parent_class; - - void (* finished) (GnomeBGCrossfade *fade, GdkWindow *window); -}; - -G_DEFINE_AUTOPTR_CLEANUP_FUNC(GnomeBGCrossfade, g_object_unref) - -GType gnome_bg_crossfade_get_type (void); -GnomeBGCrossfade *gnome_bg_crossfade_new (int width, int height); -gboolean gnome_bg_crossfade_set_start_surface (GnomeBGCrossfade *fade, - cairo_surface_t *surface); -gboolean gnome_bg_crossfade_set_end_surface (GnomeBGCrossfade *fade, - cairo_surface_t *surface); -void gnome_bg_crossfade_start (GnomeBGCrossfade *fade, - GdkWindow *window); -gboolean gnome_bg_crossfade_is_started (GnomeBGCrossfade *fade); -void gnome_bg_crossfade_stop (GnomeBGCrossfade *fade); - -G_END_DECLS - -#endif diff --git a/libgnome-desktop/gnome-bg-slide-show.c b/libgnome-desktop/gnome-bg-slide-show.c deleted file mode 100644 index cad3cb6c..00000000 --- a/libgnome-desktop/gnome-bg-slide-show.c +++ /dev/null @@ -1,839 +0,0 @@ -/* gnome-bg-slide-show.h - * - * Copyright (C) 2008, 2013 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include <string.h> -#include <math.h> -#include <stdarg.h> -#include <stdlib.h> - -#include <gio/gio.h> - -#define GNOME_DESKTOP_USE_UNSTABLE_API -#include "gnome-bg-slide-show.h" - -struct _GnomeBGSlideShowPrivate -{ - GFile *file; - - double start_time; - double total_duration; - - GQueue *slides; - - gboolean has_multiple_sizes; - - /* used during parsing */ - struct tm start_tm; - GQueue *stack; -}; - -typedef struct _Slide Slide; - -struct _Slide -{ - double duration; /* in seconds */ - gboolean fixed; - - GSList *file1; - GSList *file2; /* NULL if fixed is TRUE */ -}; - -typedef struct _FileSize FileSize; -struct _FileSize -{ - gint width; - gint height; - - char *file; -}; - -enum { - PROP_0, - PROP_FILE, - PROP_START_TIME, - PROP_TOTAL_DURATION, - PROP_HAS_MULTIPLE_SIZES, -}; - -G_DEFINE_TYPE_WITH_PRIVATE (GnomeBGSlideShow, gnome_bg_slide_show, G_TYPE_OBJECT) - -static void -gnome_bg_slide_show_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - GnomeBGSlideShow *self; - - g_assert (GNOME_BG_IS_SLIDE_SHOW (object)); - - self = GNOME_BG_SLIDE_SHOW (object); - - switch (property_id) - { - case PROP_FILE: - self->priv->file = g_object_ref (g_value_get_object (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -gnome_bg_slide_show_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - GnomeBGSlideShow *self; - - g_assert (GNOME_BG_IS_SLIDE_SHOW (object)); - - self = GNOME_BG_SLIDE_SHOW (object); - - switch (property_id) - { - case PROP_FILE: - g_value_set_object (value, self->priv->file); - break; - case PROP_START_TIME: - g_value_set_int (value, self->priv->start_time); - break; - case PROP_TOTAL_DURATION: - g_value_set_int (value, self->priv->total_duration); - break; - case PROP_HAS_MULTIPLE_SIZES: - g_value_set_boolean (value, self->priv->has_multiple_sizes); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -gnome_bg_slide_show_finalize (GObject *object) -{ - GnomeBGSlideShow *self; - - GList *list; - GSList *slist; - FileSize *size; - - self = GNOME_BG_SLIDE_SHOW (object); - - for (list = self->priv->slides->head; list != NULL; list = list->next) { - Slide *slide = list->data; - - for (slist = slide->file1; slist != NULL; slist = slist->next) { - size = slist->data; - g_free (size->file); - g_free (size); - } - g_slist_free (slide->file1); - - for (slist = slide->file2; slist != NULL; slist = slist->next) { - size = slist->data; - g_free (size->file); - g_free (size); - } - g_slist_free (slide->file2); - - g_free (slide); - } - - g_queue_free (self->priv->slides); - - g_queue_free_full (self->priv->stack, g_free); - - g_object_unref (self->priv->file); -} - -static void -gnome_bg_slide_show_class_init (GnomeBGSlideShowClass *self_class) -{ - GObjectClass *gobject_class; - - gobject_class = G_OBJECT_CLASS (self_class); - - gobject_class->get_property = gnome_bg_slide_show_get_property; - gobject_class->set_property = gnome_bg_slide_show_set_property; - gobject_class->finalize = gnome_bg_slide_show_finalize; - - g_object_class_install_property (gobject_class, - PROP_FILE, - g_param_spec_object ("file", - "File", - "File", - G_TYPE_FILE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property (gobject_class, - PROP_START_TIME, - g_param_spec_double ("start-time", - "Start time", - "start time", - 0.0, G_MAXDOUBLE, 0.0, - G_PARAM_READABLE)); - - g_object_class_install_property (gobject_class, - PROP_TOTAL_DURATION, - g_param_spec_double ("total-duration", - "Start duration", - "total duration", - 0.0, G_MAXDOUBLE, 0.0, - G_PARAM_READABLE)); - - g_object_class_install_property (gobject_class, - PROP_HAS_MULTIPLE_SIZES, - g_param_spec_boolean ("has-multiple-sizes", - "Has multiple sizes", - "Has multiple sizes", - FALSE, - G_PARAM_READABLE)); -} - -static void -gnome_bg_slide_show_init (GnomeBGSlideShow *self) -{ - self->priv = gnome_bg_slide_show_get_instance_private (self); - - self->priv->stack = g_queue_new (); - self->priv->slides = g_queue_new (); -} - -/** - * gnome_bg_slide_show_new: - * @filename: The filename of the slide show - * - * Creates a new object to manage a slide show. - * window background between two #cairo_surface_ts. - * - * Return value: the new #GnomeBGSlideShow - **/ -GnomeBGSlideShow * -gnome_bg_slide_show_new (const char *filename) -{ - GFile *file; - GnomeBGSlideShow *self; - - file = g_file_new_for_path (filename); - - self = GNOME_BG_SLIDE_SHOW (g_object_new (GNOME_BG_TYPE_SLIDE_SHOW, - "file", file, - NULL)); - g_object_unref (file); - - return self; -} - -static void -threadsafe_localtime (time_t time, struct tm *tm) -{ - struct tm *res; - - G_LOCK_DEFINE_STATIC (localtime_mutex); - - G_LOCK (localtime_mutex); - - res = localtime (&time); - if (tm) { - *tm = *res; - } - - G_UNLOCK (localtime_mutex); -} -static gboolean stack_is (GnomeBGSlideShow *self, const char *s1, ...); - -/* Parser for fading background */ -static void -handle_start_element (GMarkupParseContext *context, - const gchar *name, - const gchar **attr_names, - const gchar **attr_values, - gpointer user_data, - GError **err) -{ - GnomeBGSlideShow *self = user_data; - gint i; - - if (strcmp (name, "static") == 0 || strcmp (name, "transition") == 0) { - Slide *slide = g_new0 (Slide, 1); - - if (strcmp (name, "static") == 0) - slide->fixed = TRUE; - - g_queue_push_tail (self->priv->slides, slide); - } - else if (strcmp (name, "size") == 0) { - Slide *slide = self->priv->slides->tail->data; - FileSize *size = g_new0 (FileSize, 1); - for (i = 0; attr_names[i]; i++) { - if (strcmp (attr_names[i], "width") == 0) - size->width = atoi (attr_values[i]); - else if (strcmp (attr_names[i], "height") == 0) - size->height = atoi (attr_values[i]); - } - if (self->priv->stack->tail && - (strcmp (self->priv->stack->tail->data, "file") == 0 || - strcmp (self->priv->stack->tail->data, "from") == 0)) { - slide->file1 = g_slist_prepend (slide->file1, size); - } - else if (self->priv->stack->tail && - strcmp (self->priv->stack->tail->data, "to") == 0) { - slide->file2 = g_slist_prepend (slide->file2, size); - } - } - g_queue_push_tail (self->priv->stack, g_strdup (name)); -} - -static void -handle_end_element (GMarkupParseContext *context, - const gchar *name, - gpointer user_data, - GError **err) -{ - GnomeBGSlideShow *self = user_data; - - g_free (g_queue_pop_tail (self->priv->stack)); -} - -static gboolean -stack_is (GnomeBGSlideShow *self, - const char *s1, - ...) -{ - GList *stack = NULL; - const char *s; - GList *l1, *l2; - va_list args; - - stack = g_list_prepend (stack, (gpointer)s1); - - va_start (args, s1); - - s = va_arg (args, const char *); - while (s) { - stack = g_list_prepend (stack, (gpointer)s); - s = va_arg (args, const char *); - } - - l1 = stack; - l2 = self->priv->stack->head; - - while (l1 && l2) { - if (strcmp (l1->data, l2->data) != 0) { - g_list_free (stack); - return FALSE; - } - - l1 = l1->next; - l2 = l2->next; - } - - g_list_free (stack); - - return (!l1 && !l2); -} - -static int -parse_int (const char *text) -{ - return strtol (text, NULL, 0); -} - -static void -handle_text (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **err) -{ - GnomeBGSlideShow *self = user_data; - Slide *slide = self->priv->slides->tail? self->priv->slides->tail->data : NULL; - FileSize *fs; - gint i; - - if (stack_is (self, "year", "starttime", "background", NULL)) { - self->priv->start_tm.tm_year = parse_int (text) - 1900; - } - else if (stack_is (self, "month", "starttime", "background", NULL)) { - self->priv->start_tm.tm_mon = parse_int (text) - 1; - } - else if (stack_is (self, "day", "starttime", "background", NULL)) { - self->priv->start_tm.tm_mday = parse_int (text); - } - else if (stack_is (self, "hour", "starttime", "background", NULL)) { - self->priv->start_tm.tm_hour = parse_int (text) - 1; - } - else if (stack_is (self, "minute", "starttime", "background", NULL)) { - self->priv->start_tm.tm_min = parse_int (text); - } - else if (stack_is (self, "second", "starttime", "background", NULL)) { - self->priv->start_tm.tm_sec = parse_int (text); - } - else if (stack_is (self, "duration", "static", "background", NULL) || - stack_is (self, "duration", "transition", "background", NULL)) { - slide->duration = g_strtod (text, NULL); - self->priv->total_duration += slide->duration; - } - else if (stack_is (self, "file", "static", "background", NULL) || - stack_is (self, "from", "transition", "background", NULL)) { - for (i = 0; text[i]; i++) { - if (!g_ascii_isspace (text[i])) - break; - } - if (text[i] == 0) - return; - fs = g_new (FileSize, 1); - fs->width = -1; - fs->height = -1; - fs->file = g_strdup (text); - slide->file1 = g_slist_prepend (slide->file1, fs); - if (slide->file1->next != NULL) - self->priv->has_multiple_sizes = TRUE; - } - else if (stack_is (self, "size", "file", "static", "background", NULL) || - stack_is (self, "size", "from", "transition", "background", NULL)) { - fs = slide->file1->data; - fs->file = g_strdup (text); - if (slide->file1->next != NULL) - self->priv->has_multiple_sizes = TRUE; - } - else if (stack_is (self, "to", "transition", "background", NULL)) { - for (i = 0; text[i]; i++) { - if (!g_ascii_isspace (text[i])) - break; - } - if (text[i] == 0) - return; - fs = g_new (FileSize, 1); - fs->width = -1; - fs->height = -1; - fs->file = g_strdup (text); - slide->file2 = g_slist_prepend (slide->file2, fs); - if (slide->file2->next != NULL) - self->priv->has_multiple_sizes = TRUE; - } - else if (stack_is (self, "size", "to", "transition", "background", NULL)) { - fs = slide->file2->data; - fs->file = g_strdup (text); - if (slide->file2->next != NULL) - self->priv->has_multiple_sizes = TRUE; - } -} - -/* - * Find the FileSize that best matches the given size. - * Do two passes; the first pass only considers FileSizes - * that are larger than the given size. - * We are looking for the image that best matches the aspect ratio. - * When two images have the same aspect ratio, prefer the one whose - * width is closer to the given width. - */ -static const char * -find_best_size (GSList *sizes, gint width, gint height) -{ - GSList *s; - gdouble a, d, distance; - FileSize *best = NULL; - gint pass; - - a = width/(gdouble)height; - distance = 10000.0; - - for (pass = 0; pass < 2; pass++) { - for (s = sizes; s; s = s->next) { - FileSize *size = s->data; - - if (pass == 0 && (size->width < width || size->height < height)) - continue; - - d = fabs (a - size->width/(gdouble)size->height); - if (d < distance) { - distance = d; - best = size; - } - else if (d == distance) { - if (abs (size->width - width) < abs (best->width - width)) { - best = size; - } - } - } - - if (best) - break; - } - - return best->file; -} - -static double -now (void) -{ - GTimeVal tv; - - g_get_current_time (&tv); - - return (double)tv.tv_sec + (tv.tv_usec / 1000000.0); -} - -/** - * gnome_bg_slide_show_get_current_slide: - * @self: a #GnomeBGSlideShow - * @width: monitor width - * @height: monitor height - * @progress: (out) (allow-none): slide progress - * @duration: (out) (allow-none): slide duration - * @is_fixed: (out) (allow-none): if slide is fixed - * @file1: (out) (allow-none) (transfer none): first file in slide - * @file2: (out) (allow-none) (transfer none): second file in slide - * - * Returns the current slides progress. - **/ -void -gnome_bg_slide_show_get_current_slide (GnomeBGSlideShow *self, - int width, - int height, - gdouble *progress, - double *duration, - gboolean *is_fixed, - const char **file1, - const char **file2) -{ - double delta = fmod (now() - self->priv->start_time, self->priv->total_duration); - GList *list; - double elapsed; - int i; - - if (delta < 0) - delta += self->priv->total_duration; - - elapsed = 0; - i = 0; - for (list = self->priv->slides->head; list != NULL; list = list->next) { - Slide *slide = list->data; - - if (elapsed + slide->duration > delta) { - if (progress) - *progress = (delta - elapsed) / (double)slide->duration; - if (duration) - *duration = slide->duration; - - if (is_fixed) - *is_fixed = slide->fixed; - - if (file1) - *file1 = find_best_size (slide->file1, width, height); - - if (file2 && slide->file2) - *file2 = find_best_size (slide->file2, width, height); - - return; - } - - i++; - elapsed += slide->duration; - } - - /* this should never happen since we have slides and we should always - * find a current slide for the elapsed time since beginning -- we're - * looping with fmod() */ - g_assert_not_reached (); -} - -/** - * gnome_bg_slide_show_get_slide: - * @self: a #GnomeBGSlideShow - * @frame_number: frame number - * @width: monitor width - * @height: monitor height - * @progress: (out) (allow-none): slide progress - * @duration: (out) (allow-none): slide duration - * @is_fixed: (out) (allow-none): if slide is fixed - * @file1: (out) (allow-none) (transfer none): first file in slide - * @file2: (out) (allow-none) (transfer none): second file in slide - * - * Retrieves slide by frame number - * - * Return value: %TRUE if successful - **/ -gboolean -gnome_bg_slide_show_get_slide (GnomeBGSlideShow *self, - int frame_number, - int width, - int height, - double *progress, - double *duration, - gboolean *is_fixed, - const char **file1, - const char **file2) -{ - double delta = fmod (now() - self->priv->start_time, self->priv->total_duration); - GList *l; - int i, skipped; - gboolean found; - double elapsed; - Slide *slide; - - if (delta < 0) - delta += self->priv->total_duration; - - elapsed = 0; - i = 0; - skipped = 0; - found = FALSE; - for (l = self->priv->slides->head; l; l = l->next) { - slide = l->data; - - if (!slide->fixed) { - elapsed += slide->duration; - - skipped++; - continue; - } - if (i == frame_number) { - found = TRUE; - break; - } - i++; - elapsed += slide->duration; - } - if (!found) - return FALSE; - - if (progress) { - if (elapsed + slide->duration > delta) { - *progress = (delta - elapsed) / (double)slide->duration; - } else { - *progress = 0.0; - } - } - - if (duration) - *duration = slide->duration; - - if (is_fixed) - *is_fixed = slide->fixed; - - if (file1) - *file1 = find_best_size (slide->file1, width, height); - - if (file2 && slide->file2) - *file2 = find_best_size (slide->file2, width, height); - - return TRUE; -} - -static gboolean -parse_file_contents (GnomeBGSlideShow *self, - const char *contents, - gsize len, - GError **error) -{ - GMarkupParser parser = { - handle_start_element, - handle_end_element, - handle_text, - NULL, /* passthrough */ - NULL, /* error */ - }; - - GMarkupParseContext *context = NULL; - time_t t; - gboolean failed = FALSE; - - threadsafe_localtime ((time_t)0, &self->priv->start_tm); - - context = g_markup_parse_context_new (&parser, 0, self, NULL); - - if (!g_markup_parse_context_parse (context, contents, len, error)) { - failed = TRUE; - } - - if (!failed && !g_markup_parse_context_end_parse (context, error)) { - failed = TRUE; - } - - g_markup_parse_context_free (context); - - if (!failed) { - guint queue_length; - - t = mktime (&self->priv->start_tm); - - self->priv->start_time = (double)t; - - queue_length = g_queue_get_length (self->priv->slides); - - /* no slides, that's not a slideshow */ - if (queue_length == 0) { - g_set_error_literal (error, - G_MARKUP_ERROR, - G_MARKUP_ERROR_INVALID_CONTENT, - "file is not a slide show since it has no slides"); - failed = TRUE; - /* one slide, there's no transition */ - } else if (queue_length == 1) { - Slide *slide = self->priv->slides->head->data; - slide->duration = self->priv->total_duration = G_MAXUINT; - } - } - - return !failed; -} - -/** - * gnome_bg_slide_show_load: - * @self: a #GnomeBGSlideShow - * @error: a #GError - * - * Tries to load the slide show. - * - * Return value: %TRUE if successful - **/ -gboolean -gnome_bg_slide_show_load (GnomeBGSlideShow *self, - GError **error) -{ - char *contents; - gsize length; - gboolean parsed; - - if (!g_file_load_contents (self->priv->file, NULL, &contents, &length, - NULL, NULL)) { - return FALSE; - } - - parsed = parse_file_contents (self, contents, length, error); - g_free (contents); - - return parsed; -} - -static void -on_file_loaded (GFile *file, - GAsyncResult *result, - GTask *task) -{ - gboolean loaded; - char *contents; - gsize length; - GError *error = NULL; - - loaded = g_file_load_contents_finish (file, result, &contents, &length, NULL, &error); - - if (!loaded) { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - if (!parse_file_contents (g_task_get_source_object (task), contents, length, &error)) { - g_task_return_error (task, error); - g_object_unref (task); - g_free (contents); - return; - } - g_free (contents); - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -/** - * gnome_bg_slide_show_load_async: - * @self: a #GnomeBGSlideShow - * @cancellable: a #GCancellable - * @callback: the callback - * @user_data: user data - * - * Tries to load the slide show asynchronously. - **/ -void -gnome_bg_slide_show_load_async (GnomeBGSlideShow *self, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (self, cancellable, callback, user_data); - - g_file_load_contents_async (self->priv->file, cancellable, - (GAsyncReadyCallback) on_file_loaded, task); -} - -/** - * gnome_bg_slide_show_get_start_time: - * @self: a #GnomeBGSlideShow - * - * gets the start time of the slide show - * - * Return value: a timestamp - **/ -double -gnome_bg_slide_show_get_start_time (GnomeBGSlideShow *self) -{ - return self->priv->start_time; -} - -/** - * gnome_bg_slide_show_get_total_duration: - * @self: a #GnomeBGSlideShow - * - * gets the total duration of the slide show - * - * Return value: a timestamp - **/ -double -gnome_bg_slide_show_get_total_duration (GnomeBGSlideShow *self) -{ - return self->priv->total_duration; -} - -/** - * gnome_bg_slide_show_get_has_multiple_sizes: - * @self: a #GnomeBGSlideShow - * - * gets whether or not the slide show has multiple sizes for different monitors - * - * Return value: %TRUE if multiple sizes - **/ -gboolean -gnome_bg_slide_show_get_has_multiple_sizes (GnomeBGSlideShow *self) -{ - return self->priv->has_multiple_sizes; -} - -/** - * gnome_bg_slide_show_get_num_slides: - * @self: a #GnomeBGSlideShow - * - * Returns number of slides in slide show - **/ -int -gnome_bg_slide_show_get_num_slides (GnomeBGSlideShow *self) -{ - return g_queue_get_length (self->priv->slides); -} diff --git a/libgnome-desktop/gnome-bg-slide-show.h b/libgnome-desktop/gnome-bg-slide-show.h deleted file mode 100644 index bcf17137..00000000 --- a/libgnome-desktop/gnome-bg-slide-show.h +++ /dev/null @@ -1,96 +0,0 @@ -/* gnome-bg-slide_show.h - fade window background between two surfaces - - Copyright 2008, Red Hat, Inc. - - This file is part of the Gnome Library. - - The Gnome Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The Gnome Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the Gnome Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - Author: Ray Strode <rstrode@redhat.com> -*/ - -#ifndef __GNOME_BG_SLIDE_SHOW_H__ -#define __GNOME_BG_SLIDE_SHOW_H__ - -#ifndef GNOME_DESKTOP_USE_UNSTABLE_API -#error GnomeBGSlideShow is unstable API. You must define GNOME_DESKTOP_USE_UNSTABLE_API before including gnome-bg-slide_show.h -#endif - -#include <gdk/gdk.h> - -G_BEGIN_DECLS - -#define GNOME_BG_TYPE_SLIDE_SHOW (gnome_bg_slide_show_get_type ()) -#define GNOME_BG_SLIDE_SHOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNOME_BG_TYPE_SLIDE_SHOW, GnomeBGSlideShow)) -#define GNOME_BG_SLIDE_SHOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNOME_BG_TYPE_SLIDE_SHOW, GnomeBGSlideShowClass)) -#define GNOME_BG_IS_SLIDE_SHOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNOME_BG_TYPE_SLIDE_SHOW)) -#define GNOME_BG_IS_SLIDE_SHOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNOME_BG_TYPE_SLIDE_SHOW)) -#define GNOME_BG_SLIDE_SHOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNOME_BG_TYPE_SLIDE_SHOW, GnomeBGSlideShowClass)) - -typedef struct _GnomeBGSlideShowPrivate GnomeBGSlideShowPrivate; -typedef struct _GnomeBGSlideShow GnomeBGSlideShow; -typedef struct _GnomeBGSlideShowClass GnomeBGSlideShowClass; - -struct _GnomeBGSlideShow -{ - GObject parent_object; - - GnomeBGSlideShowPrivate *priv; -}; - -struct _GnomeBGSlideShowClass -{ - GObjectClass parent_class; -}; - -G_DEFINE_AUTOPTR_CLEANUP_FUNC(GnomeBGSlideShow, g_object_unref) - -GType gnome_bg_slide_show_get_type (void); -GnomeBGSlideShow *gnome_bg_slide_show_new (const char *filename); -gboolean gnome_bg_slide_show_load (GnomeBGSlideShow *self, - GError **error); - -void gnome_bg_slide_show_load_async (GnomeBGSlideShow *self, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean gnome_bg_slide_show_get_slide (GnomeBGSlideShow *self, - int frame_number, - int width, - int height, - gdouble *progress, - double *duration, - gboolean *is_fixed, - const char **file1, - const char **file2); - -void gnome_bg_slide_show_get_current_slide (GnomeBGSlideShow *self, - int width, - int height, - gdouble *progress, - double *duration, - gboolean *is_fixed, - const char **file1, - const char **file2); - - -double gnome_bg_slide_show_get_start_time (GnomeBGSlideShow *self); -double gnome_bg_slide_show_get_total_duration (GnomeBGSlideShow *self); -gboolean gnome_bg_slide_show_get_has_multiple_sizes (GnomeBGSlideShow *self); -int gnome_bg_slide_show_get_num_slides (GnomeBGSlideShow *self); -G_END_DECLS - -#endif diff --git a/libgnome-desktop/gnome-bg.c b/libgnome-desktop/gnome-bg.c deleted file mode 100644 index 6a453b63..00000000 --- a/libgnome-desktop/gnome-bg.c +++ /dev/null @@ -1,2317 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - -gnomebg.c: Object for the desktop background. - -Copyright (C) 2000 Eazel, Inc. -Copyright (C) 2007-2008 Red Hat, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this program; if not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -Boston, MA 02110-1301, USA. - -Derived from eel-background.c and eel-gdk-pixbuf-extensions.c by -Darin Adler <darin@eazel.com> and Ramiro Estrugo <ramiro@eazel.com> - -Author: Soren Sandmann <sandmann@redhat.com> - -*/ - -#include <string.h> -#include <math.h> -#include <stdarg.h> -#include <stdlib.h> - -#include <glib/gstdio.h> -#include <gio/gio.h> - -#include <cairo.h> - -#define GNOME_DESKTOP_USE_UNSTABLE_API -#include "gnome-bg.h" -#include "gnome-bg-slide-show.h" -#include "gnome-bg-crossfade.h" - -#define BG_KEY_PRIMARY_COLOR "primary-color" -#define BG_KEY_SECONDARY_COLOR "secondary-color" -#define BG_KEY_COLOR_TYPE "color-shading-type" -#define BG_KEY_PICTURE_PLACEMENT "picture-options" -#define BG_KEY_PICTURE_OPACITY "picture-opacity" -#define BG_KEY_PICTURE_URI "picture-uri" - -/* We keep the large pixbufs around if the next update - in the slideshow is less than 60 seconds away */ -#define KEEP_EXPENSIVE_CACHE_SECS 60 - -/* This is the size of the GdkRGB dither matrix, in order to avoid - * bad dithering when tiling the gradient - */ -#define GRADIENT_PIXMAP_TILE_SIZE 128 -#define THUMBNAIL_SIZE 256 - -typedef struct FileCacheEntry FileCacheEntry; -#define CACHE_SIZE 4 - -/* - * Implementation of the GnomeBG class - */ -struct _GnomeBG -{ - GObject parent_instance; - char * filename; - GDesktopBackgroundStyle placement; - GDesktopBackgroundShading color_type; - GdkRGBA primary; - GdkRGBA secondary; - - GFileMonitor * file_monitor; - - guint changed_id; - guint transitioned_id; - guint blow_caches_id; - - /* Cached information, only access through cache accessor functions */ - GnomeBGSlideShow * slideshow; - time_t file_mtime; - GdkPixbuf * pixbuf_cache; - int timeout_id; - - GList * file_cache; -}; - -struct _GnomeBGClass -{ - GObjectClass parent_class; -}; - -enum { - CHANGED, - TRANSITIONED, - N_SIGNALS -}; - -static guint signals[N_SIGNALS] = { 0 }; - -G_DEFINE_TYPE (GnomeBG, gnome_bg, G_TYPE_OBJECT) - -/* Pixbuf utils */ -static void pixbuf_average_value (GdkPixbuf *pixbuf, - GdkRGBA *result); -static GdkPixbuf *pixbuf_scale_to_fit (GdkPixbuf *src, - int max_width, - int max_height); -static GdkPixbuf *pixbuf_scale_to_min (GdkPixbuf *src, - int min_width, - int min_height); -static void pixbuf_draw_gradient (GdkPixbuf *pixbuf, - gboolean horizontal, - GdkRGBA *c1, - GdkRGBA *c2, - GdkRectangle *rect); -static void pixbuf_tile (GdkPixbuf *src, - GdkPixbuf *dest); -static void pixbuf_blend (GdkPixbuf *src, - GdkPixbuf *dest, - int src_x, - int src_y, - int width, - int height, - int dest_x, - int dest_y, - double alpha); - -/* Thumbnail utilities */ -static GdkPixbuf *create_thumbnail_for_filename (GnomeDesktopThumbnailFactory *factory, - const char *filename); -static gboolean get_thumb_annotations (GdkPixbuf *thumb, - int *orig_width, - int *orig_height); - -/* Cache */ -static GdkPixbuf *get_pixbuf_for_size (GnomeBG *bg, - gint num_monitor, - int width, - int height); -static void clear_cache (GnomeBG *bg); -static gboolean is_different (GnomeBG *bg, - const char *filename); -static time_t get_mtime (const char *filename); -static GdkPixbuf *create_img_thumbnail (GnomeBG *bg, - GnomeDesktopThumbnailFactory *factory, - GdkScreen *screen, - int dest_width, - int dest_height, - int frame_num); -static GnomeBGSlideShow * get_as_slideshow (GnomeBG *bg, - const char *filename); -static GnomeBGSlideShow *read_slideshow_file (const char *filename, - GError **err); - -static void -color_from_string (const char *string, - GdkRGBA *colorp) -{ - /* If all else fails use black */ - gdk_rgba_parse (colorp, "black"); - - if (!string) - return; - - gdk_rgba_parse (colorp, string); -} - -static char * -color_to_string (const GdkRGBA *color) -{ - return g_strdup_printf ("#%02x%02x%02x", - (int) (0.5 + color->red * 255), - (int) (0.5 + color->green * 255), - (int) (0.5 + color->blue * 255)); -} - -static gboolean -do_changed (GnomeBG *bg) -{ - gboolean ignore_pending_change; - bg->changed_id = 0; - - ignore_pending_change = - GPOINTER_TO_INT (g_object_get_data (G_OBJECT (bg), - "ignore-pending-change")); - - if (!ignore_pending_change) { - g_signal_emit (G_OBJECT (bg), signals[CHANGED], 0); - } - - return FALSE; -} - -static void -queue_changed (GnomeBG *bg) -{ - if (bg->changed_id > 0) { - g_source_remove (bg->changed_id); - } - - /* We unset this here to allow apps to set it if they don't want - to get the change event. This is used by nautilus when it - gets the pixmap from the bg (due to a reason other than the changed - event). Because if there is no other change after this time the - pending changed event will just uselessly cause us to recreate - the pixmap. */ - g_object_set_data (G_OBJECT (bg), "ignore-pending-change", - GINT_TO_POINTER (FALSE)); - bg->changed_id = g_timeout_add_full (G_PRIORITY_LOW, - 100, - (GSourceFunc)do_changed, - bg, - NULL); -} - -static gboolean -do_transitioned (GnomeBG *bg) -{ - bg->transitioned_id = 0; - - if (bg->pixbuf_cache) { - g_object_unref (bg->pixbuf_cache); - bg->pixbuf_cache = NULL; - } - - g_signal_emit (G_OBJECT (bg), signals[TRANSITIONED], 0); - - return FALSE; -} - -static void -queue_transitioned (GnomeBG *bg) -{ - if (bg->transitioned_id > 0) { - g_source_remove (bg->transitioned_id); - } - - bg->transitioned_id = g_timeout_add_full (G_PRIORITY_LOW, - 100, - (GSourceFunc)do_transitioned, - bg, - NULL); -} - -static gboolean -bg_gsettings_mapping (GVariant *value, - gpointer *result, - gpointer user_data) -{ - const gchar *bg_key_value; - char *filename = NULL; - - /* The final fallback if nothing matches is with a NULL value. */ - if (value == NULL) { - *result = NULL; - return TRUE; - } - - bg_key_value = g_variant_get_string (value, NULL); - - if (bg_key_value && *bg_key_value != '\0') { - filename = g_filename_from_uri (bg_key_value, NULL, NULL); - - if (filename != NULL && g_file_test (filename, G_FILE_TEST_EXISTS) == FALSE) { - g_free (filename); - return FALSE; - } - - if (filename != NULL) { - *result = filename; - return TRUE; - } - } - - return FALSE; -} - -void -gnome_bg_load_from_preferences (GnomeBG *bg, - GSettings *settings) -{ - char *tmp; - char *filename; - GDesktopBackgroundShading ctype; - GdkRGBA c1, c2; - GDesktopBackgroundStyle placement; - - g_return_if_fail (GNOME_IS_BG (bg)); - g_return_if_fail (G_IS_SETTINGS (settings)); - - /* Filename */ - filename = g_settings_get_mapped (settings, BG_KEY_PICTURE_URI, bg_gsettings_mapping, NULL); - - /* Colors */ - tmp = g_settings_get_string (settings, BG_KEY_PRIMARY_COLOR); - color_from_string (tmp, &c1); - g_free (tmp); - - tmp = g_settings_get_string (settings, BG_KEY_SECONDARY_COLOR); - color_from_string (tmp, &c2); - g_free (tmp); - - /* Color type */ - ctype = g_settings_get_enum (settings, BG_KEY_COLOR_TYPE); - - /* Placement */ - placement = g_settings_get_enum (settings, BG_KEY_PICTURE_PLACEMENT); - - gnome_bg_set_rgba (bg, ctype, &c1, &c2); - gnome_bg_set_placement (bg, placement); - gnome_bg_set_filename (bg, filename); - - g_free (filename); -} - -void -gnome_bg_save_to_preferences (GnomeBG *bg, - GSettings *settings) -{ - gchar *primary; - gchar *secondary; - gchar *uri; - - g_return_if_fail (GNOME_IS_BG (bg)); - g_return_if_fail (G_IS_SETTINGS (settings)); - - primary = color_to_string (&bg->primary); - secondary = color_to_string (&bg->secondary); - - g_settings_delay (settings); - - uri = NULL; - if (bg->filename != NULL) - uri = g_filename_to_uri (bg->filename, NULL, NULL); - if (uri == NULL) - uri = g_strdup (""); - g_settings_set_string (settings, BG_KEY_PICTURE_URI, uri); - g_settings_set_string (settings, BG_KEY_PRIMARY_COLOR, primary); - g_settings_set_string (settings, BG_KEY_SECONDARY_COLOR, secondary); - g_settings_set_enum (settings, BG_KEY_COLOR_TYPE, bg->color_type); - g_settings_set_enum (settings, BG_KEY_PICTURE_PLACEMENT, bg->placement); - - /* Apply changes atomically. */ - g_settings_apply (settings); - - g_free (primary); - g_free (secondary); - g_free (uri); -} - - -static void -gnome_bg_init (GnomeBG *bg) -{ -} - -static void -gnome_bg_dispose (GObject *object) -{ - GnomeBG *bg = GNOME_BG (object); - - if (bg->file_monitor) { - g_object_unref (bg->file_monitor); - bg->file_monitor = NULL; - } - - clear_cache (bg); - - G_OBJECT_CLASS (gnome_bg_parent_class)->dispose (object); -} - -static void -gnome_bg_finalize (GObject *object) -{ - GnomeBG *bg = GNOME_BG (object); - - if (bg->changed_id != 0) { - g_source_remove (bg->changed_id); - bg->changed_id = 0; - } - - if (bg->transitioned_id != 0) { - g_source_remove (bg->transitioned_id); - bg->transitioned_id = 0; - } - - if (bg->blow_caches_id != 0) { - g_source_remove (bg->blow_caches_id); - bg->blow_caches_id = 0; - } - - g_free (bg->filename); - bg->filename = NULL; - - G_OBJECT_CLASS (gnome_bg_parent_class)->finalize (object); -} - -static void -gnome_bg_class_init (GnomeBGClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = gnome_bg_dispose; - object_class->finalize = gnome_bg_finalize; - - signals[CHANGED] = g_signal_new ("changed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - signals[TRANSITIONED] = g_signal_new ("transitioned", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); -} - -GnomeBG * -gnome_bg_new (void) -{ - return g_object_new (GNOME_TYPE_BG, NULL); -} - -void -gnome_bg_set_rgba (GnomeBG *bg, - GDesktopBackgroundShading type, - GdkRGBA *primary, - GdkRGBA *secondary) -{ - g_return_if_fail (bg != NULL); - g_return_if_fail (primary != NULL); - - if (bg->color_type != type || - !gdk_rgba_equal (&bg->primary, primary) || - (secondary && !gdk_rgba_equal (&bg->secondary, secondary))) { - - bg->color_type = type; - bg->primary = *primary; - if (secondary) { - bg->secondary = *secondary; - } - - queue_changed (bg); - } -} - -void -gnome_bg_set_placement (GnomeBG *bg, - GDesktopBackgroundStyle placement) -{ - g_return_if_fail (bg != NULL); - - if (bg->placement != placement) { - bg->placement = placement; - - queue_changed (bg); - } -} - -GDesktopBackgroundStyle -gnome_bg_get_placement (GnomeBG *bg) -{ - g_return_val_if_fail (bg != NULL, -1); - - return bg->placement; -} - -void -gnome_bg_get_rgba (GnomeBG *bg, - GDesktopBackgroundShading *type, - GdkRGBA *primary, - GdkRGBA *secondary) -{ - g_return_if_fail (bg != NULL); - - if (type) - *type = bg->color_type; - - if (primary) - *primary = bg->primary; - - if (secondary) - *secondary = bg->secondary; -} - -const gchar * -gnome_bg_get_filename (GnomeBG *bg) -{ - g_return_val_if_fail (bg != NULL, NULL); - - return bg->filename; -} - -static inline gchar * -get_wallpaper_cache_dir (void) -{ - return g_build_filename (g_get_user_cache_dir(), "wallpaper", NULL); -} - -static inline gchar * -get_wallpaper_cache_prefix_name (gint num_monitor, - GDesktopBackgroundStyle placement, - gint width, - gint height) -{ - return g_strdup_printf ("%i_%i_%i_%i", num_monitor, (gint) placement, width, height); -} - -static char * -get_wallpaper_cache_filename (const char *filename, - gint num_monitor, - GDesktopBackgroundStyle placement, - gint width, - gint height) -{ - gchar *cache_filename; - gchar *cache_prefix_name; - gchar *md5_filename; - gchar *cache_basename; - gchar *cache_dir; - - md5_filename = g_compute_checksum_for_data (G_CHECKSUM_MD5, (const guchar *) filename, strlen (filename)); - cache_prefix_name = get_wallpaper_cache_prefix_name (num_monitor, placement, width, height); - cache_basename = g_strdup_printf ("%s_%s", cache_prefix_name, md5_filename); - cache_dir = get_wallpaper_cache_dir (); - cache_filename = g_build_filename (cache_dir, cache_basename, NULL); - - g_free (cache_prefix_name); - g_free (md5_filename); - g_free (cache_basename); - g_free (cache_dir); - - return cache_filename; -} - -static void -cleanup_cache_for_monitor (gchar *cache_dir, - gint num_monitor) -{ - GDir *g_cache_dir; - gchar *monitor_prefix; - const gchar *file; - - g_cache_dir = g_dir_open (cache_dir, 0, NULL); - monitor_prefix = g_strdup_printf ("%i_", num_monitor); - - file = g_dir_read_name (g_cache_dir); - while (file != NULL) { - gchar *path; - - path = g_build_filename (cache_dir, file, NULL); - /* purge files with same monitor id */ - if (g_str_has_prefix (file, monitor_prefix) && - g_file_test (path, G_FILE_TEST_IS_REGULAR)) - g_unlink (path); - - g_free (path); - - file = g_dir_read_name (g_cache_dir); - } - - g_free (monitor_prefix); - g_dir_close (g_cache_dir); -} - -static gboolean -cache_file_is_valid (const char *filename, - const char *cache_filename) -{ - time_t mtime; - time_t cache_mtime; - - if (!g_file_test (cache_filename, G_FILE_TEST_IS_REGULAR)) - return FALSE; - - mtime = get_mtime (filename); - cache_mtime = get_mtime (cache_filename); - - return (mtime < cache_mtime); -} - -static void -refresh_cache_file (GnomeBG *bg, - GdkPixbuf *new_pixbuf, - gint num_monitor, - gint width, - gint height) -{ - gchar *cache_filename; - gchar *cache_dir; - GdkPixbufFormat *format; - gchar *format_name; - - if ((num_monitor == -1) || (width <= 300) || (height <= 300)) - return; - - cache_filename = get_wallpaper_cache_filename (bg->filename, num_monitor, bg->placement, width, height); - cache_dir = get_wallpaper_cache_dir (); - - /* Only refresh scaled file on disk if useful (and don't cache slideshow) */ - if (!cache_file_is_valid (bg->filename, cache_filename)) { - format = gdk_pixbuf_get_file_info (bg->filename, NULL, NULL); - - if (format != NULL) { - if (!g_file_test (cache_dir, G_FILE_TEST_IS_DIR)) { - g_mkdir_with_parents (cache_dir, 0700); - } else { - cleanup_cache_for_monitor (cache_dir, num_monitor); - } - - format_name = gdk_pixbuf_format_get_name (format); - - if (strcmp (format_name, "jpeg") == 0) - gdk_pixbuf_save (new_pixbuf, cache_filename, format_name, NULL, "quality", "100", NULL); - else - gdk_pixbuf_save (new_pixbuf, cache_filename, format_name, NULL, NULL); - - g_free (format_name); - } - } - - g_free (cache_filename); - g_free (cache_dir); -} - -static void -file_changed (GFileMonitor *file_monitor, - GFile *child, - GFile *other_file, - GFileMonitorEvent event_type, - gpointer user_data) -{ - GnomeBG *bg = GNOME_BG (user_data); - - clear_cache (bg); - queue_changed (bg); -} - -void -gnome_bg_set_filename (GnomeBG *bg, - const char *filename) -{ - g_return_if_fail (bg != NULL); - - if (is_different (bg, filename)) { - g_free (bg->filename); - - bg->filename = g_strdup (filename); - bg->file_mtime = get_mtime (bg->filename); - - if (bg->file_monitor) { - g_object_unref (bg->file_monitor); - bg->file_monitor = NULL; - } - - if (bg->filename) { - GFile *f = g_file_new_for_path (bg->filename); - - bg->file_monitor = g_file_monitor_file (f, 0, NULL, NULL); - g_signal_connect (bg->file_monitor, "changed", - G_CALLBACK (file_changed), bg); - - g_object_unref (f); - } - - clear_cache (bg); - - queue_changed (bg); - } -} - -static void -draw_color_area (GnomeBG *bg, - GdkPixbuf *dest, - GdkRectangle *rect) -{ - guint32 pixel; - GdkRectangle extent; - - extent.x = 0; - extent.y = 0; - extent.width = gdk_pixbuf_get_width (dest); - extent.height = gdk_pixbuf_get_height (dest); - - gdk_rectangle_intersect (rect, &extent, rect); - - switch (bg->color_type) { - case G_DESKTOP_BACKGROUND_SHADING_SOLID: - /* not really a big deal to ignore the area of interest */ - pixel = ((int) (0.5 + bg->primary.red * 255) << 24) | - ((int) (0.5 + bg->primary.green * 255) << 16) | - ((int) (0.5 + bg->primary.blue * 255) << 8) | - (0xff); - - gdk_pixbuf_fill (dest, pixel); - break; - - case G_DESKTOP_BACKGROUND_SHADING_HORIZONTAL: - pixbuf_draw_gradient (dest, TRUE, &(bg->primary), &(bg->secondary), rect); - break; - - case G_DESKTOP_BACKGROUND_SHADING_VERTICAL: - pixbuf_draw_gradient (dest, FALSE, &(bg->primary), &(bg->secondary), rect); - break; - - default: - break; - } -} - -static void -draw_color (GnomeBG *bg, - 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_color_area (bg, dest, &rect); -} - -static GdkPixbuf * -pixbuf_clip_to_fit (GdkPixbuf *src, - int max_width, - int max_height) -{ - int src_width, src_height; - int w, h; - int src_x, src_y; - GdkPixbuf *pixbuf; - - src_width = gdk_pixbuf_get_width (src); - src_height = gdk_pixbuf_get_height (src); - - if (src_width < max_width && src_height < max_height) - return g_object_ref (src); - - w = MIN(src_width, max_width); - h = MIN(src_height, max_height); - - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - gdk_pixbuf_get_has_alpha (src), - 8, w, h); - - src_x = (src_width - w) / 2; - src_y = (src_height - h) / 2; - gdk_pixbuf_copy_area (src, - src_x, src_y, - w, h, - pixbuf, - 0, 0); - return pixbuf; -} - -static GdkPixbuf * -get_scaled_pixbuf (GDesktopBackgroundStyle placement, - GdkPixbuf *pixbuf, - int width, int height, - int *x, int *y, - int *w, int *h) -{ - GdkPixbuf *new; - -#if 0 - g_print ("original_width: %d %d\n", - gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf)); -#endif - - switch (placement) { - case G_DESKTOP_BACKGROUND_STYLE_SPANNED: - new = pixbuf_scale_to_fit (pixbuf, width, height); - break; - case G_DESKTOP_BACKGROUND_STYLE_ZOOM: - new = pixbuf_scale_to_min (pixbuf, width, height); - break; - - case G_DESKTOP_BACKGROUND_STYLE_STRETCHED: - new = gdk_pixbuf_scale_simple (pixbuf, width, height, - GDK_INTERP_BILINEAR); - break; - - case G_DESKTOP_BACKGROUND_STYLE_SCALED: - new = pixbuf_scale_to_fit (pixbuf, width, height); - break; - - case G_DESKTOP_BACKGROUND_STYLE_NONE: - /* This shouldn’t be true, but if it is, assert and - * fall through, in case assertions are disabled. - */ - g_assert_not_reached (); - case G_DESKTOP_BACKGROUND_STYLE_CENTERED: - case G_DESKTOP_BACKGROUND_STYLE_WALLPAPER: - default: - new = pixbuf_clip_to_fit (pixbuf, width, height); - break; - } - - *w = gdk_pixbuf_get_width (new); - *h = gdk_pixbuf_get_height (new); - *x = (width - *w) / 2; - *y = (height - *h) / 2; - - return new; -} - -static void -draw_image_area (GnomeBG *bg, - gint num_monitor, - GdkPixbuf *pixbuf, - GdkPixbuf *dest, - GdkRectangle *area) -{ - int dest_width = area->width; - int dest_height = area->height; - int x, y, w, h; - GdkPixbuf *scaled; - - if (!pixbuf) - return; - - scaled = get_scaled_pixbuf (bg->placement, pixbuf, dest_width, dest_height, &x, &y, &w, &h); - - switch (bg->placement) { - case G_DESKTOP_BACKGROUND_STYLE_WALLPAPER: - pixbuf_tile (scaled, dest); - break; - case G_DESKTOP_BACKGROUND_STYLE_ZOOM: - case G_DESKTOP_BACKGROUND_STYLE_CENTERED: - case G_DESKTOP_BACKGROUND_STYLE_STRETCHED: - case G_DESKTOP_BACKGROUND_STYLE_SCALED: - pixbuf_blend (scaled, dest, 0, 0, w, h, x + area->x, y + area->y, 1.0); - break; - case G_DESKTOP_BACKGROUND_STYLE_SPANNED: - pixbuf_blend (scaled, dest, 0, 0, w, h, x, y, 1.0); - break; - case G_DESKTOP_BACKGROUND_STYLE_NONE: - default: - g_assert_not_reached (); - break; - } - - refresh_cache_file (bg, scaled, num_monitor, dest_width, dest_height); - - g_object_unref (scaled); -} - -static void -draw_image_for_thumb (GnomeBG *bg, - 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_area (bg, -1, pixbuf, dest, &rect); -} - -static void -draw_once (GnomeBG *bg, - GdkPixbuf *dest) -{ - GdkRectangle rect; - GdkPixbuf *pixbuf; - gint num_monitor; - - /* we just draw on the whole screen */ - num_monitor = 0; - - rect.x = 0; - rect.y = 0; - rect.width = gdk_pixbuf_get_width (dest); - rect.height = gdk_pixbuf_get_height (dest); - - pixbuf = get_pixbuf_for_size (bg, num_monitor, rect.width, rect.height); - if (pixbuf) { - GdkPixbuf *rotated; - - rotated = gdk_pixbuf_apply_embedded_orientation (pixbuf); - if (rotated != NULL) { - g_object_unref (pixbuf); - pixbuf = rotated; - } - - draw_image_area (bg, - num_monitor, - pixbuf, - dest, - &rect); - g_object_unref (pixbuf); - } -} - -void -gnome_bg_draw (GnomeBG *bg, - GdkPixbuf *dest) -{ - draw_color (bg, dest); - if (bg->placement != G_DESKTOP_BACKGROUND_STYLE_NONE) { - draw_once (bg, dest); - } -} - -gboolean -gnome_bg_has_multiple_sizes (GnomeBG *bg) -{ - GnomeBGSlideShow *show; - gboolean ret; - - g_return_val_if_fail (bg != NULL, FALSE); - - ret = FALSE; - - show = get_as_slideshow (bg, bg->filename); - if (show) { - ret = gnome_bg_slide_show_get_has_multiple_sizes (show); - g_object_unref (show); - } - - return ret; -} - -static void -gnome_bg_get_pixmap_size (GnomeBG *bg, - int width, - int height, - int *pixmap_width, - int *pixmap_height) -{ - int dummy; - - if (!pixmap_width) - pixmap_width = &dummy; - if (!pixmap_height) - pixmap_height = &dummy; - - *pixmap_width = width; - *pixmap_height = height; - - if (!bg->filename) { - switch (bg->color_type) { - case G_DESKTOP_BACKGROUND_SHADING_SOLID: - *pixmap_width = 1; - *pixmap_height = 1; - break; - - case G_DESKTOP_BACKGROUND_SHADING_HORIZONTAL: - case G_DESKTOP_BACKGROUND_SHADING_VERTICAL: - default: - break; - } - - return; - } -} - -/** - * gnome_bg_create_surface: - * @bg: GnomeBG - * @window: - * @width: - * @height: - * - * Create a surface that can be set as background for @window. - * - * Returns: %NULL on error (e.g. out of X connections) - **/ -cairo_surface_t * -gnome_bg_create_surface (GnomeBG *bg, - GdkWindow *window, - int width, - int height) -{ - gint scale; - int pm_width, pm_height; - cairo_surface_t *surface; - cairo_t *cr; - - g_return_val_if_fail (bg != NULL, NULL); - g_return_val_if_fail (window != NULL, NULL); - - scale = gdk_window_get_scale_factor (window); - - if (bg->pixbuf_cache && - gdk_pixbuf_get_width (bg->pixbuf_cache) != width && - gdk_pixbuf_get_height (bg->pixbuf_cache) != height) { - g_object_unref (bg->pixbuf_cache); - bg->pixbuf_cache = NULL; - } - - /* has the side effect of loading and caching pixbuf only when in tile mode */ - gnome_bg_get_pixmap_size (bg, width, height, &pm_width, &pm_height); - surface = gdk_window_create_similar_surface (window, - CAIRO_CONTENT_COLOR, - pm_width, pm_height); - - if (surface == NULL) - return NULL; - - cr = cairo_create (surface); - if (!bg->filename && bg->color_type == G_DESKTOP_BACKGROUND_SHADING_SOLID) { - gdk_cairo_set_source_rgba (cr, &(bg->primary)); - } - else { - GdkPixbuf *pixbuf; - cairo_surface_t *pixbuf_surface; - - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, - scale * width, scale * height); - gnome_bg_draw (bg, pixbuf); - - pixbuf_surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 0, window); - cairo_set_source_surface (cr, pixbuf_surface, 0, 0); - - cairo_surface_destroy (pixbuf_surface); - g_object_unref (pixbuf); - } - - cairo_paint (cr); - - cairo_destroy (cr); - - return surface; -} - - -/* determine if a background is darker or lighter than average, to help - * clients know what colors to draw on top with - */ -gboolean -gnome_bg_is_dark (GnomeBG *bg, - int width, - int height) -{ - GdkRGBA color; - gdouble intensity; - GdkPixbuf *pixbuf; - - g_return_val_if_fail (bg != NULL, FALSE); - - if (bg->color_type == G_DESKTOP_BACKGROUND_SHADING_SOLID) { - color = bg->primary; - } else { - color.red = (bg->primary.red + bg->secondary.red) / 2; - color.green = (bg->primary.green + bg->secondary.green) / 2; - color.blue = (bg->primary.blue + bg->secondary.blue) / 2; - } - pixbuf = get_pixbuf_for_size (bg, -1, width, height); - if (pixbuf) { - GdkRGBA average; - - pixbuf_average_value (pixbuf, &average); - - color.red = color.red * (1.0 - average.alpha) + average.red * average.alpha; - color.green = color.green * (1.0 - average.alpha) + average.green * average.alpha; - color.blue = color.blue * (1.0 - average.alpha) + average.blue * average.alpha; - g_object_unref (pixbuf); - } - - intensity = color.red * 77 + - color.green * 150 + - color.blue * 28; - - return intensity < 160; /* biased slightly to be dark */ -} - -static gboolean -get_original_size (const char *filename, - int *orig_width, - int *orig_height) -{ - gboolean result; - - if (gdk_pixbuf_get_file_info (filename, orig_width, orig_height)) - result = TRUE; - else - result = FALSE; - - return result; -} - -static const char * -get_filename_for_size (GnomeBG *bg, gint best_width, gint best_height) -{ - GnomeBGSlideShow *show; - const char *file = NULL; - - if (!bg->filename) - return NULL; - - show = get_as_slideshow (bg, bg->filename); - if (!show) { - return bg->filename; - } - - gnome_bg_slide_show_get_current_slide (show, best_width, best_height, NULL, NULL, NULL, &file, NULL); - g_object_unref (show); - - return file; -} - -gboolean -gnome_bg_get_image_size (GnomeBG *bg, - GnomeDesktopThumbnailFactory *factory, - int best_width, - int best_height, - int *width, - int *height) -{ - GdkPixbuf *thumb; - gboolean result = FALSE; - const gchar *filename; - - g_return_val_if_fail (bg != NULL, FALSE); - g_return_val_if_fail (factory != NULL, FALSE); - - if (!bg->filename) - return FALSE; - - filename = get_filename_for_size (bg, best_width, best_height); - thumb = create_thumbnail_for_filename (factory, filename); - if (thumb) { - if (get_thumb_annotations (thumb, width, height)) - result = TRUE; - - g_object_unref (thumb); - } - - if (!result) { - if (get_original_size (filename, width, height)) - result = TRUE; - } - - return result; -} - -static double -fit_factor (int from_width, int from_height, - int to_width, int to_height) -{ - return MIN (to_width / (double) from_width, to_height / (double) from_height); -} - -/** - * gnome_bg_create_thumbnail: - * - * Returns: (transfer full): a #GdkPixbuf showing the background as a thumbnail - */ -GdkPixbuf * -gnome_bg_create_thumbnail (GnomeBG *bg, - GnomeDesktopThumbnailFactory *factory, - GdkScreen *screen, - int dest_width, - int dest_height) -{ - GdkPixbuf *result; - GdkPixbuf *thumb; - - g_return_val_if_fail (bg != NULL, NULL); - - result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, dest_width, dest_height); - - draw_color (bg, result); - - if (bg->placement != G_DESKTOP_BACKGROUND_STYLE_NONE) { - thumb = create_img_thumbnail (bg, factory, screen, dest_width, dest_height, -1); - - if (thumb) { - draw_image_for_thumb (bg, thumb, result); - g_object_unref (thumb); - } - } - - return result; -} - -/* Implementation of the pixbuf cache */ -struct _SlideShow -{ - gint ref_count; - double start_time; - double total_duration; - - GQueue *slides; - - gboolean has_multiple_sizes; - - /* used during parsing */ - struct tm start_tm; - GQueue *stack; -}; - - -static GdkPixbuf * -blend (GdkPixbuf *p1, - GdkPixbuf *p2, - double alpha) -{ - GdkPixbuf *result = gdk_pixbuf_copy (p1); - GdkPixbuf *tmp; - - if (gdk_pixbuf_get_width (p2) != gdk_pixbuf_get_width (p1) || - gdk_pixbuf_get_height (p2) != gdk_pixbuf_get_height (p1)) { - tmp = gdk_pixbuf_scale_simple (p2, - gdk_pixbuf_get_width (p1), - gdk_pixbuf_get_height (p1), - GDK_INTERP_BILINEAR); - } - else { - tmp = g_object_ref (p2); - } - - pixbuf_blend (tmp, result, 0, 0, -1, -1, 0, 0, alpha); - - g_object_unref (tmp); - - return result; -} - -typedef enum { - PIXBUF, - SLIDESHOW, - THUMBNAIL -} FileType; - -struct FileCacheEntry -{ - FileType type; - char *filename; - union { - GdkPixbuf *pixbuf; - GnomeBGSlideShow *slideshow; - GdkPixbuf *thumbnail; - } u; -}; - -static void -file_cache_entry_delete (FileCacheEntry *ent) -{ - g_free (ent->filename); - - switch (ent->type) { - case PIXBUF: - g_object_unref (ent->u.pixbuf); - break; - case SLIDESHOW: - g_object_unref (ent->u.slideshow); - break; - case THUMBNAIL: - g_object_unref (ent->u.thumbnail); - break; - default: - break; - } - - g_free (ent); -} - -static void -bound_cache (GnomeBG *bg) -{ - while (g_list_length (bg->file_cache) >= CACHE_SIZE) { - GList *last_link = g_list_last (bg->file_cache); - FileCacheEntry *ent = last_link->data; - - file_cache_entry_delete (ent); - - bg->file_cache = g_list_delete_link (bg->file_cache, last_link); - } -} - -static const FileCacheEntry * -file_cache_lookup (GnomeBG *bg, FileType type, const char *filename) -{ - GList *list; - - for (list = bg->file_cache; list != NULL; list = list->next) { - FileCacheEntry *ent = list->data; - - if (ent && ent->type == type && - strcmp (ent->filename, filename) == 0) { - return ent; - } - } - - return NULL; -} - -static FileCacheEntry * -file_cache_entry_new (GnomeBG *bg, - FileType type, - const char *filename) -{ - FileCacheEntry *ent = g_new0 (FileCacheEntry, 1); - - g_assert (!file_cache_lookup (bg, type, filename)); - - ent->type = type; - ent->filename = g_strdup (filename); - - bg->file_cache = g_list_prepend (bg->file_cache, ent); - - bound_cache (bg); - - return ent; -} - -static void -file_cache_add_pixbuf (GnomeBG *bg, - const char *filename, - GdkPixbuf *pixbuf) -{ - FileCacheEntry *ent = file_cache_entry_new (bg, PIXBUF, filename); - ent->u.pixbuf = g_object_ref (pixbuf); -} - -static void -file_cache_add_thumbnail (GnomeBG *bg, - const char *filename, - GdkPixbuf *pixbuf) -{ - FileCacheEntry *ent = file_cache_entry_new (bg, THUMBNAIL, filename); - ent->u.thumbnail = g_object_ref (pixbuf); -} - -static void -file_cache_add_slide_show (GnomeBG *bg, - const char *filename, - GnomeBGSlideShow *show) -{ - FileCacheEntry *ent = file_cache_entry_new (bg, SLIDESHOW, filename); - ent->u.slideshow = g_object_ref (show); -} - -static GdkPixbuf * -load_from_cache_file (GnomeBG *bg, - const char *filename, - gint num_monitor, - gint best_width, - gint best_height) -{ - GdkPixbuf *pixbuf = NULL; - gchar *cache_filename; - - cache_filename = get_wallpaper_cache_filename (filename, num_monitor, bg->placement, best_width, best_height); - if (cache_file_is_valid (filename, cache_filename)) - pixbuf = gdk_pixbuf_new_from_file (cache_filename, NULL); - g_free (cache_filename); - - return pixbuf; -} - -static GdkPixbuf * -get_as_pixbuf_for_size (GnomeBG *bg, - const char *filename, - gint num_monitor, - gint best_width, - gint best_height) -{ - const FileCacheEntry *ent; - if ((ent = file_cache_lookup (bg, PIXBUF, filename))) { - return g_object_ref (ent->u.pixbuf); - } - else { - GdkPixbufFormat *format; - GdkPixbuf *pixbuf; - gchar *tmp; - pixbuf = NULL; - - /* Try to hit local cache first if relevant */ - if (num_monitor != -1) - pixbuf = load_from_cache_file (bg, filename, num_monitor, best_width, best_height); - - if (!pixbuf) { - /* If scalable choose maximum size */ - format = gdk_pixbuf_get_file_info (filename, NULL, NULL); - - if (format != NULL) { - tmp = gdk_pixbuf_format_get_name (format); - } else { - tmp = NULL; - } - - if (tmp != NULL && - strcmp (tmp, "svg") == 0 && - (best_width > 0 && best_height > 0) && - (bg->placement == G_DESKTOP_BACKGROUND_STYLE_STRETCHED || - bg->placement == G_DESKTOP_BACKGROUND_STYLE_SCALED || - bg->placement == G_DESKTOP_BACKGROUND_STYLE_ZOOM)) - pixbuf = gdk_pixbuf_new_from_file_at_size (filename, best_width, best_height, NULL); - else - pixbuf = gdk_pixbuf_new_from_file (filename, NULL); - g_free (tmp); - } - - if (pixbuf) - file_cache_add_pixbuf (bg, filename, pixbuf); - - return pixbuf; - } -} - -static GnomeBGSlideShow * -get_as_slideshow (GnomeBG *bg, const char *filename) -{ - const FileCacheEntry *ent; - if ((ent = file_cache_lookup (bg, SLIDESHOW, filename))) { - return g_object_ref (ent->u.slideshow); - } - else { - GnomeBGSlideShow *show = read_slideshow_file (filename, NULL); - - if (show) - file_cache_add_slide_show (bg, filename, show); - - return show; - } -} - -static GdkPixbuf * -get_as_thumbnail (GnomeBG *bg, GnomeDesktopThumbnailFactory *factory, const char *filename) -{ - const FileCacheEntry *ent; - if ((ent = file_cache_lookup (bg, THUMBNAIL, filename))) { - return g_object_ref (ent->u.thumbnail); - } - else { - GdkPixbuf *thumb = create_thumbnail_for_filename (factory, filename); - - if (thumb) - file_cache_add_thumbnail (bg, filename, thumb); - - return thumb; - } -} - -static gboolean -blow_expensive_caches (gpointer data) -{ - GnomeBG *bg = data; - GList *list, *next; - - bg->blow_caches_id = 0; - - for (list = bg->file_cache; list != NULL; list = next) { - FileCacheEntry *ent = list->data; - next = list->next; - - if (ent->type == PIXBUF) { - file_cache_entry_delete (ent); - bg->file_cache = g_list_delete_link (bg->file_cache, - list); - } - } - - if (bg->pixbuf_cache) { - g_object_unref (bg->pixbuf_cache); - bg->pixbuf_cache = NULL; - } - - return FALSE; -} - -static void -blow_expensive_caches_in_idle (GnomeBG *bg) -{ - if (bg->blow_caches_id == 0) { - bg->blow_caches_id = - g_idle_add (blow_expensive_caches, - bg); - } -} - - -static gboolean -on_timeout (gpointer data) -{ - GnomeBG *bg = data; - - bg->timeout_id = 0; - - queue_transitioned (bg); - - return FALSE; -} - -static double -get_slide_timeout (gboolean is_fixed, - gdouble duration) -{ - double timeout; - if (is_fixed) { - timeout = duration; - } else { - /* Maybe the number of steps should be configurable? */ - - /* In the worst case we will do a fade from 0 to 256, which mean - * we will never use more than 255 steps, however in most cases - * the first and last value are similar and users can't percieve - * changes in pixel values as small as 1/255th. So, lets not waste - * CPU cycles on transitioning to often. - * - * 64 steps is enough for each step to be just detectable in a 16bit - * color mode in the worst case, so we'll use this as an approximation - * of whats detectable. - */ - timeout = duration / 64.0; - } - return timeout; -} - -static void -ensure_timeout (GnomeBG *bg, - gdouble timeout) -{ - if (!bg->timeout_id) { - /* G_MAXUINT means "only one slide" */ - if (timeout < G_MAXUINT) { - bg->timeout_id = g_timeout_add_full ( - G_PRIORITY_LOW, - timeout * 1000, on_timeout, bg, NULL); - } - } -} - -static time_t -get_mtime (const char *filename) -{ - GFile *file; - GFileInfo *info; - time_t mtime; - - mtime = (time_t)-1; - - if (filename) { - file = g_file_new_for_path (filename); - info = g_file_query_info (file, G_FILE_ATTRIBUTE_TIME_MODIFIED, - G_FILE_QUERY_INFO_NONE, NULL, NULL); - if (info) { - mtime = g_file_info_get_attribute_uint64 (info, - G_FILE_ATTRIBUTE_TIME_MODIFIED); - g_object_unref (info); - } - g_object_unref (file); - } - - return mtime; -} - -static GdkPixbuf * -scale_thumbnail (GDesktopBackgroundStyle placement, - const char *filename, - GdkPixbuf *thumb, - GdkScreen *screen, - int dest_width, - int dest_height) -{ - int o_width; - int o_height; - - if (placement != G_DESKTOP_BACKGROUND_STYLE_WALLPAPER && - placement != G_DESKTOP_BACKGROUND_STYLE_CENTERED) { - - /* In this case, the pixbuf will be scaled to fit the screen anyway, - * so just return the pixbuf here - */ - return g_object_ref (thumb); - } - - if (get_thumb_annotations (thumb, &o_width, &o_height) || - (filename && get_original_size (filename, &o_width, &o_height))) { - - int scr_height = gdk_screen_get_height (screen); - int scr_width = gdk_screen_get_width (screen); - int thumb_width = gdk_pixbuf_get_width (thumb); - int thumb_height = gdk_pixbuf_get_height (thumb); - double screen_to_dest = fit_factor (scr_width, scr_height, - dest_width, dest_height); - double thumb_to_orig = fit_factor (thumb_width, thumb_height, - o_width, o_height); - double f = thumb_to_orig * screen_to_dest; - int new_width, new_height; - - new_width = floor (thumb_width * f + 0.5); - new_height = floor (thumb_height * f + 0.5); - - if (placement == G_DESKTOP_BACKGROUND_STYLE_WALLPAPER) { - /* Heuristic to make sure tiles don't become so small that - * they turn into a blur. - * - * This is strictly speaking incorrect, but the resulting - * thumbnail gives a much better idea what the background - * will actually look like. - */ - - if ((new_width < 32 || new_height < 32) && - (new_width < o_width / 4 || new_height < o_height / 4)) { - new_width = o_width / 4; - new_height = o_height / 4; - } - } - - thumb = gdk_pixbuf_scale_simple (thumb, new_width, new_height, - GDK_INTERP_BILINEAR); - } - else - g_object_ref (thumb); - - return thumb; -} - -/* frame_num determines which slide to thumbnail. - * -1 means 'current slide'. - */ -static GdkPixbuf * -create_img_thumbnail (GnomeBG *bg, - GnomeDesktopThumbnailFactory *factory, - GdkScreen *screen, - int dest_width, - int dest_height, - int frame_num) -{ - if (bg->filename) { - GdkPixbuf *thumb; - - thumb = get_as_thumbnail (bg, factory, bg->filename); - - if (thumb) { - GdkPixbuf *result; - result = scale_thumbnail (bg->placement, - bg->filename, - thumb, - screen, - dest_width, - dest_height); - g_object_unref (thumb); - return result; - } - else { - GnomeBGSlideShow *show = get_as_slideshow (bg, bg->filename); - - if (show) { - double alpha; - double duration; - gboolean is_fixed; - const char *file1; - const char *file2; - GdkPixbuf *tmp; - - if (frame_num == -1) - gnome_bg_slide_show_get_current_slide (show, - dest_width, - dest_height, - &alpha, - &duration, - &is_fixed, - &file1, - &file2); - else - gnome_bg_slide_show_get_slide (show, - frame_num, - dest_width, - dest_height, - &alpha, - &duration, - &is_fixed, - &file1, - &file2); - - if (is_fixed) { - tmp = get_as_thumbnail (bg, factory, file1); - if (tmp) { - thumb = scale_thumbnail (bg->placement, - file1, - tmp, - screen, - dest_width, - dest_height); - g_object_unref (tmp); - } - } - else { - GdkPixbuf *p1, *p2; - p1 = get_as_thumbnail (bg, factory, file1); - p2 = get_as_thumbnail (bg, factory, file2); - - if (p1 && p2) { - GdkPixbuf *thumb1, *thumb2; - - thumb1 = scale_thumbnail (bg->placement, - file1, - p1, - screen, - dest_width, - dest_height); - - thumb2 = scale_thumbnail (bg->placement, - file2, - p2, - screen, - dest_width, - dest_height); - - thumb = blend (thumb1, thumb2, alpha); - - g_object_unref (thumb1); - g_object_unref (thumb2); - } - if (p1) - g_object_unref (p1); - if (p2) - g_object_unref (p2); - } - - ensure_timeout (bg, (guint)get_slide_timeout (is_fixed, duration)); - - g_object_unref (show); - } - } - - return thumb; - } - - return NULL; -} - -static GdkPixbuf * -get_pixbuf_for_size (GnomeBG *bg, - gint num_monitor, - gint best_width, - gint best_height) -{ - guint time_until_next_change; - gboolean hit_cache = FALSE; - - /* only hit the cache if the aspect ratio matches */ - if (bg->pixbuf_cache) { - int width, height; - width = gdk_pixbuf_get_width (bg->pixbuf_cache); - height = gdk_pixbuf_get_height (bg->pixbuf_cache); - hit_cache = 0.2 > fabs ((best_width / (double)best_height) - (width / (double)height)); - if (!hit_cache) { - g_object_unref (bg->pixbuf_cache); - bg->pixbuf_cache = NULL; - } - } - - if (!hit_cache && bg->filename) { - bg->file_mtime = get_mtime (bg->filename); - - bg->pixbuf_cache = get_as_pixbuf_for_size (bg, bg->filename, num_monitor, best_width, best_height); - time_until_next_change = G_MAXUINT; - if (!bg->pixbuf_cache) { - GnomeBGSlideShow *show = get_as_slideshow (bg, bg->filename); - - if (show) { - double alpha; - double duration; - gboolean is_fixed; - const char *file1; - const char *file2; - - g_object_ref (show); - - gnome_bg_slide_show_get_current_slide (show, - best_width, - best_height, - &alpha, - &duration, - &is_fixed, - &file1, - &file2); - time_until_next_change = (guint)get_slide_timeout (is_fixed, duration); - if (is_fixed) { - bg->pixbuf_cache = get_as_pixbuf_for_size (bg, file1, num_monitor, best_width, best_height); - } - else { - GdkPixbuf *p1, *p2; - p1 = get_as_pixbuf_for_size (bg, file1, num_monitor, best_width, best_height); - p2 = get_as_pixbuf_for_size (bg, file2, num_monitor, best_width, best_height); - - if (p1 && p2) { - bg->pixbuf_cache = blend (p1, p2, alpha); - } - if (p1) - g_object_unref (p1); - if (p2) - g_object_unref (p2); - } - - ensure_timeout (bg, time_until_next_change); - - g_object_unref (show); - } - } - - /* If the next slideshow step is a long time away then - we blow away the expensive stuff (large pixbufs) from - the cache */ - if (time_until_next_change > KEEP_EXPENSIVE_CACHE_SECS) - blow_expensive_caches_in_idle (bg); - } - - if (bg->pixbuf_cache) - g_object_ref (bg->pixbuf_cache); - - return bg->pixbuf_cache; -} - -static gboolean -is_different (GnomeBG *bg, - const char *filename) -{ - if (!filename && bg->filename) { - return TRUE; - } - else if (filename && !bg->filename) { - return TRUE; - } - else if (!filename && !bg->filename) { - return FALSE; - } - else { - time_t mtime = get_mtime (filename); - - if (mtime != bg->file_mtime) - return TRUE; - - if (strcmp (filename, bg->filename) != 0) - return TRUE; - - return FALSE; - } -} - -static void -clear_cache (GnomeBG *bg) -{ - GList *list; - - if (bg->file_cache) { - for (list = bg->file_cache; list != NULL; list = list->next) { - FileCacheEntry *ent = list->data; - - file_cache_entry_delete (ent); - } - g_list_free (bg->file_cache); - bg->file_cache = NULL; - } - - if (bg->pixbuf_cache) { - g_object_unref (bg->pixbuf_cache); - - bg->pixbuf_cache = NULL; - } - - if (bg->timeout_id) { - g_source_remove (bg->timeout_id); - - bg->timeout_id = 0; - } -} - -/* Pixbuf utilities */ -static void -pixbuf_average_value (GdkPixbuf *pixbuf, - GdkRGBA *result) -{ - guint64 a_total, r_total, g_total, b_total; - guint row, column; - int row_stride; - const guchar *pixels, *p; - int r, g, b, a; - guint64 dividend; - guint width, height; - gdouble dd; - - width = gdk_pixbuf_get_width (pixbuf); - height = gdk_pixbuf_get_height (pixbuf); - row_stride = gdk_pixbuf_get_rowstride (pixbuf); - pixels = gdk_pixbuf_get_pixels (pixbuf); - - /* iterate through the pixbuf, counting up each component */ - a_total = 0; - r_total = 0; - g_total = 0; - b_total = 0; - - if (gdk_pixbuf_get_has_alpha (pixbuf)) { - for (row = 0; row < height; row++) { - p = pixels + (row * row_stride); - for (column = 0; column < width; column++) { - r = *p++; - g = *p++; - b = *p++; - a = *p++; - - a_total += a; - r_total += r * a; - g_total += g * a; - b_total += b * a; - } - } - dividend = height * width * 0xFF; - a_total *= 0xFF; - } else { - for (row = 0; row < height; row++) { - p = pixels + (row * row_stride); - for (column = 0; column < width; column++) { - r = *p++; - g = *p++; - b = *p++; - - r_total += r; - g_total += g; - b_total += b; - } - } - dividend = height * width; - a_total = dividend * 0xFF; - } - - dd = dividend * 0xFF; - result->alpha = a_total / dd; - result->red = r_total / dd; - result->green = g_total / dd; - result->blue = b_total / dd; -} - -static GdkPixbuf * -pixbuf_scale_to_fit (GdkPixbuf *src, int max_width, int max_height) -{ - double factor; - int src_width, src_height; - int new_width, new_height; - - src_width = gdk_pixbuf_get_width (src); - src_height = gdk_pixbuf_get_height (src); - - factor = MIN (max_width / (double) src_width, max_height / (double) src_height); - - new_width = floor (src_width * factor + 0.5); - new_height = floor (src_height * factor + 0.5); - - return gdk_pixbuf_scale_simple (src, new_width, new_height, GDK_INTERP_BILINEAR); -} - -static GdkPixbuf * -pixbuf_scale_to_min (GdkPixbuf *src, int min_width, int min_height) -{ - double factor; - int src_width, src_height; - int new_width, new_height; - GdkPixbuf *dest; - - src_width = gdk_pixbuf_get_width (src); - src_height = gdk_pixbuf_get_height (src); - - factor = MAX (min_width / (double) src_width, min_height / (double) src_height); - - new_width = floor (src_width * factor + 0.5); - new_height = floor (src_height * factor + 0.5); - - dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - gdk_pixbuf_get_has_alpha (src), - 8, min_width, min_height); - if (!dest) - return NULL; - - /* crop the result */ - gdk_pixbuf_scale (src, dest, - 0, 0, - min_width, min_height, - (new_width - min_width) / -2, - (new_height - min_height) / -2, - factor, - factor, - GDK_INTERP_BILINEAR); - return dest; -} - -static guchar * -create_gradient (const GdkRGBA *primary, - const GdkRGBA *secondary, - int n_pixels) -{ - guchar *result = g_malloc (n_pixels * 3); - int i; - - for (i = 0; i < n_pixels; ++i) { - double ratio = (i + 0.5) / n_pixels; - - result[3 * i + 0] = (int) (0.5 + (primary->red * (1 - ratio) + secondary->red * ratio) * 255); - result[3 * i + 1] = (int) (0.5 + (primary->green * (1 - ratio) + secondary->green * ratio) * 255); - result[3 * i + 2] = (int) (0.5 + (primary->blue * (1 - ratio) + secondary->blue * ratio) * 255); - } - - return result; -} - -static void -pixbuf_draw_gradient (GdkPixbuf *pixbuf, - gboolean horizontal, - GdkRGBA *primary, - GdkRGBA *secondary, - GdkRectangle *rect) -{ - int width; - int height; - int rowstride; - guchar *dst; - int n_channels = 3; - - rowstride = gdk_pixbuf_get_rowstride (pixbuf); - width = rect->width; - height = rect->height; - dst = gdk_pixbuf_get_pixels (pixbuf) + rect->x * n_channels + rowstride * rect->y; - - if (horizontal) { - guchar *gradient = create_gradient (primary, secondary, width); - int copy_bytes_per_row = width * n_channels; - int i; - - for (i = 0; i < height; i++) { - guchar *d; - d = dst + rowstride * i; - memcpy (d, gradient, copy_bytes_per_row); - } - g_free (gradient); - } else { - guchar *gb, *gradient; - int i; - - gradient = create_gradient (primary, secondary, height); - for (i = 0; i < height; i++) { - int j; - guchar *d; - - d = dst + rowstride * i; - gb = gradient + n_channels * i; - for (j = width; j > 0; j--) { - int k; - - for (k = 0; k < n_channels; k++) { - *(d++) = gb[k]; - } - } - } - - g_free (gradient); - } -} - -static void -pixbuf_blend (GdkPixbuf *src, - GdkPixbuf *dest, - int src_x, - int src_y, - int src_width, - int src_height, - int dest_x, - int dest_y, - double alpha) -{ - int dest_width = gdk_pixbuf_get_width (dest); - int dest_height = gdk_pixbuf_get_height (dest); - int offset_x = dest_x - src_x; - int offset_y = dest_y - src_y; - - if (src_width < 0) - src_width = gdk_pixbuf_get_width (src); - - if (src_height < 0) - src_height = gdk_pixbuf_get_height (src); - - if (dest_x < 0) - dest_x = 0; - - if (dest_y < 0) - dest_y = 0; - - if (dest_x + src_width > dest_width) { - src_width = dest_width - dest_x; - } - - if (dest_y + src_height > dest_height) { - src_height = dest_height - dest_y; - } - - gdk_pixbuf_composite (src, dest, - dest_x, dest_y, - src_width, src_height, - offset_x, offset_y, - 1, 1, GDK_INTERP_NEAREST, - alpha * 0xFF + 0.5); -} - -static void -pixbuf_tile (GdkPixbuf *src, GdkPixbuf *dest) -{ - int x, y; - int tile_width, tile_height; - int dest_width = gdk_pixbuf_get_width (dest); - int dest_height = gdk_pixbuf_get_height (dest); - tile_width = gdk_pixbuf_get_width (src); - tile_height = gdk_pixbuf_get_height (src); - - for (y = 0; y < dest_height; y += tile_height) { - for (x = 0; x < dest_width; x += tile_width) { - pixbuf_blend (src, dest, 0, 0, - tile_width, tile_height, x, y, 1.0); - } - } -} - -static GnomeBGSlideShow * -read_slideshow_file (const char *filename, - GError **err) -{ - GnomeBGSlideShow *show; - - show = gnome_bg_slide_show_new (filename); - - if (!gnome_bg_slide_show_load (show, err)) { - g_object_unref (show); - return NULL; - } - - return show; -} - -/* Thumbnail utilities */ -static GdkPixbuf * -create_thumbnail_for_filename (GnomeDesktopThumbnailFactory *factory, - const char *filename) -{ - char *thumb; - time_t mtime; - GdkPixbuf *orig, *result = NULL; - char *uri; - - mtime = get_mtime (filename); - - if (mtime == (time_t)-1) - return NULL; - - uri = g_filename_to_uri (filename, NULL, NULL); - - if (uri == NULL) - return NULL; - - thumb = gnome_desktop_thumbnail_factory_lookup (factory, uri, mtime); - - if (thumb) { - result = gdk_pixbuf_new_from_file (thumb, NULL); - g_free (thumb); - } - else { - orig = gdk_pixbuf_new_from_file (filename, NULL); - if (orig) { - int orig_width, orig_height; - GdkPixbuf *rotated; - - rotated = gdk_pixbuf_apply_embedded_orientation (orig); - if (rotated != NULL) { - g_object_unref (orig); - orig = rotated; - } - - orig_width = gdk_pixbuf_get_width (orig); - orig_height = gdk_pixbuf_get_height (orig); - - result = pixbuf_scale_to_fit (orig, THUMBNAIL_SIZE, THUMBNAIL_SIZE); - - g_object_set_data_full (G_OBJECT (result), "gnome-thumbnail-height", - g_strdup_printf ("%d", orig_height), g_free); - g_object_set_data_full (G_OBJECT (result), "gnome-thumbnail-width", - g_strdup_printf ("%d", orig_width), g_free); - - g_object_unref (orig); - - gnome_desktop_thumbnail_factory_save_thumbnail (factory, result, uri, mtime); - } - else { - gnome_desktop_thumbnail_factory_create_failed_thumbnail (factory, uri, mtime); - } - } - - g_free (uri); - - return result; -} - -static gboolean -get_thumb_annotations (GdkPixbuf *thumb, - int *orig_width, - int *orig_height) -{ - char *end; - const char *wstr, *hstr; - - wstr = gdk_pixbuf_get_option (thumb, "tEXt::Thumb::Image::Width"); - hstr = gdk_pixbuf_get_option (thumb, "tEXt::Thumb::Image::Height"); - - if (hstr && wstr) { - *orig_width = strtol (wstr, &end, 10); - if (*end != 0) - return FALSE; - - *orig_height = strtol (hstr, &end, 10); - if (*end != 0) - return FALSE; - - return TRUE; - } - - return FALSE; -} - -/* - * Returns whether the background is a slideshow. - */ -gboolean -gnome_bg_changes_with_time (GnomeBG *bg) -{ - GnomeBGSlideShow *show; - gboolean ret = FALSE; - - g_return_val_if_fail (bg != NULL, FALSE); - - if (!bg->filename) - return FALSE; - - show = get_as_slideshow (bg, bg->filename); - if (show) { - ret = gnome_bg_slide_show_get_num_slides (show) > 1; - g_object_unref (show); - } - - return ret; -} - -/** - * gnome_bg_create_frame_thumbnail: - * - * Creates a thumbnail for a certain frame, where 'frame' is somewhat - * vaguely defined as 'suitable point to show while single-stepping - * through the slideshow'. - * - * Returns: (transfer full): the newly created thumbnail or - * or NULL if frame_num is out of bounds. - */ -GdkPixbuf * -gnome_bg_create_frame_thumbnail (GnomeBG *bg, - GnomeDesktopThumbnailFactory *factory, - GdkScreen *screen, - int dest_width, - int dest_height, - int frame_num) -{ - GnomeBGSlideShow *show; - GdkPixbuf *result; - GdkPixbuf *thumb; - int skipped; - gboolean is_fixed; - - g_return_val_if_fail (bg != NULL, FALSE); - - show = get_as_slideshow (bg, bg->filename); - - if (!show) - return NULL; - - - if (frame_num < 0 || frame_num >= gnome_bg_slide_show_get_num_slides (show)) - return NULL; - - - gnome_bg_slide_show_get_slide (show, frame_num, dest_width, dest_height, NULL, NULL, &is_fixed, NULL, NULL); - - skipped = 0; - while (!is_fixed) { - skipped++; - gnome_bg_slide_show_get_slide (show, frame_num, dest_width, dest_height, NULL, NULL, &is_fixed, NULL, NULL); - } - - result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, dest_width, dest_height); - - draw_color (bg, result); - - if (bg->placement != G_DESKTOP_BACKGROUND_STYLE_NONE) { - thumb = create_img_thumbnail (bg, factory, screen, dest_width, dest_height, frame_num + skipped); - - if (thumb) { - draw_image_for_thumb (bg, thumb, result); - g_object_unref (thumb); - } - } - - return result; -} - diff --git a/libgnome-desktop/gnome-bg.h b/libgnome-desktop/gnome-bg.h deleted file mode 100644 index a51ccbee..00000000 --- a/libgnome-desktop/gnome-bg.h +++ /dev/null @@ -1,109 +0,0 @@ -/* gnome-bg.h - - - Copyright 2007, Red Hat, Inc. - - This file is part of the Gnome Library. - - The Gnome Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The Gnome Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the Gnome Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - - Author: Soren Sandmann <sandmann@redhat.com> -*/ - -#ifndef __GNOME_BG_H__ -#define __GNOME_BG_H__ - -#ifndef GNOME_DESKTOP_USE_UNSTABLE_API -#error GnomeBG is unstable API. You must define GNOME_DESKTOP_USE_UNSTABLE_API before including gnome-bg.h -#endif - -#include <gdk/gdk.h> -#include <gio/gio.h> -#include <gdesktop-enums.h> -#include <libgnome-desktop/gnome-desktop-thumbnail.h> -#include <libgnome-desktop/gnome-bg-crossfade.h> -#include <gdesktop-enums.h> - -G_BEGIN_DECLS - -#define GNOME_TYPE_BG (gnome_bg_get_type ()) -#define GNOME_BG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNOME_TYPE_BG, GnomeBG)) -#define GNOME_BG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNOME_TYPE_BG, GnomeBGClass)) -#define GNOME_IS_BG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNOME_TYPE_BG)) -#define GNOME_IS_BG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNOME_TYPE_BG)) -#define GNOME_BG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNOME_TYPE_BG, GnomeBGClass)) - -typedef struct _GnomeBG GnomeBG; -typedef struct _GnomeBGClass GnomeBGClass; - -G_DEFINE_AUTOPTR_CLEANUP_FUNC(GnomeBG, g_object_unref) - -GType gnome_bg_get_type (void); -GnomeBG * gnome_bg_new (void); -void gnome_bg_load_from_preferences (GnomeBG *bg, - GSettings *settings); -void gnome_bg_save_to_preferences (GnomeBG *bg, - GSettings *settings); -/* Setters */ -void gnome_bg_set_filename (GnomeBG *bg, - const char *filename); -void gnome_bg_set_placement (GnomeBG *bg, - GDesktopBackgroundStyle placement); -void gnome_bg_set_rgba (GnomeBG *bg, - GDesktopBackgroundShading type, - GdkRGBA *primary, - GdkRGBA *secondary); - -/* Getters */ -GDesktopBackgroundStyle gnome_bg_get_placement (GnomeBG *bg); -void gnome_bg_get_rgba (GnomeBG *bg, - GDesktopBackgroundShading *type, - GdkRGBA *primary, - GdkRGBA *secondary); -const gchar * gnome_bg_get_filename (GnomeBG *bg); - -/* Drawing and thumbnailing */ -void gnome_bg_draw (GnomeBG *bg, - GdkPixbuf *dest); -cairo_surface_t *gnome_bg_create_surface (GnomeBG *bg, - GdkWindow *window, - int width, - int height); -gboolean gnome_bg_get_image_size (GnomeBG *bg, - GnomeDesktopThumbnailFactory *factory, - int best_width, - int best_height, - int *width, - int *height); -GdkPixbuf * gnome_bg_create_thumbnail (GnomeBG *bg, - GnomeDesktopThumbnailFactory *factory, - GdkScreen *screen, - int dest_width, - int dest_height); -gboolean gnome_bg_is_dark (GnomeBG *bg, - int dest_width, - int dest_height); -gboolean gnome_bg_has_multiple_sizes (GnomeBG *bg); -gboolean gnome_bg_changes_with_time (GnomeBG *bg); -GdkPixbuf * gnome_bg_create_frame_thumbnail (GnomeBG *bg, - GnomeDesktopThumbnailFactory *factory, - GdkScreen *screen, - int dest_width, - int dest_height, - int frame_num); - -G_END_DECLS - -#endif diff --git a/libgnome-desktop/meson.build b/libgnome-desktop/meson.build index ca1e4b2a..66bd4fc7 100644 --- a/libgnome-desktop/meson.build +++ b/libgnome-desktop/meson.build @@ -11,9 +11,6 @@ libargs = [ introspection_sources = [ 'gnome-desktop-thumbnail.c', - 'gnome-bg.c', - 'gnome-bg-slide-show.c', - 'gnome-bg-crossfade.c', 'gnome-rr.c', 'gnome-rr-config.c', 'gnome-rr-output-info.c', @@ -52,9 +49,6 @@ libgnome_desktop_sources = [ ] libgnome_desktop_headers = [ - 'gnome-bg.h', - 'gnome-bg-crossfade.h', - 'gnome-bg-slide-show.h', 'gnome-desktop-thumbnail.h', 'gnome-rr.h', 'gnome-rr-config.h', |