From 37c151ce0f6b3ad55e75fe3a9be616a2472ef6c5 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 12 Apr 2020 00:20:27 -0400 Subject: [PATCH] Add some theme apis Add apis to get the list of available themes, as well as the dark or light variant of a theme. --- docs/reference/gtk/gtk4-sections.txt | 6 + gtk/gtk.h | 1 + gtk/gtkcssprovider.c | 4 +- gtk/gtkcssproviderprivate.h | 2 + gtk/gtksettings.c | 64 +--------- gtk/gtktheme.c | 181 +++++++++++++++++++++++++++ gtk/gtktheme.h | 38 ++++++ gtk/meson.build | 2 + 8 files changed, 235 insertions(+), 63 deletions(-) create mode 100644 gtk/gtktheme.c create mode 100644 gtk/gtktheme.h diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt index d438d4bc3d..4c681a04b6 100644 --- a/docs/reference/gtk/gtk4-sections.txt +++ b/docs/reference/gtk/gtk4-sections.txt @@ -2304,6 +2304,12 @@ GtkSettingsValue gtk_settings_get_default gtk_settings_get_for_display gtk_settings_reset_property + + +gtk_theme_get_dark_variant +gtk_theme_get_light_variant +gtk_theme_get_available_themes + GtkSettingsClass GTK_IS_SETTINGS diff --git a/gtk/gtk.h b/gtk/gtk.h index 8fe078e6a9..b1fd3de207 100644 --- a/gtk/gtk.h +++ b/gtk/gtk.h @@ -230,6 +230,7 @@ #include #include #include +#include #include #include #include diff --git a/gtk/gtkcssprovider.c b/gtk/gtkcssprovider.c index 5ade761eaf..0ae06f3952 100644 --- a/gtk/gtkcssprovider.c +++ b/gtk/gtkcssprovider.c @@ -1266,8 +1266,8 @@ _gtk_css_find_theme_dir (const gchar *dir, #undef MINOR -static gchar * -_gtk_css_find_theme (const gchar *name) +char * +_gtk_css_find_theme (const char *name) { gchar *path; const char *const *dirs; diff --git a/gtk/gtkcssproviderprivate.h b/gtk/gtkcssproviderprivate.h index e345d00120..cef6706f62 100644 --- a/gtk/gtkcssproviderprivate.h +++ b/gtk/gtkcssproviderprivate.h @@ -26,6 +26,8 @@ gchar *_gtk_get_theme_dir (void); const gchar *_gtk_css_provider_get_theme_dir (GtkCssProvider *provider); +char *_gtk_css_find_theme (const char *theme); + void gtk_css_provider_set_keep_css_sections (void); G_END_DECLS diff --git a/gtk/gtksettings.c b/gtk/gtksettings.c index 301575705e..b1b1a99a9c 100644 --- a/gtk/gtksettings.c +++ b/gtk/gtksettings.c @@ -29,6 +29,7 @@ #include "gtkstyleproviderprivate.h" #include "gtktypebuiltins.h" #include "gtkversion.h" +#include "gtktheme.h" #include "gtkwidget.h" #include "gdk/gdk-private.h" @@ -1635,65 +1636,6 @@ settings_update_provider (GdkDisplay *display, * NAME/NAME-dark */ -extern char *_gtk_css_find_theme (const char *theme); - -static gboolean -theme_exists (const char *theme) -{ - char *path; - - path = _gtk_css_find_theme (theme); - if (path) - { - g_free (path); - return TRUE; - } - - return FALSE; -} - -static char * -get_light_theme_variant (const char *theme) -{ - if (g_str_equal (theme, "HighContrastInverse")) - return g_strdup ("HighContrast"); - - if (g_str_equal (theme, "Adwaita-dark")) - return g_strdup ("Adwaita"); - - if (g_str_has_suffix (theme, "-dark")) - { - char *light = g_strndup (theme, strlen (theme) - strlen ("-dark")); - if (theme_exists (light)) - return light; - - g_free (light); - } - - return g_strdup (theme); -} - -static char * -get_dark_theme_variant (const char *theme) -{ - if (g_str_equal (theme, "HighContrast")) - return g_strdup ("HighContrastInverse"); - - if (g_str_equal (theme, "Adwaita")) - return g_strdup ("Adwaita-dark"); - - if (!g_str_has_suffix (theme, "-dark")) - { - char *dark = g_strconcat (theme, "-dark", NULL); - if (theme_exists (dark)) - return dark; - - g_free (dark); - } - - return g_strdup (theme); -} - static char * get_theme_name (GtkSettings *settings) { @@ -1715,11 +1657,11 @@ get_theme_name (GtkSettings *settings) switch (user_pref) { case 0: - theme = get_light_theme_variant (theme_name); + theme = gtk_theme_get_light_variant (theme_name); g_free (theme_name); break; case 1: - theme = get_dark_theme_variant (theme_name); + theme = gtk_theme_get_dark_variant (theme_name); g_free (theme_name); break; default: diff --git a/gtk/gtktheme.c b/gtk/gtktheme.c new file mode 100644 index 0000000000..a29ed1a24b --- /dev/null +++ b/gtk/gtktheme.c @@ -0,0 +1,181 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2020 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "config.h" + +#include "gtktheme.h" +#include "gtkcssproviderprivate.h" + +static gboolean +theme_exists (const char *theme) +{ + char *path; + + path = _gtk_css_find_theme (theme); + if (path) + { + g_free (path); + return TRUE; + } + + return FALSE; +} + +/** + * gtk_theme_get_dark_variant: + * @theme: a theme name + * + * Returns the name of the dark variant of the + * given theme, if such a variant is available. + * Otherwise, @theme is returned. + * + * Returns: (transfer full): name of the dark variant + * of @theme. Free with g_free() + */ +char * +gtk_theme_get_dark_variant (const char *theme) +{ + if (g_str_equal (theme, "HighContrast")) + return g_strdup ("HighContrastInverse"); + + if (g_str_equal (theme, "Adwaita")) + return g_strdup ("Adwaita-dark"); + + if (!g_str_has_suffix (theme, "-dark")) + { + char *dark = g_strconcat (theme, "-dark", NULL); + if (theme_exists (dark)) + return dark; + + g_free (dark); + } + + return g_strdup (theme); +} + +/** + * gtk_theme_get_light_variant: + * @theme: a theme name + * + * Returns the name of the light variant of the + * given theme, if such a variant is available. + * Otherwise, @theme is returned. + * + * Returns: (transfer full): name of the light variant + * of @theme. Free with g_free() + */ +char * +gtk_theme_get_light_variant (const char *theme) +{ + if (g_str_equal (theme, "HighContrastInverse")) + return g_strdup ("HighContrast"); + + if (g_str_equal (theme, "Adwaita-dark")) + return g_strdup ("Adwaita"); + + if (g_str_has_suffix (theme, "-dark")) + { + char *light = g_strndup (theme, strlen (theme) - strlen ("-dark")); + if (theme_exists (light)) + return light; + + g_free (light); + } + + return g_strdup (theme); +} + +static void +fill_gtk (const gchar *path, + GHashTable *t) +{ + const gchar *dir_entry; + GDir *dir = g_dir_open (path, 0, NULL); + + if (!dir) + return; + + while ((dir_entry = g_dir_read_name (dir))) + { + gchar *filename = g_build_filename (path, dir_entry, "gtk-4.0", "gtk.css", NULL); + + if (g_file_test (filename, G_FILE_TEST_IS_REGULAR) && + !g_hash_table_contains (t, dir_entry)) + g_hash_table_add (t, g_strdup (dir_entry)); + + g_free (filename); + } + + g_dir_close (dir); +} + +/** + * gtk_theme_get_available_themes: + * + * Returns the list of available themes. + * + * Returns: (transfer full): an array of theme names + */ +char ** +gtk_theme_get_available_themes (void) +{ + GHashTable *t; + gchar *path; + gchar **builtin_themes; + guint i; + const gchar * const *dirs; + char **keys; + char **result; + + t = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + /* Builtin themes */ + builtin_themes = g_resources_enumerate_children ("/org/gtk/libgtk/theme", 0, NULL); + for (i = 0; builtin_themes[i] != NULL; i++) + { + if (g_str_has_suffix (builtin_themes[i], "/")) + g_hash_table_add (t, g_strndup (builtin_themes[i], strlen (builtin_themes[i]) - 1)); + } + g_strfreev (builtin_themes); + + path = _gtk_get_theme_dir (); + fill_gtk (path, t); + g_free (path); + + path = g_build_filename (g_get_user_data_dir (), "themes", NULL); + fill_gtk (path, t); + g_free (path); + + path = g_build_filename (g_get_home_dir (), ".themes", NULL); + fill_gtk (path, t); + g_free (path); + + dirs = g_get_system_data_dirs (); + for (i = 0; dirs[i]; i++) + { + path = g_build_filename (dirs[i], "themes", NULL); + fill_gtk (path, t); + g_free (path); + } + + keys = (char **)g_hash_table_get_keys_as_array (t, NULL); + result = g_strdupv (keys); + g_free (keys); + g_hash_table_destroy (t); + + return result; +} diff --git a/gtk/gtktheme.h b/gtk/gtktheme.h new file mode 100644 index 0000000000..20b46d995a --- /dev/null +++ b/gtk/gtktheme.h @@ -0,0 +1,38 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2020 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __GTK_THEME_H__ +#define __GTK_THEME_H__ + +#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +GDK_AVAILABLE_IN_ALL +char * gtk_theme_get_dark_variant (const char *theme); +GDK_AVAILABLE_IN_ALL +char * gtk_theme_get_light_variant (const char *theme); +GDK_AVAILABLE_IN_ALL +char **gtk_theme_get_available_themes (void); + +G_END_DECLS + +#endif /* __GTK_THEME_H__ */ diff --git a/gtk/meson.build b/gtk/meson.build index 28e23b6781..dec1aff698 100644 --- a/gtk/meson.build +++ b/gtk/meson.build @@ -370,6 +370,7 @@ gtk_public_sources = files([ 'gtktexttypes.c', 'gtktextutil.c', 'gtktextview.c', + 'gtktheme.c', 'gtktogglebutton.c', 'gtktooltip.c', 'gtktooltipwindow.c', @@ -602,6 +603,7 @@ gtk_public_headers = files([ 'gtktexttag.h', 'gtktexttagtable.h', 'gtktextview.h', + 'gtktheme.h', 'gtktogglebutton.h', 'gtktooltip.h', 'gtktreednd.h',