Skip to content
Commits on Source (7)
  • Sergio Gómez's avatar
    kiosk-shell: Introduce surface tree lists to the kiosk shell · a1c3c099
    Sergio Gómez authored and Marius Vlad's avatar Marius Vlad committed
    
    
    The following patchset implements proper z-order for xdg surfaces in the kiosk
    shell. For this it introduces to the kiosk shell the concept of a "surface
    tree": a list of kiosk shell surface structures having a common ancestor (in
    the xdg protocol sense).
    
    The design is based on the following assumptions that the kiosk shell currently
    makes:
    
    - A kiosk surface with no parent must be fullscreen.
    - If a parent is set on a kiosk surface, that surface is assigned the output of
      the root kiosk surface. This means that all kiosk surfaces in a surface tree
      will always have the same output.
    - There is no possibility to minimize a kiosk surface.
    
    With these in mind, the following design decisions were deemed convenient:
    
    - For every output, at most one surface tree list will be active. This means
      that, for a given output, only views belonging to surfaces of the same
      surface tree will be in the normal layer. Moreover, all such views will be in
      the normal layer if the surface tree list is active.
    - The z-order of surface trees (the weston views' relative placement in the
      normal layer) is determined by the placement of their corresponding kiosk
      surface in the surface tree list.
    
    Each kiosk shell surface begins its life as root of its own surface tree list.
    Whenever a parent is set on a surface, that surface is linked to the surface
    tree list of the root surface of the parent. If a parent kiosk shell surface is
    destroyed, its children will keep the link to the root surface's surface tree
    list. If the destroyed parent is also the root surface of the surface tree,
    each child is unlinked from this root and they become the root of a new surface
    tree.
    
    This commit introduces to the kiosk_shell_surface structure the fields
    'surface_tree_list', representing the surface tree list to which the surface is
    linked at creation as its root, and 'surface_tree_link', the link to the
    surface tree list.
    
    Signed-off-by: default avatarSergio Gómez <sergio.g.delreal@gmail.com>
    a1c3c099
  • Sergio Gómez's avatar
    kiosk-shell: Introduce an "active surface tree" for each kiosk shell output · 1077a8ed
    Sergio Gómez authored and Marius Vlad's avatar Marius Vlad committed
    
    
    This commit introduces to the kiosk shell output structure a pointer to a
    surface tree list. This pointer will reference the surface tree list currently
    active on the output. (Surface tree lists were introduced in the previous
    commit)
    
    Each output will have at most one active surface tree. A surface tree being
    active on an output means that all views for this output belonging to that
    surface tree, and only those views, are in the normal layer.
    
    kiosk_shell_output_set_active_surface_tree() sets the current active surface
    tree for the specified output, replacing the previous one.
    
    Set the new active surface tree when first mapping a surface
    
    Signed-off-by: default avatarSergio Gómez <sergio.g.delreal@gmail.com>
    1077a8ed
  • Sergio Gómez's avatar
    kiosk-shell: Handle relinking of surface trees when setting a parent · beece021
    Sergio Gómez authored and Marius Vlad's avatar Marius Vlad committed
    
    
    This commit adds code to maintain the correct order and linking of a surface in
    its surface tree list for when a new parent is being set on it.
    
    If the new parent is not NULL, the child might already belong to the same
    surface tree as the new parent's root, in which case no relinking is necessary.
    Check this by calling kiosk_shell_surface_is_surface_in_tree(shsurf, shroot),
    to see if 'shsurf' is in the surface tree list represented by 'shroot', where
    'shroot' is the new parent's root surface. In case 'shsurf' doesn't belong to
    this surface tree, relink it there.
    
    If parent is NULL, 'shsurf' will become root of a new surface tree list. In
    this case 'shroot' is the root surface of shsurf's current surface tree list.
    Iterate through the surface tree list of this 'shroot' to relink all
    descendents of 'shsurf' into this new list and set it as the new active surface
    tree for the output.
    
    Signed-off-by: default avatarSergio Gómez <sergio.g.delreal@gmail.com>
    beece021
  • Sergio Gómez's avatar
    kiosk-shell: Distinguish between 'destroy_signal' and 'parent_destroy_signal' · d53efc6c
    Sergio Gómez authored and Marius Vlad's avatar Marius Vlad committed
    
    
    Currently, the 'parent_destroy_listener' is being paired with
    'destroy_signal'. The signal is emitted from kiosk_shell_surface_destroy(),
    which is the appropriate place to emit this general-purpose surface destruction
    signal.
    
    However, we need to inform the children of the surface destruction before
    finding the focus successor and activating it, that is, before calling
    find_focus_successor() and kiosk_shell_surface_activate(), which happen before
    kiosk_shell_surface_destroy().
    Since there are currently other uses for 'destroy_signal' (e.g. in
    kiosk-shell-grab.c), don't mess with it and simply add a new
    'parent_destroy_signal', placing its emition where we need it.
    
    Signed-off-by: default avatarSergio Gómez <sergio.g.delreal@gmail.com>
    d53efc6c
  • Sergio Gómez's avatar
    kiosk-shell: Redesign the function 'find_focus_successor()' · cc837eea
    Sergio Gómez authored and Marius Vlad's avatar Marius Vlad committed
    
    
    The function find_focus_successor() is called when destroying a surface to find
    a successor to the current focus. It, however, has the following issues:
    
    - Its first parameter is the weston layer from which to search for a successor.
      This is an unnecessary flexibility for our use, which only adds complexity to
      the user of the function by having to make a call for each layer. We know
      that we want to search for a successor first in the normal layer, and if that
      fails, then in the inactive layer. So we change the signature of
      find_focus_successor(), removing this first parameter.
    
    - It includes logic to decide whether to do the search or not: if the destroyed
      surface is different from the surface that currently has focus, and if their
      outputs are the same, then abort and don't do the search. This returns NULL to
      the calling function. The problem is that the function also returns NULL if
      it does the search and finds no successor. The distinction for the failing
      reason is lost, and the user of the function needs to add more logic to know
      the reason for failure. To simplify, we take the logic out of
      find_focus_successor() and inside the caller.
    
    - It returns the successor view, although it receives surfaces and the client
      has logic to retrieve the surface corresponding to the returned view. To
      simplify and maintain symmetry, we change the signature so that the function
      returns the surface corresponding to the successor view.
    
    Fixes: #738
    
    Signed-off-by: default avatarSergio Gómez <sergio.g.delreal@gmail.com>
    cc837eea
  • Sergio Gómez's avatar
    kiosk-shell: Set the new active surface tree for inactive focus successor · 5d5e8642
    Sergio Gómez authored and Marius Vlad's avatar Marius Vlad committed
    
    
    If we have a successor view that comes from the inactive layer, this means that
    we have a change in the active surface tree, so call
    kiosk_shell_output_set_active_surface_tree() on the root of that view's kiosk
    surface.
    If we have no successors, just reset the current active surface tree.
    
    Signed-off-by: default avatarSergio Gómez <sergio.g.delreal@gmail.com>
    5d5e8642
  • Sergio Gómez's avatar
    kiosk-shell: Implement new view layer handling logic in surface activation · 19539314
    Sergio Gómez authored and Marius Vlad's avatar Marius Vlad committed
    
    
    Replace previous logic when placing views in the weston layers upon surface
    activation with new one that takes into account the surface tree lists design
    from the previous commits.
    
    This commit is based on previous code by Alexandros Frantzis.
    
    Fixes: #680
    
    Signed-off-by: default avatarSergio Gómez <sergio.g.delreal@gmail.com>
    19539314
......@@ -1221,6 +1221,9 @@ struct weston_layer_entry {
* at their discretion.
*/
enum weston_layer_position {
/* Special value to indicate an invalid layer position. */
WESTON_LAYER_POSITION_NONE = -1,
/*
* Special value to make the layer invisible and still rendered.
* This is used by compositors wanting e.g. minimized surfaces to still
......
......@@ -73,6 +73,9 @@ weston_shell_utils_curtain_create(struct weston_compositor *compositor,
void
weston_shell_utils_curtain_destroy(struct weston_curtain *curtain);
enum weston_layer_position
weston_shell_utils_view_get_layer_position(struct weston_view *view);
#ifdef __cplusplus
}
#endif
......@@ -32,6 +32,7 @@
#include "kiosk-shell.h"
#include "kiosk-shell-grab.h"
#include "compositor/weston.h"
#include "libweston/libweston.h"
#include "shared/helpers.h"
#include <libweston/shell-utils.h>
......@@ -121,6 +122,15 @@ kiosk_shell_surface_set_output(struct kiosk_shell_surface *shsurf,
static void
kiosk_shell_surface_set_parent(struct kiosk_shell_surface *shsurf,
struct kiosk_shell_surface *parent);
static void
kiosk_shell_output_set_active_surface_tree(struct kiosk_shell_output *shoutput,
struct kiosk_shell_surface *shroot);
static void
kiosk_shell_output_raise_surface_subtree(struct kiosk_shell_output *shoutput,
struct kiosk_shell_surface *shroot);
static struct kiosk_shell_output *
kiosk_shell_find_shell_output(struct kiosk_shell *shell,
struct weston_output *output);
static void
kiosk_shell_surface_notify_parent_destroy(struct wl_listener *listener, void *data)
......@@ -257,10 +267,58 @@ kiosk_shell_surface_set_normal(struct kiosk_shell_surface *shsurf)
weston_desktop_surface_set_size(shsurf->desktop_surface, 0, 0);
}
static bool
kiosk_shell_surface_is_surface_in_tree(struct kiosk_shell_surface *shsurf,
struct kiosk_shell_surface *shroot)
{
struct kiosk_shell_surface *s;
wl_list_for_each(s, &shroot->surface_tree_list, surface_tree_link) {
if (s == shsurf)
return true;
}
return false;
}
static bool
kiosk_shell_surface_is_descendant_of(struct kiosk_shell_surface *shsurf,
struct kiosk_shell_surface *ancestor)
{
while (shsurf) {
if (shsurf == ancestor)
return true;
shsurf = shsurf->parent;
}
return false;
}
static void
active_surface_tree_move_element_to_top(struct wl_list *active_surface_tree,
struct wl_list *element)
{
wl_list_remove(element);
wl_list_insert(active_surface_tree, element);
}
static void
kiosk_shell_surface_set_parent(struct kiosk_shell_surface *shsurf,
struct kiosk_shell_surface *parent)
{
struct kiosk_shell_output *shoutput =
kiosk_shell_find_shell_output(shsurf->shell,
shsurf->output);
struct kiosk_shell_surface *shroot = parent ?
kiosk_shell_surface_get_parent_root(parent) :
kiosk_shell_surface_get_parent_root(shsurf);
/* There are cases where xdg clients call .set_parent(nil) on a surface
* that does not have a parent. The protocol states that this is
* effectively a no-op. */
if (!parent && shsurf == shroot)
return;
if (shsurf->parent_destroy_listener.notify) {
wl_list_remove(&shsurf->parent_destroy_listener.link);
shsurf->parent_destroy_listener.notify = NULL;
......@@ -271,11 +329,29 @@ kiosk_shell_surface_set_parent(struct kiosk_shell_surface *shsurf,
if (shsurf->parent) {
shsurf->parent_destroy_listener.notify =
kiosk_shell_surface_notify_parent_destroy;
wl_signal_add(&shsurf->parent->destroy_signal,
wl_signal_add(&parent->parent_destroy_signal,
&shsurf->parent_destroy_listener);
if (!kiosk_shell_surface_is_surface_in_tree(shsurf, shroot)) {
active_surface_tree_move_element_to_top(&shroot->surface_tree_list,
&shsurf->surface_tree_link);
}
kiosk_shell_surface_set_output(shsurf, NULL);
kiosk_shell_surface_set_normal(shsurf);
} else {
struct kiosk_shell_surface *s, *tmp;
/* Relink the child and all its descendents to a new surface
* tree list, with the child as root. */
wl_list_init(&shsurf->surface_tree_list);
wl_list_for_each_reverse_safe(s, tmp, &shroot->surface_tree_list,
surface_tree_link) {
if (kiosk_shell_surface_is_descendant_of(s, shsurf)) {
active_surface_tree_move_element_to_top(&shsurf->surface_tree_list,
&s->surface_tree_link);
}
}
kiosk_shell_output_set_active_surface_tree(shoutput, shsurf);
kiosk_shell_surface_set_fullscreen(shsurf, shsurf->output);
}
}
......@@ -305,6 +381,7 @@ static void
kiosk_shell_surface_destroy(struct kiosk_shell_surface *shsurf)
{
wl_signal_emit(&shsurf->destroy_signal, shsurf);
wl_list_remove(&shsurf->surface_tree_link);
weston_desktop_surface_set_user_data(shsurf->desktop_surface, NULL);
shsurf->desktop_surface = NULL;
......@@ -359,6 +436,12 @@ kiosk_shell_surface_create(struct kiosk_shell *shell,
weston_desktop_surface_set_user_data(desktop_surface, shsurf);
wl_signal_init(&shsurf->destroy_signal);
wl_signal_init(&shsurf->parent_destroy_signal);
/* start life inserting itself as root of its own surface tree list */
wl_list_init(&shsurf->surface_tree_list);
wl_list_init(&shsurf->surface_tree_link);
wl_list_insert(&shsurf->surface_tree_list, &shsurf->surface_tree_link);
return shsurf;
}
......@@ -371,6 +454,8 @@ kiosk_shell_surface_activate(struct kiosk_shell_surface *shsurf,
struct weston_desktop_surface *dsurface = shsurf->desktop_surface;
struct weston_surface *surface =
weston_desktop_surface_get_surface(dsurface);
struct kiosk_shell_output *shoutput =
kiosk_shell_find_shell_output(shsurf->shell, shsurf->output);
/* keyboard focus */
weston_view_activate_input(shsurf->view, kiosk_seat->seat, activate_flags);
......@@ -385,16 +470,6 @@ kiosk_shell_surface_activate(struct kiosk_shell_surface *shsurf,
dsurface_focus = current_focus->desktop_surface;
if (--current_focus->focus_count == 0)
weston_desktop_surface_set_activated(dsurface_focus, false);
/* removes it from the normal_layer and move it to inactive
* one, without occluding the top-level window if the new one
* is a child to that. Also, do not occlude another view
* (currently focused one) on a different output when activating
* a new one. */
if (!shsurf->parent && (shsurf->output == current_focus->output)) {
weston_view_move_to_layer(current_focus->view,
&shsurf->shell->inactive_layer.view_list);
}
}
/* xdg-shell activation for the new one */
......@@ -402,10 +477,8 @@ kiosk_shell_surface_activate(struct kiosk_shell_surface *shsurf,
if (shsurf->focus_count++ == 0)
weston_desktop_surface_set_activated(dsurface, true);
/* removes it from the inactive_layer, on removal of a surface, and
* move it back to the normal layer */
weston_view_move_to_layer(shsurf->view,
&shsurf->shell->normal_layer.view_list);
/* raise the focused subtree to the top of the visible layer */
kiosk_shell_output_raise_surface_subtree(shoutput, shsurf);
}
/*
......@@ -461,6 +534,69 @@ kiosk_shell_seat_create(struct kiosk_shell *shell, struct weston_seat *seat)
* kiosk_shell_output
*/
static void
kiosk_shell_output_set_active_surface_tree(struct kiosk_shell_output *shoutput,
struct kiosk_shell_surface *shroot)
{
struct kiosk_shell *shell = shoutput->shell;
struct kiosk_shell_surface *s;
/* Remove the previous active surface tree (i.e., move the tree to
* WESTON_LAYER_POSITION_HIDDEN) */
if (shoutput->active_surface_tree) {
wl_list_for_each_reverse(s, shoutput->active_surface_tree, surface_tree_link) {
weston_view_move_to_layer(s->view,
&shell->inactive_layer.view_list);
}
}
if (shroot) {
wl_list_for_each_reverse(s, &shroot->surface_tree_list, surface_tree_link) {
weston_view_move_to_layer(s->view,
&shell->normal_layer.view_list);
}
}
shoutput->active_surface_tree = shroot ?
&shroot->surface_tree_list :
NULL;
}
/* Raises the subtree originating at the specified 'shroot' of the output's
* active surface tree to the top of the visible layer. */
static void
kiosk_shell_output_raise_surface_subtree(struct kiosk_shell_output *shoutput,
struct kiosk_shell_surface *shroot)
{
struct kiosk_shell *shell = shroot->shell;
struct wl_list tmp_list;
struct kiosk_shell_surface *s, *tmp_s;
wl_list_init(&tmp_list);
/* Move all shell surfaces in the active surface tree starting at
* shroot to the tmp_list while maintaining the relative order. */
wl_list_for_each_reverse_safe(s, tmp_s,
shoutput->active_surface_tree, surface_tree_link) {
if (kiosk_shell_surface_is_descendant_of(s, shroot)) {
active_surface_tree_move_element_to_top(&tmp_list,
&s->surface_tree_link);
}
}
/* Now insert the views corresponding to the shell surfaces stored to
* the top of the layer in the proper order.
* Also remove the shell surface from tmp_list and insert it at the top
* of the output's active surface tree. */
wl_list_for_each_reverse_safe(s, tmp_s, &tmp_list, surface_tree_link) {
weston_view_move_to_layer(s->view, &shell->normal_layer.view_list);
active_surface_tree_move_element_to_top(shoutput->active_surface_tree,
&s->surface_tree_link);
}
}
static int
kiosk_shell_background_surface_get_label(struct weston_surface *surface,
char *buf, size_t len)
......@@ -630,58 +766,62 @@ desktop_surface_added(struct weston_desktop_surface *desktop_surface,
kiosk_shell_surface_set_fullscreen(shsurf, NULL);
}
/* Return the view that should gain focus after the specified shsurf is
/* Return the shell surface that should gain focus after the specified shsurf is
* destroyed. We prefer the top remaining view from the same parent surface,
* but if we can't find one we fall back to the top view regardless of
* parentage. */
static struct weston_view *
find_focus_successor(struct weston_layer *layer,
struct kiosk_shell_surface *shsurf,
* parentage.
* First look for the successor in the normal layer, and if that
* fails, look for it in the inactive layer, and if that also fails, then there
* is no successor. */
static struct kiosk_shell_surface *
find_focus_successor(struct kiosk_shell_surface *shsurf,
struct weston_surface *focused_surface)
{
struct kiosk_shell_surface *parent_root =
kiosk_shell_surface_get_parent_root(shsurf);
struct weston_view *top_view = NULL;
struct kiosk_shell_surface *successor = NULL;
struct wl_list *layers = &shsurf->shell->compositor->layer_list;
struct weston_layer *layer;
struct weston_view *view;
wl_list_for_each(layer, layers, link) {
struct kiosk_shell *shell = shsurf->shell;
/* we need to take into account that the surface being destroyed it not
* always the same as the focus_surface, which could result in picking
* and *activating* the wrong window, so avoid returning a view for
* that case. A particular case is when a top-level child window, would
* pick a parent window below the focused_surface.
*
* Apply that only on the same output to avoid incorrectly returning an
* invalid/empty view, which could happen if the view being destroyed
* is on a output different than the focused_surface output */
if (focused_surface && focused_surface != shsurf->view->surface &&
shsurf->output == focused_surface->output)
return top_view;
wl_list_for_each(view, &layer->view_list.link, layer_link.link) {
struct kiosk_shell_surface *view_shsurf;
struct kiosk_shell_surface *root;
if (!view->is_mapped || view == shsurf->view)
if (layer != &shell->inactive_layer &&
layer != &shell->normal_layer) {
continue;
}
wl_list_for_each(view, &layer->view_list.link, layer_link.link) {
struct kiosk_shell_surface *view_shsurf;
struct kiosk_shell_surface *root;
/* pick views only on the same output */
if (view->output != shsurf->output)
continue;
if (!view->is_mapped || view == shsurf->view)
continue;
view_shsurf = get_kiosk_shell_surface(view->surface);
if (!view_shsurf)
continue;
/* pick views only on the same output */
if (view->output != shsurf->output)
continue;
view_shsurf = get_kiosk_shell_surface(view->surface);
if (!view_shsurf)
continue;
if (!top_view)
top_view = view;
if (!top_view)
top_view = view;
root = kiosk_shell_surface_get_parent_root(view_shsurf);
if (root == parent_root)
return view;
root = kiosk_shell_surface_get_parent_root(view_shsurf);
if (root == parent_root) {
top_view = view;
break;
}
}
}
return top_view;
if (top_view)
successor = get_kiosk_shell_surface(top_view->surface);
return successor;
}
static void
......@@ -693,7 +833,6 @@ desktop_surface_removed(struct weston_desktop_surface *desktop_surface,
weston_desktop_surface_get_user_data(desktop_surface);
struct weston_surface *surface =
weston_desktop_surface_get_surface(desktop_surface);
struct weston_view *focus_view;
struct weston_seat *seat;
struct kiosk_shell_seat* kiosk_seat;
......@@ -703,19 +842,44 @@ desktop_surface_removed(struct weston_desktop_surface *desktop_surface,
seat = get_kiosk_shell_first_seat(shell);
kiosk_seat = get_kiosk_shell_seat(seat);
if (seat && kiosk_seat) {
focus_view = find_focus_successor(&shell->inactive_layer, shsurf,
kiosk_seat->focused_surface);
/* Inform children about destruction of their parent, so that we can
* reparent them and potentially relink surface tree links before
* finding a focus successor and activating a new surface. */
wl_signal_emit(&shsurf->parent_destroy_signal, shsurf);
if (focus_view) {
struct kiosk_shell_surface *focus_shsurf =
get_kiosk_shell_surface(focus_view->surface);
kiosk_shell_surface_activate(focus_shsurf, kiosk_seat,
/* We need to take into account that the surface being destroyed it not
* always the same as the focused surface, which could result in picking
* and *activating* the wrong window.
*
* Apply that only on the same output to avoid incorrectly picking an
* invalid surface, which could happen if the view being destroyed
* is on a output different than the focused_surface output */
if (seat && kiosk_seat &&
(kiosk_seat->focused_surface == surface ||
surface->output != kiosk_seat->focused_surface->output)) {
struct kiosk_shell_surface *successor;
struct kiosk_shell_output *shoutput;
successor = find_focus_successor(shsurf,
kiosk_seat->focused_surface);
shoutput = kiosk_shell_find_shell_output(shsurf->shell, shsurf->output);
if (shoutput && successor) {
enum weston_layer_position succesor_view_layer_pos;
succesor_view_layer_pos = weston_shell_utils_view_get_layer_position(successor->view);
if (succesor_view_layer_pos == WESTON_LAYER_POSITION_HIDDEN) {
struct kiosk_shell_surface *shroot =
kiosk_shell_surface_get_parent_root(successor);
kiosk_shell_output_set_active_surface_tree(shoutput,
shroot);
}
kiosk_shell_surface_activate(successor, kiosk_seat,
WESTON_ACTIVATE_FLAG_NONE);
} else {
if (kiosk_seat->focused_surface == surface)
kiosk_seat->focused_surface = NULL;
kiosk_seat->focused_surface = NULL;
kiosk_shell_output_set_active_surface_tree(shoutput,
NULL);
}
}
......@@ -789,12 +953,23 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface,
if (!weston_surface_is_mapped(surface)) {
struct weston_seat *seat =
get_kiosk_shell_first_seat(shsurf->shell);
struct kiosk_shell_output *shoutput =
kiosk_shell_find_shell_output(shsurf->shell,
shsurf->output);
struct kiosk_shell_seat *kiosk_seat;
shsurf->view->is_mapped = true;
weston_surface_map(surface);
kiosk_seat = get_kiosk_shell_seat(seat);
/* We are mapping a new surface tree root; set it active,
* replacing the previous one */
if (!shsurf->parent) {
kiosk_shell_output_set_active_surface_tree(shoutput,
shsurf);
}
if (seat && kiosk_seat)
kiosk_shell_surface_activate(shsurf, kiosk_seat,
WESTON_ACTIVATE_FLAG_NONE);
......@@ -1011,18 +1186,10 @@ kiosk_shell_activate_view(struct kiosk_shell *shell,
struct kiosk_shell_seat *kiosk_seat =
get_kiosk_shell_seat(seat);
if (!shsurf)
if (!shsurf || !kiosk_seat)
return;
/* If the view belongs to a child window bring it to the front.
* We don't do this for the parent top-level, since that would
* obscure all children.
*/
if (shsurf->parent)
weston_view_move_to_layer(view, &shell->normal_layer.view_list);
if (kiosk_seat)
kiosk_shell_surface_activate(shsurf, kiosk_seat, flags);
kiosk_shell_surface_activate(shsurf, kiosk_seat, flags);
}
static void
......
......@@ -60,9 +60,14 @@ struct kiosk_shell_surface {
struct wl_listener output_destroy_listener;
struct wl_signal destroy_signal;
struct wl_signal parent_destroy_signal;
struct wl_listener parent_destroy_listener;
struct kiosk_shell_surface *parent;
struct wl_list surface_tree_list;
struct wl_list surface_tree_link;
int focus_count;
int32_t last_width, last_height;
......@@ -94,6 +99,8 @@ struct kiosk_shell_output {
struct wl_list link;
char *app_ids;
struct wl_list *active_surface_tree;
};
#endif /* WESTON_KIOSK_SHELL_H */
......@@ -250,3 +250,15 @@ weston_shell_utils_curtain_destroy(struct weston_curtain *curtain)
weston_buffer_destroy_solid(curtain->buffer_ref);
free(curtain);
}
/**
* \ingroup shell-utils
*/
WL_EXPORT enum weston_layer_position
weston_shell_utils_view_get_layer_position(struct weston_view *view)
{
if (!weston_view_is_mapped(view))
return WESTON_LAYER_POSITION_NONE;
return view->layer_link.layer->position;
}