diff --git a/configure.ac b/configure.ac index 415ca5d42..efd8fb813 100644 --- a/configure.ac +++ b/configure.ac @@ -232,7 +232,7 @@ AS_IF([test "x$WAYLAND_SCANNER" = "xno"], AC_SUBST([WAYLAND_SCANNER]) AC_SUBST(XWAYLAND_PATH) -MUTTER_PC_MODULES="$MUTTER_PC_MODULES wayland-server" +MUTTER_PC_MODULES="$MUTTER_PC_MODULES wayland-server libdrm" PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES) PKG_CHECK_EXISTS([xi >= 1.6.99.1], diff --git a/src/Makefile.am b/src/Makefile.am index 4fc7c5820..462e8a82d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -195,7 +195,9 @@ libmutter_wayland_la_SOURCES += \ wayland/meta-wayland-seat.c \ wayland/meta-wayland-seat.h \ wayland/meta-wayland-stage.h \ - wayland/meta-wayland-stage.c + wayland/meta-wayland-stage.c \ + wayland/meta-weston-launch.c \ + wayland/meta-weston-launch.h libmutter_wayland_la_LDFLAGS = -no-undefined libmutter_wayland_la_LIBADD = $(MUTTER_LIBS) diff --git a/src/core/main.c b/src/core/main.c index c4620a175..5f1f4daeb 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -58,6 +58,7 @@ #include "meta-wayland-private.h" #include +#include #include #include @@ -352,59 +353,12 @@ meta_finalize (void) meta_wayland_finalize (); } -static int signal_pipe_fds[2] = { -1, -1 }; - -static void -signal_handler (int signum) -{ - if (signal_pipe_fds[1] >= 0) - { - switch (signum) - { - case SIGTERM: - write (signal_pipe_fds[1], "T", 1); - break; - default: - break; - } - } -} - static gboolean -on_signal (GIOChannel *source, - GIOCondition condition, - void *data) +on_sigterm (gpointer user_data) { - char signal; - int count; + meta_quit (EXIT_SUCCESS); - for (;;) - { - count = read (signal_pipe_fds[0], &signal, 1); - if (count == EINTR) - continue; - if (count < 0) - { - const char *msg = strerror (errno); - g_warning ("Error handling signal: %s", msg); - } - if (count != 1) - { - g_warning ("Unexpectedly failed to read byte from signal pipe\n"); - return TRUE; - } - break; - } - switch (signal) - { - case 'T': /* SIGTERM */ - meta_quit (META_EXIT_SUCCESS); - break; - default: - g_warning ("Spurious character '%c' read from signal pipe", signal); - } - - return TRUE; + return G_SOURCE_REMOVE; } /** @@ -418,7 +372,6 @@ meta_init (void) { struct sigaction act; sigset_t empty_mask; - GIOChannel *channel; sigemptyset (&empty_mask); act.sa_handler = SIG_IGN; @@ -433,20 +386,7 @@ meta_init (void) g_strerror (errno)); #endif - if (pipe (signal_pipe_fds) != 0) - g_printerr ("Failed to create signal pipe: %s\n", - g_strerror (errno)); - - channel = g_io_channel_unix_new (signal_pipe_fds[0]); - g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL); - g_io_add_watch (channel, G_IO_IN, (GIOFunc) on_signal, NULL); - g_io_channel_set_close_on_unref (channel, TRUE); - g_io_channel_unref (channel); - - act.sa_handler = &signal_handler; - if (sigaction (SIGTERM, &act, NULL) < 0) - g_printerr ("Failed to register SIGTERM handler: %s\n", - g_strerror (errno)); + g_unix_signal_add (SIGTERM, on_sigterm, NULL); if (g_getenv ("MUTTER_VERBOSE")) meta_set_verbose (TRUE); diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h index e470dfa79..2c51a7dc5 100644 --- a/src/wayland/meta-wayland-private.h +++ b/src/wayland/meta-wayland-private.h @@ -28,6 +28,7 @@ #include #include "window-private.h" +#include "meta-weston-launch.h" #include typedef struct _MetaWaylandCompositor MetaWaylandCompositor; @@ -140,6 +141,9 @@ struct _MetaWaylandCompositor struct wl_client *xwayland_client; struct wl_resource *xserver_resource; + MetaLauncher *launcher; + int drm_fd; + MetaWaylandSeat *seat; /* This surface is only used to keep drag of the implicit grab when @@ -330,6 +334,8 @@ void meta_wayland_compositor_repick (MetaWaylandComp void meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor, MetaWindow *window); +MetaLauncher *meta_wayland_compositor_get_launcher (MetaWaylandCompositor *compositor); + void meta_wayland_surface_free (MetaWaylandSurface *surface); #endif /* META_WAYLAND_PRIVATE_H */ diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c index 267a5361d..c4f5e0bcf 100644 --- a/src/wayland/meta-wayland.c +++ b/src/wayland/meta-wayland.c @@ -50,6 +50,7 @@ #include #include "frame.h" #include "meta-idle-monitor-private.h" +#include "meta-weston-launch.h" #include "monitor-private.h" static MetaWaylandCompositor _meta_wayland_compositor; @@ -1545,6 +1546,9 @@ meta_wayland_init (void) MetaWaylandCompositor *compositor = &_meta_wayland_compositor; guint event_signal; MetaMonitorManager *monitors; + ClutterBackend *backend; + CoglContext *cogl_context; + CoglRenderer *cogl_renderer; memset (compositor, 0, sizeof (MetaWaylandCompositor)); @@ -1581,9 +1585,33 @@ meta_wayland_init (void) clutter_wayland_set_compositor_display (compositor->wayland_display); + if (getenv ("WESTON_LAUNCHER_SOCK")) + compositor->launcher = meta_launcher_new (); + if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS) g_error ("Failed to initialize Clutter"); + backend = clutter_get_default_backend (); + cogl_context = clutter_backend_get_cogl_context (backend); + cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (cogl_context)); + + if (cogl_renderer_get_winsys_id (cogl_renderer) == COGL_WINSYS_ID_EGL_KMS) + compositor->drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer); + else + compositor->drm_fd = -1; + + if (compositor->drm_fd >= 0) + { + GError *error; + + error = NULL; + if (!meta_launcher_set_drm_fd (compositor->launcher, compositor->drm_fd, &error)) + { + g_error ("Failed to set DRM fd to weston-launch and become DRM master: %s", error->message); + g_error_free (error); + } + } + meta_monitor_manager_initialize (); monitors = meta_monitor_manager_get (); g_signal_connect (monitors, "monitors-changed", @@ -1646,5 +1674,16 @@ meta_wayland_init (void) void meta_wayland_finalize (void) { - meta_xwayland_stop (meta_wayland_compositor_get_default ()); + MetaWaylandCompositor *compositor; + + compositor = meta_wayland_compositor_get_default (); + + meta_xwayland_stop (compositor); + g_clear_object (&compositor->launcher); +} + +MetaLauncher * +meta_wayland_compositor_get_launcher (MetaWaylandCompositor *compositor) +{ + return compositor->launcher; } diff --git a/src/wayland/meta-weston-launch.c b/src/wayland/meta-weston-launch.c new file mode 100644 index 000000000..709eacc5a --- /dev/null +++ b/src/wayland/meta-weston-launch.c @@ -0,0 +1,453 @@ +/* + * Copyright (C) 2013 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "meta-weston-launch.h" + +struct _MetaLauncherClass +{ + GObjectClass parent_class; + + void (*enter) (MetaLauncher *); + void (*leave) (MetaLauncher *); +}; + +struct _MetaLauncher +{ + GObject parent; + + GSocket *weston_launch; + + gboolean vt_switched; + + GMainContext *nested_context; + GMainLoop *nested_loop; + + GSource *inner_source; + GSource *outer_source; +}; + +enum { + SIGNAL_ENTER, + SIGNAL_LEAVE, + SIGNAL_LAST +}; + +static int signals[SIGNAL_LAST]; + +G_DEFINE_TYPE (MetaLauncher, meta_launcher, G_TYPE_OBJECT); + +static void handle_request_vt_switch (MetaLauncher *self); + +static gboolean +request_vt_switch_idle (gpointer user_data) +{ + handle_request_vt_switch (user_data); + + return FALSE; +} + +static gboolean +send_message_to_wl (MetaLauncher *self, + void *message, + gsize size, + GSocketControlMessage *out_cmsg, + GSocketControlMessage **in_cmsg, + GError **error) +{ + struct weston_launcher_reply reply; + GInputVector in_iov = { &reply, sizeof (reply) }; + GOutputVector out_iov = { message, size }; + GSocketControlMessage *out_all_cmsg[2]; + GSocketControlMessage **in_all_cmsg; + int flags = 0; + int i; + + out_all_cmsg[0] = out_cmsg; + out_all_cmsg[1] = NULL; + if (g_socket_send_message (self->weston_launch, NULL, + &out_iov, 1, + out_all_cmsg, -1, + flags, NULL, error) != (gssize)size) + return FALSE; + + if (g_socket_receive_message (self->weston_launch, NULL, + &in_iov, 1, + &in_all_cmsg, NULL, + &flags, NULL, error) != sizeof (reply)) + return FALSE; + + while (reply.header.opcode != ((struct weston_launcher_message*)message)->opcode) + { + /* There were events queued */ + g_assert ((reply.header.opcode & WESTON_LAUNCHER_EVENT) == WESTON_LAUNCHER_EVENT); + + /* This can never happen, because the only time mutter-launch can queue + this event is after confirming a VT switch, and we don't make requests + during that time. + + Note that getting this event would be really bad, because we would be + in the wrong loop/context. + */ + g_assert (reply.header.opcode != WESTON_LAUNCHER_SERVER_VT_ENTER); + + switch (reply.header.opcode) + { + case WESTON_LAUNCHER_SERVER_REQUEST_VT_SWITCH: + g_idle_add (request_vt_switch_idle, self); + break; + + default: + g_assert_not_reached (); + } + + if (g_socket_receive_message (self->weston_launch, NULL, + &in_iov, 1, + NULL, NULL, + &flags, NULL, error) != sizeof (reply)) + return FALSE; + } + + if (reply.ret != 0) + { + if (reply.ret == -1) + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Got failure from weston-launch"); + else + g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-reply.ret), + "Got failure from weston-launch: %s", strerror (-reply.ret)); + + 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 && in_all_cmsg[0]) + { + for (i = 1; in_all_cmsg[i]; i++) + g_object_unref (in_all_cmsg[i]); + *in_cmsg = in_all_cmsg[0]; + } + + g_free (in_all_cmsg); + return TRUE; +} + +gboolean +meta_launcher_set_drm_fd (MetaLauncher *self, + int drm_fd, + GError **error) +{ + struct weston_launcher_message message; + GSocketControlMessage *cmsg; + gboolean ok; + + message.opcode = WESTON_LAUNCHER_DRM_SET_FD; + + cmsg = g_unix_fd_message_new (); + if (g_unix_fd_message_append_fd (G_UNIX_FD_MESSAGE (cmsg), + drm_fd, error) == FALSE) + { + g_object_unref (cmsg); + return FALSE; + } + + ok = send_message_to_wl (self, &message, sizeof message, cmsg, NULL, error); + + g_object_unref (cmsg); + return ok; +} + +int +meta_launcher_open_input_device (MetaLauncher *self, + const char *name, + int flags, + GError **error) +{ + struct weston_launcher_open *message; + GSocketControlMessage *cmsg; + gboolean ok; + gsize size; + int *fds, n_fd; + int ret; + + 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 (self, message, size, NULL, &cmsg, error); + + if (ok) + { + g_assert (G_IS_UNIX_FD_MESSAGE (cmsg)); + + fds = g_unix_fd_message_steal_fds (G_UNIX_FD_MESSAGE (cmsg), &n_fd); + g_assert (n_fd == 1); + + ret = fds[0]; + g_free (fds); + g_object_unref (cmsg); + } + else + ret = -1; + + g_free (message); + return ret; +} + +static void +meta_launcher_finalize (GObject *object) +{ + MetaLauncher *launcher = META_LAUNCHER (object); + + g_source_destroy (launcher->outer_source); + g_source_destroy (launcher->inner_source); + + g_main_loop_unref (launcher->nested_loop); + g_main_context_unref (launcher->nested_context); + + g_object_unref (launcher->weston_launch); + + G_OBJECT_CLASS (meta_launcher_parent_class)->finalize (object); +} + +static void +meta_launcher_enter (MetaLauncher *launcher) +{ + ClutterBackend *backend; + CoglContext *cogl_context; + CoglDisplay *cogl_display; + + backend = clutter_get_default_backend (); + cogl_context = clutter_backend_get_cogl_context (backend); + cogl_display = cogl_context_get_display (cogl_context); + cogl_kms_display_queue_modes_reset (cogl_display); + + clutter_evdev_reclaim_devices (); +} + +static void +meta_launcher_leave (MetaLauncher *launcher) +{ + clutter_evdev_release_devices (); +} + +static int +on_evdev_device_open (const char *path, + int flags, + gpointer user_data, + GError **error) +{ + MetaLauncher *launcher = user_data; + + return meta_launcher_open_input_device (launcher, path, flags, error); +} + +static void +handle_vt_enter (MetaLauncher *launcher) +{ + g_assert (launcher->vt_switched); + + g_main_loop_quit (launcher->nested_loop); +} + +static void +handle_request_vt_switch (MetaLauncher *launcher) +{ + struct weston_launcher_message message; + GError *error; + gboolean ok; + + g_signal_emit (launcher, signals[SIGNAL_LEAVE], 0); + + message.opcode = WESTON_LAUNCHER_CONFIRM_VT_SWITCH; + + error = NULL; + ok = send_message_to_wl (launcher, &message, sizeof (message), NULL, NULL, &error); + if (!ok) { + g_warning ("Failed to acknowledge VT switch: %s", error->message); + g_error_free (error); + + return; + } + + g_assert (!launcher->vt_switched); + launcher->vt_switched = TRUE; + + /* 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 (launcher->nested_loop); + + g_assert (launcher->vt_switched); + launcher->vt_switched = FALSE; + + g_signal_emit (launcher, signals[SIGNAL_ENTER], 0); +} + +static gboolean +on_socket_readable (GSocket *socket, + GIOCondition condition, + gpointer user_data) +{ + MetaLauncher *launcher = user_data; + struct weston_launcher_event event; + gssize read; + GError *error; + + if ((condition & G_IO_IN) == 0) + return TRUE; + + error = NULL; + read = g_socket_receive (socket, (char*)&event, sizeof(event), NULL, &error); + if (read < (gssize)sizeof(event)) + { + g_warning ("Error reading from weston-launcher socket: %s", error->message); + g_error_free (error); + return TRUE; + } + + switch (event.header.opcode) + { + case WESTON_LAUNCHER_SERVER_REQUEST_VT_SWITCH: + handle_request_vt_switch (launcher); + break; + + case WESTON_LAUNCHER_SERVER_VT_ENTER: + handle_vt_enter (launcher); + break; + } + + return TRUE; +} + +static int +env_get_fd (const char *env) +{ + const char *value; + + value = g_getenv (env); + + if (value == NULL) + return -1; + else + return g_ascii_strtoll (value, NULL, 10); +} + +static void +meta_launcher_init (MetaLauncher *self) +{ + int launch_fd; + + launch_fd = env_get_fd ("WESTON_LAUNCHER_SOCK"); + if (launch_fd < 0) + g_error ("Invalid mutter-launch socket"); + + self->weston_launch = g_socket_new_from_fd (launch_fd, NULL); + + clutter_evdev_set_open_callback (on_evdev_device_open, self); + + self->nested_context = g_main_context_new (); + self->nested_loop = g_main_loop_new (self->nested_context, FALSE); + + self->outer_source = g_socket_create_source (self->weston_launch, G_IO_IN, NULL); + g_source_set_callback (self->outer_source, (GSourceFunc)on_socket_readable, self, NULL); + g_source_attach (self->outer_source, NULL); + g_source_unref (self->outer_source); + + self->inner_source = g_socket_create_source (self->weston_launch, G_IO_IN, NULL); + g_source_set_callback (self->inner_source, (GSourceFunc)on_socket_readable, self, NULL); + g_source_attach (self->inner_source, self->nested_context); + g_source_unref (self->inner_source); +} + +static void +meta_launcher_class_init (MetaLauncherClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = meta_launcher_finalize; + + klass->enter = meta_launcher_enter; + klass->leave = meta_launcher_leave; + + signals[SIGNAL_ENTER] = g_signal_new ("enter", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (MetaLauncherClass, enter), + NULL, NULL, /* accumulator */ + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[SIGNAL_LEAVE] = g_signal_new ("leave", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (MetaLauncherClass, leave), + NULL, NULL, /* accumulator */ + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +MetaLauncher * +meta_launcher_new (void) +{ + return g_object_new (META_TYPE_LAUNCHER, NULL); +} + +gboolean +meta_launcher_activate_vt (MetaLauncher *launcher, + int vt, + GError **error) +{ + struct weston_launcher_activate_vt message; + + message.header.opcode = WESTON_LAUNCHER_ACTIVATE_VT; + message.vt = vt; + + return send_message_to_wl (launcher, &message, sizeof (message), NULL, NULL, error); +} + diff --git a/src/wayland/meta-weston-launch.h b/src/wayland/meta-weston-launch.h new file mode 100644 index 000000000..19d3756a2 --- /dev/null +++ b/src/wayland/meta-weston-launch.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2013 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef META_WESTON_LAUNCH_H +#define META_WESTON_LAUNCH_H + +#include +#include "weston-launch.h" + +#define META_TYPE_LAUNCHER (meta_launcher_get_type()) +#define META_LAUNCHER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_LAUNCHER, MetaLauncher)) +#define META_LAUNCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_LAUNCHER, MetaLauncherClass)) +#define META_IS_LAUNCHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_LAUNCHER)) +#define META_IS_LAUNCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_LAUNCHER)) +#define META_LAUNCHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_LAUNCHER, MetaLauncherClass)) + +typedef struct _MetaLauncher MetaLauncher; +typedef struct _MetaLauncherClass MetaLauncherClass; + +GType meta_launcher_get_type (void) G_GNUC_CONST; + +MetaLauncher *meta_launcher_new (void); + +gboolean meta_launcher_activate_vt (MetaLauncher *self, + int number, + GError **error); + +gboolean meta_launcher_set_drm_fd (MetaLauncher *self, + int drm_fd, + GError **error); +gboolean meta_launcher_set_master (MetaLauncher *self, + gboolean master, + GError **error); +int meta_launcher_open_input_device (MetaLauncher *self, + const char *name, + int flags, + GError **error); + +#endif diff --git a/src/wayland/weston-launch.c b/src/wayland/weston-launch.c index 1efff30d0..71c753093 100644 --- a/src/wayland/weston-launch.c +++ b/src/wayland/weston-launch.c @@ -171,14 +171,17 @@ setenv_fd(const char *env, int fd) static int handle_setdrmfd(struct weston_launch *wl, struct msghdr *msg, ssize_t len) { - int ret = -1; + struct weston_launcher_reply reply; struct cmsghdr *cmsg; union cmsg_data *data; struct stat s; + reply.header.opcode = WESTON_LAUNCHER_DRM_SET_FD; + reply.ret = -1; + if (wl->drm_fd != -1) { error(0, 0, "DRM FD already set"); - ret = -EINVAL; + reply.ret = -EINVAL; goto out; } @@ -187,40 +190,40 @@ handle_setdrmfd(struct weston_launch *wl, struct msghdr *msg, ssize_t len) cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) { error(0, 0, "invalid control message"); - ret = -EINVAL; + reply.ret = -EINVAL; goto out; } data = (union cmsg_data *) CMSG_DATA(cmsg); if (data->fd < 0) { error(0, 0, "missing drm fd in socket request"); - ret = -EINVAL; + reply.ret = -EINVAL; goto out; } if (fstat(data->fd, &s) < 0) { - ret = -errno; + reply.ret = -errno; goto out; } if (major(s.st_rdev) != DRM_MAJOR) { fprintf(stderr, "FD is not for DRM\n"); - ret = -EPERM; + reply.ret = -EPERM; goto out; } wl->drm_fd = data->fd; - ret = drmSetMaster(data->fd); - if (ret < 0) - ret = -errno; + reply.ret = drmSetMaster(data->fd); + if (reply.ret < 0) + reply.ret = -errno; if (wl->verbose) fprintf(stderr, "weston-launch: set drm FD, ret: %d, fd: %d\n", - ret, data->fd); + reply.ret, data->fd); out: do { - len = send(wl->sock[0], &ret, sizeof ret, 0); + len = send(wl->sock[0], &reply, sizeof reply, 0); } while (len < 0 && errno == EINTR); if (len < 0) return -1; @@ -231,7 +234,10 @@ out: static int handle_confirm_vt_switch(struct weston_launch *wl, struct msghdr *msg, ssize_t len) { - int ret = -1; + struct weston_launcher_reply reply; + + reply.header.opcode = WESTON_LAUNCHER_CONFIRM_VT_SWITCH; + reply.ret = -1; if (wl->vt_state != VT_PENDING_CONFIRM) { error(0, 0, "unexpected CONFIRM_VT_SWITCH"); @@ -255,11 +261,11 @@ handle_confirm_vt_switch(struct weston_launch *wl, struct msghdr *msg, ssize_t l if (wl->verbose) fprintf(stderr, "weston-launcher: confirmed VT switch\n"); - ret = 0; + reply.ret = 0; out: do { - len = send(wl->sock[0], &ret, sizeof ret, 0); + len = send(wl->sock[0], &reply, sizeof reply, 0); } while (len < 0 && errno == EINTR); if (len < 0) return -1; @@ -270,9 +276,12 @@ out: static int handle_activate_vt(struct weston_launch *wl, struct msghdr *msg, ssize_t len) { - int ret = -1; + struct weston_launcher_reply reply; struct weston_launcher_activate_vt *message; + reply.header.opcode = WESTON_LAUNCHER_ACTIVATE_VT; + reply.ret = -1; + if (len != sizeof(*message)) { error(0, 0, "missing value in activate_vt request"); goto out; @@ -280,16 +289,16 @@ handle_activate_vt(struct weston_launch *wl, struct msghdr *msg, ssize_t len) message = msg->msg_iov->iov_base; - ret = ioctl(wl->tty, VT_ACTIVATE, message->vt); - if (ret < 0) - ret = -errno; + reply.ret = ioctl(wl->tty, VT_ACTIVATE, message->vt); + if (reply.ret < 0) + reply.ret = -errno; if (wl->verbose) - fprintf(stderr, "weston-launch: activate VT, ret: %d\n", ret); + fprintf(stderr, "weston-launch: activate VT, ret: %d\n", reply.ret); out: do { - len = send(wl->sock[0], &ret, sizeof ret, 0); + len = send(wl->sock[0], &reply, sizeof reply, 0); } while (len < 0 && errno == EINTR); if (len < 0) return -1; @@ -301,7 +310,8 @@ out: static int handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len) { - int fd = -1, ret = -1; + struct weston_launcher_reply reply; + int fd = -1; char control[CMSG_SPACE(sizeof(fd))]; struct cmsghdr *cmsg; struct stat s; @@ -310,6 +320,9 @@ handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len) struct weston_launcher_open *message; union cmsg_data *data; + reply.header.opcode = WESTON_LAUNCHER_OPEN; + reply.ret = -1; + message = msg->msg_iov->iov_base; if ((size_t)len < sizeof(*message)) goto err0; @@ -318,7 +331,7 @@ handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len) ((char *) message)[len-1] = '\0'; if (stat(message->path, &s) < 0) { - ret = -errno; + reply.ret = -errno; goto err0; } @@ -326,7 +339,7 @@ handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len) if (fd < 0) { fprintf(stderr, "Error opening device %s: %m\n", message->path); - ret = -errno; + reply.ret = -errno; goto err0; } @@ -335,7 +348,7 @@ handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len) fd = -1; fprintf(stderr, "Device %s is not an input device\n", message->path); - ret = -EPERM; + reply.ret = -EPERM; goto err0; } @@ -353,14 +366,14 @@ err0: data = (union cmsg_data *) CMSG_DATA(cmsg); data->fd = fd; nmsg.msg_controllen = cmsg->cmsg_len; - ret = 0; + reply.ret = 0; } - iov.iov_base = &ret; - iov.iov_len = sizeof ret; + iov.iov_base = &reply; + iov.iov_len = sizeof reply; if (wl->verbose) fprintf(stderr, "weston-launch: opened %s: ret: %d, fd: %d\n", - message->path, ret, fd); + message->path, reply.ret, fd); do { len = sendmsg(wl->sock[0], &nmsg, 0); } while (len < 0 && errno == EINTR); @@ -467,12 +480,12 @@ quit(struct weston_launch *wl, int status) static int handle_vt_switch(struct weston_launch *wl) { - struct weston_launcher_message message; + struct weston_launcher_event message; ssize_t len; if (wl->vt_state == VT_HAS_VT) { wl->vt_state = VT_PENDING_CONFIRM; - message.opcode = WESTON_LAUNCHER_SERVER_REQUEST_VT_SWITCH; + message.header.opcode = WESTON_LAUNCHER_SERVER_REQUEST_VT_SWITCH; } else if (wl->vt_state == VT_NOT_HAVE_VT) { wl->vt_state = VT_HAS_VT; ioctl(wl->tty, VT_RELDISP, VT_ACKACQ); @@ -490,10 +503,12 @@ handle_vt_switch(struct weston_launch *wl) } } - message.opcode = WESTON_LAUNCHER_SERVER_VT_ENTER; + message.header.opcode = WESTON_LAUNCHER_SERVER_VT_ENTER; } else return -1; + message.detail = 0; + do { len = send(wl->sock[0], &message, sizeof(message), 0); } while (len < 0 && errno == EINTR); diff --git a/src/wayland/weston-launch.h b/src/wayland/weston-launch.h index 092a47605..74e6c3be6 100644 --- a/src/wayland/weston-launch.h +++ b/src/wayland/weston-launch.h @@ -24,16 +24,21 @@ #ifndef _WESTON_LAUNCH_H_ #define _WESTON_LAUNCH_H_ +enum weston_launcher_message_type { + WESTON_LAUNCHER_REQUEST, + WESTON_LAUNCHER_EVENT, +}; + enum weston_launcher_opcode { - WESTON_LAUNCHER_OPEN, - WESTON_LAUNCHER_DRM_SET_FD, - WESTON_LAUNCHER_ACTIVATE_VT, - WESTON_LAUNCHER_CONFIRM_VT_SWITCH, + WESTON_LAUNCHER_OPEN = (1 << 1 | WESTON_LAUNCHER_REQUEST), + WESTON_LAUNCHER_DRM_SET_FD = (2 << 1 | WESTON_LAUNCHER_REQUEST), + WESTON_LAUNCHER_ACTIVATE_VT = (3 << 1 | WESTON_LAUNCHER_REQUEST), + WESTON_LAUNCHER_CONFIRM_VT_SWITCH = (4 << 1 | WESTON_LAUNCHER_REQUEST), }; enum weston_launcher_server_opcode { - WESTON_LAUNCHER_SERVER_REQUEST_VT_SWITCH, - WESTON_LAUNCHER_SERVER_VT_ENTER, + WESTON_LAUNCHER_SERVER_REQUEST_VT_SWITCH = (1 << 1 | WESTON_LAUNCHER_EVENT), + WESTON_LAUNCHER_SERVER_VT_ENTER = (2 << 1 | WESTON_LAUNCHER_EVENT), }; struct weston_launcher_message { @@ -51,4 +56,14 @@ struct weston_launcher_activate_vt { int vt; }; +struct weston_launcher_reply { + struct weston_launcher_message header; + int ret; +}; + +struct weston_launcher_event { + struct weston_launcher_message header; + int detail; /* unused, but makes sure replies and events are serialized the same */ +}; + #endif