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

Reply via email to