[gnome-panel] redo session handling



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]