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. v2: - Rename rotater to rotator, which is actual English. - Add documentation for every new option, and a default value. - Add the bare minimum of those options in the sample weston.ini. - Fix for an inaccurate sampling frequency due to integer downcasting. - Make the server-side a module instead of a simple function that has to be called by every shell. - Remove the mostly-useless smoothing of the captured input. - Make the protocol take an accelerometer name, to let the rotator match its name with the outputs using it. Signed-off-by: Emmanuel Gil Peyrot <[email protected]> --- .gitignore | 1 + Makefile.am | 28 +++ clients/autorotator.c | 435 ++++++++++++++++++++++++++++++++++++++++++++ compositor/rotator.c | 246 +++++++++++++++++++++++++ configure.ac | 15 ++ libweston/compositor.c | 1 + libweston/compositor.h | 1 + man/weston.ini.man | 41 +++++ protocol/weston-rotator.xml | 26 +++ weston.ini.in | 4 + 10 files changed, 798 insertions(+) create mode 100644 clients/autorotator.c create mode 100644 compositor/rotator.c create mode 100644 protocol/weston-rotator.xml diff --git a/.gitignore b/.gitignore index 41a140b..72cea9f 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ protocol/*.[ch] 00*.patch +weston-autorotator weston-calibrator weston-clickdot weston-cliptest diff --git a/Makefile.am b/Makefile.am index 32627f5..0e990ab 100644 --- a/Makefile.am +++ b/Makefile.am @@ -124,6 +124,8 @@ endif nodist_libweston_@LIBWESTON_MAJOR@_la_SOURCES = \ protocol/weston-screenshooter-protocol.c \ protocol/weston-screenshooter-server-protocol.h \ + protocol/weston-rotator-protocol.c \ + protocol/weston-rotator-server-protocol.h \ protocol/text-cursor-position-protocol.c \ protocol/text-cursor-position-server-protocol.h \ protocol/text-input-unstable-v1-protocol.c \ @@ -610,6 +612,32 @@ nodist_weston_screenshooter_SOURCES = \ weston_screenshooter_LDADD = $(CLIENT_LIBS) libshared.la weston_screenshooter_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS) +if BUILD_AUTOROTATOR +libexec_PROGRAMS += weston-autorotator + +weston_autorotator_SOURCES = \ + clients/autorotator.c +nodist_weston_autorotator_SOURCES = \ + protocol/weston-rotator-protocol.c \ + protocol/weston-rotator-client-protocol.h +weston_autorotator_LDADD = $(CLIENT_LIBS) $(LIBIIO_LIBS) libshared.la +weston_autorotator_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS) $(LIBIIO_CFLAGS) + +module_LTLIBRARIES += rotator.la +rotator_la_LDFLAGS = -module -avoid-version +rotator_la_LIBADD = $(COMPOSITOR_LIBS) libshared.la +rotator_la_CFLAGS = $(AM_CFLAGS) $(COMPOSITOR_CFLAGS) +rotator_la_SOURCES = \ + compositor/rotator.c + +BUILT_SOURCES += \ + protocol/weston-rotator-protocol.c \ + protocol/weston-rotator-client-protocol.h + +EXTRA_DIST += \ + protocol/weston-rotator.xml +endif + weston_terminal_SOURCES = \ clients/terminal.c \ shared/helpers.h diff --git a/clients/autorotator.c b/clients/autorotator.c new file mode 100644 index 0000000..89697c9 --- /dev/null +++ b/clients/autorotator.c @@ -0,0 +1,435 @@ +/* + * 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-rotator-client-protocol.h" +#include "shared/config-parser.h" +#include "shared/helpers.h" +#include "shared/xalloc.h" + +#include <iio.h> + +#define BUFFER_SIZE 16 + +static struct weston_rotator *rotator; + +#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; + struct wl_array allowed_rotations; +}; + +struct accelerometer { + struct iio_context *context; + struct iio_device *device; + struct iio_channel *channel_x, *channel_y; + double sampling_frequency; +}; + +static const struct { + const char *name; + int token; +} transforms[] = { + { "normal", WESTON_ROTATOR_TRANSFORM_NORMAL }, + { "90", WESTON_ROTATOR_TRANSFORM_90 }, + { "180", WESTON_ROTATOR_TRANSFORM_180 }, + { "270", WESTON_ROTATOR_TRANSFORM_270 }, + { "flipped", WESTON_ROTATOR_TRANSFORM_FLIPPED }, + { "flipped-90", WESTON_ROTATOR_TRANSFORM_FLIPPED_90 }, + { "flipped-180", WESTON_ROTATOR_TRANSFORM_FLIPPED_180 }, + { "flipped-270", WESTON_ROTATOR_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(const char *device_name) +{ + 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; + + config_file = weston_config_get_name_from_env(); + config = weston_config_parse(config_file); + if (config == NULL) + return NULL; + + s = weston_config_get_section(config, "accelerometer", "name", device_name); + if (s == NULL) { + weston_config_destroy(config); + return NULL; + } + + configuration = zalloc(sizeof *configuration); + if (!configuration) { + weston_config_destroy(config); + return NULL; + } + + weston_config_section_get_string(s, "name", + &configuration->device_name, NULL); + weston_config_section_get_string(s, "channel_x", + &configuration->channel_x_name, "accel_x"); + weston_config_section_get_string(s, "channel_y", + &configuration->channel_y_name, "accel_y"); + weston_config_section_get_string(s, "sampling_frequency_attr", + &configuration->sampling_frequency_name, + "accel_sampling_frequency"); + weston_config_section_get_double(s, "wanted_sampling_frequency", + &configuration->wanted_sampling_frequency, + 0.); + weston_config_section_get_int(s, "threshold", + &configuration->threshold, 128); + weston_config_section_get_string(s, "allowed_rotations", + &allowed_rotations, NULL); + + weston_config_destroy(config); + + 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_ROTATOR_TRANSFORM_NORMAL; + array_items[1] = WESTON_ROTATOR_TRANSFORM_90; + array_items[2] = WESTON_ROTATOR_TRANSFORM_180; + array_items[3] = WESTON_ROTATOR_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 *x, int *y) +{ + 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; + } + *x = 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; + } + *y = atoi(buf); + return true; +} + +static int +get_transform(int x, int y, int threshold) +{ + if (y > threshold && y > x) + return WESTON_ROTATOR_TRANSFORM_NORMAL; + if (x > threshold && x > y) + return WESTON_ROTATOR_TRANSFORM_90; + if (y < -threshold && y < x) + return WESTON_ROTATOR_TRANSFORM_180; + if (x < -threshold && x < y) + return WESTON_ROTATOR_TRANSFORM_270; + return -1; +} + +static bool +synchronize(struct wl_display *display, double 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) +{ + if (strcmp(interface, "weston_rotator") == 0) { + rotator = wl_registry_bind(registry, name, + &weston_rotator_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 config *config; + struct accelerometer *accel; + const char *accelerometer_device; + bool ret, found; + 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; + } + + accelerometer_device = getenv("WESTON_ACCELEROMETER"); + if (accelerometer_device == NULL) { + fprintf(stderr, "Weston must pass an accelerometer device.\n"); + return 2; + } + + config = read_configuration(accelerometer_device); + if (!config) { + fprintf(stderr, "failed to read configuration\n"); + return 3; + } + + display = wl_display_connect(NULL); + if (display == NULL) { + fprintf(stderr, "failed to create display: %m\n"); + destroy_configuration(config); + return 4; + } + + registry = wl_display_get_registry(display); + wl_registry_add_listener(registry, ®istry_listener, NULL); + wl_display_dispatch(display); + wl_display_roundtrip(display); + if (rotator == NULL) { + fprintf(stderr, "display doesn't support rotator\n"); + free(registry); + wl_display_disconnect(display); + destroy_configuration(config); + return 5; + } + + accel = initialize_iio(config); + if (!accel) { + fprintf(stderr, "failed to initialize iio subsystem\n"); + free(registry); + wl_display_disconnect(display); + destroy_configuration(config); + return 6; + } + + previous_transform = WESTON_ROTATOR_TRANSFORM_NORMAL; + for (;;) { + ret = capture_rotation(accel, &x, &y); + if (!ret) { + fprintf(stderr, "failed to capture accelerometer " + "values\n"); + break; + } + + transform = get_transform(x, y, config->threshold); + if (transform < 0) { + if (!synchronize(display, accel->sampling_frequency)) + return 7; + 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 7; + continue; + } + + if (transform != previous_transform) { + weston_rotator_rotate(rotator, + accelerometer_device, + transform); + } + previous_transform = transform; + + if (!synchronize(display, accel->sampling_frequency)) + return 7; + } + + wl_display_disconnect(display); + destroy_accelerometer(accel); + destroy_configuration(config); + + return 0; +} diff --git a/compositor/rotator.c b/compositor/rotator.c new file mode 100644 index 0000000..c823205 --- /dev/null +++ b/compositor/rotator.c @@ -0,0 +1,246 @@ +/* + * 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 <string.h> +#include <linux/input-event-codes.h> + +#include "compositor.h" +#include "weston-rotator-server-protocol.h" +#include "weston.h" +#include "shared/helpers.h" +#include "shared/zalloc.h" + +struct autorotator_process { + char *accelerometer; + struct wl_client *client; + struct weston_process process; + struct wl_list link; +}; + +struct rotator { + struct weston_compositor *ec; + struct wl_global *global; + struct wl_list process_list; + struct wl_listener destroy_listener; +}; + +static void +rotator_rotate(struct wl_client *client, + struct wl_resource *resource, + const char *accelerometer_device, + int32_t transform) +{ + struct rotator *rotator = wl_resource_get_user_data(resource); + int32_t current_width; + struct weston_output *output; + struct weston_mode *mode; + + wl_list_for_each(output, &rotator->ec->output_list, link) { + if (!output->accelerometer || strcmp(accelerometer_device, output->accelerometer) != 0) + continue; + + output->transform = transform; + output->dirty = 1; + + /* Only swap width and height when the aspect ratio changed. */ + mode = output->current_mode; + if ((transform ^ output->transform) & 1) { + current_width = mode->width; + mode->width = mode->height; + mode->height = current_width; + weston_output_mode_set_native(output, mode, output->current_scale); + } + + weston_output_damage(output); + } +} + +struct weston_rotator_interface rotator_implementation = { + rotator_rotate +}; + +static void +bind_rotator(struct wl_client *client, + void *data, uint32_t version, uint32_t id) +{ + struct rotator *rotator = data; + struct autorotator_process *process; + struct wl_resource *resource; + bool found; + + resource = wl_resource_create(client, + &weston_rotator_interface, 1, id); + + found = false; + wl_list_for_each(process, &rotator->process_list, link) + if (client == process->client) + found = true; + if (!found) { + wl_resource_post_error(resource, + WL_DISPLAY_ERROR_INVALID_OBJECT, + "rotator failed: permission denied"); + return; + } + + wl_resource_set_implementation(resource, &rotator_implementation, + data, NULL); +} + +static void +rotator_sigchld(struct weston_process *process, int status) +{ + struct autorotator_process *autorotator_process = + container_of(process, struct autorotator_process, process); + + autorotator_process->client = NULL; +} + +static void +rotator_launch_autorotator(struct rotator *rotator) +{ + struct autorotator_process *process; + char *rotator_exe; + int ret; + + const char *old_device = getenv("WESTON_ACCELEROMETER"); + + ret = asprintf(&rotator_exe, "%s/%s", + weston_config_get_libexec_dir(), + "weston-autorotator"); + if (ret < 0) { + weston_log("Could not construct rotator path.\n"); + return; + } + + wl_list_for_each(process, &rotator->process_list, link) { + setenv("WESTON_ACCELEROMETER", process->accelerometer, 1); + process->client = weston_client_launch(rotator->ec, + &process->process, + rotator_exe, + rotator_sigchld); + } + free(rotator_exe); + + if (old_device) + setenv("WESTON_ACCELEROMETER", old_device, 1); + else + unsetenv("WESTON_ACCELEROMETER"); +} + +static void +rotator_destroy(struct wl_listener *listener, void *data) +{ + struct weston_output *output; + struct autorotator_process *process, *next; + struct rotator *rotator = + container_of(listener, struct rotator, destroy_listener); + + wl_list_for_each(output, &rotator->ec->output_list, link) + free(output->accelerometer); + + wl_list_for_each_safe(process, next, &rotator->process_list, link) { + free(process->accelerometer); + free(process); + } + + wl_global_destroy(rotator->global); + free(rotator); +} + +static bool +read_configuration(struct rotator *rotator) +{ + const char *config_file; + struct weston_config *config; + struct weston_config_section *section = NULL; + struct weston_output *output; + struct autorotator_process *process; + const char *section_name; + char *output_name, *accelerometer_name; + + config_file = weston_config_get_name_from_env(); + config = weston_config_parse(config_file); + if (config == NULL) + return false; + + while (weston_config_next_section(config, §ion, §ion_name)) { + if (strcmp(section_name, "output") == 0) { + weston_config_section_get_string(section, "name", &output_name, NULL); + if (output_name == NULL) + continue; + weston_config_section_get_string(section, "accelerometer", &accelerometer_name, NULL); + wl_list_for_each(output, &rotator->ec->output_list, link) + if (output->name && strcmp(output->name, output_name) == 0) { + output->accelerometer = accelerometer_name; //TODO: free at deletion? + break; + } + free(output_name); + } else if (strcmp(section_name, "accelerometer") == 0) { + weston_config_section_get_string(section, "name", &accelerometer_name, NULL); + if (accelerometer_name == NULL) + continue; + process = zalloc(sizeof *process); + if (process == NULL) + return false; + process->accelerometer = accelerometer_name; + wl_list_insert(&rotator->process_list, &process->link); + } + } + + weston_config_destroy(config); + + return true; +} + +WL_EXPORT int +module_init(struct weston_compositor *ec, int *argc, char *argv[]) +{ + struct rotator *rotator; + + rotator = zalloc(sizeof *rotator); + if (rotator == NULL) + return -1; + + rotator->ec = ec; + wl_list_init(&rotator->process_list); + + if (!read_configuration(rotator)) + return -1; + + rotator->global = wl_global_create(ec->wl_display, + &weston_rotator_interface, 1, + rotator, bind_rotator); + rotator->destroy_listener.notify = rotator_destroy; + wl_signal_add(&ec->destroy_signal, &rotator->destroy_listener); + + rotator_launch_autorotator(rotator); + + return 0; +} diff --git a/configure.ac b/configure.ac index 74f931d..186fc25 100644 --- a/configure.ac +++ b/configure.ac @@ -379,6 +379,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-autorotator, + AS_HELP_STRING([--disable-weston-autorotator], + [do not build the autorotator client]),, + enable_autorotator="auto") +if ! test "x$enable_autorotator" = "xno"; then + PKG_CHECK_MODULES(LIBIIO, [libiio], + have_autorotator=yes, have_autorotator=no) + if test "x$have_autorotator" = "xno" -a "x$enable_autorotator" = "xyes"; then + AC_MSG_ERROR([autorotator client explicitly enabled, but libiio couldn't be found]) + fi + enable_autorotator="$have_autorotator" +fi +AM_CONDITIONAL(BUILD_AUTOROTATOR, test "x$enable_autorotator" = "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 @@ -685,6 +699,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 Auto-rotator Client ${enable_autorotator} Install Demo Clients ${enable_demo_clients_install} diff --git a/libweston/compositor.c b/libweston/compositor.c index b17c76d..75c2d2f 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -4113,6 +4113,7 @@ weston_output_destroy(struct weston_output *output) wl_signal_emit(&output->destroy_signal, output); free(output->name); + free(output->accelerometer); pixman_region32_fini(&output->region); pixman_region32_fini(&output->previous_damage); output->compositor->output_id_pool &= ~(1u << output->id); diff --git a/libweston/compositor.h b/libweston/compositor.h index 0133084..9cf5c19 100644 --- a/libweston/compositor.h +++ b/libweston/compositor.h @@ -240,6 +240,7 @@ struct weston_output { uint16_t *b); struct weston_timeline_object timeline; + char *accelerometer; }; enum weston_pointer_motion_mask { diff --git a/man/weston.ini.man b/man/weston.ini.man index 7aa7810..a527707 100644 --- a/man/weston.ini.man +++ b/man/weston.ini.man @@ -412,6 +412,47 @@ multiheaded environment with a single compositor for multiple output and input configurations. The default seat is called "default" and will always be present. This seat can be constrained like any other. .RE +.TP 7 +.BI "accelerometer=" device +The name of an accelerometer corresponding to an accelerometer section, which +will be used to make this particular output rotate. +.RE +.SH "ACCELEROMETER SECTION" +There can be multiple accelerometer sections, each corresponding to one +accelerometer device. Each one should be listed in at least one output section +in order to have any effect, to select which outputs it will rotate. +.TP 7 +.BI "name=" device +defines the device that will be used for this accelerometer. Must be the same +string as the accelerometer field in an output section. +.RE +.TP 7 +.BI "channel_x=" attribute +sets the iio channel that will be used as the horizontal value. By default, +this channel is named accel_x. +.RE +.TP 7 +.BI "channel_y=" attribute +sets the iio channel that will be used as the vertical value. By default, this +channel is named accel_y. +.RE +.TP 7 +.BI "sampling_frequency_attr=" attribute +sets the iio channel that will be used to set the desired sampling frequency. +By default, this channel is named accel_sampling_frequency. +.RE +.TP 7 +.BI "sampling_frequency=" number +sets the target sampling frequency, for the sampling_frequency_attr. If there +is any error while setting it, the current value will be used instead. +.RE +.TP 7 +.BI "allowed_rotations=" list +restricts the allowed rotation configurations, list can take up to four +space-separated values, selected from “normal”, “90”, “180” and “270”. Any +value not listed in list will disallow this rotation, and the absence of this +option will allow all four of them. +.RE .SH "INPUT-METHOD SECTION" .TP 7 .BI "path=" "/usr/libexec/weston-keyboard" diff --git a/protocol/weston-rotator.xml b/protocol/weston-rotator.xml new file mode 100644 index 0000000..37f027a --- /dev/null +++ b/protocol/weston-rotator.xml @@ -0,0 +1,26 @@ +<protocol name="weston_rotator"> + + <interface name="weston_rotator" 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="accelerometer" type="string"/> + <arg name="transform" type="int" enum="transform"/> + </request> + + <event name="done"/> + + </interface> + +</protocol> diff --git a/weston.ini.in b/weston.ini.in index 14a4c0c..5e36e5f 100644 --- a/weston.ini.in +++ b/weston.ini.in @@ -46,6 +46,7 @@ path=@libexecdir@/weston-keyboard #mode=1680x1050 #transform=90 #icc_profile=/usr/share/color/icc/colord/Bluish.icc +#accelerometer=iio:device0 #[output] #name=VGA1 @@ -65,6 +66,9 @@ path=@libexecdir@/weston-keyboard #min_accel_factor = 0.16 #max_accel_factor = 1.0 +#[accelerometer] +#device=iio:device0 + [screen-share] command=@bindir@/weston --backend=rdp-backend.so --shell=fullscreen-shell.so --no-clients-resize -- 2.9.2 _______________________________________________ wayland-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/wayland-devel
