From: Quentin Glidic <[email protected]>

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.

Signed-off-by: Quentin Glidic <[email protected]>
Acked-by: Pekka Paalanen <[email protected]>
---

v3:
 - Added weston_layer_unset_position
 - HIDDEN is now still rendered
   (Feature needed by Giulio Camuffo)
 - weston_layer now stores the weston_compositor pointer to avoid its
   need in set_position
 - Reordered weston_layer members (we break the ABI anyway)
 - weston_layer_init now only initialize the struct, you must
   call set_position to add it to the layer list
 - BACKGROUND is now 2 instead of 1, as these values are mainly meant
   for libweston modules. The compositor should simply use
   (BACKGROUND - 1) if it wants to support such modules with
   a fallback surface
   (Suggestion by Bill Spitzak)

v2:
 - Tiny commit message addition: added runtime behaviour comment.
 - Reworked (a lot) the enum comment to explain further the position
   values and their actual expected scope. I hope their are clear enough.
   Here are the biggest changes:
     - Added a BOTTOM_UI value for widgets and conky-like applications.
     - Changed BACKGROUND to be 1, as nothing should be under it
     - Added a comment about mandatory background

 desktop-shell/input-panel.c         |  6 ++--
 desktop-shell/shell.c               | 64 +++++++++++++++++----------------
 fullscreen-shell/fullscreen-shell.c |  4 ++-
 ivi-shell/input-panel-ivi.c         |  6 ++--
 ivi-shell/ivi-layout.c              |  4 ++-
 ivi-shell/ivi-shell.c               |  2 +-
 libweston/compositor.c              | 52 ++++++++++++++++++++++++---
 libweston/compositor.h              | 70 +++++++++++++++++++++++++++++++++++--
 tests/weston-test.c                 |  3 +-
 9 files changed, 163 insertions(+), 48 deletions(-)

diff --git a/desktop-shell/input-panel.c b/desktop-shell/input-panel.c
index 0d003b1..23e22b1 100644
--- a/desktop-shell/input-panel.c
+++ b/desktop-shell/input-panel.c
@@ -114,8 +114,8 @@ show_input_panels(struct wl_listener *listener, void *data)
        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) {
@@ -140,7 +140,7 @@ hide_input_panels(struct wl_listener *listener, void *data)
        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,
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index c72f801..bdaad87 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -1079,13 +1079,13 @@ seat_destroyed(struct wl_listener *listener, void *data)
 }
 
 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(shell->compositor, &ws->layer);
 
        wl_list_init(&ws->focus_list);
        wl_list_init(&ws->seat_destroyed_listener.link);
@@ -1124,7 +1124,7 @@ activate_workspace(struct desktop_shell *shell, unsigned 
int index)
        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;
 }
@@ -4596,20 +4596,16 @@ resume_desktop(struct desktop_shell *shell)
 {
        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));
 
@@ -5302,13 +5298,14 @@ lock(struct desktop_shell *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);
 
@@ -6732,11 +6729,18 @@ module_init(struct weston_compositor *ec,
        ec->shell_interface.set_pid = set_pid;
        ec->shell_interface.get_output_work_area = get_output_work_area;
 
-       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(ec, &shell->fullscreen_layer);
+       weston_layer_init(ec, &shell->panel_layer);
+       weston_layer_init(ec, &shell->background_layer);
+       weston_layer_init(ec, &shell->lock_layer);
+       weston_layer_init(ec, &shell->input_panel_layer);
+
+       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);
@@ -6758,13 +6762,13 @@ module_init(struct weston_compositor *ec,
                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(ec, &shell->minimized_layer);
 
        wl_list_init(&shell->workspaces.anim_sticky_list);
        wl_list_init(&shell->workspaces.animation.link);
diff --git a/fullscreen-shell/fullscreen-shell.c 
b/fullscreen-shell/fullscreen-shell.c
index 2ec2d02..5842d50 100644
--- a/fullscreen-shell/fullscreen-shell.c
+++ b/fullscreen-shell/fullscreen-shell.c
@@ -834,7 +834,9 @@ module_init(struct weston_compositor *compositor,
 
        shell->client_destroyed.notify = client_destroyed;
 
-       weston_layer_init(&shell->layer, &compositor->cursor_layer.link);
+       weston_layer_init(compositor, &shell->layer);
+       weston_layer_set_position(&shell->layer,
+                                 WESTON_LAYER_POSITION_FULLSCREEN);
 
        wl_list_init(&shell->output_list);
        shell->output_created_listener.notify = output_created;
diff --git a/ivi-shell/input-panel-ivi.c b/ivi-shell/input-panel-ivi.c
index 954d4ef..8ba0230 100644
--- a/ivi-shell/input-panel-ivi.c
+++ b/ivi-shell/input-panel-ivi.c
@@ -115,8 +115,8 @@ show_input_panels(struct wl_listener *listener, void *data)
        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) {
@@ -141,7 +141,7 @@ hide_input_panels(struct wl_listener *listener, void *data)
        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,
diff --git a/ivi-shell/ivi-layout.c b/ivi-shell/ivi-layout.c
index dec4936..1dbb40c 100644
--- a/ivi-shell/ivi-layout.c
+++ b/ivi-shell/ivi-layout.c
@@ -2028,7 +2028,9 @@ ivi_layout_init_with_compositor(struct weston_compositor 
*ec)
        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(ec, &layout->layout_layer);
+       weston_layer_set_position(&layout->layout_layer,
+                                 WESTON_LAYER_POSITION_NORMAL);
 
        create_screen(ec);
 
diff --git a/ivi-shell/ivi-shell.c b/ivi-shell/ivi-shell.c
index 090ee4d..ff47879 100644
--- a/ivi-shell/ivi-shell.c
+++ b/ivi-shell/ivi-shell.c
@@ -391,7 +391,7 @@ init_ivi_shell(struct weston_compositor *compositor, struct 
ivi_shell *shell,
 
        wl_list_init(&shell->ivi_surface_list);
 
-       weston_layer_init(&shell->input_panel_layer, NULL);
+       weston_layer_init(compositor, &shell->input_panel_layer);
 
        if (setting->developermode) {
                weston_install_debug_key_binding(compositor, MODIFIER_SUPER);
diff --git a/libweston/compositor.c b/libweston/compositor.c
index 771f1c9..9d6bbf6 100644
--- a/libweston/compositor.c
+++ b/libweston/compositor.c
@@ -2402,14 +2402,52 @@ weston_layer_entry_remove(struct weston_layer_entry 
*entry)
        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_compositor *compositor,
+                 struct weston_layer *layer)
 {
+       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.
+ *
+ * \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;
+
+       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.next, &layer->link);
+}
+
+/** Hide a layer by taking it off the layer list.
+ *
+ * \param layer The layer to hide
+ */
+WL_EXPORT void
+weston_layer_unset_position(struct weston_layer *layer)
+{
+       wl_list_remove(&layer->link);
 }
 
 WL_EXPORT void
@@ -4725,8 +4763,12 @@ weston_compositor_create(struct wl_display *display, 
void *user_data)
        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, &ec->fade_layer);
+       weston_layer_init(ec, &ec->cursor_layer);
+
+       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);
diff --git a/libweston/compositor.h b/libweston/compositor.h
index 557d2f5..d6e35e0 100644
--- a/libweston/compositor.h
+++ b/libweston/compositor.h
@@ -605,10 +605,68 @@ struct weston_layer_entry {
        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 {
@@ -1222,7 +1280,13 @@ weston_layer_entry_insert(struct weston_layer_entry 
*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_compositor *compositor,
+                 struct weston_layer *layer);
+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);
diff --git a/tests/weston-test.c b/tests/weston-test.c
index 09d8b5e..4de42fc 100644
--- a/tests/weston-test.c
+++ b/tests/weston-test.c
@@ -595,7 +595,8 @@ module_init(struct weston_compositor *ec,
                return -1;
 
        test->compositor = ec;
-       weston_layer_init(&test->layer, &ec->cursor_layer.link);
+       weston_layer_init(ec, &test->layer);
+       weston_layer_set_position(&test->layer, WESTON_LAYER_POSITION_NORMAL);
 
        if (wl_global_create(ec->wl_display, &weston_test_interface, 1,
                             test, bind_test) == NULL)
-- 
2.9.0

_______________________________________________
wayland-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to