Not compile-tested, merely syntactically plausible, just wanted to get
this out for a second look.  This implements the primary output requests
in the DIX, and mangles the appropriate protocol requests to sort the
primary output to the front.

Patch #4 maps the primary output to the RANDR 1.0 "first" output, which
is sort of vaguely defined but seems like the right thing to do.  The
xf86 DDX also has a "compat" output which is even more vaguely defined;
I'm not yet sure what the correct thing to do with that is.  Input
appreciated.

Updated protocol specs and client-side library are in git on the
get-set-primary branches of the appropriate modules.

- ajax
From 0a40d1959735ee82cdee80ac937bb2c55385af32 Mon Sep 17 00:00:00 2001
From: Adam Jackson <[EMAIL PROTECTED]>
Date: Mon, 8 Dec 2008 16:26:49 -0500
Subject: [PATCH] randr: Add [GS]etOutputPrimary

---
 randr/randrstr.h    |    8 ++++
 randr/rrdispatch.c  |    2 +
 randr/rroutput.c    |  107 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 randr/rrsdispatch.c |   27 +++++++++++++
 4 files changed, 143 insertions(+), 1 deletions(-)

diff --git a/randr/randrstr.h b/randr/randrstr.h
index 0cc4ff7..b868144 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -2,6 +2,7 @@
  * Copyright © 2000 Compaq Computer Corporation
  * Copyright © 2002 Hewlett-Packard Company
  * Copyright © 2006 Intel Corporation
+ * Copyright © 2008 Red Hat, Inc.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -272,6 +273,7 @@ typedef struct _rrScrPriv {
 
     int			    numOutputs;
     RROutputPtr		    *outputs;
+    RROutputPtr		    primaryOutput;
 
     int			    numCrtcs;
     RRCrtcPtr		    *crtcs;
@@ -811,6 +813,12 @@ RROutputDestroy (RROutputPtr	output);
 extern _X_EXPORT int
 ProcRRGetOutputInfo (ClientPtr client);
 
+extern int
+ProcRRSetOutputPrimary (ClientPtr client);
+
+extern int
+ProcRRGetOutputPrimary (ClientPtr client);
+
 /*
  * Initialize output type
  */
diff --git a/randr/rrdispatch.c b/randr/rrdispatch.c
index 0cc0bca..5a2ea71 100644
--- a/randr/rrdispatch.c
+++ b/randr/rrdispatch.c
@@ -217,5 +217,7 @@ int (*ProcRandrVector[RRNumberRequests])(ClientPtr) = {
     ProcRRGetCrtcTransform,	/* 27 */
     ProcRRGetPanning,		/* 28 */
     ProcRRSetPanning,		/* 29 */
+    ProcRRSetOutputPrimary,	/* 30 */
+    ProcRRGetOutputPrimary,	/* 31 */
 };
 
diff --git a/randr/rroutput.c b/randr/rroutput.c
index 1ecde31..5eedba3 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2006 Keith Packard
+ * Copyright © 2008 Red Hat, Inc.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -426,7 +427,7 @@ RROutputInit (void)
 }
 
 #define OutputInfoExtra	(SIZEOF(xRRGetOutputInfoReply) - 32)
-				
+
 int
 ProcRRGetOutputInfo (ClientPtr client)
 {
@@ -533,3 +534,107 @@ ProcRRGetOutputInfo (ClientPtr client)
     
     return client->noClientException;
 }
+
+void
+RRSetPrimaryOutput(ScreenPtr pScreen, rrScrPrivPtr pScrPriv,
+		   RROutputPtr output)
+{
+    if (pScrPriv->primaryOutput == output)
+	return;
+
+    /* clear the old primary */
+    if (pScrPriv->primaryOutput) {
+	RROutputChanged(pScrPriv->primaryOutput, 0);
+	pScrPriv->primaryOutput = NULL;
+    }
+
+    /* set the new primary */
+    if (output) {
+	pScrPriv->primaryOutput = output;
+	RROutputChanged(output, 0);
+    }
+
+    rrScrPriv->layoutChanged = TRUE;
+
+    RRTellChanged(pScreen);
+}
+
+int
+ProcRRSetOutputPrimary(ClientPtr client)
+{
+    REQUEST(xRRSetOutputPrimary);
+    RROutputPtr output = NULL;
+    WindowPtr pWin;
+
+    REQUEST_SIZE_MATCH(xRRSetOutputPrimary);
+
+    pWin = SecurityLookupIDByType(client, stuff->window, RT_WINDOW,
+				  DixReadAccess);
+
+    if (!pWin) {
+	client->errorValue = stuff->window;
+	return BadWindow;
+    }
+
+    if (stuff->output) {
+	output = LookupOutput(client, stuff->output, DixReadAccess);
+
+	if (!output) {
+	    client->errorValue = stuff->output;
+	    return RRErrorBase + BadRROutput;
+	}
+
+	if (output->crtc) {
+	    client->errorValue = stuff->output;
+	    return BadMatch;
+	}
+
+	if (output->pScreen != pWin->drawable.pScreen) {
+	    client->errorValue = stuff->window;
+	    return BadMatch;
+	}
+    }
+
+    RRSetPrimaryOutput(pWin->drawable.pScreen, pScrPriv, output);
+
+    return client->noClientException;
+}
+
+int
+ProcRRGetOutputPrimary(ClientPtr client)
+{
+    REQUEST(xRRGetOutputPrimaryReq);
+    WindowPtr pWin;
+    rrScrPrivPtr pScrPriv;
+    xRRGetOutputPrimary rep;
+    RROutputPtr primary = NULL;
+
+    REQUEST_SIZE_MATCH(xRRGetOutputPrimary);
+
+    pWin = SecurityLookupIDByType(client, stuff->window, RT_WINDOW,
+				  DixReadAccess);
+
+    if (!pWin) {
+	client->errorValue = stuff->window;
+	return BadWindow;
+    }
+
+    pScrPriv = rrGetScrPriv(pWin->drawable.pScreen);
+    if (pScrPriv)
+	primary = pScrPriv->primaryOutput;
+
+    memset(&rep, 0, sizeof(rep));
+    rep.type = X_Reply;
+    rep.sequenceNumber = client->sequence;
+    rep.output = primary ? primary->id : None;
+
+    if (client->swapped) {
+	int n;
+	swaps(&rep.sequenceNumber, n);
+	swapl(&rep.output, n);
+    }
+
+    WriteToClient(client, sizeof(xRRGetOutputPrimary), &rep);
+
+    return client->noClientException;
+}
diff --git a/randr/rrsdispatch.c b/randr/rrsdispatch.c
index 3ff9f3f..9fbf8f0 100644
--- a/randr/rrsdispatch.c
+++ b/randr/rrsdispatch.c
@@ -436,6 +436,31 @@ SProcRRSetPanning (ClientPtr client)
     return (*ProcRandrVector[stuff->randrReqType]) (client);
 }
 
+static int
+SProcRRSetOutputPrimary (ClientPtr client)
+{
+    int n;
+    REQUEST(xRRSetOutputPrimaryReq);
+
+    REQUEST_SIZE_MATCH(xRRSetOutputPrimaryReq);
+    swaps(&stuff->length, n);
+    swapl(&stuff->window, n);
+    swapl(&stuff->output, n);
+    return ProcRandrVector[stuff->randrReqType](client);
+}
+
+static int
+SProcRRGetOutputPrimary (ClientPtr client)
+{
+    int n;
+    REQUEST(xRRSetOutputPrimaryReq);
+
+    REQUEST_SIZE_MATCH(xRRGetOutputPrimaryReq);
+    swaps(&stuff->length, n);
+    swapl(&stuff->window, n);
+    return ProcRandrVector[stuff->randrReqType](client);
+}
+
 int (*SProcRandrVector[RRNumberRequests])(ClientPtr) = {
     SProcRRQueryVersion,	/* 0 */
 /* we skip 1 to make old clients fail pretty immediately */
@@ -472,5 +497,7 @@ int (*SProcRandrVector[RRNumberRequests])(ClientPtr) = {
     SProcRRGetCrtcTransform,	/* 27 */
     SProcRRGetPanning,		/* 28 */
     SProcRRSetPanning,		/* 29 */
+    SProcRRSetOutputPrimary,	/* 30 */
+    SProcRRGetOutputPrimary,	/* 31 */
 };
 
-- 
1.6.0.3

From cc2e104dcbc31362fd1f289f115dcaee1ed1a296 Mon Sep 17 00:00:00 2001
From: Adam Jackson <[EMAIL PROTECTED]>
Date: Mon, 8 Dec 2008 17:28:55 -0500
Subject: [PATCH] randr: Mangle compat Xinerama reply based on primary output

---
 randr/rrxinerama.c |   48 +++++++++++++++++++++++++++++++-----------------
 1 files changed, 31 insertions(+), 17 deletions(-)

diff --git a/randr/rrxinerama.c b/randr/rrxinerama.c
index 544666f..ad40a1e 100644
--- a/randr/rrxinerama.c
+++ b/randr/rrxinerama.c
@@ -260,6 +260,30 @@ ProcRRXineramaIsActive(ClientPtr client)
     return client->noClientException;
 }
 
+static void
+RRXineramaWriteCrtc(ClientPtr client, RRCrtcPtr crtc)
+{
+    xXineramaScreenInfo scratch;
+
+    if (RRXineramaCrtcActive (crtc))
+    {
+	int width, height;
+	RRCrtcGetScanoutSize (crtc, &width, &height);
+	scratch.x_org  = crtc->x;
+	scratch.y_org  = crtc->y;
+	scratch.width  = width;
+	scratch.height = height;
+	if(client->swapped) {
+	    register int n;
+	    swaps(&scratch.x_org, n);
+	    swaps(&scratch.y_org, n);
+	    swaps(&scratch.width, n);
+	    swaps(&scratch.height, n);
+	}
+	WriteToClient(client, sz_XineramaScreenInfo, &scratch);
+    }
+}
+
 int
 ProcRRXineramaQueryScreens(ClientPtr client)
 {
@@ -291,26 +315,16 @@ ProcRRXineramaQueryScreens(ClientPtr client)
 	rrScrPriv(pScreen);
 	xXineramaScreenInfo scratch;
 	int i;
+	int has_primary = (pScrPriv->primaryOutput != NULL);
+
+	if (has_primary) {
+	    RRXineramaWriteCrtc(client, pScrPriv->primaryOutput->crtc);
+	}
 
 	for(i = 0; i < pScrPriv->numCrtcs; i++) {
 	    RRCrtcPtr	crtc = pScrPriv->crtcs[i];
-	    if (RRXineramaCrtcActive (crtc))
-	    {
-	        int width, height;
-		RRCrtcGetScanoutSize (crtc, &width, &height);
-		scratch.x_org  = crtc->x;
-		scratch.y_org  = crtc->y;
-		scratch.width  = width;
-		scratch.height = height;
-		if(client->swapped) {
-		    register int n;
-		    swaps(&scratch.x_org, n);
-		    swaps(&scratch.y_org, n);
-		    swaps(&scratch.width, n);
-		    swaps(&scratch.height, n);
-		}
-		WriteToClient(client, sz_XineramaScreenInfo, (char *)&scratch);
-	    }
+	    if (!has_primary || (crtc != pScrPriv->primaryOutput->crtc))
+		RRXineramaWriteCrtc(client, crtc);
 	}
     }
 
-- 
1.6.0.3

From 3a7d40a453274a10ab1c8d463ad654158e42ffbe Mon Sep 17 00:00:00 2001
From: Adam Jackson <[EMAIL PROTECTED]>
Date: Mon, 8 Dec 2008 17:37:17 -0500
Subject: [PATCH] randr: Mangle GetScreenResources sort order based on primary output

---
 randr/rrscreen.c |   17 ++++++++++++++---
 1 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/randr/rrscreen.c b/randr/rrscreen.c
index c8fea99..85a30a4 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -324,7 +324,7 @@ rrGetScreenResources(ClientPtr client, Bool query)
     rrScrPrivPtr		pScrPriv;
     CARD8			*extra;
     unsigned long		extraLen;
-    int				i, n, rc;
+    int				i, n, rc, has_primary;
     RRCrtc			*crtcs;
     RROutput			*outputs;
     xRRModeInfo			*modeinfos;
@@ -401,12 +401,23 @@ rrGetScreenResources(ClientPtr client, Bool query)
 	outputs = (RROutput *) (crtcs + pScrPriv->numCrtcs);
 	modeinfos = (xRRModeInfo *) (outputs + pScrPriv->numOutputs);
 	names = (CARD8 *) (modeinfos + num_modes);
+
+	has_primary = (pScrPriv->primaryOutput != NULL);
+	if (pScrPriv->primaryOutput)
+	{
+	    crtcs[0] = pScrPriv->primaryOutput->id;
+	    if (client->swapped)
+		swapl (&crtcs[0], n);
+	}
 	
 	for (i = 0; i < pScrPriv->numCrtcs; i++)
 	{
-	    crtcs[i] = pScrPriv->crtcs[i]->id;
+	    if (pScrPriv->primaryOutput &&
+		pScrPriv->primaryOutput->crtc == pScrPriv->crtcs[i])
+		continue;
+	    crtcs[i + has_primary] = pScrPriv->crtcs[i]->id;
 	    if (client->swapped)
-		swapl (&crtcs[i], n);
+		swapl (&crtcs[i + has_primary], n);
 	}
 	
 	for (i = 0; i < pScrPriv->numOutputs; i++)
-- 
1.6.0.3

From 2c41f0329d28dda19261c4eba9057863de3c46c8 Mon Sep 17 00:00:00 2001
From: Adam Jackson <[EMAIL PROTECTED]>
Date: Mon, 8 Dec 2008 17:40:07 -0500
Subject: [PATCH] randr: use primary output for RRFirstOutput()

---
 randr/randr.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/randr/randr.c b/randr/randr.c
index 230d816..2e482f0 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -438,6 +438,9 @@ RRFirstOutput (ScreenPtr pScreen)
     RROutputPtr		    output;
     int	i, j;
     
+    if (pScrPriv->primaryOutput)
+	return pScrPriv->primaryOutput;
+
     for (i = 0; i < pScrPriv->numCrtcs; i++)
     {
 	RRCrtcPtr   crtc = pScrPriv->crtcs[i];
-- 
1.6.0.3

From 318223e7b43a1f034952e507553a09af26f4e268 Mon Sep 17 00:00:00 2001
From: Adam Jackson <[EMAIL PROTECTED]>
Date: Mon, 8 Dec 2008 17:42:47 -0500
Subject: [PATCH] randr: clear primaryOutput when the output is deleted

---
 randr/rroutput.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/randr/rroutput.c b/randr/rroutput.c
index 5eedba3..06761b9 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -380,6 +380,9 @@ RROutputDestroyResource (pointer value, XID pid)
     {
 	rrScrPriv(pScreen);
 	int		i;
+
+	if (pScrPriv->primaryOutput == output)
+	    pScrPriv->primaryOutput = NULL;
     
 	for (i = 0; i < pScrPriv->numOutputs; i++)
 	{
-- 
1.6.0.3

Attachment: signature.asc
Description: This is a digitally signed message part

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

Reply via email to