If unplugged output is a clone output or a master output without associated clone output, just destroy it as normal.
If unplugged output is a master output with associated clone output, one clone output will be upgraded to master output, this new master is put at the end of compositor->output_list. Signed-off-by: Xiong Zhang <xiong.y.zh...@intel.com> --- src/compositor-drm.c | 40 ++++++++++++++++++++++++++++------------ src/compositor.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 12 deletions(-) diff --git a/src/compositor-drm.c b/src/compositor-drm.c index a30f88d..56d60d9 100644 --- a/src/compositor-drm.c +++ b/src/compositor-drm.c @@ -2252,11 +2252,36 @@ create_outputs(struct drm_compositor *ec, uint32_t option_connector, } static void +destroy_disconnect_output(struct drm_output *output, uint32_t *disconnects) +{ + if (*disconnects & (1 << output->connector_id)) { + *disconnects &= ~(1 << output->connector_id); + + weston_log("connector %d disconnected\n", output->connector_id); + + drm_output_destroy(&output->base); + } +} + +static void +destroy_disconnect_outputs(struct drm_compositor *ec, uint32_t disconnects) +{ + struct drm_output *output, *clone, *next1, *next2; + + wl_list_for_each_safe(output, next1, &ec->base.output_list, base.link) { + wl_list_for_each_safe(clone, next2, + &output->base.clone_output_list, base.link) + destroy_disconnect_output(clone, &disconnects); + + destroy_disconnect_output(output, &disconnects); + } +} + +static void update_outputs(struct drm_compositor *ec, struct udev_device *drm_device) { drmModeConnector *connector; drmModeRes *resources; - struct drm_output *output, *next; uint32_t connected = 0, disconnects = 0; int i, add_output = 0; @@ -2300,17 +2325,8 @@ update_outputs(struct drm_compositor *ec, struct udev_device *drm_device) } disconnects = ec->connector_allocator & ~connected; - if (disconnects) { - wl_list_for_each_safe(output, next, &ec->base.output_list, - base.link) { - if (disconnects & (1 << output->connector_id)) { - disconnects &= ~(1 << output->connector_id); - weston_log("connector %d disconnected\n", - output->connector_id); - drm_output_destroy(&output->base); - } - } - } + if (disconnects) + destroy_disconnect_outputs(ec, disconnects); /* FIXME: handle zero outputs, without terminating */ if (ec->connector_allocator == 0) diff --git a/src/compositor.c b/src/compositor.c index 39081bb..5694d29 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -3117,6 +3117,24 @@ weston_compositor_add_clone_outputs(struct weston_compositor *compositor) } } +/* The output with max width wll be new master. */ +static struct weston_output * +find_new_master(struct weston_output *master) +{ + struct weston_output *new, *output; + int32_t max_width = 0; + + new = NULL; + wl_list_for_each(output, &master->clone_output_list, link) { + if (output->width > max_width) { + new = output; + max_width = output->width; + } + } + + return new; +} + /* Move other outputs when one is removed so the space remains contiguos. */ static void weston_compositor_remove_output(struct weston_compositor *compositor, @@ -3176,11 +3194,39 @@ migrate_clone_output(struct weston_output *clone, struct weston_output *master) clone->original_scale); } +/* If a master is unplugged, one output will be chosen from + * master->clone_output_list to replace the unplugged master. */ +static void +output_destroy_with_clone(struct weston_output *output) +{ + struct weston_compositor *compositor = output->compositor; + struct weston_output *new_master; + struct weston_output *clone, *next; + + new_master = find_new_master(output); + + delete_output_from_list(new_master); + + new_master->master_output = NULL; + new_master->is_clone = 0; + + weston_output_init(new_master, compositor, new_master->mm_width, + new_master->mm_height, new_master->transform, + new_master->original_scale); + + wl_list_for_each_safe(clone, next, &output->clone_output_list, link) + migrate_clone_output(clone, new_master); + +} + WL_EXPORT void weston_output_destroy(struct weston_output *output) { output->destroying = 1; + if (!wl_list_empty(&output->clone_output_list)) + output_destroy_with_clone(output); + delete_output_from_list(output); free(output->name); -- 1.8.3.2 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel