diff --git a/src/compositor.c b/src/compositor.c index 679894b7..95513da1 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -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. */ - 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) /* @@ -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); diff --git a/src/compositor.h b/src/compositor.h index 9f29c4b5..d0b7206d 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -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); diff --git a/src/shell.c b/src/shell.c index accc1c56..6afdf3ae 100644 --- a/src/shell.c +++ b/src/shell.c @@ -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, - 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) { @@ -580,22 +589,17 @@ 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); - } + weston_surface_damage(surface); + weston_surface_damage(shsurf->fullscreen.black_surface); } static void @@ -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; - } + 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,