* 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Ryan Lortie <desrt@desrt.ca>
*/
+#include "config.h"
+
#include "gmenuexporter.h"
#include "gdbusmethodinvocation.h"
* SECTION:gmenuexporter
* @title: GMenuModel exporter
* @short_description: Export GMenuModels on D-Bus
- * @see_also: #GMenuModel, #GMenuProxy
+ * @include: gio/gio.h
+ * @see_also: #GMenuModel, #GDBusMenuModel
*
* These functions support exporting a #GMenuModel on D-Bus.
* The D-Bus interface that is used is a private implementation
* detail.
*
* To access an exported #GMenuModel remotely, use
- * g_menu_proxy_get() to obtain a #GMenuProxy.
+ * g_dbus_menu_model_get() to obtain a #GDBusMenuModel.
*/
/* {{{1 D-Bus Interface description */
+
+/* For documentation of this interface, see
+ * https://wiki.gnome.org/Projects/GLib/GApplication/DBusAPI
+ */
+
static GDBusInterfaceInfo *
org_gtk_Menus_get_interface (void)
{
GMenuExporterGroup *group;
GMenuExporterLink *tmp;
- if (0) /* [magic] */
+ /* keep sections in the same group, but create new groups
+ * otherwise
+ */
+ if (!g_str_equal (name, "section"))
group = g_menu_exporter_create_group (g_menu_exporter_group_get_exporter (menu->group));
else
group = menu->group;
group->prepared = TRUE;
menu = g_hash_table_lookup (group->menus, 0);
- g_menu_exporter_menu_prepare (menu);
+
+ /* If the group was created by a subscription and does not yet
+ * exist, it won't have a root menu...
+ *
+ * That menu will be prepared if it is ever added (due to
+ * group->prepared == TRUE).
+ */
+ if (menu)
+ g_menu_exporter_menu_prepare (menu);
}
group->subscribed++;
count = (gsize) g_hash_table_lookup (remote->watches, GINT_TO_POINTER (group_id));
g_hash_table_insert (remote->watches, GINT_TO_POINTER (group_id), GINT_TO_POINTER (count + 1));
+ /* Group will be created (as empty/unsubscribed if it does not exist) */
group = g_menu_exporter_lookup_group (remote->exporter, group_id);
g_menu_exporter_group_subscribe (group, builder);
}
{
GMenuExporter *exporter = user_data;
- g_assert (exporter->connection == connection);
+ /* connection == NULL when we get called because the connection closed */
+ g_assert (exporter->connection == connection || connection == NULL);
g_hash_table_remove (exporter->remotes, name);
}
}
static void
-g_menu_exporter_free (GMenuExporter *exporter)
+g_menu_exporter_free (gpointer user_data)
{
- g_dbus_connection_unregister_object (exporter->connection, exporter->registration_id);
+ GMenuExporter *exporter = user_data;
+
g_menu_exporter_menu_free (exporter->root);
g_hash_table_unref (exporter->remotes);
g_hash_table_unref (exporter->groups);
g_variant_unref (group_ids);
}
-static GDBusConnection *
-g_menu_exporter_get_connection (GMenuExporter *exporter)
-{
- return exporter->connection;
-}
-
-static const gchar *
-g_menu_exporter_get_object_path (GMenuExporter *exporter)
-{
- return exporter->object_path;
-}
-
-static GMenuExporter *
-g_menu_exporter_new (GDBusConnection *connection,
- const gchar *object_path,
- GMenuModel *model,
- GError **error)
-{
- const GDBusInterfaceVTable vtable = {
- g_menu_exporter_method_call,
- };
- GMenuExporter *exporter;
- guint id;
-
- exporter = g_slice_new0 (GMenuExporter);
-
- id = g_dbus_connection_register_object (connection, object_path, org_gtk_Menus_get_interface (),
- &vtable, exporter, NULL, error);
-
- if (id == 0)
- {
- g_slice_free (GMenuExporter, exporter);
- return NULL;
- }
-
- exporter->connection = g_object_ref (connection);
- exporter->object_path = g_strdup (object_path);
- exporter->registration_id = id;
- exporter->groups = g_hash_table_new (NULL, NULL);
- exporter->remotes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_menu_exporter_remote_free);
- exporter->root = g_menu_exporter_group_add_menu (g_menu_exporter_create_group (exporter), model);
-
- return exporter;
-}
-
/* {{{1 Public API */
-static GHashTable *g_menu_exporter_exported_menus;
-
/**
- * g_menu_exporter_export:
+ * g_dbus_connection_export_menu_model:
* @connection: a #GDBusConnection
* @object_path: a D-Bus object path
* @menu: a #GMenuModel
* The implemented D-Bus API should be considered private.
* It is subject to change in the future.
*
- * A given menu model can only be exported on one object path
- * and an object_path can only have one action group exported
- * on it. If either constraint is violated, the export will
- * fail and %FALSE will be returned (with @error set accordingly).
+ * An object path can only have one menu model exported on it. If this
+ * constraint is violated, the export will fail and 0 will be
+ * returned (with @error set accordingly).
+ *
+ * You can unexport the menu model using
+ * g_dbus_connection_unexport_menu_model() with the return value of
+ * this function.
*
- * Use g_menu_exporter_stop() to stop exporting @menu
- * or g_menu_exporter_query() to find out if and where a given
- * menu model is exported.
+ * Returns: the ID of the export (never zero), or 0 in case of failure
*
- * Returns: %TRUE if the export is successful, or %FALSE (with
- * @error set) in the event of a failure.
+ * Since: 2.32
*/
-gboolean
-g_menu_exporter_export (GDBusConnection *connection,
- const gchar *object_path,
- GMenuModel *menu,
- GError **error)
+guint
+g_dbus_connection_export_menu_model (GDBusConnection *connection,
+ const gchar *object_path,
+ GMenuModel *menu,
+ GError **error)
{
+ const GDBusInterfaceVTable vtable = {
+ g_menu_exporter_method_call,
+ };
GMenuExporter *exporter;
+ guint id;
+
+ exporter = g_slice_new0 (GMenuExporter);
- if G_UNLIKELY (g_menu_exporter_exported_menus == NULL)
- g_menu_exporter_exported_menus = g_hash_table_new (NULL, NULL);
+ id = g_dbus_connection_register_object (connection, object_path, org_gtk_Menus_get_interface (),
+ &vtable, exporter, g_menu_exporter_free, error);
- if G_UNLIKELY (g_hash_table_lookup (g_menu_exporter_exported_menus, menu))
+ if (id == 0)
{
- g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FILE_EXISTS, "The given GMenuModel has already been exported");
- return FALSE;
+ g_slice_free (GMenuExporter, exporter);
+ return 0;
}
- exporter = g_menu_exporter_new (connection, object_path, menu, error);
-
- if (exporter == NULL)
- return FALSE;
-
- g_hash_table_insert (g_menu_exporter_exported_menus, menu, exporter);
-
- return TRUE;
-}
-
-/**
- * g_menu_exporter_stop:
- * @menu: a #GMenuModel
- *
- * Stops the export of @menu.
- *
- * This reverses the effect of a previous call to
- * g_menu_exporter_export() for @menu.
- *
- * Returns: %TRUE if an export was stopped or %FALSE
- * if @menu was not exported in the first place
- */
-gboolean
-g_menu_exporter_stop (GMenuModel *menu)
-{
- GMenuExporter *exporter;
-
- if G_UNLIKELY (g_menu_exporter_exported_menus == NULL)
- return FALSE;
-
- exporter = g_hash_table_lookup (g_menu_exporter_exported_menus, menu);
- if G_UNLIKELY (exporter == NULL)
- return FALSE;
-
- g_hash_table_remove (g_menu_exporter_exported_menus, menu);
- g_menu_exporter_free (exporter);
+ exporter->connection = g_object_ref (connection);
+ exporter->object_path = g_strdup (object_path);
+ exporter->groups = g_hash_table_new (NULL, NULL);
+ exporter->remotes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_menu_exporter_remote_free);
+ exporter->root = g_menu_exporter_group_add_menu (g_menu_exporter_create_group (exporter), menu);
- return TRUE;
+ return id;
}
/**
- * g_menu_exporter_query:
- * @menu: a #GMenuModel
- * @connection: (out): the #GDBusConnection used for exporting
- * @object_path: (out): the object path used for exporting
- *
- * Queries if and where @menu is exported.
+ * g_dbus_connection_unexport_menu_model:
+ * @connection: a #GDBusConnection
+ * @export_id: the ID from g_dbus_connection_export_menu_model()
*
- * If @menu is exported, %TRUE is returned. If @connection is
- * non-%NULL then it is set to the #GDBusConnection used for
- * the export. If @object_path is non-%NULL then it is set to
- * the object path.
+ * Reverses the effect of a previous call to
+ * g_dbus_connection_export_menu_model().
*
- * If the @menu is not exported, %FALSE is returned and
- * @connection and @object_path remain unmodified.
+ * It is an error to call this function with an ID that wasn't returned
+ * from g_dbus_connection_export_menu_model() or to call it with the
+ * same ID more than once.
*
- * Returns: %TRUE if @menu was exported, else %FALSE
+ * Since: 2.32
*/
-gboolean
-g_menu_exporter_query (GMenuModel *menu,
- GDBusConnection **connection,
- const gchar **object_path)
+void
+g_dbus_connection_unexport_menu_model (GDBusConnection *connection,
+ guint export_id)
{
- GMenuExporter *exporter;
-
- if (g_menu_exporter_exported_menus == NULL)
- return FALSE;
-
- exporter = g_hash_table_lookup (g_menu_exporter_exported_menus, menu);
- if (exporter == NULL)
- return FALSE;
-
- if (connection)
- *connection = g_menu_exporter_get_connection (exporter);
-
- if (object_path)
- *object_path = g_menu_exporter_get_object_path (exporter);
-
- return TRUE;
+ g_dbus_connection_unregister_object (connection, export_id);
}
/* {{{1 Epilogue */