[PATCH weston] clients: Add a weston-autorotater client and rotater protocol
Pekka Paalanen
ppaalanen at gmail.com
Mon May 23 09:00:13 UTC 2016
On Sat, 21 May 2016 03:43:04 +0100
Emmanuel Gil Peyrot <emmanuel.peyrot at collabora.com> wrote:
> 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
Hi Emmanuel,
why is there a new client for this? Could it not be a plugin?
Is IIO potentially so slow and blocking we cannot use it in the server
process?
Why the polling approach, cannot IIO deliver events?
Should there be a way to set which outputs get rotated by a specific
IIO device, rather than assuming there is just one device rotating all
outputs at once?
Any reason why this is limited to desktop-shell rather than being a
shell-agnostic feature?
Thanks,
pq
>
> 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);
> +}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 811 bytes
Desc: OpenPGP digital signature
URL: <https://lists.freedesktop.org/archives/wayland-devel/attachments/20160523/e25202bf/attachment-0001.sig>
More information about the wayland-devel
mailing list