gnome-online-accounts-gtk: add recipe

GNOME Online Accounts only provides the daemon and library that
applications such as gnome-calendar, gnome-contacts and evolution use
for their calendar, mail and contact accounts. The only user interface
for adding accounts is the online-accounts panel of gnome-control-center,
which pulls in gnome-shell and its settings daemon. Desktops built on
wlroots compositors or other GTK environments have no way to configure
these accounts at all.

gnome-online-accounts-gtk from the xapp project is a standalone GTK4 and
libadwaita application for exactly that job and works without GNOME
Shell.

GNOME applications open the accounts settings by activating the
"launch-panel" action of org.gnome.Settings on the session bus. The
included patch provides that name and action from
gnome-online-accounts-gtk together with a D-Bus service file, so these
buttons work here too. Since only one package can own the bus name, the
package conflicts with gnome-control-center.

Build tested on corei7-64.

AI-Generated: Uses Claude Code (Claude Fable 5.1)
Signed-off-by: Markus Volk <f_l_k@t-online.de>
Signed-off-by: Khem Raj <khem.raj@oss.qualcomm.com>
This commit is contained in:
Markus Volk
2026-09-07 19:01:28 -07:00
committed by Khem Raj
parent ba483062c6
commit 824f6afda9
2 changed files with 290 additions and 0 deletions
@@ -0,0 +1,261 @@
From 08e3b37df99f89c8e36cea80304e2bc1f2986659 Mon Sep 17 00:00:00 2001
From: Markus Volk <f_l_k@t-online.de>
Date: Sun, 6 Sep 2026 18:36:48 +0200
Subject: [PATCH] Provide the org.gnome.Settings launch-panel interface
GNOME applications such as gnome-calendar, gnome-contacts or evolution
open the online accounts settings by activating the "launch-panel"
action of org.gnome.Settings on the session bus, which is only provided
by gnome-control-center. On desktops that ship gnome-online-accounts-gtk
instead, these buttons silently do nothing.
Export the application actions on /org/gnome/Settings as well, own the
org.gnome.Settings name once the application has started and install a
D-Bus service file so the application gets activated on demand. The
"online-accounts" panel presents the main window; when an account id is
passed as the first argument, the matching account is opened, mirroring
the behaviour of the gnome-control-center panel. Other panel ids are
ignored with a warning.
Upstream-Status: Pending
AI-Generated: Uses Claude Code (Claude Fable 5.1)
---
data/meson.build | 8 ++
data/org.gnome.Settings.service.in | 3 +
src/gnome-online-accounts-gtk.c | 152 ++++++++++++++++++++++++++++-
3 files changed, 159 insertions(+), 4 deletions(-)
create mode 100644 data/org.gnome.Settings.service.in
diff --git a/data/meson.build b/data/meson.build
index deadf44..71e27aa 100644
--- a/data/meson.build
+++ b/data/meson.build
@@ -24,4 +24,12 @@ i18n.merge_file(
install_dir: datadir / 'applications'
)
+configure_file(
+ input: 'org.gnome.Settings.service.in',
+ output: 'org.gnome.Settings.service',
+ configuration: bin_conf,
+ install: true,
+ install_dir: datadir / 'dbus-1' / 'services',
+)
+
subdir('icons')
\ No newline at end of file
diff --git a/data/org.gnome.Settings.service.in b/data/org.gnome.Settings.service.in
new file mode 100644
index 0000000..ab4b5a1
--- /dev/null
+++ b/data/org.gnome.Settings.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.gnome.Settings
+Exec=@bindir@/gnome-online-accounts-gtk --gapplication-service
diff --git a/src/gnome-online-accounts-gtk.c b/src/gnome-online-accounts-gtk.c
index 25bd116..60d3472 100644
--- a/src/gnome-online-accounts-gtk.c
+++ b/src/gnome-online-accounts-gtk.c
@@ -32,6 +32,8 @@ struct _OaWindow
GtkWidget *accounts_label;
GtkWidget *offline_revealer;
+
+ gchar *pending_account_id;
};
G_DEFINE_TYPE (OaWindow, oa_window, GTK_TYPE_APPLICATION_WINDOW)
@@ -102,6 +104,43 @@ show_account (OaWindow *window,
}
}
+static void
+show_account_by_id (OaWindow *window,
+ const gchar *account_id)
+{
+ guint n_items;
+ guint i;
+
+ if (window->client == NULL)
+ {
+ g_free (window->pending_account_id);
+ window->pending_account_id = g_strdup (account_id);
+ return;
+ }
+
+ n_items = g_list_model_get_n_items (window->accounts_model);
+
+ for (i = 0; i < n_items; i++)
+ {
+ GoaObject *object;
+ GoaAccount *account;
+
+ object = g_list_model_get_item (window->accounts_model, i);
+ account = goa_object_peek_account (object);
+
+ if (g_strcmp0 (goa_account_get_id (account), account_id) == 0)
+ {
+ show_account (window, object);
+ g_object_unref (object);
+ return;
+ }
+
+ g_object_unref (object);
+ }
+
+ g_warning ("No account with id '%s'", account_id);
+}
+
static void
add_account_cb (GoaProvider *provider,
GAsyncResult *res,
@@ -418,6 +457,15 @@ new_client_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
populate_accounts (window);
goa_provider_get_all (get_all_providers_cb, window);
+
+ if (window->pending_account_id != NULL)
+ {
+ gchar *account_id;
+
+ account_id = g_steal_pointer (&window->pending_account_id);
+ show_account_by_id (window, account_id);
+ g_free (account_id);
+ }
}
static void
@@ -440,6 +488,7 @@ oa_window_dispose (GObject *object)
}
g_clear_object (&window->client);
+ g_clear_pointer (&window->pending_account_id, g_free);
G_OBJECT_CLASS (oa_window_parent_class)->dispose (object);
}
@@ -507,18 +556,112 @@ oa_window_new (void)
return g_object_new (oa_window_get_type (), NULL);
}
+static OaWindow *
+get_window (GtkApplication *app)
+{
+ OaWindow *window;
+ GList *l;
+
+ for (l = gtk_application_get_windows (app); l != NULL; l = l->next)
+ {
+ if (OA_IS_WINDOW (l->data))
+ {
+ return OA_WINDOW (l->data);
+ }
+ }
+
+ window = oa_window_new ();
+ gtk_window_set_application (GTK_WINDOW (window), app);
+
+ return window;
+}
+
static void
on_app_activate (GtkApplication *app, gpointer user_data)
{
- static OaWindow *window = NULL;
+ gtk_window_present (GTK_WINDOW (get_window (app)));
+}
+
+static void
+launch_panel_activated (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ GtkApplication *app = GTK_APPLICATION (user_data);
+ OaWindow *window;
+ const gchar *panel_id;
+ GVariant *parameters;
+
+ g_variant_get (parameter, "(&s@av)", &panel_id, &parameters);
- if (window == NULL)
+ if (g_strcmp0 (panel_id, "online-accounts") != 0)
{
- window = oa_window_new ();
- gtk_window_set_application (GTK_WINDOW (window), app);
+ g_warning ("Panel '%s' is not provided by gnome-online-accounts-gtk", panel_id);
+ g_variant_unref (parameters);
+ return;
}
+ window = get_window (app);
gtk_window_present (GTK_WINDOW (window));
+
+ if (g_variant_n_children (parameters) > 0)
+ {
+ GVariant *value;
+
+ g_variant_get_child (parameters, 0, "v", &value);
+
+ if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING) &&
+ g_variant_get_string (value, NULL)[0] != '\0')
+ {
+ show_account_by_id (window, g_variant_get_string (value, NULL));
+ }
+
+ g_variant_unref (value);
+ }
+
+ g_variant_unref (parameters);
+}
+
+static const GActionEntry app_actions[] = {
+ { "launch-panel", launch_panel_activated, "(sav)", NULL, NULL, { 0 } },
+ { "launch-single-panel-mode", launch_panel_activated, "(sav)", NULL, NULL, { 0 } },
+};
+
+static void
+on_app_startup (GApplication *app, gpointer user_data)
+{
+ GDBusConnection *connection;
+ GError *error = NULL;
+
+ g_action_map_add_action_entries (G_ACTION_MAP (app),
+ app_actions,
+ G_N_ELEMENTS (app_actions),
+ app);
+
+ connection = g_application_get_dbus_connection (app);
+
+ if (connection == NULL)
+ {
+ return;
+ }
+
+ if (g_dbus_connection_export_action_group (connection,
+ "/org/gnome/Settings",
+ G_ACTION_GROUP (app),
+ &error) == 0)
+ {
+ g_warning ("Failed to export actions on /org/gnome/Settings: %s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ g_bus_own_name_on_connection (connection,
+ "org.gnome.Settings",
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
}
int main(int argc, char *argv[]) {
@@ -541,6 +684,7 @@ int main(int argc, char *argv[]) {
g_application_set_option_context_summary (G_APPLICATION (app), "gnome-online-accounts-gtk: A GTK Frontend for GNOME Online Accounts");
+ g_signal_connect (app, "startup", G_CALLBACK (on_app_startup), NULL);
g_signal_connect (app, "activate", G_CALLBACK (on_app_activate), NULL);
ret = g_application_run (G_APPLICATION (app), argc, argv);
@@ -0,0 +1,29 @@
# AI-Generated: Uses Claude Code (Claude Fable 5.1)
SUMMARY = "GTK frontend for configuring GNOME Online Accounts"
DESCRIPTION = "Standalone GTK4/libadwaita application to add and manage \
GNOME Online Accounts on desktops that do not ship gnome-control-center."
HOMEPAGE = "https://github.com/xapp-project/gnome-online-accounts-gtk"
SECTION = "x11/gnome"
LICENSE = "GPL-3.0-or-later"
LIC_FILES_CHKSUM = "file://COPYING;md5=d32239bcb673463ab874e80d47fae504"
DEPENDS = " \
glib-2.0 \
glib-2.0-native \
gnome-online-accounts \
gtk4 \
libadwaita \
libxml2-native \
"
SRC_URI = " \
git://github.com/xapp-project/gnome-online-accounts-gtk.git;protocol=https;branch=master;tag=${PV} \
file://0001-Provide-the-org.gnome.Settings-launch-panel-interface.patch \
"
SRCREV = "b42482522bc9089c139ceda9b8a7d81a7a149cf9"
inherit meson pkgconfig gettext gtk-icon-cache
FILES:${PN} += "${datadir}/dbus-1/services"
RCONFLICTS:${PN} += "gnome-control-center"