diff --git a/Makefile.am.inc b/Makefile.am.inc
index 7be4c4f89..32b3d3656 100644
--- a/Makefile.am.inc
+++ b/Makefile.am.inc
@@ -9,6 +9,7 @@ PORTAL_IFACE_FILES =\
$(top_srcdir)/data/org.freedesktop.portal.FileChooser.xml \
$(top_srcdir)/data/org.freedesktop.portal.FileTransfer.xml \
$(top_srcdir)/data/org.freedesktop.portal.GameMode.xml \
+ $(top_srcdir)/data/org.freedesktop.portal.GlobalShortcuts.xml \
$(top_srcdir)/data/org.freedesktop.portal.Inhibit.xml \
$(top_srcdir)/data/org.freedesktop.portal.Location.xml \
$(top_srcdir)/data/org.freedesktop.portal.MemoryMonitor.xml \
@@ -38,6 +39,7 @@ PORTAL_IMPL_IFACE_FILES =\
$(top_srcdir)/data/org.freedesktop.impl.portal.DynamicLauncher.xml \
$(top_srcdir)/data/org.freedesktop.impl.portal.Email.xml \
$(top_srcdir)/data/org.freedesktop.impl.portal.FileChooser.xml \
+ $(top_srcdir)/data/org.freedesktop.impl.portal.GlobalShortcuts.xml \
$(top_srcdir)/data/org.freedesktop.impl.portal.Inhibit.xml \
$(top_srcdir)/data/org.freedesktop.impl.portal.Lockdown.xml \
$(top_srcdir)/data/org.freedesktop.impl.portal.Notification.xml \
diff --git a/data/meson.build b/data/meson.build
index 489479f18..22355c2d9 100644
--- a/data/meson.build
+++ b/data/meson.build
@@ -12,6 +12,7 @@ portal_sources = files(
'org.freedesktop.portal.FileChooser.xml',
'org.freedesktop.portal.FileTransfer.xml',
'org.freedesktop.portal.GameMode.xml',
+ 'org.freedesktop.portal.GlobalShortcuts.xml',
'org.freedesktop.portal.Inhibit.xml',
'org.freedesktop.portal.Location.xml',
'org.freedesktop.portal.MemoryMonitor.xml',
@@ -41,6 +42,7 @@ portal_impl_sources = files(
'org.freedesktop.impl.portal.DynamicLauncher.xml',
'org.freedesktop.impl.portal.Email.xml',
'org.freedesktop.impl.portal.FileChooser.xml',
+ 'org.freedesktop.impl.portal.GlobalShortcuts.xml',
'org.freedesktop.impl.portal.Inhibit.xml',
'org.freedesktop.impl.portal.Lockdown.xml',
'org.freedesktop.impl.portal.Notification.xml',
@@ -58,4 +60,4 @@ portal_impl_sources = files(
install_data([portal_sources, portal_impl_sources],
install_dir: datadir / 'dbus-1' / 'interfaces',
-)
\ No newline at end of file
+)
diff --git a/data/org.freedesktop.impl.portal.GlobalShortcuts.xml b/data/org.freedesktop.impl.portal.GlobalShortcuts.xml
new file mode 100644
index 000000000..85fcf6259
--- /dev/null
+++ b/data/org.freedesktop.impl.portal.GlobalShortcuts.xml
@@ -0,0 +1,168 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/data/org.freedesktop.portal.GlobalShortcuts.xml b/data/org.freedesktop.portal.GlobalShortcuts.xml
new file mode 100644
index 000000000..aa4042628
--- /dev/null
+++ b/data/org.freedesktop.portal.GlobalShortcuts.xml
@@ -0,0 +1,192 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Makefile.am.inc b/src/Makefile.am.inc
index 86a8de0b9..d7e07fe78 100644
--- a/src/Makefile.am.inc
+++ b/src/Makefile.am.inc
@@ -130,6 +130,8 @@ xdg_desktop_portal_SOURCES = \
src/flatpak-instance.h \
src/portal-impl.h \
src/portal-impl.c \
+ src/globalshortcuts.h \
+ src/globalshortcuts.c \
$(NULL)
if HAVE_LIBSYSTEMD
diff --git a/src/globalshortcuts.c b/src/globalshortcuts.c
new file mode 100644
index 000000000..311124518
--- /dev/null
+++ b/src/globalshortcuts.c
@@ -0,0 +1,553 @@
+/*
+ * Copyright © 2022 Aleix Pol Gonzalez
+ *
+ * This program 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 .
+ *
+ * Authors:
+ * Aleix Pol Gonzalez
+ */
+
+#include "config.h"
+
+#include
+#include
+
+#include "globalshortcuts.h"
+#include "request.h"
+#include "session.h"
+#include "permissions.h"
+#include "xdp-dbus.h"
+#include "xdp-impl-dbus.h"
+#include "xdp-utils.h"
+
+typedef struct _GlobalShortcuts GlobalShortcuts;
+typedef struct _GlobalShortcutsClass GlobalShortcutsClass;
+
+static GQuark quark_request_session;
+
+struct _GlobalShortcuts
+{
+ XdpDbusGlobalShortcutsSkeleton parent_instance;
+};
+
+struct _GlobalShortcutsClass
+{
+ XdpDbusGlobalShortcutsSkeletonClass parent_class;
+};
+
+static XdpDbusImplGlobalShortcuts *impl;
+static GlobalShortcuts *global_shortcuts;
+
+GType global_shortcuts_get_type (void) G_GNUC_CONST;
+static void global_shortcuts_iface_init (XdpDbusGlobalShortcutsIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GlobalShortcuts, global_shortcuts, XDP_DBUS_TYPE_GLOBAL_SHORTCUTS_SKELETON,
+ G_IMPLEMENT_INTERFACE (XDP_DBUS_TYPE_GLOBAL_SHORTCUTS, global_shortcuts_iface_init));
+
+typedef struct _GlobalShortcutsSession
+{
+ Session parent;
+
+ gboolean closed;
+} GlobalShortcutsSession;
+
+typedef struct _GlobalShortcutsSessionClass
+{
+ SessionClass parent_class;
+} GlobalShortcutsSessionClass;
+
+GType global_shortcuts_session_get_type (void);
+
+G_DEFINE_TYPE (GlobalShortcutsSession, global_shortcuts_session, session_get_type ())
+
+static void
+global_shortcuts_session_close (Session *session)
+{
+ GlobalShortcutsSession *global_shortcuts_session = (GlobalShortcutsSession *)session;
+
+ global_shortcuts_session->closed = TRUE;
+}
+
+static void
+global_shortcuts_session_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (global_shortcuts_session_parent_class)->finalize (object);
+}
+
+static void
+global_shortcuts_session_init (GlobalShortcutsSession *global_shortcuts_session)
+{
+}
+
+static void
+global_shortcuts_session_class_init (GlobalShortcutsSessionClass *klass)
+{
+ GObjectClass *object_class;
+ SessionClass *session_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = global_shortcuts_session_finalize;
+
+ session_class = (SessionClass *)klass;
+ session_class->close = global_shortcuts_session_close;
+}
+
+static GlobalShortcutsSession *
+global_shortcuts_session_new (GVariant *options,
+ Request *request,
+ GError **error)
+{
+ Session *session;
+ GDBusInterfaceSkeleton *interface_skeleton =
+ G_DBUS_INTERFACE_SKELETON (request);
+ const char *session_token;
+ GDBusConnection *connection =
+ g_dbus_interface_skeleton_get_connection (interface_skeleton);
+ GDBusConnection *impl_connection =
+ g_dbus_proxy_get_connection (G_DBUS_PROXY (impl));
+ const char *impl_dbus_name = g_dbus_proxy_get_name (G_DBUS_PROXY (impl));
+
+ session_token = lookup_session_token (options);
+ session = g_initable_new (global_shortcuts_session_get_type (), NULL, error,
+ "sender", request->sender,
+ "app-id", xdp_app_info_get_id (request->app_info),
+ "token", session_token,
+ "connection", connection,
+ "impl-connection", impl_connection,
+ "impl-dbus-name", impl_dbus_name,
+ NULL);
+
+ if (session)
+ g_debug ("global shortcuts session owned by '%s' created", session->sender);
+
+ return (GlobalShortcutsSession *) session;
+}
+
+static void
+create_session_done (GObject *source_object,
+ GAsyncResult *res,
+ gpointer data)
+{
+ g_autoptr(Request) request = data;
+ Session *session;
+ guint response = 2;
+ GVariant *opts;
+ gboolean should_close_session;
+ GVariantBuilder results_builder;
+ g_autoptr(GError) error = NULL;
+
+ REQUEST_AUTOLOCK (request);
+
+ session = g_object_get_qdata (G_OBJECT (request), quark_request_session);
+ SESSION_AUTOLOCK_UNREF (g_object_ref (session));
+ g_object_set_qdata (G_OBJECT (request), quark_request_session, NULL);
+
+ g_variant_builder_init (&results_builder, G_VARIANT_TYPE_VARDICT);
+
+ if (!xdp_dbus_impl_global_shortcuts_call_create_session_finish (impl,
+ &response,
+ &opts,
+ res,
+ &error))
+ {
+ g_dbus_error_strip_remote_error (error);
+ g_warning ("A backend call failed: %s", error->message);
+ should_close_session = TRUE;
+ goto out;
+ }
+
+ if (request->exported && response == 0)
+ {
+ if (!session_export (session, &error))
+ {
+ g_warning ("Failed to export session: %s", error->message);
+ response = 2;
+ should_close_session = TRUE;
+ goto out;
+ }
+
+ should_close_session = FALSE;
+ session_register (session);
+ }
+ else
+ {
+ should_close_session = TRUE;
+ }
+
+ GVariantDict *dict = g_variant_dict_new (opts);
+ g_variant_builder_add (&results_builder, "{sv}",
+ "shortcuts", g_variant_dict_lookup_value(dict, "shortcuts", 0));
+ g_variant_builder_add (&results_builder, "{sv}",
+ "session_handle", g_variant_new ("s", session->id));
+
+out:
+ if (request->exported)
+ {
+ xdp_dbus_request_emit_response (XDP_DBUS_REQUEST (request),
+ response,
+ g_variant_builder_end (&results_builder));
+ request_unexport (request);
+ }
+ else
+ {
+ g_variant_builder_clear (&results_builder);
+ }
+
+ if (should_close_session)
+ session_close (session, FALSE);
+}
+
+static gboolean
+handle_create_session (XdpDbusGlobalShortcuts *object,
+ GDBusMethodInvocation *invocation,
+ GVariant *arg_options)
+{
+ Request *request = request_from_invocation (invocation);
+ g_autoptr(GError) error = NULL;
+ g_autoptr(XdpDbusImplRequest) impl_request = NULL;
+ Session *session;
+
+ REQUEST_AUTOLOCK (request);
+
+ impl_request =
+ xdp_dbus_impl_request_proxy_new_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (impl)),
+ G_DBUS_PROXY_FLAGS_NONE,
+ g_dbus_proxy_get_name (G_DBUS_PROXY (impl)),
+ request->id,
+ NULL, &error);
+ if (!impl_request)
+ {
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ return G_DBUS_METHOD_INVOCATION_HANDLED;
+ }
+
+ request_set_impl_request (request, impl_request);
+ request_export (request, g_dbus_method_invocation_get_connection (invocation));
+
+ session = (Session *)global_shortcuts_session_new (arg_options, request, &error);
+ if (!session)
+ {
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ return G_DBUS_METHOD_INVOCATION_HANDLED;
+ }
+
+ g_object_set_qdata_full (G_OBJECT (request),
+ quark_request_session,
+ g_object_ref (session),
+ g_object_unref);
+
+ xdp_dbus_impl_global_shortcuts_call_create_session (impl,
+ request->id,
+ session->id,
+ xdp_app_info_get_id (request->app_info),
+ arg_options,
+ NULL,
+ create_session_done,
+ g_object_ref (request));
+
+ xdp_dbus_global_shortcuts_complete_create_session (object, invocation, request->id);
+
+ return G_DBUS_METHOD_INVOCATION_HANDLED;
+}
+
+void
+bind_shortcuts_done (GObject *source_object,
+ GAsyncResult *res,
+ gpointer data)
+{
+ g_autoptr(Request) request = data;
+ Session *session;
+ guint response = 2;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) results = NULL;
+
+ REQUEST_AUTOLOCK (request);
+
+ session = g_object_get_qdata (G_OBJECT (request), quark_request_session);
+ SESSION_AUTOLOCK_UNREF (g_object_ref (session));
+ g_object_set_qdata (G_OBJECT (request), quark_request_session, NULL);
+
+ if (!xdp_dbus_impl_global_shortcuts_call_bind_shortcuts_finish (impl, &results, res, &error))
+ {
+ g_dbus_error_strip_remote_error (error);
+ g_warning ("A backend call failed: %s", error->message);
+ }
+
+ if (request->exported)
+ {
+ if (!results)
+ {
+ GVariantBuilder results_builder;
+
+ g_variant_builder_init (&results_builder, G_VARIANT_TYPE_VARDICT);
+ results = g_variant_ref_sink (g_variant_builder_end (&results_builder));
+ }
+
+ xdp_dbus_request_emit_response (XDP_DBUS_REQUEST (request), response, results);
+ request_unexport (request);
+ }
+}
+
+static gboolean
+handle_bind_shortcuts (XdpDbusGlobalShortcuts *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_session_handle,
+ const gchar *const *arg_shortcuts,
+ const gchar *arg_parent_window,
+ GVariant *arg_options)
+{
+ Request *request = request_from_invocation (invocation);
+ Session *session;
+ g_autoptr(XdpDbusImplRequest) impl_request = NULL;
+ g_autoptr(GError) error = NULL;
+
+ REQUEST_AUTOLOCK (request);
+
+ session = acquire_session (arg_session_handle, request);
+ if (!session)
+ {
+ g_dbus_method_invocation_return_error (invocation,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_ACCESS_DENIED,
+ "Invalid session");
+ return G_DBUS_METHOD_INVOCATION_HANDLED;
+ }
+
+ SESSION_AUTOLOCK_UNREF (session);
+
+ impl_request =
+ xdp_dbus_impl_request_proxy_new_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (impl)),
+ G_DBUS_PROXY_FLAGS_NONE,
+ g_dbus_proxy_get_name (G_DBUS_PROXY (impl)),
+ request->id,
+ NULL, &error);
+ if (!impl_request)
+ {
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ return G_DBUS_METHOD_INVOCATION_HANDLED;
+ }
+
+ request_set_impl_request (request, impl_request);
+ request_export (request, g_dbus_method_invocation_get_connection (invocation));
+
+ g_object_set_qdata_full (G_OBJECT (request),
+ quark_request_session,
+ g_object_ref (session),
+ g_object_unref);
+
+ xdp_dbus_impl_global_shortcuts_call_bind_shortcuts (impl,
+ request->id,
+ arg_session_handle,
+ arg_shortcuts,
+ arg_parent_window,
+ arg_options,
+ NULL,
+ bind_shortcuts_done,
+ g_object_ref (request));
+
+ xdp_dbus_global_shortcuts_complete_bind_shortcuts (object, invocation, request->id);
+
+ return G_DBUS_METHOD_INVOCATION_HANDLED;
+}
+
+static void
+list_shortcuts_done (GObject *source_object,
+ GAsyncResult *res,
+ gpointer data)
+{
+ g_autoptr(Request) request = data;
+ Session *session;
+ guint response = 2;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GVariant) results = NULL;
+
+ REQUEST_AUTOLOCK (request);
+
+ session = g_object_get_qdata (G_OBJECT (request), quark_request_session);
+ SESSION_AUTOLOCK_UNREF (g_object_ref (session));
+ g_object_set_qdata (G_OBJECT (request), quark_request_session, NULL);
+
+ if (!xdp_dbus_impl_global_shortcuts_call_list_shortcuts_finish (impl, &results, res, &error))
+ {
+ g_dbus_error_strip_remote_error (error);
+ g_warning ("A backend call failed: %s", error->message);
+ }
+
+ if (request->exported)
+ {
+ if (!results)
+ {
+ GVariantBuilder results_builder;
+
+ g_variant_builder_init (&results_builder, G_VARIANT_TYPE_VARDICT);
+ results = g_variant_ref_sink (g_variant_builder_end (&results_builder));
+ }
+
+ xdp_dbus_request_emit_response (XDP_DBUS_REQUEST (request), response, results);
+ request_unexport (request);
+ }
+}
+
+static gboolean
+handle_list_shortcuts (XdpDbusGlobalShortcuts *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_session_handle)
+{
+ Request *request = request_from_invocation (invocation);
+ Session *session;
+ g_autoptr(XdpDbusImplRequest) impl_request = NULL;
+ g_autoptr(GError) error = NULL;
+
+ REQUEST_AUTOLOCK (request);
+
+ session = acquire_session (arg_session_handle, request);
+ if (!session)
+ {
+ g_dbus_method_invocation_return_error (invocation,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_ACCESS_DENIED,
+ "Invalid session");
+ return G_DBUS_METHOD_INVOCATION_HANDLED;
+ }
+
+ impl_request =
+ xdp_dbus_impl_request_proxy_new_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (impl)),
+ G_DBUS_PROXY_FLAGS_NONE,
+ g_dbus_proxy_get_name (G_DBUS_PROXY (impl)),
+ request->id,
+ NULL, &error);
+ if (!impl_request)
+ {
+ g_dbus_method_invocation_return_gerror (invocation, error);
+ return G_DBUS_METHOD_INVOCATION_HANDLED;
+ }
+
+ request_set_impl_request (request, impl_request);
+ request_export (request, g_dbus_method_invocation_get_connection (invocation));
+
+ g_object_set_qdata_full (G_OBJECT (request),
+ quark_request_session,
+ g_object_ref (session),
+ g_object_unref);
+
+ xdp_dbus_impl_global_shortcuts_call_list_shortcuts (impl,
+ request->id,
+ arg_session_handle,
+ NULL,
+ list_shortcuts_done,
+ g_object_ref (request));
+
+ xdp_dbus_global_shortcuts_complete_list_shortcuts (object, invocation, request->id);
+ return G_DBUS_METHOD_INVOCATION_HANDLED;
+}
+
+static void
+global_shortcuts_iface_init (XdpDbusGlobalShortcutsIface *iface)
+{
+ iface->handle_create_session = handle_create_session;
+ iface->handle_bind_shortcuts = handle_bind_shortcuts;
+ iface->handle_list_shortcuts = handle_list_shortcuts;
+}
+
+static void
+global_shortcuts_init (GlobalShortcuts *global_shortcuts)
+{
+ xdp_dbus_global_shortcuts_set_version (XDP_DBUS_GLOBAL_SHORTCUTS (global_shortcuts), 1);
+}
+
+static void
+global_shortcuts_class_init (GlobalShortcutsClass *klass)
+{
+ quark_request_session =
+ g_quark_from_static_string ("-xdp-request-global-shortcuts-session");
+}
+
+static void
+activated_cb (XdpDbusImplGlobalShortcuts *impl,
+ const char *session_id,
+ const char *shortcut_id,
+ guint64 timestamp,
+ GVariant *options,
+ gpointer data)
+{
+ g_autoptr(Session) session = lookup_session (session_id);
+ GlobalShortcutsSession *global_shortcuts_session = (GlobalShortcutsSession *)session;
+
+ g_debug ("Received activated %s for %s", session_id, shortcut_id);
+
+ if (global_shortcuts_session && !global_shortcuts_session->closed) {
+ xdp_dbus_global_shortcuts_emit_activated (data, session_id, shortcut_id, timestamp, options);
+ }
+}
+
+static void
+deactivated_cb (XdpDbusImplGlobalShortcuts *impl,
+ const char *session_id,
+ const char *shortcut_id,
+ guint64 timestamp,
+ GVariant *options,
+ gpointer data)
+{
+ g_autoptr(Session) session = lookup_session (session_id);
+ GlobalShortcutsSession *global_shortcuts_session = (GlobalShortcutsSession *)session;
+
+ g_debug ("Received deactivated %s for %s", session_id, shortcut_id);
+
+ if (global_shortcuts_session && !global_shortcuts_session->closed)
+ {
+ xdp_dbus_global_shortcuts_emit_deactivated (data, session_id, shortcut_id, timestamp, options);
+ }
+}
+
+static void
+shortcutschanged_cb (XdpDbusImplGlobalShortcuts *impl,
+ const char *session_id,
+ GVariant *shortcuts,
+ gpointer data)
+{
+ g_autoptr(Session) session = lookup_session (session_id);
+ GlobalShortcutsSession *global_shortcuts_session = (GlobalShortcutsSession *)session;
+
+ g_debug ("Received ShortcutsChanged %s", session_id);
+
+ if (global_shortcuts_session && !global_shortcuts_session->closed)
+ xdp_dbus_global_shortcuts_emit_shortcuts_changed (data, session_id, shortcuts);
+}
+
+GDBusInterfaceSkeleton *
+global_shortcuts_create (GDBusConnection *connection,
+ const char *dbus_name)
+{
+ g_autoptr(GError) error = NULL;
+
+ impl = xdp_dbus_impl_global_shortcuts_proxy_new_sync (connection,
+ G_DBUS_PROXY_FLAGS_NONE,
+ dbus_name,
+ "/org/freedesktop/portal/desktop",
+ NULL, &error);
+ if (impl == NULL)
+ {
+ g_warning ("Failed to create global_shortcuts proxy: %s", error->message);
+ return NULL;
+ }
+
+ g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (impl), G_MAXINT);
+ global_shortcuts = g_object_new (global_shortcuts_get_type (), NULL);
+
+ g_signal_connect (impl, "activated", G_CALLBACK (activated_cb), global_shortcuts);
+ g_signal_connect (impl, "deactivated", G_CALLBACK (deactivated_cb), global_shortcuts);
+ g_signal_connect (impl, "shortcuts-changed", G_CALLBACK (shortcutschanged_cb), global_shortcuts);
+
+ return G_DBUS_INTERFACE_SKELETON (global_shortcuts);
+}
diff --git a/src/globalshortcuts.h b/src/globalshortcuts.h
new file mode 100644
index 000000000..beab1a26e
--- /dev/null
+++ b/src/globalshortcuts.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright © 2022 Aleix Pol Gonzalez
+ *
+ * This program 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 .
+ *
+ * Authors:
+ * Aleix Pol Gonzalez
+ */
+
+#pragma once
+
+#include
+
+GDBusInterfaceSkeleton *
+global_shortcuts_create (GDBusConnection *connection,
+ const char *dbus_name);
diff --git a/src/meson.build b/src/meson.build
index 24227fe4f..08587a32a 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -49,6 +49,7 @@ xdg_desktop_portal_sources = files(
'flatpak-instance.c',
'gamemode.c',
'glib-backports.c',
+ 'globalshortcuts.c',
'inhibit.c',
'memory-monitor.c',
'network-monitor.c',
diff --git a/src/request.c b/src/request.c
index 5bd5016de..8a95d842d 100644
--- a/src/request.c
+++ b/src/request.c
@@ -343,6 +343,22 @@ get_token (GDBusMethodInvocation *invocation)
{
options = g_variant_get_child_value (parameters, 1);
}
+ else if (strcmp (interface, "org.freedesktop.portal.GlobalShortcuts") == 0)
+ {
+ if (strcmp (method, "CreateSession") == 0 )
+ {
+ options = g_variant_get_child_value (parameters, 0);
+ }
+ else if (strcmp (method, "BindShortcuts") == 0 )
+ {
+ options = g_variant_get_child_value (parameters, 3);
+ }
+ else
+ {
+ g_warning ("Support for %s::%s missing in %s",
+ interface, method, G_STRLOC);
+ }
+ }
else
{
g_print ("Support for %s missing in " G_STRLOC, interface);
diff --git a/src/xdg-desktop-portal.c b/src/xdg-desktop-portal.c
index a5a3baa86..7cf99344b 100644
--- a/src/xdg-desktop-portal.c
+++ b/src/xdg-desktop-portal.c
@@ -40,6 +40,7 @@
#include "email.h"
#include "file-chooser.h"
#include "gamemode.h"
+#include "globalshortcuts.h"
#include "inhibit.h"
#include "location.h"
#include "memory-monitor.h"
@@ -327,6 +328,11 @@ on_bus_acquired (GDBusConnection *connection,
export_portal_implementation (connection,
secret_create (connection, implementation->dbus_name));
+ implementation = find_portal_implementation ("org.freedesktop.impl.portal.GlobalShortcuts");
+ if (implementation != NULL)
+ export_portal_implementation (connection,
+ global_shortcuts_create (connection, implementation->dbus_name));
+
#ifdef HAVE_GLIB_2_66
implementation = find_portal_implementation ("org.freedesktop.impl.portal.DynamicLauncher");
if (implementation != NULL)