diff --git a/src/compositor-drm.c b/src/compositor-drm.c index cfaad15d..d2a5652b 100644 --- a/src/compositor-drm.c +++ b/src/compositor-drm.c @@ -214,7 +214,8 @@ drm_output_prepare_scanout_surface(struct drm_output *output) } static void -drm_output_repaint(struct weston_output *output_base) +drm_output_repaint(struct weston_output *output_base, + pixman_region32_t *damage) { struct drm_output *output = (struct drm_output *) output_base; struct drm_compositor *compositor = @@ -235,7 +236,7 @@ drm_output_repaint(struct weston_output *output_base) drm_output_prepare_scanout_surface(output); wl_list_for_each_reverse(surface, &compositor->base.surface_list, link) - weston_surface_draw(surface, &output->base); + weston_surface_draw(surface, &output->base, damage); glFlush(); diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c index f8b5a32c..f23c357c 100644 --- a/src/compositor-wayland.c +++ b/src/compositor-wayland.c @@ -329,7 +329,8 @@ static const struct wl_callback_listener frame_listener = { }; static void -wayland_output_repaint(struct weston_output *output_base) +wayland_output_repaint(struct weston_output *output_base, + pixman_region32_t *damage) { struct wayland_output *output = (struct wayland_output *) output_base; struct wayland_compositor *compositor = @@ -344,7 +345,7 @@ wayland_output_repaint(struct weston_output *output_base) } wl_list_for_each_reverse(surface, &compositor->base.surface_list, link) - weston_surface_draw(surface, &output->base); + weston_surface_draw(surface, &output->base, damage); draw_border(output); diff --git a/src/compositor-x11.c b/src/compositor-x11.c index 53998d24..c227063b 100644 --- a/src/compositor-x11.c +++ b/src/compositor-x11.c @@ -186,7 +186,8 @@ x11_compositor_fini_egl(struct x11_compositor *compositor) } static void -x11_output_repaint(struct weston_output *output_base) +x11_output_repaint(struct weston_output *output_base, + pixman_region32_t *damage) { struct x11_output *output = (struct x11_output *)output_base; struct x11_compositor *compositor = @@ -200,7 +201,7 @@ x11_output_repaint(struct weston_output *output_base) } wl_list_for_each_reverse(surface, &compositor->base.surface_list, link) - weston_surface_draw(surface, &output->base); + weston_surface_draw(surface, &output->base, damage); eglSwapBuffers(compositor->base.display, output->egl_surface); diff --git a/src/compositor.c b/src/compositor.c index 069ea74d..0c99a5f4 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; @@ -225,6 +226,7 @@ weston_surface_create(struct weston_compositor *compositor) pixman_region32_init(&surface->damage); pixman_region32_init(&surface->opaque); + pixman_region32_init(&surface->clip); undef_region(&surface->input); pixman_region32_init(&surface->transform.opaque); wl_list_init(&surface->frame_callback_list); @@ -281,17 +283,15 @@ surface_to_global_float(struct weston_surface *surface, WL_EXPORT void weston_surface_damage_below(struct weston_surface *surface) { - struct weston_surface *below; + struct weston_compositor *compositor = surface->compositor; + pixman_region32_t damage; - if (surface->output == NULL) - return; - - if (surface->link.next == &surface->compositor->surface_list) - return; - - below = container_of(surface->link.next, struct weston_surface, link); - pixman_region32_union(&below->damage, &below->damage, - &surface->transform.boundingbox); + pixman_region32_init(&damage); + pixman_region32_subtract(&damage, &surface->transform.boundingbox, + &surface->clip); + pixman_region32_union(&compositor->damage, + &compositor->damage, &damage); + pixman_region32_fini(&damage); } static void @@ -510,21 +510,6 @@ weston_surface_damage(struct weston_surface *surface) weston_compositor_schedule_repaint(surface->compositor); } -static void -weston_surface_flush_damage(struct weston_surface *surface) -{ - struct weston_surface *below; - - if (surface->output && - surface->link.next != &surface->compositor->surface_list) { - below = container_of(surface->link.next, - struct weston_surface, link); - - pixman_region32_union(&below->damage, - &below->damage, &surface->damage); - } -} - WL_EXPORT void weston_surface_configure(struct weston_surface *surface, GLfloat x, GLfloat y, int width, int height) @@ -613,11 +598,18 @@ weston_compositor_repick(struct weston_compositor *compositor) static void weston_surface_unmap(struct weston_surface *surface) { + struct wl_input_device *device = surface->compositor->input_device; + weston_surface_damage_below(surface); - weston_surface_flush_damage(surface); surface->output = NULL; wl_list_remove(&surface->link); + wl_list_remove(&surface->layer_link); weston_compositor_repick(surface->compositor); + + if (device->keyboard_focus == &surface->surface) + wl_input_device_set_keyboard_focus(device, NULL, + weston_compositor_get_time()); + weston_compositor_schedule_repaint(surface->compositor); } @@ -647,6 +639,7 @@ destroy_surface(struct wl_resource *resource) pixman_region32_fini(&surface->transform.boundingbox); pixman_region32_fini(&surface->damage); pixman_region32_fini(&surface->opaque); + pixman_region32_fini(&surface->clip); if (!region_is_undefined(&surface->input)) pixman_region32_fini(&surface->input); @@ -762,7 +755,8 @@ texture_region(struct weston_surface *es, pixman_region32_t *region) } WL_EXPORT void -weston_surface_draw(struct weston_surface *es, struct weston_output *output) +weston_surface_draw(struct weston_surface *es, struct weston_output *output, + pixman_region32_t *damage) { struct weston_compositor *ec = es->compositor; GLfloat *v; @@ -771,12 +765,9 @@ weston_surface_draw(struct weston_surface *es, struct weston_output *output) int n; pixman_region32_init(&repaint); - pixman_region32_intersect(&repaint, &es->transform.boundingbox, - &output->region); - pixman_region32_intersect(&repaint, &repaint, &es->damage); - - /* Clear damage, assume outputs do not overlap. */ - pixman_region32_subtract(&es->damage, &es->damage, &output->region); + pixman_region32_intersect(&repaint, + &es->transform.boundingbox, damage); + pixman_region32_subtract(&repaint, &repaint, &es->clip); if (!pixman_region32_not_empty(&repaint)) goto out; @@ -826,37 +817,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); } @@ -883,14 +852,9 @@ WL_EXPORT void weston_output_damage(struct weston_output *output) { struct weston_compositor *compositor = output->compositor; - struct weston_surface *es; - if (wl_list_empty(&compositor->surface_list)) - return; - - es = container_of(compositor->surface_list.next, - struct weston_surface, link); - pixman_region32_union(&es->damage, &es->damage, &output->region); + pixman_region32_union(&compositor->damage, + &compositor->damage, &output->region); weston_compositor_schedule_repaint(compositor); } @@ -935,9 +899,10 @@ 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, total_damage; + pixman_region32_t opaque, new_damage, output_damage; int32_t width, height; weston_compositor_update_drag_surfaces(ec); @@ -948,13 +913,14 @@ weston_output_repaint(struct weston_output *output, int msecs) output->border.top + output->border.bottom; glViewport(0, 0, width, height); - pixman_region32_init(&new_damage); - pixman_region32_init(&opaque); - - 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) /* @@ -965,33 +931,36 @@ weston_output_repaint(struct weston_output *output, int msecs) */ output->assign_planes(output); + pixman_region32_init(&new_damage); + pixman_region32_init(&opaque); + wl_list_for_each(es, &ec->surface_list, link) { pixman_region32_subtract(&es->damage, &es->damage, &opaque); pixman_region32_union(&new_damage, &new_damage, &es->damage); + empty_region(&es->damage); + pixman_region32_copy(&es->clip, &opaque); pixman_region32_union(&opaque, &opaque, &es->transform.opaque); } - pixman_region32_init(&total_damage); - pixman_region32_union(&total_damage, &new_damage, - &output->previous_damage); - pixman_region32_intersect(&output->previous_damage, - &new_damage, &output->region); + pixman_region32_union(&ec->damage, &ec->damage, &new_damage); + + pixman_region32_init(&output_damage); + pixman_region32_union(&output_damage, + &ec->damage, &output->previous_damage); + pixman_region32_copy(&output->previous_damage, &ec->damage); + pixman_region32_intersect(&output_damage, + &output_damage, &output->region); + pixman_region32_subtract(&ec->damage, &ec->damage, &output->region); pixman_region32_fini(&opaque); pixman_region32_fini(&new_damage); - wl_list_for_each(es, &ec->surface_list, link) { - pixman_region32_copy(&es->damage, &total_damage); - pixman_region32_subtract(&total_damage, - &total_damage, &es->transform.opaque); - } - if (output->dirty) weston_output_update_matrix(output); - output->repaint(output); + output->repaint(output, &output_damage); - pixman_region32_fini(&total_damage); + pixman_region32_fini(&output_damage); output->repaint_needed = 0; @@ -1025,6 +994,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) { @@ -1064,7 +1040,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); @@ -1512,7 +1489,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); @@ -1837,13 +1813,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); } @@ -1856,12 +1833,25 @@ input_device_attach(struct wl_client *client, buffer->width, buffer->height); weston_buffer_attach(buffer, &device->sprite->surface); + weston_surface_damage(device->sprite); } const static struct wl_input_device_interface input_device_interface = { input_device_attach, }; +static void +handle_drag_surface_destroy(struct wl_listener *listener, + struct wl_resource *resource, uint32_t time) +{ + struct weston_input_device *device; + + device = container_of(listener, struct weston_input_device, + drag_surface_destroy_listener); + + device->drag_surface = NULL; +} + static void unbind_input_device(struct wl_resource *resource) { wl_list_remove(&resource->link); @@ -1898,6 +1888,8 @@ weston_input_device_init(struct weston_input_device *device, device->modifier_state = 0; device->num_tp = 0; + device->drag_surface_destroy_listener.func = handle_drag_surface_destroy; + wl_list_insert(ec->input_device_list.prev, &device->link); } @@ -1913,6 +1905,42 @@ weston_input_device_release(struct weston_input_device *device) wl_input_device_release(&device->input_device); } +static void +device_setup_new_drag_surface(struct weston_input_device *device, + struct weston_surface *surface) +{ + struct wl_input_device *input_device = &device->input_device; + + device->drag_surface = surface; + + weston_surface_set_position(device->drag_surface, + input_device->x, input_device->y); + + wl_list_insert(surface->surface.resource.destroy_listener_list.prev, + &device->drag_surface_destroy_listener.link); +} + +static void +device_release_drag_surface(struct weston_input_device *device) +{ + undef_region(&device->drag_surface->input); + wl_list_remove(&device->drag_surface_destroy_listener.link); + device->drag_surface = NULL; +} + +static void +device_map_drag_surface(struct weston_input_device *device) +{ + if (device->drag_surface->output || + !device->drag_surface->buffer) + return; + + 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); +} + static void weston_input_update_drag_surface(struct wl_input_device *input_device, int dx, int dy) @@ -1931,27 +1959,20 @@ weston_input_update_drag_surface(struct wl_input_device *input_device, surface_changed = 1; if (!input_device->drag_surface || surface_changed) { - undef_region(&device->drag_surface->input); - device->drag_surface = NULL; + device_release_drag_surface(device); if (!surface_changed) return; } if (!device->drag_surface || surface_changed) { - device->drag_surface = (struct weston_surface *) + struct weston_surface *surface = (struct weston_surface *) input_device->drag_surface; - - weston_surface_set_position(device->drag_surface, - input_device->x, input_device->y); + device_setup_new_drag_surface(device, surface); } - if (device->drag_surface->output == NULL && - device->drag_surface->buffer) { - wl_list_insert(&device->sprite->link, - &device->drag_surface->link); - weston_surface_assign_output(device->drag_surface); - empty_region(&device->drag_surface->input); - } + /* the client may not have attached a buffer to the drag surface + * when we setup it up, so check if map is needed on every update */ + device_map_drag_surface(device); /* the client may have attached a buffer with a different size to * the drag surface, causing the input region to be reset */ @@ -2293,6 +2314,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); @@ -2301,6 +2323,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 8c57e4f4..6f462493 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -91,7 +91,8 @@ struct weston_output { struct weston_mode *current; struct wl_list mode_list; - void (*repaint)(struct weston_output *output); + void (*repaint)(struct weston_output *output, + pixman_region32_t *damage); void (*destroy)(struct weston_output *output); void (*assign_planes)(struct weston_output *output); @@ -106,6 +107,7 @@ struct weston_input_device { struct weston_compositor *compositor; struct weston_surface *sprite; struct weston_surface *drag_surface; + struct wl_listener drag_surface_destroy_listener; int32_t hotspot_x, hotspot_y; struct wl_list link; uint32_t modifier_state; @@ -162,6 +164,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; @@ -180,8 +187,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; @@ -198,8 +209,8 @@ struct weston_compositor { int idle_time; /* effective timeout, s */ /* Repaint state. */ - struct timespec previous_swap; struct wl_array vertices, indices; + pixman_region32_t damage; uint32_t focus; @@ -260,11 +271,13 @@ struct weston_surface { struct wl_surface surface; struct weston_compositor *compositor; GLuint texture; + pixman_region32_t clip; pixman_region32_t damage; pixman_region32_t opaque; 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]; @@ -341,7 +354,8 @@ void weston_surface_activate(struct weston_surface *surface, struct weston_input_device *device, uint32_t time); void -weston_surface_draw(struct weston_surface *es, struct weston_output *output); +weston_surface_draw(struct weston_surface *es, + struct weston_output *output, pixman_region32_t *damage); void notify_motion(struct wl_input_device *device, @@ -368,6 +382,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 @@ -420,6 +437,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 5abfdb5e..2b61202c 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; @@ -93,7 +98,6 @@ struct shell_surface { struct shell_surface *parent; enum shell_surface_type type; - enum shell_surface_type prev_type; int32_t saved_x, saved_y; bool saved_position_valid; @@ -379,6 +383,8 @@ shell_unset_fullscreen(struct shell_surface *shsurf) shsurf->fullscreen.black_surface = NULL; shsurf->fullscreen_output = NULL; shsurf->surface->force_configure = 1; + weston_surface_set_position(shsurf->surface, + shsurf->saved_x, shsurf->saved_y); } static int @@ -412,7 +418,6 @@ reset_shell_surface_type(struct shell_surface *surface) break; } - surface->prev_type = surface->type; surface->type = SHELL_SURFACE_NONE; return 0; } @@ -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 @@ -623,17 +627,15 @@ shell_surface_set_fullscreen(struct wl_client *client, if (reset_shell_surface_type(shsurf)) return; - if (shsurf->prev_type != SHELL_SURFACE_FULLSCREEN) { - shsurf->saved_x = es->geometry.x; - shsurf->saved_y = es->geometry.y; - shsurf->saved_position_valid = true; - } - shsurf->fullscreen_output = shsurf->output; shsurf->fullscreen.type = method; shsurf->fullscreen.framerate = framerate; shsurf->type = SHELL_SURFACE_FULLSCREEN; + shsurf->saved_x = es->geometry.x; + shsurf->saved_y = es->geometry.y; + shsurf->saved_position_valid = true; + if (es->output) shsurf->surface->force_configure = 1; @@ -860,7 +862,6 @@ shell_get_shell_surface(struct wl_client *client, weston_matrix_init(&shsurf->rotation.rotation); shsurf->type = SHELL_SURFACE_NONE; - shsurf->prev_type = SHELL_SURFACE_NONE; wl_client_add_resource(client, &shsurf->resource); } @@ -884,6 +885,11 @@ launch_screensaver(struct wl_shell *shell) if (!shell->screensaver.path) return; + if (shell->screensaver.process.pid != 0) { + fprintf(stderr, "old screensaver still running\n"); + return; + } + weston_client_launch(shell->compositor, &shell->screensaver.process, shell->screensaver.path, @@ -905,12 +911,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); } @@ -918,8 +924,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; } @@ -940,7 +946,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; } @@ -978,7 +984,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; } @@ -1038,8 +1044,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) @@ -1047,21 +1051,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); @@ -1383,7 +1378,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); @@ -1392,35 +1386,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; } } @@ -1451,9 +1433,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; @@ -1469,28 +1448,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); @@ -1558,24 +1524,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; @@ -1618,19 +1574,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. */ @@ -1641,32 +1597,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: @@ -1697,10 +1641,8 @@ configure(struct weston_shell *base, struct weston_surface *surface, struct shell_surface *shsurf; shsurf = get_shell_surface(surface); - if (shsurf) { + if (shsurf) surface_type = shsurf->type; - prev_surface_type = shsurf->prev_type; - } surface->geometry.x = x; surface->geometry.y = y; @@ -1724,18 +1666,6 @@ configure(struct weston_shell *base, struct weston_surface *surface, get_output_panel_height(shell,surface->output); 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: break; @@ -2071,11 +2001,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,