[gnome-control-center/wip/exalm/dark-wallpapers: 1/2] background: Support dark wallpapers




commit 85f1860000c5f982073cff31940b9693eb4d9758
Author: Alexander Mikhaylenko <alexm gnome org>
Date:   Sat Nov 27 17:53:52 2021 +0500

    background: Support dark wallpapers

 panels/background/cc-background-chooser.c   |  30 ++-
 panels/background/cc-background-item.c      | 134 +++++++++---
 panels/background/cc-background-item.h      |  15 +-
 panels/background/cc-background-paintable.c | 306 ++++++++++++++++++++++++++++
 panels/background/cc-background-paintable.h |  35 ++++
 panels/background/cc-background-panel.c     |  24 ++-
 panels/background/cc-background-preview.c   |   4 +-
 panels/background/cc-background-xml.c       |  21 ++
 panels/background/meson.build               |   1 +
 9 files changed, 526 insertions(+), 44 deletions(-)
---
diff --git a/panels/background/cc-background-chooser.c b/panels/background/cc-background-chooser.c
index 587bbad1f..43b093877 100644
--- a/panels/background/cc-background-chooser.c
+++ b/panels/background/cc-background-chooser.c
@@ -28,6 +28,7 @@
 #include "bg-recent-source.h"
 #include "bg-wallpapers-source.h"
 #include "cc-background-chooser.h"
+#include "cc-background-paintable.h"
 
 struct _CcBackgroundChooser
 {
@@ -84,11 +85,21 @@ on_delete_background_clicked_cb (GtkButton *button,
   bg_recent_source_remove_item (source, item);
 }
 
+static void
+direction_changed_cb (GtkWidget        *widget,
+                      GtkTextDirection *previous_direction,
+                      GdkPaintable     *paintable)
+{
+  g_object_set (paintable,
+                "text-direction", gtk_widget_get_direction (widget),
+                NULL);
+}
+
 static GtkWidget*
 create_widget_func (gpointer model_item,
                     gpointer user_data)
 {
-  g_autoptr(GdkPixbuf) pixbuf = NULL;
+  g_autoptr(CcBackgroundPaintable) paintable = NULL;
   CcBackgroundItem *item;
   GtkWidget *overlay;
   GtkWidget *child;
@@ -100,14 +111,19 @@ create_widget_func (gpointer model_item,
 
   source = BG_SOURCE (user_data);
   item = CC_BACKGROUND_ITEM (model_item);
-  pixbuf = cc_background_item_get_thumbnail (item,
-                                             bg_source_get_thumbnail_factory (source),
-                                             bg_source_get_thumbnail_width (source),
-                                             bg_source_get_thumbnail_height (source),
-                                             bg_source_get_scale_factor (source));
-  picture = gtk_picture_new_for_pixbuf (pixbuf);
+
+  paintable = cc_background_paintable_new (source, item);
+
+  picture = gtk_picture_new_for_paintable (GDK_PAINTABLE (paintable));
   gtk_picture_set_can_shrink (GTK_PICTURE (picture), FALSE);
 
+  g_object_bind_property (picture, "scale-factor",
+                          paintable, "scale-factor", G_BINDING_SYNC_CREATE);
+  g_object_bind_property (picture, "text-direction",
+                          paintable, "text-direction", G_BINDING_SYNC_CREATE);
+  g_signal_connect_object (picture, "direction-changed",
+                           G_CALLBACK (direction_changed_cb), paintable, 0);
+
   icon = gtk_image_new_from_icon_name ("slideshow-symbolic");
   gtk_widget_set_halign (icon, GTK_ALIGN_START);
   gtk_widget_set_valign (icon, GTK_ALIGN_END);
diff --git a/panels/background/cc-background-item.c b/panels/background/cc-background-item.c
index b69a9d940..e25c8c43d 100644
--- a/panels/background/cc-background-item.c
+++ b/panels/background/cc-background-item.c
@@ -32,6 +32,14 @@
 #include "cc-background-item.h"
 #include "gdesktop-enums-types.h"
 
+typedef struct {
+        int        width;
+        int        height;
+        int        frame;
+        int        scale_factor;
+        GdkPixbuf *thumbnail;
+} CachedThumbnail;
+
 struct _CcBackgroundItem
 {
         GObject          parent_instance;
@@ -39,6 +47,7 @@ struct _CcBackgroundItem
         /* properties */
         char            *name;
         char            *uri;
+        char            *uri_dark;
         char            *size;
         GDesktopBackgroundStyle placement;
         GDesktopBackgroundShading shading;
@@ -57,19 +66,17 @@ struct _CcBackgroundItem
         int              width;
         int              height;
 
-        struct {
-                int        width;
-                int        height;
-                int        frame;
-                int        scale_factor;
-                GdkPixbuf *thumbnail;
-        } cached_thumbnail;
+        GnomeBG         *bg_dark;
+
+        CachedThumbnail cached_thumbnail;
+        CachedThumbnail cached_thumbnail_dark;
 };
 
 enum {
         PROP_0,
         PROP_NAME,
         PROP_URI,
+        PROP_URI_DARK,
         PROP_PLACEMENT,
         PROP_SHADING,
         PROP_PRIMARY_COLOR,
@@ -102,6 +109,15 @@ set_bg_properties (CcBackgroundItem *item)
                gnome_bg_set_filename (item->bg, filename);
        }
 
+        if (item->uri_dark) {
+               g_autoptr(GFile) file = NULL;
+               g_autofree gchar *filename = NULL;
+
+               file = g_file_new_for_commandline_arg (item->uri_dark);
+               filename = g_file_get_path (file);
+               gnome_bg_set_filename (item->bg_dark, filename);
+       }
+
         if (item->primary_color != NULL) {
                 gdk_rgba_parse (&pcolor, item->primary_color);
         }
@@ -110,7 +126,9 @@ set_bg_properties (CcBackgroundItem *item)
         }
 
         gnome_bg_set_rgba (item->bg, item->shading, &pcolor, &scolor);
+        gnome_bg_set_rgba (item->bg_dark, item->shading, &pcolor, &scolor);
         gnome_bg_set_placement (item->bg, item->placement);
+        gnome_bg_set_placement (item->bg_dark, item->placement);
 }
 
 
@@ -125,9 +143,20 @@ cc_background_item_changes_with_time (CcBackgroundItem *item)
         if (item->bg != NULL) {
                 changes = gnome_bg_changes_with_time (item->bg);
         }
+        if (item->bg_dark != NULL) {
+                changes |= gnome_bg_changes_with_time (item->bg_dark);
+        }
         return changes;
 }
 
+gboolean
+cc_background_item_has_dark_version (CcBackgroundItem *item)
+{
+       g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), FALSE);
+
+        return item->uri && item->uri_dark;
+}
+
 static void
 update_size (CcBackgroundItem *item)
 {
@@ -168,21 +197,27 @@ cc_background_item_get_frame_thumbnail (CcBackgroundItem             *item,
                                         int                           height,
                                         int                           scale_factor,
                                         int                           frame,
-                                        gboolean                      force_size)
+                                        gboolean                      force_size,
+                                        gboolean                      dark)
 {
         g_autoptr(GdkPixbuf) pixbuf = NULL;
         g_autoptr(GdkPixbuf) retval = NULL;
+        CachedThumbnail *thumbnail;
+        GnomeBG *bg;
 
        g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
        g_return_val_if_fail (width > 0 && height > 0, NULL);
 
+        thumbnail = dark ? &item->cached_thumbnail_dark : &item->cached_thumbnail;
+        bg = dark ? item->bg_dark : item->bg;
+
         /* Use the cached thumbnail if the sizes match */
-        if (item->cached_thumbnail.thumbnail &&
-            item->cached_thumbnail.width == width &&
-            item->cached_thumbnail.height == height &&
-            item->cached_thumbnail.scale_factor == scale_factor &&
-            item->cached_thumbnail.frame == frame)
-                    return g_object_ref (item->cached_thumbnail.thumbnail);
+        if (thumbnail->thumbnail &&
+            thumbnail->width == width &&
+            thumbnail->height == height &&
+            thumbnail->scale_factor == scale_factor &&
+            thumbnail->frame == frame)
+                    return g_object_ref (thumbnail->thumbnail);
 
         set_bg_properties (item);
 
@@ -194,7 +229,7 @@ cc_background_item_get_frame_thumbnail (CcBackgroundItem             *item,
                  * the slideshow frame though, so we can't do much better than this
                  * for now.
                  */
-                pixbuf = render_at_size (item->bg, width, height);
+                pixbuf = render_at_size (bg, width, height);
         } else {
                 g_autoptr(GdkMonitor) monitor = NULL;
                 GdkDisplay *display;
@@ -208,14 +243,14 @@ cc_background_item_get_frame_thumbnail (CcBackgroundItem             *item,
                 gdk_monitor_get_geometry (monitor, &monitor_layout);
 
                 if (frame >= 0) {
-                        pixbuf = gnome_bg_create_frame_thumbnail (item->bg,
+                        pixbuf = gnome_bg_create_frame_thumbnail (bg,
                                                                   thumbs,
                                                                   &monitor_layout,
                                                                   width,
                                                                   height,
                                                                   frame);
                 } else {
-                        pixbuf = gnome_bg_create_thumbnail (item->bg,
+                        pixbuf = gnome_bg_create_thumbnail (bg,
                                                             thumbs,
                                                             &monitor_layout,
                                                             width,
@@ -225,7 +260,7 @@ cc_background_item_get_frame_thumbnail (CcBackgroundItem             *item,
 
         retval = g_steal_pointer (&pixbuf);
 
-        gnome_bg_get_image_size (item->bg,
+        gnome_bg_get_image_size (bg,
                                  thumbs,
                                  width,
                                  height,
@@ -235,11 +270,11 @@ cc_background_item_get_frame_thumbnail (CcBackgroundItem             *item,
         update_size (item);
 
         /* Cache the new thumbnail */
-        g_set_object (&item->cached_thumbnail.thumbnail, retval);
-        item->cached_thumbnail.width = width;
-        item->cached_thumbnail.height = height;
-        item->cached_thumbnail.scale_factor = scale_factor;
-        item->cached_thumbnail.frame = frame;
+        g_set_object (&thumbnail->thumbnail, retval);
+        thumbnail->width = width;
+        thumbnail->height = height;
+        thumbnail->scale_factor = scale_factor;
+        thumbnail->frame = frame;
 
         return g_steal_pointer (&retval);
 }
@@ -250,9 +285,10 @@ cc_background_item_get_thumbnail (CcBackgroundItem             *item,
                                   GnomeDesktopThumbnailFactory *thumbs,
                                   int                           width,
                                   int                           height,
-                                  int                           scale_factor)
+                                  int                           scale_factor,
+                                  gboolean                      dark)
 {
-        return cc_background_item_get_frame_thumbnail (item, thumbs, width, height, scale_factor, -1, FALSE);
+        return cc_background_item_get_frame_thumbnail (item, thumbs, width, height, scale_factor, -1, FALSE, 
dark);
 }
 
 static void
@@ -362,6 +398,21 @@ _set_uri (CcBackgroundItem *item,
        }
 }
 
+
+static void
+_set_uri_dark (CcBackgroundItem *item,
+               const char       *value)
+{
+        g_free (item->uri_dark);
+        if (value && *value == '\0') {
+               item->uri_dark = NULL;
+       } else {
+               if (value && strstr (value, "://") == NULL)
+                       g_warning ("URI '%s' is invalid", value);
+               item->uri_dark = g_strdup (value);
+       }
+}
+
 const char *
 cc_background_item_get_uri (CcBackgroundItem *item)
 {
@@ -370,6 +421,14 @@ cc_background_item_get_uri (CcBackgroundItem *item)
        return item->uri;
 }
 
+const char *
+cc_background_item_get_uri_dark (CcBackgroundItem *item)
+{
+       g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
+
+       return item->uri_dark;
+}
+
 static void
 _set_placement (CcBackgroundItem        *item,
                 GDesktopBackgroundStyle  value)
@@ -541,6 +600,9 @@ cc_background_item_set_property (GObject      *object,
         case PROP_URI:
                 _set_uri (self, g_value_get_string (value));
                 break;
+        case PROP_URI_DARK:
+                _set_uri_dark (self, g_value_get_string (value));
+                break;
         case PROP_PLACEMENT:
                 _set_placement (self, g_value_get_enum (value));
                 break;
@@ -591,9 +653,12 @@ cc_background_item_get_property (GObject    *object,
         case PROP_NAME:
                 g_value_set_string (value, self->name);
                 break;
-       case PROP_URI:
+        case PROP_URI:
                 g_value_set_string (value, self->uri);
                 break;
+        case PROP_URI_DARK:
+                g_value_set_string (value, self->uri_dark);
+                break;
         case PROP_PLACEMENT:
                 g_value_set_enum (value, self->placement);
                 break;
@@ -671,6 +736,13 @@ cc_background_item_class_init (CcBackgroundItemClass *klass)
                                                               "uri",
                                                               NULL,
                                                               G_PARAM_READWRITE));
+        g_object_class_install_property (object_class,
+                                         PROP_URI_DARK,
+                                         g_param_spec_string ("uri-dark",
+                                                              "uri-dark",
+                                                              "uri-dark",
+                                                              NULL,
+                                                              G_PARAM_READWRITE));
         g_object_class_install_property (object_class,
                                          PROP_PLACEMENT,
                                         g_param_spec_enum ("placement",
@@ -767,6 +839,7 @@ static void
 cc_background_item_init (CcBackgroundItem *item)
 {
         item->bg = gnome_bg_new ();
+        item->bg_dark = gnome_bg_new ();
 
         item->shading = G_DESKTOP_BACKGROUND_SHADING_SOLID;
         item->placement = G_DESKTOP_BACKGROUND_STYLE_SCALED;
@@ -790,6 +863,7 @@ cc_background_item_finalize (GObject *object)
         g_return_if_fail (item != NULL);
 
         g_clear_object (&item->cached_thumbnail.thumbnail);
+        g_clear_object (&item->cached_thumbnail_dark.thumbnail);
         g_free (item->name);
         g_free (item->uri);
         g_free (item->primary_color);
@@ -799,8 +873,8 @@ cc_background_item_finalize (GObject *object)
         g_free (item->source_url);
         g_free (item->source_xml);
 
-        if (item->bg != NULL)
-                g_object_unref (item->bg);
+        g_clear_object (&item->bg);
+        g_clear_object (&item->bg_dark);
 
         G_OBJECT_CLASS (cc_background_item_parent_class)->finalize (object);
 }
@@ -959,6 +1033,10 @@ cc_background_item_compare (CcBackgroundItem *saved,
                if (files_equal (saved->uri, configured->uri) == FALSE)
                        return FALSE;
        }
+       if (flags & CC_BACKGROUND_ITEM_HAS_URI_DARK) {
+               if (files_equal (saved->uri_dark, configured->uri_dark) == FALSE)
+                       return FALSE;
+       }
        if (flags & CC_BACKGROUND_ITEM_HAS_SHADING) {
                if (saved->shading != configured->shading)
                        return FALSE;
diff --git a/panels/background/cc-background-item.h b/panels/background/cc-background-item.h
index 9832d1e04..80fd5a2e7 100644
--- a/panels/background/cc-background-item.h
+++ b/panels/background/cc-background-item.h
@@ -35,7 +35,8 @@ typedef enum {
        CC_BACKGROUND_ITEM_HAS_PLACEMENT = 1 << 1,
        CC_BACKGROUND_ITEM_HAS_PCOLOR    = 1 << 2,
        CC_BACKGROUND_ITEM_HAS_SCOLOR    = 1 << 3,
-       CC_BACKGROUND_ITEM_HAS_URI       = 1 << 4
+       CC_BACKGROUND_ITEM_HAS_URI       = 1 << 4,
+       CC_BACKGROUND_ITEM_HAS_URI_DARK  = 1 << 5
 } CcBackgroundItemFlags;
 
 #define CC_BACKGROUND_ITEM_HAS_ALL (CC_BACKGROUND_ITEM_HAS_SHADING &   \
@@ -46,26 +47,30 @@ typedef enum {
 
 CcBackgroundItem * cc_background_item_new                 (const char                   *uri);
 CcBackgroundItem * cc_background_item_copy                (CcBackgroundItem             *item);
-gboolean           cc_background_item_load                (CcBackgroundItem             *item,
-                                                          GFileInfo                    *info);
+gboolean           cc_background_item_load                (CcBackgroundItem *item,
+                                                           GFileInfo        *info);
 gboolean           cc_background_item_changes_with_time   (CcBackgroundItem             *item);
+gboolean           cc_background_item_has_dark_version    (CcBackgroundItem             *item);
 
 GdkPixbuf *        cc_background_item_get_thumbnail       (CcBackgroundItem             *item,
                                                            GnomeDesktopThumbnailFactory *thumbs,
                                                            int                           width,
                                                            int                           height,
-                                                           int                           scale_factor);
+                                                           int                           scale_factor,
+                                                           gboolean                      dark);
 GdkPixbuf *        cc_background_item_get_frame_thumbnail (CcBackgroundItem             *item,
                                                            GnomeDesktopThumbnailFactory *thumbs,
                                                            int                           width,
                                                            int                           height,
                                                            int                           scale_factor,
                                                            int                           frame,
-                                                           gboolean                      force_size);
+                                                           gboolean                      force_size,
+                                                           gboolean                      dark);
 
 GDesktopBackgroundStyle   cc_background_item_get_placement  (CcBackgroundItem *item);
 GDesktopBackgroundShading cc_background_item_get_shading    (CcBackgroundItem *item);
 const char *              cc_background_item_get_uri        (CcBackgroundItem *item);
+const char *              cc_background_item_get_uri_dark   (CcBackgroundItem *item);
 const char *              cc_background_item_get_source_url (CcBackgroundItem *item);
 const char *              cc_background_item_get_source_xml (CcBackgroundItem *item);
 CcBackgroundItemFlags     cc_background_item_get_flags      (CcBackgroundItem *item);
diff --git a/panels/background/cc-background-paintable.c b/panels/background/cc-background-paintable.c
new file mode 100644
index 000000000..763370601
--- /dev/null
+++ b/panels/background/cc-background-paintable.c
@@ -0,0 +1,306 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2021 Alexander Mikhaylenko <alexm gnome org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+
+#include "cc-background-paintable.h"
+
+struct _CcBackgroundPaintable
+{
+  GObject           parent_instance;
+
+  BgSource         *source;
+  CcBackgroundItem *item;
+  int               scale_factor;
+  GtkTextDirection  text_direction;
+
+  GdkPaintable     *texture;
+  GdkPaintable     *dark_texture;
+};
+
+enum
+{
+  PROP_0,
+  PROP_SOURCE,
+  PROP_ITEM,
+  PROP_SCALE_FACTOR,
+  PROP_TEXT_DIRECTION,
+  N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+static void cc_background_paintable_paintable_init (GdkPaintableInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (CcBackgroundPaintable, cc_background_paintable, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
+                                                cc_background_paintable_paintable_init))
+
+static void
+update_cache (CcBackgroundPaintable *self)
+{
+  g_autoptr (GdkPixbuf) pixbuf = NULL;
+  GnomeDesktopThumbnailFactory *factory;
+  int width, height;
+
+  g_clear_object (&self->texture);
+  g_clear_object (&self->dark_texture);
+
+  factory = bg_source_get_thumbnail_factory (self->source);
+  width = bg_source_get_thumbnail_width (self->source);
+  height = bg_source_get_thumbnail_height (self->source);
+
+  pixbuf = cc_background_item_get_thumbnail (self->item,
+                                             factory,
+                                             width,
+                                             height,
+                                             self->scale_factor,
+                                             FALSE);
+
+  self->texture = GDK_PAINTABLE (gdk_texture_new_for_pixbuf (pixbuf));
+
+  if (cc_background_item_has_dark_version (self->item))
+    {
+      g_autoptr (GdkPixbuf) dark_pixbuf = NULL;
+
+      dark_pixbuf = cc_background_item_get_thumbnail (self->item,
+                                                      factory,
+                                                      width,
+                                                      height,
+                                                      self->scale_factor,
+                                                      TRUE);
+      self->dark_texture = GDK_PAINTABLE (gdk_texture_new_for_pixbuf (dark_pixbuf));
+    }
+
+  gdk_paintable_invalidate_size (GDK_PAINTABLE (self));
+}
+
+static void
+cc_background_paintable_dispose (GObject *object)
+{
+  CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (object);
+
+  g_clear_object (&self->item);
+  g_clear_object (&self->source);
+  g_clear_object (&self->texture);
+  g_clear_object (&self->dark_texture);
+
+  G_OBJECT_CLASS (cc_background_paintable_parent_class)->dispose (object);
+}
+
+static void
+cc_background_paintable_constructed (GObject *object)
+{
+  CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (object);
+
+  G_OBJECT_CLASS (cc_background_paintable_parent_class)->constructed (object);
+
+  update_cache (self);
+}
+
+static void
+cc_background_paintable_get_property (GObject    *object,
+                                      guint       prop_id,
+                                      GValue     *value,
+                                      GParamSpec *pspec)
+{
+  CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (object);
+
+  switch (prop_id)
+    {
+    case PROP_SOURCE:
+      g_value_set_object (value, self->source);
+      break;
+
+    case PROP_ITEM:
+      g_value_set_object (value, self->item);
+      break;
+
+    case PROP_SCALE_FACTOR:
+      g_value_set_int (value, self->scale_factor);
+      break;
+
+    case PROP_TEXT_DIRECTION:
+      g_value_set_enum (value, self->text_direction);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+cc_background_paintable_set_property (GObject      *object,
+                                      guint         prop_id,
+                                      const GValue *value,
+                                      GParamSpec   *pspec)
+{
+  CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (object);
+
+  switch (prop_id)
+    {
+    case PROP_SOURCE:
+      g_set_object (&self->source, g_value_get_object (value));
+      break;
+
+    case PROP_ITEM:
+      g_set_object (&self->item, g_value_get_object (value));
+      break;
+
+    case PROP_SCALE_FACTOR:
+      self->scale_factor = g_value_get_int (value);
+      update_cache (self);
+      break;
+
+    case PROP_TEXT_DIRECTION:
+      self->text_direction = g_value_get_enum (value);
+      gdk_paintable_invalidate_contents (GDK_PAINTABLE (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+cc_background_paintable_class_init (CcBackgroundPaintableClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->dispose = cc_background_paintable_dispose;
+  object_class->constructed = cc_background_paintable_constructed;
+  object_class->get_property = cc_background_paintable_get_property;
+  object_class->set_property = cc_background_paintable_set_property;
+
+  properties[PROP_SOURCE] =
+    g_param_spec_object ("source",
+                         "Source",
+                         "Source",
+                         BG_TYPE_SOURCE,
+                         G_PARAM_READWRITE |
+                         G_PARAM_CONSTRUCT_ONLY |
+                         G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_ITEM] =
+    g_param_spec_object ("item",
+                         "Item",
+                         "Item",
+                         CC_TYPE_BACKGROUND_ITEM,
+                         G_PARAM_READWRITE |
+                         G_PARAM_CONSTRUCT_ONLY |
+                         G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_SCALE_FACTOR] =
+    g_param_spec_int ("scale-factor",
+                      "Scale Factor",
+                      "Scale Factor",
+                      1, G_MAXINT, 1,
+                      G_PARAM_READWRITE |
+                      G_PARAM_STATIC_STRINGS);
+
+  properties[PROP_TEXT_DIRECTION] =
+    g_param_spec_enum ("text-direction",
+                       "Text Direction",
+                       "Text Direction",
+                       GTK_TYPE_TEXT_DIRECTION,
+                       GTK_TEXT_DIR_LTR,
+                       G_PARAM_READWRITE |
+                       G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+cc_background_paintable_init (CcBackgroundPaintable *self)
+{
+  self->scale_factor = 1;
+  self->text_direction = GTK_TEXT_DIR_LTR;
+}
+
+static void
+cc_background_paintable_snapshot (GdkPaintable *paintable,
+                                  GdkSnapshot  *snapshot,
+                                  double        width,
+                                  double        height)
+{
+  CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (paintable);
+
+  gdk_paintable_snapshot (self->texture, snapshot, width, height);
+
+  if (self->dark_texture)
+    {
+      gboolean is_rtl = self->text_direction == GTK_TEXT_DIR_RTL;
+
+      gtk_snapshot_push_clip (GTK_SNAPSHOT (snapshot),
+                              &GRAPHENE_RECT_INIT (is_rtl ? 0.0f : width / 2.0f,
+                                                   0.0f,
+                                                   width / 2.0f,
+                                                   height));
+
+      gdk_paintable_snapshot (self->dark_texture, snapshot, width, height);
+
+      gtk_snapshot_pop (GTK_SNAPSHOT (snapshot));
+    }
+}
+
+static int
+cc_background_paintable_get_intrinsic_width (GdkPaintable *paintable)
+{
+  CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (paintable);
+
+  return gdk_paintable_get_intrinsic_width (self->texture) / self->scale_factor;
+}
+
+static int
+cc_background_paintable_get_intrinsic_height (GdkPaintable *paintable)
+{
+  CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (paintable);
+
+  return gdk_paintable_get_intrinsic_height (self->texture) / self->scale_factor;
+}
+
+static double
+cc_background_paintable_get_intrinsic_aspect_ratio (GdkPaintable *paintable)
+{
+  CcBackgroundPaintable *self = CC_BACKGROUND_PAINTABLE (paintable);
+
+  return gdk_paintable_get_intrinsic_aspect_ratio (self->texture);
+}
+
+static void
+cc_background_paintable_paintable_init (GdkPaintableInterface *iface)
+{
+  iface->snapshot = cc_background_paintable_snapshot;
+  iface->get_intrinsic_width = cc_background_paintable_get_intrinsic_width;
+  iface->get_intrinsic_height = cc_background_paintable_get_intrinsic_height;
+  iface->get_intrinsic_aspect_ratio = cc_background_paintable_get_intrinsic_aspect_ratio;
+}
+
+CcBackgroundPaintable *
+cc_background_paintable_new (BgSource         *source,
+                             CcBackgroundItem *item)
+{
+  g_return_val_if_fail (BG_IS_SOURCE (source), NULL);
+  g_return_val_if_fail (CC_IS_BACKGROUND_ITEM (item), NULL);
+
+  return g_object_new (CC_TYPE_BACKGROUND_PAINTABLE,
+                       "source", source,
+                       "item", item,
+                       NULL);
+}
diff --git a/panels/background/cc-background-paintable.h b/panels/background/cc-background-paintable.h
new file mode 100644
index 000000000..75360dc40
--- /dev/null
+++ b/panels/background/cc-background-paintable.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2021 Alexander Mikhaylenko <alexm gnome org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "bg-source.h"
+#include "cc-background-item.h"
+
+G_BEGIN_DECLS
+
+#define CC_TYPE_BACKGROUND_PAINTABLE (cc_background_paintable_get_type ())
+G_DECLARE_FINAL_TYPE (CcBackgroundPaintable, cc_background_paintable, CC, BACKGROUND_PAINTABLE, GObject)
+
+CcBackgroundPaintable * cc_background_paintable_new (BgSource         *source,
+                                                     CcBackgroundItem *item);
+
+G_END_DECLS
diff --git a/panels/background/cc-background-panel.c b/panels/background/cc-background-panel.c
index d55566c55..8fff61f72 100644
--- a/panels/background/cc-background-panel.c
+++ b/panels/background/cc-background-panel.c
@@ -38,6 +38,7 @@
 #define WP_PATH_ID "org.gnome.desktop.background"
 #define WP_LOCK_PATH_ID "org.gnome.desktop.screensaver"
 #define WP_URI_KEY "picture-uri"
+#define WP_URI_DARK_KEY "picture-uri-dark"
 #define WP_OPTIONS_KEY "picture-options"
 #define WP_SHADING_KEY "color-shading-type"
 #define WP_PCOLOR_KEY "primary-color"
@@ -152,6 +153,7 @@ reload_current_bg (CcBackgroundPanel *panel)
   CcBackgroundItem *configured;
   GSettings *settings = NULL;
   g_autofree gchar *uri = NULL;
+  g_autofree gchar *dark_uri = NULL;
   g_autofree gchar *pcolor = NULL;
   g_autofree gchar *scolor = NULL;
 
@@ -165,12 +167,15 @@ reload_current_bg (CcBackgroundPanel *panel)
   if (uri && *uri == '\0')
     g_clear_pointer (&uri, g_free);
 
+
   configured = cc_background_item_new (uri);
 
+  dark_uri = g_settings_get_string (settings, WP_URI_DARK_KEY);
   pcolor = g_settings_get_string (settings, WP_PCOLOR_KEY);
   scolor = g_settings_get_string (settings, WP_SCOLOR_KEY);
   g_object_set (G_OBJECT (configured),
                 "name", _("Current background"),
+                "uri-dark", dark_uri,
                 "placement", g_settings_get_enum (settings, WP_OPTIONS_KEY),
                 "shading", g_settings_get_enum (settings, WP_SHADING_KEY),
                 "primary-color", pcolor,
@@ -217,7 +222,8 @@ create_save_dir (void)
 static void
 set_background (CcBackgroundPanel *panel,
                 GSettings         *settings,
-                CcBackgroundItem  *item)
+                CcBackgroundItem  *item,
+                gboolean           set_dark)
 {
   GDesktopBackgroundStyle style;
   CcBackgroundItemFlags flags;
@@ -232,6 +238,18 @@ set_background (CcBackgroundPanel *panel,
 
   g_settings_set_string (settings, WP_URI_KEY, uri);
 
+  if (set_dark)
+    {
+      const char *uri_dark;
+
+      uri_dark = cc_background_item_get_uri_dark (item);
+
+      if (uri_dark && uri_dark[0])
+        g_settings_set_string (settings, WP_URI_DARK_KEY, uri_dark);
+      else
+        g_settings_set_string (settings, WP_URI_DARK_KEY, uri);
+    }
+
   /* Also set the placement if we have a URI and the previous value was none */
   if (flags & CC_BACKGROUND_ITEM_HAS_PLACEMENT)
     {
@@ -263,8 +281,8 @@ static void
 on_chooser_background_chosen_cb (CcBackgroundPanel *self,
                                  CcBackgroundItem  *item)
 {
-  set_background (self, self->settings, item);
-  set_background (self, self->lock_settings, item);
+  set_background (self, self->settings, item, TRUE);
+  set_background (self, self->lock_settings, item, FALSE);
 }
 
 static void
diff --git a/panels/background/cc-background-preview.c b/panels/background/cc-background-preview.c
index 69de0249a..428c44f8b 100644
--- a/panels/background/cc-background-preview.c
+++ b/panels/background/cc-background-preview.c
@@ -71,7 +71,9 @@ draw_preview_func (GtkDrawingArea *drawing_area,
                                                    height,
                                                    scale_factor,
                                                    0,
-                                                   TRUE);
+                                                   TRUE,
+                                                   self->is_dark &&
+                                                   cc_background_item_has_dark_version (self->item));
 
 
   gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
diff --git a/panels/background/cc-background-xml.c b/panels/background/cc-background-xml.c
index 270fcc2fb..84f0a047e 100644
--- a/panels/background/cc-background-xml.c
+++ b/panels/background/cc-background-xml.c
@@ -210,6 +210,27 @@ cc_background_xml_load_xml_internal (CcBackgroundXml *xml,
          } else {
            break;
          }
+       } else if (!strcmp ((gchar *)wpa->name, "filename-dark")) {
+         if (wpa->last != NULL && wpa->last->content != NULL) {
+           gchar *content = g_strstrip ((gchar *)wpa->last->content);
+           g_autofree gchar *bg_uri = NULL;
+
+           /* FIXME same rubbish as in other parts of the code */
+           if (strcmp (content, NONE) == 0) {
+             bg_uri = NULL;
+           } else {
+             g_autoptr(GFile) file = NULL;
+             g_autofree gchar *dirname = NULL;
+
+             dirname = g_path_get_dirname (filename);
+             file = g_file_new_for_commandline_arg_and_cwd (content, dirname);
+             bg_uri = g_file_get_uri (file);
+           }
+           SET_FLAG(CC_BACKGROUND_ITEM_HAS_URI_DARK);
+           g_object_set (G_OBJECT (item), "uri-dark", bg_uri, NULL);
+         } else {
+           break;
+         }
        } else if (!strcmp ((gchar *)wpa->name, "name")) {
          if (wpa->last != NULL && wpa->last->content != NULL) {
            g_autofree gchar *name = NULL;
diff --git a/panels/background/meson.build b/panels/background/meson.build
index 9348dac72..3634c4727 100644
--- a/panels/background/meson.build
+++ b/panels/background/meson.build
@@ -70,6 +70,7 @@ sources = common_sources + files(
   'bg-wallpapers-source.c',
   'cc-background-chooser.c',
   'cc-background-item.c',
+  'cc-background-paintable.c',
   'cc-background-panel.c',
   'cc-background-preview.c',
   'cc-background-xml.c',


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]