shell: Add implementation of fullscreen.

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@linux.intel.com>
Signed-off-by: Juan Zhao <juan.j.zhao@linux.intel.com>
dev
Alex Wu 13 years ago committed by Kristian Høgsberg
parent 067fd60534
commit b9747d02c6
  1. 204
      src/shell.c

@ -93,7 +93,9 @@ struct shell_surface {
struct shell_surface *parent; struct shell_surface *parent;
enum shell_surface_type type; enum shell_surface_type type;
enum shell_surface_type prev_type;
int32_t saved_x, saved_y; int32_t saved_x, saved_y;
bool saved_position_valid;
struct { struct {
struct weston_transform transform; struct weston_transform transform;
@ -108,6 +110,13 @@ struct shell_surface {
int32_t initial_up; int32_t initial_up;
} popup; } 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 *fullscreen_output;
struct weston_output *output; struct weston_output *output;
struct wl_list link; struct wl_list link;
@ -133,6 +142,10 @@ struct rotate_grab {
} center; } center;
}; };
static void
center_on_output(struct weston_surface *surface,
struct weston_output *output);
static void static void
shell_configuration(struct wl_shell *shell) shell_configuration(struct wl_shell *shell)
{ {
@ -303,7 +316,8 @@ weston_surface_resize(struct shell_surface *shsurf,
{ {
struct weston_resize_grab *resize; struct weston_resize_grab *resize;
/* FIXME: Reject if fullscreen */ if (shsurf->type == SHELL_SURFACE_FULLSCREEN)
return 0;
if (edges == 0 || edges > 15 || if (edges == 0 || edges > 15 ||
(edges & 3) == 3 || (edges & 12) == 12) (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 weston_input_device *wd = input_resource->data;
struct shell_surface *shsurf = 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 || if (wd->input_device.button_count == 0 ||
wd->input_device.grab_time != time || wd->input_device.grab_time != time ||
@ -352,15 +367,26 @@ get_default_output(struct weston_compositor *compositor)
struct weston_output, link); 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 static int
reset_shell_surface_type(struct shell_surface *surface) reset_shell_surface_type(struct shell_surface *surface)
{ {
switch (surface->type) { switch (surface->type) {
case SHELL_SURFACE_FULLSCREEN: case SHELL_SURFACE_FULLSCREEN:
weston_surface_set_position(surface->surface, shell_unset_fullscreen(surface);
surface->saved_x,
surface->saved_y);
surface->fullscreen_output = NULL;
break; break;
case SHELL_SURFACE_MAXIMIZED: case SHELL_SURFACE_MAXIMIZED:
surface->output = get_default_output(surface->surface->compositor); surface->output = get_default_output(surface->surface->compositor);
@ -386,6 +412,7 @@ reset_shell_surface_type(struct shell_surface *surface)
break; break;
} }
surface->prev_type = surface->type;
surface->type = SHELL_SURFACE_NONE; surface->type = SHELL_SURFACE_NONE;
return 0; return 0;
} }
@ -474,6 +501,7 @@ shell_surface_set_maximized(struct wl_client *client,
shsurf->saved_x = es->geometry.x; shsurf->saved_x = es->geometry.x;
shsurf->saved_y = es->geometry.y; shsurf->saved_y = es->geometry.y;
shsurf->saved_position_valid = true;
wlshell = shell_surface_get_shell(shsurf); wlshell = shell_surface_get_shell(shsurf);
panel_height = get_output_panel_height(wlshell, es->output); 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; 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 static void
shell_surface_set_fullscreen(struct wl_client *client, shell_surface_set_fullscreen(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *resource,
@ -496,21 +614,29 @@ shell_surface_set_fullscreen(struct wl_client *client,
{ {
struct shell_surface *shsurf = resource->data; struct shell_surface *shsurf = resource->data;
struct weston_surface *es = shsurf->surface; 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)) if (reset_shell_surface_type(shsurf))
return; return;
/* FIXME: Fullscreen on first output */ if (shsurf->prev_type != SHELL_SURFACE_FULLSCREEN) {
/* FIXME: Handle output going away */
output = get_default_output(es->compositor);
shsurf->saved_x = es->geometry.x; shsurf->saved_x = es->geometry.x;
shsurf->saved_y = es->geometry.y; shsurf->saved_y = es->geometry.y;
shsurf->output = output; shsurf->saved_position_valid = true;
shsurf->fullscreen_output = output; }
shsurf->fullscreen_output = shsurf->output;
shsurf->fullscreen.type = method;
shsurf->fullscreen.framerate = framerate;
shsurf->type = SHELL_SURFACE_FULLSCREEN; shsurf->type = SHELL_SURFACE_FULLSCREEN;
if (es->output)
shsurf->surface->force_configure = 1;
wl_resource_post_event(resource, wl_resource_post_event(resource,
WL_SHELL_SURFACE_CONFIGURE, WL_SHELL_SURFACE_CONFIGURE,
weston_compositor_get_time(), 0, weston_compositor_get_time(), 0,
@ -715,7 +841,13 @@ shell_get_shell_surface(struct wl_client *client,
(void (**)(void)) &shell_surface_implementation; (void (**)(void)) &shell_surface_implementation;
shsurf->resource.data = shsurf; shsurf->resource.data = shsurf;
shsurf->saved_position_valid = false;
shsurf->surface = surface; 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; shsurf->surface_destroy_listener.func = shell_handle_surface_destroy;
wl_list_insert(surface->surface.resource.destroy_listener_list.prev, wl_list_insert(surface->surface.resource.destroy_listener_list.prev,
&shsurf->surface_destroy_listener.link); &shsurf->surface_destroy_listener.link);
@ -728,6 +860,7 @@ shell_get_shell_surface(struct wl_client *client,
weston_matrix_init(&shsurf->rotation.rotation); weston_matrix_init(&shsurf->rotation.rotation);
shsurf->type = SHELL_SURFACE_NONE; shsurf->type = SHELL_SURFACE_NONE;
shsurf->prev_type = SHELL_SURFACE_NONE;
wl_client_add_resource(client, &shsurf->resource); wl_client_add_resource(client, &shsurf->resource);
} }
@ -1274,6 +1407,9 @@ activate(struct weston_shell *base, struct weston_surface *es,
&es->link); &es->link);
} }
break; break;
case SHELL_SURFACE_FULLSCREEN:
/* should on top of panels */
break;
default: default:
if (!shell->locked) { if (!shell->locked) {
list = weston_compositor_top(compositor); list = weston_compositor_top(compositor);
@ -1296,8 +1432,17 @@ click_to_activate_binding(struct wl_input_device *device,
struct weston_input_device *wd = (struct weston_input_device *) device; struct weston_input_device *wd = (struct weston_input_device *) device;
struct weston_compositor *compositor = data; struct weston_compositor *compositor = data;
struct weston_surface *focus; struct weston_surface *focus;
struct weston_surface *upper;
focus = (struct weston_surface *) device->pointer_focus; 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) if (state && focus && device->pointer_grab == &device->default_pointer_grab)
activate(compositor->shell, focus, wd, time); activate(compositor->shell, focus, wd, time);
} }
@ -1444,9 +1589,11 @@ map(struct weston_shell *base, struct weston_surface *surface,
10 + random() % 400); 10 + random() % 400);
break; break;
case SHELL_SURFACE_SCREENSAVER: case SHELL_SURFACE_SCREENSAVER:
case SHELL_SURFACE_FULLSCREEN:
center_on_output(surface, shsurf->fullscreen_output); center_on_output(surface, shsurf->fullscreen_output);
break; break;
case SHELL_SURFACE_FULLSCREEN:
shell_map_fullscreen(shsurf);
break;
case SHELL_SURFACE_MAXIMIZED: 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); panel_height = get_output_panel_height(shell,surface->output);
@ -1496,6 +1643,9 @@ map(struct weston_shell *base, struct weston_surface *surface,
} }
do_configure = 0; do_configure = 0;
break; break;
case SHELL_SURFACE_FULLSCREEN:
do_configure = 1;
break;
case SHELL_SURFACE_NONE: case SHELL_SURFACE_NONE:
do_configure = 0; do_configure = 0;
break; break;
@ -1543,11 +1693,14 @@ configure(struct weston_shell *base, struct weston_surface *surface,
{ {
struct wl_shell *shell = container_of(base, struct wl_shell, shell); struct wl_shell *shell = container_of(base, struct wl_shell, shell);
enum shell_surface_type surface_type = SHELL_SURFACE_NONE; enum shell_surface_type surface_type = SHELL_SURFACE_NONE;
enum shell_surface_type prev_surface_type = SHELL_SURFACE_NONE;
struct shell_surface *shsurf; struct shell_surface *shsurf;
shsurf = get_shell_surface(surface); shsurf = get_shell_surface(surface);
if (shsurf) if (shsurf) {
surface_type = shsurf->type; surface_type = shsurf->type;
prev_surface_type = shsurf->prev_type;
}
surface->geometry.x = x; surface->geometry.x = x;
surface->geometry.y = y; surface->geometry.y = y;
@ -1557,15 +1710,33 @@ configure(struct weston_shell *base, struct weston_surface *surface,
switch (surface_type) { switch (surface_type) {
case SHELL_SURFACE_SCREENSAVER: case SHELL_SURFACE_SCREENSAVER:
case SHELL_SURFACE_FULLSCREEN:
center_on_output(surface, shsurf->fullscreen_output); center_on_output(surface, shsurf->fullscreen_output);
break; 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: 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.x = surface->output->x;
surface->geometry.y = surface->output->y + surface->geometry.y = surface->output->y +
get_output_panel_height(shell,surface->output); get_output_panel_height(shell,surface->output);
break; 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: default:
break; break;
} }
@ -1573,6 +1744,7 @@ configure(struct weston_shell *base, struct weston_surface *surface,
/* XXX: would a fullscreen surface need the same handling? */ /* XXX: would a fullscreen surface need the same handling? */
if (surface->output) { if (surface->output) {
weston_surface_assign_output(surface); weston_surface_assign_output(surface);
weston_compositor_repick(surface->compositor);
if (surface_type == SHELL_SURFACE_SCREENSAVER) if (surface_type == SHELL_SURFACE_SCREENSAVER)
surface->output = shsurf->output; surface->output = shsurf->output;

Loading…
Cancel
Save