diff options
author | Dave Airlie <airlied@redhat.com> | 2014-10-13 15:54:21 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2014-10-13 15:54:21 +1000 |
commit | 39fa77564da0139bb82ebbd74d7021f49e40cdce (patch) | |
tree | eac681c72e7f6863759de724861b6097b97add64 /src | |
parent | 72ec20e48f085af729c5b0afdd78d259694a052a (diff) |
initial WIP - add multi monitor
this get maximising to work at least properly
Diffstat (limited to 'src')
-rw-r--r-- | src/compositor/meta-window-actor.c | 2 | ||||
-rw-r--r-- | src/core/monitor-private.h | 11 | ||||
-rw-r--r-- | src/core/monitor-xrandr.c | 60 | ||||
-rw-r--r-- | src/core/monitor.c | 95 | ||||
-rw-r--r-- | src/core/window.c | 4 |
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; |