[PATCH 2/3] shell: Add implementation of fullscreen.
zhiwen.wu at linux.intel.com
zhiwen.wu at linux.intel.com
Sat Feb 25 23:21:37 PST 2012
From: Alex Wu <zhiwen.wu at linux.intel.com>
For now, fullscreen surface will be atop panels and with a black surface underlying it.
Only the WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE method implemented in this patch. For
other methods, just center on the surface.
---
src/shell.c | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 191 insertions(+), 16 deletions(-)
diff --git a/src/shell.c b/src/shell.c
index ee71dcc..641a53f 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -108,6 +108,14 @@ struct shell_surface {
int32_t initial_up;
} popup;
+ struct {
+ enum wl_shell_surface_fullscreen_method type;
+ struct weston_transform transform; /* matrix from x, y */
+ bool setted;/*If transform already added to the list*/
+ uint32_t framerate;
+ struct weston_surface *black_surface;
+ } fullscreen;
+
struct weston_output *fullscreen_output;
struct weston_output *output;
struct wl_list link;
@@ -130,6 +138,14 @@ struct rotate_grab {
};
static void
+activate(struct weston_shell *base, struct weston_surface *es,
+ struct weston_input_device *device, uint32_t time);
+
+static void
+center_on_output(struct weston_surface *surface,
+ struct weston_output *output);
+
+static void
shell_configuration(struct wl_shell *shell)
{
char *config_file;
@@ -299,7 +315,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)
@@ -330,7 +347,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 ||
@@ -348,15 +366,32 @@ get_default_output(struct weston_compositor *compositor)
struct weston_output, link);
}
+static void
+shell_unmap_fullscreen(struct shell_surface *shsurf)
+{
+ weston_surface_set_position(shsurf->surface,
+ shsurf->saved_x,
+ shsurf->saved_y);
+ shsurf->fullscreen_output = NULL;
+ shsurf->fullscreen.type = 0;
+ weston_surface_unmap(shsurf->fullscreen.black_surface);
+ wl_list_init(&shsurf->fullscreen.black_surface->link);
+ weston_surface_unmap(shsurf->surface);
+ wl_list_init(&shsurf->surface->link);
+
+ if (shsurf->fullscreen.setted) {
+ wl_list_remove(&shsurf->fullscreen.transform.link);
+ wl_list_init(&shsurf->fullscreen.transform.link);
+ shsurf->fullscreen.setted = false;
+ }
+}
+
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_unmap_fullscreen(surface);
break;
case SHELL_SURFACE_MAXIMIZED:
surface->output = get_default_output(surface->surface->compositor);
@@ -483,6 +518,112 @@ shell_surface_set_maximized(struct wl_client *client,
shsurf->type = SHELL_SURFACE_MAXIMIZED;
}
+static struct weston_surface *
+create_black_surface(struct weston_compositor *ec)
+{
+ struct weston_surface *surface = NULL;
+
+ surface = weston_surface_create(ec);
+ if (surface == NULL) {
+ fprintf(stderr, "no memory\n");
+ return NULL;
+ }
+
+ weston_surface_configure(surface, 0, 0, 8192, 8192);
+ weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
+ return 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;
+
+ center_on_output(surface, 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);
+ weston_matrix_scale(matrix,
+ (float)output->current->width/(float)surface->geometry.width,
+ (float)output->current->width/(float)surface->geometry.width,
+ 1.0);
+ if (!shsurf->fullscreen.setted) {
+ wl_list_insert(surface->geometry.transformation_list.prev,
+ &shsurf->fullscreen.transform.link);
+ shsurf->fullscreen.setted = true;
+ }
+ 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;
+ }
+}
+
+/*
+ * Handle the stacking order of the fullscreen surface and the associated black surface.
+ */
+static void
+shell_stack_fullscreen(struct shell_surface *shsurf, bool mapped)
+{
+ struct weston_surface *surface = shsurf->surface;
+ struct wl_shell *shell = shell_surface_get_shell(shsurf);
+ struct wl_list *list;
+
+ if (mapped) {
+ 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);
+
+ /*assign output*/
+ surface->output = shsurf->fullscreen_output;
+ shsurf->fullscreen.black_surface->output = shsurf->fullscreen_output;
+ if (!wl_list_empty(&surface->frame_callback_list)) {
+ wl_list_insert_list(surface->output->frame_callback_list.prev,
+ &surface->frame_callback_list);
+ wl_list_init(&surface->frame_callback_list);
+ }
+
+ weston_compositor_repick(surface->compositor);
+ 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, false);
+}
+
+static void
+shell_raise_fullscreen(struct shell_surface *shsurf)
+{
+ shell_configure_fullscreen(shsurf);
+ shell_stack_fullscreen(shsurf, true);
+}
+
static void
shell_surface_set_fullscreen(struct wl_client *client,
struct wl_resource *resource,
@@ -492,21 +633,37 @@ shell_surface_set_fullscreen(struct wl_client *client,
{
struct shell_surface *shsurf = resource->data;
struct weston_surface *es = shsurf->surface;
- struct weston_output *output;
+ struct wl_shell *shell;
+
+ 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);
-
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 (shsurf->fullscreen.black_surface == NULL)
+ shsurf->fullscreen.black_surface = create_black_surface(es->compositor);
+
+ if (es->output) {
+ /*already mapped, just raise it on top*/
+ shell_raise_fullscreen(shsurf);
+ shell = shell_surface_get_shell(shsurf);
+ if (!shell->locked)
+ activate(es->compositor->shell, es,
+ (struct weston_input_device *)
+ es->compositor->input_device,
+ weston_compositor_get_time());
+ }
+
wl_resource_post_event(resource,
WL_SHELL_SURFACE_CONFIGURE,
weston_compositor_get_time(), 0,
@@ -649,6 +806,9 @@ destroy_shell_surface(struct wl_resource *resource)
if (shsurf->surface)
wl_list_remove(&shsurf->surface_destroy_listener.link);
+ if (shsurf->fullscreen.black_surface)
+ destroy_surface(&shsurf->fullscreen.black_surface->surface.resource);
+
wl_list_remove(&shsurf->link);
free(shsurf);
}
@@ -712,6 +872,11 @@ shell_get_shell_surface(struct wl_client *client,
shsurf->resource.data = shsurf;
shsurf->surface = surface;
+ shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
+ shsurf->fullscreen.framerate = 0;
+ shsurf->fullscreen.setted = false;
+ shsurf->fullscreen.black_surface = NULL;
+
shsurf->surface_destroy_listener.func = shell_handle_surface_destroy;
wl_list_insert(surface->surface.resource.destroy_listener_list.prev,
&shsurf->surface_destroy_listener.link);
@@ -1254,6 +1419,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);
@@ -1418,9 +1586,11 @@ 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*/
panel_height = get_output_panel_height(shell,surface->output);
@@ -1470,6 +1640,9 @@ map(struct weston_shell *base, struct weston_surface *surface,
}
do_configure = 0;
break;
+ case SHELL_SURFACE_FULLSCREEN:
+ do_configure = 0;
+ break;
case SHELL_SURFACE_NONE:
do_configure = 0;
break;
@@ -1500,7 +1673,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:
@@ -1531,9 +1704,11 @@ 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);
+ break;
case SHELL_SURFACE_MAXIMIZED:
/*setting x, y and using configure to change that geometry*/
surface->geometry.x = surface->output->x;
--
1.7.5.4
More information about the wayland-devel
mailing list