Hi,

Can someone pls have a look at this patch?

I implemented configuration options for relativ output positioning in
weston.ini. Currently the implementation is private to the drm compositor,
but i think this can be generalized for all output drivers.
ATM it can only be configured in weston.ini, a dynamic way like xrandr
would be nice (now idea how to).
Next i want to introduce a concept of primary output, to center the
mouse on the right monitor on start, draw the launcher only there and
other stuff.

I'm new to wayland/weston, so i'm not sure if this is even the right
approach ...

only tested with 2 monitors, sadly i don't have more :)

>From 4ee86a0b78a1c0d217cf5c973af0f3d50bd15c68 Mon Sep 17 00:00:00 2001
From: Florian Scandella <[email protected]>
Date: Thu, 13 Jun 2013 21:23:51 +0200
Subject: [PATCH] [drm] Add support for output layout configuration

Output configuration is specified by the "output" entries:

above=<NAME>
below=<NAME>
left-of=<NAME>
right-of=<NAME>

where name references another output configuration.
---
 src/compositor-drm.c | 189 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 189 insertions(+)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 76d0810..0823f54 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -187,6 +187,16 @@ struct drm_sprite {
 	uint32_t formats[];
 };
 
+struct drm_output_layout {
+	struct drm_output *output;
+	int visited;
+	int vx, vy;
+	struct drm_output_layout *left;
+	struct drm_output_layout *right;
+	struct drm_output_layout *top;
+	struct drm_output_layout *bottom;
+};
+
 static const char default_seat[] = "seat0";
 
 static void
@@ -2031,6 +2041,182 @@ destroy_sprites(struct drm_compositor *compositor)
 }
 
 static int
+drm_output_layout_init (struct drm_compositor *ec, struct drm_output_layout **map, int *n)
+{
+	struct drm_output *output;
+	int i = 0;
+
+	*n = wl_list_length(&ec->base.output_list);
+	*map = malloc((*n) * sizeof **map);
+
+	if (*map == NULL)
+		return -1;
+
+	memset(*map, 0, (*n) * sizeof **map);
+
+	wl_list_for_each(output, &ec->base.output_list, base.link) {
+		(*map)[i].output = output;
+		++i;
+	}
+
+	return 0;
+}
+
+static int
+drm_output_layout_find_index_by_name (struct drm_output_layout const *map, int n, char const *name)
+{
+	int j;
+	for (j=0; j < n; ++j) {
+		if (strcmp(name, map[j].output->base.name) == 0) {
+			return j;
+		}
+	}
+	return -1;
+}
+
+static void
+drm_output_layout_calculate_positions (struct drm_output_layout *current, int *minx, int *miny)
+{
+	current->visited = 1;
+
+	if (current->vx < *minx)
+		*minx = current->vx;
+	if (current->vy < *miny)
+		*miny = current->vy;
+
+	if (current->left && !current->left->visited) {
+		current->left->vx = current->vx - current->left->output->base.width;
+		current->left->vy = current->vy;
+		drm_output_layout_calculate_positions(current->left, minx, miny);
+	}
+	if (current->right && !current->right->visited) {
+		current->right->vx = current->vx + current->output->base.width;
+		current->right->vy = current->vy;
+		drm_output_layout_calculate_positions(current->right, minx, miny);
+	}
+	if (current->bottom && !current->bottom->visited) {
+		current->bottom->vx = current->vx;
+		current->bottom->vy = current->vy + current->output->base.height;
+		drm_output_layout_calculate_positions(current->bottom, minx, miny);
+	}
+	if (current->top && !current->top->visited) {
+		current->top->vx = current->vx;
+		current->top->vy = current->vy - current->top->output->base.height;
+		drm_output_layout_calculate_positions(current->top, minx, miny);
+	}
+}
+
+
+static void
+drm_output_layout_put_left_of (struct drm_output_layout *map, int left_idx, int right_idx)
+{
+	map[left_idx].right = &map[right_idx];
+	map[right_idx].left = &map[left_idx];
+}
+
+
+static void
+drm_output_layout_put_above (struct drm_output_layout *map, int bottom_idx, int top_idx)
+{
+	map[bottom_idx].top = &map[top_idx];
+	map[top_idx].bottom = &map[bottom_idx];
+}
+
+/* merge defined und undefined output configurations */
+static void
+drm_output_layout_prepare (struct drm_output_layout *map, int n)
+{
+	struct drm_output_layout *last_undefined = NULL;
+	struct drm_output_layout *last_defined = NULL;
+
+	int i;
+	for (i = 0; i<n; ++i) {
+		if (map[i].left || map[i].right || map[i].bottom || map[i].top ) {
+			last_defined = &map[i];
+		} else {
+			if (last_undefined) {
+				last_undefined->right = &map[i];
+				map[i].left = last_undefined;
+			}
+			last_undefined = &map[i];
+		}
+	}
+
+	if (last_undefined && last_defined) {
+
+		while(last_undefined->left)
+			last_undefined = last_undefined->left;
+
+		while (last_defined->right)
+			last_defined = last_defined->right;
+
+		last_defined->right = last_undefined;
+		last_undefined->left = last_defined;
+	}
+}
+
+
+static int
+arrange_outputs(struct drm_compositor *ec)
+{
+	struct drm_output_layout *map;
+	int n_outputs, idx, minx = 0, miny = 0;
+
+	if (drm_output_layout_init(ec, &map, &n_outputs))
+		return -1;
+
+
+	for(idx=0; idx < n_outputs; ++idx) {
+		struct weston_config_section *current_section = weston_config_get_section(ec->base.config, "output", "name", map[idx].output->base.name);
+		char *option;
+
+		if (current_section == NULL)
+			continue;
+
+		weston_config_section_get_string(current_section, "left-of", &option, NULL);
+		if (option != NULL) {
+			int other_idx = drm_output_layout_find_index_by_name(map, n_outputs, option);
+			if (other_idx >= 0 && other_idx != idx) {
+				drm_output_layout_put_left_of(map, idx, other_idx);
+			}
+		}
+		weston_config_section_get_string(current_section, "right-of", &option, NULL);
+		if (option != NULL) {
+			int other_idx = drm_output_layout_find_index_by_name(map, n_outputs, option);
+			if (other_idx >= 0 && other_idx != idx) {
+				drm_output_layout_put_left_of(map, other_idx, idx);
+			}
+		}
+		weston_config_section_get_string(current_section, "above", &option, NULL);
+		if (option != NULL) {
+			int other_idx = drm_output_layout_find_index_by_name(map, n_outputs, option);
+			if (other_idx >= 0 && other_idx != idx) {
+				drm_output_layout_put_above(map, other_idx, idx);
+			}
+		}
+		weston_config_section_get_string(current_section, "below", &option, NULL);
+		if (option != NULL) {
+			int other_idx = drm_output_layout_find_index_by_name(map, n_outputs, option);
+			if (other_idx >= 0 && other_idx != idx) {
+				drm_output_layout_put_above(map, idx, other_idx);
+			}
+		}
+	}
+
+	drm_output_layout_prepare(map, n_outputs);
+	drm_output_layout_calculate_positions(map, &minx, &miny);
+
+	for(idx=0; idx < n_outputs; ++idx) {
+		weston_output_move(&map[idx].output->base, map[idx].vx - minx, map[idx].vy - miny);
+	}
+
+	free(map);
+
+	return 0;
+}
+
+
+static int
 create_outputs(struct drm_compositor *ec, uint32_t option_connector,
 	       struct udev_device *drm_device)
 {
@@ -2088,6 +2274,7 @@ create_outputs(struct drm_compositor *ec, uint32_t option_connector,
 		drmModeFreeResources(resources);
 		return -1;
 	}
+	arrange_outputs(ec);
 
 	drmModeFreeResources(resources);
 
@@ -2170,6 +2357,8 @@ update_outputs(struct drm_compositor *ec, struct udev_device *drm_device)
 	/* FIXME: handle zero outputs, without terminating */	
 	if (ec->connector_allocator == 0)
 		wl_display_terminate(ec->base.wl_display);
+
+	arrange_outputs(ec);
 }
 
 static int
-- 
1.8.3.1

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to