libweston: add weston_view_set_output()
Instead of desktop shell assigning view outputs directly, use a new method, weston_view_set_output(). The method can set up an output destroy listener to make sure that views do not have stale output pointers. Without this patch it is possible to end up in a scenario where, e.g. configure_static_view() accesses memory that has already been freed. The scenario can be provoked by repeatedly plugging and unplugging a display. The faulty memory accesses are reported by valgrind. Signed-off-by: Semi Malinen <semi.malinen@ge.com> Signed-off-by: Fabien Lahoudere <fabien.lahoudere@collabora.com> Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
This commit is contained in:
parent
03dc95a131
commit
e7a52fbb7d
|
@ -580,7 +580,7 @@ create_focus_surface(struct weston_compositor *ec,
|
|||
free(fsurf);
|
||||
return NULL;
|
||||
}
|
||||
fsurf->view->output = output;
|
||||
weston_view_set_output(fsurf->view, output);
|
||||
fsurf->view->is_mapped = true;
|
||||
|
||||
weston_surface_set_size(surface, output->width, output->height);
|
||||
|
@ -2464,7 +2464,7 @@ map(struct desktop_shell *shell, struct shell_surface *shsurf,
|
|||
shsurf->view->is_mapped = true;
|
||||
if (shsurf->state.maximized) {
|
||||
surface->output = shsurf->output;
|
||||
shsurf->view->output = shsurf->output;
|
||||
weston_view_set_output(shsurf->view, shsurf->output);
|
||||
}
|
||||
|
||||
if (!shell->locked) {
|
||||
|
@ -2881,6 +2881,9 @@ configure_static_view(struct weston_view *ev, struct weston_layer *layer, int x,
|
|||
{
|
||||
struct weston_view *v, *next;
|
||||
|
||||
if (!ev->output)
|
||||
return;
|
||||
|
||||
wl_list_for_each_safe(v, next, &layer->view_list.link, layer_link.link) {
|
||||
if (v->output == ev->output && v != ev) {
|
||||
weston_view_unmap(v);
|
||||
|
@ -2970,7 +2973,7 @@ desktop_shell_set_background(struct wl_client *client,
|
|||
surface->committed_private = shell;
|
||||
weston_surface_set_label_func(surface, background_get_label);
|
||||
surface->output = weston_head_from_resource(output_resource)->output;
|
||||
view->output = surface->output;
|
||||
weston_view_set_output(view, surface->output);
|
||||
|
||||
sh_output = find_shell_output_from_weston_output(shell, surface->output);
|
||||
if (sh_output->background_surface) {
|
||||
|
@ -3067,7 +3070,7 @@ desktop_shell_set_panel(struct wl_client *client,
|
|||
surface->committed_private = shell;
|
||||
weston_surface_set_label_func(surface, panel_get_label);
|
||||
surface->output = weston_head_from_resource(output_resource)->output;
|
||||
view->output = surface->output;
|
||||
weston_view_set_output(view, surface->output);
|
||||
|
||||
sh_output = find_shell_output_from_weston_output(shell, surface->output);
|
||||
if (sh_output->panel_surface) {
|
||||
|
|
|
@ -1022,6 +1022,45 @@ weston_surface_update_output_mask(struct weston_surface *es, uint32_t mask)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
notify_view_output_destroy(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct weston_view *view =
|
||||
container_of(listener,
|
||||
struct weston_view, output_destroy_listener);
|
||||
|
||||
view->output = NULL;
|
||||
view->output_destroy_listener.notify = NULL;
|
||||
}
|
||||
|
||||
/** Set the primary output of the view
|
||||
*
|
||||
* \param view The view whose primary output to set
|
||||
* \param output The new primary output for the view
|
||||
*
|
||||
* Set \a output to be the primary output of the \a view.
|
||||
*
|
||||
* Notice that the assignment may be temporary; the primary output could be
|
||||
* automatically changed. Hence, one cannot rely on the value persisting.
|
||||
*
|
||||
* Passing NULL as /a output will set the primary output to NULL.
|
||||
*/
|
||||
WL_EXPORT void
|
||||
weston_view_set_output(struct weston_view *view, struct weston_output *output)
|
||||
{
|
||||
if (view->output_destroy_listener.notify) {
|
||||
wl_list_remove(&view->output_destroy_listener.link);
|
||||
view->output_destroy_listener.notify = NULL;
|
||||
}
|
||||
view->output = output;
|
||||
if (output) {
|
||||
view->output_destroy_listener.notify =
|
||||
notify_view_output_destroy;
|
||||
wl_signal_add(&output->destroy_signal,
|
||||
&view->output_destroy_listener);
|
||||
}
|
||||
}
|
||||
|
||||
/** Recalculate which output(s) the surface has views displayed on
|
||||
*
|
||||
* \param es The surface to remap to outputs
|
||||
|
@ -1113,7 +1152,7 @@ weston_view_assign_output(struct weston_view *ev)
|
|||
}
|
||||
pixman_region32_fini(®ion);
|
||||
|
||||
ev->output = new_output;
|
||||
weston_view_set_output(ev, new_output);
|
||||
ev->output_mask = mask;
|
||||
|
||||
weston_surface_assign_output(ev->surface);
|
||||
|
@ -1823,7 +1862,7 @@ weston_view_unmap(struct weston_view *view)
|
|||
return;
|
||||
|
||||
weston_view_damage_below(view);
|
||||
view->output = NULL;
|
||||
weston_view_set_output(view, NULL);
|
||||
view->plane = NULL;
|
||||
view->is_mapped = false;
|
||||
weston_layer_entry_remove(&view->layer_link);
|
||||
|
|
|
@ -1183,6 +1183,7 @@ struct weston_view {
|
|||
* view, inheriting the primary output for related views in shells, etc.
|
||||
*/
|
||||
struct weston_output *output;
|
||||
struct wl_listener output_destroy_listener;
|
||||
|
||||
/*
|
||||
* A more complete representation of all outputs this surface is
|
||||
|
@ -1397,6 +1398,9 @@ enum weston_activate_flag {
|
|||
void
|
||||
weston_version(int *major, int *minor, int *micro);
|
||||
|
||||
void
|
||||
weston_view_set_output(struct weston_view *view, struct weston_output *output);
|
||||
|
||||
void
|
||||
weston_view_update_transform(struct weston_view *view);
|
||||
|
||||
|
|
Loading…
Reference in New Issue