mirror of
https://github.com/brl/mutter.git
synced 2024-11-25 01:20:42 -05:00
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
This commit is contained in:
parent
045d03014d
commit
c96fd23e79
@ -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);
|
||||
|
||||
|
@ -1391,7 +1391,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
|
||||
@ -1506,6 +1506,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)
|
||||
@ -1514,7 +1516,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 ();
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user