From 3a8bc79d69acae3735cc0203b54d93b4137caa09 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Mon, 21 Jan 2019 23:19:01 +0100
Subject: Improved code as GTK failed to load CSS content it has exported.

---
 src/gui/core/theme.c | 175 +++++++++++++++++++--------------------------------
 1 file changed, 65 insertions(+), 110 deletions(-)

diff --git a/src/gui/core/theme.c b/src/gui/core/theme.c
index 420fb79..8e68780 100644
--- a/src/gui/core/theme.c
+++ b/src/gui/core/theme.c
@@ -48,19 +48,16 @@
 
 
 /* Parcourt tous les répertoires connus pour trouver un thème. */
-static char *browse_themes_directories(const char *, gboolean);
+static bool browse_themes_directories(GdkScreen *, const char *, gboolean);
 
 /* Parcourt un répertoire donné à la recherche d'un thème. */
-static char *look_for_named_theme(const char *, const char *, gboolean);
+static bool look_for_named_theme(GdkScreen *, const char *, const char *, gboolean);
 
 /* Ajoute les définitions CSS à partir d'un chemin donné. */
-static void load_css_partial_content(char **, const char *, gboolean);
+static bool load_css_content(GdkScreen *, const char *, gboolean);
 
 /* Parcourt tous les greffons à la recherche de définitions CSS. */
-static void prepend_plugins_themes(char **, gboolean);
-
-/* Etend le thème courant de GTK. */
-static void activate_css_content(GdkScreen *, const char *);
+static bool extend_with_plugins_themes(GdkScreen *, gboolean);
 
 
 /* Répertoires de recherche */
@@ -93,7 +90,6 @@ bool load_extra_gtk_theme(void)
     GdkScreen *screen;                      /* Ecran(s) concerné(s)        */
     GtkSettings *settings;                  /* Propriétés du système       */
     gboolean dark;                          /* Envie d'un thème sombre ?   */
-    char *content;                          /* Définitions CSS à charger   */
 
     result = false;
 
@@ -106,18 +102,10 @@ bool load_extra_gtk_theme(void)
 
     g_object_get(settings, "gtk-application-prefer-dark-theme", &dark, NULL);
 
-    content = browse_themes_directories(name, dark);
-
-    if (content != NULL)
-    {
-        prepend_plugins_themes(&content, dark);
-
-        activate_css_content(screen, content);
-        free(content);
+    result = browse_themes_directories(screen, name, dark);
 
-        result = true;
-
-    }
+    if (result)
+        result = extend_with_plugins_themes(screen, dark);
 
  legt_done:
 
@@ -128,25 +116,26 @@ bool load_extra_gtk_theme(void)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : name    = nom du thème recherché, et donc de son répertoire. *
-*                dark    = indique une préférence pour la variante foncée.    *
+*  Paramètres  : screen = écran visé par le chargement d'un thème.            *
+*                name   = nom du thème recherché, et donc de son répertoire.  *
+*                dark   = indique une préférence pour la variante foncée.     *
 *                                                                             *
 *  Description : Parcourt tous les répertoires connus pour trouver un thème.  *
 *                                                                             *
-*  Retour      : Contenu CSS chargé ou NULL si aucun.                         *
+*  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static char *browse_themes_directories(const char *name, gboolean dark)
+static bool browse_themes_directories(GdkScreen *screen, const char *name, gboolean dark)
 {
-    char *result;                           /* Défintions CSS à renvoyer   */
+    bool result;                            /* Bilan à renvoyer            */
     char *suffix;                           /* Fin du répertoire personnel */
     char *owndir;                           /* Thèmes personnels ?         */
     const char **iter;                      /* Boucle de parcours          */
 
-    result = NULL;
+    result = false;
 
     /* Répertoire de l'utilisateur en premier ! */
 
@@ -160,7 +149,7 @@ static char *browse_themes_directories(const char *name, gboolean dark)
 
     if (owndir != NULL)
     {
-        result = look_for_named_theme(owndir, name, dark);
+        result = look_for_named_theme(screen, owndir, name, dark);
 
         free(owndir);
 
@@ -168,8 +157,8 @@ static char *browse_themes_directories(const char *name, gboolean dark)
 
     /* Parcours des autres répertoires classiques au besoin */
 
-    for (iter = _themes_directories; *iter != NULL && result == NULL; iter++)
-        result = look_for_named_theme(*iter, name, dark);
+    for (iter = _themes_directories; *iter != NULL && !result; iter++)
+        result = look_for_named_theme(screen, *iter, name, dark);
 
     return result;
 
@@ -178,21 +167,22 @@ static char *browse_themes_directories(const char *name, gboolean dark)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : dirname = chemin du répertoire où effectuer des recherches.  *
+*  Paramètres  : screen  = écran visé par le chargement d'un thème.           *
+*                dirname = chemin du répertoire où effectuer des recherches.  *
 *                name    = nom du thème recherché, et donc de son répertoire. *
 *                dark    = indique une préférence pour la variante foncée.    *
 *                                                                             *
 *  Description : Parcourt un répertoire donné à la recherche d'un thème.      *
 *                                                                             *
-*  Retour      : Contenu CSS chargé ou NULL si aucun.                         *
+*  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static char *look_for_named_theme(const char *dirname, const char *name, gboolean dark)
+static bool look_for_named_theme(GdkScreen *screen, const char *dirname, const char *name, gboolean dark)
 {
-    char *result;                           /* Défintions CSS à renvoyer   */
+    bool result;                            /* Bilan à renvoyer            */
     char *path;                             /* Chemin d'accès à essayer    */
     int ret;                                /* Bilan d'un appel            */
     int dirfd;                              /* Canal de lecture            */
@@ -201,7 +191,7 @@ static char *look_for_named_theme(const char *dirname, const char *name, gboolea
     int i;                                  /* Boucle de parcours          */
     char *filename;                         /* Chemin d'accès constitué    */
 
-    result = NULL;
+    result = false;
 
     ret = asprintf(&path, "%s" G_DIR_SEPARATOR_S "%s", dirname, name);
     if (ret == -1) goto lfnt_done;
@@ -219,12 +209,14 @@ static char *look_for_named_theme(const char *dirname, const char *name, gboolea
 
     count = scandirat(dirfd, ".", &namelist, keep_css_only, alphasort);
 
-    for (i = 0; i < count; i++)
+    result = (count > 0);
+
+    for (i = 0; i < count && result; i++)
     {
         ret = asprintf(&filename, "%s%s%s", path, G_DIR_SEPARATOR_S, namelist[i]->d_name);
         if (ret == -1) continue;
 
-        load_css_partial_content(&result, filename, dark);
+        result = load_css_content(screen, filename, dark);
 
         free(filename);
 
@@ -248,28 +240,40 @@ static char *look_for_named_theme(const char *dirname, const char *name, gboolea
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : content = définitions CSS à compléter. [OUT]                 *
-*                path    = chemin vers la nouvelle définition à ajouter.      *
-*                dark    = indique une préférence pour la variante foncée.    *
+*  Paramètres  : screen = écran visé par le chargement d'un thème.            *
+*                path   = chemin vers la nouvelle définition à ajouter.       *
+*                dark   = indique une préférence pour la variante foncée.     *
 *                                                                             *
 *  Description : Ajoute les définitions CSS à partir d'un chemin donné.       *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static void load_css_partial_content(char **content, const char *path, gboolean dark)
+static bool load_css_content(GdkScreen *screen, const char *path, gboolean dark)
 {
-    bool got_it;                            /* Version sombre présente ?   */
+    bool result;                            /* Bilan à renvoyer            */
     GtkCssProvider *provider;               /* Nouveau fournisseur CSS     */
     char *dark_path;                        /* Version sombre du chemin    */
     GFile *file;                            /* Fichier à charger           */
     GError *error;                          /* Relevé d'éventuelles erreurs*/
-    char *css;                              /* Contenu d'une feuille       */
 
-    got_it = false;
+    result = false;
+
+    /**
+     * Comme GTK exporte les images sous forme de données encodées en base 64
+     * (cf. gtk_css_image_surface_print()) et ne sait pas recharger ensuite
+     * ces mêmes données (cf. gtk_css_image_url_load_image()), on ne peut pas
+     * collecter les images des ressources via gtk_css_provider_to_string()
+     * pour constituer un contenu CSS global...
+     *
+     * On intègre ainsi les contenus CSS un par un, sans pouvoir déterminer
+     * si l'ensemble est complètement intégré sans erreur.
+     *
+     * Ce constat est valable pour la version 3.22.11-1 de Debian, au moins.
+     */
 
     if (dark)
     {
@@ -293,13 +297,10 @@ static void load_css_partial_content(char **content, const char *path, gboolean
         {
             log_variadic_message(LMT_INFO, _("Loaded CSS definitions from '%s'"), dark_path);
 
-            css = gtk_css_provider_to_string(provider);
+            gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER(provider),
+                                                      GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
 
-            *content = stradd(*content, css);
-
-            free(css);
-
-            got_it = true;
+            result = true;
 
         }
         else
@@ -311,7 +312,7 @@ static void load_css_partial_content(char **content, const char *path, gboolean
 
     }
 
-    if (!got_it)
+    if (!result)
     {
         provider = gtk_css_provider_new();
 
@@ -330,11 +331,10 @@ static void load_css_partial_content(char **content, const char *path, gboolean
         {
             log_variadic_message(LMT_INFO, _("Loaded CSS definitions from '%s'"), path);
 
-            css = gtk_css_provider_to_string(provider);
-
-            *content = stradd(*content, css);
+            gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER(provider),
+                                                      GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
 
-            free(css);
+            result = true;
 
         }
         else
@@ -347,92 +347,47 @@ static void load_css_partial_content(char **content, const char *path, gboolean
 
     }
 
+    return result;
+
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : content = définitions CSS à compléter. [OUT]                 *
-*                dark    = indique une préférence pour la variante foncée.    *
+*  Paramètres  : screen = écran visé par le chargement d'un thème.            *
+*                dark   = indique une préférence pour la variante foncée.     *
 *                                                                             *
 *  Description : Parcourt tous les greffons à la recherche de définitions CSS.*
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static void prepend_plugins_themes(char **content, gboolean dark)
+static bool extend_with_plugins_themes(GdkScreen *screen, gboolean dark)
 {
-    char *extra;                            /* Nouvelles définitions CSS   */
+    bool result;                            /* Bilan à renvoyer            */
     char **resources;                       /* Fichiers supplémentaires    */
     size_t count;                           /* Nombre de ces fichiers      */
     size_t i;                               /* Boucle de parcours          */
 
-    extra = NULL;
+    result = true;
 
     resources = NULL;
     count = 0;
 
     include_plugin_theme(&resources, &count);
 
-    for (i = 0; i < count; i++)
+    for (i = 0; i < count && result; i++)
     {
-        load_css_partial_content(&extra, resources[i], dark);
+        result = load_css_content(screen, resources[i], dark);
         free(resources[i]);
     }
 
     if (resources != NULL)
         free(resources);
 
-    if (extra != NULL)
-    {
-        *content = strprep(*content, extra);
-        free(extra);
-    }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : screen  = écran concerné par les éventuels chargements.      *
-*                content = contenu CSS reconstitué à charger.                 *
-*                                                                             *
-*  Description : Etend le thème courant de GTK.                               *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void activate_css_content(GdkScreen *screen, const char *content)
-{
-    GtkCssProvider *provider;               /* Nouveau fournisseur CSS     */
-    GError *error;                          /* Relevé d'éventuelles erreurs*/
-
-    provider = gtk_css_provider_new();
-
-    error = NULL;
-
-    gtk_css_provider_load_from_data(provider, content, -1, &error);
-
-    if (error == NULL)
-    {
-        gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER(provider),
-                                                  GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
-    }
-    else
-    {
-        assert(false);
-
-        log_variadic_message(LMT_ERROR, _("Failed to load the global CSS extra definition"));
-        g_error_free(error);
-
-    }
-
-    g_object_unref(G_OBJECT(provider));
+    return result;
 
 }
-- 
cgit v0.11.2-87-g4458