[libdazzle] application: use consistent "resources://" prefix



commit c21c461bae464c81d82e2e8641b4db20eb064f28
Author: Christian Hergert <chergert redhat com>
Date:   Tue Jun 13 20:23:20 2017 -0700

    application: use consistent "resources://" prefix
    
    Previously, we had mixed use of filesystem API and resource API. Instead,
    this changes things to use resource:// explicitly as prefixes so that we
    can also load files from disk. That might be necessary with plugins that
    do not support GResources or for which GResources is not convenient.
    
    This changes the function name of the public API entrypoint in
    DzlApplication to make things a bit more apparent that it has changed
    during this development cycle.

 src/app/dzl-application.c           |  112 ++++++++++++++++++++++-------------
 src/app/dzl-application.h           |   12 ++--
 src/menus/dzl-menu-manager.c        |    7 ++
 src/theming/dzl-css-provider.c      |   55 ++++++++++++++---
 src/theming/dzl-theme-manager.c     |   38 +++++++++---
 src/theming/dzl-theme-manager.h     |   10 ++--
 tests/data/shortcuts/0/gtk/menus.ui |    9 +++
 tests/data/shortcuts/1/gtk/menus.ui |   19 ++++++
 tests/data/shortcuts/2/gtk/menus.ui |   13 ++++
 tests/meson.build                   |    6 ++
 tests/test-cpu-graph.c              |    2 +-
 tests/test-desktop-index.c          |    2 +-
 tests/test-panel.c                  |    2 +-
 tests/test-path-bar.c               |    2 +-
 tests/test-pill-box.c               |    2 +-
 tests/test-preferences.c            |    2 +-
 tests/test-progress-button.c        |    2 +-
 tests/test-shortcut-overlays.c      |   74 +++++++++++++++++++++++
 tests/test-stack-list.c             |    2 +-
 tests/test-suggestion.c             |    2 +-
 20 files changed, 293 insertions(+), 80 deletions(-)
---
diff --git a/src/app/dzl-application.c b/src/app/dzl-application.c
index b1d73be..5b4459b 100644
--- a/src/app/dzl-application.c
+++ b/src/app/dzl-application.c
@@ -69,8 +69,8 @@ typedef struct
 G_DEFINE_TYPE_WITH_PRIVATE (DzlApplication, dzl_application, GTK_TYPE_APPLICATION)
 
 static void
-dzl_application_real_add_resource_path (DzlApplication *self,
-                                        const gchar    *resource_path)
+dzl_application_real_add_resources (DzlApplication *self,
+                                    const gchar    *resource_path)
 {
   DzlApplicationPrivate *priv = dzl_application_get_instance_private (self);
   g_autoptr(GError) error = NULL;
@@ -88,16 +88,24 @@ dzl_application_real_add_resource_path (DzlApplication *self,
    * Allow the theme manager to monitor the css/Adwaita.css or other themes
    * based on gtk-theme-name. The theme manager also loads icons.
    */
-  dzl_theme_manager_add_resource_path (priv->theme_manager, resource_path);
+  dzl_theme_manager_add_resources (priv->theme_manager, resource_path);
 
   /*
    * If the resource path has a gtk/menus.ui file, we want to auto-load and
    * merge the menus.
    */
   menu_path = g_build_filename (resource_path, "gtk", "menus.ui", NULL);
-  merge_id = dzl_menu_manager_add_resource (priv->menu_manager, menu_path, &error);
+
+  if (g_str_has_prefix (menu_path, "resource://"))
+    merge_id = dzl_menu_manager_add_resource (priv->menu_manager, menu_path, &error);
+  else
+    merge_id = dzl_menu_manager_add_filename (priv->menu_manager, menu_path, &error);
+
   g_hash_table_insert (priv->menu_merge_ids, (gchar *)resource_path, GUINT_TO_POINTER (merge_id));
-  if (error != NULL && !g_error_matches (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND))
+
+  if (error != NULL &&
+      !(g_error_matches (error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND) ||
+        g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)))
     g_warning ("%s", error->message);
 
   /*
@@ -105,13 +113,13 @@ dzl_application_real_add_resource_path (DzlApplication *self,
    * resources. We always append so that the application resource dir is
    * loaded before any plugin paths.
    */
-  keythemes_path = g_strjoin (NULL, "resources://", resource_path, "/shortcuts", NULL);
+  keythemes_path = g_build_filename (resource_path, "shortcuts", NULL);
   dzl_shortcut_manager_append_search_path (priv->shortcut_manager, keythemes_path);
 }
 
 static void
-dzl_application_real_remove_resource_path (DzlApplication *self,
-                                           const gchar    *resource_path)
+dzl_application_real_remove_resources (DzlApplication *self,
+                                       const gchar    *resource_path)
 {
   DzlApplicationPrivate *priv = dzl_application_get_instance_private (self);
   g_autofree gchar *keythemes_path = NULL;
@@ -124,7 +132,7 @@ dzl_application_real_remove_resource_path (DzlApplication *self,
   resource_path = g_intern_string (resource_path);
 
   /* Remove any loaded CSS providers for @resource_path/css/. */
-  dzl_theme_manager_remove_resource_path (priv->theme_manager, resource_path);
+  dzl_theme_manager_remove_resources (priv->theme_manager, resource_path);
 
   /* Remove any merged menus from the @resource_path/gtk/menus.ui */
   merge_id = GPOINTER_TO_UINT (g_hash_table_lookup (priv->menu_merge_ids, resource_path));
@@ -132,7 +140,7 @@ dzl_application_real_remove_resource_path (DzlApplication *self,
     dzl_menu_manager_remove (priv->menu_manager, merge_id);
 
   /* Remove keythemes path from the shortcuts manager */
-  keythemes_path = g_strjoin (NULL, "resources://", resource_path, "/shortcuts", NULL);
+  keythemes_path = g_strjoin (NULL, "resource://", resource_path, "/shortcuts", NULL);
   dzl_shortcut_manager_remove_search_path (priv->shortcut_manager, keythemes_path);
 }
 
@@ -141,59 +149,78 @@ dzl_application_startup (GApplication *app)
 {
   DzlApplication *self = (DzlApplication *)app;
   DzlApplicationPrivate *priv = dzl_application_get_instance_private (self);
+  const gchar *resource_base_path;
   GMenu *app_menu;
 
   g_assert (DZL_IS_APPLICATION (self));
 
-  priv->theme_manager = dzl_theme_manager_new ();
-  priv->menu_manager = dzl_menu_manager_new ();
-  priv->menu_merge_ids = g_hash_table_new (NULL, NULL);
-  priv->shortcut_manager = g_object_ref (dzl_shortcut_manager_get_default ());
-
   G_APPLICATION_CLASS (dzl_application_parent_class)->startup (app);
 
   /*
    * We cannot register resources before chaining startup because
    * the GtkSettings and other plumbing will not yet be initialized.
    */
-  dzl_application_add_resource_path (self, "/org/gnome/dazzle");
-  dzl_application_add_resource_path (self, g_application_get_resource_base_path (app));
+
+  /* Register our resources that are part of libdazzle. */
+  dzl_application_add_resources (self, "resource:///org/gnome/dazzle");
+
+  /* Now register the application resources */
+  if (NULL != (resource_base_path = g_application_get_resource_base_path (app)))
+    {
+      g_autofree gchar *resource_path = NULL;
+
+      resource_path = g_strdup_printf ("resource://%s", resource_base_path);
+      dzl_application_add_resources (self, resource_path);
+    }
+
+  /* If the application has "app-menu" defined in menus.ui, we want to
+   * assign it to the application. If we used the base GtkApplication for
+   * menus, this would be done for us. But since we are doing menu merging,
+   * we need to do it manually.
+   */
   app_menu = dzl_menu_manager_get_menu_by_id (priv->menu_manager, "app-menu");
   gtk_application_set_app_menu (GTK_APPLICATION (self), G_MENU_MODEL (app_menu));
 }
 
 static void
-dzl_application_shutdown (GApplication *app)
+dzl_application_finalize (GObject *object)
 {
-  DzlApplication *self = (DzlApplication *)app;
+  DzlApplication *self = (DzlApplication *)object;
   DzlApplicationPrivate *priv = dzl_application_get_instance_private (self);
 
-  g_assert (DZL_IS_APPLICATION (self));
-
-  G_APPLICATION_CLASS (dzl_application_parent_class)->shutdown (app);
-
   g_clear_pointer (&priv->menu_merge_ids, g_hash_table_unref);
   g_clear_object (&priv->theme_manager);
   g_clear_object (&priv->menu_manager);
   g_clear_object (&priv->shortcut_manager);
+
+  G_OBJECT_CLASS (dzl_application_parent_class)->finalize (object);
 }
 
 static void
 dzl_application_class_init (DzlApplicationClass *klass)
 {
   GApplicationClass *g_app_class = G_APPLICATION_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = dzl_application_finalize;
 
   g_app_class->startup = dzl_application_startup;
-  g_app_class->shutdown = dzl_application_shutdown;
 
-  klass->add_resource_path = dzl_application_real_add_resource_path;
-  klass->remove_resource_path = dzl_application_real_remove_resource_path;
+  klass->add_resources = dzl_application_real_add_resources;
+  klass->remove_resources = dzl_application_real_remove_resources;
 }
 
 static void
 dzl_application_init (DzlApplication *self)
 {
+  DzlApplicationPrivate *priv = dzl_application_get_instance_private (self);
+
   g_application_set_default (G_APPLICATION (self));
+
+  priv->theme_manager = dzl_theme_manager_new ();
+  priv->menu_manager = dzl_menu_manager_new ();
+  priv->menu_merge_ids = g_hash_table_new (NULL, NULL);
+  priv->shortcut_manager = g_object_ref (dzl_shortcut_manager_get_default ());
 }
 
 /**
@@ -255,42 +282,45 @@ dzl_application_get_menu_by_id (DzlApplication *self,
 }
 
 /**
- * dzl_application_add_resource_path:
+ * dzl_application_add_resources:
  * @self: a #DzlApplication
- * @resource_path: a path to a #GResources path
+ * @resource_path: the location of the resources.
+ *
+ * This adds @resource_path to the list of "automatic resources".
  *
- * This adds @resource_path to the list of automatic resources.
+ * If @resource_path starts with "resource://", then the corresponding
+ * #GResources path will be searched for resources. Otherwise, @resource_path
+ * should be a path to a location on disk.
  *
  * The #DzlApplication will locate resources such as CSS themes, icons, and
- * keybindings.
+ * keyboard shortcuts using @resource_path.
  */
 void
-dzl_application_add_resource_path (DzlApplication *self,
-                                   const gchar    *resource_path)
+dzl_application_add_resources (DzlApplication *self,
+                               const gchar    *resource_path)
 {
   g_return_if_fail (DZL_IS_APPLICATION (self));
   g_return_if_fail (resource_path != NULL);
 
-  DZL_APPLICATION_GET_CLASS (self)->add_resource_path (self, resource_path);
+  DZL_APPLICATION_GET_CLASS (self)->add_resources (self, resource_path);
 }
 
 /**
- * dzl_application_remove_resource_path:
+ * dzl_application_remove_resources:
  * @self: a #DzlApplication
- * @resource_path: a path to a #GResources path
+ * @resource_path: the location of the resources.
  *
- * This removes @resource_path to the list of automatic resources. This
- * directory should have been previously registered with
- * dzl_application_add_resource_path().
+ * This attempts to undo as many side-effects as possible from a call to
+ * dzl_application_add_resources().
  */
 void
-dzl_application_remove_resource_path (DzlApplication *self,
-                                      const gchar    *resource_path)
+dzl_application_remove_resources (DzlApplication *self,
+                                  const gchar    *resource_path)
 {
   g_return_if_fail (DZL_IS_APPLICATION (self));
   g_return_if_fail (resource_path != NULL);
 
-  DZL_APPLICATION_GET_CLASS (self)->remove_resource_path (self, resource_path);
+  DZL_APPLICATION_GET_CLASS (self)->remove_resources (self, resource_path);
 }
 
 /**
diff --git a/src/app/dzl-application.h b/src/app/dzl-application.h
index a9d2664..744b3c0 100644
--- a/src/app/dzl-application.h
+++ b/src/app/dzl-application.h
@@ -40,10 +40,10 @@ struct _DzlApplicationClass
 {
   GtkApplicationClass parent_class;
 
-  void (*add_resource_path)    (DzlApplication *self,
-                                const gchar    *resource_path);
-  void (*remove_resource_path) (DzlApplication *self,
-                                const gchar    *resource_path);
+  void (*add_resources)    (DzlApplication *self,
+                            const gchar    *resource_path);
+  void (*remove_resources) (DzlApplication *self,
+                            const gchar    *resource_path);
 
   gpointer _reserved1;
   gpointer _reserved2;
@@ -60,9 +60,9 @@ DzlShortcutManager *dzl_application_get_shortcut_manager (DzlApplication *self);
 DzlThemeManager    *dzl_application_get_theme_manager    (DzlApplication *self);
 GMenu              *dzl_application_get_menu_by_id       (DzlApplication *self,
                                                           const gchar    *menu_id);
-void                dzl_application_add_resource_path    (DzlApplication *self,
+void                dzl_application_add_resources        (DzlApplication *self,
                                                           const gchar    *resource_path);
-void                dzl_application_remove_resource_path (DzlApplication *self,
+void                dzl_application_remove_resources     (DzlApplication *self,
                                                           const gchar    *resource_path);
 
 G_END_DECLS
diff --git a/src/menus/dzl-menu-manager.c b/src/menus/dzl-menu-manager.c
index eb661d2..6894ef0 100644
--- a/src/menus/dzl-menu-manager.c
+++ b/src/menus/dzl-menu-manager.c
@@ -16,6 +16,10 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#define G_LOG_DOMAIN "dzl-menu-manager"
+
+#include <string.h>
+
 #include "dzl-menu-manager.h"
 
 struct _DzlMenuManager
@@ -506,6 +510,9 @@ dzl_menu_manager_add_resource (DzlMenuManager  *self,
   g_return_val_if_fail (DZL_IS_MENU_MANAGER (self), 0);
   g_return_val_if_fail (resource != NULL, 0);
 
+  if (g_str_has_prefix (resource, "resource://"))
+    resource += strlen ("resource://");
+
   builder = gtk_builder_new ();
 
   if (!gtk_builder_add_from_resource (builder, resource, error))
diff --git a/src/theming/dzl-css-provider.c b/src/theming/dzl-css-provider.c
index d0b73cc..718901a 100644
--- a/src/theming/dzl-css-provider.c
+++ b/src/theming/dzl-css-provider.c
@@ -47,14 +47,52 @@ dzl_css_provider_new (const gchar *base_path)
                        NULL);
 }
 
+static gboolean
+resource_exists (const gchar *resource_path)
+{
+  g_assert (resource_path != NULL);
+
+  if (g_str_has_prefix (resource_path, "resource://"))
+    {
+      gsize len = 0;
+      guint32 flags = 0;
+
+      resource_path += strlen ("resource://");
+
+      return g_resources_get_info (resource_path, G_RESOURCE_LOOKUP_FLAGS_NONE, &len, &flags, NULL);
+    }
+
+  return g_file_test (resource_path, G_FILE_TEST_IS_REGULAR);
+}
+
+static void
+load_resource (DzlCssProvider *self,
+               const gchar    *resource_path)
+{
+  g_assert (DZL_IS_CSS_PROVIDER (self));
+  g_assert (resource_path != NULL);
+
+  if (g_str_has_prefix (resource_path, "resource://"))
+    {
+      resource_path += strlen ("resource://");
+      gtk_css_provider_load_from_resource (GTK_CSS_PROVIDER (self), resource_path);
+    }
+  else
+    {
+      g_autoptr(GError) error = NULL;
+
+      if (!gtk_css_provider_load_from_path (GTK_CSS_PROVIDER (self), resource_path, &error))
+        g_warning ("%s", error->message);
+    }
+
+}
+
 static void
 dzl_css_provider_update (DzlCssProvider *self)
 {
   g_autofree gchar *theme_name = NULL;
   g_autofree gchar *resource_path = NULL;
   GtkSettings *settings;
-  gsize len = 0;
-  guint32 flags = 0;
   gboolean prefer_dark_theme = FALSE;
 
   g_assert (DZL_IS_CSS_PROVIDER (self));
@@ -88,27 +126,26 @@ dzl_css_provider_update (DzlCssProvider *self)
                                    self->base_path,
                                    theme_name, prefer_dark_theme ? "-dark" : "");
 
-  if (!g_resources_get_info (resource_path, G_RESOURCE_LOOKUP_FLAGS_NONE, &len, &flags, NULL))
+  if (!resource_exists (resource_path))
     {
       /* Now try without the theme variant */
       g_free (resource_path);
       resource_path = g_strdup_printf ("%s/%s.css", self->base_path, theme_name);
 
       /* Now fallback to shared styling */
-      if (!g_resources_get_info (resource_path, G_RESOURCE_LOOKUP_FLAGS_NONE, &len, &flags, NULL))
+      if (!resource_exists (resource_path))
         {
           g_free (resource_path);
           resource_path = g_strdup_printf ("%s/shared.css", self->base_path);
+
+          if (!resource_exists (resource_path))
+            return;
         }
     }
 
-  /* Nothing to load */
-  if (!g_resources_get_info (resource_path, G_RESOURCE_LOOKUP_FLAGS_NONE, &len, &flags, NULL))
-    return;
-
   g_debug ("Loading css overrides \"%s\"", resource_path);
 
-  gtk_css_provider_load_from_resource (GTK_CSS_PROVIDER (self), resource_path);
+  load_resource (self, resource_path);
 }
 
 static gboolean
diff --git a/src/theming/dzl-theme-manager.c b/src/theming/dzl-theme-manager.c
index 9554b19..f3cd6dd 100644
--- a/src/theming/dzl-theme-manager.c
+++ b/src/theming/dzl-theme-manager.c
@@ -18,6 +18,8 @@
 
 #define G_LOG_DOMAIN "dzl-theme-manager"
 
+#include <string.h>
+
 #include "theming/dzl-css-provider.h"
 #include "theming/dzl-theme-manager.h"
 
@@ -63,69 +65,85 @@ dzl_theme_manager_new (void)
 }
 
 /**
- * dzl_theme_manager_add_resource_path:
+ * dzl_theme_manager_add_resources:
  * @self: a #DzlThemeManager
  * @resource_path: A path to a #GResources directory
  *
  * This will automatically register resources found within @resource_path.
  *
+ * If @resource_path starts with "resource://", embedded #GResources will be
+ * used to locate the theme files. Otherwise, @resource_path is expected to be
+ * a path on disk that may or may not exist.
+ *
  * If the @resource_path contains a directory named "themes", that directory
  * will be traversed for files matching the theme name and variant. For
  * example, if using the Adwaita theme, "themes/Adwaita.css" will be loaded. If
  * the dark variant is being used, "themes/Adwaita-dark.css" will be loaeded. If
  * no matching theme file is located, "themes/shared.css" will be loaded.
  *
+ * When the current theme changes, the CSS will be reloaded to adapt.
+ *
  * The "icons" sub-directory will be used to locate icon themes.
  */
 void
-dzl_theme_manager_add_resource_path (DzlThemeManager *self,
-                                     const gchar     *resource_path)
+dzl_theme_manager_add_resources (DzlThemeManager *self,
+                                 const gchar     *resource_path)
 {
   g_autoptr(GtkCssProvider) provider = NULL;
   g_autofree gchar *css_dir = NULL;
   g_autofree gchar *icons_dir = NULL;
+  GtkIconTheme *theme;
+  const gchar *real_path = resource_path;
 
   g_return_if_fail (DZL_IS_THEME_MANAGER (self));
   g_return_if_fail (resource_path != NULL);
 
+  theme = gtk_icon_theme_get_default ();
+
+  if (g_str_has_prefix (real_path, "resource://"))
+    real_path += strlen ("resource://");
+
   /*
    * Create a CSS provider that will load the proper variant based on the
    * current application theme, using @resource_path/css as the base directory
    * to locate theming files.
    */
   css_dir = g_build_filename (resource_path, "themes", NULL);
+  g_debug ("Including CSS overrides from %s", css_dir);
   provider = dzl_css_provider_new (css_dir);
   g_hash_table_insert (self->providers_by_path, g_strdup (resource_path), g_object_ref (provider));
   gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
                                              GTK_STYLE_PROVIDER (provider),
                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
-  g_debug ("Including CSS overrides from %s", css_dir);
 
   /*
    * Add the icons sub-directory so that Gtk can locate the themed
    * icons (svg, png, etc).
    */
-  icons_dir = g_build_filename (resource_path, "icons", NULL);
-  gtk_icon_theme_add_resource_path (gtk_icon_theme_get_default (), icons_dir);
+  icons_dir = g_build_filename (real_path, "icons", NULL);
   g_debug ("Loading icon resources from %s", icons_dir);
+  if (!g_str_equal (real_path, resource_path))
+    gtk_icon_theme_add_resource_path (theme, icons_dir);
+  else
+    gtk_icon_theme_append_search_path (theme, icons_dir);
 }
 
 /**
- * dzl_theme_manager_remove_resource_path:
+ * dzl_theme_manager_remove_resources:
  * @self: a #DzlThemeManager
  * @resource_path: A previously registered resources path
  *
  * This removes the CSS providers that were registered using @resource_path.
  *
- * You must have previously called dzl_theme_manager_add_resource_path() for
+ * You must have previously called dzl_theme_manager_add_resources() for
  * this function to do anything.
  *
  * Since icons cannot be unloaded, previously loaded icons will continue to
  * be available even after calling this function.
  */
 void
-dzl_theme_manager_remove_resource_path (DzlThemeManager *self,
-                                        const gchar     *resource_path)
+dzl_theme_manager_remove_resources (DzlThemeManager *self,
+                                    const gchar     *resource_path)
 {
   GtkStyleProvider *provider;
 
diff --git a/src/theming/dzl-theme-manager.h b/src/theming/dzl-theme-manager.h
index df9a925..b74a2d5 100644
--- a/src/theming/dzl-theme-manager.h
+++ b/src/theming/dzl-theme-manager.h
@@ -27,11 +27,11 @@ G_BEGIN_DECLS
 
 G_DECLARE_FINAL_TYPE (DzlThemeManager, dzl_theme_manager, DZL, THEME_MANAGER, GObject)
 
-DzlThemeManager *dzl_theme_manager_new                 (void);
-void             dzl_theme_manager_add_resource_path   (DzlThemeManager *self,
-                                                        const gchar     *resource_path);
-void             dzl_theme_manager_remove_resource_path (DzlThemeManager *self,
-                                                        const gchar     *resource_path);
+DzlThemeManager *dzl_theme_manager_new              (void);
+void             dzl_theme_manager_add_resources    (DzlThemeManager *self,
+                                                     const gchar     *resource_path);
+void             dzl_theme_manager_remove_resources (DzlThemeManager *self,
+                                                     const gchar     *resource_path);
 
 G_END_DECLS
 
diff --git a/tests/data/shortcuts/0/gtk/menus.ui b/tests/data/shortcuts/0/gtk/menus.ui
new file mode 100644
index 0000000..2aa8159
--- /dev/null
+++ b/tests/data/shortcuts/0/gtk/menus.ui
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <menu id="app-menu">
+    <section id="section-1"></section>
+    <section id="section-2"></section>
+    <section id="section-3"></section>
+    <section id="section-4"></section>
+  </menu>
+</interface>
diff --git a/tests/data/shortcuts/1/gtk/menus.ui b/tests/data/shortcuts/1/gtk/menus.ui
new file mode 100644
index 0000000..6c69f3a
--- /dev/null
+++ b/tests/data/shortcuts/1/gtk/menus.ui
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <menu id="app-menu">
+    <section id="section-2">
+      <item>
+        <attribute name="id">section-2-item-1</attribute>
+        <attribute name="label">Item 2.1</attribute>
+        <attribute name="action">dummy</attribute>
+      </item>
+    </section>
+    <section id="section-4">
+      <item>
+        <attribute name="id">section-4-item-1</attribute>
+        <attribute name="label">Item 4.1</attribute>
+        <attribute name="action">dummy</attribute>
+      </item>
+    </section>
+  </menu>
+</interface>
diff --git a/tests/data/shortcuts/2/gtk/menus.ui b/tests/data/shortcuts/2/gtk/menus.ui
new file mode 100644
index 0000000..ed9cc46
--- /dev/null
+++ b/tests/data/shortcuts/2/gtk/menus.ui
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <menu id="app-menu">
+    <section id="section-2">
+      <item>
+        <attribute name="id">section-2-item-2</attribute>
+        <attribute name="after">section-2-item-1</attribute>
+        <attribute name="label">Item 2.2</attribute>
+        <attribute name="action">dummy</attribute>
+      </item>
+    </section>
+  </menu>
+</interface>
diff --git a/tests/meson.build b/tests/meson.build
index bcd5f5a..7f40618 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -139,6 +139,12 @@ test_shortcut_chord = executable('test-shortcut-chord', 'test-shortcut-chord.c',
   dependencies: libdazzle_deps + [libdazzle_dep],
 )
 
+test_shortcut_overlays = executable('test-shortcut-overlays', 'test-shortcut-overlays.c',
+        c_args: test_cflags,
+     link_args: test_link_args,
+  dependencies: libdazzle_deps + [libdazzle_dep],
+)
+
 test_shortcut_theme = executable('test-shortcut-theme', 'test-shortcut-theme.c',
         c_args: test_cflags,
      link_args: test_link_args,
diff --git a/tests/test-cpu-graph.c b/tests/test-cpu-graph.c
index 6b971b1..6e97bab 100644
--- a/tests/test-cpu-graph.c
+++ b/tests/test-cpu-graph.c
@@ -37,7 +37,7 @@ main (int argc,
   timespan = (gint64)seconds * G_USEC_PER_SEC;
   max_samples = seconds * samples;
 
-  provider = dzl_css_provider_new ("/org/gnome/dazzle/themes");
+  provider = dzl_css_provider_new ("resource:///org/gnome/dazzle/themes");
   gtk_style_context_add_provider_for_screen (gdk_screen_get_default (), GTK_STYLE_PROVIDER (provider), 
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
   g_object_unref (provider);
 
diff --git a/tests/test-desktop-index.c b/tests/test-desktop-index.c
index 0307131..c3e4099 100644
--- a/tests/test-desktop-index.c
+++ b/tests/test-desktop-index.c
@@ -115,7 +115,7 @@ create_ui (void)
   g_autoptr(GtkCssProvider) provider = NULL;
   gboolean r;
 
-  provider = dzl_css_provider_new ("/org/gnome/dazzle/themes");
+  provider = dzl_css_provider_new ("resource:///org/gnome/dazzle/themes");
   gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
                                              GTK_STYLE_PROVIDER (provider),
                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION-1);
diff --git a/tests/test-panel.c b/tests/test-panel.c
index 0918529..c6b54a9 100644
--- a/tests/test-panel.c
+++ b/tests/test-panel.c
@@ -149,7 +149,7 @@ load_css (void)
 {
   g_autoptr(GtkCssProvider) provider = NULL;
 
-  provider = dzl_css_provider_new ("/org/gnome/dazzle/themes");
+  provider = dzl_css_provider_new ("resource:///org/gnome/dazzle/themes");
   gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
                                              GTK_STYLE_PROVIDER (provider),
                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
diff --git a/tests/test-path-bar.c b/tests/test-path-bar.c
index 8092b0b..4166a1d 100644
--- a/tests/test-path-bar.c
+++ b/tests/test-path-bar.c
@@ -5,7 +5,7 @@ load_css (void)
 {
   g_autoptr(GtkCssProvider) provider = NULL;
 
-  provider = dzl_css_provider_new ("/org/gnome/dazzle/themes");
+  provider = dzl_css_provider_new ("resource:///org/gnome/dazzle/themes");
   gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
                                              GTK_STYLE_PROVIDER (provider),
                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
diff --git a/tests/test-pill-box.c b/tests/test-pill-box.c
index 85907a0..1330041 100644
--- a/tests/test-pill-box.c
+++ b/tests/test-pill-box.c
@@ -15,7 +15,7 @@ load_css (void)
 {
   g_autoptr(GtkCssProvider) provider = NULL;
 
-  provider = dzl_css_provider_new ("/org/gnome/dazzle/themes");
+  provider = dzl_css_provider_new ("resource:///org/gnome/dazzle/themes");
   gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
                                              GTK_STYLE_PROVIDER (provider),
                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
diff --git a/tests/test-preferences.c b/tests/test-preferences.c
index 06fdbab..550f016 100644
--- a/tests/test-preferences.c
+++ b/tests/test-preferences.c
@@ -54,7 +54,7 @@ load_css (void)
 {
   g_autoptr(GtkCssProvider) provider = NULL;
 
-  provider = dzl_css_provider_new ("/org/gnome/dazzle/themes");
+  provider = dzl_css_provider_new ("resource:///org/gnome/dazzle/themes");
   gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
                                              GTK_STYLE_PROVIDER (provider),
                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
diff --git a/tests/test-progress-button.c b/tests/test-progress-button.c
index 7f2df57..74c9720 100644
--- a/tests/test-progress-button.c
+++ b/tests/test-progress-button.c
@@ -5,7 +5,7 @@ load_css (void)
 {
   g_autoptr(GtkCssProvider) provider = NULL;
 
-  provider = dzl_css_provider_new ("/org/gnome/dazzle/themes");
+  provider = dzl_css_provider_new ("resource:///org/gnome/dazzle/themes");
   gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
                                              GTK_STYLE_PROVIDER (provider),
                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
diff --git a/tests/test-shortcut-overlays.c b/tests/test-shortcut-overlays.c
new file mode 100644
index 0000000..e585a10
--- /dev/null
+++ b/tests/test-shortcut-overlays.c
@@ -0,0 +1,74 @@
+#include <dazzle.h>
+
+static void
+on_startup (DzlApplication *app)
+{
+  dzl_application_add_resources (app, TEST_DATA_DIR"/shortcuts/0");
+  dzl_application_add_resources (app, TEST_DATA_DIR"/shortcuts/1");
+  dzl_application_add_resources (app, TEST_DATA_DIR"/shortcuts/2");
+}
+
+static void
+on_activate (DzlApplication *app)
+{
+  g_autofree gchar *id1 = NULL;
+  g_autofree gchar *id2 = NULL;
+  g_autofree gchar *id3 = NULL;
+  g_autofree gchar *label1 = NULL;
+  g_autoptr(GMenuModel) link1 = NULL;
+  g_autoptr(GMenuModel) link2 = NULL;
+  GMenu *menu;
+  guint len;
+  gboolean r;
+
+  menu = dzl_application_get_menu_by_id (app, "app-menu");
+  g_assert (G_IS_MENU (menu));
+
+  len = g_menu_model_get_n_items (G_MENU_MODEL (menu));
+  g_assert_cmpint (len, ==, 4);
+
+  g_assert (NULL != g_menu_model_get_item_link (G_MENU_MODEL (menu), 0, G_MENU_LINK_SECTION));
+
+  link1 = g_menu_model_get_item_link (G_MENU_MODEL (menu), 1, G_MENU_LINK_SECTION);
+  g_assert (link1 != NULL);
+  g_assert_cmpint (g_menu_model_get_n_items (link1), ==, 2);
+
+  r = g_menu_model_get_item_attribute (link1, 0, "id", "s", &id1);
+  g_assert_cmpint (r, ==, TRUE);
+  g_assert_cmpstr (id1, ==, "section-2-item-1");
+
+  r = g_menu_model_get_item_attribute (link1, 0, "label", "s", &label1);
+  g_assert_cmpint (r, ==, TRUE);
+  g_assert_cmpstr (label1, ==, "Item 2.1");
+
+  r = g_menu_model_get_item_attribute (link1, 1, "id", "s", &id2);
+  g_assert_cmpint (r, ==, TRUE);
+  g_assert_cmpstr (id2, ==, "section-2-item-2");
+
+  g_assert (NULL != g_menu_model_get_item_link (G_MENU_MODEL (menu), 2, G_MENU_LINK_SECTION));
+
+  link2 = g_menu_model_get_item_link (G_MENU_MODEL (menu), 3, G_MENU_LINK_SECTION);
+  g_assert (link2 != NULL);
+  g_assert_cmpint (g_menu_model_get_n_items (link2), ==, 1);
+
+  r = g_menu_model_get_item_attribute (link2, 0, "id", "s", &id3);
+  g_assert_cmpint (r, ==, TRUE);
+  g_assert_cmpstr (id3, ==, "section-4-item-1");
+}
+
+gint
+main (gint   argc,
+      gchar *argv[])
+{
+  g_autoptr(DzlApplication) app = NULL;
+
+  app = g_object_new (DZL_TYPE_APPLICATION,
+                      "application-id", "org.gnome.Dazzle.Tests.Shortcuts",
+                      "flags", G_APPLICATION_NON_UNIQUE,
+                      NULL);
+
+  g_signal_connect (app, "activate", G_CALLBACK (on_activate), NULL);
+  g_signal_connect (app, "startup", G_CALLBACK (on_startup), NULL);
+
+  return g_application_run (G_APPLICATION (app), argc, argv);
+}
diff --git a/tests/test-stack-list.c b/tests/test-stack-list.c
index 82910ba..9fedad4 100644
--- a/tests/test-stack-list.c
+++ b/tests/test-stack-list.c
@@ -84,7 +84,7 @@ load_css (void)
 {
   g_autoptr(GtkCssProvider) provider = NULL;
 
-  provider = dzl_css_provider_new ("/org/gnome/dazzle/themes");
+  provider = dzl_css_provider_new ("resource:///org/gnome/dazzle/themes");
   gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
                                              GTK_STYLE_PROVIDER (provider),
                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
diff --git a/tests/test-suggestion.c b/tests/test-suggestion.c
index 82df712..46091e4 100644
--- a/tests/test-suggestion.c
+++ b/tests/test-suggestion.c
@@ -227,7 +227,7 @@ load_css (void)
 {
   g_autoptr(GtkCssProvider) provider = NULL;
 
-  provider = dzl_css_provider_new ("/org/gnome/dazzle/themes");
+  provider = dzl_css_provider_new ("resource:///org/gnome/dazzle/themes");
   gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
                                              GTK_STYLE_PROVIDER (provider),
                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);


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