[PATCH V2 7/8] Apps: Add weston-randr application

Quanxian Wang quanxian.wang at intel.com
Mon Mar 24 04:39:19 PDT 2014


Functions implemented in this application
1) Query output mode list
2) Update properties of output (transform, scale, mode setting)
3) Position of output (leftof and rightof are supported.)
4) Custom a mode for output.
5) Delete mode of output.
6) Combination of above 2-5 in one shot.

Note:
Does not support operations on multiple outputs in one time.

More details, please run "weston-wrandr -h"

Signed-off-by: Quanxian Wang <quanxian.wang at intel.com>
---
 clients/Makefile.am |   9 +
 clients/wrandr.c    | 862 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 871 insertions(+)
 create mode 100644 clients/wrandr.c

diff --git a/clients/Makefile.am b/clients/Makefile.am
index 4f8d4a6..757dba3 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 = libtoytoolkit.la $(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..86e58a1
--- /dev/null
+++ b/clients/wrandr.c
@@ -0,0 +1,862 @@
+/*
+ * Copyright © 2014 Quanxian Wang
+ * Copyright © 2014 Intel Corporation
+
+ * 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>
+#include "../shared/config-parser.h"
+
+#ifndef HZ
+#define HZ 1000
+#endif
+
+#define ARRAY_LENGTH(a) (sizeof(a) / sizeof(a)[0])
+
+enum randr_status {
+	RANDR_EXIT = 0,
+	RANDR_COMMIT = 1,
+};
+
+static int running = 1;
+
+struct output;
+struct mode;
+
+struct randr {
+	struct wl_display *display;
+	struct wl_registry *registry;
+	struct wl_compositor *compositor;
+	struct weston_randr *randr;
+	struct wl_list output_list;
+	struct wl_output *loutput;
+	struct wl_output *routput;
+	struct output *output;
+	struct wl_output *wayland_output;
+	struct mode *delmode;
+	struct mode *mode;
+	struct {
+		int clock;
+		int hdisplay;
+		int hsync_start;
+		int hsync_end;
+		int htotal;
+		int vdisplay;
+		int vsync_start;
+		int vsync_end;
+		int vtotal;
+		char hsync[128];
+		char vsync[128];
+	} newmode;
+	struct wrandr_callback *callback;
+};
+
+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;
+	char *mode;
+	char *newmode;
+	char *delmode;
+	int query;
+	int scale;
+	int transform;
+	int help;
+};
+
+static void
+delete_argument(struct argument *argument)
+{
+	if (argument->output)
+		free(argument->output);
+
+	if (argument->leftof)
+		free(argument->leftof);
+
+	if (argument->rightof)
+		free(argument->rightof);
+
+	if (argument->mode)
+		free(argument->mode);
+
+	if (argument->newmode)
+		free(argument->newmode);
+
+	if (argument->delmode)
+		free(argument->delmode);
+}
+
+#define RESULT_MASK 0x3
+
+static void
+print_line(int flags, int results, int flag, char *name)
+{
+	if (!(flags & 1<<flag))
+		return;
+
+	printf("%s:", name);
+	switch (results>>(flag * 2) & RESULT_MASK) {
+	case WRANDR_CALLBACK_RESULT_SUCCESS:
+		printf("SUCCESS!\n");
+		break;
+	case WRANDR_CALLBACK_RESULT_FAIL:
+		printf("FAIL!\n");
+		break;
+	case WRANDR_CALLBACK_RESULT_NOACT:
+		printf("Same as current, no change!\n");
+		break;
+	}
+}
+
+static void
+randr_done(void *data,
+	   struct wrandr_callback *callback,
+	   uint32_t flags,
+	   uint32_t results)
+{
+	print_line(flags, results,
+		   WRANDR_CALLBACK_ACTION_TRANSFORM, "TRANSFORM");
+	print_line(flags, results, WRANDR_CALLBACK_ACTION_MODE, "MODE");
+	print_line(flags, results, WRANDR_CALLBACK_ACTION_SCALE, "SCALE");
+	print_line(flags, results, WRANDR_CALLBACK_ACTION_MOVE, "MOVE");
+	print_line(flags, results, WRANDR_CALLBACK_ACTION_NEWMODE, "NEWMODE");
+	print_line(flags, results, WRANDR_CALLBACK_ACTION_DELMODE, "DELMODE");
+
+	running = 0;
+}
+
+static const struct wrandr_callback_listener wrandr_listener = {
+	randr_done
+};
+
+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_name(void *data,
+		   struct wl_output *wl_output,
+		   const char *name)
+{
+	struct output *output = data;
+	if (name)
+		output->name = strdup(name);
+}
+
+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,
+	output_handle_name
+};
+
+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->server_output_id = id;
+	output->output = wl_registry_bind(randr->registry,
+					  id,
+					  &wl_output_interface,
+					  2);
+
+	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, "weston_randr") == 0) {
+		randr->randr = wl_registry_bind(registry, id,
+						&weston_randr_interface,
+						1);
+	} 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
+newmode_format(void)
+{
+	fprintf(stderr,
+		"\t\nNewmode Format:"
+		"\t--newmode='d,d,d,d,d,d,d,d,d,s,s'"
+		"(d:digit, s:string)\n\n"
+		"\tclock: Pixel clock (Mhz)\n\n"
+		"\thdisplay: Pixel number of one horticontal line(Hz)\n\n"
+		"\thsync_start: Start of horizontal sync signal(Hz)\n\n"
+		"\thsycn_end: End of horizontal sync signal(Hz)\n\n"
+		"\thtotal: Whole cycle of a horizontal line(Hz)\n\n"
+		"\tvdisplay: Pixel number of one vertical line(Hz)\n\n"
+		"\tvsync_start: Start of vertical sync signal(Hz)\n\n"
+		"\tvsycn_end: End of vertical sync signal(Hz)\n\n"
+		"\tvtotal: Whole cycle of a vertical line(Hz)\n\n"
+		"\thsync: Polarity of the horizontal sync pulses\n"
+		"\t\tvalue:(+-)hsync\n"
+		"\tvsync: Polarity of the vertical sync pulses\n"
+		"\t\tvsync value:(+-)vsync\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"
+		"  --newmode \tcustome one mode\n"
+		"  --delmode \tdelete a mode like 800x600 at 58 or number\n"
+		"  -q|--query  \tquery all outputs\n"
+		"  --mode \tset mode like 800x600 at 60 or number"
+		"  --scale \tthe value of scale"
+		"(Firstly use -q to get mode list and find number).\n"
+		"  --transform \toutput trasform(0-7)\n"
+		"  -h|--help \tThis help text\n\n");
+
+	transform_usage();
+	newmode_format();
+	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) {
+			state = "";
+			if (mode->flags & WL_OUTPUT_MODE_CURRENT)
+				state = "(current)";
+			else if (mode->flags & WL_OUTPUT_MODE_PREFERRED)
+				state = "(preferred)";
+
+			printf("%d)%dx%d@%d%s\n",
+			       i++,
+			       mode->width,
+			       mode->height,
+			       (mode->refresh + HZ/2)/HZ,
+			       state);
+		}
+		printf("\n");
+	}
+}
+
+static int
+get_newmode(char *str, struct randr *randr)
+{
+	if (sscanf(str, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%6s,%6s",
+		   &randr->newmode.clock,
+		   &randr->newmode.hdisplay,
+		   &randr->newmode.hsync_start,
+		   &randr->newmode.hsync_end,
+		   &randr->newmode.htotal,
+		   &randr->newmode.vdisplay,
+		   &randr->newmode.vsync_start,
+		   &randr->newmode.vsync_end,
+		   &randr->newmode.vtotal,
+		   randr->newmode.hsync,
+		   randr->newmode.vsync) == 11) {
+
+		if ((strcmp(randr->newmode.hsync, "+hsync") != 0 &&
+		    strcmp(randr->newmode.hsync, "-hsync") != 0) ||
+		    (strcmp(randr->newmode.vsync, "+vsync") != 0 &&
+		    strcmp(randr->newmode.vsync, "-vsync") != 0)) {
+			fprintf(stderr,
+				"Invalid format of hsync and vsync\n"
+				"hsync:%s, vsync:%s\n",
+				randr->newmode.hsync,
+				randr->newmode.vsync);
+
+			return WRANDR_CALLBACK_RESULT_FAIL;
+		}
+		return WRANDR_CALLBACK_RESULT_SUCCESS;
+	}
+	return WRANDR_CALLBACK_RESULT_FAIL;
+}
+
+static struct mode *
+found_mode(struct output *output,
+	   const char *modestr)
+{
+	int width = -1, height = -1, refresh = -1;
+	int num = -1;
+	int i = 0;
+	struct mode *mode;
+
+	if (sscanf(modestr, "%dx%d@%d", &width, &height, &refresh) != 3) {
+		if (sscanf(modestr, "%dx%d", &width, &height) != 2) {
+			if (sscanf(modestr, "%d", &num) != 1) {
+				printf("Error formatting for mode.\n");
+				return NULL;
+			}
+		}
+	}
+
+	if (num >= 0) {
+		wl_list_for_each(mode, &output->mode_list, link) {
+			i++;
+			if (i == num)
+				return mode;
+		}
+	} else if (width > 0 && height > 0)
+		wl_list_for_each(mode, &output->mode_list, link) {
+			if (mode->width == width && mode->height == height)
+				if (refresh <= 0 || mode->refresh == refresh)
+					return mode;
+		}
+
+	return NULL;
+}
+
+static void
+randr_printmode(struct output *output)
+{
+	struct mode *mode;
+	char *state;
+	int i = 1;
+
+	printf("%s\n", output->name);
+	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);
+	}
+}
+
+static void
+randr_commit(struct randr *randr,
+	     struct wl_output *wayland_output)
+{
+	weston_randr_commit(randr->randr,
+			    wayland_output);
+}
+
+static void
+get_output_handle(struct randr *randr,
+		  struct argument *argument)
+{
+	struct output *output;
+
+	/* Get all output handles. */
+	wl_list_for_each(output, &randr->output_list, link) {
+		if (argument->leftof &&
+		    !strcmp(output->name, argument->leftof)) {
+			randr->loutput = output->output;
+		}
+
+		if (argument->rightof &&
+		    !strcmp(output->name, argument->rightof)) {
+			randr->routput = output->output;
+		}
+
+		if (argument->output &&
+		    !strcmp(output->name, argument->output)) {
+			randr->output = output;
+			randr->wayland_output = output->output;
+		}
+	}
+}
+
+static int
+verify_params(struct randr *randr,
+	      struct argument *argument)
+{
+	int ret = WRANDR_CALLBACK_RESULT_SUCCESS;
+	/* Verify output paramerters */
+	if (argument->output && !randr->wayland_output) {
+		printf("%s does not exists or not connected.\n",
+		       argument->output);
+		ret = WRANDR_CALLBACK_RESULT_FAIL;
+	}
+
+	if (argument->newmode) {
+		if (get_newmode(argument->newmode, randr) ==
+		    WRANDR_CALLBACK_RESULT_FAIL) {
+			printf("Invalid newmode format!\n");
+			newmode_format();
+			ret = WRANDR_CALLBACK_RESULT_FAIL;
+		}
+	}
+
+	if (argument->delmode) {
+		randr->delmode = found_mode(randr->output, argument->delmode);
+		if (!randr->delmode) {
+			printf("%s not exists\n", argument->delmode);
+			ret = WRANDR_CALLBACK_RESULT_FAIL;
+		}
+	}
+
+	if (argument->leftof) {
+		if (!randr->loutput) {
+			printf("%s not exists\n", argument->leftof);
+			ret = WRANDR_CALLBACK_RESULT_FAIL;
+		}
+	}
+
+	if (argument->rightof) {
+		if (!randr->routput) {
+			printf("%s not exists\n", argument->rightof);
+			ret = WRANDR_CALLBACK_RESULT_FAIL;
+		}
+	}
+
+	if (argument->mode) {
+		randr->mode = found_mode(randr->output, argument->mode);
+		if (randr->mode) {
+			if (randr->mode->flags & WL_OUTPUT_MODE_CURRENT) {
+				printf("%dx%d@%d has been the current.\n",
+				       randr->mode->width,
+				       randr->mode->height,
+				       randr->mode->refresh);
+
+				ret = WRANDR_CALLBACK_RESULT_FAIL;
+			}
+		} else {
+			printf("%s not exists\n", argument->mode);
+			ret = WRANDR_CALLBACK_RESULT_FAIL;
+		}
+	}
+
+	if (argument->scale != -1) {
+		if (argument->scale <= 0) {
+			printf("scale %d should be great than 0.\n",
+			       argument->scale);
+			ret = WRANDR_CALLBACK_RESULT_FAIL;
+		}
+
+		if (argument->scale == randr->output->scale) {
+			printf("scale %d is the same as current.\n",
+			       argument->scale);
+			ret = WRANDR_CALLBACK_RESULT_FAIL;
+		}
+	}
+
+	if (argument->transform != -1) {
+		if (argument->transform >= 0 && argument->transform <= 7) {
+			if (argument->transform == randr->output->transform) {
+				printf("transform %d is the same as current.\n",
+				       argument->transform);
+				ret = WRANDR_CALLBACK_RESULT_FAIL;
+			}
+		} else {
+			transform_usage();
+			ret = WRANDR_CALLBACK_RESULT_FAIL;
+		}
+	}
+
+	return ret;
+}
+
+static void
+query_output(struct randr *randr,
+	     struct argument *argument)
+{
+	/* Query mode */
+	if (argument->query > 0) {
+		if (randr->output)
+			randr_printmode(randr->output);
+		else
+			randr_query(randr);
+	}
+}
+
+static int
+del_new_mode(struct randr *randr,
+	     struct argument *argument)
+{
+	int ret = RANDR_EXIT;
+
+	/* Delete mode */
+	if (argument->delmode) {
+		weston_randr_del_mode(randr->randr,
+				      randr->wayland_output,
+				      randr->delmode->width,
+				      randr->delmode->height,
+				      randr->delmode->refresh);
+		ret = RANDR_COMMIT;
+	}
+
+	/* New mode */
+	if (argument->newmode) {
+		weston_randr_new_mode(randr->randr,
+				      randr->wayland_output,
+				      randr->newmode.clock,
+				      randr->newmode.hdisplay,
+				      randr->newmode.hsync_start,
+				      randr->newmode.hsync_end,
+				      randr->newmode.htotal,
+				      randr->newmode.vdisplay,
+				      randr->newmode.vsync_start,
+				      randr->newmode.vsync_end,
+				      randr->newmode.vtotal,
+				      randr->newmode.hsync,
+				      randr->newmode.vsync);
+
+		ret = RANDR_COMMIT;
+	}
+
+	return ret;
+}
+
+static int
+output_modeset(struct randr *randr,
+	       struct argument *argument)
+{
+	int ret = RANDR_EXIT;
+
+	/* Single action for output. */
+	if (randr->mode) {
+		weston_randr_set_mode(randr->randr,
+				      randr->wayland_output,
+				      randr->mode->width,
+				      randr->mode->height,
+				      randr->mode->refresh);
+		ret = RANDR_COMMIT;
+	}
+
+	if (argument->scale != -1) {
+		weston_randr_set_scale(randr->randr,
+				       randr->wayland_output,
+				       argument->scale);
+		ret = RANDR_COMMIT;
+	}
+
+	if (argument->transform >= 0) {
+		weston_randr_set_transform(randr->randr,
+					   randr->wayland_output,
+					   argument->transform);
+		ret = RANDR_COMMIT;
+
+	}
+
+	if (randr->loutput) {
+		weston_randr_move(randr->randr,
+				  randr->wayland_output,
+				  randr->loutput,
+				  WESTON_RANDR_MOVE_LEFTOF);
+		ret = RANDR_COMMIT;
+	}
+
+	if (randr->routput) {
+		weston_randr_move(randr->randr,
+				  randr->wayland_output,
+				  randr->routput,
+				  WESTON_RANDR_MOVE_RIGHTOF);
+		ret = RANDR_COMMIT;
+	}
+
+	return ret;
+}
+
+int
+main(int argc, char **argv)
+{
+	struct randr randr = { 0 };
+	struct argument argument = {NULL, NULL, NULL, NULL,
+				    NULL, NULL, -1, -1, -1, -1};
+	int ret = 0;
+	int commit = 0;
+
+	const struct weston_option randr_options[] = {
+		{ WESTON_OPTION_STRING, "output", 0, &argument.output},
+		{ WESTON_OPTION_STRING, "mode", 0, &argument.mode},
+		{ WESTON_OPTION_STRING, "newmode", 0, &argument.newmode},
+		{ WESTON_OPTION_STRING, "delmode", 0, &argument.delmode},
+		{ WESTON_OPTION_STRING, "leftof", 0, &argument.leftof},
+		{ WESTON_OPTION_STRING, "rightof", 0, &argument.rightof},
+		{ WESTON_OPTION_BOOLEAN, "query", 'q', &argument.query},
+		{ WESTON_OPTION_INTEGER, "scale", 0, &argument.scale},
+		{ WESTON_OPTION_INTEGER, "transform", 0, &argument.transform},
+		{ WESTON_OPTION_BOOLEAN, "help", 'h', &argument.help },
+	};
+
+	parse_options(randr_options, ARRAY_LENGTH(randr_options), &argc, argv);
+
+	if (argument.help > 0)
+		usage(EXIT_SUCCESS);
+
+	randr_init(&randr);
+
+	wl_display_roundtrip(randr.display);
+
+	/* Check if weston_randr is enable or not. */
+	if (!randr.randr) {
+		printf("weston_randr is not available in compositor.\n");
+		goto exit;
+	}
+
+	get_output_handle(&randr, &argument);
+
+	if (verify_params(&randr, &argument) ==
+	    WRANDR_CALLBACK_RESULT_FAIL)
+		goto exit;
+
+	query_output(&randr, &argument);
+
+	if (!randr.output)
+		goto exit;
+
+	randr.callback =
+		weston_randr_start(randr.randr, randr.wayland_output);
+	wrandr_callback_add_listener(randr.callback,
+				     &wrandr_listener, &randr);
+
+	if (del_new_mode(&randr, &argument) == RANDR_COMMIT)
+		commit += 1;
+
+	if (del_new_mode(&randr, &argument) == RANDR_COMMIT)
+		commit += 1;
+
+	if (output_modeset(&randr, &argument) == RANDR_COMMIT)
+		commit += 1;
+
+	if (commit > 0) {
+		randr_commit(&randr,
+			     randr.wayland_output);
+	} else
+		goto exit;
+
+	while (running && ret != -1)
+		ret = wl_display_dispatch(randr.display);
+
+exit:
+	delete_argument(&argument);
+	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