[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