[gnome-flashback] desktop: handle background drawing
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-flashback] desktop: handle background drawing
- Date: Tue, 29 Oct 2019 13:32:16 +0000 (UTC)
commit 7417f4762aa66d032d645310e1959ef4a6da3b2e
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date: Tue Oct 29 15:28:04 2019 +0200
desktop: handle background drawing
gnome-flashback/libdesktop/gf-background.c | 284 ++++++++++++++++++++++++++++-
1 file changed, 280 insertions(+), 4 deletions(-)
---
diff --git a/gnome-flashback/libdesktop/gf-background.c b/gnome-flashback/libdesktop/gf-background.c
index 334bba1..5e88c02 100644
--- a/gnome-flashback/libdesktop/gf-background.c
+++ b/gnome-flashback/libdesktop/gf-background.c
@@ -18,14 +18,38 @@
#include "config.h"
#include "gf-background.h"
+#include <libgnome-desktop/gnome-bg.h>
+
+#include "gf-desktop-window.h"
+
+typedef struct
+{
+ cairo_surface_t *start;
+ cairo_surface_t *end;
+
+ double start_time;
+ double total_duration;
+ gboolean is_first_frame;
+ double percent_done;
+
+ guint timeout_id;
+} FadeData;
+
struct _GfBackground
{
- GObject parent;
+ GObject parent;
+
+ GtkWidget *window;
+
+ GSettings *settings1;
+ GSettings *settings2;
- GtkWidget *window;
+ GnomeBG *bg;
- GSettings *settings1;
- GSettings *settings2;
+ guint change_id;
+
+ FadeData *fade_data;
+ cairo_surface_t *surface;
};
enum
@@ -50,6 +74,213 @@ static guint background_signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE (GfBackground, gf_background, G_TYPE_OBJECT)
+static void
+free_fade_data (FadeData *data)
+{
+ if (data->timeout_id != 0)
+ {
+ g_source_remove (data->timeout_id);
+ data->timeout_id = 0;
+ }
+
+ g_clear_pointer (&data->start, cairo_surface_destroy);
+ g_clear_pointer (&data->end, cairo_surface_destroy);
+ g_free (data);
+}
+
+static gboolean
+fade_cb (gpointer user_data)
+{
+ GfBackground *self;
+ FadeData *fade;
+ double current_time;
+ double percent_done;
+ GdkScreen *screen;
+
+ self = GF_BACKGROUND (user_data);
+ fade = self->fade_data;
+
+ current_time = g_get_real_time () / (double) G_USEC_PER_SEC;
+ percent_done = (current_time - fade->start_time) / fade->total_duration;
+ percent_done = CLAMP (percent_done, 0.0, 1.0);
+
+ if (fade->is_first_frame && percent_done > 0.33)
+ {
+ fade->total_duration *= 1.5;
+ fade->is_first_frame = FALSE;
+
+ return fade_cb (self);
+ }
+
+ gtk_widget_queue_draw (self->window);
+
+ fade->is_first_frame = FALSE;
+ fade->percent_done = percent_done;
+
+ if (percent_done < 0.99)
+ return G_SOURCE_CONTINUE;
+
+ self->fade_data->timeout_id = 0;
+
+ g_clear_pointer (&self->surface, cairo_surface_destroy);
+ self->surface = cairo_surface_reference (fade->end);
+
+ g_clear_pointer (&self->fade_data, free_fade_data);
+
+ screen = gtk_widget_get_screen (self->window);
+ gnome_bg_set_surface_as_root (screen, self->surface);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+change (GfBackground *self,
+ gboolean fade)
+{
+ GdkScreen *screen;
+ GdkWindow *root;
+ int width;
+ int height;
+
+ screen = gtk_widget_get_screen (self->window);
+ root = gdk_screen_get_root_window (screen);
+
+ width = gf_desktop_window_get_width (GF_DESKTOP_WINDOW (self->window));
+ height = gf_desktop_window_get_height (GF_DESKTOP_WINDOW (self->window));
+
+ if (fade)
+ {
+ FadeData *data;
+
+ g_assert (self->fade_data == NULL);
+ self->fade_data = data = g_new0 (FadeData, 1);
+
+ if (self->surface != NULL)
+ data->start = cairo_surface_reference (self->surface);
+ else
+ data->start = gnome_bg_get_surface_from_root (screen);
+
+ data->end = gnome_bg_create_surface (self->bg, root, width, height, TRUE);
+
+ data->start_time = g_get_real_time () / (double) G_USEC_PER_SEC;
+ data->total_duration = .75;
+ data->is_first_frame = TRUE;
+ data->percent_done = .0;
+
+ data->timeout_id = g_timeout_add (1000 / 60.0, fade_cb, self);
+ }
+ else
+ {
+ g_clear_pointer (&self->surface, cairo_surface_destroy);
+ self->surface = gnome_bg_create_surface (self->bg,
+ root,
+ width,
+ height,
+ TRUE);
+
+ gnome_bg_set_surface_as_root (screen, self->surface);
+ }
+
+ g_signal_emit (self, background_signals[READY], 0);
+ gtk_widget_queue_draw (self->window);
+}
+
+typedef struct
+{
+ GfBackground *background;
+ gboolean fade;
+} ChangeData;
+
+static gboolean
+change_cb (gpointer user_data)
+{
+ ChangeData *data;
+
+ data = (ChangeData *) user_data;
+
+ change (data->background, data->fade);
+ data->background->change_id = 0;
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+queue_change (GfBackground *self,
+ gboolean fade)
+{
+ ChangeData *data;
+
+ if (self->change_id != 0)
+ return;
+
+ data = g_new (ChangeData, 1);
+
+ data->background = self;
+ data->fade = fade;
+
+ self->change_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+ change_cb, data, g_free);
+
+ g_source_set_name_by_id (self->change_id, "[gnome-flashback] change_cb");
+}
+
+static gboolean
+draw_cb (GtkWidget *widget,
+ cairo_t *cr,
+ GfBackground *self)
+{
+ if (self->fade_data != NULL)
+ {
+ cairo_set_source_surface (cr, self->fade_data->start, 0, 0);
+ cairo_paint (cr);
+
+ cairo_set_source_surface (cr, self->fade_data->end, 0, 0);
+ cairo_paint_with_alpha (cr, self->fade_data->percent_done);
+ }
+ else if (self->surface != NULL)
+ {
+ cairo_set_source_surface (cr, self->surface, 0, 0);
+ cairo_paint (cr);
+ }
+
+ return FALSE;
+}
+
+static void
+size_changed_cb (GfDesktopWindow *window,
+ GfBackground *self)
+{
+ queue_change (self, FALSE);
+}
+
+static gboolean
+change_event_cb (GSettings *settings,
+ gpointer keys,
+ gint n_keys,
+ GfBackground *self)
+{
+ gnome_bg_load_from_preferences (self->bg, self->settings1);
+
+ return TRUE;
+}
+
+static void
+changed_cb (GnomeBG *bg,
+ GfBackground *self)
+{
+ gboolean fade;
+
+ fade = g_settings_get_boolean (self->settings2, "fade");
+ queue_change (self, fade);
+}
+
+static void
+transitioned_cb (GnomeBG *bg,
+ GfBackground *self)
+{
+ queue_change (self, FALSE);
+}
+
static void
gf_background_constructed (GObject *object)
{
@@ -61,6 +292,30 @@ gf_background_constructed (GObject *object)
self->settings1 = g_settings_new ("org.gnome.desktop.background");
self->settings2 = g_settings_new ("org.gnome.gnome-flashback.desktop.background");
+
+ self->bg = gnome_bg_new ();
+
+ g_signal_connect_object (self->window, "draw",
+ G_CALLBACK (draw_cb),
+ self, 0);
+
+ g_signal_connect_object (self->window, "size-changed",
+ G_CALLBACK (size_changed_cb),
+ self, 0);
+
+ g_signal_connect (self->settings1, "change-event",
+ G_CALLBACK (change_event_cb),
+ self);
+
+ g_signal_connect (self->bg, "changed",
+ G_CALLBACK (changed_cb),
+ self);
+
+ g_signal_connect (self->bg, "transitioned",
+ G_CALLBACK (transitioned_cb),
+ self);
+
+ gnome_bg_load_from_preferences (self->bg, self->settings1);
}
static void
@@ -72,10 +327,30 @@ gf_background_dispose (GObject *object)
g_clear_object (&self->settings1);
g_clear_object (&self->settings2);
+ g_clear_object (&self->bg);
G_OBJECT_CLASS (gf_background_parent_class)->dispose (object);
}
+static void
+gf_background_finalize (GObject *object)
+{
+ GfBackground *self;
+
+ self = GF_BACKGROUND (object);
+
+ if (self->change_id != 0)
+ {
+ g_source_remove (self->change_id);
+ self->change_id = 0;
+ }
+
+ g_clear_pointer (&self->fade_data, free_fade_data);
+ g_clear_pointer (&self->surface, cairo_surface_destroy);
+
+ G_OBJECT_CLASS (gf_background_parent_class)->finalize (object);
+}
+
static void
gf_background_set_property (GObject *object,
guint property_id,
@@ -131,6 +406,7 @@ gf_background_class_init (GfBackgroundClass *self_class)
object_class->constructed = gf_background_constructed;
object_class->dispose = gf_background_dispose;
+ object_class->finalize = gf_background_finalize;
object_class->set_property = gf_background_set_property;
install_properties (object_class);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]