[PATCH 1/2] shell: Add implementation of fullscreen.

zhiwen.wu at linux.intel.com zhiwen.wu at linux.intel.com
Wed Feb 29 20:57:46 PST 2012


From: Alex Wu <zhiwen.wu at linux.intel.com>

Undo fullscreen in shell_unset_fullscreen(), do all the stacking order
in shell_stack_fullscreen(), and configure black surface, method in
shell_configure_fullscreen().

Signed-off-by: Alex Wu <zhiwen.wu at linux.intel.com>
Signed-off-by: Juan Zhao <juan.j.zhao at linux.intel.com>
---
 src/shell.c |  218 ++++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 195 insertions(+), 23 deletions(-)

diff --git a/src/shell.c b/src/shell.c
index 01e5cf6..d53b6f6 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -93,7 +93,9 @@ struct shell_surface {
 	struct shell_surface *parent;
 
 	enum shell_surface_type type;
+	enum shell_surface_type prev_type;
 	int32_t saved_x, saved_y;
+	bool saved_position_valid;
 
 	struct {
 		struct weston_transform transform;
@@ -108,6 +110,13 @@ struct shell_surface {
 		int32_t initial_up;
 	} popup;
 
+	struct {
+		enum wl_shell_surface_fullscreen_method type;
+		struct weston_transform transform; /* matrix from x, y */
+		uint32_t framerate;
+		struct weston_surface *black_surface;
+	} fullscreen;
+
 	struct weston_output *fullscreen_output;
 	struct weston_output *output;
 	struct wl_list link;
@@ -134,6 +143,10 @@ struct rotate_grab {
 };
 
 static void
+center_on_output(struct weston_surface *surface,
+		 struct weston_output *output);
+
+static void
 shell_configuration(struct wl_shell *shell)
 {
 	char *config_file;
@@ -303,7 +316,8 @@ weston_surface_resize(struct shell_surface *shsurf,
 {
 	struct weston_resize_grab *resize;
 
-	/* FIXME: Reject if fullscreen */
+	if (shsurf->type == SHELL_SURFACE_FULLSCREEN)
+		return 0;
 
 	if (edges == 0 || edges > 15 ||
 	    (edges & 3) == 3 || (edges & 12) == 12)
@@ -334,7 +348,8 @@ shell_surface_resize(struct wl_client *client, struct wl_resource *resource,
 	struct weston_input_device *wd = input_resource->data;
 	struct shell_surface *shsurf = resource->data;
 
-	/* FIXME: Reject if fullscreen */
+	if (shsurf->type == SHELL_SURFACE_FULLSCREEN)
+		return;
 
 	if (wd->input_device.button_count == 0 ||
 	    wd->input_device.grab_time != time ||
@@ -352,15 +367,26 @@ get_default_output(struct weston_compositor *compositor)
 			    struct weston_output, link);
 }
 
+static void
+shell_unset_fullscreen(struct shell_surface *shsurf)
+{
+	/* undo all fullscreen things here */
+	shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
+	shsurf->fullscreen.framerate = 0;
+	wl_list_remove(&shsurf->fullscreen.transform.link);
+	wl_list_init(&shsurf->fullscreen.transform.link);
+	weston_surface_destroy(shsurf->fullscreen.black_surface);
+	shsurf->fullscreen.black_surface = NULL;
+	shsurf->fullscreen_output = NULL;
+	shsurf->surface->force_configure = 1;
+}
+
 static int
 reset_shell_surface_type(struct shell_surface *surface)
 {
 	switch (surface->type) {
 	case SHELL_SURFACE_FULLSCREEN:
-		weston_surface_set_position(surface->surface,
-					    surface->saved_x,
-					    surface->saved_y);
-		surface->fullscreen_output = NULL;
+		shell_unset_fullscreen(surface);
 		break;
 	case SHELL_SURFACE_MAXIMIZED:
 		surface->output = get_default_output(surface->surface->compositor);
@@ -386,6 +412,7 @@ reset_shell_surface_type(struct shell_surface *surface)
 		break;
 	}
 
+	surface->prev_type = surface->type;
 	surface->type = SHELL_SURFACE_NONE;
 	return 0;
 }
@@ -417,7 +444,7 @@ shell_surface_set_transient(struct wl_client *client,
 	if (reset_shell_surface_type(shsurf))
 		return;
 
-	/* assign to parents output  */
+	/* assign to parents output */
 	shsurf->output = pes->output;
  	weston_surface_set_position(es, pes->geometry.x + x,
 					pes->geometry.y + y);
@@ -474,6 +501,7 @@ shell_surface_set_maximized(struct wl_client *client,
 
 	shsurf->saved_x = es->geometry.x;
 	shsurf->saved_y = es->geometry.y;
+	shsurf->saved_position_valid = true;
 
 	wlshell = shell_surface_get_shell(shsurf);
 	panel_height = get_output_panel_height(wlshell, es->output);
@@ -487,6 +515,96 @@ shell_surface_set_maximized(struct wl_client *client,
 	shsurf->type = SHELL_SURFACE_MAXIMIZED;
 }
 
+static struct weston_surface *
+create_black_surface(struct weston_compositor *ec, 
+		     GLfloat x, GLfloat y, int w, int h)
+{
+	struct weston_surface *surface = NULL;
+
+	surface = weston_surface_create(ec);
+	if (surface == NULL) {
+		fprintf(stderr, "no memory\n");
+		return NULL;
+	}
+
+	weston_surface_configure(surface, x, y, w, h);
+	weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
+	return surface;
+}
+
+/* Create black surface and append it to the associated fullscreen surface.
+ * Handle size dismatch and positioning according to the method. */
+static void
+shell_configure_fullscreen(struct shell_surface *shsurf)
+{
+	struct weston_output *output = shsurf->fullscreen_output;
+	struct weston_surface *surface = shsurf->surface;
+	struct weston_matrix *matrix;
+	float scale;
+
+	center_on_output(surface, output);
+
+	if (!shsurf->fullscreen.black_surface)
+		shsurf->fullscreen.black_surface = create_black_surface(surface->compositor,
+									output->x, output->y,
+									output->current->width, output->current->height);
+	wl_list_remove(&shsurf->fullscreen.black_surface->link);
+	wl_list_insert(&surface->link, &shsurf->fullscreen.black_surface->link);
+	shsurf->fullscreen.black_surface->output = output;
+
+	switch (shsurf->fullscreen.type) {
+	case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT:
+		break;
+	case WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE:
+		matrix = &shsurf->fullscreen.transform.matrix;
+		weston_matrix_init(matrix);
+		scale = (float)output->current->width/(float)surface->geometry.width;
+		weston_matrix_scale(matrix, scale, scale, 1);
+		wl_list_remove(&shsurf->fullscreen.transform.link);
+		wl_list_insert(surface->geometry.transformation_list.prev,
+			       &shsurf->fullscreen.transform.link);
+		weston_surface_set_position(surface, output->x, output->y);
+		break;
+	case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER:
+		break;
+	case WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL:
+		break;
+	default:
+		break;
+	}
+}
+
+/* make the fullscreen and black surface at the top */
+static void
+shell_stack_fullscreen(struct shell_surface *shsurf)
+{
+	struct weston_surface *surface = shsurf->surface;
+	struct wl_shell *shell = shell_surface_get_shell(shsurf);
+	struct wl_list *list;
+
+	wl_list_remove(&surface->link);
+	wl_list_remove(&shsurf->fullscreen.black_surface->link);
+
+	if (shell->locked) {
+		wl_list_insert(&shell->hidden_surface_list, &surface->link);
+		wl_list_insert(&surface->link, &shsurf->fullscreen.black_surface->link);
+	} else {
+		list = weston_compositor_top(surface->compositor);
+		wl_list_insert(list, &surface->link);
+		wl_list_insert(&surface->link, &shsurf->fullscreen.black_surface->link);
+
+		weston_surface_damage(surface);
+		weston_surface_damage(shsurf->fullscreen.black_surface);
+	}
+}
+
+static void
+shell_map_fullscreen(struct shell_surface *shsurf)
+{
+	shell_configure_fullscreen(shsurf);
+	shell_stack_fullscreen(shsurf);
+}
+
 static void
 shell_surface_set_fullscreen(struct wl_client *client,
 			     struct wl_resource *resource,
@@ -496,21 +614,29 @@ shell_surface_set_fullscreen(struct wl_client *client,
 {
 	struct shell_surface *shsurf = resource->data;
 	struct weston_surface *es = shsurf->surface;
-	struct weston_output *output;
+
+	if (output_resource)
+		shsurf->output = output_resource->data;
+	else
+		shsurf->output = get_default_output(es->compositor);
 
 	if (reset_shell_surface_type(shsurf))
 		return;
 
-	/* FIXME: Fullscreen on first output */
-	/* FIXME: Handle output going away */
-	output = get_default_output(es->compositor);
+	if (shsurf->prev_type != SHELL_SURFACE_FULLSCREEN) {
+		shsurf->saved_x = es->geometry.x;
+		shsurf->saved_y = es->geometry.y;
+		shsurf->saved_position_valid = true;
+	}
 
-	shsurf->saved_x = es->geometry.x;
-	shsurf->saved_y = es->geometry.y;
-	shsurf->output = output;
-	shsurf->fullscreen_output = output;
+	shsurf->fullscreen_output = shsurf->output;
+	shsurf->fullscreen.type = method;
+	shsurf->fullscreen.framerate = framerate;
 	shsurf->type = SHELL_SURFACE_FULLSCREEN;
 
+	if (es->output)
+		shsurf->surface->force_configure = 1;
+
 	wl_resource_post_event(resource,
 			       WL_SHELL_SURFACE_CONFIGURE,
 			       weston_compositor_get_time(), 0,
@@ -715,7 +841,13 @@ shell_get_shell_surface(struct wl_client *client,
 		(void (**)(void)) &shell_surface_implementation;
 	shsurf->resource.data = shsurf;
 
+	shsurf->saved_position_valid = false;
 	shsurf->surface = surface;
+	shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
+	shsurf->fullscreen.framerate = 0;
+	shsurf->fullscreen.black_surface = NULL;
+	wl_list_init(&shsurf->fullscreen.transform.link);
+
 	shsurf->surface_destroy_listener.func = shell_handle_surface_destroy;
 	wl_list_insert(surface->surface.resource.destroy_listener_list.prev,
 		       &shsurf->surface_destroy_listener.link);
@@ -728,6 +860,7 @@ shell_get_shell_surface(struct wl_client *client,
 	weston_matrix_init(&shsurf->rotation.rotation);
 
 	shsurf->type = SHELL_SURFACE_NONE;
+	shsurf->prev_type = SHELL_SURFACE_NONE;
 
 	wl_client_add_resource(client, &shsurf->resource);
 }
@@ -1274,6 +1407,9 @@ activate(struct weston_shell *base, struct weston_surface *es,
 				       &es->link);
 		}
 		break;
+	case SHELL_SURFACE_FULLSCREEN:
+		/* should on top of panels */
+		break;
 	default:
 		if (!shell->locked) {
 			list = weston_compositor_top(compositor);
@@ -1290,14 +1426,23 @@ activate(struct weston_shell *base, struct weston_surface *es,
 
 static void
 click_to_activate_binding(struct wl_input_device *device,
-                         uint32_t time, uint32_t key,
+			  uint32_t time, uint32_t key,
 			  uint32_t button, uint32_t state, void *data)
 {
 	struct weston_input_device *wd = (struct weston_input_device *) device;
 	struct weston_compositor *compositor = data;
 	struct weston_surface *focus;
+	struct weston_surface *upper;
 
 	focus = (struct weston_surface *) device->pointer_focus;
+	upper = container_of(focus->link.prev, struct weston_surface, link);
+	if (focus->link.prev != &compositor->surface_list &&
+	    get_shell_surface_type(upper) == SHELL_SURFACE_FULLSCREEN) {
+		printf("%s: focus is black surface, raise its fullscreen surface\n", __func__);
+		shell_stack_fullscreen(get_shell_surface(upper));
+		focus = upper;
+	}
+
 	if (state && focus && device->pointer_grab == &device->default_pointer_grab)
 		activate(compositor->shell, focus, wd, time);
 }
@@ -1444,11 +1589,13 @@ map(struct weston_shell *base, struct weston_surface *surface,
 					    10 + random() % 400);
 		break;
 	case SHELL_SURFACE_SCREENSAVER:
-	case SHELL_SURFACE_FULLSCREEN:
 		center_on_output(surface, shsurf->fullscreen_output);
 		break;
+	case SHELL_SURFACE_FULLSCREEN:
+		shell_map_fullscreen(shsurf);
+		break;
 	case SHELL_SURFACE_MAXIMIZED:
-		/*use surface configure to set the geometry*/
+		/* use surface configure to set the geometry */
 		panel_height = get_output_panel_height(shell,surface->output);
 		weston_surface_set_position(surface, surface->output->x,
 					    surface->output->y + panel_height);
@@ -1496,6 +1643,9 @@ map(struct weston_shell *base, struct weston_surface *surface,
 		}
 		do_configure = 0;
 		break;
+	case SHELL_SURFACE_FULLSCREEN:
+		do_configure = 1;
+		break;
 	case SHELL_SURFACE_NONE:
 		do_configure = 0;
 		break;
@@ -1526,7 +1676,7 @@ map(struct weston_shell *base, struct weston_surface *surface,
 		if (!shell->locked)
 			activate(base, surface,
 				 (struct weston_input_device *)
-					compositor->input_device,
+				 compositor->input_device,
 				 weston_compositor_get_time());
 		break;
 	default:
@@ -1543,11 +1693,14 @@ configure(struct weston_shell *base, struct weston_surface *surface,
 {
 	struct wl_shell *shell = container_of(base, struct wl_shell, shell);
 	enum shell_surface_type surface_type = SHELL_SURFACE_NONE;
+	enum shell_surface_type prev_surface_type = SHELL_SURFACE_NONE;
 	struct shell_surface *shsurf;
 
 	shsurf = get_shell_surface(surface);
-	if (shsurf)
+	if (shsurf) {
 		surface_type = shsurf->type;
+		prev_surface_type = shsurf->prev_type;
+	}
 
 	surface->geometry.x = x;
 	surface->geometry.y = y;
@@ -1557,22 +1710,41 @@ configure(struct weston_shell *base, struct weston_surface *surface,
 
 	switch (surface_type) {
 	case SHELL_SURFACE_SCREENSAVER:
-	case SHELL_SURFACE_FULLSCREEN:
 		center_on_output(surface, shsurf->fullscreen_output);
 		break;
+	case SHELL_SURFACE_FULLSCREEN:
+		shell_configure_fullscreen(shsurf);
+		if (prev_surface_type != SHELL_SURFACE_FULLSCREEN)
+			shell_stack_fullscreen(shsurf);
+		break;
 	case SHELL_SURFACE_MAXIMIZED:
-		/*setting x, y and using configure to change that geometry*/
+		/* setting x, y and using configure to change that geometry */
 		surface->geometry.x = surface->output->x;
 		surface->geometry.y = surface->output->y +
 			get_output_panel_height(shell,surface->output);
 		break;
+	case SHELL_SURFACE_TOPLEVEL:
+		if (prev_surface_type != SHELL_SURFACE_TOPLEVEL) {
+			if (shsurf->saved_position_valid &&
+			    shsurf->saved_x != surface->geometry.x &&
+			    shsurf->saved_y != surface->geometry.y) {
+				weston_surface_set_position(surface,
+							    shsurf->saved_x,
+							    shsurf->saved_y);
+			} else if (!shsurf->saved_position_valid) {
+				weston_surface_set_position(surface, 10 + random() % 400,
+							    10 + random() % 400);
+			}
+		}
+		break;
 	default:
 		break;
 	}
 
-	/*  XXX: would a fullscreen surface need the same handling? */
+	/* XXX: would a fullscreen surface need the same handling? */
 	if (surface->output) {
 		weston_surface_assign_output(surface);
+		weston_compositor_repick(surface->compositor);
 
 		if (surface_type == SHELL_SURFACE_SCREENSAVER)
 			surface->output = shsurf->output;
-- 
1.7.5.4



More information about the wayland-devel mailing list