[PATCH 2/2] rrxinerama: report tiled monitors in one rectangle

Dave Airlie airlied at gmail.com
Mon Nov 24 19:00:52 PST 2014


From: Fedora X Ninjas <x at fedoraproject.org>

This changes the xinerama reporting for tiled monitors
so that the large rectangle is reported as a single
xinerama rectangle.

Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 randr/rrxinerama.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 118 insertions(+), 4 deletions(-)

diff --git a/randr/rrxinerama.c b/randr/rrxinerama.c
index 26894a6..4a71678 100644
--- a/randr/rrxinerama.c
+++ b/randr/rrxinerama.c
@@ -153,18 +153,61 @@ RRXineramaCrtcActive(RRCrtcPtr crtc)
     return crtc->mode != NULL && crtc->numOutputs > 0;
 }
 
+static Atom GetTileAtom(void)
+{
+    return MakeAtom("TILE", sizeof("TILE") - 1, TRUE);
+}
+
+struct tile_info {
+    int id;
+    int flags;
+    int h_tiles;
+    int v_tiles;
+    int h_loc;
+    int v_loc;
+    int h_tile_size;
+    int v_tile_size;
+};
+
+static int SplitTile(RRPropertyValuePtr tile_val,
+                     struct tile_info *info)
+{
+    const char *tok = tile_val->data;
+
+    return sscanf(tok, "%d:%d:%d:%d:%d:%d:%d:%d",
+           &info->id, &info->flags,
+           &info->h_tiles, &info->v_tiles,
+           &info->h_loc, &info->v_loc,
+           &info->h_tile_size, &info->v_tile_size);
+}
+
 static int
 RRXineramaScreenCount(ScreenPtr pScreen)
 {
-    int i, n;
+    int i, n, o;
     ScreenPtr slave;
-
+    RRPropertyPtr tile;
+    struct tile_info info;
     n = 0;
     if (rrGetScrPriv(pScreen)) {
         rrScrPriv(pScreen);
         for (i = 0; i < pScrPriv->numCrtcs; i++)
             if (RRXineramaCrtcActive(pScrPriv->crtcs[i]))
                 n++;
+
+        /* remove tiles */
+        for (i = 0; i < pScrPriv->numCrtcs; i++) {
+            for (o = 0; o < pScrPriv->crtcs[i]->numOutputs; o++) {
+                RROutputPtr output = pScrPriv->crtcs[i]->outputs[o];
+                tile = RRQueryOutputProperty(output, GetTileAtom());
+                if (!tile)
+                    continue;
+
+                SplitTile(&tile->current, &info);
+                if (info.h_loc || info.v_loc)
+                    n--;
+            }
+        }
     }
 
     xorg_list_for_each_entry(slave, &pScreen->output_slave_list, output_head) {
@@ -312,13 +355,74 @@ RRXineramaWriteCrtc(ClientPtr client, RRCrtcPtr crtc)
     }
 }
 
+static void
+RRXineramaWriteTile(ClientPtr client, ScreenPtr pScreen, RRPropertyPtr orig)
+{
+    rrScrPriv(pScreen);
+    RRPropertyPtr tile;
+    xXineramaScreenInfo scratch;
+    int o;
+    int total_w = 0, total_h = 0;
+    int orig_id;
+    int width, height;
+    int x_org = 0, y_org = 0;
+    struct tile_info info;
+    int ret;
+
+    ret = SplitTile(&orig->current, &info);
+    if (ret < 0)
+        return;
+
+    if (info.h_loc > 0 || info.v_loc > 0)
+        return;
+
+    orig_id = info.id;
+    for (o = 0; o < pScrPriv->numOutputs; o++) {
+        RROutputPtr output = pScrPriv->outputs[o];
+
+        if (!output->crtc)
+            continue;
+        tile = RRQueryOutputProperty(output, GetTileAtom());
+
+        if (!tile)
+            continue;
+
+        ret = SplitTile(&tile->current, &info);
+        if (orig_id == info.id) {
+            RRCrtcGetScanoutSize(output->crtc, &width, &height);
+            if (info.h_loc == 0 && info.v_loc == 0) {
+                x_org = output->crtc->x;
+                y_org = output->crtc->y;
+            }
+            if (info.h_loc == 0)
+                total_h += height;
+            if (info.v_loc == 0)
+                total_w += width;
+        }
+    }
+
+    scratch.x_org = x_org;
+    scratch.y_org = y_org;
+    scratch.width = total_w;
+    scratch.height = total_h;
+
+    if (client->swapped) {
+        swaps(&scratch.x_org);
+        swaps(&scratch.y_org);
+        swaps(&scratch.width);
+        swaps(&scratch.height);
+    }
+    WriteToClient(client, sz_XineramaScreenInfo, &scratch);
+}
+
 int
 ProcRRXineramaQueryScreens(ClientPtr client)
 {
     xXineramaQueryScreensReply rep;
     ScreenPtr pScreen = screenInfo.screens[RR_XINERAMA_SCREEN];
     int n = 0;
-    int i;
+    int i, o;
+    RRPropertyPtr tile;
 
     REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
 
@@ -351,12 +455,22 @@ ProcRRXineramaQueryScreens(ClientPtr client)
         }
 
         for (i = 0; i < pScrPriv->numCrtcs; i++) {
+            Bool skip = FALSE;
             if (has_primary &&
                 pScrPriv->primaryOutput->crtc == pScrPriv->crtcs[i]) {
                 has_primary = 0;
                 continue;
             }
-            RRXineramaWriteCrtc(client, pScrPriv->crtcs[i]);
+            for (o = 0; o < pScrPriv->crtcs[i]->numOutputs; o++) {
+                RROutputPtr output = pScrPriv->crtcs[i]->outputs[o];
+                tile = RRQueryOutputProperty(output, GetTileAtom());
+                if (tile) {
+                    RRXineramaWriteTile(client, pScreen, tile);
+                    skip = TRUE;
+                }
+            }
+            if (!skip)
+                RRXineramaWriteCrtc(client, pScrPriv->crtcs[i]);
         }
 
         xorg_list_for_each_entry(slave, &pScreen->output_slave_list, output_head) {
-- 
2.1.0



More information about the xorg-devel mailing list