libweston: Position layers in an absolute way

Currently, layers’ order depends on the module loading order and it does
not survive runtime modifications (like shell locking/unlocking).
With this patch, modules can safely add their own layer at the expected
position in the stack, with runtime persistence.

v4 Reviewed-by: Giulio Camuffo <giuliocamuffo@gmail.com>
Signed-off-by: Quentin Glidic <sardemff7+git@sardemff7.net>
Acked-by: Daniel Stone <daniels@collabora.com>
[Pekka: fix three whitespace issues]
Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
dev
Quentin Glidic 8 years ago committed by Pekka Paalanen
parent 39d7e99a46
commit 82681571cf
  1. 6
      desktop-shell/input-panel.c
  2. 79
      desktop-shell/shell.c
  3. 4
      fullscreen-shell/fullscreen-shell.c
  4. 6
      ivi-shell/input-panel-ivi.c
  5. 4
      ivi-shell/ivi-layout.c
  6. 2
      ivi-shell/ivi-shell.c
  7. 6
      libweston-desktop/xwayland.c
  8. 62
      libweston/compositor.c
  9. 72
      libweston/compositor.h
  10. 3
      tests/weston-test.c

@ -115,8 +115,8 @@ show_input_panels(struct wl_listener *listener, void *data)
shell->showing_input_panels = true; shell->showing_input_panels = true;
if (!shell->locked) if (!shell->locked)
wl_list_insert(&shell->compositor->cursor_layer.link, weston_layer_set_position(&shell->input_panel_layer,
&shell->input_panel_layer.link); WESTON_LAYER_POSITION_TOP_UI);
wl_list_for_each_safe(ipsurf, next, wl_list_for_each_safe(ipsurf, next,
&shell->input_panel.surfaces, link) { &shell->input_panel.surfaces, link) {
@ -141,7 +141,7 @@ hide_input_panels(struct wl_listener *listener, void *data)
shell->showing_input_panels = false; shell->showing_input_panels = false;
if (!shell->locked) if (!shell->locked)
wl_list_remove(&shell->input_panel_layer.link); weston_layer_unset_position(&shell->input_panel_layer);
wl_list_for_each_safe(view, next, wl_list_for_each_safe(view, next,
&shell->input_panel_layer.view_list.link, &shell->input_panel_layer.view_list.link,

@ -892,13 +892,13 @@ seat_destroyed(struct wl_listener *listener, void *data)
} }
static struct workspace * static struct workspace *
workspace_create(void) workspace_create(struct desktop_shell *shell)
{ {
struct workspace *ws = malloc(sizeof *ws); struct workspace *ws = malloc(sizeof *ws);
if (ws == NULL) if (ws == NULL)
return NULL; return NULL;
weston_layer_init(&ws->layer, NULL); weston_layer_init(&ws->layer, shell->compositor);
wl_list_init(&ws->focus_list); wl_list_init(&ws->focus_list);
wl_list_init(&ws->seat_destroyed_listener.link); wl_list_init(&ws->seat_destroyed_listener.link);
@ -937,7 +937,7 @@ activate_workspace(struct desktop_shell *shell, unsigned int index)
struct workspace *ws; struct workspace *ws;
ws = get_workspace(shell, index); ws = get_workspace(shell, index);
wl_list_insert(&shell->panel_layer.link, &ws->layer.link); weston_layer_set_position(&ws->layer, WESTON_LAYER_POSITION_NORMAL);
shell->workspaces.current = index; shell->workspaces.current = index;
} }
@ -1018,6 +1018,9 @@ reverse_workspace_change_animation(struct desktop_shell *shell,
shell->workspaces.anim_dir = -1 * shell->workspaces.anim_dir; shell->workspaces.anim_dir = -1 * shell->workspaces.anim_dir;
shell->workspaces.anim_timestamp = 0; shell->workspaces.anim_timestamp = 0;
weston_layer_set_position(&to->layer, WESTON_LAYER_POSITION_NORMAL);
weston_layer_set_position(&from->layer, WESTON_LAYER_POSITION_NORMAL - 1);
weston_compositor_schedule_repaint(shell->compositor); weston_compositor_schedule_repaint(shell->compositor);
} }
@ -1065,7 +1068,7 @@ finish_workspace_change_animation(struct desktop_shell *shell,
workspace_deactivate_transforms(to); workspace_deactivate_transforms(to);
shell->workspaces.anim_to = NULL; shell->workspaces.anim_to = NULL;
wl_list_remove(&shell->workspaces.anim_from->layer.link); weston_layer_unset_position(&shell->workspaces.anim_from->layer);
} }
static void static void
@ -1147,7 +1150,8 @@ animate_workspace_change(struct desktop_shell *shell,
wl_list_insert(&output->animation_list, wl_list_insert(&output->animation_list,
&shell->workspaces.animation.link); &shell->workspaces.animation.link);
wl_list_insert(from->layer.link.prev, &to->layer.link); weston_layer_set_position(&to->layer, WESTON_LAYER_POSITION_NORMAL);
weston_layer_set_position(&from->layer, WESTON_LAYER_POSITION_NORMAL - 1);
workspace_translate_in(to, 0); workspace_translate_in(to, 0);
@ -1161,8 +1165,8 @@ update_workspace(struct desktop_shell *shell, unsigned int index,
struct workspace *from, struct workspace *to) struct workspace *from, struct workspace *to)
{ {
shell->workspaces.current = index; shell->workspaces.current = index;
wl_list_insert(&from->layer.link, &to->layer.link); weston_layer_set_position(&to->layer, WESTON_LAYER_POSITION_NORMAL);
wl_list_remove(&from->layer.link); weston_layer_unset_position(&from->layer);
} }
static void static void
@ -1286,9 +1290,6 @@ take_surface_to_workspace_by_seat(struct desktop_shell *shell,
if (shell->workspaces.anim_from == to && if (shell->workspaces.anim_from == to &&
shell->workspaces.anim_to == from) { shell->workspaces.anim_to == from) {
wl_list_remove(&to->layer.link);
wl_list_insert(from->layer.link.prev, &to->layer.link);
reverse_workspace_change_animation(shell, index, from, to); reverse_workspace_change_animation(shell, index, from, to);
return; return;
@ -3064,20 +3065,16 @@ resume_desktop(struct desktop_shell *shell)
{ {
struct workspace *ws = get_current_workspace(shell); struct workspace *ws = get_current_workspace(shell);
wl_list_remove(&shell->lock_layer.link); weston_layer_unset_position(&shell->lock_layer);
if (shell->showing_input_panels) {
wl_list_insert(&shell->compositor->cursor_layer.link, if (shell->showing_input_panels)
&shell->input_panel_layer.link); weston_layer_set_position(&shell->input_panel_layer,
wl_list_insert(&shell->input_panel_layer.link, WESTON_LAYER_POSITION_TOP_UI);
&shell->fullscreen_layer.link); weston_layer_set_position(&shell->fullscreen_layer,
} else { WESTON_LAYER_POSITION_FULLSCREEN);
wl_list_insert(&shell->compositor->cursor_layer.link, weston_layer_set_position(&shell->panel_layer,
&shell->fullscreen_layer.link); WESTON_LAYER_POSITION_UI);
} weston_layer_set_position(&ws->layer, WESTON_LAYER_POSITION_NORMAL);
wl_list_insert(&shell->fullscreen_layer.link,
&shell->panel_layer.link);
wl_list_insert(&shell->panel_layer.link,
&ws->layer.link),
restore_focus_state(shell, get_current_workspace(shell)); restore_focus_state(shell, get_current_workspace(shell));
@ -3757,13 +3754,14 @@ lock(struct desktop_shell *shell)
* toplevel layers. This way nothing else can show or receive * toplevel layers. This way nothing else can show or receive
* input events while we are locked. */ * input events while we are locked. */
wl_list_remove(&shell->panel_layer.link); weston_layer_unset_position(&shell->panel_layer);
wl_list_remove(&shell->fullscreen_layer.link); weston_layer_unset_position(&shell->fullscreen_layer);
if (shell->showing_input_panels) if (shell->showing_input_panels)
wl_list_remove(&shell->input_panel_layer.link); weston_layer_unset_position(&shell->input_panel_layer);
wl_list_remove(&ws->layer.link); weston_layer_unset_position(&ws->layer);
wl_list_insert(&shell->compositor->cursor_layer.link,
&shell->lock_layer.link); weston_layer_set_position(&shell->lock_layer,
WESTON_LAYER_POSITION_LOCK);
weston_compositor_sleep(shell->compositor); weston_compositor_sleep(shell->compositor);
@ -4900,11 +4898,18 @@ module_init(struct weston_compositor *ec,
shell->transform_listener.notify = transform_handler; shell->transform_listener.notify = transform_handler;
wl_signal_add(&ec->transform_signal, &shell->transform_listener); wl_signal_add(&ec->transform_signal, &shell->transform_listener);
weston_layer_init(&shell->fullscreen_layer, &ec->cursor_layer.link); weston_layer_init(&shell->fullscreen_layer, ec);
weston_layer_init(&shell->panel_layer, &shell->fullscreen_layer.link); weston_layer_init(&shell->panel_layer, ec);
weston_layer_init(&shell->background_layer, &shell->panel_layer.link); weston_layer_init(&shell->background_layer, ec);
weston_layer_init(&shell->lock_layer, NULL); weston_layer_init(&shell->lock_layer, ec);
weston_layer_init(&shell->input_panel_layer, NULL); weston_layer_init(&shell->input_panel_layer, ec);
weston_layer_set_position(&shell->fullscreen_layer,
WESTON_LAYER_POSITION_FULLSCREEN);
weston_layer_set_position(&shell->panel_layer,
WESTON_LAYER_POSITION_UI);
weston_layer_set_position(&shell->background_layer,
WESTON_LAYER_POSITION_BACKGROUND);
wl_array_init(&shell->workspaces.array); wl_array_init(&shell->workspaces.array);
wl_list_init(&shell->workspaces.client_list); wl_list_init(&shell->workspaces.client_list);
@ -4926,13 +4931,13 @@ module_init(struct weston_compositor *ec,
if (pws == NULL) if (pws == NULL)
return -1; return -1;
*pws = workspace_create(); *pws = workspace_create(shell);
if (*pws == NULL) if (*pws == NULL)
return -1; return -1;
} }
activate_workspace(shell, 0); activate_workspace(shell, 0);
weston_layer_init(&shell->minimized_layer, NULL); weston_layer_init(&shell->minimized_layer, ec);
wl_list_init(&shell->workspaces.anim_sticky_list); wl_list_init(&shell->workspaces.anim_sticky_list);
wl_list_init(&shell->workspaces.animation.link); wl_list_init(&shell->workspaces.animation.link);

@ -912,7 +912,9 @@ module_init(struct weston_compositor *compositor,
shell->client_destroyed.notify = client_destroyed; shell->client_destroyed.notify = client_destroyed;
weston_layer_init(&shell->layer, &compositor->cursor_layer.link); weston_layer_init(&shell->layer, compositor);
weston_layer_set_position(&shell->layer,
WESTON_LAYER_POSITION_FULLSCREEN);
wl_list_init(&shell->output_list); wl_list_init(&shell->output_list);
shell->output_created_listener.notify = output_created; shell->output_created_listener.notify = output_created;

@ -116,8 +116,8 @@ show_input_panels(struct wl_listener *listener, void *data)
shell->showing_input_panels = true; shell->showing_input_panels = true;
if (!shell->locked) if (!shell->locked)
wl_list_insert(&shell->compositor->cursor_layer.link, weston_layer_set_position(&shell->input_panel_layer,
&shell->input_panel_layer.link); WESTON_LAYER_POSITION_TOP_UI);
wl_list_for_each_safe(ipsurf, next, wl_list_for_each_safe(ipsurf, next,
&shell->input_panel.surfaces, link) { &shell->input_panel.surfaces, link) {
@ -142,7 +142,7 @@ hide_input_panels(struct wl_listener *listener, void *data)
shell->showing_input_panels = false; shell->showing_input_panels = false;
if (!shell->locked) if (!shell->locked)
wl_list_remove(&shell->input_panel_layer.link); weston_layer_unset_position(&shell->input_panel_layer);
wl_list_for_each_safe(view, next, wl_list_for_each_safe(view, next,
&shell->input_panel_layer.view_list.link, &shell->input_panel_layer.view_list.link,

@ -2019,7 +2019,9 @@ ivi_layout_init_with_compositor(struct weston_compositor *ec)
wl_signal_init(&layout->surface_notification.configure_changed); wl_signal_init(&layout->surface_notification.configure_changed);
/* Add layout_layer at the last of weston_compositor.layer_list */ /* Add layout_layer at the last of weston_compositor.layer_list */
weston_layer_init(&layout->layout_layer, ec->layer_list.prev); weston_layer_init(&layout->layout_layer, ec);
weston_layer_set_position(&layout->layout_layer,
WESTON_LAYER_POSITION_NORMAL);
create_screen(ec); create_screen(ec);

@ -392,7 +392,7 @@ init_ivi_shell(struct weston_compositor *compositor, struct ivi_shell *shell,
wl_list_init(&shell->ivi_surface_list); wl_list_init(&shell->ivi_surface_list);
weston_layer_init(&shell->input_panel_layer, NULL); weston_layer_init(&shell->input_panel_layer, compositor);
if (setting->developermode) { if (setting->developermode) {
weston_install_debug_key_binding(compositor, MODIFIER_SUPER); weston_install_debug_key_binding(compositor, MODIFIER_SUPER);

@ -386,7 +386,11 @@ weston_desktop_xwayland_init(struct weston_desktop *desktop)
xwayland->desktop = desktop; xwayland->desktop = desktop;
xwayland->client = weston_desktop_client_create(desktop, NULL, NULL, NULL, NULL, 0, 0); xwayland->client = weston_desktop_client_create(desktop, NULL, NULL, NULL, NULL, 0, 0);
weston_layer_init(&xwayland->layer, &compositor->cursor_layer.link); weston_layer_init(&xwayland->layer, compositor);
/* We put this layer on top of regular shell surfaces, but hopefully
* below any UI the shell would add */
weston_layer_set_position(&xwayland->layer,
WESTON_LAYER_POSITION_NORMAL + 1);
compositor->xwayland = xwayland; compositor->xwayland = xwayland;
compositor->xwayland_interface = &weston_desktop_xwayland_interface; compositor->xwayland_interface = &weston_desktop_xwayland_interface;

@ -2422,14 +2422,62 @@ weston_layer_entry_remove(struct weston_layer_entry *entry)
entry->layer = NULL; entry->layer = NULL;
} }
/** Initialize the weston_layer struct.
*
* \param compositor The compositor instance
* \param layer The layer to initialize
*/
WL_EXPORT void WL_EXPORT void
weston_layer_init(struct weston_layer *layer, struct wl_list *below) weston_layer_init(struct weston_layer *layer,
struct weston_compositor *compositor)
{ {
layer->compositor = compositor;
wl_list_init(&layer->link);
wl_list_init(&layer->view_list.link); wl_list_init(&layer->view_list.link);
layer->view_list.layer = layer; layer->view_list.layer = layer;
weston_layer_set_mask_infinite(layer); weston_layer_set_mask_infinite(layer);
if (below != NULL) }
wl_list_insert(below, &layer->link);
/** Sets the position of the layer in the layer list. The layer will be placed
* below any layer with the same position value, if any.
* This function is safe to call if the layer is already on the list, but the
* layer may be moved below other layers at the same position, if any.
*
* \param layer The layer to modify
* \param position The position the layer will be placed at
*/
WL_EXPORT void
weston_layer_set_position(struct weston_layer *layer,
enum weston_layer_position position)
{
struct weston_layer *below;
wl_list_remove(&layer->link);
/* layer_list is ordered from top to bottom, the last layer being the
* background with the smallest position value */
layer->position = position;
wl_list_for_each_reverse(below, &layer->compositor->layer_list, link) {
if (below->position >= layer->position) {
wl_list_insert(&below->link, &layer->link);
return;
}
}
wl_list_insert(&layer->compositor->layer_list, &layer->link);
}
/** Hide a layer by taking it off the layer list.
* This function is safe to call if the layer is not on the list.
*
* \param layer The layer to hide
*/
WL_EXPORT void
weston_layer_unset_position(struct weston_layer *layer)
{
wl_list_remove(&layer->link);
wl_list_init(&layer->link);
} }
WL_EXPORT void WL_EXPORT void
@ -5036,8 +5084,12 @@ weston_compositor_create(struct wl_display *display, void *user_data)
loop = wl_display_get_event_loop(ec->wl_display); loop = wl_display_get_event_loop(ec->wl_display);
ec->idle_source = wl_event_loop_add_timer(loop, idle_handler, ec); ec->idle_source = wl_event_loop_add_timer(loop, idle_handler, ec);
weston_layer_init(&ec->fade_layer, &ec->layer_list); weston_layer_init(&ec->fade_layer, ec);
weston_layer_init(&ec->cursor_layer, &ec->fade_layer.link); weston_layer_init(&ec->cursor_layer, ec);
weston_layer_set_position(&ec->fade_layer, WESTON_LAYER_POSITION_FADE);
weston_layer_set_position(&ec->cursor_layer,
WESTON_LAYER_POSITION_CURSOR);
weston_compositor_add_debug_binding(ec, KEY_T, weston_compositor_add_debug_binding(ec, KEY_T,
timeline_key_binding_handler, ec); timeline_key_binding_handler, ec);

@ -632,10 +632,68 @@ struct weston_layer_entry {
struct weston_layer *layer; struct weston_layer *layer;
}; };
/**
* Higher value means higher in the stack.
*
* These values are based on well-known concepts in a classic desktop
* environment. Third-party modules based on libweston are encouraged to use
* them to integrate better with other projects.
*
* A fully integrated environment can use any value, based on these or not,
* at their discretion.
*/
enum weston_layer_position {
/*
* Special value to make the layer invisible and still rendered.
* This is used by compositors wanting e.g. minimized surfaces to still
* receive frame callbacks.
*/
WESTON_LAYER_POSITION_HIDDEN = 0x00000000,
/*
* There should always be a background layer with a surface covering
* the visible area.
*
* If the compositor handles the background itself, it should use
* BACKGROUND.
*
* If the compositor supports runtime-loadable modules to set the
* background, it should put a solid color surface at (BACKGROUND - 1)
* and modules must use BACKGROUND.
*/
WESTON_LAYER_POSITION_BACKGROUND = 0x00000002,
/* For "desktop widgets" and applications like conky. */
WESTON_LAYER_POSITION_BOTTOM_UI = 0x30000000,
/* For regular applications, only one layer should have this value
* to ensure proper stacking control. */
WESTON_LAYER_POSITION_NORMAL = 0x50000000,
/* For desktop UI, like panels. */
WESTON_LAYER_POSITION_UI = 0x80000000,
/* For fullscreen applications that should cover UI. */
WESTON_LAYER_POSITION_FULLSCREEN = 0xb0000000,
/* For special UI like on-screen keyboard that fullscreen applications
* will need. */
WESTON_LAYER_POSITION_TOP_UI = 0xe0000000,
/* For the lock surface. */
WESTON_LAYER_POSITION_LOCK = 0xffff0000,
/* Values reserved for libweston internal usage */
WESTON_LAYER_POSITION_CURSOR = 0xfffffffe,
WESTON_LAYER_POSITION_FADE = 0xffffffff,
};
struct weston_layer { struct weston_layer {
struct weston_layer_entry view_list; struct weston_compositor *compositor;
struct wl_list link; struct wl_list link; /* weston_compositor::layer_list */
enum weston_layer_position position;
pixman_box32_t mask; pixman_box32_t mask;
struct weston_layer_entry view_list;
}; };
struct weston_plane { struct weston_plane {
@ -773,7 +831,7 @@ struct weston_compositor {
struct wl_list pending_output_list; struct wl_list pending_output_list;
struct wl_list output_list; struct wl_list output_list;
struct wl_list seat_list; struct wl_list seat_list;
struct wl_list layer_list; struct wl_list layer_list; /* struct weston_layer::link */
struct wl_list view_list; /* struct weston_view::link */ struct wl_list view_list; /* struct weston_view::link */
struct wl_list plane_list; struct wl_list plane_list;
struct wl_list key_binding_list; struct wl_list key_binding_list;
@ -1297,7 +1355,13 @@ weston_layer_entry_insert(struct weston_layer_entry *list,
void void
weston_layer_entry_remove(struct weston_layer_entry *entry); weston_layer_entry_remove(struct weston_layer_entry *entry);
void void
weston_layer_init(struct weston_layer *layer, struct wl_list *below); weston_layer_init(struct weston_layer *layer,
struct weston_compositor *compositor);
void
weston_layer_set_position(struct weston_layer *layer,
enum weston_layer_position position);
void
weston_layer_unset_position(struct weston_layer *layer);
void void
weston_layer_set_mask(struct weston_layer *layer, int x, int y, int width, int height); weston_layer_set_mask(struct weston_layer *layer, int x, int y, int width, int height);

@ -596,7 +596,8 @@ module_init(struct weston_compositor *ec,
return -1; return -1;
test->compositor = ec; test->compositor = ec;
weston_layer_init(&test->layer, &ec->cursor_layer.link); weston_layer_init(&test->layer, ec);
weston_layer_set_position(&test->layer, WESTON_LAYER_POSITION_CURSOR - 1);
if (wl_global_create(ec->wl_display, &weston_test_interface, 1, if (wl_global_create(ec->wl_display, &weston_test_interface, 1,
test, bind_test) == NULL) test, bind_test) == NULL)

Loading…
Cancel
Save