[PATCH 1/2] Add support for move method on outputs

Casey Dahlin cdahlin at redhat.com
Fri Apr 29 00:04:54 PDT 2011


Outputs can now be rotated, flipped, and shifted by using the new move method
of the output interface.
---
 clients/window.c                |    3 +-
 compositor/compositor-wayland.c |    4 +-
 compositor/compositor.c         |   97 ++++++++++++++++++++++++++++----------
 compositor/compositor.h         |    3 +-
 4 files changed, 77 insertions(+), 30 deletions(-)

diff --git a/clients/window.c b/clients/window.c
index 9d0b753..33dbc94 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -1523,7 +1523,8 @@ window_set_buffer_type(struct window *window, enum window_buffer_type type)
 static void
 display_handle_geometry(void *data,
 			struct wl_output *output,
-			int32_t x, int32_t y, int32_t width, int32_t height)
+			int32_t x, int32_t y, uint32_t tflags,
+			uint32_t width, uint32_t height)
 {
 	struct display *display = data;
 
diff --git a/compositor/compositor-wayland.c b/compositor/compositor-wayland.c
index 4093f2a..508ea88 100644
--- a/compositor/compositor-wayland.c
+++ b/compositor/compositor-wayland.c
@@ -283,8 +283,8 @@ cleanup_output:
 static void
 display_handle_geometry(void *data,
 			struct wl_output *output,
-			int32_t x, int32_t y,
-			int32_t width, int32_t height)
+			int32_t x, int32_t y, uint32_t tflags,
+			uint32_t width, uint32_t height)
 {
 	struct wayland_compositor *c = data;
 
diff --git a/compositor/compositor.c b/compositor/compositor.c
index df25407..4f0912f 100644
--- a/compositor/compositor.c
+++ b/compositor/compositor.c
@@ -113,6 +113,16 @@ wlsc_matrix_scale(struct wlsc_matrix *matrix, GLfloat x, GLfloat y, GLfloat z)
 }
 
 static void
+wlsc_matrix_rotate_90ccw(struct wlsc_matrix *matrix)
+{
+	struct wlsc_matrix rot = {
+		{ 0, -1, 0, 0,  1, 0, 0, 0,  0, 0, 1, 0,  0, 0, 0, 1 }
+	};
+
+	wlsc_matrix_multiply(matrix, &rot);
+}
+
+static void
 wlsc_matrix_transform(struct wlsc_matrix *matrix, struct wlsc_vector *v)
 {
 	int i, j;
@@ -649,7 +659,7 @@ wlsc_output_damage(struct wlsc_output *output)
 	pixman_region32_union_rect(&compositor->damage_region,
 				   &compositor->damage_region,
 				   output->x, output->y,
-				   output->width, output->height);
+				   output->swidth, output->sheight);
 	wlsc_compositor_schedule_repaint(compositor);
 }
 
@@ -687,8 +697,8 @@ fade_output(struct wlsc_output *output,
 	surface.compositor = compositor;
 	surface.x = output->x;
 	surface.y = output->y;
-	surface.width = output->width;
-	surface.height = output->height;
+	surface.width = output->swidth;
+	surface.height = output->sheight;
 	surface.texture = GL_NONE;
 
 	if (tint <= 1.0)
@@ -727,7 +737,7 @@ wlsc_output_repaint(struct wlsc_output *output)
 	pixman_region32_intersect_rect(&new_damage,
 				       &ec->damage_region,
 				       output->x, output->y,
-				       output->width, output->height);
+				       output->swidth, output->sheight);
 	pixman_region32_subtract(&ec->damage_region,
 				 &ec->damage_region, &new_damage);
 	pixman_region32_union(&total_damage, &new_damage,
@@ -754,8 +764,8 @@ wlsc_output_repaint(struct wlsc_output *output)
 			}
 		}
 
-		if (es->width < output->width ||
-		    es->height < output->height)
+		if (es->width < output->swidth ||
+		    es->height < output->sheight)
 			glClear(GL_COLOR_BUFFER_BIT);
 		wlsc_surface_draw(es, output, &total_damage);
 	} else {
@@ -893,9 +903,10 @@ wlsc_surface_assign_output(struct wlsc_surface *es)
 	struct wlsc_output *tmp = es->output;
 	es->output = NULL;
 
+
 	wl_list_for_each(output, &ec->output_list, link) {
-		if (output->x < es->x && es->x < output->x + output->width &&
-		    output->y < es->y && es->y < output->y + output->height) {
+		if (output->x < es->x && es->x < output->x + output->swidth &&
+		    output->y < es->y && es->y < output->y + output->sheight) {
 			if (output != tmp)
 				printf("assiging surface %p to output %p\n",
 				       es, output);
@@ -928,8 +939,8 @@ surface_attach(struct wl_client *client,
 	es->buffer = buffer;
 	switch (es->map_type) {
 	case WLSC_SURFACE_MAP_FULLSCREEN:
-		es->x = (es->fullscreen_output->width - es->width) / 2;
-		es->y = (es->fullscreen_output->height - es->height) / 2;
+		es->x = (es->fullscreen_output->swidth - es->width) / 2;
+		es->y = (es->fullscreen_output->sheight - es->height) / 2;
 		break;
 	default:
 		es->x += x;
@@ -1034,8 +1045,8 @@ surface_map_fullscreen(struct wl_client *client, struct wl_surface *surface)
 
 	es->saved_x = es->x;
 	es->saved_y = es->y;
-	es->x = (output->width - es->width) / 2;
-	es->y = (output->height - es->height) / 2;
+	es->x = (output->swidth - es->width) / 2;
+	es->y = (output->sheight - es->height) / 2;
 	es->fullscreen_output = output;
 	wlsc_surface_update_matrix(es);
 	wlsc_surface_damage(es);
@@ -1259,10 +1270,10 @@ notify_motion(struct wl_input_device *device, uint32_t time, int x, int y)
 	wlsc_compositor_wake(ec);
 
 	wl_list_for_each(output, &ec->output_list, link) {
-		if (output->x <= x && x <= output->x + output->width)
+		if (output->x <= x && x <= output->x + output->swidth)
 			x_valid = 1;
 
-		if (output->y <= y && y <= output->y + output->height)
+		if (output->y <= y && y <= output->y + output->sheight)
 			y_valid = 1;
 
 		/* FIXME: calculate this only on output addition/deletion */
@@ -1271,10 +1282,10 @@ notify_motion(struct wl_input_device *device, uint32_t time, int x, int y)
 		if (output->y < min_y)
 			min_y = output->y;
 
-		if (output->x + output->width > max_x)
-			max_x = output->x + output->width;
-		if (output->y + output->height > max_y)
-			max_y = output->y + output->height;
+		if (output->x + output->swidth > max_x)
+			max_x = output->x + output->swidth;
+		if (output->y + output->sheight > max_y)
+			max_y = output->y + output->sheight;
 	}
 	
 	if (!x_valid) {
@@ -1631,7 +1642,7 @@ wlsc_output_post_geometry(struct wl_client *client,
 
 	wl_client_post_event(client, global,
 			     WL_OUTPUT_GEOMETRY,
-			     output->x, output->y,
+			     output->x, output->y, output->transform_flags,
 			     output->width, output->height);
 }
 
@@ -1757,14 +1768,25 @@ void
 wlsc_output_move(struct wlsc_output *output, int x, int y)
 {
 	struct wlsc_compositor *c = output->compositor;
-	int flip;
+	int hflip;
+	int vflip;
 
 	output->x = x;
 	output->y = y;
 
+	if (output->transform_flags & WL_OUTPUT_CWROTATE) {
+		output->sheight = output->width;
+		output->swidth = output->height;
+	} else {
+		output->sheight = output->height;
+		output->swidth = output->width;
+	}
+
 	if (output->background) {
 		output->background->x = x;
 		output->background->y = y;
+		output->background->height = output->sheight;
+		output->background->width = output->swidth;
 		wlsc_surface_update_matrix(output->background);
 	}
 
@@ -1772,19 +1794,39 @@ wlsc_output_move(struct wlsc_output *output, int x, int y)
 
 	wlsc_matrix_init(&output->matrix);
 	wlsc_matrix_translate(&output->matrix,
-			      -output->x - output->width / 2.0,
-			      -output->y - output->height / 2.0, 0);
+			      -output->x - output->swidth / 2.0,
+			      -output->y - output->sheight / 2.0, 0);
+
+	hflip = (output->transform_flags & WL_OUTPUT_HORIZFLIP) ? -1 : 1;
+	vflip = (output->flags & WL_OUTPUT_FLIPPED) ? -1 : 1;
+	vflip *= (output->transform_flags & WL_OUTPUT_VERTFLIP) ? -1 : 1;
 
-	flip = (output->flags & WL_OUTPUT_FLIPPED) ? -1 : 1;
 	wlsc_matrix_scale(&output->matrix,
-			  2.0 / output->width,
-			  flip * 2.0 / output->height, 1);
+			  hflip * 2.0 / output->swidth,
+			  vflip * 2.0 / output->sheight, 1);
+
+	if (output->transform_flags & WL_OUTPUT_CWROTATE)
+		wlsc_matrix_rotate_90ccw(&output->matrix);
 
 	pixman_region32_union_rect(&c->damage_region,
 				   &c->damage_region,
-				   x, y, output->width, output->height);
+				   x, y, output->swidth, output->sheight);
 }
 
+static void
+output_move(struct wl_client *client, struct wl_output *output, int x, int y,
+	    uint32_t transform_flags)
+{
+	struct wlsc_output *wlsc_output = (struct wlsc_output *)output;
+
+	wlsc_output->transform_flags = transform_flags;
+	wlsc_output_move(wlsc_output, x, y);
+}
+
+const static struct wl_output_interface output_interface = {
+	output_move,
+};
+
 void
 wlsc_output_init(struct wlsc_output *output, struct wlsc_compositor *c,
 		 int x, int y, int width, int height, uint32_t flags)
@@ -1794,6 +1836,8 @@ wlsc_output_init(struct wlsc_output *output, struct wlsc_compositor *c,
 	output->y = y;
 	output->width = width;
 	output->height = height;
+	output->swidth = width;
+	output->sheight = height;
 
 	output->background =
 		background_create(output, option_background);
@@ -1803,6 +1847,7 @@ wlsc_output_init(struct wlsc_output *output, struct wlsc_compositor *c,
 	wlsc_output_move(output, x, y);
 
 	output->object.interface = &wl_output_interface;
+	output->object.implementation = (void (**)(void))&output_interface;
 	wl_display_add_object(c->wl_display, &output->object);
 	wl_display_add_global(c->wl_display, &output->object,
 			      wlsc_output_post_geometry);
diff --git a/compositor/compositor.h b/compositor/compositor.h
index bbbae98..88ed115 100644
--- a/compositor/compositor.h
+++ b/compositor/compositor.h
@@ -45,9 +45,10 @@ struct wlsc_output {
 	struct wlsc_compositor *compositor;
 	struct wlsc_surface *background;
 	struct wlsc_matrix matrix;
-	int32_t x, y, width, height;
+	int32_t x, y, width, height, swidth, sheight;
 	pixman_region32_t previous_damage_region;
 	uint32_t flags;
+	uint32_t transform_flags;
 	int repaint_needed;
 	int finished;
 
-- 
1.7.5



More information about the wayland-devel mailing list