/** * 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 (); }
static void init_fade (AthenaDesktopBackground *self) { GtkWidget *widget; gboolean do_fade; widget = self->details->widget; if (widget == NULL || !gtk_widget_get_realized (widget)) return; do_fade = g_settings_get_boolean (athena_desktop_preferences, ATHENA_PREFERENCES_DESKTOP_BACKGROUND_FADE); if (!do_fade) { return; } if (self->details->fade == NULL) { GdkWindow *window; GdkScreen *screen; int old_width, old_height, width, height; /* If this was the result of a screen size change, * we don't want to crossfade */ window = gtk_widget_get_window (widget); old_width = gdk_window_get_width (window); old_height = gdk_window_get_height (window); screen = gtk_widget_get_screen (widget); width = gdk_screen_get_width (screen); height = gdk_screen_get_height (screen); if (old_width == width && old_height == height) { self->details->fade = gnome_bg_crossfade_new (width, height); g_signal_connect_swapped (self->details->fade, "finished", G_CALLBACK (free_fade), self); } } if (self->details->fade != NULL && !gnome_bg_crossfade_is_started (self->details->fade)) { cairo_surface_t *start_surface; if (self->details->background_surface == NULL) { start_surface = gnome_bg_get_surface_from_root (gtk_widget_get_screen (widget)); } else { start_surface = cairo_surface_reference (self->details->background_surface); } gnome_bg_crossfade_set_start_surface (self->details->fade, start_surface); cairo_surface_destroy (start_surface); } }
/** * 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; }
static gboolean fade_to_surface (AthenaDesktopBackground *self, GdkWindow *window, cairo_surface_t *surface) { if (self->details->fade == NULL) { return FALSE; } if (!gnome_bg_crossfade_set_end_surface (self->details->fade, surface)) { return FALSE; } if (!gnome_bg_crossfade_is_started (self->details->fade)) { gnome_bg_crossfade_start (self->details->fade, window); g_signal_connect (self->details->fade, "finished", G_CALLBACK (on_fade_finished), self); } return gnome_bg_crossfade_is_started (self->details->fade); }