[mutter/wip/carlosg/startup-sequences: 7/16] x11: Refactor the X11 startup notification bits into src/x11



commit 26fbd56a95b1ff98a80c44550bb4e3a3ef0407ec
Author: Carlos Garnacho <carlosg gnome org>
Date:   Wed Aug 22 20:57:04 2018 +0200

    x11: Refactor the X11 startup notification bits into src/x11
    
    Only one little bit left in MetaDisplay, because SnStartupSequence
    is exposed in API there. These bits will be removed in future
    commits.

 src/Makefile.am                         |   2 +
 src/core/display.c                      |  29 ++-
 src/core/startup-notification-private.h |  20 ++
 src/core/startup-notification.c         | 369 +++-----------------------------
 src/meson.build                         |   2 +
 src/wayland/meta-wayland-gtk-shell.c    |  11 +-
 src/x11/events.c                        |   4 +-
 src/x11/meta-startup-notification-x11.c | 290 +++++++++++++++++++++++++
 src/x11/meta-startup-notification-x11.h |  39 ++++
 src/x11/meta-x11-display-private.h      |   3 +
 src/x11/meta-x11-display.c              |   4 +
 11 files changed, 422 insertions(+), 351 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 1afc1204d..5e08c1d61 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -343,6 +343,8 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES =      \
        meta/meta-x11-display.h                 \
        x11/meta-x11-errors.c                   \
        meta/meta-x11-errors.h                  \
+       x11/meta-startup-notification-x11.c     \
+       x11/meta-startup-notification-x11.h     \
        x11/events.c                            \
        x11/events.h                            \
        x11/group-private.h                     \
diff --git a/src/core/display.c b/src/core/display.c
index 5840b1e2e..72f562edc 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -68,6 +68,7 @@
 #include "meta/meta-enum-types.h"
 #include "meta/meta-x11-errors.h"
 #include "meta/prefs.h"
+#include "x11/meta-startup-notification-x11.h"
 #include "x11/meta-x11-display-private.h"
 #include "x11/window-x11.h"
 #include "x11/xprops.h"
@@ -632,10 +633,34 @@ on_startup_notification_changed (MetaStartupNotification *sn,
                                  gpointer                 sequence,
                                  MetaDisplay             *display)
 {
+  GSList *sequences, *l;
+  SnStartupSequence *seq;
+
   g_slist_free (display->startup_sequences);
-  display->startup_sequences =
+  display->startup_sequences = NULL;
+
+  sequences =
     meta_startup_notification_get_sequences (display->startup_notification);
-  g_signal_emit_by_name (display, "startup-sequence-changed", sequence);
+
+  for (l = sequences; l; l = l->next)
+    {
+      if (!META_IS_STARTUP_SEQUENCE_X11 (l->data))
+        continue;
+
+      g_object_get (G_OBJECT (l->data),
+                    "seq", &seq,
+                    NULL);
+      display->startup_sequences = g_slist_prepend (display->startup_sequences,
+                                                    seq);
+    }
+
+  if (META_IS_STARTUP_SEQUENCE_X11 (sequence))
+    {
+      g_object_get (G_OBJECT (sequence),
+                    "seq", &seq,
+                    NULL);
+      g_signal_emit_by_name (display, "startup-sequence-changed", seq);
+    }
 }
 
 static void
diff --git a/src/core/startup-notification-private.h b/src/core/startup-notification-private.h
index d2e46cba8..d606aa028 100644
--- a/src/core/startup-notification-private.h
+++ b/src/core/startup-notification-private.h
@@ -28,11 +28,26 @@
 #include "core/display-private.h"
 
 #define META_TYPE_STARTUP_NOTIFICATION (meta_startup_notification_get_type ())
+#define META_TYPE_STARTUP_SEQUENCE (meta_startup_sequence_get_type ())
+
+typedef struct _MetaStartupSequence MetaStartupSequence;
+typedef struct _MetaStartupSequenceClass MetaStartupSequenceClass;
+
+struct _MetaStartupSequenceClass
+{
+  GObjectClass parent_class;
+
+  void (* complete) (MetaStartupSequence *sequence);
+};
 
 G_DECLARE_FINAL_TYPE (MetaStartupNotification,
                       meta_startup_notification,
                       META, STARTUP_NOTIFICATION,
                       GObject)
+G_DECLARE_DERIVABLE_TYPE (MetaStartupSequence,
+                          meta_startup_sequence,
+                          META, STARTUP_SEQUENCE,
+                          GObject)
 
 MetaStartupNotification *
          meta_startup_notification_get             (MetaDisplay             *display);
@@ -40,7 +55,12 @@ MetaStartupNotification *
 gboolean meta_startup_notification_handle_xevent   (MetaStartupNotification *sn,
                                                     XEvent                  *xevent);
 
+void     meta_startup_notification_add_sequence    (MetaStartupNotification *sn,
+                                                    MetaStartupSequence     *seq);
 void     meta_startup_notification_remove_sequence (MetaStartupNotification *sn,
+                                                    MetaStartupSequence     *seq);
+MetaStartupSequence *
+         meta_startup_notification_lookup_sequence (MetaStartupNotification *sn,
                                                     const gchar             *id);
 
 GSList * meta_startup_notification_get_sequences   (MetaStartupNotification *sn);
diff --git a/src/core/startup-notification.c b/src/core/startup-notification.c
index 861bff389..24c389cdd 100644
--- a/src/core/startup-notification.c
+++ b/src/core/startup-notification.c
@@ -28,6 +28,7 @@
 
 #include "core/display-private.h"
 #include "core/startup-notification-private.h"
+#include "core/util-private.h"
 #include "meta/meta-x11-errors.h"
 #include "x11/meta-x11-display-private.h"
 
@@ -38,13 +39,10 @@
  */
 #define STARTUP_TIMEOUT 15000000
 
-typedef struct _MetaStartupSequence MetaStartupSequence;
-typedef struct _MetaStartupSequenceClass MetaStartupSequenceClass;
-
 enum {
-  PROP_SN_0,
-  PROP_SN_DISPLAY,
-  N_SN_PROPS
+  PROP_0,
+  PROP_DISPLAY,
+  N_PROPS
 };
 
 enum {
@@ -55,12 +53,12 @@ enum {
 };
 
 enum {
-  SN_CHANGED,
-  N_SN_SIGNALS
+  CHANGED,
+  N_SIGNALS
 };
 
-static guint sn_signals[N_SN_SIGNALS];
-static GParamSpec *sn_props[N_SN_PROPS];
+static guint sn_signals[N_SIGNALS];
+static GParamSpec *sn_props[N_PROPS];
 static GParamSpec *seq_props[N_SEQ_PROPS];
 
 typedef struct
@@ -74,34 +72,16 @@ struct _MetaStartupNotification
   GObject parent_instance;
   MetaDisplay *display;
 
-#ifdef HAVE_STARTUP_NOTIFICATION
-  SnDisplay *sn_display;
-  SnMonitorContext *sn_context;
-#endif
 
   GSList *startup_sequences;
   guint startup_sequence_timeout;
 };
 
-#define META_TYPE_STARTUP_SEQUENCE \
-  (meta_startup_sequence_get_type ())
-
-G_DECLARE_DERIVABLE_TYPE (MetaStartupSequence,
-                          meta_startup_sequence,
-                          META, STARTUP_SEQUENCE,
-                          GObject)
-
 typedef struct {
   gchar *id;
   gint64 timestamp;
 } MetaStartupSequencePrivate;
 
-struct _MetaStartupSequenceClass {
-  GObjectClass parent_class;
-
-  void (* complete) (MetaStartupSequence *sequence);
-};
-
 G_DEFINE_TYPE (MetaStartupNotification,
                meta_startup_notification,
                G_TYPE_OBJECT)
@@ -109,37 +89,9 @@ G_DEFINE_TYPE_WITH_PRIVATE (MetaStartupSequence,
                             meta_startup_sequence,
                             G_TYPE_OBJECT)
 
-#ifdef HAVE_STARTUP_NOTIFICATION
-
-enum {
-  PROP_SEQ_X11_0,
-  PROP_SEQ_X11_SEQ,
-  N_SEQ_X11_PROPS
-};
-
-struct _MetaStartupSequenceX11 {
-  MetaStartupSequence parent_instance;
-  SnStartupSequence *seq;
-};
-
-static GParamSpec *seq_x11_props[N_SEQ_X11_PROPS];
-
-#define META_TYPE_STARTUP_SEQUENCE_X11 \
-  (meta_startup_sequence_x11_get_type ())
-
-G_DECLARE_FINAL_TYPE (MetaStartupSequenceX11,
-                      meta_startup_sequence_x11,
-                      META, STARTUP_SEQUENCE_X11,
-                      MetaStartupSequence)
-
-G_DEFINE_TYPE (MetaStartupSequenceX11,
-               meta_startup_sequence_x11,
-               META_TYPE_STARTUP_SEQUENCE)
 
 static void meta_startup_notification_ensure_timeout  (MetaStartupNotification *sn);
 
-#endif
-
 static void
 meta_startup_notification_update_feedback (MetaStartupNotification *sn)
 {
@@ -266,7 +218,6 @@ meta_startup_sequence_get_id (MetaStartupSequence *seq)
   return priv->id;
 }
 
-#ifdef HAVE_STARTUP_NOTIFICATION
 static gint64
 meta_startup_sequence_get_timestamp (MetaStartupSequence *seq)
 {
@@ -286,124 +237,18 @@ meta_startup_sequence_complete (MetaStartupSequence *seq)
   if (klass->complete)
     klass->complete (seq);
 }
-#endif
-
-#ifdef HAVE_STARTUP_NOTIFICATION
-static void
-meta_startup_sequence_x11_complete (MetaStartupSequence *seq)
-{
-  MetaStartupSequenceX11 *seq_x11;
-
-  seq_x11 = META_STARTUP_SEQUENCE_X11 (seq);
-  sn_startup_sequence_complete (seq_x11->seq);
-}
-
-static void
-meta_startup_sequence_x11_finalize (GObject *object)
-{
-  MetaStartupSequenceX11 *seq;
-
-  seq = META_STARTUP_SEQUENCE_X11 (object);
-  sn_startup_sequence_unref (seq->seq);
-
-  G_OBJECT_CLASS (meta_startup_sequence_x11_parent_class)->finalize (object);
-}
 
-static void
-meta_startup_sequence_x11_set_property (GObject      *object,
-                                        guint         prop_id,
-                                        const GValue *value,
-                                        GParamSpec   *pspec)
-{
-  MetaStartupSequenceX11 *seq;
-
-  seq = META_STARTUP_SEQUENCE_X11 (object);
-
-  switch (prop_id)
-    {
-    case PROP_SEQ_X11_SEQ:
-      seq->seq = g_value_get_pointer (value);
-      sn_startup_sequence_ref (seq->seq);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-static void
-meta_startup_sequence_x11_get_property (GObject    *object,
-                                        guint       prop_id,
-                                        GValue     *value,
-                                        GParamSpec *pspec)
-{
-  MetaStartupSequenceX11 *seq;
-
-  seq = META_STARTUP_SEQUENCE_X11 (object);
-
-  switch (prop_id)
-    {
-    case PROP_SEQ_X11_SEQ:
-      g_value_set_pointer (value, seq->seq);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-static void
-meta_startup_sequence_x11_init (MetaStartupSequenceX11 *seq)
-{
-}
-
-static void
-meta_startup_sequence_x11_class_init (MetaStartupSequenceX11Class *klass)
-{
-  MetaStartupSequenceClass *seq_class;
-  GObjectClass *object_class;
-
-  seq_class = META_STARTUP_SEQUENCE_CLASS (klass);
-  seq_class->complete = meta_startup_sequence_x11_complete;
-
-  object_class = G_OBJECT_CLASS (klass);
-  object_class->finalize = meta_startup_sequence_x11_finalize;
-  object_class->set_property = meta_startup_sequence_x11_set_property;
-  object_class->get_property = meta_startup_sequence_x11_get_property;
-
-  seq_x11_props[PROP_SEQ_X11_SEQ] =
-    g_param_spec_pointer ("seq",
-                          "Sequence",
-                          "Sequence",
-                          G_PARAM_READWRITE |
-                          G_PARAM_CONSTRUCT_ONLY);
-
-  g_object_class_install_properties (object_class, N_SEQ_X11_PROPS,
-                                     seq_x11_props);
-}
-
-static MetaStartupSequence *
-meta_startup_sequence_x11_new (SnStartupSequence *seq)
-{
-  gint64 timestamp;
-
-  timestamp = sn_startup_sequence_get_timestamp (seq) * 1000;
-  return g_object_new (META_TYPE_STARTUP_SEQUENCE_X11,
-                       "id", sn_startup_sequence_get_id (seq),
-                       "timestamp", timestamp,
-                       "seq", seq,
-                       NULL);
-}
-
-static void
-meta_startup_notification_add_sequence_internal (MetaStartupNotification *sn,
-                                                 MetaStartupSequence     *seq)
+void
+meta_startup_notification_add_sequence (MetaStartupNotification *sn,
+                                        MetaStartupSequence     *seq)
 {
   sn->startup_sequences = g_slist_prepend (sn->startup_sequences,
                                            g_object_ref (seq));
 
   meta_startup_notification_ensure_timeout (sn);
   meta_startup_notification_update_feedback (sn);
+
+  g_signal_emit (sn, sn_signals[CHANGED], 0, seq);
 }
 
 static void
@@ -479,11 +324,10 @@ meta_startup_notification_ensure_timeout (MetaStartupNotification *sn)
   g_source_set_name_by_id (sn->startup_sequence_timeout,
                            "[mutter] startup_sequence_timeout");
 }
-#endif
 
-static void
-meta_startup_notification_remove_sequence_internal (MetaStartupNotification *sn,
-                                                    MetaStartupSequence     *seq)
+void
+meta_startup_notification_remove_sequence (MetaStartupNotification *sn,
+                                           MetaStartupSequence     *seq)
 {
   sn->startup_sequences = g_slist_remove (sn->startup_sequences, seq);
   meta_startup_notification_update_feedback (sn);
@@ -495,10 +339,11 @@ meta_startup_notification_remove_sequence_internal (MetaStartupNotification *sn,
       sn->startup_sequence_timeout = 0;
     }
 
+  g_signal_emit (sn, sn_signals[CHANGED], 0, seq);
   g_object_unref (seq);
 }
 
-static MetaStartupSequence *
+MetaStartupSequence *
 meta_startup_notification_lookup_sequence (MetaStartupNotification *sn,
                                            const gchar             *id)
 {
@@ -548,7 +393,7 @@ meta_startup_notification_set_property (GObject      *object,
 
   switch (prop_id)
     {
-    case PROP_SN_DISPLAY:
+    case PROP_DISPLAY:
       sn->display = g_value_get_object (value);
       break;
     default:
@@ -567,7 +412,7 @@ meta_startup_notification_get_property (GObject    *object,
 
   switch (prop_id)
     {
-    case PROP_SN_DISPLAY:
+    case PROP_DISPLAY:
       g_value_set_object (value, sn->display);
       break;
     default:
@@ -576,114 +421,6 @@ meta_startup_notification_get_property (GObject    *object,
     }
 }
 
-#ifdef HAVE_STARTUP_NOTIFICATION
-static void
-sn_error_trap_push (SnDisplay *sn_display,
-                    Display   *xdisplay)
-{
-  MetaDisplay *display;
-  display = meta_display_for_x_display (xdisplay);
-  if (display != NULL)
-    meta_x11_error_trap_push (display->x11_display);
-}
-
-static void
-sn_error_trap_pop (SnDisplay *sn_display,
-                   Display   *xdisplay)
-{
-  MetaDisplay *display;
-  display = meta_display_for_x_display (xdisplay);
-  if (display != NULL)
-    meta_x11_error_trap_pop (display->x11_display);
-}
-
-static void
-meta_startup_notification_sn_event (SnMonitorEvent *event,
-                                    void           *user_data)
-{
-  MetaStartupNotification *sn = user_data;
-  MetaStartupSequence *seq;
-  SnStartupSequence *sequence;
-
-  sequence = sn_monitor_event_get_startup_sequence (event);
-
-  sn_startup_sequence_ref (sequence);
-
-  switch (sn_monitor_event_get_type (event))
-    {
-    case SN_MONITOR_EVENT_INITIATED:
-      {
-        const char *wmclass;
-
-        wmclass = sn_startup_sequence_get_wmclass (sequence);
-
-        meta_topic (META_DEBUG_STARTUP,
-                    "Received startup initiated for %s wmclass %s\n",
-                    sn_startup_sequence_get_id (sequence),
-                    wmclass ? wmclass : "(unset)");
-
-        seq = meta_startup_sequence_x11_new (sequence);
-        meta_startup_notification_add_sequence_internal (sn, seq);
-        g_object_unref (seq);
-      }
-      break;
-
-    case SN_MONITOR_EVENT_COMPLETED:
-      {
-        meta_topic (META_DEBUG_STARTUP,
-                    "Received startup completed for %s\n",
-                    sn_startup_sequence_get_id (sequence));
-
-        meta_startup_notification_remove_sequence (sn, sn_startup_sequence_get_id (sequence));
-      }
-      break;
-
-    case SN_MONITOR_EVENT_CHANGED:
-      meta_topic (META_DEBUG_STARTUP,
-                  "Received startup changed for %s\n",
-                  sn_startup_sequence_get_id (sequence));
-      break;
-
-    case SN_MONITOR_EVENT_CANCELED:
-      meta_topic (META_DEBUG_STARTUP,
-                  "Received startup canceled for %s\n",
-                  sn_startup_sequence_get_id (sequence));
-      break;
-    }
-
-  g_signal_emit (sn, sn_signals[SN_CHANGED], 0, sequence);
-
-  sn_startup_sequence_unref (sequence);
-}
-
-static void
-on_x11_display_opened (MetaStartupNotification *sn)
-{
-  MetaX11Display *x11_display = sn->display->x11_display;
-
-  sn->sn_display = sn_display_new (x11_display->xdisplay,
-                                   sn_error_trap_push,
-                                   sn_error_trap_pop);
-
-  sn->sn_context =
-    sn_monitor_context_new (sn->sn_display,
-                            meta_x11_display_get_screen_number (x11_display),
-                            meta_startup_notification_sn_event,
-                            sn,
-                            NULL);
-}
-
-static void
-on_x11_display_closing (MetaStartupNotification *sn)
-{
-  sn_monitor_context_unref (sn->sn_context);
-  sn->sn_context = NULL;
-
-  sn_display_unref (sn->sn_display);
-  sn->sn_display = NULL;
-}
-#endif
-
 static void
 meta_startup_notification_constructed (GObject *object)
 {
@@ -691,23 +428,6 @@ meta_startup_notification_constructed (GObject *object)
 
   g_assert (sn->display != NULL);
 
-#ifdef HAVE_STARTUP_NOTIFICATION
-  sn->sn_display = NULL;
-  sn->sn_context = NULL;
-
-  g_signal_connect_object (sn->display,
-                          "x11-display-opened",
-                           G_CALLBACK (on_x11_display_opened),
-                           sn,
-                           G_CONNECT_SWAPPED);
-
-  g_signal_connect_object (sn->display,
-                           "x11-display-closing",
-                           G_CALLBACK (on_x11_display_closing),
-                           sn,
-                           G_CONNECT_SWAPPED);
-#endif
-
   sn->startup_sequences = NULL;
   sn->startup_sequence_timeout = 0;
 }
@@ -722,7 +442,7 @@ meta_startup_notification_class_init (MetaStartupNotificationClass *klass)
   object_class->set_property = meta_startup_notification_set_property;
   object_class->get_property = meta_startup_notification_get_property;
 
-  sn_props[PROP_SN_DISPLAY] =
+  sn_props[PROP_DISPLAY] =
     g_param_spec_object ("display",
                          "Display",
                          "Display",
@@ -730,14 +450,14 @@ meta_startup_notification_class_init (MetaStartupNotificationClass *klass)
                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
                          G_PARAM_STATIC_STRINGS);
 
-  sn_signals[SN_CHANGED] =
+  sn_signals[CHANGED] =
     g_signal_new ("changed",
                   META_TYPE_STARTUP_NOTIFICATION,
                   G_SIGNAL_RUN_LAST,
                   0, NULL, NULL, NULL,
                   G_TYPE_NONE, 1, G_TYPE_POINTER);
 
-  g_object_class_install_properties (object_class, N_SN_PROPS, sn_props);
+  g_object_class_install_properties (object_class, N_PROPS, sn_props);
 }
 
 MetaStartupNotification *
@@ -753,49 +473,8 @@ meta_startup_notification_get (MetaDisplay *display)
   return notification;
 }
 
-void
-meta_startup_notification_remove_sequence (MetaStartupNotification *sn,
-                                           const gchar             *id)
-{
-  MetaStartupSequence *seq;
-
-  seq = meta_startup_notification_lookup_sequence (sn, id);
-  if (seq)
-    meta_startup_notification_remove_sequence_internal (sn, seq);
-}
-
-gboolean
-meta_startup_notification_handle_xevent (MetaStartupNotification *sn,
-                                         XEvent                  *xevent)
-{
-#ifdef HAVE_STARTUP_NOTIFICATION
-  return sn_display_process_event (sn->sn_display, xevent);
-#endif
-  return FALSE;
-}
-
 GSList *
 meta_startup_notification_get_sequences (MetaStartupNotification *sn)
 {
-  GSList *sequences = NULL;
-#ifdef HAVE_STARTUP_NOTIFICATION
-  GSList *l;
-
-  if (!sn->sn_display)
-    return sequences;
-
-  /* We return a list of SnStartupSequences here */
-  for (l = sn->startup_sequences; l; l = l->next)
-    {
-      MetaStartupSequenceX11 *seq_x11;
-
-      if (!META_IS_STARTUP_SEQUENCE_X11 (l->data))
-        continue;
-
-      seq_x11 = META_STARTUP_SEQUENCE_X11 (l->data);
-      sequences = g_slist_prepend (sequences, seq_x11->seq);
-    }
-#endif
-
-  return sequences;
+  return sn->startup_sequences;
 }
diff --git a/src/meson.build b/src/meson.build
index 11669e974..fcad37870 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -362,6 +362,8 @@ mutter_sources = [
   'x11/group-props.h',
   'x11/iconcache.c',
   'x11/iconcache.h',
+  'x11/meta-startup-notification-x11.c',
+  'x11/meta-startup-notification-x11.h',
   'x11/meta-x11-display.c',
   'x11/meta-x11-display-private.h',
   'x11/meta-x11-errors.c',
diff --git a/src/wayland/meta-wayland-gtk-shell.c b/src/wayland/meta-wayland-gtk-shell.c
index f53818265..772198a7b 100644
--- a/src/wayland/meta-wayland-gtk-shell.c
+++ b/src/wayland/meta-wayland-gtk-shell.c
@@ -311,11 +311,18 @@ gtk_shell_set_startup_id (struct wl_client   *client,
                           struct wl_resource *resource,
                           const char         *startup_id)
 {
+  MetaStartupSequence *sequence;
   MetaDisplay *display;
 
   display = meta_get_display ();
-  meta_startup_notification_remove_sequence (display->startup_notification,
-                                             startup_id);
+
+  sequence = meta_startup_notification_lookup_sequence (display->startup_notification,
+                                                        startup_id);
+  if (sequence)
+    {
+      meta_startup_notification_remove_sequence (display->startup_notification,
+                                                 sequence);
+    }
 }
 
 static void
diff --git a/src/x11/events.c b/src/x11/events.c
index 517cf6ec5..e363fdbb6 100644
--- a/src/x11/events.c
+++ b/src/x11/events.c
@@ -39,6 +39,7 @@
 #include "meta/meta-backend.h"
 #include "meta/meta-x11-errors.h"
 #include "x11/meta-x11-display-private.h"
+#include "x11/meta-startup-notification-x11.h"
 #include "x11/window-x11.h"
 #include "x11/xprops.h"
 
@@ -1744,8 +1745,7 @@ meta_x11_display_handle_xevent (MetaX11Display *x11_display,
   meta_spew_event_print (x11_display, event);
 #endif
 
-  if (meta_startup_notification_handle_xevent (display->startup_notification,
-                                               event))
+  if (meta_x11_startup_notification_handle_xevent (x11_display, event))
     {
       bypass_gtk = bypass_compositor = TRUE;
       goto out;
diff --git a/src/x11/meta-startup-notification-x11.c b/src/x11/meta-startup-notification-x11.c
new file mode 100644
index 000000000..6162eb2f7
--- /dev/null
+++ b/src/x11/meta-startup-notification-x11.c
@@ -0,0 +1,290 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2018 Red Hat, Inc
+ *
+ * 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 "meta-startup-notification-x11.h"
+
+#include "core/display-private.h"
+#include "core/startup-notification-private.h"
+#include "meta/meta-x11-errors.h"
+#include "x11/meta-x11-display-private.h"
+
+#ifdef HAVE_STARTUP_NOTIFICATION
+
+enum {
+  PROP_SEQ_X11_0,
+  PROP_SEQ_X11_SEQ,
+  N_SEQ_X11_PROPS
+};
+
+struct _MetaStartupSequenceX11
+{
+  MetaStartupSequence parent_instance;
+  SnStartupSequence *seq;
+};
+
+struct _MetaX11StartupNotification
+{
+  SnDisplay *sn_display;
+  SnMonitorContext *sn_context;
+};
+
+static GParamSpec *seq_x11_props[N_SEQ_X11_PROPS];
+
+G_DEFINE_TYPE (MetaStartupSequenceX11,
+               meta_startup_sequence_x11,
+               META_TYPE_STARTUP_SEQUENCE)
+
+static void
+meta_startup_sequence_x11_complete (MetaStartupSequence *seq)
+{
+  MetaStartupSequenceX11 *seq_x11;
+
+  seq_x11 = META_STARTUP_SEQUENCE_X11 (seq);
+  sn_startup_sequence_complete (seq_x11->seq);
+}
+
+static void
+meta_startup_sequence_x11_finalize (GObject *object)
+{
+  MetaStartupSequenceX11 *seq_x11;
+
+  seq_x11 = META_STARTUP_SEQUENCE_X11 (object);
+  sn_startup_sequence_unref (seq_x11->seq);
+
+  G_OBJECT_CLASS (meta_startup_sequence_x11_parent_class)->finalize (object);
+}
+
+static void
+meta_startup_sequence_x11_set_property (GObject      *object,
+                                        guint         prop_id,
+                                        const GValue *value,
+                                        GParamSpec   *pspec)
+{
+  MetaStartupSequenceX11 *seq_x11;
+
+  seq_x11 = META_STARTUP_SEQUENCE_X11 (object);
+
+  switch (prop_id)
+    {
+    case PROP_SEQ_X11_SEQ:
+      seq_x11->seq = g_value_get_pointer (value);
+      sn_startup_sequence_ref (seq_x11->seq);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+meta_startup_sequence_x11_get_property (GObject    *object,
+                                        guint       prop_id,
+                                        GValue     *value,
+                                        GParamSpec *pspec)
+{
+  MetaStartupSequenceX11 *seq_x11;
+
+  seq_x11 = META_STARTUP_SEQUENCE_X11 (object);
+
+  switch (prop_id)
+    {
+    case PROP_SEQ_X11_SEQ:
+      g_value_set_pointer (value, seq_x11->seq);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+meta_startup_sequence_x11_init (MetaStartupSequenceX11 *seq)
+{
+}
+
+static void
+meta_startup_sequence_x11_class_init (MetaStartupSequenceX11Class *klass)
+{
+  MetaStartupSequenceClass *seq_class;
+  GObjectClass *object_class;
+
+  seq_class = META_STARTUP_SEQUENCE_CLASS (klass);
+  seq_class->complete = meta_startup_sequence_x11_complete;
+
+  object_class = G_OBJECT_CLASS (klass);
+  object_class->finalize = meta_startup_sequence_x11_finalize;
+  object_class->set_property = meta_startup_sequence_x11_set_property;
+  object_class->get_property = meta_startup_sequence_x11_get_property;
+
+  seq_x11_props[PROP_SEQ_X11_SEQ] =
+    g_param_spec_pointer ("seq",
+                          "Sequence",
+                          "Sequence",
+                          G_PARAM_READWRITE |
+                          G_PARAM_CONSTRUCT_ONLY);
+
+  g_object_class_install_properties (object_class, N_SEQ_X11_PROPS,
+                                     seq_x11_props);
+}
+
+static MetaStartupSequence *
+meta_startup_sequence_x11_new (SnStartupSequence *seq)
+{
+  gint64 timestamp;
+
+  timestamp = sn_startup_sequence_get_timestamp (seq) * 1000;
+  return g_object_new (META_TYPE_STARTUP_SEQUENCE_X11,
+                       "id", sn_startup_sequence_get_id (seq),
+                       "timestamp", timestamp,
+                       "seq", seq,
+                       NULL);
+}
+
+static void
+sn_error_trap_push (SnDisplay *sn_display,
+                    Display   *xdisplay)
+{
+  MetaDisplay *display;
+
+  display = meta_display_for_x_display (xdisplay);
+  if (display != NULL)
+    meta_x11_error_trap_push (display->x11_display);
+}
+
+static void
+sn_error_trap_pop (SnDisplay *sn_display,
+                   Display   *xdisplay)
+{
+  MetaDisplay *display;
+
+  display = meta_display_for_x_display (xdisplay);
+  if (display != NULL)
+    meta_x11_error_trap_pop (display->x11_display);
+}
+
+static void
+meta_startup_notification_sn_event (SnMonitorEvent *event,
+                                    void           *user_data)
+{
+  MetaX11Display *x11_display = user_data;
+  MetaStartupNotification *sn = x11_display->display->startup_notification;
+  MetaStartupSequence *seq;
+  SnStartupSequence *sequence;
+
+  sequence = sn_monitor_event_get_startup_sequence (event);
+
+  sn_startup_sequence_ref (sequence);
+
+  switch (sn_monitor_event_get_type (event))
+    {
+    case SN_MONITOR_EVENT_INITIATED:
+      {
+        const char *wmclass;
+
+        wmclass = sn_startup_sequence_get_wmclass (sequence);
+
+        meta_topic (META_DEBUG_STARTUP,
+                    "Received startup initiated for %s wmclass %s\n",
+                    sn_startup_sequence_get_id (sequence),
+                    wmclass ? wmclass : "(unset)");
+
+        seq = meta_startup_sequence_x11_new (sequence);
+        meta_startup_notification_add_sequence (sn, seq);
+        g_object_unref (seq);
+      }
+      break;
+
+    case SN_MONITOR_EVENT_COMPLETED:
+      {
+        meta_topic (META_DEBUG_STARTUP,
+                    "Received startup completed for %s\n",
+                    sn_startup_sequence_get_id (sequence));
+
+        seq = meta_startup_notification_lookup_sequence (sn, sn_startup_sequence_get_id (sequence));
+        if (seq)
+          meta_startup_notification_remove_sequence (sn, seq);
+      }
+      break;
+
+    case SN_MONITOR_EVENT_CHANGED:
+      meta_topic (META_DEBUG_STARTUP,
+                  "Received startup changed for %s\n",
+                  sn_startup_sequence_get_id (sequence));
+      break;
+
+    case SN_MONITOR_EVENT_CANCELED:
+      meta_topic (META_DEBUG_STARTUP,
+                  "Received startup canceled for %s\n",
+                  sn_startup_sequence_get_id (sequence));
+      break;
+    }
+
+  sn_startup_sequence_unref (sequence);
+}
+#endif
+
+void
+meta_x11_startup_notification_init (MetaX11Display *x11_display)
+{
+#ifdef HAVE_STARTUP_NOTIFICATION
+  MetaX11StartupNotification *x11_sn;
+
+  x11_sn = g_new0 (MetaX11StartupNotification, 1);
+  x11_sn->sn_display = sn_display_new (x11_display->xdisplay,
+                                            sn_error_trap_push,
+                                            sn_error_trap_pop);
+  x11_sn->sn_context =
+    sn_monitor_context_new (x11_sn->sn_display,
+                            meta_x11_display_get_screen_number (x11_display),
+                            meta_startup_notification_sn_event,
+                            x11_display,
+                            NULL);
+
+  x11_display->startup_notification = x11_sn;
+#endif
+}
+
+void
+meta_x11_startup_notification_release (MetaX11Display *x11_display)
+{
+#ifdef HAVE_STARTUP_NOTIFICATION
+  MetaX11StartupNotification *x11_sn = x11_display->startup_notification;
+
+  x11_display->startup_notification = NULL;
+
+  if (x11_sn)
+    {
+      sn_monitor_context_unref (x11_sn->sn_context);
+      sn_display_unref (x11_sn->sn_display);
+      g_free (x11_sn);
+    }
+#endif
+}
+
+gboolean
+meta_x11_startup_notification_handle_xevent (MetaX11Display *x11_display,
+                                             XEvent         *xevent)
+{
+  MetaX11StartupNotification *x11_sn = x11_display->startup_notification;
+
+  if (!x11_sn)
+    return FALSE;
+
+  return sn_display_process_event (x11_sn->sn_display, xevent);
+}
diff --git a/src/x11/meta-startup-notification-x11.h b/src/x11/meta-startup-notification-x11.h
new file mode 100644
index 000000000..050d20caf
--- /dev/null
+++ b/src/x11/meta-startup-notification-x11.h
@@ -0,0 +1,39 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2018 Red Hat, Inc
+ *
+ * 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 "meta-x11-display-private.h"
+
+#ifndef META_X11_STARTUP_NOTIFICATION_H
+#define META_X11_STARTUP_NOTIFICATION_H
+
+typedef struct _MetaX11StartupNotification MetaX11StartupNotification;
+
+#define META_TYPE_STARTUP_SEQUENCE_X11 (meta_startup_sequence_x11_get_type ())
+
+G_DECLARE_FINAL_TYPE (MetaStartupSequenceX11,
+                      meta_startup_sequence_x11,
+                      META, STARTUP_SEQUENCE_X11,
+                      MetaStartupSequence)
+
+void     meta_x11_startup_notification_init    (MetaX11Display *x11_display);
+void     meta_x11_startup_notification_release (MetaX11Display *x11_display);
+
+gboolean meta_x11_startup_notification_handle_xevent (MetaX11Display *x11_display,
+                                                      XEvent         *xevent);
+
+#endif /* META_X11_STARTUP_NOTIFICATION_H */
diff --git a/src/x11/meta-x11-display-private.h b/src/x11/meta-x11-display-private.h
index 54bbcf7f2..e3382642f 100644
--- a/src/x11/meta-x11-display-private.h
+++ b/src/x11/meta-x11-display-private.h
@@ -33,6 +33,7 @@
 #include "meta/common.h"
 #include "meta/types.h"
 #include "meta/meta-x11-display.h"
+#include "meta-startup-notification-x11.h"
 #include "ui/ui.h"
 
 typedef struct _MetaGroupPropHooks  MetaGroupPropHooks;
@@ -149,6 +150,8 @@ struct _MetaX11Display
 #define META_X11_DISPLAY_HAS_DAMAGE(x11_display) ((x11_display)->have_damage)
   gboolean have_xinput_23 : 1;
 #define META_X11_DISPLAY_HAS_XINPUT_23(x11_display) ((x11_display)->have_xinput_23)
+
+  MetaX11StartupNotification *startup_notification;
 };
 
 MetaX11Display *meta_x11_display_new (MetaDisplay *display, GError **error);
diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c
index 8c5dfaafd..77fb091f6 100644
--- a/src/x11/meta-x11-display.c
+++ b/src/x11/meta-x11-display.c
@@ -99,6 +99,8 @@ meta_x11_display_dispose (GObject *object)
 {
   MetaX11Display *x11_display = META_X11_DISPLAY (object);
 
+  meta_x11_startup_notification_release (x11_display);
+
   meta_prefs_remove_listener (prefs_changed_callback, x11_display);
 
   meta_x11_display_ungrab_keys (x11_display);
@@ -1352,6 +1354,8 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
 
   set_x11_bell_is_audible (x11_display, meta_prefs_bell_is_audible ());
 
+  meta_x11_startup_notification_init (x11_display);
+
   return x11_display;
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]