[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,
+				 &registry_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