shell->showing_input_panels = true;
if (!shell->locked)
- wl_list_insert(&shell->compositor->cursor_layer.link,
- &shell->input_panel_layer.link);
+ weston_layer_set_position(&shell->input_panel_layer,
+ WESTON_LAYER_POSITION_TOP_UI);
wl_list_for_each_safe(ipsurf, next,
&shell->input_panel.surfaces, link) {
shell->showing_input_panels = false;
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,
&shell->input_panel_layer.view_list.link,
}
static struct workspace *
-workspace_create(void)
+workspace_create(struct desktop_shell *shell)
{
struct workspace *ws = malloc(sizeof *ws);
if (ws == 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->seat_destroyed_listener.link);
struct workspace *ws;
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.anim_dir = -1 * shell->workspaces.anim_dir;
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);
}
workspace_deactivate_transforms(to);
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
wl_list_insert(&output->animation_list,
&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);
struct workspace *from, struct workspace *to)
{
shell->workspaces.current = index;
- wl_list_insert(&from->layer.link, &to->layer.link);
- wl_list_remove(&from->layer.link);
+ weston_layer_set_position(&to->layer, WESTON_LAYER_POSITION_NORMAL);
+ weston_layer_unset_position(&from->layer);
}
static void
if (shell->workspaces.anim_from == to &&
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);
return;
{
struct workspace *ws = get_current_workspace(shell);
- wl_list_remove(&shell->lock_layer.link);
- if (shell->showing_input_panels) {
- wl_list_insert(&shell->compositor->cursor_layer.link,
- &shell->input_panel_layer.link);
- wl_list_insert(&shell->input_panel_layer.link,
- &shell->fullscreen_layer.link);
- } else {
- 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,
- &ws->layer.link),
+ weston_layer_unset_position(&shell->lock_layer);
+
+ if (shell->showing_input_panels)
+ weston_layer_set_position(&shell->input_panel_layer,
+ WESTON_LAYER_POSITION_TOP_UI);
+ 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(&ws->layer, WESTON_LAYER_POSITION_NORMAL);
restore_focus_state(shell, get_current_workspace(shell));
* toplevel layers. This way nothing else can show or receive
* input events while we are locked. */
- wl_list_remove(&shell->panel_layer.link);
- wl_list_remove(&shell->fullscreen_layer.link);
+ weston_layer_unset_position(&shell->panel_layer);
+ weston_layer_unset_position(&shell->fullscreen_layer);
if (shell->showing_input_panels)
- wl_list_remove(&shell->input_panel_layer.link);
- wl_list_remove(&ws->layer.link);
- wl_list_insert(&shell->compositor->cursor_layer.link,
- &shell->lock_layer.link);
+ weston_layer_unset_position(&shell->input_panel_layer);
+ weston_layer_unset_position(&ws->layer);
+
+ weston_layer_set_position(&shell->lock_layer,
+ WESTON_LAYER_POSITION_LOCK);
weston_compositor_sleep(shell->compositor);
shell->transform_listener.notify = transform_handler;
wl_signal_add(&ec->transform_signal, &shell->transform_listener);
- weston_layer_init(&shell->fullscreen_layer, &ec->cursor_layer.link);
- weston_layer_init(&shell->panel_layer, &shell->fullscreen_layer.link);
- weston_layer_init(&shell->background_layer, &shell->panel_layer.link);
- weston_layer_init(&shell->lock_layer, NULL);
- weston_layer_init(&shell->input_panel_layer, NULL);
+ weston_layer_init(&shell->fullscreen_layer, ec);
+ weston_layer_init(&shell->panel_layer, ec);
+ weston_layer_init(&shell->background_layer, ec);
+ weston_layer_init(&shell->lock_layer, ec);
+ 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_list_init(&shell->workspaces.client_list);
if (pws == NULL)
return -1;
- *pws = workspace_create();
+ *pws = workspace_create(shell);
if (*pws == NULL)
return -1;
}
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.animation.link);
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);
shell->output_created_listener.notify = output_created;
shell->showing_input_panels = true;
if (!shell->locked)
- wl_list_insert(&shell->compositor->cursor_layer.link,
- &shell->input_panel_layer.link);
+ weston_layer_set_position(&shell->input_panel_layer,
+ WESTON_LAYER_POSITION_TOP_UI);
wl_list_for_each_safe(ipsurf, next,
&shell->input_panel.surfaces, link) {
shell->showing_input_panels = false;
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,
&shell->input_panel_layer.view_list.link,
wl_signal_init(&layout->surface_notification.configure_changed);
/* 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);
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) {
weston_install_debug_key_binding(compositor, MODIFIER_SUPER);
xwayland->desktop = desktop;
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_interface = &weston_desktop_xwayland_interface;
entry->layer = NULL;
}
+
+/** Initialize the weston_layer struct.
+ *
+ * \param compositor The compositor instance
+ * \param layer The layer to initialize
+ */
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);
layer->view_list.layer = 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
loop = wl_display_get_event_loop(ec->wl_display);
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->cursor_layer, &ec->fade_layer.link);
+ weston_layer_init(&ec->fade_layer, ec);
+ 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,
timeline_key_binding_handler, ec);
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_entry view_list;
- struct wl_list link;
+ struct weston_compositor *compositor;
+ struct wl_list link; /* weston_compositor::layer_list */
+ enum weston_layer_position position;
pixman_box32_t mask;
+ struct weston_layer_entry view_list;
};
struct weston_plane {
struct wl_list pending_output_list;
struct wl_list output_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 plane_list;
struct wl_list key_binding_list;
void
weston_layer_entry_remove(struct weston_layer_entry *entry);
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
weston_layer_set_mask(struct weston_layer *layer, int x, int y, int width, int height);
return -1;
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,
test, bind_test) == NULL)