summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2014-10-13 15:54:21 +1000
committerDave Airlie <airlied@redhat.com>2014-10-13 15:54:21 +1000
commit39fa77564da0139bb82ebbd74d7021f49e40cdce (patch)
treeeac681c72e7f6863759de724861b6097b97add64
parent72ec20e48f085af729c5b0afdd78d259694a052a (diff)
initial WIP - add multi monitor
this get maximising to work at least properly
-rw-r--r--src/compositor/meta-window-actor.c2
-rw-r--r--src/core/monitor-private.h11
-rw-r--r--src/core/monitor-xrandr.c60
-rw-r--r--src/core/monitor.c95
-rw-r--r--src/core/window.c4
5 files changed, 163 insertions, 9 deletions
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index ed196472..23c32f73 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -969,7 +969,7 @@ queue_send_frame_messages_timeout (MetaWindowActor *self)
outputs = meta_monitor_manager_get_outputs (monitor_manager, &n_outputs);
for (i = 0; i < n_outputs; i++)
{
- if (outputs[i].output_id == window->monitor->output_id && outputs[i].crtc)
+ if (outputs[i].output_id == window->monitor->output_ids[0] && outputs[i].crtc)
{
refresh_rate = outputs[i].crtc->current_mode->refresh_rate;
break;
diff --git a/src/core/monitor-private.h b/src/core/monitor-private.h
index bbe73f5e..c9903ac6 100644
--- a/src/core/monitor-private.h
+++ b/src/core/monitor-private.h
@@ -119,6 +119,12 @@ struct _MetaOutput
/* get a new preferred mode on hotplug events, to handle dynamic guest resizing */
gboolean hotplug_mode_update;
+
+ gboolean is_tiled, is_single_monitor;
+ int tile_group_id;
+ int max_h_tiles, max_v_tiles;
+ int loc_h_tile, loc_v_tile;
+ int tile_w, tile_h;
};
struct _MetaCRTC
@@ -167,6 +173,8 @@ struct _MetaMonitorInfo
gboolean is_presentation; /* XXX: not yet used */
gboolean in_fullscreen;
+ gboolean is_tiled;
+
/* The primary or first output for this monitor, 0 if we can't figure out.
It can be matched to an output_id of a MetaOutput.
@@ -175,7 +183,8 @@ struct _MetaMonitorInfo
(it's an attempt to keep windows on the same monitor, and preferably on
the primary one).
*/
- glong output_id;
+ glong output_ids[4];
+ int tile_group_id;
};
/*
diff --git a/src/core/monitor-xrandr.c b/src/core/monitor-xrandr.c
index 05888b62..7cbbee54 100644
--- a/src/core/monitor-xrandr.c
+++ b/src/core/monitor-xrandr.c
@@ -311,6 +311,65 @@ read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
return NULL;
}
+static int
+output_get_tiled_info(MetaMonitorManagerXrandr *manager_xrandr,
+ MetaOutput *output)
+{
+ unsigned char *prop;
+ Atom tile_atom;
+ int actual_format;
+ unsigned long nitems, bytes_after;
+ Atom actual_type;
+ guint8 *result;
+ int res = 1;
+ tile_atom = XInternAtom(manager_xrandr->xdisplay, "TILE", FALSE);
+ XRRGetOutputProperty(manager_xrandr->xdisplay,
+ (XID)output->output_id,
+ tile_atom, 0, 100, False,
+ False, AnyPropertyType,
+ &actual_type, &actual_format,
+ &nitems, &bytes_after, &prop);
+
+ if (actual_type == XA_INTEGER && actual_format == 8) {
+ int ver;
+ int single_mon;
+ int ret;
+
+ /* v1 tile prop */
+ if (prop[0] != '0' || prop[1] != ':')
+ goto out;
+
+ ret = sscanf((char *)prop, "%d:%d:%d:%d:%d:%d:%d:%d:%d",
+ &ver,
+ &output->tile_group_id,
+ &single_mon,
+ &output->max_h_tiles, &output->max_v_tiles,
+ &output->loc_h_tile, &output->loc_v_tile,
+ &output->tile_w, &output->tile_h);
+ if (ret != 9)
+ goto out;
+
+ output->tile_w += 1;
+ output->tile_h += 1;
+ output->is_tiled = True;
+ output->is_single_monitor = single_mon == 1 ? True : False;
+
+#if 0
+ fprintf(stderr, "monitor info %d tile %dx%d at %dx%d of %dx%d\n",
+ output->tile_group_id,
+ output->tile_w + 1, output->tile_h + 1,
+ output->loc_h_tile, output->loc_v_tile,
+ output->max_h_tiles, output->max_v_tiles);
+#endif
+ res = 1;
+ } else {
+ res = 0;
+ }
+out:
+ XFree(prop);
+ return res;
+}
+
static gboolean
output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
XID output_id)
@@ -512,6 +571,7 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
meta_output->hotplug_mode_update =
output_get_hotplug_mode_update (manager_xrandr, meta_output->output_id);
+ output_get_tiled_info(manager_xrandr, meta_output);
meta_output->n_modes = output->nmode;
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
for (j = 0; j < meta_output->n_modes; j++)
diff --git a/src/core/monitor.c b/src/core/monitor.c
index a07571d4..93fd3a78 100644
--- a/src/core/monitor.c
+++ b/src/core/monitor.c
@@ -383,6 +383,78 @@ read_current_config (MetaMonitorManager *manager)
* that will be used by the core and API layer (MetaScreen
* and friends)
*/
+/*
+ * rules for constructing a tiled monitor
+ * 1. find a tile_group_id
+ * 2. iterate over all outputs for that tile group id
+ * 3. see if output has a crtc and if it is configured for the tile size
+ * 4. calculate the total tile size
+ * 5. set tile finished size
+ * 6. check for more tile_group_id
+*/
+static void
+construct_tile_monitor (MetaMonitorManager *manager,
+ GArray *monitor_infos,
+ int tile_group_id)
+{
+ MetaMonitorInfo info;
+ unsigned i;
+
+ for (i = 0; i < monitor_infos->len; i++) {
+ MetaMonitorInfo *pinfo = &g_array_index(monitor_infos, MetaMonitorInfo, i);
+
+ if (pinfo->tile_group_id == tile_group_id) {
+ return;
+ }
+ }
+
+ /* didn't find it */
+ info.number = monitor_infos->len;
+ info.tile_group_id = tile_group_id;
+ info.is_tiled = True;
+ info.is_presentation = False;
+ info.is_primary = False;
+ info.rect.x = INT_MAX;
+ info.rect.y = INT_MAX;
+ info.rect.width = 0;
+ info.rect.height = 0;
+ info.output_ids[0] = 0;
+
+ for (i = 0; i < manager->n_outputs; i++)
+ {
+ MetaOutput *output = &manager->outputs[i];
+
+ if (!output->is_tiled)
+ continue;
+
+ if (output->tile_group_id != tile_group_id)
+ continue;
+
+ if (!output->crtc)
+ continue;
+
+ if (output->crtc->rect.width != output->tile_w ||
+ output->crtc->rect.height != output->tile_h)
+ continue;
+
+ /* hack */
+ if (output->crtc->rect.x < info.rect.x)
+ info.rect.x = output->crtc->rect.x;
+ if (output->crtc->rect.y < info.rect.y)
+ info.rect.y = output->crtc->rect.y;
+
+ if (output->loc_h_tile == 0)
+ info.rect.height += output->tile_h;
+
+ if (output->loc_v_tile == 0)
+ info.rect.width += output->tile_w;
+ }
+
+ fprintf(stderr," adding monitors info %dx%d @ %dx%d\n",
+ info.rect.width, info.rect.height, info.rect.x, info.rect.y);
+ g_array_append_val (monitor_infos, info);
+}
+
static void
make_logical_config (MetaMonitorManager *manager)
{
@@ -392,6 +464,15 @@ make_logical_config (MetaMonitorManager *manager)
monitor_infos = g_array_sized_new (FALSE, TRUE, sizeof (MetaMonitorInfo),
manager->n_outputs);
+ /* for tiling we need to work out how many tiled outputs there are */
+ for (i = 0; i < manager->n_outputs; i++)
+ {
+ MetaOutput *output = &manager->outputs[i];
+
+ if (output->is_tiled) {
+ construct_tile_monitor(manager, monitor_infos, output->tile_group_id);
+ }
+ }
/* Walk the list of MetaCRTCs, and build a MetaMonitorInfo
for each of them, unless they reference a rectangle that
is already there.
@@ -407,8 +488,7 @@ make_logical_config (MetaMonitorManager *manager)
for (j = 0; j < monitor_infos->len; j++)
{
MetaMonitorInfo *info = &g_array_index (monitor_infos, MetaMonitorInfo, j);
- if (meta_rectangle_equal (&crtc->rect,
- &info->rect))
+ if (meta_rectangle_contains_rect (&info->rect, &crtc->rect))
{
crtc->logical_monitor = info;
break;
@@ -420,6 +500,7 @@ make_logical_config (MetaMonitorManager *manager)
MetaMonitorInfo info;
info.number = monitor_infos->len;
+ info.tile_group_id = 0;
info.rect = crtc->rect;
info.is_primary = FALSE;
/* This starts true because we want
@@ -429,7 +510,7 @@ make_logical_config (MetaMonitorManager *manager)
*/
info.is_presentation = TRUE;
info.in_fullscreen = -1;
- info.output_id = 0;
+ info.output_ids[0] = 0;
g_array_append_val (monitor_infos, info);
@@ -452,6 +533,9 @@ make_logical_config (MetaMonitorManager *manager)
if (output->crtc == NULL)
continue;
+ if (output->is_tiled)
+ continue;
+
/* We must have a logical monitor on every CRTC at this point */
g_assert (output->crtc->logical_monitor != NULL);
@@ -460,13 +544,14 @@ make_logical_config (MetaMonitorManager *manager)
info->is_primary = info->is_primary || output->is_primary;
info->is_presentation = info->is_presentation && output->is_presentation;
- if (output->is_primary || info->output_id == 0)
- info->output_id = output->output_id;
+ if (output->is_primary || info->output_ids[0] == 0)
+ info->output_ids[0] = output->output_id;
if (info->is_primary)
manager->primary_monitor_index = info->number;
}
+ fprintf(stderr, "monitor info len %d\n", monitor_infos->len);
manager->n_monitor_infos = monitor_infos->len;
manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE);
}
diff --git a/src/core/window.c b/src/core/window.c
index 7a02c013..0b6b3957 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -4745,8 +4745,8 @@ meta_window_update_for_monitors_changed (MetaWindow *window)
{
MetaMonitorInfo *info = &window->screen->monitor_infos[i];
- if (info->output_id != 0 &&
- info->output_id == old->output_id)
+ if (info->output_ids[0] != 0 &&
+ info->output_ids[0] == old->output_ids[0])
{
new = info;
break;