[PATCH weston] clients: Add a weston-autorotater client and rotater protocol
Emmanuel Gil Peyrot
emmanuel.peyrot at collabora.com
Sat May 21 02:43:04 UTC 2016
This client uses libiio to retrieve accelerometer values from the iio
subsystem on Linux (and maybe some other kernels), and automatically
rotate the output whenever orientation changed.
I tested it with a mma8453 accelerometer, but everything needed should
be available in the configuration to make it work with any other iio
device.
Signed-off-by: Emmanuel Gil Peyrot <emmanuel.peyrot at collabora.com>
---
Makefile.am | 24 +++
clients/autorotater.c | 472 ++++++++++++++++++++++++++++++++++++++++++++
configure.ac | 15 ++
desktop-shell/shell.c | 1 +
protocol/weston-rotater.xml | 26 +++
src/compositor.h | 3 +
src/rotater.c | 150 ++++++++++++++
7 files changed, 691 insertions(+)
create mode 100644 clients/autorotater.c
create mode 100644 protocol/weston-rotater.xml
create mode 100644 src/rotater.c
diff --git a/Makefile.am b/Makefile.am
index 00b74e5..b1e0ade 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -122,6 +122,8 @@ endif
nodist_weston_SOURCES = \
protocol/weston-screenshooter-protocol.c \
protocol/weston-screenshooter-server-protocol.h \
+ protocol/weston-rotater-protocol.c \
+ protocol/weston-rotater-server-protocol.h \
protocol/text-cursor-position-protocol.c \
protocol/text-cursor-position-server-protocol.h \
protocol/text-input-unstable-v1-protocol.c \
@@ -611,6 +613,28 @@ nodist_weston_screenshooter_SOURCES = \
weston_screenshooter_LDADD = $(CLIENT_LIBS) libshared.la
weston_screenshooter_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS)
+if BUILD_AUTOROTATER
+libexec_PROGRAMS += weston-autorotater
+
+weston_autorotater_SOURCES = \
+ clients/autorotater.c
+nodist_weston_autorotater_SOURCES = \
+ protocol/weston-rotater-protocol.c \
+ protocol/weston-rotater-client-protocol.h
+weston_autorotater_LDADD = $(CLIENT_LIBS) $(LIBIIO_LIBS) libshared.la
+weston_autorotater_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS) $(LIBIIO_CFLAGS)
+
+weston_SOURCES += \
+ src/rotater.c
+
+BUILT_SOURCES += \
+ protocol/weston-rotater-protocol.c \
+ protocol/weston-rotater-client-protocol.h
+
+EXTRA_DIST += \
+ protocol/weston-rotater.xml
+endif
+
weston_terminal_SOURCES = \
clients/terminal.c \
shared/helpers.h
diff --git a/clients/autorotater.c b/clients/autorotater.c
new file mode 100644
index 0000000..0547f83
--- /dev/null
+++ b/clients/autorotater.c
@@ -0,0 +1,472 @@
+/*
+ * Copyright © 2016 Collabora, Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "config.h"
+
+#include <stdint.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <wayland-client.h>
+#include "weston-rotater-client-protocol.h"
+#include "shared/config-parser.h"
+#include "shared/helpers.h"
+#include "shared/xalloc.h"
+
+#include <iio.h>
+
+#define BUFFER_SIZE 256
+
+static struct weston_rotater *rotater;
+static struct wl_list output_list;
+
+struct rotater_output {
+ struct wl_output *output;
+ struct wl_list link;
+};
+
+#define DEFAULT_SAMPLING_FREQUENCY 100.
+
+struct config {
+ char *device_name;
+ char *channel_x_name, *channel_y_name;
+ char *sampling_frequency_name;
+ double wanted_sampling_frequency;
+ int threshold;
+ int smooth_capture;
+ struct wl_array allowed_rotations;
+};
+
+#define MAX_CAPTURE_BUFFER_LENGTH 16
+
+struct accelerometer {
+ struct iio_context *context;
+ struct iio_device *device;
+ struct iio_channel *channel_x, *channel_y;
+ double sampling_frequency;
+
+ struct {
+ int x[MAX_CAPTURE_BUFFER_LENGTH];
+ int y[MAX_CAPTURE_BUFFER_LENGTH];
+ } capture_buffer;
+};
+
+static const struct {
+ const char *name;
+ int token;
+} transforms[] = {
+ { "normal", WESTON_ROTATER_TRANSFORM_NORMAL },
+ { "90", WESTON_ROTATER_TRANSFORM_90 },
+ { "180", WESTON_ROTATER_TRANSFORM_180 },
+ { "270", WESTON_ROTATER_TRANSFORM_270 },
+ { "flipped", WESTON_ROTATER_TRANSFORM_FLIPPED },
+ { "flipped-90", WESTON_ROTATER_TRANSFORM_FLIPPED_90 },
+ { "flipped-180", WESTON_ROTATER_TRANSFORM_FLIPPED_180 },
+ { "flipped-270", WESTON_ROTATER_TRANSFORM_FLIPPED_270 },
+};
+
+static bool
+parse_transform(const char *transform, int *out)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_LENGTH(transforms); i++)
+ if (strncmp(transforms[i].name, transform,
+ strlen(transforms[i].name)) == 0) {
+ *out = transforms[i].token;
+ return true;
+ }
+
+ return false;
+}
+
+static struct config *
+read_configuration(void)
+{
+ struct config *configuration;
+ const char *config_file;
+ struct weston_config *config;
+ struct weston_config_section *s;
+
+ char *allowed_rotations, *p;
+ int transform, *array_items;
+ int i;
+
+ configuration = zalloc(sizeof *configuration);
+ if (!configuration)
+ return NULL;
+
+ config_file = weston_config_get_name_from_env();
+ config = weston_config_parse(config_file);
+ s = weston_config_get_section(config, "autorotater", NULL, NULL);
+ weston_config_section_get_string(s, "device",
+ &configuration->device_name, NULL);
+ weston_config_section_get_string(s, "channel_x",
+ &configuration->channel_x_name, NULL);
+ weston_config_section_get_string(s, "channel_y",
+ &configuration->channel_y_name, NULL);
+ weston_config_section_get_int(s, "threshold",
+ &configuration->threshold, 128);
+ weston_config_section_get_string(s, "sampling_frequency_attr",
+ &configuration->sampling_frequency_name,
+ NULL);
+ weston_config_section_get_double(s, "wanted_sampling_frequency",
+ &configuration->wanted_sampling_frequency,
+ 0.);
+ weston_config_section_get_int(s, "smooth_capture",
+ &configuration->smooth_capture, 1);
+ weston_config_section_get_string(s, "allowed_rotations",
+ &allowed_rotations, NULL);
+ weston_config_destroy(config);
+
+ if (configuration->smooth_capture < 1)
+ configuration->smooth_capture = 1;
+ else if (configuration->smooth_capture > MAX_CAPTURE_BUFFER_LENGTH)
+ configuration->smooth_capture = MAX_CAPTURE_BUFFER_LENGTH;
+
+ wl_array_init(&configuration->allowed_rotations);
+ if (allowed_rotations) {
+ p = allowed_rotations;
+ for (i = 0; i < 4; ++i) {
+ if (!parse_transform(p, &transform))
+ break;
+ array_items = wl_array_add(&configuration->allowed_rotations,
+ sizeof(int));
+ *array_items = transform;
+ for (; *p != ' ' && *p != '\0'; p++);
+ if (*p++ == '\0')
+ break;
+ }
+ free(allowed_rotations);
+ } else {
+ array_items = wl_array_add(&configuration->allowed_rotations,
+ sizeof(int));
+ array_items[0] = WESTON_ROTATER_TRANSFORM_NORMAL;
+ array_items[1] = WESTON_ROTATER_TRANSFORM_90;
+ array_items[2] = WESTON_ROTATER_TRANSFORM_180;
+ array_items[3] = WESTON_ROTATER_TRANSFORM_270;
+ }
+
+ return configuration;
+}
+
+static void
+destroy_configuration(struct config *config)
+{
+ free(config->device_name);
+ free(config->channel_x_name);
+ free(config->channel_y_name);
+ free(config->sampling_frequency_name);
+ wl_array_release(&config->allowed_rotations);
+ free(config);
+}
+
+static struct accelerometer *
+initialize_iio(struct config *config)
+{
+ struct accelerometer *accel;
+ int ret;
+
+ accel = zalloc(sizeof *accel);
+ if (!accel)
+ return NULL;
+
+ accel->context = iio_create_local_context();
+ if (!accel->context)
+ goto err_context;
+
+ if (config->device_name)
+ accel->device = iio_context_find_device(accel->context,
+ config->device_name);
+
+ if (!accel->device) {
+ fprintf(stderr, "couldn't find device %s\n",
+ config->device_name);
+ goto err_device;
+ }
+
+ accel->channel_x = iio_device_find_channel(accel->device,
+ config->channel_x_name,
+ false);
+ if (!accel->channel_x) {
+ fprintf(stderr, "couldn't find x channel %s\n",
+ config->channel_x_name);
+ goto err_channel;
+ }
+
+ accel->channel_y = iio_device_find_channel(accel->device,
+ config->channel_y_name,
+ false);
+ if (!accel->channel_y) {
+ fprintf(stderr, "couldn't find y channel %s\n",
+ config->channel_y_name);
+ goto err_channel;
+ }
+
+ if (config->wanted_sampling_frequency) {
+ ret = iio_device_attr_write_double(accel->device,
+ config->sampling_frequency_name,
+ config->wanted_sampling_frequency);
+ if (ret < 0) {
+ fprintf(stderr, "couldn't set sampling frequency to "
+ "%f\n",
+ config->wanted_sampling_frequency);
+ goto err_channel;
+ }
+ }
+
+ ret = iio_device_attr_read_double(accel->device,
+ config->sampling_frequency_name,
+ &accel->sampling_frequency);
+ if (ret < 0) {
+ fprintf(stderr, "couldn't retrieve sampling frequency, "
+ "defaulting to %f\n",
+ DEFAULT_SAMPLING_FREQUENCY);
+ accel->sampling_frequency = DEFAULT_SAMPLING_FREQUENCY;
+ }
+
+ return accel;
+
+err_channel:
+err_device:
+ iio_context_destroy(accel->context);
+err_context:
+ free(accel);
+ return NULL;
+}
+
+static void
+destroy_accelerometer(struct accelerometer *accel)
+{
+ if (accel->context)
+ iio_context_destroy(accel->context);
+ free(accel);
+}
+
+static bool
+capture_rotation(struct accelerometer *accel, int pos)
+{
+ char buf[BUFFER_SIZE];
+ ssize_t ret;
+
+ ret = iio_channel_attr_read(accel->channel_x, "raw", buf, BUFFER_SIZE);
+ if (ret < 0) {
+ iio_strerror(-ret, buf, BUFFER_SIZE);
+ fprintf(stderr, "%s\n", buf);
+ return false;
+ }
+ accel->capture_buffer.x[pos] = atoi(buf);
+
+ ret = iio_channel_attr_read(accel->channel_y, "raw", buf, BUFFER_SIZE);
+ if (ret < 0) {
+ iio_strerror(-ret, buf, BUFFER_SIZE);
+ fprintf(stderr, "%s\n", buf);
+ return false;
+ }
+ accel->capture_buffer.y[pos] = atoi(buf);
+ return true;
+}
+
+static void
+smooth_input(struct accelerometer *accel, int pos, int values_count, int *x, int *y)
+{
+ int i;
+
+ *x = accel->capture_buffer.x[pos];
+ *y = accel->capture_buffer.y[pos];
+
+ if (values_count > 1) {
+ for (i = 1; i < values_count; ++i) {
+ *x += accel->capture_buffer.x[(pos - i) % values_count];
+ *y += accel->capture_buffer.y[(pos - i) % values_count];
+ }
+
+ *x /= values_count;
+ *y /= values_count;
+ }
+}
+
+static int
+get_transform(int x, int y, int threshold)
+{
+ if (y > threshold && y > x)
+ return WESTON_ROTATER_TRANSFORM_NORMAL;
+ if (x > threshold && x > y)
+ return WESTON_ROTATER_TRANSFORM_90;
+ if (y < -threshold && y < x)
+ return WESTON_ROTATER_TRANSFORM_180;
+ if (x < -threshold && x < y)
+ return WESTON_ROTATER_TRANSFORM_270;
+ return -1;
+}
+
+static bool
+synchronize(struct wl_display *display, int sampling_frequency)
+{
+ if (wl_display_roundtrip(display) < 0) {
+ fprintf(stderr, "lost connection, aborting\n");
+ return false;
+ }
+ usleep(1000 * sampling_frequency);
+ return true;
+}
+
+static void
+handle_global(void *data, struct wl_registry *registry,
+ uint32_t name, const char *interface, uint32_t version)
+{
+ static struct rotater_output *output;
+
+ if (strcmp(interface, "wl_output") == 0) {
+ output = xmalloc(sizeof *output);
+ output->output = wl_registry_bind(registry, name,
+ &wl_output_interface, 1);
+ wl_list_insert(&output_list, &output->link);
+ } else if (strcmp(interface, "weston_rotater") == 0) {
+ rotater = wl_registry_bind(registry, name,
+ &weston_rotater_interface,
+ 1);
+ }
+}
+
+static void
+handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
+{
+ /* XXX: unimplemented */
+}
+
+static const struct wl_registry_listener registry_listener = {
+ handle_global,
+ handle_global_remove
+};
+
+int main(int argc, char *argv[])
+{
+ struct wl_display *display;
+ struct wl_registry *registry;
+ struct rotater_output *output;
+ struct config *config;
+ struct accelerometer *accel;
+ bool ret, found;
+ int frame = 0;
+ int x, y;
+ int transform, previous_transform, *allowed_transform;
+
+ if (getenv("WAYLAND_SOCKET") == NULL) {
+ fprintf(stderr, "%s must be launched by weston.\n",
+ program_invocation_short_name);
+ return 1;
+ }
+
+ display = wl_display_connect(NULL);
+ if (display == NULL) {
+ fprintf(stderr, "failed to create display: %m\n");
+ return 2;
+ }
+
+ wl_list_init(&output_list);
+ registry = wl_display_get_registry(display);
+ wl_registry_add_listener(registry, ®istry_listener, NULL);
+ wl_display_dispatch(display);
+ wl_display_roundtrip(display);
+ if (rotater == NULL) {
+ fprintf(stderr, "display doesn't support rotater\n");
+ free(registry);
+ wl_display_disconnect(display);
+ return 3;
+ }
+
+ config = read_configuration();
+ if (!config) {
+ fprintf(stderr, "failed to read configuration\n");
+ free(registry);
+ wl_display_disconnect(display);
+ return 4;
+ }
+
+ accel = initialize_iio(config);
+ if (!accel) {
+ fprintf(stderr, "failed to initialize iio subsystem\n");
+ free(registry);
+ wl_display_disconnect(display);
+ destroy_configuration(config);
+ return 5;
+ }
+
+ previous_transform = WESTON_ROTATER_TRANSFORM_NORMAL;
+ for (;;) {
+ ret = capture_rotation(accel, frame);
+ if (!ret) {
+ fprintf(stderr, "failed to capture accelerometer "
+ "values\n");
+ break;
+ }
+
+ smooth_input(accel, frame, config->smooth_capture, &x, &y);
+
+ transform = get_transform(x, y, config->threshold);
+ if (transform < 0) {
+ if (!synchronize(display, accel->sampling_frequency))
+ return 6;
+ continue;
+ }
+
+ found = false;
+ wl_array_for_each(allowed_transform,
+ &config->allowed_rotations) {
+ if (transform == *allowed_transform) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ if (!synchronize(display, accel->sampling_frequency))
+ return 6;
+ continue;
+ }
+
+ if (transform != previous_transform) {
+ wl_list_for_each(output, &output_list, link) {
+ weston_rotater_rotate(rotater,
+ output->output,
+ transform);
+ }
+ }
+ previous_transform = transform;
+ frame = (frame + 1) % config->smooth_capture;
+
+ if (!synchronize(display, accel->sampling_frequency))
+ return 6;
+ }
+
+ wl_display_disconnect(display);
+ destroy_accelerometer(accel);
+ destroy_configuration(config);
+
+ return 0;
+}
diff --git a/configure.ac b/configure.ac
index e1300b4..61f9eba 100644
--- a/configure.ac
+++ b/configure.ac
@@ -384,6 +384,20 @@ if ! test "x$enable_simple_dmabuf_v4l_client" = "xno"; then
fi
AM_CONDITIONAL(BUILD_SIMPLE_DMABUF_V4L_CLIENT, test "x$enable_simple_dmabuf_v4l_client" = "xyes")
+AC_ARG_ENABLE(weston-autorotater,
+ AS_HELP_STRING([--disable-weston-autorotater],
+ [do not build the autorotater client]),,
+ enable_autorotater="auto")
+if ! test "x$enable_autorotater" = "xno"; then
+ PKG_CHECK_MODULES(LIBIIO, [libiio],
+ have_autorotater=yes, have_autorotater=no)
+ if test "x$have_autorotater" = "xno" -a "x$enable_autorotater" = "xyes"; then
+ AC_MSG_ERROR([autorotater client explicitly enabled, but libiio couldn't be found])
+ fi
+ enable_autorotater="$have_autorotater"
+fi
+AM_CONDITIONAL(BUILD_AUTOROTATER, test "x$enable_autorotater" = "xyes")
+
AC_ARG_ENABLE(clients, [ --enable-clients],, enable_clients=yes)
AM_CONDITIONAL(BUILD_CLIENTS, test x$enable_clients = xyes)
if test x$enable_clients = xyes; then
@@ -688,6 +702,7 @@ AC_MSG_RESULT([
Build EGL Clients ${have_cairo_egl}
Build Simple Clients ${enable_simple_clients}
Build Simple EGL Clients ${enable_simple_egl_clients}
+ Build Autorotater Client ${enable_autorotater}
Install Demo Clients ${enable_demo_clients_install}
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index 7d5bca9..c1750a7 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -6704,6 +6704,7 @@ module_init(struct weston_compositor *ec,
wl_signal_add(&ec->seat_created_signal, &shell->seat_create_listener);
screenshooter_create(ec);
+ rotater_create(ec);
shell_add_bindings(ec, shell);
diff --git a/protocol/weston-rotater.xml b/protocol/weston-rotater.xml
new file mode 100644
index 0000000..90a6f84
--- /dev/null
+++ b/protocol/weston-rotater.xml
@@ -0,0 +1,26 @@
+<protocol name="weston_rotater">
+
+ <interface name="weston_rotater" version="1">
+
+ <enum name="transform">
+ <description summary="copied from wl_output.transform"/>
+ <entry name="normal" value="0"/>
+ <entry name="90" value="1"/>
+ <entry name="180" value="2"/>
+ <entry name="270" value="3"/>
+ <entry name="flipped" value="4"/>
+ <entry name="flipped_90" value="5"/>
+ <entry name="flipped_180" value="6"/>
+ <entry name="flipped_270" value="7"/>
+ </enum>
+
+ <request name="rotate">
+ <arg name="output" type="object" interface="wl_output"/>
+ <arg name="transform" type="int" enum="transform"/>
+ </request>
+
+ <event name="done"/>
+
+ </interface>
+
+</protocol>
diff --git a/src/compositor.h b/src/compositor.h
index 0bbf458..9a211c1 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -1592,6 +1592,9 @@ int
weston_screenshooter_shoot(struct weston_output *output, struct weston_buffer *buffer,
weston_screenshooter_done_func_t done, void *data);
+void
+rotater_create(struct weston_compositor *ec);
+
struct clipboard *
clipboard_create(struct weston_seat *seat);
diff --git a/src/rotater.c b/src/rotater.c
new file mode 100644
index 0000000..4575ac7
--- /dev/null
+++ b/src/rotater.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright © 2016 Collabora, Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <linux/input-event-codes.h>
+
+#include "compositor.h"
+#include "weston-rotater-server-protocol.h"
+#include "shared/helpers.h"
+
+struct rotater {
+ struct weston_compositor *ec;
+ struct wl_global *global;
+ struct wl_client *client;
+ struct weston_process process;
+ struct wl_listener destroy_listener;
+};
+
+static void
+rotater_rotate(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *output_resource,
+ int32_t transform)
+{
+ int32_t current_width;
+ struct weston_output *output =
+ wl_resource_get_user_data(output_resource);
+
+ /* Only swap width and height when the aspect ratio changed. */
+ if ((transform ^ output->transform) & 1) {
+ current_width = output->width;
+ output->width = output->height;
+ output->height = current_width;
+ }
+
+ output->transform = transform;
+ output->dirty = 1;
+ weston_output_damage(output);
+}
+
+struct weston_rotater_interface rotater_implementation = {
+ rotater_rotate
+};
+
+static void
+bind_rotater(struct wl_client *client,
+ void *data, uint32_t version, uint32_t id)
+{
+ struct rotater *rotater = data;
+ struct wl_resource *resource;
+
+ resource = wl_resource_create(client,
+ &weston_rotater_interface, 1, id);
+
+ if (client != rotater->client) {
+ wl_resource_post_error(resource,
+ WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "rotater failed: permission denied");
+ return;
+ }
+
+ wl_resource_set_implementation(resource, &rotater_implementation,
+ data, NULL);
+}
+
+static void
+rotater_sigchld(struct weston_process *process, int status)
+{
+ struct rotater *rotater =
+ container_of(process, struct rotater, process);
+
+ rotater->client = NULL;
+}
+
+static void
+rotater_launch_autorotater(struct rotater *rotater)
+{
+ char *rotater_exe;
+ int ret;
+
+ ret = asprintf(&rotater_exe, "%s/%s",
+ weston_config_get_libexec_dir(),
+ "/weston-autorotater");
+ if (ret < 0) {
+ weston_log("Could not construct rotater path.\n");
+ return;
+ }
+
+ if (!rotater->client)
+ rotater->client = weston_client_launch(rotater->ec,
+ &rotater->process,
+ rotater_exe, rotater_sigchld);
+ free(rotater_exe);
+}
+
+static void
+rotater_destroy(struct wl_listener *listener, void *data)
+{
+ struct rotater *rotater =
+ container_of(listener, struct rotater, destroy_listener);
+
+ wl_global_destroy(rotater->global);
+ free(rotater);
+}
+
+WL_EXPORT void
+rotater_create(struct weston_compositor *ec)
+{
+ struct rotater *rotater;
+
+ rotater = malloc(sizeof *rotater);
+ if (rotater == NULL)
+ return;
+
+ rotater->ec = ec;
+ rotater->client = NULL;
+
+ rotater->global = wl_global_create(ec->wl_display,
+ &weston_rotater_interface, 1,
+ rotater, bind_rotater);
+ rotater->destroy_listener.notify = rotater_destroy;
+ wl_signal_add(&ec->destroy_signal, &rotater->destroy_listener);
+ rotater_launch_autorotater(rotater);
+}
--
2.8.2
More information about the wayland-devel
mailing list