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;
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);
}
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);
}
{
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;
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. */
- weston_surface_update_transform(es);
+ /* 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)
/*
}
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)
{
struct weston_output *output;
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);
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);
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);
}
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);
}
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);
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);
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;
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;
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 =
+ create_black_surface(surface->compositor,
+ output->x, output->y,
+ 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) {
{
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);
- }
+ weston_surface_damage(surface);
+ weston_surface_damage(shsurf->fullscreen.black_surface);
}
static void
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);
}
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;
}
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;
}
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;
}
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)
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);
{
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);
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;
}
}
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;
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);
{
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;
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. */
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;
- }
+ 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:
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,