[PATCH 3/6] Add the detailed implementation of randr protocol
Quanxian Wang
quanxian.wang at intel.com
Wed Feb 26 19:28:02 PST 2014
1) add the initialization of randr protocol
2) add the randr request implementation
Signed-off-by: Quanxian Wang <quanxian.wang at intel.com>
Reviewed-by: Zhang, Xiong Y <xiong.y.zhang at intel.com>
---
src/Makefile.am | 4 +
src/compositor.c | 466 +++++++++++++++++++++++++++++++++++++++++++++++++------
2 files changed, 423 insertions(+), 47 deletions(-)
diff --git a/src/Makefile.am b/src/Makefile.am
index 446639c..5a19a7f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -34,6 +34,8 @@ weston_SOURCES = \
text-server-protocol.h \
input-method-protocol.c \
input-method-server-protocol.h \
+ randr-protocol.c \
+ randr-server-protocol.h \
workspaces-protocol.c \
workspaces-server-protocol.h \
scaler-protocol.c \
@@ -321,6 +323,8 @@ BUILT_SOURCES = \
text-server-protocol.h \
input-method-protocol.c \
input-method-server-protocol.h \
+ randr-protocol.c \
+ randr-server-protocol.h \
workspaces-server-protocol.h \
workspaces-protocol.c \
scaler-server-protocol.h \
diff --git a/src/compositor.c b/src/compositor.c
index 40e4b11..3306c99 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -54,6 +54,7 @@
#include "compositor.h"
#include "scaler-server-protocol.h"
+#include "randr-server-protocol.h"
#include "../shared/os-compatibility.h"
#include "git-version.h"
#include "version.h"
@@ -95,12 +96,90 @@ weston_output_transform_scale_init(struct weston_output *output,
static void
weston_compositor_build_view_list(struct weston_compositor *compositor);
+static void
+adjust_pointer(struct weston_output *output,
+ pixman_region32_t *old_output_region)
+{
+ struct weston_seat *seat;
+ int32_t x, y;
+ struct weston_pointer *pointer;
+
+ /* If a pointer falls outside the outputs new geometry, move it to its
+ * lower-right corner. */
+ wl_list_for_each(seat, &output->compositor->seat_list, link) {
+ pointer = seat->pointer;
+ if (!pointer)
+ continue;
+
+ x = wl_fixed_to_int(pointer->x);
+ y = wl_fixed_to_int(pointer->y);
+
+ if (!pixman_region32_contains_point(old_output_region,
+ x, y, NULL) ||
+ pixman_region32_contains_point(&output->region,
+ x, y, NULL))
+ continue;
+
+ if (x >= output->x + output->width)
+ x = output->x + output->width - 1;
+ if (y >= output->y + output->height)
+ y = output->y + output->height - 1;
+
+ pointer->x = wl_fixed_from_int(x);
+ pointer->y = wl_fixed_from_int(y);
+ }
+}
+
+static void
+notify_change(struct weston_output *output,
+ struct weston_mode *mode,
+ int mode_changed,
+ int scale_changed,
+ int transform_changed,
+ int32_t scale)
+{
+ struct wl_resource *resource;
+
+ if (!mode_changed && !scale_changed &&
+ !transform_changed)
+ return;
+
+ /* Notify clients of the changes */
+ wl_resource_for_each(resource,
+ &output->resource_list) {
+ if (mode_changed) {
+ wl_output_send_mode(resource,
+ mode->flags |
+ WL_OUTPUT_MODE_CURRENT,
+ mode->width,
+ mode->height,
+ mode->refresh);
+ }
+
+ if (transform_changed) {
+ wl_output_send_geometry(resource,
+ output->x,
+ output->y,
+ output->mm_width,
+ output->mm_height,
+ output->subpixel,
+ output->make,
+ output->model,
+ output->transform);
+ }
+
+ if (scale_changed)
+ wl_output_send_scale(resource, scale);
+
+ if (wl_resource_get_version(resource) >= 2)
+ wl_output_send_done(resource);
+ }
+}
+
WL_EXPORT int
weston_output_switch_mode(struct weston_output *output, struct weston_mode *mode,
int32_t scale, enum weston_mode_switch_op op)
{
- struct weston_seat *seat;
- struct wl_resource *resource;
pixman_region32_t old_output_region;
int ret, notify_mode_changed, notify_scale_changed;
int temporary_mode, temporary_scale;
@@ -178,53 +257,12 @@ weston_output_switch_mode(struct weston_output *output, struct weston_mode *mode
weston_output_update_matrix(output);
- /* If a pointer falls outside the outputs new geometry, move it to its
- * lower-right corner */
- wl_list_for_each(seat, &output->compositor->seat_list, link) {
- struct weston_pointer *pointer = seat->pointer;
- int32_t x, y;
-
- if (!pointer)
- continue;
-
- x = wl_fixed_to_int(pointer->x);
- y = wl_fixed_to_int(pointer->y);
-
- if (!pixman_region32_contains_point(&old_output_region,
- x, y, NULL) ||
- pixman_region32_contains_point(&output->region,
- x, y, NULL))
- continue;
-
- if (x >= output->x + output->width)
- x = output->x + output->width - 1;
- if (y >= output->y + output->height)
- y = output->y + output->height - 1;
-
- pointer->x = wl_fixed_from_int(x);
- pointer->y = wl_fixed_from_int(y);
- }
-
+ adjust_pointer(output, &old_output_region);
pixman_region32_fini(&old_output_region);
- /* notify clients of the changes */
- if (notify_mode_changed || notify_scale_changed) {
- wl_resource_for_each(resource, &output->resource_list) {
- if(notify_mode_changed) {
- wl_output_send_mode(resource,
- mode->flags | WL_OUTPUT_MODE_CURRENT,
- mode->width,
- mode->height,
- mode->refresh);
- }
-
- if (notify_scale_changed)
- wl_output_send_scale(resource, scale);
-
- if (wl_resource_get_version(resource) >= 2)
- wl_output_send_done(resource);
- }
- }
+ /* Notify clients of the changes */
+ notify_change(output, mode, notify_mode_changed,
+ notify_scale_changed, 0, scale);
return ret;
}
@@ -3740,6 +3778,9 @@ weston_compositor_shutdown(struct weston_compositor *ec)
if (ec->renderer)
ec->renderer->destroy(ec);
+ if (ec->randr)
+ ec->randr->destroy(ec);
+
weston_binding_list_destroy_all(&ec->key_binding_list);
weston_binding_list_destroy_all(&ec->button_binding_list);
weston_binding_list_destroy_all(&ec->touch_binding_list);
@@ -3768,6 +3809,337 @@ weston_compositor_set_default_pointer_grab(struct weston_compositor *ec,
}
}
+/* Weston randr code here. */
+static void
+randr_destroy(struct wl_client *client,
+ struct wl_resource *resource)
+{
+ wl_resource_destroy(resource);
+ return;
+}
+
+static void
+randr_get_disoutputs(struct wl_client *client,
+ struct wl_resource *resource)
+{
+ struct weston_randr *randr = wl_resource_get_user_data(resource);
+ struct weston_compositor *ec = randr->compositor;
+ char ret_str[1024];
+
+ /* Show disconnected port */
+ if (ec->randr->get_disoutputs) {
+ ec->randr->get_disoutputs(ec, ret_str);
+ wl_randr_send_disoutputs(randr->resource, ret_str);
+ }
+}
+
+static void
+randr_get_output_name(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *output_resource)
+{
+ struct weston_randr *randr =
+ wl_resource_get_user_data(resource);
+ struct weston_output *output;
+
+ output = wl_resource_get_user_data(output_resource);
+
+ wl_randr_send_output_name(
+ randr->resource,
+ wl_resource_find_for_client(&output->resource_list,
+ client),
+ output->name);
+}
+
+static void
+randr_output_switch_transform(struct weston_output *output, uint32_t transform)
+{
+ pixman_region32_t old_output_region;
+
+ pixman_region32_init(&old_output_region);
+ pixman_region32_copy(&old_output_region, &output->region);
+
+ /* Update output region and transformation matrix. */
+ if (transform == output->transform)
+ return;
+
+ weston_output_transform_scale_init(output,
+ transform % 8,
+ output->current_scale);
+
+ pixman_region32_init(&output->previous_damage);
+ pixman_region32_init_rect(&output->region,
+ output->x, output->y,
+ output->width, output->height);
+
+ weston_output_update_matrix(output);
+ adjust_pointer(output, &old_output_region);
+ pixman_region32_fini(&old_output_region);
+
+ /* Notify clients of the changes. */
+ notify_change(output, output->current_mode,
+ 0, 0, 1, 0);
+ return;
+}
+
+static void
+randr_set_transform(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *output_resource,
+ uint32_t transform)
+{
+ struct weston_randr *randr =
+ wl_resource_get_user_data(resource);
+ struct weston_compositor *ec = randr->compositor;
+ struct weston_output *target_output =
+ wl_resource_get_user_data(output_resource);
+ struct weston_output *output;
+ int offset = 0;
+ int ret = 1;
+
+ if (transform == target_output->transform) {
+ ret = 1;
+ weston_log("Transform is the same as before.\n");
+ wl_randr_send_action_done(randr->resource,
+ 1<<WL_RANDR_ACTION_TRANSFORM,
+ ret);
+ return;
+ }
+
+ if (!target_output) {
+ ret = -1;
+ weston_log("Output is null.\n");
+ wl_randr_send_action_done(randr->resource,
+ 1<<WL_RANDR_ACTION_TRANSFORM,
+ ret);
+ return;
+ }
+
+ wl_list_for_each(output, &ec->output_list, link) {
+ if (output == target_output) {
+ randr_output_switch_transform(output, transform);
+ weston_output_damage(output);
+ offset = output->x + output->width;
+ } else if (offset > 0) {
+ weston_output_move(output, offset, 0);
+ offset += output->width;
+ weston_output_damage(output);
+ }
+ }
+
+ wl_randr_send_action_done(randr->resource,
+ 1<<WL_RANDR_ACTION_TRANSFORM, ret);
+ weston_log("Successfully set rotate.\n");
+}
+
+static int
+randr_switch_mode(struct weston_output *output,
+ int width,
+ int height,
+ uint32_t refresh)
+{
+ struct weston_mode *mode;
+ int ret = -1;
+
+ wl_list_for_each(mode, &output->mode_list, link) {
+ if (width != mode->width ||
+ height != mode->height ||
+ refresh != mode->refresh)
+ continue;
+
+ ret = 1;
+ if (mode->flags & WL_OUTPUT_MODE_CURRENT) {
+ ret = 2;
+ break;
+ }
+
+ weston_output_switch_mode(output, mode,
+ output->current_scale,
+ WESTON_MODE_SWITCH_SET_NATIVE);
+ weston_output_damage(output);
+
+ break;
+ }
+
+ if (ret < 0)
+ weston_log("No right mode is found.\n");
+
+ return ret;
+}
+
+static void
+randr_set_mode(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *output_resource,
+ int width, int height, int refresh)
+{
+ struct weston_randr *randr = wl_resource_get_user_data(resource);
+ struct weston_compositor *ec = randr->compositor;
+ struct weston_output *target_output =
+ wl_resource_get_user_data(output_resource);
+ struct weston_output *output;
+ int offset = 0;
+ int ret = -1;
+
+ if (!target_output) {
+ ret = -1;
+ weston_log("Output is null.\n");
+ wl_randr_send_action_done(randr->resource,
+ 1<<WL_RANDR_ACTION_MODE, ret);
+ return;
+ }
+
+ wl_list_for_each(output, &ec->output_list, link) {
+ if (target_output == output) {
+ ret = randr_switch_mode(output, width, height, refresh);
+ if (ret == 1)
+ offset = output->x + output->width;
+ else
+ break;
+ } else if (offset > 0) {
+ weston_output_move(output, offset, 0);
+ offset += output->width;
+ weston_output_damage(output);
+ }
+ }
+
+ if (ret == 1)
+ weston_log("Successfully set %dx%d@%d mode.\n",
+ width, height, refresh);
+ else if (ret == 2)
+ weston_log("%dx%d@%d mode has been current.\n",
+ width, height, refresh);
+ else if (ret == -1)
+ weston_log("Failed to set mode.\n");
+
+ wl_randr_send_action_done(randr->resource,
+ 1<<WL_RANDR_ACTION_MODE,
+ ret);
+}
+
+static void
+randr_move(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *target_resource,
+ struct wl_resource *source_resource, int move)
+{
+ struct weston_randr *randr = wl_resource_get_user_data(resource);
+ struct weston_compositor *ec = randr->compositor;
+ struct weston_output *target_output =
+ wl_resource_get_user_data(target_resource);
+ struct weston_output *source_output =
+ wl_resource_get_user_data(source_resource);
+ struct weston_output *output = NULL;
+ int no_move = 0;
+ int ret = -1;
+ int x = 0;
+
+ if (source_output == NULL ||
+ target_output == NULL ||
+ target_output == source_output) {
+ weston_log("One output does't exist or Both are same.\n");
+ wl_randr_send_action_done(randr->resource,
+ 1<<WL_RANDR_ACTION_MOVE,
+ ret);
+ return;
+ }
+
+ /* Move the output. */
+ if (move == WL_RANDR_MOVE_LEFTOF) {
+ if (source_output->link.prev == &target_output->link)
+ no_move = 1;
+ } else if (move == WL_RANDR_MOVE_RIGHTOF) {
+ if (source_output->link.next == &target_output->link)
+ no_move = 1;
+ }
+
+ if (no_move) {
+ ret = 2;
+ weston_log("%s is in the %s position of %s.",
+ target_output->name,
+ move == WL_RANDR_MOVE_LEFTOF ? "left" : "right",
+ source_output->name);
+ wl_randr_send_action_done(randr->resource,
+ 1<<WL_RANDR_ACTION_MOVE,
+ ret);
+ return;
+ }
+
+ ret = 1;
+ wl_list_remove(&target_output->link);
+
+ if (move == WL_RANDR_MOVE_LEFTOF)
+ wl_list_insert(source_output->link.prev,
+ &target_output->link);
+ else if (move == WL_RANDR_MOVE_RIGHTOF)
+ wl_list_insert(&source_output->link,
+ &target_output->link);
+
+ wl_list_for_each(output, &ec->output_list, link) {
+ weston_output_move(output, x, 0);
+ weston_output_damage(output);
+ x += output->width;
+ }
+
+ wl_randr_send_action_done(randr->resource,
+ 1<<WL_RANDR_ACTION_MOVE,
+ ret);
+}
+
+static const struct wl_randr_interface randr_interface = {
+ randr_destroy,
+ randr_set_mode,
+ randr_set_transform,
+ randr_move,
+ randr_get_disoutputs,
+ randr_get_output_name
+};
+
+static void
+bind_randr(struct wl_client *client,
+ void *data, uint32_t version, uint32_t id)
+{
+ struct weston_randr *randr = data;
+
+ randr->resource = wl_resource_create(client,
+ &wl_randr_interface,
+ 1, id);
+
+ if (randr->resource == NULL) {
+ wl_client_post_no_memory(client);
+ return;
+ }
+
+ wl_resource_set_implementation(randr->resource,
+ &randr_interface,
+ randr, NULL);
+}
+
+static void
+weston_randr_destroy(struct weston_compositor *ec)
+{
+ wl_global_destroy(ec->randr->global);
+ free(ec->randr);
+}
+
+WL_EXPORT int
+weston_randr_init(struct weston_randr *randr, struct weston_compositor *ec)
+{
+ randr->compositor = ec;
+ ec->randr = randr;
+ randr->global = wl_global_create(ec->wl_display,
+ &wl_randr_interface, 1,
+ randr, bind_randr);
+
+ if (randr->global == NULL) {
+ weston_log("Failed to create global wl_randr_interface.\n");
+ return -1;
+ }
+
+ randr->destroy = weston_randr_destroy;
+ return 1;
+}
+
WL_EXPORT void
weston_version(int *major, int *minor, int *micro)
{
--
1.8.1.2
More information about the wayland-devel
mailing list