[mutter/wip/wayland-display: 51/93] Improve handling while VT switched



commit df3602ba9e353f73b622eb5b6a4e8e872aad1884
Author: Giovanni Campagna <gcampagn redhat com>
Date:   Tue Jul 16 14:10:14 2013 +0200

    Improve handling while VT switched
    
    When we don't have the DRM master, there is absolutely nothing
    we can do (no event processing, no video output), so emulate
    the old X DRM lock with a nested GMainContext without sources.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=705861

 src/wayland/meta-tty.c           |   69 +++++++++++++++++++++++++------------
 src/wayland/meta-wayland.c       |   12 +++++-
 src/wayland/meta-weston-launch.c |   15 ++++----
 3 files changed, 64 insertions(+), 32 deletions(-)
---
diff --git a/src/wayland/meta-tty.c b/src/wayland/meta-tty.c
index 8aae4c7..0ac342a 100644
--- a/src/wayland/meta-tty.c
+++ b/src/wayland/meta-tty.c
@@ -59,9 +59,12 @@ struct _MetaTTY
   int fd;
   struct termios terminal_attributes;
 
-  int input_source, vt_source;
+  GMainContext *nested_context;
+  GMainLoop *nested_loop;
+
+  int input_source;
+  GSource *vt_enter_source, *vt_leave_source;
   int vt, starting_vt;
-  gboolean has_vt;
   int kb_mode;
 };
 
@@ -79,27 +82,35 @@ G_DEFINE_TYPE_WITH_CODE (MetaTTY, meta_tty, G_TYPE_OBJECT,
                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
                                                meta_tty_initable_iface_init));
 
-static int
-vt_handler (gpointer user_data)
+static gboolean
+vt_acquire_handler (gpointer user_data)
 {
   MetaTTY *tty = user_data;
 
-  if (tty->has_vt)
-    {
-      tty->has_vt = FALSE;
-      g_signal_emit (tty, signals[SIGNAL_LEAVE], 0);
+  g_main_loop_quit (tty->nested_loop);
 
-      ioctl (tty->fd, VT_RELDISP, 1);
-    }
-  else
-    {
-      ioctl (tty->fd, VT_RELDISP, VT_ACKACQ);
+  return FALSE;
+}
 
-      tty->has_vt = 1;
-      g_signal_emit (tty, signals[SIGNAL_ENTER], 0);
-    }
+static gboolean
+vt_release_handler (gpointer user_data)
+{
+  MetaTTY *tty = user_data;
 
-  return 1;
+  g_signal_emit (tty, signals[SIGNAL_LEAVE], 0);
+
+  ioctl (tty->fd, VT_RELDISP, 1);
+
+  /* We can't do anything at this point, because we don't
+     have input devices and we don't have the DRM master,
+     so let's run a nested busy loop until the VT is reentered */
+  g_main_loop_run (tty->nested_loop);
+
+  ioctl (tty->fd, VT_RELDISP, VT_ACKACQ);
+
+  g_signal_emit (tty, signals[SIGNAL_ENTER], 0);
+
+  return FALSE;
 }
 
 static int
@@ -164,7 +175,7 @@ env_get_fd (const char *env)
   if (value == NULL)
     return -1;
   else
-    return g_ascii_strtoll (env, NULL, 10);
+    return g_ascii_strtoll (value, NULL, 10);
 }
 
 static gboolean
@@ -271,10 +282,9 @@ meta_tty_initable_init(GInitable     *initable,
       goto err_kdkbmode;
     }
 
-  tty->has_vt = 1;
   mode.mode = VT_PROCESS;
   mode.relsig = SIGUSR1;
-  mode.acqsig = SIGUSR1;
+  mode.acqsig = SIGUSR2;
   if (ioctl(tty->fd, VT_SETMODE, &mode) < 0)
     {
       g_set_error (error, G_IO_ERROR,
@@ -283,7 +293,16 @@ meta_tty_initable_init(GInitable     *initable,
       goto err_kdmode;
     }
 
-  tty->vt_source = g_unix_signal_add (SIGUSR1, vt_handler, tty);
+  tty->vt_enter_source = g_unix_signal_source_new (SIGUSR2);
+  g_source_set_callback (tty->vt_enter_source, vt_acquire_handler, tty, NULL);
+  tty->vt_leave_source = g_unix_signal_source_new (SIGUSR1);
+  g_source_set_callback (tty->vt_leave_source, vt_release_handler, tty, NULL);
+
+  tty->nested_context = g_main_context_new ();
+  tty->nested_loop = g_main_loop_new (tty->nested_context, FALSE);
+
+  g_source_attach (tty->vt_leave_source, NULL);
+  g_source_attach (tty->vt_enter_source, tty->nested_context);
 
   return TRUE;
 
@@ -321,7 +340,7 @@ tty_reset (MetaTTY *tty)
   if (ioctl (tty->fd, VT_SETMODE, &mode) < 0)
     g_warning ("could not reset vt handling\n");
 
-  if (tty->has_vt && tty->vt != tty->starting_vt)
+  if (tty->vt != tty->starting_vt)
     {
       ioctl(tty->fd, VT_ACTIVATE, tty->starting_vt);
       ioctl(tty->fd, VT_WAITACTIVE, tty->starting_vt);
@@ -336,7 +355,11 @@ meta_tty_finalize (GObject *object)
   if (tty->input_source)
     g_source_remove (tty->input_source);
 
-  g_source_remove (tty->vt_source);
+  g_source_destroy (tty->vt_enter_source);
+  g_source_destroy (tty->vt_leave_source);
+
+  g_main_loop_unref (tty->nested_loop);
+  g_main_context_unref (tty->nested_context);
 
   tty_reset (tty);
 
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index f0ef1f0..8ef9a18 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -1406,7 +1406,7 @@ env_get_fd (const char *env)
   if (value == NULL)
     return -1;
   else
-    return g_ascii_strtoll (env, NULL, 10);
+    return g_ascii_strtoll (value, NULL, 10);
 }
 
 static void
@@ -1521,6 +1521,8 @@ meta_wayland_init (void)
 
   if (compositor->drm_fd >= 0)
     {
+      GError *error;
+
       /* Running on bare metal, let's initalize DRM master and VT handling */
       compositor->tty = meta_tty_new ();
       if (compositor->tty)
@@ -1529,7 +1531,13 @@ meta_wayland_init (void)
          g_signal_connect (compositor->tty, "leave", G_CALLBACK (on_our_vt_leave), compositor);
        }
 
-      on_our_vt_enter (compositor->tty, compositor);
+      error = NULL;
+      if (!meta_weston_launch_set_master (compositor->weston_launch,
+                                         compositor->drm_fd, TRUE, &error))
+       {
+         g_error ("Failed to become DRM master: %s", error->message);
+         g_error_free (error);
+       }
     }
 
   compositor->stage = meta_wayland_stage_new ();
diff --git a/src/wayland/meta-weston-launch.c b/src/wayland/meta-weston-launch.c
index 68f14cf..225ef2e 100644
--- a/src/wayland/meta-weston-launch.c
+++ b/src/wayland/meta-weston-launch.c
@@ -79,14 +79,14 @@ send_message_to_wl (GSocket                *weston_launch,
        g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ok),
                     "Got failure from weston-launch: %s", strerror (-ok));
 
-      for (i = 0; in_all_cmsg[i]; i++)
+      for (i = 0; in_all_cmsg && in_all_cmsg[i]; i++)
        g_object_unref (in_all_cmsg[i]);
       g_free (in_all_cmsg);
 
       return FALSE;
     }
 
-  if (in_all_cmsg[0])
+  if (in_all_cmsg && in_all_cmsg[0])
     {
       for (i = 1; in_all_cmsg[i]; i++)
        g_object_unref (in_all_cmsg[i]);
@@ -156,17 +156,18 @@ meta_weston_launch_open_input_device (GSocket    *weston_launch,
       struct weston_launcher_open *message;
       GSocketControlMessage *cmsg;
       gboolean ok;
+      gsize size;
       int *fds, n_fd;
       int ret;
 
-      message = g_malloc (sizeof (struct weston_launcher_open) +
-                         strlen (name));
+      size = sizeof (struct weston_launcher_open) + strlen (name) + 1;
+      message = g_malloc (size);
       message->header.opcode = WESTON_LAUNCHER_OPEN;
       message->flags = flags;
       strcpy (message->path, name);
+      message->path[strlen(name)] = 0;
 
-      ok = send_message_to_wl (weston_launch, message,
-                              sizeof (struct weston_launcher_open) + strlen (name),
+      ok = send_message_to_wl (weston_launch, message, size,
                               NULL, &cmsg, error);
 
       if (ok)
@@ -178,12 +179,12 @@ meta_weston_launch_open_input_device (GSocket    *weston_launch,
 
          ret = fds[0];
          g_free (fds);
+         g_object_unref (cmsg);
        }
       else
        ret = -1;
 
       g_free (message);
-      g_object_unref (cmsg);
       return ret;
     }
   else


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