compositor: Organize surface stack using new struct weston_layer

The surface data structure is now a list of list of surfaces.  The core
compositor defines the fade and cursor layer, and it's up to the shell to
provide more layers for the various surface types it implements.
This commit is contained in:
Kristian Høgsberg 2012-02-29 12:42:35 -05:00
parent 944236a712
commit 3be2ce9e49
3 changed files with 123 additions and 162 deletions

View File

@ -211,6 +211,7 @@ weston_surface_create(struct weston_compositor *compositor)
wl_list_init(&surface->surface.resource.destroy_listener_list);
wl_list_init(&surface->link);
wl_list_init(&surface->layer_link);
wl_list_init(&surface->buffer_link);
surface->surface.resource.client = NULL;
@ -600,6 +601,7 @@ weston_surface_unmap(struct weston_surface *surface)
weston_surface_damage_below(surface);
surface->output = NULL;
wl_list_remove(&surface->link);
wl_list_remove(&surface->layer_link);
weston_compositor_repick(surface->compositor);
weston_compositor_schedule_repaint(surface->compositor);
}
@ -808,37 +810,15 @@ out:
pixman_region32_fini(&repaint);
}
WL_EXPORT struct wl_list *
weston_compositor_top(struct weston_compositor *compositor)
{
struct weston_input_device *input_device;
struct wl_list *list;
input_device = (struct weston_input_device *) compositor->input_device;
/* Insert below pointer */
list = &compositor->surface_list;
if (compositor->fade.surface &&
list->next == &compositor->fade.surface->link)
list = list->next;
if (list->next == &input_device->sprite->link)
list = list->next;
if (input_device->drag_surface &&
list->next == &input_device->drag_surface->link)
list = list->next;
return list;
}
static void
weston_surface_raise(struct weston_surface *surface)
WL_EXPORT void
weston_surface_restack(struct weston_surface *surface, struct wl_list *below)
{
struct weston_compositor *compositor = surface->compositor;
struct wl_list *list = weston_compositor_top(compositor);
wl_list_remove(&surface->link);
wl_list_insert(list, &surface->link);
wl_list_remove(&surface->layer_link);
wl_list_insert(below, &surface->layer_link);
weston_compositor_repick(compositor);
weston_surface_damage_below(surface);
weston_surface_damage(surface);
}
@ -912,6 +892,7 @@ weston_output_repaint(struct weston_output *output, int msecs)
{
struct weston_compositor *ec = output->compositor;
struct weston_surface *es;
struct weston_layer *layer;
struct weston_animation *animation, *next;
struct weston_frame_callback *cb, *cnext;
pixman_region32_t opaque, new_damage, output_damage;
@ -925,10 +906,14 @@ weston_output_repaint(struct weston_output *output, int msecs)
output->border.top + output->border.bottom;
glViewport(0, 0, width, height);
wl_list_for_each(es, &ec->surface_list, link)
/* Update surface transform now to avoid calling it ever
* again from the repaint sub-functions. */
/* Rebuild the surface list and update surface transforms up front. */
wl_list_init(&ec->surface_list);
wl_list_for_each(layer, &ec->layer_list, link) {
wl_list_for_each(es, &layer->surface_list, layer_link) {
weston_surface_update_transform(es);
wl_list_insert(ec->surface_list.prev, &es->link);
}
}
if (output->assign_planes)
/*
@ -1002,6 +987,13 @@ weston_output_finish_frame(struct weston_output *output, int msecs)
output->repaint_scheduled = 0;
}
WL_EXPORT void
weston_layer_init(struct weston_layer *layer, struct wl_list *below)
{
wl_list_init(&layer->surface_list);
wl_list_insert(below, &layer->link);
}
WL_EXPORT void
weston_compositor_schedule_repaint(struct weston_compositor *compositor)
{
@ -1041,7 +1033,8 @@ weston_compositor_fade(struct weston_compositor *compositor, float tint)
surface = weston_surface_create(compositor);
weston_surface_configure(surface, 0, 0, 8192, 8192);
weston_surface_set_color(surface, 0.0, 0.0, 0.0, 0.0);
wl_list_insert(&compositor->surface_list, &surface->link);
wl_list_insert(&compositor->fade_layer.surface_list,
&surface->layer_link);
weston_surface_assign_output(surface);
compositor->fade.surface = surface;
pixman_region32_init(&surface->input);
@ -1489,7 +1482,6 @@ WL_EXPORT void
weston_surface_activate(struct weston_surface *surface,
struct weston_input_device *device, uint32_t time)
{
weston_surface_raise(surface);
wl_input_device_set_keyboard_focus(&device->input_device,
&surface->surface, time);
wl_data_device_set_keyboard_focus(&device->input_device);
@ -1814,13 +1806,14 @@ input_device_attach(struct wl_client *client,
if (!buffer_resource && device->sprite->output) {
wl_list_remove(&device->sprite->link);
wl_list_remove(&device->sprite->layer_link);
device->sprite->output = NULL;
return;
}
if (!device->sprite->output) {
wl_list_insert(&compositor->surface_list,
&device->sprite->link);
wl_list_insert(&compositor->cursor_layer.surface_list,
&device->sprite->layer_link);
weston_surface_assign_output(device->sprite);
}
@ -1924,8 +1917,8 @@ weston_input_update_drag_surface(struct wl_input_device *input_device,
if (device->drag_surface->output == NULL &&
device->drag_surface->buffer) {
wl_list_insert(&device->sprite->link,
&device->drag_surface->link);
wl_list_insert(&device->sprite->layer_link,
&device->drag_surface->layer_link);
weston_surface_assign_output(device->drag_surface);
empty_region(&device->drag_surface->input);
}
@ -2270,6 +2263,7 @@ weston_compositor_init(struct weston_compositor *ec, struct wl_display *display)
ec->bind_display(ec->display, ec->wl_display);
wl_list_init(&ec->surface_list);
wl_list_init(&ec->layer_list);
wl_list_init(&ec->input_device_list);
wl_list_init(&ec->output_list);
wl_list_init(&ec->binding_list);
@ -2278,6 +2272,9 @@ weston_compositor_init(struct weston_compositor *ec, struct wl_display *display)
ec->fade.animation.frame = fade_frame;
wl_list_init(&ec->fade.animation.link);
weston_layer_init(&ec->fade_layer, &ec->layer_list);
weston_layer_init(&ec->cursor_layer, &ec->fade_layer.link);
ec->screenshooter = screenshooter_create(ec);
wl_data_device_manager_init(ec->wl_display);

View File

@ -163,6 +163,11 @@ enum {
struct screenshooter;
struct weston_layer {
struct wl_list surface_list;
struct wl_list link;
};
struct weston_compositor {
struct wl_shm *shm;
struct weston_xserver *wxs;
@ -181,8 +186,12 @@ struct weston_compositor {
/* There can be more than one, but not right now... */
struct wl_input_device *input_device;
struct weston_layer fade_layer;
struct weston_layer cursor_layer;
struct wl_list output_list;
struct wl_list input_device_list;
struct wl_list layer_list;
struct wl_list surface_list;
struct wl_list binding_list;
struct wl_list animation_list;
@ -267,6 +276,7 @@ struct weston_surface {
pixman_region32_t input;
int32_t pitch;
struct wl_list link;
struct wl_list layer_link;
struct wl_list buffer_link;
struct weston_shader *shader;
GLfloat color[4];
@ -371,6 +381,9 @@ void
notify_touch(struct wl_input_device *device, uint32_t time, int touch_id,
int x, int y, int touch_type);
void
weston_layer_init(struct weston_layer *layer, struct wl_list *below);
void
weston_output_finish_frame(struct weston_output *output, int msecs);
void
@ -423,6 +436,9 @@ void
weston_surface_configure(struct weston_surface *surface,
GLfloat x, GLfloat y, int width, int height);
void
weston_surface_restack(struct weston_surface *surface, struct wl_list *below);
void
weston_surface_set_position(struct weston_surface *surface,
GLfloat x, GLfloat y);

View File

@ -42,6 +42,12 @@ struct wl_shell {
struct weston_compositor *compositor;
struct weston_shell shell;
struct weston_layer fullscreen_layer;
struct weston_layer panel_layer;
struct weston_layer toplevel_layer;
struct weston_layer background_layer;
struct weston_layer lock_layer;
struct {
struct weston_process process;
struct wl_client *client;
@ -56,7 +62,6 @@ struct wl_shell {
struct shell_surface *lock_surface;
struct wl_listener lock_surface_listener;
struct wl_list hidden_surface_list;
struct wl_list backgrounds;
struct wl_list panels;
@ -545,11 +550,15 @@ shell_configure_fullscreen(struct shell_surface *shsurf)
center_on_output(surface, output);
if (!shsurf->fullscreen.black_surface)
shsurf->fullscreen.black_surface = create_black_surface(surface->compositor,
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);
output->current->width,
output->current->height);
wl_list_remove(&shsurf->fullscreen.black_surface->layer_link);
wl_list_insert(&surface->layer_link,
&shsurf->fullscreen.black_surface->layer_link);
shsurf->fullscreen.black_surface->output = output;
switch (shsurf->fullscreen.type) {
@ -580,23 +589,18 @@ 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);
wl_list_remove(&surface->layer_link);
wl_list_remove(&shsurf->fullscreen.black_surface->layer_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);
wl_list_insert(&shell->fullscreen_layer.surface_list,
&surface->layer_link);
wl_list_insert(&surface->layer_link,
&shsurf->fullscreen.black_surface->layer_link);
weston_surface_damage(surface);
weston_surface_damage(shsurf->fullscreen.black_surface);
}
}
static void
shell_map_fullscreen(struct shell_surface *shsurf)
@ -902,12 +906,12 @@ show_screensaver(struct wl_shell *shell, struct shell_surface *surface)
struct wl_list *list;
if (shell->lock_surface)
list = &shell->lock_surface->surface->link;
list = &shell->lock_surface->surface->layer_link;
else
list = &shell->compositor->surface_list;
list = &shell->lock_layer.surface_list;
wl_list_remove(&surface->surface->link);
wl_list_insert(list, &surface->surface->link);
wl_list_remove(&surface->surface->layer_link);
wl_list_insert(list, &surface->surface->layer_link);
surface->surface->output = surface->output;
weston_surface_damage(surface->surface);
}
@ -915,8 +919,8 @@ show_screensaver(struct wl_shell *shell, struct shell_surface *surface)
static void
hide_screensaver(struct wl_shell *shell, struct shell_surface *surface)
{
wl_list_remove(&surface->surface->link);
wl_list_init(&surface->surface->link);
wl_list_remove(&surface->surface->layer_link);
wl_list_init(&surface->surface->layer_link);
surface->surface->output = NULL;
}
@ -937,7 +941,7 @@ desktop_shell_set_background(struct wl_client *client,
wl_list_for_each(priv, &shell->backgrounds, link) {
if (priv->output == output_resource->data) {
priv->surface->output = NULL;
wl_list_remove(&priv->surface->link);
wl_list_remove(&priv->surface->layer_link);
wl_list_remove(&priv->link);
break;
}
@ -975,7 +979,7 @@ desktop_shell_set_panel(struct wl_client *client,
wl_list_for_each(priv, &shell->panels, link) {
if (priv->output == output_resource->data) {
priv->surface->output = NULL;
wl_list_remove(&priv->surface->link);
wl_list_remove(&priv->surface->layer_link);
wl_list_remove(&priv->link);
break;
}
@ -1035,8 +1039,6 @@ desktop_shell_set_lock_surface(struct wl_client *client,
static void
resume_desktop(struct wl_shell *shell)
{
struct weston_surface *surface;
struct wl_list *list;
struct shell_surface *tmp;
wl_list_for_each(tmp, &shell->screensaver.surfaces, link)
@ -1044,21 +1046,12 @@ resume_desktop(struct wl_shell *shell)
terminate_screensaver(shell);
wl_list_for_each(surface, &shell->hidden_surface_list, link)
weston_surface_assign_output(surface);
if (wl_list_empty(&shell->backgrounds)) {
list = &shell->compositor->surface_list;
} else {
struct shell_surface *background;
background = container_of(shell->backgrounds.prev,
struct shell_surface, link);
list = background->surface->link.prev;
}
if (!wl_list_empty(&shell->hidden_surface_list))
wl_list_insert_list(list, &shell->hidden_surface_list);
wl_list_init(&shell->hidden_surface_list);
wl_list_remove(&shell->lock_layer.link);
wl_list_insert(&shell->compositor->cursor_layer.link,
&shell->fullscreen_layer.link);
wl_list_insert(&shell->fullscreen_layer.link,
&shell->panel_layer.link);
wl_list_insert(&shell->panel_layer.link, &shell->toplevel_layer.link);
shell->locked = false;
weston_compositor_repick(shell->compositor);
@ -1380,7 +1373,6 @@ activate(struct weston_shell *base, struct weston_surface *es,
{
struct wl_shell *shell = container_of(base, struct wl_shell, shell);
struct weston_compositor *compositor = shell->compositor;
struct wl_list *list;
weston_surface_activate(es, device, time);
@ -1389,35 +1381,23 @@ activate(struct weston_shell *base, struct weston_surface *es,
switch (get_shell_surface_type(es)) {
case SHELL_SURFACE_BACKGROUND:
/* put background back to bottom */
wl_list_remove(&es->link);
wl_list_insert(compositor->surface_list.prev, &es->link);
break;
case SHELL_SURFACE_PANEL:
/* already put on top */
case SHELL_SURFACE_LOCK:
break;
case SHELL_SURFACE_SCREENSAVER:
/* always below lock surface */
if (shell->lock_surface) {
wl_list_remove(&es->link);
wl_list_insert(&shell->lock_surface->surface->link,
&es->link);
}
if (shell->lock_surface)
weston_surface_restack(es,
&shell->lock_surface->surface->layer_link);
break;
case SHELL_SURFACE_FULLSCREEN:
/* should on top of panels */
break;
default:
if (!shell->locked) {
list = weston_compositor_top(compositor);
/* bring panel back to top */
struct shell_surface *panel;
wl_list_for_each(panel, &shell->panels, link) {
wl_list_remove(&panel->surface->link);
wl_list_insert(list, &panel->surface->link);
}
}
weston_surface_restack(es,
&shell->toplevel_layer.surface_list);
break;
}
}
@ -1448,9 +1428,6 @@ static void
lock(struct weston_shell *base)
{
struct wl_shell *shell = container_of(base, struct wl_shell, shell);
struct wl_list *surface_list = &shell->compositor->surface_list;
struct weston_surface *cur;
struct weston_surface *tmp;
struct weston_input_device *device;
struct shell_surface *shsurf;
struct weston_output *output;
@ -1466,28 +1443,15 @@ lock(struct weston_shell *base)
shell->locked = true;
/* Move all surfaces from compositor's list to our hidden list,
* except the background. This way nothing else can show or
* receive input events while we are locked. */
/* Hide all surfaces by removing the fullscreen, panel and
* toplevel layers. This way nothing else can show or receive
* input events while we are locked. */
if (!wl_list_empty(&shell->hidden_surface_list)) {
fprintf(stderr,
"%s: Assertion failed: hidden_surface_list is not empty.\n",
__func__);
}
wl_list_for_each_safe(cur, tmp, surface_list, link) {
/* skip input device sprites, cur->surface is uninitialised */
if (cur->surface.resource.client == NULL)
continue;
if (get_shell_surface_type(cur) == SHELL_SURFACE_BACKGROUND)
continue;
cur->output = NULL;
wl_list_remove(&cur->link);
wl_list_insert(shell->hidden_surface_list.prev, &cur->link);
}
wl_list_remove(&shell->panel_layer.link);
wl_list_remove(&shell->toplevel_layer.link);
wl_list_remove(&shell->fullscreen_layer.link);
wl_list_insert(&shell->compositor->cursor_layer.link,
&shell->lock_layer.link);
launch_screensaver(shell);
@ -1555,24 +1519,14 @@ map(struct weston_shell *base, struct weston_surface *surface,
{
struct wl_shell *shell = container_of(base, struct wl_shell, shell);
struct weston_compositor *compositor = shell->compositor;
struct wl_list *list;
struct shell_surface *shsurf;
enum shell_surface_type surface_type = SHELL_SURFACE_NONE;
int do_configure;
int panel_height = 0;
shsurf = get_shell_surface(surface);
if (shsurf)
surface_type = shsurf->type;
if (shell->locked) {
list = &shell->hidden_surface_list;
do_configure = 0;
} else {
list = weston_compositor_top(compositor);
do_configure = 1;
}
surface->geometry.width = width;
surface->geometry.height = height;
surface->geometry.dirty = 1;
@ -1615,19 +1569,19 @@ map(struct weston_shell *base, struct weston_surface *surface,
switch (surface_type) {
case SHELL_SURFACE_BACKGROUND:
/* background always visible, at the bottom */
wl_list_insert(compositor->surface_list.prev, &surface->link);
do_configure = 1;
wl_list_insert(&shell->background_layer.surface_list,
&surface->layer_link);
break;
case SHELL_SURFACE_PANEL:
/* panel always on top, hidden while locked */
wl_list_insert(list, &surface->link);
wl_list_insert(&shell->panel_layer.surface_list,
&surface->layer_link);
break;
case SHELL_SURFACE_LOCK:
/* lock surface always visible, on top */
wl_list_insert(&compositor->surface_list, &surface->link);
wl_list_insert(&shell->lock_layer.surface_list,
&surface->layer_link);
weston_compositor_wake(compositor);
do_configure = 1;
break;
case SHELL_SURFACE_SCREENSAVER:
/* If locked, show it. */
@ -1638,32 +1592,20 @@ map(struct weston_shell *base, struct weston_surface *surface,
if (!shell->lock_surface)
compositor->state = WESTON_COMPOSITOR_IDLE;
}
do_configure = 0;
break;
case SHELL_SURFACE_FULLSCREEN:
do_configure = 1;
break;
case SHELL_SURFACE_NONE:
do_configure = 0;
break;
default:
/* everything else just below the panel */
if (!wl_list_empty(&shell->panels)) {
struct shell_surface *panel =
container_of(shell->panels.prev,
struct shell_surface, link);
wl_list_insert(&panel->surface->link, &surface->link);
} else {
wl_list_insert(list, &surface->link);
}
wl_list_insert(&shell->toplevel_layer.surface_list,
&surface->layer_link);
break;
}
if (do_configure) {
weston_surface_assign_output(surface);
weston_compositor_repick(compositor);
if (surface_type == SHELL_SURFACE_MAXIMIZED)
surface->output = shsurf->output;
}
switch (surface_type) {
case SHELL_SURFACE_TOPLEVEL:
@ -2054,11 +1996,17 @@ shell_init(struct weston_compositor *ec)
shell->shell.configure = configure;
shell->shell.destroy = shell_destroy;
wl_list_init(&shell->hidden_surface_list);
wl_list_init(&shell->backgrounds);
wl_list_init(&shell->panels);
wl_list_init(&shell->screensaver.surfaces);
weston_layer_init(&shell->fullscreen_layer, &ec->cursor_layer.link);
weston_layer_init(&shell->panel_layer, &shell->fullscreen_layer.link);
weston_layer_init(&shell->toplevel_layer, &shell->panel_layer.link);
weston_layer_init(&shell->background_layer,
&shell->toplevel_layer.link);
wl_list_init(&shell->lock_layer.surface_list);
shell_configuration(shell);
if (wl_display_add_global(ec->wl_display, &wl_shell_interface,