@ -251,6 +251,44 @@ struct ping_timer {
uint32_t serial ;
uint32_t serial ;
} ;
} ;
/*
* Surface stacking and ordering .
*
* This is handled using several linked lists of surfaces , organised into
* ‘ layers ’ . The layers are ordered , and each of the surfaces in one layer are
* above all of the surfaces in the layer below . The set of layers is static and
* in the following order ( top - most first ) :
* • Lock layer ( only ever displayed on its own )
* • Cursor layer
* • Fullscreen layer
* • Panel layer
* • Input panel layer
* • Workspace layers
* • Background layer
*
* The list of layers may be manipulated to remove whole layers of surfaces from
* display . For example , when locking the screen , all layers except the lock
* layer are removed .
*
* A surface ’ s layer is modified on configuring the surface , in
* set_surface_type ( ) ( which is only called when the surface ’ s type change is
* _committed_ ) . If a surface ’ s type changes ( e . g . when making a window
* fullscreen ) its layer changes too .
*
* In order to allow popup and transient surfaces to be correctly stacked above
* their parent surfaces , each surface tracks both its parent surface , and a
* linked list of its children . When a surface ’ s layer is updated , so are the
* layers of its children . Note that child surfaces are * not * the same as
* subsurfaces — child / parent surfaces are purely for maintaining stacking
* order .
*
* The children_link list of siblings of a surface ( i . e . those surfaces which
* have the same parent ) only contains weston_surfaces which have a
* shell_surface . Stacking is not implemented for non - shell_surface
* weston_surfaces . This means that the following implication does * not * hold :
* ( shsurf - > parent ! = NULL ) ⇒ ! wl_list_is_empty ( shsurf - > children_link )
*/
struct shell_surface {
struct shell_surface {
struct wl_resource * resource ;
struct wl_resource * resource ;
struct wl_signal destroy_signal ;
struct wl_signal destroy_signal ;
@ -259,6 +297,8 @@ struct shell_surface {
struct weston_view * view ;
struct weston_view * view ;
struct wl_listener surface_destroy_listener ;
struct wl_listener surface_destroy_listener ;
struct weston_surface * parent ;
struct weston_surface * parent ;
struct wl_list children_list ; /* child surfaces of this one */
struct wl_list children_link ; /* sibling surfaces of this one */
struct desktop_shell * shell ;
struct desktop_shell * shell ;
enum shell_surface_type type , next_type ;
enum shell_surface_type type , next_type ;
@ -369,6 +409,9 @@ shell_fade_startup(struct desktop_shell *shell);
static struct shell_seat *
static struct shell_seat *
get_shell_seat ( struct weston_seat * seat ) ;
get_shell_seat ( struct weston_seat * seat ) ;
static void
shell_surface_update_child_surface_layers ( struct shell_surface * shsurf ) ;
static bool
static bool
shell_surface_is_top_fullscreen ( struct shell_surface * shsurf )
shell_surface_is_top_fullscreen ( struct shell_surface * shsurf )
{
{
@ -1263,6 +1306,8 @@ move_surface_to_workspace(struct desktop_shell *shell,
wl_list_remove ( & view - > layer_link ) ;
wl_list_remove ( & view - > layer_link ) ;
wl_list_insert ( & to - > layer . view_list , & view - > layer_link ) ;
wl_list_insert ( & to - > layer . view_list , & view - > layer_link ) ;
shell_surface_update_child_surface_layers ( shsurf ) ;
drop_focus_state ( shell , from , view - > surface ) ;
drop_focus_state ( shell , from , view - > surface ) ;
wl_list_for_each ( seat , & shell - > compositor - > seat_list , link ) {
wl_list_for_each ( seat , & shell - > compositor - > seat_list , link ) {
if ( ! seat - > keyboard )
if ( ! seat - > keyboard )
@ -1302,6 +1347,8 @@ take_surface_to_workspace_by_seat(struct desktop_shell *shell,
wl_list_insert ( & to - > layer . view_list , & view - > layer_link ) ;
wl_list_insert ( & to - > layer . view_list , & view - > layer_link ) ;
shsurf = get_shell_surface ( surface ) ;
shsurf = get_shell_surface ( surface ) ;
if ( shsurf ! = NULL )
shell_surface_update_child_surface_layers ( shsurf ) ;
replace_focus_state ( shell , to , seat ) ;
replace_focus_state ( shell , to , seat ) ;
drop_focus_state ( shell , from , surface ) ;
drop_focus_state ( shell , from , surface ) ;
@ -2083,8 +2130,36 @@ shell_surface_calculate_layer_link (struct shell_surface *shsurf)
return & ws - > layer . view_list ;
return & ws - > layer . view_list ;
}
}
static void
shell_surface_update_child_surface_layers ( struct shell_surface * shsurf )
{
struct shell_surface * child ;
/* Move the child layers to the same workspace as shsurf. They will be
* stacked above shsurf . */
wl_list_for_each_reverse ( child , & shsurf - > children_list , children_link ) {
if ( shsurf - > view - > layer_link . prev ! = & child - > view - > layer_link ) {
weston_view_geometry_dirty ( child - > view ) ;
wl_list_remove ( & child - > view - > layer_link ) ;
wl_list_insert ( shsurf - > view - > layer_link . prev ,
& child - > view - > layer_link ) ;
weston_view_geometry_dirty ( child - > view ) ;
weston_surface_damage ( child - > surface ) ;
/* Recurse. We don’t expect this to recurse very far (if
* at all ) because that would imply we have transient
* ( or popup ) children of transient surfaces , which
* would be unusual . */
shell_surface_update_child_surface_layers ( child ) ;
}
}
}
/* Update the surface’s layer. Mark both the old and new views as having dirty
/* Update the surface’s layer. Mark both the old and new views as having dirty
* geometry to ensure the changes are redrawn . */
* geometry to ensure the changes are redrawn .
*
* If any child surfaces exist and are mapped , ensure they ’ re in the same layer
* as this surface . */
static void
static void
shell_surface_update_layer ( struct shell_surface * shsurf )
shell_surface_update_layer ( struct shell_surface * shsurf )
{
{
@ -2100,6 +2175,8 @@ shell_surface_update_layer(struct shell_surface *shsurf)
wl_list_insert ( new_layer_link , & shsurf - > view - > layer_link ) ;
wl_list_insert ( new_layer_link , & shsurf - > view - > layer_link ) ;
weston_view_geometry_dirty ( shsurf - > view ) ;
weston_view_geometry_dirty ( shsurf - > view ) ;
weston_surface_damage ( shsurf - > surface ) ;
weston_surface_damage ( shsurf - > surface ) ;
shell_surface_update_child_surface_layers ( shsurf ) ;
}
}
static void
static void
@ -2107,6 +2184,17 @@ shell_surface_set_parent(struct shell_surface *shsurf,
struct weston_surface * parent )
struct weston_surface * parent )
{
{
shsurf - > parent = parent ;
shsurf - > parent = parent ;
wl_list_remove ( & shsurf - > children_link ) ;
wl_list_init ( & shsurf - > children_link ) ;
/* Insert into the parent surface’s child list. */
if ( parent ! = NULL ) {
struct shell_surface * parent_shsurf = get_shell_surface ( parent ) ;
if ( parent_shsurf ! = NULL )
wl_list_insert ( & parent_shsurf - > children_list ,
& shsurf - > children_link ) ;
}
}
}
static void
static void
@ -2131,6 +2219,9 @@ set_toplevel(struct shell_surface *shsurf)
shell_surface_set_parent ( shsurf , NULL ) ;
shell_surface_set_parent ( shsurf , NULL ) ;
shsurf - > next_type = SHELL_SURFACE_TOPLEVEL ;
shsurf - > next_type = SHELL_SURFACE_TOPLEVEL ;
/* The layer_link is updated in set_surface_type(),
* called from configure . */
}
}
static void
static void
@ -2155,6 +2246,9 @@ set_transient(struct shell_surface *shsurf,
shell_surface_set_parent ( shsurf , parent ) ;
shell_surface_set_parent ( shsurf , parent ) ;
shsurf - > next_type = SHELL_SURFACE_TRANSIENT ;
shsurf - > next_type = SHELL_SURFACE_TRANSIENT ;
/* The layer_link is updated in set_surface_type(),
* called from configure . */
}
}
static void
static void
@ -2189,6 +2283,9 @@ set_fullscreen(struct shell_surface *shsurf,
shsurf - > client - > send_configure ( shsurf - > surface , 0 ,
shsurf - > client - > send_configure ( shsurf - > surface , 0 ,
shsurf - > output - > width ,
shsurf - > output - > width ,
shsurf - > output - > height ) ;
shsurf - > output - > height ) ;
/* The layer_link is updated in set_surface_type(),
* called from configure . */
}
}
static void
static void
@ -2851,6 +2948,8 @@ destroy_shell_surface(struct shell_surface *shsurf)
weston_view_destroy ( shsurf - > view ) ;
weston_view_destroy ( shsurf - > view ) ;
wl_list_remove ( & shsurf - > children_link ) ;
wl_list_remove ( & shsurf - > link ) ;
wl_list_remove ( & shsurf - > link ) ;
free ( shsurf ) ;
free ( shsurf ) ;
}
}
@ -2941,6 +3040,10 @@ create_shell_surface(void *shell, struct weston_surface *surface,
wl_list_init ( & shsurf - > workspace_transform . link ) ;
wl_list_init ( & shsurf - > workspace_transform . link ) ;
wl_list_init ( & shsurf - > children_link ) ;
wl_list_init ( & shsurf - > children_list ) ;
shsurf - > parent = NULL ;
shsurf - > type = SHELL_SURFACE_NONE ;
shsurf - > type = SHELL_SURFACE_NONE ;
shsurf - > next_type = SHELL_SURFACE_NONE ;
shsurf - > next_type = SHELL_SURFACE_NONE ;