[gnome-panel] redo session handling
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-panel] redo session handling
- Date: Sat, 28 Dec 2019 20:12:39 +0000 (UTC)
commit d4e90ead871157de3cede5bb8dea463247e6f58e
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date: Sat Dec 28 22:07:29 2019 +0200
redo session handling
gnome-panel/Makefile.am | 6 +-
gnome-panel/gp-main.c | 236 +++++++++++++++++++++++++
gnome-panel/gp-session.c | 418 ++++++++++++++++++++++++++++++++++++++++++++
gnome-panel/gp-session.h | 35 ++++
gnome-panel/main.c | 137 ---------------
gnome-panel/panel-session.c | 332 -----------------------------------
gnome-panel/panel-session.h | 66 -------
po/POTFILES.in | 2 +-
8 files changed, 693 insertions(+), 539 deletions(-)
---
diff --git a/gnome-panel/Makefile.am b/gnome-panel/Makefile.am
index 5d4374961..583c0c998 100644
--- a/gnome-panel/Makefile.am
+++ b/gnome-panel/Makefile.am
@@ -16,16 +16,17 @@ panel_sources = \
gp-application.h \
gp-arrow-button.c \
gp-arrow-button.h \
+ gp-main.c \
gp-module-manager.c \
gp-module-manager.h \
gp-properties-dialog.c \
gp-properties-dialog.h \
+ gp-session.c \
+ gp-session.h \
gp-theme.c \
gp-theme.h \
- main.c \
panel-widget.c \
button-widget.c \
- panel-session.c \
panel.c \
applet.c \
panel-util.c \
@@ -54,7 +55,6 @@ panel_headers = \
panel-types.h \
panel-widget.h \
button-widget.h \
- panel-session.h \
panel.h \
applet.h \
panel-util.h \
diff --git a/gnome-panel/gp-main.c b/gnome-panel/gp-main.c
new file mode 100644
index 000000000..4febe4223
--- /dev/null
+++ b/gnome-panel/gp-main.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2019 Alberts Muktupāvels
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <glib-unix.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <gtk/gtkx.h>
+#include <stdlib.h>
+
+#include "gp-application.h"
+#include "gp-session.h"
+#include "libpanel-util/panel-cleanup.h"
+#include "panel-action-protocol.h"
+#include "panel-icon-names.h"
+#include "panel-layout.h"
+#include "panel-multiscreen.h"
+#include "panel-toplevel.h"
+
+typedef struct
+{
+ GMainLoop *loop;
+ GpApplication *application;
+ int exit_status;
+} GpMainData;
+
+static gboolean replace = FALSE;
+static gboolean version = FALSE;
+
+static GOptionEntry entries[] =
+{
+ {
+ "replace", 'r', G_OPTION_FLAG_NONE,
+ G_OPTION_ARG_NONE, &replace,
+ N_("Replace a currently running panel"),
+ NULL
+ },
+ {
+ "version", 'v', G_OPTION_FLAG_NONE,
+ G_OPTION_ARG_NONE, &version,
+ N_("Print version"),
+ NULL
+ },
+ {
+ NULL
+ }
+};
+
+static gboolean
+parse_arguments (int *argc,
+ char ***argv)
+{
+ GOptionContext *context;
+ GOptionGroup *gtk_group;
+ GError *error;
+
+ context = g_option_context_new (NULL);
+ gtk_group = gtk_get_option_group (FALSE);
+
+ g_option_context_add_main_entries (context, entries, NULL);
+ g_option_context_add_group (context, gtk_group);
+
+ error = NULL;
+ if (g_option_context_parse (context, argc, argv, &error) == FALSE)
+ {
+ g_warning ("Failed to parse command line arguments: %s", error->message);
+ g_error_free (error);
+
+ g_option_context_free (context);
+
+ return FALSE;
+ }
+
+ g_option_context_free (context);
+
+ return TRUE;
+}
+
+static void
+main_loop_quit (GpMainData *main_data)
+{
+ g_clear_object (&main_data->application);
+ g_main_loop_quit (main_data->loop);
+}
+
+static gboolean
+on_term_signal (gpointer user_data)
+{
+ main_loop_quit (user_data);
+
+ return G_SOURCE_REMOVE;
+}
+
+static gboolean
+on_int_signal (gpointer user_data)
+{
+ main_loop_quit (user_data);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+name_lost_cb (GpSession *session,
+ gboolean was_acquired,
+ GpMainData *main_data)
+{
+ main_loop_quit (main_data);
+
+ if (was_acquired)
+ return;
+
+ main_data->exit_status = EXIT_FAILURE;
+
+ g_warning ("Failed to acquire bus name!");
+}
+
+static void
+session_ready_cb (GpSession *session,
+ GpMainData *main_data)
+{
+ GdkDisplay *display;
+
+ g_unix_signal_add (SIGTERM, on_term_signal, main_data);
+ g_unix_signal_add (SIGINT, on_int_signal, main_data);
+
+ g_set_application_name (_("Panel"));
+ gtk_window_set_default_icon_name (PANEL_ICON_PANEL);
+
+ panel_action_protocol_init ();
+ panel_multiscreen_init ();
+
+ if (!panel_layout_load ())
+ {
+ main_loop_quit (main_data);
+
+ main_data->exit_status = EXIT_FAILURE;
+ return;
+ }
+
+ display = gdk_display_get_default ();
+ gdk_display_flush (display);
+
+ main_data->application = gp_application_new ();
+ gp_session_register (session);
+}
+
+static void
+end_session_cb (GpSession *session,
+ GpMainData *main_data)
+{
+ main_loop_quit (main_data);
+}
+
+int
+main (int argc, char *argv[])
+{
+ GdkDisplay *display;
+ const char *autostart_id;
+ GpMainData main_data;
+ GpSession *session;
+ GSList *toplevels_to_destroy;
+ GSList *l;
+
+ bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ gtk_init (&argc, &argv);
+
+ /* FIXME: High dpi scaling does not work... */
+ display = gdk_display_get_default ();
+ gdk_x11_display_set_window_scale (display, 1);
+
+ if (!parse_arguments (&argc, &argv))
+ return EXIT_FAILURE;
+
+ if (version)
+ {
+ g_print (PACKAGE_STRING "\n");
+
+ return EXIT_SUCCESS;
+ }
+
+ main_data.exit_status = EXIT_SUCCESS;
+ main_data.loop = g_main_loop_new (NULL, FALSE);
+ main_data.application = NULL;
+
+ autostart_id = g_getenv ("DESKTOP_AUTOSTART_ID");
+ session = gp_session_new (replace, autostart_id != NULL ? autostart_id : "");
+ g_unsetenv ("DESKTOP_AUTOSTART_ID");
+
+ g_signal_connect (session,
+ "name-lost",
+ G_CALLBACK (name_lost_cb),
+ &main_data);
+
+ g_signal_connect (session,
+ "session-ready",
+ G_CALLBACK (session_ready_cb),
+ &main_data);
+
+ g_signal_connect (session,
+ "end-session",
+ G_CALLBACK (end_session_cb),
+ &main_data);
+
+ g_main_loop_run (main_data.loop);
+
+ g_main_loop_unref (main_data.loop);
+ g_object_unref (session);
+
+ toplevels_to_destroy = g_slist_copy (panel_toplevel_list_toplevels ());
+ for (l = toplevels_to_destroy; l != NULL; l = l->next)
+ gtk_widget_destroy (l->data);
+
+ g_slist_free (toplevels_to_destroy);
+
+ panel_cleanup_do ();
+
+ return main_data.exit_status;
+}
diff --git a/gnome-panel/gp-session.c b/gnome-panel/gp-session.c
new file mode 100644
index 000000000..ad690bc06
--- /dev/null
+++ b/gnome-panel/gp-session.c
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2019 Alberts Muktupāvels
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include "gp-session.h"
+
+#include <gio/gio.h>
+
+struct _GpSession
+{
+ GObject parent;
+
+ gboolean replace;
+ char *startup_id;
+
+ guint name_id;
+ gboolean name_acquired;
+
+ GCancellable *cancellable;
+
+ GDBusProxy *session_manager;
+
+ char *client_id;
+ GDBusProxy *client_private;
+};
+
+enum
+{
+ PROP_0,
+
+ PROP_REPLACE,
+ PROP_STARTUP_ID,
+
+ LAST_PROP
+};
+
+static GParamSpec *session_properties[LAST_PROP] = { NULL };
+
+enum
+{
+ NAME_LOST,
+
+ SESSION_READY,
+ END_SESSION,
+
+ LAST_SIGNAL
+};
+
+static guint session_signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (GpSession, gp_session, G_TYPE_OBJECT)
+
+static void
+respond_to_end_session (GpSession *self)
+{
+ g_dbus_proxy_call (self->client_private,
+ "EndSessionResponse",
+ g_variant_new ("(bs)", TRUE, ""),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ self->cancellable,
+ NULL,
+ NULL);
+}
+
+static void
+g_signal_cb (GDBusProxy *proxy,
+ char *sender_name,
+ char *signal_name,
+ GVariant *parameters,
+ GpSession *self)
+{
+ if (g_strcmp0 (signal_name, "QueryEndSession") == 0)
+ respond_to_end_session (self);
+ else if (g_strcmp0 (signal_name, "EndSession") == 0)
+ respond_to_end_session (self);
+ else if (g_strcmp0 (signal_name, "Stop") == 0)
+ g_signal_emit (self, session_signals[END_SESSION], 0);
+}
+
+static void
+client_private_ready_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GError *error;
+ GDBusProxy *proxy;
+ GpSession *self;
+
+ error = NULL;
+ proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+
+ if (error != NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to get a client proxy: %s", error->message);
+
+ g_error_free (error);
+ return;
+ }
+
+ self = GP_SESSION (user_data);
+ self->client_private = proxy;
+
+ g_signal_connect (self->client_private,
+ "g-signal",
+ G_CALLBACK (g_signal_cb),
+ self);
+}
+
+static void
+register_client_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GError *error;
+ GVariant *variant;
+ GpSession *self;
+
+ error = NULL;
+ variant = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
+
+ if (error != NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to register client: %s", error->message);
+
+ g_error_free (error);
+ return;
+ }
+
+ self = GP_SESSION (user_data);
+
+ g_variant_get (variant, "(o)", &self->client_id);
+ g_variant_unref (variant);
+
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
+ NULL,
+ "org.gnome.SessionManager",
+ self->client_id,
+ "org.gnome.SessionManager.ClientPrivate",
+ self->cancellable,
+ client_private_ready_cb,
+ self);
+}
+
+static void
+session_manager_ready_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GError *error;
+ GDBusProxy *proxy;
+ GpSession *self;
+
+ error = NULL;
+ proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+
+ if (error != NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to get session manager proxy: %s", error->message);
+
+ g_error_free (error);
+ return;
+ }
+
+ self = GP_SESSION (user_data);
+ self->session_manager = proxy;
+
+ g_signal_emit (self, session_signals[SESSION_READY], 0);
+}
+
+static void
+name_acquired_cb (GDBusConnection *connection,
+ const char *name,
+ gpointer user_data)
+{
+ GpSession *self;
+ GDBusProxyFlags flags;
+
+ self = GP_SESSION (user_data);
+ self->name_acquired = TRUE;
+
+ flags = G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
+ G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS;
+
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+ flags,
+ NULL,
+ "org.gnome.SessionManager",
+ "/org/gnome/SessionManager",
+ "org.gnome.SessionManager",
+ self->cancellable,
+ session_manager_ready_cb,
+ self);
+}
+
+static void
+name_lost_cb (GDBusConnection *connection,
+ const char *name,
+ gpointer user_data)
+{
+ GpSession *self;
+
+ self = GP_SESSION (user_data);
+
+ g_signal_emit (self, session_signals[NAME_LOST], 0, self->name_acquired);
+}
+
+static void
+gp_session_constructed (GObject *object)
+{
+ GpSession *self;
+ GBusNameOwnerFlags flags;
+
+ self = GP_SESSION (object);
+
+ G_OBJECT_CLASS (gp_session_parent_class)->constructed (object);
+
+ flags = G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT;
+ if (self->replace)
+ flags |= G_BUS_NAME_OWNER_FLAGS_REPLACE;
+
+ self->name_id = g_bus_own_name (G_BUS_TYPE_SESSION,
+ "org.gnome.Panel",
+ flags,
+ NULL,
+ name_acquired_cb,
+ name_lost_cb,
+ self,
+ NULL);
+}
+
+static void
+gp_session_dispose (GObject *object)
+{
+ GpSession *self;
+
+ self = GP_SESSION (object);
+
+ if (self->name_id != 0)
+ {
+ g_bus_unown_name (self->name_id);
+ self->name_id = 0;
+ }
+
+ g_cancellable_cancel (self->cancellable);
+ g_clear_object (&self->cancellable);
+
+ g_clear_object (&self->session_manager);
+ g_clear_object (&self->client_private);
+
+ G_OBJECT_CLASS (gp_session_parent_class)->dispose (object);
+}
+
+static void
+gp_session_finalize (GObject *object)
+{
+ GpSession *self;
+
+ self = GP_SESSION (object);
+
+ g_clear_pointer (&self->startup_id, g_free);
+ g_clear_pointer (&self->client_id, g_free);
+
+ G_OBJECT_CLASS (gp_session_parent_class)->finalize (object);
+}
+
+static void
+gp_session_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GpSession *self;
+
+ self = GP_SESSION (object);
+
+ switch (property_id)
+ {
+ case PROP_REPLACE:
+ self->replace = g_value_get_boolean (value);
+ break;
+
+ case PROP_STARTUP_ID:
+ self->startup_id = g_value_dup_string (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+install_properties (GObjectClass *object_class)
+{
+ session_properties[PROP_REPLACE] =
+ g_param_spec_boolean ("replace",
+ "replace",
+ "replace",
+ FALSE,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_WRITABLE |
+ G_PARAM_STATIC_STRINGS);
+
+ session_properties[PROP_STARTUP_ID] =
+ g_param_spec_string ("startup-id",
+ "startup-id",
+ "startup-id",
+ "",
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_WRITABLE |
+ G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class,
+ LAST_PROP,
+ session_properties);
+}
+
+static void
+install_signals (void)
+{
+ session_signals[NAME_LOST] =
+ g_signal_new ("name-lost",
+ GP_TYPE_SESSION,
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_BOOLEAN);
+
+ session_signals[SESSION_READY] =
+ g_signal_new ("session-ready",
+ GP_TYPE_SESSION,
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ G_TYPE_NONE,
+ 0);
+
+ session_signals[END_SESSION] =
+ g_signal_new ("end-session",
+ GP_TYPE_SESSION,
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ G_TYPE_NONE,
+ 0);
+}
+
+static void
+gp_session_class_init (GpSessionClass *self_class)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (self_class);
+
+ object_class->constructed = gp_session_constructed;
+ object_class->dispose = gp_session_dispose;
+ object_class->finalize = gp_session_finalize;
+ object_class->set_property = gp_session_set_property;
+
+ install_properties (object_class);
+ install_signals ();
+}
+
+static void
+gp_session_init (GpSession *self)
+{
+ self->cancellable = g_cancellable_new ();
+}
+
+GpSession *
+gp_session_new (gboolean replace,
+ const char *startup_id)
+{
+ return g_object_new (GP_TYPE_SESSION,
+ "replace", replace,
+ "startup-id", startup_id,
+ NULL);
+}
+
+void
+gp_session_register (GpSession *self)
+{
+ g_dbus_proxy_call (self->session_manager,
+ "RegisterClient",
+ g_variant_new ("(ss)", "gnome-panel", self->startup_id),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ self->cancellable,
+ register_client_cb,
+ self);
+}
diff --git a/gnome-panel/gp-session.h b/gnome-panel/gp-session.h
new file mode 100644
index 000000000..f0b30f2fb
--- /dev/null
+++ b/gnome-panel/gp-session.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 Alberts Muktupāvels
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GP_SESSION_H
+#define GP_SESSION_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GP_TYPE_SESSION (gp_session_get_type ())
+G_DECLARE_FINAL_TYPE (GpSession, gp_session, GP, SESSION, GObject)
+
+GpSession *gp_session_new (gboolean replace,
+ const char *startup_id);
+
+void gp_session_register (GpSession *self);
+
+G_END_DECLS
+
+#endif
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 8e3cb33ea..4613b27ae 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -13,6 +13,7 @@ gnome-panel/button-widget.c
gnome-panel/gnome-panel.desktop.in
gnome-panel/gp-add-applet-window.c
gnome-panel/gp-arrow-button.c
+gnome-panel/gp-main.c
gnome-panel/gp-properties-dialog.c
gnome-panel/gp-properties-dialog.ui
gnome-panel/launcher.c
@@ -21,7 +22,6 @@ gnome-panel/libpanel-util/panel-error.c
gnome-panel/libpanel-util/panel-icon-chooser.c
gnome-panel/libpanel-util/panel-launch.c
gnome-panel/libpanel-util/panel-show.c
-gnome-panel/main.c
gnome-panel/panel-action-button.c
gnome-panel/panel-addto-dialog.c
gnome-panel/panel-addto-dialog.ui
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]