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.w...@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@58 or number\n"
+               "  -q|--query  \tquery all outputs\n"
+               "  --mode \tset mode like 800x600@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

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to