[PATCH 12/12] compositor: Output unplug in clone mode

Xiong Zhang xiong.y.zhang at intel.com
Fri Mar 7 00:27:30 PST 2014


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.zhang at 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



More information about the wayland-devel mailing list