Signed-off-by: Quanxian Wang <quanxian.w...@intel.com>
Reviewed-by: Zhang, Xiong Y <xiong.y.zh...@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

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

Reply via email to