mirror of
https://github.com/brl/mutter.git
synced 2024-11-25 09:30:45 -05:00
wayland/subsurface: Move placement ops to the parents pending state
Unlike other subsurface state, placement operations need to get applied in order. As per spec: ``` Requests are handled in order and applied immediately to a pending state. The final pending state is copied to the active state the next time the state of the parent surface is applied. ``` Having placement operations being part of the subsurface state makes it difficult to support arbitrary orderings. Make them part of the parents surface pending state instead. Closes https://gitlab.gnome.org/GNOME/mutter/-/issues/1691 Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1768>
This commit is contained in:
parent
eed368ee91
commit
ba8499f9ec
@ -30,19 +30,6 @@
|
|||||||
#include "wayland/meta-wayland-surface.h"
|
#include "wayland/meta-wayland-surface.h"
|
||||||
#include "wayland/meta-window-wayland.h"
|
#include "wayland/meta-window-wayland.h"
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE,
|
|
||||||
META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW
|
|
||||||
} MetaWaylandSubsurfacePlacement;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
MetaWaylandSubsurfacePlacement placement;
|
|
||||||
MetaWaylandSurface *sibling;
|
|
||||||
struct wl_listener sibling_destroy_listener;
|
|
||||||
} MetaWaylandSubsurfacePlacementOp;
|
|
||||||
|
|
||||||
struct _MetaWaylandSubsurface
|
struct _MetaWaylandSubsurface
|
||||||
{
|
{
|
||||||
MetaWaylandActorSurface parent;
|
MetaWaylandActorSurface parent;
|
||||||
@ -146,57 +133,6 @@ meta_wayland_subsurface_parent_state_applied (MetaWaylandSubsurface *subsurface)
|
|||||||
surface->sub.pending_pos = FALSE;
|
surface->sub.pending_pos = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (surface->sub.pending_placement_ops)
|
|
||||||
{
|
|
||||||
GSList *it;
|
|
||||||
MetaWaylandSurface *parent;
|
|
||||||
|
|
||||||
parent = surface->sub.parent;
|
|
||||||
|
|
||||||
for (it = surface->sub.pending_placement_ops; it; it = it->next)
|
|
||||||
{
|
|
||||||
MetaWaylandSubsurfacePlacementOp *op = it->data;
|
|
||||||
MetaWaylandSurface *sibling;
|
|
||||||
GNode *sibling_node;
|
|
||||||
|
|
||||||
if (!op->sibling)
|
|
||||||
{
|
|
||||||
g_free (op);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
sibling = op->sibling;
|
|
||||||
if (is_child (surface, sibling))
|
|
||||||
sibling_node = sibling->subsurface_leaf_node;
|
|
||||||
else
|
|
||||||
sibling_node = sibling->subsurface_branch_node;
|
|
||||||
|
|
||||||
g_node_unlink (surface->subsurface_branch_node);
|
|
||||||
|
|
||||||
switch (op->placement)
|
|
||||||
{
|
|
||||||
case META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE:
|
|
||||||
g_node_insert_after (parent->subsurface_branch_node,
|
|
||||||
sibling_node,
|
|
||||||
surface->subsurface_branch_node);
|
|
||||||
break;
|
|
||||||
case META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW:
|
|
||||||
g_node_insert_before (parent->subsurface_branch_node,
|
|
||||||
sibling_node,
|
|
||||||
surface->subsurface_branch_node);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_list_remove (&op->sibling_destroy_listener.link);
|
|
||||||
g_free (op);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_slist_free (surface->sub.pending_placement_ops);
|
|
||||||
surface->sub.pending_placement_ops = NULL;
|
|
||||||
|
|
||||||
meta_wayland_surface_notify_subsurface_state_changed (parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_surface_effectively_synchronized (surface))
|
if (is_surface_effectively_synchronized (surface))
|
||||||
meta_wayland_surface_apply_cached_state (surface);
|
meta_wayland_surface_apply_cached_state (surface);
|
||||||
|
|
||||||
@ -418,6 +354,16 @@ is_valid_sibling (MetaWaylandSurface *surface,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
subsurface_handle_pending_surface_destroyed (struct wl_listener *listener,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
MetaWaylandSubsurfacePlacementOp *op =
|
||||||
|
wl_container_of (listener, op, surface_destroy_listener);
|
||||||
|
|
||||||
|
op->surface = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
subsurface_handle_pending_sibling_destroyed (struct wl_listener *listener,
|
subsurface_handle_pending_sibling_destroyed (struct wl_listener *listener,
|
||||||
void *data)
|
void *data)
|
||||||
@ -428,23 +374,39 @@ subsurface_handle_pending_sibling_destroyed (struct wl_listener *listener,
|
|||||||
op->sibling = NULL;
|
op->sibling = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_wayland_subsurface_placement_op_free (MetaWaylandSubsurfacePlacementOp *op)
|
||||||
|
{
|
||||||
|
if (op->surface)
|
||||||
|
wl_list_remove (&op->surface_destroy_listener.link);
|
||||||
|
if (op->sibling)
|
||||||
|
wl_list_remove (&op->sibling_destroy_listener.link);
|
||||||
|
g_free (op);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
queue_subsurface_placement (MetaWaylandSurface *surface,
|
queue_subsurface_placement (MetaWaylandSurface *surface,
|
||||||
MetaWaylandSurface *sibling,
|
MetaWaylandSurface *sibling,
|
||||||
MetaWaylandSubsurfacePlacement placement)
|
MetaWaylandSubsurfacePlacement placement)
|
||||||
{
|
{
|
||||||
|
MetaWaylandSurface *parent = surface->sub.parent;
|
||||||
MetaWaylandSubsurfacePlacementOp *op =
|
MetaWaylandSubsurfacePlacementOp *op =
|
||||||
g_new0 (MetaWaylandSubsurfacePlacementOp, 1);
|
g_new0 (MetaWaylandSubsurfacePlacementOp, 1);
|
||||||
|
|
||||||
op->placement = placement;
|
op->placement = placement;
|
||||||
|
op->surface = surface;
|
||||||
op->sibling = sibling;
|
op->sibling = sibling;
|
||||||
|
op->surface_destroy_listener.notify =
|
||||||
|
subsurface_handle_pending_surface_destroyed;
|
||||||
op->sibling_destroy_listener.notify =
|
op->sibling_destroy_listener.notify =
|
||||||
subsurface_handle_pending_sibling_destroyed;
|
subsurface_handle_pending_sibling_destroyed;
|
||||||
|
wl_resource_add_destroy_listener (surface->resource,
|
||||||
|
&op->surface_destroy_listener);
|
||||||
wl_resource_add_destroy_listener (sibling->resource,
|
wl_resource_add_destroy_listener (sibling->resource,
|
||||||
&op->sibling_destroy_listener);
|
&op->sibling_destroy_listener);
|
||||||
|
|
||||||
surface->sub.pending_placement_ops =
|
parent->pending_state->subsurface_placement_ops =
|
||||||
g_slist_append (surface->sub.pending_placement_ops, op);
|
g_slist_append (parent->pending_state->subsurface_placement_ops, op);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -29,6 +29,21 @@ G_DECLARE_FINAL_TYPE (MetaWaylandSubsurface,
|
|||||||
META, WAYLAND_SUBSURFACE,
|
META, WAYLAND_SUBSURFACE,
|
||||||
MetaWaylandActorSurface)
|
MetaWaylandActorSurface)
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE,
|
||||||
|
META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW
|
||||||
|
} MetaWaylandSubsurfacePlacement;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
MetaWaylandSubsurfacePlacement placement;
|
||||||
|
MetaWaylandSurface *surface;
|
||||||
|
MetaWaylandSurface *sibling;
|
||||||
|
struct wl_listener surface_destroy_listener;
|
||||||
|
struct wl_listener sibling_destroy_listener;
|
||||||
|
} MetaWaylandSubsurfacePlacementOp;
|
||||||
|
|
||||||
void meta_wayland_subsurface_parent_state_applied (MetaWaylandSubsurface *subsurface);
|
void meta_wayland_subsurface_parent_state_applied (MetaWaylandSubsurface *subsurface);
|
||||||
|
|
||||||
void meta_wayland_subsurface_union_geometry (MetaWaylandSubsurface *subsurface,
|
void meta_wayland_subsurface_union_geometry (MetaWaylandSubsurface *subsurface,
|
||||||
@ -36,6 +51,8 @@ void meta_wayland_subsurface_union_geometry (MetaWaylandSubsurface *subsurface,
|
|||||||
int parent_y,
|
int parent_y,
|
||||||
MetaRectangle *out_geometry);
|
MetaRectangle *out_geometry);
|
||||||
|
|
||||||
|
void meta_wayland_subsurface_placement_op_free (MetaWaylandSubsurfacePlacementOp *op);
|
||||||
|
|
||||||
void meta_wayland_subsurfaces_init (MetaWaylandCompositor *compositor);
|
void meta_wayland_subsurfaces_init (MetaWaylandCompositor *compositor);
|
||||||
|
|
||||||
#endif /* META_WAYLAND_SUBSURFACE_H */
|
#endif /* META_WAYLAND_SUBSURFACE_H */
|
||||||
|
@ -468,6 +468,8 @@ meta_wayland_surface_state_set_default (MetaWaylandSurfaceState *state)
|
|||||||
state->has_new_viewport_src_rect = FALSE;
|
state->has_new_viewport_src_rect = FALSE;
|
||||||
state->has_new_viewport_dst_size = FALSE;
|
state->has_new_viewport_dst_size = FALSE;
|
||||||
|
|
||||||
|
state->subsurface_placement_ops = NULL;
|
||||||
|
|
||||||
wl_list_init (&state->presentation_feedback_list);
|
wl_list_init (&state->presentation_feedback_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -499,6 +501,13 @@ meta_wayland_surface_state_clear (MetaWaylandSurfaceState *state)
|
|||||||
wl_list_for_each_safe (cb, next, &state->frame_callback_list, link)
|
wl_list_for_each_safe (cb, next, &state->frame_callback_list, link)
|
||||||
wl_resource_destroy (cb->resource);
|
wl_resource_destroy (cb->resource);
|
||||||
|
|
||||||
|
if (state->subsurface_placement_ops)
|
||||||
|
{
|
||||||
|
g_slist_free_full (
|
||||||
|
state->subsurface_placement_ops,
|
||||||
|
(GDestroyNotify) meta_wayland_subsurface_placement_op_free);
|
||||||
|
}
|
||||||
|
|
||||||
meta_wayland_surface_state_discard_presentation_feedback (state);
|
meta_wayland_surface_state_discard_presentation_feedback (state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -609,6 +618,21 @@ meta_wayland_surface_state_merge_into (MetaWaylandSurfaceState *from,
|
|||||||
to);
|
to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (from->subsurface_placement_ops != NULL)
|
||||||
|
{
|
||||||
|
if (to->subsurface_placement_ops != NULL)
|
||||||
|
{
|
||||||
|
to->subsurface_placement_ops =
|
||||||
|
g_slist_concat (to->subsurface_placement_ops,
|
||||||
|
from->subsurface_placement_ops);
|
||||||
|
from->subsurface_placement_ops = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
to->subsurface_placement_ops = from->subsurface_placement_ops;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wl_list_insert_list (&to->presentation_feedback_list,
|
wl_list_insert_list (&to->presentation_feedback_list,
|
||||||
&from->presentation_feedback_list);
|
&from->presentation_feedback_list);
|
||||||
wl_list_init (&from->presentation_feedback_list);
|
wl_list_init (&from->presentation_feedback_list);
|
||||||
@ -827,6 +851,43 @@ meta_wayland_surface_apply_state (MetaWaylandSurface *surface,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state->subsurface_placement_ops)
|
||||||
|
{
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
for (l = state->subsurface_placement_ops; l; l = l->next)
|
||||||
|
{
|
||||||
|
MetaWaylandSubsurfacePlacementOp *op = l->data;
|
||||||
|
GNode *sibling_node;
|
||||||
|
|
||||||
|
if (!op->surface || !op->sibling)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (op->sibling == surface)
|
||||||
|
sibling_node = surface->subsurface_leaf_node;
|
||||||
|
else
|
||||||
|
sibling_node = op->sibling->subsurface_branch_node;
|
||||||
|
|
||||||
|
g_node_unlink (op->surface->subsurface_branch_node);
|
||||||
|
|
||||||
|
switch (op->placement)
|
||||||
|
{
|
||||||
|
case META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE:
|
||||||
|
g_node_insert_after (surface->subsurface_branch_node,
|
||||||
|
sibling_node,
|
||||||
|
op->surface->subsurface_branch_node);
|
||||||
|
break;
|
||||||
|
case META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW:
|
||||||
|
g_node_insert_before (surface->subsurface_branch_node,
|
||||||
|
sibling_node,
|
||||||
|
op->surface->subsurface_branch_node);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_wayland_surface_notify_subsurface_state_changed (surface);
|
||||||
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
/* If we have a buffer that we are not using, decrease the use count so it may
|
/* If we have a buffer that we are not using, decrease the use count so it may
|
||||||
* be released if no-one else has a use-reference to it.
|
* be released if no-one else has a use-reference to it.
|
||||||
|
@ -121,6 +121,8 @@ struct _MetaWaylandSurfaceState
|
|||||||
int viewport_dst_width;
|
int viewport_dst_width;
|
||||||
int viewport_dst_height;
|
int viewport_dst_height;
|
||||||
|
|
||||||
|
GSList *subsurface_placement_ops;
|
||||||
|
|
||||||
/* presentation-time */
|
/* presentation-time */
|
||||||
struct wl_list presentation_feedback_list;
|
struct wl_list presentation_feedback_list;
|
||||||
};
|
};
|
||||||
@ -212,7 +214,6 @@ struct _MetaWaylandSurface
|
|||||||
int32_t pending_x;
|
int32_t pending_x;
|
||||||
int32_t pending_y;
|
int32_t pending_y;
|
||||||
gboolean pending_pos;
|
gboolean pending_pos;
|
||||||
GSList *pending_placement_ops;
|
|
||||||
} sub;
|
} sub;
|
||||||
|
|
||||||
/* wp_viewport */
|
/* wp_viewport */
|
||||||
|
Loading…
Reference in New Issue
Block a user