summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog56
-rw-r--r--configure.ac3
-rw-r--r--src/common/extstr.c32
-rw-r--r--src/common/extstr.h4
-rw-r--r--src/core/params.c3
-rw-r--r--src/core/params.h1
-rw-r--r--src/glibext/configuration.c3
-rw-r--r--src/gtkext/Makefile.am3
-rw-r--r--src/gtkext/theme.c106
-rwxr-xr-xsrc/gui/core/Makefile.am3
-rw-r--r--src/gui/core/core.c8
-rw-r--r--src/gui/core/theme.c260
-rw-r--r--src/gui/core/theme.h (renamed from src/gtkext/theme.h)6
-rw-r--r--src/main.c8
-rw-r--r--themes/Adwaita/Makefile.am12
-rw-r--r--themes/Adwaita/clean.png (renamed from themes/clean.png)bin741 -> 741 bytes
-rw-r--r--themes/Adwaita/display.css (renamed from themes/segments.css)2
-rw-r--r--themes/Adwaita/icons.css (renamed from themes/icons.css)0
-rw-r--r--themes/Adwaita/portions.css (renamed from themes/portions.css)0
-rw-r--r--themes/Adwaita/redo.png (renamed from themes/redo.png)bin617 -> 617 bytes
-rw-r--r--themes/Adwaita/undo.png (renamed from themes/undo.png)bin602 -> 602 bytes
-rw-r--r--themes/Makefile.am7
22 files changed, 389 insertions, 128 deletions
diff --git a/ChangeLog b/ChangeLog
index bc94578..9790da7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,59 @@
+16-11-09 Cyrille Bagard <nocbos@gmail.com>
+
+ * configure.ac:
+ Add the new Makefile from the 'themes/Adwaita' directory.
+
+ * src/common/extstr.c:
+ * src/common/extstr.h:
+ Guess if a string ends with the specified suffix.
+
+ * src/core/params.c:
+ * src/core/params.h:
+ Define a new configuration parameter for the current theme name.
+
+ * src/glibext/configuration.c:
+ Fix a silent bug about portable directories separator.
+
+ * src/gtkext/Makefile.am:
+ Remove the 'theme.[ch]' files from libgtkext_la_SOURCES.
+
+ * src/gtkext/theme.c:
+ * src/gtkext/theme.h:
+ Moved entries.
+
+ * src/gui/core/Makefile.am:
+ Add the 'theme.[ch]' files to libguicore_la_SOURCES.
+
+ * src/gui/core/core.c:
+ Update GUI item loading.
+
+ * src/gui/core/theme.c:
+ * src/gui/core/theme.h:
+ New entries: load GTK CSS extensions from files in a given theme directory.
+
+ * src/main.c:
+ Update code.
+
+ * themes/Adwaita/Makefile.am:
+ * themes/Adwaita/clean.png:
+ * themes/Adwaita/display.css:
+ * themes/Adwaita/icons.css:
+ * themes/Adwaita/portions.css:
+ * themes/Adwaita/redo.png:
+ * themes/Adwaita/undo.png:
+ New entries: define the first named theme for Chrysalide.
+
+ * themes/Makefile.am:
+ Redirect processing to SUBDIRS.
+
+ * themes/clean.png:
+ * themes/icons.css:
+ * themes/portions.css:
+ * themes/redo.png:
+ * themes/segments.css:
+ * themes/undo.png:
+ Moved entries.
+
16-11-07 Cyrille Bagard <nocbos@gmail.com>
* src/analysis/contents/file.c:
diff --git a/configure.ac b/configure.ac
index c34cfb6..bfca0b6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -406,7 +406,8 @@ AC_CONFIG_FILES([Makefile
tools/d2c/hooks/Makefile
tools/d2c/rules/Makefile
tools/d2c/syntax/Makefile
- themes/Makefile])
+ themes/Makefile
+ themes/Adwaita/Makefile])
AC_OUTPUT
diff --git a/src/common/extstr.c b/src/common/extstr.c
index cabc307..0b37606 100644
--- a/src/common/extstr.c
+++ b/src/common/extstr.c
@@ -368,3 +368,35 @@ char *ellipsis(char *input, size_t max)
return result;
}
+
+
+/******************************************************************************
+* *
+* Paramètres : str = chaîne à analyser. *
+* suffix = chaîne à retrouver en extrémité éventuellement. *
+* *
+* Description : Détermine si une chaîne se termine par une autre. *
+* *
+* Retour : true si le suffixe a été identifié, ou false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool endswith(const char *str, const char *suffix)
+{
+ bool result; /* Bilan à faire remonter */
+ size_t len; /* Taille de la chaîne soumise */
+ size_t suflen; /* Taille du suffixe */
+
+ result = false;
+
+ len = strlen(str);
+ suflen = strlen(suffix);
+
+ if (len > suflen && strncmp(&str[len - suflen], suffix, suflen) == 0)
+ result = true;
+
+ return result;
+
+}
diff --git a/src/common/extstr.h b/src/common/extstr.h
index 6eb3889..9b49563 100644
--- a/src/common/extstr.h
+++ b/src/common/extstr.h
@@ -26,6 +26,7 @@
#include <ctype.h>
+#include <stdbool.h>
#include <sys/types.h>
@@ -60,6 +61,9 @@ char *escape_crlf(char *);
/* Borne la taille d'une chaîne à une valeur donnée. */
char *ellipsis(char *, size_t);
+/* Détermine si une chaîne se termine par une autre. */
+bool endswith(const char *, const char *);
+
#endif /* _COMMON_EXTSTR_H */
diff --git a/src/core/params.c b/src/core/params.c
index 540ce48..b3f766e 100644
--- a/src/core/params.c
+++ b/src/core/params.c
@@ -138,6 +138,9 @@ bool load_main_config_parameters(void)
param = g_generic_config_create_param(config, MPK_FORMAT_NO_NAME, CPT_BOOLEAN, false);
if (param == NULL) return false;
+ param = g_generic_config_create_param(config, MPK_INTERNAL_THEME, CPT_STRING, "Adwaita");
+ if (param == NULL) return false;
+
param = g_generic_config_create_param(config, MPK_TITLE_BAR, CPT_BOOLEAN, true);
if (param == NULL) return false;
diff --git a/src/core/params.h b/src/core/params.h
index 281e617..2ec45cc 100644
--- a/src/core/params.h
+++ b/src/core/params.h
@@ -40,6 +40,7 @@
#define MPK_LOCAL_PORT "cdb.network.local.port"
#define MPK_SERVER_BACKLOG "cdb.network.server.backlog"
#define MPK_FORMAT_NO_NAME "format.symbols.use_phy_instead_of_virt"
+#define MPK_INTERNAL_THEME "gui.editor.theme"
#define MPK_TITLE_BAR "gui.editor.hide_titlebar"
#define MPK_LAST_PROJECT "gui.editor.last_project"
#define MPK_MAXIMIZED "gui.editor.start_maximized"
diff --git a/src/glibext/configuration.c b/src/glibext/configuration.c
index 1dc7dc6..870bc72 100644
--- a/src/glibext/configuration.c
+++ b/src/glibext/configuration.c
@@ -1161,7 +1161,8 @@ GGenConfig *g_generic_config_new(const char *name)
result = g_object_new(G_TYPE_GEN_CONFIG, NULL);
- suffix = strdup("chrysalide/");
+ suffix = strdup("chrysalide");
+ suffix = stradd(suffix, G_DIR_SEPARATOR_S);
suffix = stradd(suffix, name);
suffix = stradd(suffix, ".xml");
diff --git a/src/gtkext/Makefile.am b/src/gtkext/Makefile.am
index bdd0a31..f1bd18a 100644
--- a/src/gtkext/Makefile.am
+++ b/src/gtkext/Makefile.am
@@ -16,8 +16,7 @@ libgtkext_la_SOURCES = \
gtkstatusstack.h gtkstatusstack.c \
gtkviewpanel-int.h \
gtkviewpanel.h gtkviewpanel.c \
- support.h support.c \
- theme.h theme.c
+ support.h support.c
libgtkext_la_LIBADD = \
graph/libgtkextgraph.la
diff --git a/src/gtkext/theme.c b/src/gtkext/theme.c
deleted file mode 100644
index fbaed3c..0000000
--- a/src/gtkext/theme.c
+++ /dev/null
@@ -1,106 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * theme.c - prototypes pour l'ajout d'extensions au thème GTK
- *
- * Copyright (C) 2009-2012 Cyrille Bagard
- *
- * This file is part of Chrysalide.
- *
- * Chrysalide 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 3 of the License, or
- * (at your option) any later version.
- *
- * Chrysalide 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-
-#include "theme.h"
-
-
-#include <config.h>
-
-
-
-static const char *_themes_directories[] = {
-
- PACKAGE_SOURCE_DIR G_DIR_SEPARATOR_S "themes",
- PACKAGE_DATA_DIR G_DIR_SEPARATOR_S "themes",
- NULL
-
-};
-
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Charge le thème GTK pour les composants spécifiques. *
-* *
-* Retour : true ou false selon le bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-bool load_extra_gtk_theme(void)
-{
- GdkScreen *screen; /* Ecran(s) concerné(s) */
- const char **iter_f; /* Boucle de parcours #1 */
- bool done; /* Traitement d'un fichier */
- const char **iter_d; /* Boucle de parcours #2 */
- gchar *filename; /* Chemin d'accès constitué */
- GtkCssProvider *provider; /* Nouveau fournisseur CSS */
-
- static const char *css_files[] = {
- "portions.css",
- "segments.css",
- "icons.css",
- NULL
- };
-
- screen = gdk_screen_get_default();
-
- done = true;
-
- for (iter_f = css_files; *iter_f != NULL; iter_f++)
- {
- done = false;
-
- for (iter_d = _themes_directories; *iter_d != NULL && !done; iter_d++)
- {
- filename = g_strdup_printf("%s%s%s", *iter_d, G_DIR_SEPARATOR_S, *iter_f);
-
- if (g_file_test(filename, G_FILE_TEST_EXISTS))
- {
- provider = gtk_css_provider_new();
- done = gtk_css_provider_load_from_path(provider, filename, NULL);
-
- if (done)
- gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER(provider),
- GTK_STYLE_PROVIDER_PRIORITY_USER);
-
- g_object_unref(G_OBJECT(provider));
-
- }
-
- g_free(filename);
-
- }
-
- if (!done)
- break;
-
- }
-
- return done;
-
-}
diff --git a/src/gui/core/Makefile.am b/src/gui/core/Makefile.am
index 75b342f..85aaacf 100755
--- a/src/gui/core/Makefile.am
+++ b/src/gui/core/Makefile.am
@@ -4,7 +4,8 @@ noinst_LTLIBRARIES = libguicore.la
libguicore_la_SOURCES = \
core.h core.c \
global.h global.c \
- panels.h panels.c
+ panels.h panels.c \
+ theme.h theme.c
libguicore_la_LDFLAGS = $(LIBGTK_LIBS) $(LIBXML_LIBS)
diff --git a/src/gui/core/core.c b/src/gui/core/core.c
index 4f84127..7d75167 100644
--- a/src/gui/core/core.c
+++ b/src/gui/core/core.c
@@ -27,6 +27,7 @@
#include "panels.h"
+#include "theme.h"
#include "../../core/params.h"
#include "../../glibext/linesegment.h"
@@ -48,13 +49,14 @@ bool load_all_gui_components(GObject *ref)
{
bool result; /* Bilan à retourner */
+ load_main_panels(ref);
+
+ load_extra_gtk_theme();
+
result = load_segment_rendering_parameters();
result &= init_segment_content_hash_table();
- if (result)
- load_main_panels(ref);
-
return result;
}
diff --git a/src/gui/core/theme.c b/src/gui/core/theme.c
new file mode 100644
index 0000000..7e81497
--- /dev/null
+++ b/src/gui/core/theme.c
@@ -0,0 +1,260 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * theme.c - prototypes pour l'ajout d'extensions au thème GTK
+ *
+ * Copyright (C) 2009-2012 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "theme.h"
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <string.h>
+
+
+#include <config.h>
+#include <i18n.h>
+
+
+#include "../panels/log.h"
+#include "../../common/extstr.h"
+#include "../../common/xdg.h"
+#include "../../core/params.h"
+
+
+
+/* Parcourt tous les répertoires connus pour trouver un thème. */
+static bool browse_themes_directories(GdkScreen *, const char *, gboolean);
+
+/* Parcourt un répertoire donné à la recherche d'un thème. */
+static bool look_for_named_theme(GdkScreen *, const char *, const char *, gboolean);
+
+
+/* Répertoires de recherche */
+static const char *_themes_directories[] = {
+
+ PACKAGE_SOURCE_DIR G_DIR_SEPARATOR_S "themes",
+ PACKAGE_DATA_DIR G_DIR_SEPARATOR_S "themes",
+ NULL
+
+};
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Charge le thème GTK pour les composants spécifiques. *
+* *
+* Retour : true ou false selon le bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool load_extra_gtk_theme(void)
+{
+ bool result; /* Bilan à faire remonter */
+ const char *name; /* Nom du thème recherché */
+ GdkScreen *screen; /* Ecran(s) concerné(s) */
+ GtkSettings *settings; /* Propriétés du système */
+ gboolean dark; /* Envie d'un thème sombre ? */
+
+ result = false;
+
+ if (!g_generic_config_get_value(get_main_configuration(), MPK_INTERNAL_THEME, &name))
+ goto legt_done;
+
+ screen = gdk_screen_get_default();
+
+ settings = gtk_settings_get_for_screen(screen);
+
+ g_object_get(settings, "gtk-application-prefer-dark-theme", &dark, NULL);
+
+ if (dark)
+ result = browse_themes_directories(screen, name, true);
+
+ if (!result)
+ result = browse_themes_directories(screen, name, false);
+
+ legt_done:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : screen = écran concerné par les éventuels chargements. *
+* 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 : true si un élément de thème a pu être chargé, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool browse_themes_directories(GdkScreen *screen, const char *name, gboolean dark)
+{
+ bool result; /* Bilan à faire remonter */
+ char *suffix; /* Fin du répertoire personnel */
+ char *owndir; /* Thèmes personnels ? */
+ const char **iter; /* Boucle de parcours */
+
+ result = false;
+
+ /* Répertoire de l'utilisateur en premier ! */
+
+ suffix = strdup("chrysalide");
+ suffix = stradd(suffix, G_DIR_SEPARATOR_S);
+ suffix = stradd(suffix, "themes");
+
+ owndir = get_xdg_config_dir(suffix);
+
+ free(suffix);
+
+ if (owndir != NULL)
+ {
+ result = look_for_named_theme(screen, owndir, name, dark);
+
+ free(owndir);
+
+ }
+
+ /* Parcours des autres répertoires classiques au besoin */
+
+ for (iter = _themes_directories; *iter != NULL && !result; iter++)
+ result = look_for_named_theme(screen, *iter, name, dark);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : screen = écran concerné par les éventuels chargements. *
+* 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 : true si un élément de thème a pu être chargé, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool look_for_named_theme(GdkScreen *screen, const char *dirname, const char *name, gboolean dark)
+{
+ bool result; /* Bilan à faire remonter */
+ char *path; /* Chemin d'accès à essayer */
+ int ret; /* Bilan d'un appel */
+ int dirfd; /* Canal de lecture */
+ struct dirent **namelist; /* Liste des trouvailles */
+ int count; /* Nombre de fichiers trouvés */
+ int i; /* Boucle de parcours */
+ char *filename; /* Chemin d'accès constitué */
+ GtkCssProvider *provider; /* Nouveau fournisseur CSS */
+ GError *error; /* Relevé d'éventuelles erreurs*/
+
+ result = false;
+
+ ret = asprintf(&path, "%s" G_DIR_SEPARATOR_S "%s", dirname, name);
+ if (ret == -1) goto lfnt_done;
+
+ dirfd = open(path, O_RDONLY | O_DIRECTORY);
+ if (dirfd == -1) goto lfnt_not_found;
+
+ int keep_dark_css_only(const struct dirent *entry)
+ {
+ return (entry->d_type == DT_REG
+ && endswith(entry->d_name, "-dark.css") ? 1 : 0);
+
+ }
+
+ int keep_css_only(const struct dirent *entry)
+ {
+ return (entry->d_type == DT_REG
+ && endswith(entry->d_name, ".css")
+ && !endswith(entry->d_name, "-dark.css") ? 1 : 0);
+
+ }
+
+ count = scandirat(dirfd, ".", &namelist, dark ? keep_dark_css_only : keep_css_only, alphasort);
+
+ for (i = 0; i < count; i++)
+ {
+ ret = asprintf(&filename, "%s%s%s", path, G_DIR_SEPARATOR_S, namelist[i]->d_name);
+ if (ret == -1) continue;
+
+ provider = gtk_css_provider_new();
+
+ error = NULL;
+
+ gtk_css_provider_load_from_path(provider, filename, &error);
+
+ if (error == NULL)
+ {
+ log_variadic_message(LMT_INFO, _("Loaded CSS definitions from '%s'"), filename);
+
+ gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER(provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+ result = true;
+
+ }
+ else
+ {
+ log_variadic_message(LMT_ERROR, _("Failed to load CSS definitions from '%s'"), filename);
+ g_error_free(error);
+ }
+
+ g_object_unref(G_OBJECT(provider));
+
+ free(filename);
+
+ }
+
+ if (count > 0)
+ free(namelist);
+
+ close(dirfd);
+
+ lfnt_not_found:
+
+ free(path);
+
+ lfnt_done:
+
+ return result;
+
+}
diff --git a/src/gtkext/theme.h b/src/gui/core/theme.h
index 3c893a4..77341e3 100644
--- a/src/gtkext/theme.h
+++ b/src/gui/core/theme.h
@@ -22,8 +22,8 @@
*/
-#ifndef _GTKEXT_THEME_H
-#define _GTKEXT_THEME_H
+#ifndef _GUI_CORE_THEME_H
+#define _GUI_CORE_THEME_H
#include <stdbool.h>
@@ -36,4 +36,4 @@ bool load_extra_gtk_theme(void);
-#endif /* _GTKEXT_THEME_H */
+#endif /* _GUI_CORE_THEME_H */
diff --git a/src/main.c b/src/main.c
index 5d0e587..14fa1b4 100644
--- a/src/main.c
+++ b/src/main.c
@@ -35,7 +35,6 @@
#include "core/params.h"
#include "glibext/delayed.h"
#include "glibext/gbinportion.h"
-#include "gtkext/theme.h"
#include "gui/editor.h"
#include "gui/core/core.h"
#include "gui/core/global.h"
@@ -122,9 +121,6 @@ int main(int argc, char **argv)
setlocale (LC_ALL, "");
gtk_init(&argc, &argv);
- if (!load_extra_gtk_theme())
- return EXIT_FAILURE;
-
/* Initialisation du programme */
if (!load_all_basic_components())
return EXIT_FAILURE;
@@ -170,6 +166,8 @@ int main(int argc, char **argv)
editor = create_editor();
+ if (editor == NULL) goto failed_to_load_editor;
+
gtk_widget_show_now(editor);
init_work_queue(get_global_status());
@@ -237,6 +235,8 @@ int main(int argc, char **argv)
//gtk_widget_destroy(editor);
+ failed_to_load_editor:
+
unload_all_basic_components();
return result;
diff --git a/themes/Adwaita/Makefile.am b/themes/Adwaita/Makefile.am
new file mode 100644
index 0000000..9ef46c5
--- /dev/null
+++ b/themes/Adwaita/Makefile.am
@@ -0,0 +1,12 @@
+
+GTK3_CSS = \
+ display.css \
+ icons.css \
+ portions.css \
+ clean.png \
+ redo.png \
+ undo.png
+
+cssdir = $(datadir)/themes/Adwaita
+
+css_DATA = $(GTK3_CSS)
diff --git a/themes/clean.png b/themes/Adwaita/clean.png
index f8f8c78..f8f8c78 100644
--- a/themes/clean.png
+++ b/themes/Adwaita/clean.png
Binary files differ
diff --git a/themes/segments.css b/themes/Adwaita/display.css
index 9a4a589..2368b64 100644
--- a/themes/segments.css
+++ b/themes/Adwaita/display.css
@@ -23,7 +23,7 @@
font-style: italic;
font-weight: normal;
-
+
}
.segment-phys-addr-padding {
diff --git a/themes/icons.css b/themes/Adwaita/icons.css
index 4986ab2..4986ab2 100644
--- a/themes/icons.css
+++ b/themes/Adwaita/icons.css
diff --git a/themes/portions.css b/themes/Adwaita/portions.css
index 3c5c582..3c5c582 100644
--- a/themes/portions.css
+++ b/themes/Adwaita/portions.css
diff --git a/themes/redo.png b/themes/Adwaita/redo.png
index 9fb3199..9fb3199 100644
--- a/themes/redo.png
+++ b/themes/Adwaita/redo.png
Binary files differ
diff --git a/themes/undo.png b/themes/Adwaita/undo.png
index 55b8c34..55b8c34 100644
--- a/themes/undo.png
+++ b/themes/Adwaita/undo.png
Binary files differ
diff --git a/themes/Makefile.am b/themes/Makefile.am
index c790aad..8010143 100644
--- a/themes/Makefile.am
+++ b/themes/Makefile.am
@@ -1,7 +1,2 @@
-GTK3_CSS = \
- portions.css
-
-cssdir = $(datadir)/themes
-
-css_DATA = $(GTK3_CSS)
+SUBDIRS = Adwaita