[PATCH 5/6] Add weston-randr application
Quanxian Wang
quanxian.wang at intel.com
Wed Feb 26 19:28:04 PST 2014
Signed-off-by: Quanxian Wang <quanxian.wang at intel.com>
Reviewed-by: Zhang, Xiong Y <xiong.y.zhang at intel.com>
---
clients/Makefile.am | 9 +
clients/wrandr.c | 642 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 651 insertions(+)
create mode 100644 clients/wrandr.c
diff --git a/clients/Makefile.am b/clients/Makefile.am
index 4f8d4a6..cc509e9 100644
--- a/clients/Makefile.am
+++ b/clients/Makefile.am
@@ -60,6 +60,7 @@ libexec_PROGRAMS = \
weston-desktop-shell \
weston-screenshooter \
$(screensaver) \
+ weston-wrandr \
weston-keyboard \
weston-simple-im
@@ -101,6 +102,12 @@ libtoytoolkit_la_LIBADD = \
weston_flower_SOURCES = flower.c
weston_flower_LDADD = libtoytoolkit.la
+weston_wrandr_SOURCES = \
+ wrandr.c \
+ randr-protocol.c \
+ randr-client-protocol.h
+weston_wrandr_LDADD = $(CLIENT_LIBS)
+
weston_screenshooter_SOURCES = \
screenshot.c \
screenshooter-protocol.c \
@@ -211,6 +218,8 @@ BUILT_SOURCES = \
text-cursor-position-protocol.c \
text-protocol.c \
text-client-protocol.h \
+ randr-protocol.c \
+ randr-client-protocol.h \
input-method-protocol.c \
input-method-client-protocol.h \
desktop-shell-client-protocol.h \
diff --git a/clients/wrandr.c b/clients/wrandr.c
new file mode 100644
index 0000000..cc14a8d
--- /dev/null
+++ b/clients/wrandr.c
@@ -0,0 +1,642 @@
+/*
+ * Copyright © 2011 Benjamin Franzke
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+#include <signal.h>
+
+#include "randr-client-protocol.h"
+#include <wayland-client.h>
+#include <wayland-server.h>
+
+#ifndef HZ
+#define HZ 1000
+#endif
+
+static int running = 1;
+
+struct randr {
+ struct wl_display *display;
+ struct wl_registry *registry;
+ struct wl_compositor *compositor;
+ struct wl_randr *randr;
+ struct wl_list output_list;
+};
+
+struct mode {
+ struct wl_list link;
+ int height;
+ int width;
+ int refresh;
+ uint32_t flags;
+};
+
+struct output {
+ struct wl_list link;
+ struct wl_list mode_list;
+ struct randr *randr;
+ struct wl_output *output;
+ char *name;
+ int x;
+ int y;
+ int physical_width;
+ int physical_height;
+ int subpixel;
+ char *make;
+ char *model;
+ int transform;
+ int scale;
+ int server_output_id;
+};
+
+struct argument {
+ char *output;
+ char *leftof;
+ char *rightof;
+ int query;
+ int mode;
+ int transform;
+};
+
+static void
+get_disoutputs(void *data,
+ struct wl_randr *wl_randr,
+ const char *output)
+{
+ running = 0;
+ printf("%s\n", output);
+}
+
+static void
+get_action_done(void *data,
+ struct wl_randr *wl_randr,
+ uint32_t flags,
+ int ret)
+{
+ char *result;
+ char *action;
+
+ switch (ret) {
+ case WL_RANDR_RESULT_FAIL:
+ result = "Fail";
+ break;
+ case WL_RANDR_RESULT_SUCCESS:
+ result = "Success";
+ break;
+ case WL_RANDR_RESULT_NOACT:
+ result = "Same as before, no action happens.";
+ break;
+ default:
+ result = "Success";
+ }
+
+ if (flags & (1<<WL_RANDR_ACTION_MOVE))
+ action = "MOVING:";
+ else if (flags & (1<<WL_RANDR_ACTION_TRANSFORM))
+ action = "TRANSFORM:";
+ else if (flags & (1<<WL_RANDR_ACTION_MODE))
+ action = "MODE:";
+
+ printf("%s %s\n", action, result);
+
+ running = 0;
+}
+
+static void
+get_output_name(void *data,
+ struct wl_randr *wl_randr,
+ struct wl_output *output,
+ const char *name)
+{
+ struct randr *randr = data;
+ struct output *randr_output;
+
+ wl_list_for_each(randr_output, &randr->output_list, link)
+ if (randr_output->output == output)
+ randr_output->name = strdup(name);
+}
+
+static const struct wl_randr_listener wrandr_listener = {
+ get_output_name,
+ get_action_done,
+ get_disoutputs
+};
+
+static void
+output_handle_geometry(void *data,
+ struct wl_output *wl_output,
+ int x, int y,
+ int physical_width,
+ int physical_height,
+ int subpixel,
+ const char *make,
+ const char *model,
+ int transform)
+{
+ struct output *output = data;
+
+ output->output = wl_output;
+ output->x = x;
+ output->y = y;
+ output->physical_height = physical_height;
+ output->physical_width = physical_width;
+ output->subpixel = subpixel;
+ output->make = strdup(make);
+ output->model = strdup(model);
+ output->transform = transform;
+}
+
+static void
+output_handle_done(void *data,
+ struct wl_output *wl_output)
+{
+}
+
+static void
+output_handle_scale(void *data,
+ struct wl_output *wl_output,
+ int32_t scale)
+{
+ struct output *output = data;
+
+ output->scale = scale;
+}
+
+static void
+output_handle_mode(void *data,
+ struct wl_output *wl_output,
+ uint32_t flags,
+ int width,
+ int height,
+ int refresh)
+{
+ struct output *output = data;
+ struct mode *mode;
+
+ wl_list_for_each(mode, &output->mode_list, link) {
+ if (mode->width == width &&
+ mode->height == height &&
+ mode->refresh == refresh) {
+ if (flags != mode->flags)
+ mode->flags = flags;
+ return;
+ }
+ }
+
+ mode = (struct mode *)malloc(sizeof(*mode));
+ if (!mode)
+ return;
+
+ mode->width = width;
+ mode->height = height;
+ mode->refresh = refresh;
+ mode->flags = flags;
+
+ wl_list_insert(output->mode_list.prev, &mode->link);
+}
+
+static const struct wl_output_listener output_listener = {
+ output_handle_geometry,
+ output_handle_mode,
+ output_handle_done,
+ output_handle_scale
+};
+
+static void
+randr_add_output(struct randr *randr, uint32_t id)
+{
+ struct output *output;
+
+ output = (struct output *)malloc(sizeof(*output));
+ if (!output)
+ return;
+
+ output->randr = randr;
+ output->scale = 1;
+ output->name = NULL;
+ output->output = wl_registry_bind(randr->registry,
+ id,
+ &wl_output_interface,
+ 2);
+ output->server_output_id = id;
+
+ wl_list_init(&output->mode_list);
+ wl_list_insert(randr->output_list.prev, &output->link);
+
+ wl_output_add_listener(output->output, &output_listener, output);
+}
+
+static void
+mode_destroy(struct mode *mode)
+{
+ wl_list_remove(&mode->link);
+ free(mode);
+}
+
+static void
+output_destroy(struct output *output)
+{
+ struct mode *mode;
+
+ wl_list_for_each(mode, &output->mode_list, link)
+ mode_destroy(mode);
+
+ wl_list_remove(&output->link);
+
+ free(output->name);
+ free(output->make);
+ free(output->model);
+ free(output);
+}
+
+static void
+randr_destroy_output(struct randr *randr)
+{
+ struct output *output;
+
+ wl_list_for_each(output, &randr->output_list, link)
+ output_destroy(output);
+}
+
+static void
+registry_handle_global(void *data, struct wl_registry *registry, uint32_t id,
+ const char *interface, uint32_t version)
+{
+ struct randr *randr = data;
+
+ if (strcmp(interface, "wl_randr") == 0) {
+ randr->randr = wl_registry_bind(registry, id,
+ &wl_randr_interface,
+ 1);
+ wl_randr_add_listener(randr->randr,
+ &wrandr_listener, randr);
+ } else if (strcmp(interface, "wl_compositor") == 0) {
+ randr->compositor = wl_registry_bind(registry, id,
+ &wl_compositor_interface,
+ 3);
+ } else if (strcmp(interface, "wl_output") == 0) {
+ randr_add_output(randr, id);
+ }
+}
+
+static void
+registry_handle_global_remove(void *data,
+ struct wl_registry *registry,
+ uint32_t name)
+{
+ struct randr *randr = data;
+
+ randr_destroy_output(randr);
+}
+
+static const struct wl_registry_listener registry_listener = {
+ registry_handle_global,
+ registry_handle_global_remove
+};
+
+static void
+transform_usage(void)
+{
+ fprintf(stderr,
+ " -R (0-7)\n"
+ " 0: TRANSFORM NORMAL\n"
+ " 1: TRANSFORM 90\n"
+ " 2: TRANSFORM 180\n"
+ " 3: TRANSFORM 270\n"
+ " 4: TRANSFORM FLIP 0\n"
+ " 5: TRANSFORM FLIP 90\n"
+ " 6: TRANSFORM FLIP 180\n"
+ " 7: TRANSFORM FLIP 270\n");
+}
+
+static void
+usage(int error_code)
+{
+ fprintf(stderr, "Usage: weston-randr [OPTIONS]\n\n"
+ " --leftof \tleft output\n"
+ " --rightof \tright output\n"
+ " --output \ttarget output\n"
+ " -q \tquery all outputs\n"
+ " -m \tthe number of mode to be set"
+ "(Firstly use -q to get mode list and find number).\n"
+ " -R \toutput trasform(0-7)\n"
+ " -h\tThis help text\n\n");
+
+ transform_usage();
+ exit(error_code);
+}
+
+static void
+randr_init(struct randr *randr)
+{
+ wl_list_init(&randr->output_list);
+ randr->display = wl_display_connect(NULL);
+ assert(randr->display);
+
+ randr->registry = wl_display_get_registry(randr->display);
+ wl_registry_add_listener(randr->registry,
+ ®istry_listener, randr);
+
+ wl_display_dispatch(randr->display);
+}
+
+static void
+randr_query(struct randr *randr)
+{
+ struct output *output;
+ struct mode *mode;
+ char *state;
+ int i;
+
+ wl_list_for_each(output, &randr->output_list, link) {
+ printf("%s\n", output->name);
+ i = 1;
+
+ wl_list_for_each(mode, &output->mode_list, link) {
+ if (mode->flags & WL_OUTPUT_MODE_CURRENT)
+ state = "(current)";
+ else if (mode->flags & WL_OUTPUT_MODE_PREFERRED)
+ state = "(preferred)";
+ else
+ state = "";
+
+ printf("%d)%dx%d@%d%s\n",
+ i++,
+ mode->width,
+ mode->height,
+ (mode->refresh + HZ/2)/HZ,
+ state);
+ }
+ printf("\n");
+ }
+
+ wl_randr_get_disoutputs(randr->randr);
+}
+
+static void
+randr_set_mode(struct randr *randr,
+ struct wl_output *wayland_output,
+ struct output *target_output, int num)
+{
+ int found = 0;
+ int i = 0;
+ struct mode *mode;
+
+ wl_list_for_each(mode, &target_output->mode_list, link) {
+ i++;
+ if (i == num) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (found) {
+ wl_randr_set_mode(randr->randr,
+ wayland_output,
+ mode->width,
+ mode->height,
+ mode->refresh);
+ } else {
+ printf("Mode parameter exceeds max mode number %d.\n", i);
+ running = 0;
+ }
+}
+
+static void
+randr_query_mode(struct output *target_output)
+{
+ struct mode *mode;
+ char *state;
+ int i = 1;
+
+ printf("%s\n", target_output->name);
+ wl_list_for_each(mode, &target_output->mode_list, link) {
+ if (mode->flags & WL_OUTPUT_MODE_CURRENT)
+ state = "(current)";
+ else if (mode->flags & WL_OUTPUT_MODE_PREFERRED)
+ state = "(preferred)";
+ else
+ state = "";
+ printf("%d)%dx%d@%d%s\n",
+ i++,
+ mode->width,
+ mode->height,
+ (mode->refresh + HZ/2)/HZ,
+ state);
+ }
+}
+
+static int
+is_digit(const char *str)
+{
+ int len = strlen(str);
+
+ while (len > 0) {
+ if (*str < '0' || *str > '9')
+ return -1;
+ str++;
+ len--;
+ }
+
+ return 0;
+}
+
+static void
+parse_args(struct argument *argument, int argc, char **argv)
+{
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ if (strcmp("--output", argv[i]) == 0) {
+ if ((i + 1) >= argc) {
+ printf("output should have parameter.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ argument->output = strdup(argv[++i]);
+ } else if (strcmp("--leftof", argv[i]) == 0) {
+ if ((i + 1) >= argc) {
+ printf("leftof should have parameter.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ argument->leftof = strdup(argv[++i]);
+ } else if (strcmp("--rightof", argv[i]) == 0) {
+ if ((i + 1) >= argc) {
+ printf("rightof should have parameter.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ argument->rightof = strdup(argv[++i]);
+ } else if (strcmp("-q", argv[i]) == 0)
+ argument->query = 1;
+ else if (strcmp("-R", argv[i]) == 0) {
+ if ((i + 1) >= argc) {
+ printf("-R should have numeric parameter.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (is_digit(argv[i + 1]) == 0) {
+ argument->transform =
+ atoi(argv[++i]);
+ if (argument->transform <= 7)
+ continue;
+ }
+
+ printf("-R parameter should be numeric(0-7).\n");
+ transform_usage();
+ exit(EXIT_FAILURE);
+ } else if (strcmp("-m", argv[i]) == 0) {
+ if ((i + 1) >= argc) {
+ printf("-m should have numeric parameter.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (is_digit(argv[i + 1]) == 0) {
+ argument->mode =
+ atoi(argv[++i]);
+ continue;
+ }
+
+ printf("-m parameter should be numeric.\n");
+ exit(EXIT_FAILURE);
+ } else if (strcmp("-h", argv[i]) == 0)
+ usage(EXIT_SUCCESS);
+ else
+ usage(EXIT_FAILURE);
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ struct randr randr = { 0 };
+ struct argument argument = {NULL, NULL, NULL, -1, -1, -1};
+ int ret = 0;
+ struct output *output, *target_output;
+ struct wl_output *left_output = NULL;
+ struct wl_output *right_output = NULL;
+ struct wl_output *wayland_output = NULL;
+
+ parse_args(&argument, argc, argv);
+
+ randr_init(&randr);
+
+ /* Get output name for every wl_output. */
+ wl_list_for_each(output, &randr.output_list, link) {
+ wl_randr_get_output_name(randr.randr, output->output);
+
+ while (!output->name && ret != -1)
+ ret = wl_display_dispatch(randr.display);
+ }
+
+ /* Currently we got the randr handle. */
+ if (argument.query > 0) {
+ randr_query(&randr);
+ goto wait;
+ }
+
+ wl_list_for_each(output, &randr.output_list, link) {
+ if (argument.leftof &&
+ !strcmp(output->name, argument.leftof))
+ left_output = output->output;
+
+ if (argument.rightof &&
+ !strcmp(output->name, argument.rightof))
+ right_output = output->output;
+
+ if (argument.output &&
+ !strcmp(output->name, argument.output)) {
+ target_output = output;
+ wayland_output = output->output;
+ }
+ }
+
+ if (!wayland_output) {
+ printf("%s does not exists or not connected.\n",
+ argument.output);
+ goto exit;
+ }
+
+ if (argument.mode > 0 && target_output) {
+ randr_set_mode(&randr,
+ wayland_output,
+ target_output,
+ argument.mode);
+ goto wait;
+ }
+
+ if (argument.transform >= 0 && wayland_output) {
+ wl_randr_set_transform(randr.randr,
+ wayland_output,
+ argument.transform);
+ goto wait;
+ }
+
+ if (argument.leftof && wayland_output) {
+ if (!left_output) {
+ printf("%s not exists\n", argument.leftof);
+ goto exit;
+ }
+
+ wl_randr_move(randr.randr,
+ wayland_output,
+ left_output,
+ WL_RANDR_MOVE_LEFTOF);
+
+ goto wait;
+ }
+
+ if (argument.rightof && wayland_output) {
+ if (!right_output) {
+ printf("%s not exists\n", argument.rightof);
+ goto exit;
+ }
+
+ wl_randr_move(randr.randr,
+ wayland_output,
+ right_output,
+ WL_RANDR_MOVE_RIGHTOF);
+
+ goto wait;
+ }
+
+ if (target_output) {
+ /* List modes of target output. */
+ randr_query_mode(target_output);
+ goto exit;
+ }
+
+wait:
+ while (running && ret != -1)
+ ret = wl_display_dispatch(randr.display);
+
+exit:
+ wl_registry_destroy(randr.registry);
+ wl_display_flush(randr.display);
+ wl_display_disconnect(randr.display);
+
+ return 0;
+}
--
1.8.1.2
More information about the wayland-devel
mailing list