[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