xserver: Branch 'master' - 4 commits

Eamon Walsh ewalsh at kemper.freedesktop.org
Fri Feb 29 15:03:39 PST 2008


 Xext/security.c                 |    2 
 Xext/xace.c                     |    9 -
 Xext/xace.h                     |    7 
 Xext/xacestr.h                  |    4 
 Xext/xselinux.c                 |   31 +---
 dix/Makefile.am                 |    1 
 dix/dispatch.c                  |  274 -----------------------------------
 dix/main.c                      |    2 
 dix/property.c                  |  225 +++++++++++++----------------
 dix/selection.c                 |  310 ++++++++++++++++++++++++++++++++++++++++
 hw/xfree86/common/xf86Init.c    |   11 -
 hw/xfree86/loader/dixsym.c      |    9 -
 hw/xprint/pcl/PclMisc.c         |   17 --
 hw/xprint/pcl/PclWindow.c       |    6 
 hw/xprint/ps/PsMisc.c           |   17 --
 hw/xprint/ps/PsWindow.c         |    6 
 hw/xquartz/applewm.c            |   14 -
 hw/xquartz/quartzPasteboard.c   |   48 ++----
 hw/xquartz/xpr/xprFrame.c       |    4 
 hw/xwin/winwin32rootless.c      |    4 
 include/dix.h                   |   23 --
 include/property.h              |    7 
 include/selection.h             |   47 +++++-
 miext/rootless/rootlessWindow.c |    4 
 xkb/xkbInit.c                   |    4 
 25 files changed, 554 insertions(+), 532 deletions(-)

New commits:
commit ef60632e200853680282016e32a7a9fb01882852
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date:   Fri Feb 29 18:00:27 2008 -0500

    dix: Modify callers of property and selection API to use new interfaces.

diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
index d1603c0..6d5eaad 100644
--- a/hw/xfree86/common/xf86Init.c
+++ b/hw/xfree86/common/xf86Init.c
@@ -172,12 +172,11 @@ xf86CreateRootWindow(WindowPtr pWin)
 	  Atom prop;
 
 	  prop = MakeAtom(pProp->name, strlen(pProp->name), TRUE);
-	  err = ChangeWindowProperty(pWin,
-				     prop, pProp->type,
-				     pProp->format, PropModeReplace,
-				     pProp->size, pProp->data,
-				     FALSE
-				     );
+	  err = dixChangeWindowProperty(serverClient, pWin,
+					prop, pProp->type,
+					pProp->format, PropModeReplace,
+					pProp->size, pProp->data,
+					FALSE);
 	}
       
       /* Look at err */
diff --git a/hw/xprint/pcl/PclMisc.c b/hw/xprint/pcl/PclMisc.c
index e0b7dce..0b37836 100644
--- a/hw/xprint/pcl/PclMisc.c
+++ b/hw/xprint/pcl/PclMisc.c
@@ -115,7 +115,7 @@ GetPropString(
     if(atom != BAD_RESOURCE)
     {
         WindowPtr pPropWin;
-	int n;
+	int rc, n;
 
 	/*
 	 * The atom has been defined, but it might only exist as a
@@ -124,15 +124,12 @@ GetPropString(
         for(pPropWin = pWin; pPropWin != (WindowPtr)NULL; 
 	    pPropWin = pPropWin->parent)
         {
-	    for(pProp = (PropertyPtr)(wUserProps(pPropWin)); 
-		pProp != (PropertyPtr)NULL;
-	        pProp = pProp->next)
-	    {
-                if (pProp->propertyName == atom)
-                    break;
-	    }
-	    if(pProp != (PropertyPtr)NULL)
-	        break;
+	    rc = dixLookupProperty(&pProp, pPropWin, atom,
+				   serverClient, DixReadAccess);
+	    if (rc == Success)
+		break;
+	    else
+		pProp = NULL;
         }
 	if(pProp == (PropertyPtr)NULL)
 	    return (char *)NULL;
diff --git a/hw/xprint/pcl/PclWindow.c b/hw/xprint/pcl/PclWindow.c
index a87dc0e..950933e 100644
--- a/hw/xprint/pcl/PclWindow.c
+++ b/hw/xprint/pcl/PclWindow.c
@@ -128,9 +128,9 @@ PclCreateWindow(
 	    {
                 propName = MakeAtom(propStrings[i], strlen(propStrings[i]),
 				    TRUE);
-	        ChangeWindowProperty(pWin, propName, XA_STRING, 8, 
-			             PropModeReplace,  strlen(propVal), 
-			             (pointer)propVal, FALSE);
+	        dixChangeWindowProperty(serverClient, pWin, propName, XA_STRING,
+					8, PropModeReplace, strlen(propVal),
+					(pointer)propVal, FALSE);
 	        xfree(propVal);
 	    }
 	}
diff --git a/hw/xprint/ps/PsMisc.c b/hw/xprint/ps/PsMisc.c
index 0df039e..8d5005f 100644
--- a/hw/xprint/ps/PsMisc.c
+++ b/hw/xprint/ps/PsMisc.c
@@ -175,7 +175,7 @@ GetPropString(
     if(atom != BAD_RESOURCE)
     {
         WindowPtr pPropWin;
-	int n;
+	int rc, n;
 */
 
 	/*
@@ -186,15 +186,12 @@ GetPropString(
         for(pPropWin = pWin; pPropWin != (WindowPtr)NULL; 
 	    pPropWin = pPropWin->parent)
         {
-	    for(pProp = (PropertyPtr)(wUserProps(pPropWin)); 
-		pProp != (PropertyPtr)NULL;
-	        pProp = pProp->next)
-	    {
-                if (pProp->propertyName == atom)
-                    break;
-	    }
-	    if(pProp != (PropertyPtr)NULL)
-	        break;
+	    rc = dixLookupProperty(&pProp, pPropWin, atom,
+				   serverClient, DixReadAccess);
+	    if (rc == Success)
+		break;
+	    else
+		pProp = NULL;
         }
 	if(pProp == (PropertyPtr)NULL)
 	    return (char *)NULL;
diff --git a/hw/xprint/ps/PsWindow.c b/hw/xprint/ps/PsWindow.c
index d17cf8c..8bfde4b 100644
--- a/hw/xprint/ps/PsWindow.c
+++ b/hw/xprint/ps/PsWindow.c
@@ -154,9 +154,9 @@ PsCreateWindow(WindowPtr pWin)
 	    {
                 propName = MakeAtom(propStrings[i], strlen(propStrings[i]),
 				    TRUE);
-	        ChangeWindowProperty(pWin, propName, XA_STRING, 8, 
-			             PropModeReplace,  strlen(propVal), 
-			             (pointer)propVal, FALSE);
+	        dixChangeWindowProperty(serverClient, pWin, propName, XA_STRING,
+					8, PropModeReplace, strlen(propVal),
+					(pointer)propVal, FALSE);
 	        xfree(propVal);
 	    }
 	}
diff --git a/hw/xquartz/applewm.c b/hw/xquartz/applewm.c
index c460ec6..072e57f 100644
--- a/hw/xquartz/applewm.c
+++ b/hw/xquartz/applewm.c
@@ -154,8 +154,8 @@ AppleWMSetScreenOrigin(
     data[1] = (dixScreenOrigins[pWin->drawable.pScreen->myNum].y
                 + darwinMainScreenY);
 
-    ChangeWindowProperty(pWin, xa_native_screen_origin(), XA_INTEGER,
-                         32, PropModeReplace, 2, data, TRUE);
+    dixChangeWindowProperty(serverClient, pWin, xa_native_screen_origin(),
+			    XA_INTEGER, 32, PropModeReplace, 2, data, TRUE);
 }
 
 /* Window managers can set the _APPLE_NO_ORDER_IN property on windows
@@ -169,15 +169,11 @@ AppleWMDoReorderWindow(
 {
     Atom atom;
     PropertyPtr prop;
+    int rc;
 
     atom = xa_apple_no_order_in();
-    for (prop = wUserProps(pWin); prop != NULL; prop = prop->next)
-    {
-        if (prop->propertyName == atom && prop->type == atom)
-            return FALSE;
-    }
-
-    return TRUE;
+    rc = dixLookupProperty(&prop, pWin, atom, serverClient, DixReadAccess);
+    return (rc == Success) && (prop->type == atom);
 }
 
 
diff --git a/hw/xquartz/quartzPasteboard.c b/hw/xquartz/quartzPasteboard.c
index 0cecff5..0bf84f5 100644
--- a/hw/xquartz/quartzPasteboard.c
+++ b/hw/xquartz/quartzPasteboard.c
@@ -43,9 +43,6 @@
 #include "selection.h"
 #include "globals.h"
 
-extern Selection *CurrentSelections;
-extern int NumCurrentSelections;
-
 
 // Helper function to read the X11 cut buffer
 // FIXME: What about multiple screens? Currently, this reads the first
@@ -54,18 +51,16 @@ extern int NumCurrentSelections;
 // Returns NULL if there is no cut text or there is not enough memory.
 static char * QuartzReadCutBuffer(void)
 {
-    int i;
+    int rc, i;
     char *text = NULL;
 
     for (i = 0; i < screenInfo.numScreens; i++) {
         ScreenPtr pScreen = screenInfo.screens[i];
         PropertyPtr pProp;
 
-        pProp = wUserProps (WindowTable[pScreen->myNum]);
-        while (pProp && pProp->propertyName != XA_CUT_BUFFER0) {
-	    pProp = pProp->next;
-        }
-        if (! pProp) continue;
+	rc = dixLookupProperty(&pProp, WindowTable[pScreen->myNum],
+			       XA_CUT_BUFFER0, serverClient, DixReadAccess);
+        if (rc != Success) continue;
         if (pProp->type != XA_STRING) continue;
         if (pProp->format != 8) continue;
 
@@ -108,43 +103,40 @@ void QuartzReadPasteboard(void)
 
     if ((text && oldText && !strequal(text, oldText)) ||
         (text && !oldText)) {
-        int scrn, sel;
+        int scrn, rc;
+	Selection *pSel;
 
         for (scrn = 0; scrn < screenInfo.numScreens; scrn++) {
 	    ScreenPtr pScreen = screenInfo.screens[scrn];
 	    // Set the cut buffers on each screen
 	    // fixme really on each screen?
-	    ChangeWindowProperty(WindowTable[pScreen->myNum], XA_CUT_BUFFER0,
-				 XA_STRING, 8, PropModeReplace,
-				 strlen(text), (pointer)text, TRUE);
+	    dixChangeWindowProperty(serverClient, WindowTable[pScreen->myNum],
+				    XA_CUT_BUFFER0, XA_STRING, 8, PropModeReplace,
+				    strlen(text), (pointer)text, TRUE);
         }
 
         // Undo any current X selection (similar to code in dispatch.c)
         // FIXME: what about secondary selection?
         // FIXME: only touch first XA_PRIMARY selection?
-        sel = 0;
-        while ((sel < NumCurrentSelections)  &&
-	       CurrentSelections[sel].selection != XA_PRIMARY)
-	    sel++;
-        if (sel < NumCurrentSelections) {
+	rc = dixLookupSelection(&pSel, XA_PRIMARY, serverClient,
+				DixSetAttrAccess);
+        if (rc == Success) {
 	    // Notify client if necessary
-	    if (CurrentSelections[sel].client) {
+	    if (pSel->client) {
 	        xEvent event;
 
 	        event.u.u.type = SelectionClear;
 		event.u.selectionClear.time = GetTimeInMillis();
-		event.u.selectionClear.window = CurrentSelections[sel].window;
-		event.u.selectionClear.atom = CurrentSelections[sel].selection;
-		TryClientEvents(CurrentSelections[sel].client, &event, 1,
-				NoEventMask, NoEventMask /*CantBeFiltered*/,
-				NullGrab);
+		event.u.selectionClear.window = pSel->window;
+		event.u.selectionClear.atom = pSel->selection;
+		TryClientEvents(pSel->client, &event, 1, NoEventMask,
+				NoEventMask /*CantBeFiltered*/, NullGrab);
 	    }
 
 	    // Erase it
-	    // FIXME: need to erase .selection too? dispatch.c doesn't
-	    CurrentSelections[sel].pWin = NullWindow;
-	    CurrentSelections[sel].window = None;
-	    CurrentSelections[sel].client = NullClient;
+	    pSel->pWin = NullWindow;
+	    pSel->window = None;
+	    pSel->client = NullClient;
         }
     }
 
diff --git a/hw/xquartz/xpr/xprFrame.c b/hw/xquartz/xpr/xprFrame.c
index b9a33de..864ef0d 100644
--- a/hw/xquartz/xpr/xprFrame.c
+++ b/hw/xquartz/xpr/xprFrame.c
@@ -90,8 +90,8 @@ xprSetNativeProperty(RootlessWindowPtr pFrame)
         /* FIXME: move this to AppleWM extension */
 
         data = native_id;
-        ChangeWindowProperty(pFrame->win, xa_native_window_id(),
-                             XA_INTEGER, 32, PropModeReplace, 1, &data, TRUE);
+        dixChangeWindowProperty(serverClient, pFrame->win, xa_native_window_id(),
+				XA_INTEGER, 32, PropModeReplace, 1, &data, TRUE);
     }
 }
 
diff --git a/hw/xwin/winwin32rootless.c b/hw/xwin/winwin32rootless.c
index 4b4cd3d..6f4e2c9 100755
--- a/hw/xwin/winwin32rootless.c
+++ b/hw/xwin/winwin32rootless.c
@@ -1087,6 +1087,6 @@ winMWExtWMSetNativeProperty (RootlessWindowPtr pFrame)
   /* FIXME: move this to WindowsWM extension */
 
   lData = (long) pRLWinPriv->hWnd;
-  ChangeWindowProperty (pFrame->win, AtmWindowsWmNativeHwnd (),
-			XA_INTEGER, 32, PropModeReplace, 1, &lData, TRUE);
+  dixChangeWindowProperty(serverClient, pFrame->win, AtmWindowsWmNativeHwnd(),
+			  XA_INTEGER, 32, PropModeReplace, 1, &lData, TRUE);
 }
diff --git a/miext/rootless/rootlessWindow.c b/miext/rootless/rootlessWindow.c
index 7285f95..0dad44a 100644
--- a/miext/rootless/rootlessWindow.c
+++ b/miext/rootless/rootlessWindow.c
@@ -181,8 +181,8 @@ set_screen_origin (WindowPtr pWin)
   data[1] = (dixScreenOrigins[pWin->drawable.pScreen->myNum].y
 	     + darwinMainScreenY);
 
-  ChangeWindowProperty (pWin, xa_native_screen_origin (), XA_INTEGER,
-			32, PropModeReplace, 2, data, TRUE);
+  dixChangeWindowProperty(serverClient, pWin, xa_native_screen_origin(),
+			  XA_INTEGER, 32, PropModeReplace, 2, data, TRUE);
 }
 
 /*
diff --git a/xkb/xkbInit.c b/xkb/xkbInit.c
index 2b5f1fb..c0afad0 100644
--- a/xkb/xkbInit.c
+++ b/xkb/xkbInit.c
@@ -222,8 +222,8 @@ char *			pval;
 	ErrorF("Internal Error! bad size (%d!=%d) for _XKB_RULES_NAMES\n",
 								out,len);
     }
-    ChangeWindowProperty(WindowTable[0],name,XA_STRING,8,PropModeReplace,
-							len,pval,True);
+    dixChangeWindowProperty(serverClient, WindowTable[0], name, XA_STRING, 8,
+			    PropModeReplace, len, pval, True);
     xfree(pval);
     return True;
 }
commit cc76ea6e3ac6a405f0c198c4e62be40aa8d2b546
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date:   Fri Feb 29 17:55:31 2008 -0500

    XACE: Add generic support for property and selection polyinstantiation.

diff --git a/Xext/security.c b/Xext/security.c
index cd67120..e82b976 100644
--- a/Xext/security.c
+++ b/Xext/security.c
@@ -910,7 +910,7 @@ SecurityProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 {    
     XacePropertyAccessRec *rec = calldata;
     SecurityStateRec *subj, *obj;
-    ATOM name = rec->pProp->propertyName;
+    ATOM name = (*rec->ppProp)->propertyName;
     Mask requested = rec->access_mode;
     Mask allowed = SecurityResourceMask | DixReadAccess;
 
diff --git a/Xext/xace.c b/Xext/xace.c
index e88debc..8a8f8c6 100644
--- a/Xext/xace.c
+++ b/Xext/xace.c
@@ -56,16 +56,17 @@ int XaceHookDispatch(ClientPtr client, int major)
 }
 
 int XaceHookPropertyAccess(ClientPtr client, WindowPtr pWin,
-			   PropertyPtr pProp, Mask access_mode)
+			   PropertyPtr *ppProp, Mask access_mode)
 {
-    XacePropertyAccessRec rec = { client, pWin, pProp, access_mode, Success };
+    XacePropertyAccessRec rec = { client, pWin, ppProp, access_mode, Success };
     CallCallbacks(&XaceHooks[XACE_PROPERTY_ACCESS], &rec);
     return rec.status;
 }
 
-int XaceHookSelectionAccess(ClientPtr client, Atom name, Mask access_mode)
+int XaceHookSelectionAccess(ClientPtr client,
+			    Selection **ppSel, Mask access_mode)
 {
-    XaceSelectionAccessRec rec = { client, name, access_mode, Success };
+    XaceSelectionAccessRec rec = { client, ppSel, access_mode, Success };
     CallCallbacks(&XaceHooks[XACE_SELECTION_ACCESS], &rec);
     return rec.status;
 }
diff --git a/Xext/xace.h b/Xext/xace.h
index 1f07d9f..bd69bca 100644
--- a/Xext/xace.h
+++ b/Xext/xace.h
@@ -29,6 +29,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "region.h"
 #include "window.h"
 #include "property.h"
+#include "selection.h"
 
 /* Default window background */
 #define XaceBackgroundNoneState(w) ((w)->forcedBG ? BackgroundPixel : None)
@@ -68,9 +69,9 @@ extern int XaceHook(
  */
 extern int XaceHookDispatch(ClientPtr ptr, int major);
 extern int XaceHookPropertyAccess(ClientPtr ptr, WindowPtr pWin,
-				  PropertyPtr pProp, Mask access_mode);
-extern int XaceHookSelectionAccess(ClientPtr ptr, Atom name,
-				   Mask access_mode);
+				  PropertyPtr *ppProp, Mask access_mode);
+extern int XaceHookSelectionAccess(ClientPtr ptr,
+				   Selection **ppSel, Mask access_mode);
 extern void XaceHookAuditEnd(ClientPtr ptr, int result);
 
 /* Register a callback for a given hook.
diff --git a/Xext/xacestr.h b/Xext/xacestr.h
index e31d424..ba115a4 100644
--- a/Xext/xacestr.h
+++ b/Xext/xacestr.h
@@ -59,7 +59,7 @@ typedef struct {
 typedef struct {
     ClientPtr client;
     WindowPtr pWin;
-    PropertyPtr pProp;
+    PropertyPtr *ppProp;
     Mask access_mode;
     int status;
 } XacePropertyAccessRec;
@@ -110,7 +110,7 @@ typedef struct {
 /* XACE_SELECTION_ACCESS */
 typedef struct {
     ClientPtr client;
-    Atom name;
+    Selection **ppSel;
     Mask access_mode;
     int status;
 } XaceSelectionAccessRec;
diff --git a/Xext/xselinux.c b/Xext/xselinux.c
index 8d66ea1..a7d3999 100644
--- a/Xext/xselinux.c
+++ b/Xext/xselinux.c
@@ -134,7 +134,7 @@ static struct security_class_mapping map[] = {
     { "x_gc", { "", "", "destroy", "create", "getattr", "setattr", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "use", NULL }},
     { "x_font", { "", "", "destroy", "create", "getattr", "", "", "", "", "", "", "", "add_glyph", "remove_glyph", "", "", "", "", "", "", "", "", "", "", "use", NULL }},
     { "x_colormap", { "read", "write", "destroy", "create", "getattr", "", "", "", "", "", "", "", "add_color", "remove_color", "", "", "", "", "", "", "install", "uninstall", "", "", "use", NULL }},
-    { "x_property", { "read", "write", "destroy", "create", "getattr", "setattr", NULL }},
+    { "x_property", { "read", "write", "destroy", "create", "getattr", "setattr", "", "", "", "", "", "", "", "", "", "", "write", NULL }},
     { "x_selection", { "read", "", "", "", "getattr", "setattr", NULL }},
     { "x_cursor", { "read", "write", "destroy", "create", "getattr", "setattr", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "use", NULL }},
     { "x_client", { "", "", "destroy", "", "getattr", "setattr", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "manage", NULL }},
@@ -691,14 +691,15 @@ SELinuxProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata)
     SELinuxSubjectRec *subj;
     SELinuxObjectRec *obj;
     SELinuxAuditRec auditdata = { .client = rec->client };
+    PropertyPtr pProp = *rec->ppProp;
     int rc;
 
     subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
-    obj = dixLookupPrivate(&rec->pProp->devPrivates, objectKey);
+    obj = dixLookupPrivate(&pProp->devPrivates, objectKey);
 
     /* If this is a new object that needs labeling, do it now */
     if (rec->access_mode & DixCreateAccess) {
-	const char *name = NameForAtom(rec->pProp->propertyName);
+	const char *name = NameForAtom(pProp->propertyName);
 	security_context_t con;
 	security_id_t sid;
 
@@ -729,7 +730,7 @@ SELinuxProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata)
     }
 
     /* Perform the security check */
-    auditdata.property = rec->pProp->propertyName;
+    auditdata.property = pProp->propertyName;
     rc = SELinuxDoCheck(subj, obj, SECCLASS_X_PROPERTY, rec->access_mode,
 			&auditdata);
     if (rc != Success)
@@ -870,17 +871,21 @@ SELinuxSelection(CallbackListPtr *pcbl, pointer unused, pointer calldata)
     SELinuxSubjectRec *subj;
     SELinuxObjectRec sel_sid;
     SELinuxAuditRec auditdata = { .client = rec->client };
+    Selection *pSel = *rec->ppSel;
     int rc;
 
+    if (rec->access_mode & DixCreateAccess)
+	return; /* don't use create currently */
+
     subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
 
-    rc = SELinuxSelectionToSID(rec->name, &sel_sid);
+    rc = SELinuxSelectionToSID(pSel->selection, &sel_sid);
     if (rc != Success) {
 	rec->status = rc;
 	return;
     }
 
-    auditdata.selection = rec->name;
+    auditdata.selection = pSel->selection;
     rc = SELinuxDoCheck(subj, &sel_sid, SECCLASS_X_SELECTION, rec->access_mode,
 			&auditdata);
     if (rc != Success)
@@ -1206,16 +1211,8 @@ ProcSELinuxGetPropertyContext(ClientPtr client)
     if (rc != Success)
 	return rc;
 
-    pProp = wUserProps(pWin);
-    while (pProp) {
-	if (pProp->propertyName == stuff->property)
-	    break;
-	pProp = pProp->next;
-    }
-    if (!pProp)
-	return BadValue;
-
-    rc = XaceHookPropertyAccess(client, pWin, pProp, DixGetAttrAccess);
+    rc = dixLookupProperty(&pProp, pWin, stuff->property, client,
+			   DixGetAttrAccess);
     if (rc != Success)
 	return rc;
 
diff --git a/dix/property.c b/dix/property.c
index e74becf..8b66ad6 100644
--- a/dix/property.c
+++ b/dix/property.c
@@ -103,7 +103,7 @@ dixLookupProperty(PropertyPtr *result, WindowPtr pWin, Atom propertyName,
 	    break;
 
     if (pProp)
-	rc = XaceHookPropertyAccess(client, pWin, pProp, access_mode);
+	rc = XaceHookPropertyAccess(client, pWin, &pProp, access_mode);
     *result = pProp;
     return rc;
 }
@@ -256,12 +256,14 @@ dixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
     PropertyPtr pProp;
     int sizeInBytes, totalSize, rc;
     pointer data;
+    Mask access_mode;
 
     sizeInBytes = format>>3;
     totalSize = len * sizeInBytes;
+    access_mode = (mode == PropModeReplace) ? DixWriteAccess : DixBlendAccess;
 
     /* first see if property already exists */
-    rc = dixLookupProperty(&pProp, pWin, property, pClient, DixWriteAccess);
+    rc = dixLookupProperty(&pProp, pWin, property, pClient, access_mode);
 
     if (rc == BadMatch)   /* just add to list */
     {
@@ -284,7 +286,7 @@ dixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
 	    memmove((char *)data, (char *)value, totalSize);
 	pProp->size = len;
 	pProp->devPrivates = NULL;
-	rc = XaceHookPropertyAccess(pClient, pWin, pProp,
+	rc = XaceHookPropertyAccess(pClient, pWin, &pProp,
 				    DixCreateAccess|DixWriteAccess);
 	if (rc != Success) {
 	    xfree(data);
@@ -588,7 +590,7 @@ ProcListProperties(ClientPtr client)
     temppAtoms = pAtoms;
     for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) {
 	realProp = pProp;
-	rc = XaceHookPropertyAccess(client, pWin, pProp, DixGetAttrAccess);
+	rc = XaceHookPropertyAccess(client, pWin, &realProp, DixGetAttrAccess);
 	if (rc == Success && realProp == pProp) {
 	    *temppAtoms++ = pProp->propertyName;
 	    numProps++;
diff --git a/dix/selection.c b/dix/selection.c
index e2e279a..52b1611 100644
--- a/dix/selection.c
+++ b/dix/selection.c
@@ -80,7 +80,7 @@ dixLookupSelection(Selection **result, Atom selectionName,
     for (i = 0; i < NumCurrentSelections; i++)
 	if (CurrentSelections[i].selection == selectionName) {
 	    pSel = CurrentSelections + i;
-	    rc = XaceHookSelectionAccess(client, selectionName, access_mode);
+	    rc = XaceHookSelectionAccess(client, &pSel, access_mode);
 	    break;
 	}
 
@@ -206,6 +206,10 @@ ProcSetSelectionOwner(ClientPtr client)
 	pSel = CurrentSelections + NumCurrentSelections;
 	pSel->selection = stuff->selection;
 	pSel->devPrivates = NULL;
+
+	/* security creation/labeling check */
+	(void)XaceHookSelectionAccess(client, &pSel, DixCreateAccess);
+
 	pSel->next = NULL;
 	if (NumCurrentSelections > 0)
 	    CurrentSelections[NumCurrentSelections - 1].next = pSel;
commit 34bf308a9e66f1a2f48630a15b1802afad50ec24
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date:   Fri Feb 29 18:00:23 2008 -0500

    dix: Refactoring of selection code to allow for polyinstantiation.
    Introduces dixLookupSelection() API.
    Removes NumCurrentSelections from API.

diff --git a/Xext/xselinux.c b/Xext/xselinux.c
index 9adc931..8d66ea1 100644
--- a/Xext/xselinux.c
+++ b/Xext/xselinux.c
@@ -967,8 +967,6 @@ SELinuxSelectionState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
 
     switch (rec->kind) {
     case SelectionSetOwner:
-    case SelectionGetOwner:
-    case SelectionConvertSelection:
     default:
 	break;
     }
diff --git a/dix/Makefile.am b/dix/Makefile.am
index 2cf9014..b7b1ec0 100644
--- a/dix/Makefile.am
+++ b/dix/Makefile.am
@@ -29,6 +29,7 @@ libdix_la_SOURCES = 	\
 	property.c	\
 	registry.c	\
 	resource.c	\
+	selection.c	\
 	swaprep.c	\
 	swapreq.c	\
 	tables.c	\
diff --git a/dix/dispatch.c b/dix/dispatch.c
index e8e650a..bb8b0c4 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -165,10 +165,6 @@ typedef const char *string;
 extern xConnSetupPrefix connSetupPrefix;
 extern char *ConnectionInfo;
 
-_X_EXPORT Selection *CurrentSelections;
-_X_EXPORT int NumCurrentSelections;
-CallbackListPtr SelectionCallback = NULL;
-
 static ClientPtr grabClient;
 #define GrabNone 0
 #define GrabActive 1
@@ -181,8 +177,6 @@ extern int connBlockScreenStart;
 
 static void KillAllClients(void);
 
-static void DeleteClientFromAnySelections(ClientPtr client);
-
 static int nextFreeClientID; /* always MIN free client ID */
 
 static int	nClients;	/* number of authorized clients */
@@ -246,14 +240,6 @@ UpdateCurrentTimeIf(void)
 	currentTime = systime;
 }
 
-static void
-InitSelections(void)
-{
-    if (CurrentSelections)
-	xfree(CurrentSelections);
-    CurrentSelections = (Selection *)NULL;
-    NumCurrentSelections = 0;
-}
 #ifdef SMART_SCHEDULE
 
 #undef SMART_DEBUG
@@ -372,7 +358,6 @@ Dispatch(void)
 #endif
 
     nextFreeClientID = 1;
-    InitSelections();
     nClients = 0;
 
     clientReady = (int *) xalloc(sizeof(int) * MaxClients);
@@ -968,217 +953,6 @@ ProcGetAtomName(ClientPtr client)
 }
 
 int
-ProcSetSelectionOwner(ClientPtr client)
-{
-    WindowPtr pWin;
-    TimeStamp time;
-    int rc;
-    REQUEST(xSetSelectionOwnerReq);
-    REQUEST_SIZE_MATCH(xSetSelectionOwnerReq);
-
-    UpdateCurrentTime();
-    time = ClientTimeToServerTime(stuff->time);
-
-    /* If the client's time stamp is in the future relative to the server's
-	time stamp, do not set the selection, just return success. */
-    if (CompareTimeStamps(time, currentTime) == LATER)
-    	return Success;
-    if (stuff->window != None)
-    {
-	rc = dixLookupWindow(&pWin, stuff->window, client, DixSetAttrAccess);
-        if (rc != Success)
-            return rc;
-    }
-    else
-        pWin = (WindowPtr)None;
-    if (ValidAtom(stuff->selection))
-    {
-	int i = 0;
-
-	rc = XaceHookSelectionAccess(client, stuff->selection,
-				     DixSetAttrAccess);
-	if (rc != Success)
-	    return rc;
-
-	/*
-	 * First, see if the selection is already set... 
-	 */
-	while ((i < NumCurrentSelections) && 
-	       CurrentSelections[i].selection != stuff->selection) 
-            i++;
-        if (i < NumCurrentSelections)
-        {        
-	    xEvent event;
-
-	    /* If the timestamp in client's request is in the past relative
-		to the time stamp indicating the last time the owner of the
-		selection was set, do not set the selection, just return 
-		success. */
-            if (CompareTimeStamps(time, CurrentSelections[i].lastTimeChanged)
-		== EARLIER)
-		return Success;
-	    if (CurrentSelections[i].client &&
-		(!pWin || (CurrentSelections[i].client != client)))
-	    {
-		event.u.u.type = SelectionClear;
-		event.u.selectionClear.time = time.milliseconds;
-		event.u.selectionClear.window = CurrentSelections[i].window;
-		event.u.selectionClear.atom = CurrentSelections[i].selection;
-		(void) TryClientEvents (CurrentSelections[i].client, &event, 1,
-				NoEventMask, NoEventMask /* CantBeFiltered */,
-				NullGrab);
-	    }
-	}
-	else
-	{
-	    /*
-	     * It doesn't exist, so add it...
-	     */
-	    Selection *newsels;
-
-	    if (i == 0)
-		newsels = (Selection *)xalloc(sizeof(Selection));
-	    else
-		newsels = (Selection *)xrealloc(CurrentSelections,
-			    (NumCurrentSelections + 1) * sizeof(Selection));
-	    if (!newsels)
-		return BadAlloc;
-	    NumCurrentSelections++;
-	    CurrentSelections = newsels;
-	    CurrentSelections[i].selection = stuff->selection;
-	    CurrentSelections[i].devPrivates = NULL;
-	}
-        CurrentSelections[i].lastTimeChanged = time;
-	CurrentSelections[i].window = stuff->window;
-	CurrentSelections[i].pWin = pWin;
-	CurrentSelections[i].client = (pWin ? client : NullClient);
-	if (SelectionCallback)
-	{
-	    SelectionInfoRec	info;
-
-	    info.selection = &CurrentSelections[i];
-	    info.client = client;
-	    info.kind= SelectionSetOwner;
-	    CallCallbacks(&SelectionCallback, &info);
-	}
-	return (client->noClientException);
-    }
-    else 
-    {
-	client->errorValue = stuff->selection;
-        return (BadAtom);
-    }
-}
-
-int
-ProcGetSelectionOwner(ClientPtr client)
-{
-    REQUEST(xResourceReq);
-
-    REQUEST_SIZE_MATCH(xResourceReq);
-    if (ValidAtom(stuff->id))
-    {
-	int rc, i;
-        xGetSelectionOwnerReply reply;
-
-	rc = XaceHookSelectionAccess(client, stuff->id, DixGetAttrAccess);
-	if (rc != Success)
-	    return rc;
-
-	i = 0;
-        while ((i < NumCurrentSelections) && 
-	       CurrentSelections[i].selection != stuff->id) i++;
-        reply.type = X_Reply;
-	reply.length = 0;
-	reply.sequenceNumber = client->sequence;
-	if (i < NumCurrentSelections) {
-	    if (SelectionCallback) {
-		SelectionInfoRec info;
-
-		info.selection = &CurrentSelections[i];
-		info.client = client;
-		info.kind= SelectionGetOwner;
-		CallCallbacks(&SelectionCallback, &info);
-	    }
-            reply.owner = CurrentSelections[i].window;
-	} else
-            reply.owner = None;
-        WriteReplyToClient(client, sizeof(xGetSelectionOwnerReply), &reply);
-        return(client->noClientException);
-    }
-    else            
-    {
-	client->errorValue = stuff->id;
-        return (BadAtom); 
-    }
-}
-
-int
-ProcConvertSelection(ClientPtr client)
-{
-    Bool paramsOkay;
-    xEvent event;
-    WindowPtr pWin;
-    REQUEST(xConvertSelectionReq);
-    int rc;
-
-    REQUEST_SIZE_MATCH(xConvertSelectionReq);
-    rc = dixLookupWindow(&pWin, stuff->requestor, client, DixSetAttrAccess);
-    if (rc != Success)
-        return rc;
-    rc = XaceHookSelectionAccess(client, stuff->selection, DixReadAccess);
-    if (rc != Success)
-	return rc;
-
-    paramsOkay = (ValidAtom(stuff->selection) && ValidAtom(stuff->target));
-    if (stuff->property != None)
-	paramsOkay &= ValidAtom(stuff->property);
-    if (paramsOkay)
-    {
-	int i;
-
-	i = 0;
-	while ((i < NumCurrentSelections) && 
-	       CurrentSelections[i].selection != stuff->selection) i++;
-	if (i < NumCurrentSelections && CurrentSelections[i].window != None) {
-	    if (SelectionCallback) {
-		SelectionInfoRec info;
-
-		info.selection = &CurrentSelections[i];
-		info.client = client;
-		info.kind= SelectionConvertSelection;
-		CallCallbacks(&SelectionCallback, &info);
-	    }
-	    event.u.u.type = SelectionRequest;
-	    event.u.selectionRequest.time = stuff->time;
-	    event.u.selectionRequest.owner = CurrentSelections[i].window;
-	    event.u.selectionRequest.requestor = stuff->requestor;
-	    event.u.selectionRequest.selection = stuff->selection;
-	    event.u.selectionRequest.target = stuff->target;
-	    event.u.selectionRequest.property = stuff->property;
-	    if (TryClientEvents(
-		CurrentSelections[i].client, &event, 1, NoEventMask,
-		NoEventMask /* CantBeFiltered */, NullGrab))
-		return (client->noClientException);
-	}
-	event.u.u.type = SelectionNotify;
-	event.u.selectionNotify.time = stuff->time;
-	event.u.selectionNotify.requestor = stuff->requestor;
-	event.u.selectionNotify.selection = stuff->selection;
-	event.u.selectionNotify.target = stuff->target;
-	event.u.selectionNotify.property = None;
-	(void) TryClientEvents(client, &event, 1, NoEventMask,
-			       NoEventMask /* CantBeFiltered */, NullGrab);
-	return (client->noClientException);
-    }
-    else 
-    {
-	client->errorValue = stuff->property;
-        return (BadAtom);
-    }
-}
-
-int
 ProcGrabServer(ClientPtr client)
 {
     int rc;
@@ -3981,54 +3755,6 @@ SendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode,
 }
 
 void
-DeleteWindowFromAnySelections(WindowPtr pWin)
-{
-    int i;
-
-    for (i = 0; i< NumCurrentSelections; i++)
-        if (CurrentSelections[i].pWin == pWin)
-        {
-	    if (SelectionCallback)
-	    {
-	        SelectionInfoRec    info;
-
-		info.selection = &CurrentSelections[i];
-		info.kind = SelectionWindowDestroy;
-		CallCallbacks(&SelectionCallback, &info);
-	    }
-	    dixFreePrivates(CurrentSelections[i].devPrivates);
-            CurrentSelections[i].pWin = (WindowPtr)NULL;
-            CurrentSelections[i].window = None;
-	    CurrentSelections[i].client = NullClient;
-	    CurrentSelections[i].devPrivates = NULL;
-	}
-}
-
-static void
-DeleteClientFromAnySelections(ClientPtr client)
-{
-    int i;
-
-    for (i = 0; i< NumCurrentSelections; i++)
-        if (CurrentSelections[i].client == client)
-        {
-	    if (SelectionCallback)
-	    {
-	        SelectionInfoRec    info;
-
-		info.selection = &CurrentSelections[i];
-		info.kind = SelectionWindowDestroy;
-		CallCallbacks(&SelectionCallback, &info);
-	    }
-	    dixFreePrivates(CurrentSelections[i].devPrivates);
-            CurrentSelections[i].pWin = (WindowPtr)NULL;
-            CurrentSelections[i].window = None;
-	    CurrentSelections[i].client = NullClient;
-	    CurrentSelections[i].devPrivates = NULL;
-	}
-}
-
-void
 MarkClientException(ClientPtr client)
 {
     client->noClientException = -1;
diff --git a/dix/main.c b/dix/main.c
index 068dae9..db43473 100644
--- a/dix/main.c
+++ b/dix/main.c
@@ -93,6 +93,7 @@ Equipment Corporation.
 #include "colormap.h"
 #include "colormapst.h"
 #include "cursorstr.h"
+#include "selection.h"
 #include <X11/fonts/font.h>
 #include "opaque.h"
 #include "servermd.h"
@@ -346,6 +347,7 @@ main(int argc, char *argv[], char *envp[])
 
 	InitAtoms();
 	InitEvents();
+	InitSelections();
 	InitGlyphCaching();
 	if (!dixResetPrivates())
 	    FatalError("couldn't init private data storage");
diff --git a/dix/selection.c b/dix/selection.c
new file mode 100644
index 0000000..e2e279a
--- /dev/null
+++ b/dix/selection.c
@@ -0,0 +1,306 @@
+/************************************************************
+
+Copyright 1987, 1989, 1998  The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its 
+documentation for any purpose and without fee is hereby granted, 
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in 
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.  
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+********************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "windowstr.h"
+#include "dixstruct.h"
+#include "dispatch.h"
+#include "selection.h"
+#include "xace.h"
+
+/*****************************************************************
+ * Selection Stuff
+ *
+ *    dixLookupSelection
+ *
+ *   Selections are global to the server.  The list of selections should
+ *   not be traversed directly.  Instead, use the functions listed above.
+ *
+ *****************************************************************/
+
+_X_EXPORT Selection *CurrentSelections;
+static int NumCurrentSelections;
+CallbackListPtr SelectionCallback;
+
+_X_EXPORT int
+dixLookupSelection(Selection **result, Atom selectionName,
+		   ClientPtr client, Mask access_mode)
+{
+    Selection *pSel = NULL;
+    int i, rc = BadMatch;
+    client->errorValue = selectionName;
+
+    for (i = 0; i < NumCurrentSelections; i++)
+	if (CurrentSelections[i].selection == selectionName) {
+	    pSel = CurrentSelections + i;
+	    rc = XaceHookSelectionAccess(client, selectionName, access_mode);
+	    break;
+	}
+
+    *result = pSel;
+    return rc;
+}
+
+void
+InitSelections(void)
+{
+    Selection *pSel = CurrentSelections;
+
+    for (; pSel - CurrentSelections < NumCurrentSelections; pSel++)
+	dixFreePrivates(pSel->devPrivates);
+
+    xfree(CurrentSelections);
+    CurrentSelections = NULL;
+    NumCurrentSelections = 0;
+}
+
+static _X_INLINE void
+CallSelectionCallback(Selection *pSel, ClientPtr client,
+		      SelectionCallbackKind kind)
+{
+    SelectionInfoRec info = { pSel, client, kind };
+    CallCallbacks(&SelectionCallback, &info);
+}
+
+void
+DeleteWindowFromAnySelections(WindowPtr pWin)
+{
+    Selection *pSel = CurrentSelections;
+
+    for (; pSel - CurrentSelections < NumCurrentSelections; pSel++)
+        if (pSel->pWin == pWin) {
+	    CallSelectionCallback(pSel, NULL, SelectionWindowDestroy);
+
+            pSel->pWin = (WindowPtr)NULL;
+            pSel->window = None;
+	    pSel->client = NullClient;
+	}
+}
+
+void
+DeleteClientFromAnySelections(ClientPtr client)
+{
+    Selection *pSel = CurrentSelections;
+
+    for (; pSel - CurrentSelections < NumCurrentSelections; pSel++)
+        if (pSel->client == client) {
+	    CallSelectionCallback(pSel, NULL, SelectionClientClose);
+
+            pSel->pWin = (WindowPtr)NULL;
+            pSel->window = None;
+	    pSel->client = NullClient;
+	}
+}
+
+int
+ProcSetSelectionOwner(ClientPtr client)
+{
+    WindowPtr pWin = NULL;
+    TimeStamp time;
+    Selection *pSel;
+    int rc;
+
+    REQUEST(xSetSelectionOwnerReq);
+    REQUEST_SIZE_MATCH(xSetSelectionOwnerReq);
+
+    UpdateCurrentTime();
+    time = ClientTimeToServerTime(stuff->time);
+
+    /* If the client's time stamp is in the future relative to the server's
+	time stamp, do not set the selection, just return success. */
+    if (CompareTimeStamps(time, currentTime) == LATER)
+    	return Success;
+
+    if (stuff->window != None) {
+	rc = dixLookupWindow(&pWin, stuff->window, client, DixSetAttrAccess);
+        if (rc != Success)
+            return rc;
+    }
+    if (!ValidAtom(stuff->selection)) {
+	client->errorValue = stuff->selection;
+        return BadAtom;
+    }
+
+    /*
+     * First, see if the selection is already set...
+     */
+    rc = dixLookupSelection(&pSel, stuff->selection, client, DixSetAttrAccess);
+
+    if (rc == Success) {
+	xEvent event;
+
+	/* If the timestamp in client's request is in the past relative
+	   to the time stamp indicating the last time the owner of the
+	   selection was set, do not set the selection, just return 
+	   success. */
+	if (CompareTimeStamps(time, pSel->lastTimeChanged) == EARLIER)
+	    return Success;
+	if (pSel->client && (!pWin || (pSel->client != client)))
+	{
+	    event.u.u.type = SelectionClear;
+	    event.u.selectionClear.time = time.milliseconds;
+	    event.u.selectionClear.window = pSel->window;
+	    event.u.selectionClear.atom = pSel->selection;
+	    TryClientEvents(pSel->client, &event, 1, NoEventMask,
+			    NoEventMask /* CantBeFiltered */, NullGrab);
+	}
+    }
+    else if (rc == BadMatch)
+    {
+	/*
+	 * It doesn't exist, so add it...
+	 */
+	int size = (NumCurrentSelections + 1) * sizeof(Selection);
+	CurrentSelections = xrealloc(CurrentSelections, size);
+	if (!CurrentSelections) {
+	    NumCurrentSelections = 0;
+	    return BadAlloc;
+	}
+	pSel = CurrentSelections + NumCurrentSelections;
+	pSel->selection = stuff->selection;
+	pSel->devPrivates = NULL;
+	pSel->next = NULL;
+	if (NumCurrentSelections > 0)
+	    CurrentSelections[NumCurrentSelections - 1].next = pSel;
+	NumCurrentSelections++;
+    }
+    else
+	return rc;
+
+    pSel->lastTimeChanged = time;
+    pSel->window = stuff->window;
+    pSel->pWin = pWin;
+    pSel->client = (pWin ? client : NullClient);
+
+    CallSelectionCallback(pSel, client, SelectionSetOwner);
+    return client->noClientException;
+}
+
+int
+ProcGetSelectionOwner(ClientPtr client)
+{
+    int rc;
+    Selection *pSel;
+    xGetSelectionOwnerReply reply;
+
+    REQUEST(xResourceReq);
+    REQUEST_SIZE_MATCH(xResourceReq);
+
+    if (!ValidAtom(stuff->id)) {
+	client->errorValue = stuff->id;
+        return BadAtom;
+    }
+
+    reply.type = X_Reply;
+    reply.length = 0;
+    reply.sequenceNumber = client->sequence;
+
+    rc = dixLookupSelection(&pSel, stuff->id, client, DixGetAttrAccess);
+    if (rc == Success)
+	reply.owner = pSel->window;
+    else if (rc == BadMatch)
+	reply.owner = None;
+    else
+	return rc;
+
+    WriteReplyToClient(client, sizeof(xGetSelectionOwnerReply), &reply);
+    return client->noClientException;
+}
+
+int
+ProcConvertSelection(ClientPtr client)
+{
+    Bool paramsOkay;
+    xEvent event;
+    WindowPtr pWin;
+    Selection *pSel;
+    int rc;
+
+    REQUEST(xConvertSelectionReq);
+    REQUEST_SIZE_MATCH(xConvertSelectionReq);
+
+    rc = dixLookupWindow(&pWin, stuff->requestor, client, DixSetAttrAccess);
+    if (rc != Success)
+        return rc;
+
+    paramsOkay = ValidAtom(stuff->selection) && ValidAtom(stuff->target);
+    paramsOkay &= (stuff->property == None) || ValidAtom(stuff->property);
+    if (!paramsOkay) {
+	client->errorValue = stuff->property;
+        return BadAtom;
+    }
+
+    rc = dixLookupSelection(&pSel, stuff->selection, client, DixReadAccess);
+
+    if (rc != Success && rc != BadMatch)
+	return rc;
+    else if (rc == Success && pSel->window != None) {
+	event.u.u.type = SelectionRequest;
+	event.u.selectionRequest.owner = pSel->window;
+	event.u.selectionRequest.time = stuff->time;
+	event.u.selectionRequest.requestor = stuff->requestor;
+	event.u.selectionRequest.selection = stuff->selection;
+	event.u.selectionRequest.target = stuff->target;
+	event.u.selectionRequest.property = stuff->property;
+	if (TryClientEvents(pSel->client, &event, 1, NoEventMask,
+			    NoEventMask /* CantBeFiltered */, NullGrab))
+	    return client->noClientException;
+    }
+
+    event.u.u.type = SelectionNotify;
+    event.u.selectionNotify.time = stuff->time;
+    event.u.selectionNotify.requestor = stuff->requestor;
+    event.u.selectionNotify.selection = stuff->selection;
+    event.u.selectionNotify.target = stuff->target;
+    event.u.selectionNotify.property = None;
+    TryClientEvents(client, &event, 1, NoEventMask,
+		    NoEventMask /* CantBeFiltered */, NullGrab);
+    return client->noClientException;
+}
diff --git a/hw/xfree86/loader/dixsym.c b/hw/xfree86/loader/dixsym.c
index e6c37fe..d035c76 100644
--- a/hw/xfree86/loader/dixsym.c
+++ b/hw/xfree86/loader/dixsym.c
@@ -92,9 +92,6 @@
 extern int XkbDfltRepeatDelay, XkbDfltRepeatInterval;
 #endif
 
-extern Selection *CurrentSelections;
-extern int NumCurrentSelections;
-
 /* DIX things */
 
 _X_HIDDEN void *dixLookupTab[] = {
@@ -150,8 +147,6 @@ _X_HIDDEN void *dixLookupTab[] = {
     SYMVAR(isItTimeToYield)
     SYMVAR(ClientStateCallback)
     SYMVAR(ServerGrabCallback)
-    SYMVAR(CurrentSelections)
-    SYMVAR(NumCurrentSelections)
     /* dixfonts.c */
     SYMFUNC(CloseFont)
     SYMFUNC(FontToXError)
@@ -196,6 +191,9 @@ _X_HIDDEN void *dixLookupTab[] = {
     SYMFUNC(dixLookupProperty)
     SYMFUNC(ChangeWindowProperty)
     SYMFUNC(dixChangeWindowProperty)
+    /* selection.c */
+    SYMFUNC(dixLookupSelection)
+    SYMVAR(CurrentSelections)
     /* extension.c */
     SYMFUNC(AddExtension)
     SYMFUNC(AddExtensionAlias)
diff --git a/include/dix.h b/include/dix.h
index 52212e7..0790f58 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -166,9 +166,6 @@ extern void SendErrorToClient(
     XID /*resId*/,
     int /*errorCode*/);
 
-extern void DeleteWindowFromAnySelections(
-    WindowPtr /*pWin*/);
-
 extern void MarkClientException(
     ClientPtr /*client*/);
 
@@ -556,26 +553,6 @@ typedef struct {
     int count;
 } DeviceEventInfoRec;
 
-/*
- * SelectionCallback stuff
- */
-
-extern CallbackListPtr SelectionCallback;
-
-typedef enum {
-    SelectionSetOwner,
-    SelectionGetOwner,
-    SelectionConvertSelection,
-    SelectionWindowDestroy,
-    SelectionClientClose
-} SelectionCallbackKind;
-
-typedef struct {
-    struct _Selection	    *selection;
-    ClientPtr		    client;
-    SelectionCallbackKind   kind;
-} SelectionInfoRec;
-
 /* strcasecmp.c */
 #if NEED_STRCASECMP
 #define strcasecmp xstrcasecmp
diff --git a/include/selection.h b/include/selection.h
index 859b6a3..dd9b056 100644
--- a/include/selection.h
+++ b/include/selection.h
@@ -1,7 +1,3 @@
-
-#ifndef SELECTION_H
-#define SELECTION_H 1
-
 /***********************************************************
 
 Copyright 1987, 1998  The Open Group
@@ -49,10 +45,13 @@ SOFTWARE.
 
 ******************************************************************/
 
+#ifndef SELECTION_H
+#define SELECTION_H 1
+
 #include "dixstruct.h"
 #include "privates.h"
+
 /*
- *
  *  Selection data structures 
  */
 
@@ -62,11 +61,45 @@ typedef struct _Selection {
     Window window;
     WindowPtr pWin;
     ClientPtr client;
-    ClientPtr alt_client; /* support for redirection */
-    Window alt_window;    /* support for redirection */
+    struct _Selection *next;
     PrivateRec *devPrivates;
 } Selection;
 
+
+/*
+ *  Selection API
+ */
+
+int dixLookupSelection(Selection **result, Atom name,
+		       ClientPtr client, Mask access_mode);
+
+extern Selection *CurrentSelections;
+
+extern CallbackListPtr SelectionCallback;
+
+typedef enum {
+    SelectionSetOwner,
+    SelectionWindowDestroy,
+    SelectionClientClose
+} SelectionCallbackKind;
+
+typedef struct {
+    struct _Selection	    *selection;
+    ClientPtr		    client;
+    SelectionCallbackKind   kind;
+} SelectionInfoRec;
+
+
+/*
+ *  Selection server internals
+ */
+
+void InitSelections(void);
+
+void DeleteWindowFromAnySelections(WindowPtr pWin);
+
+void DeleteClientFromAnySelections(ClientPtr client);
+
 #endif /* SELECTION_H */
 
 
commit d5715f7beaad6816db27b01b67d7a3c69164d106
Author: Eamon Walsh <ewalsh at tycho.nsa.gov>
Date:   Fri Feb 29 16:16:12 2008 -0500

    dix: Refactoring of property code to allow for polyinstantiation.
    Introduces dixLookupProperty() API.

diff --git a/dix/property.c b/dix/property.c
index ce61169..e74becf 100644
--- a/dix/property.c
+++ b/dix/property.c
@@ -63,11 +63,10 @@ SOFTWARE.
 /*****************************************************************
  * Property Stuff
  *
- *    ChangeProperty, DeleteProperty, GetProperties,
- *    ListProperties
+ *    dixLookupProperty, dixChangeProperty, DeleteProperty
  *
- *   Properties below to windows.  A allocate slots each time
- *   a property is added.  No fancy searching done.
+ *   Properties belong to windows.  The list of properties should not be
+ *   traversed directly.  Instead, use the three functions listed above.
  *
  *****************************************************************/
 
@@ -91,17 +90,22 @@ PrintPropertys(WindowPtr pWin)
 }
 #endif
 
-static _X_INLINE PropertyPtr
-FindProperty(WindowPtr pWin, Atom propertyName)
+_X_EXPORT int
+dixLookupProperty(PropertyPtr *result, WindowPtr pWin, Atom propertyName,
+		  ClientPtr client, Mask access_mode)
 {
-    PropertyPtr pProp = wUserProps(pWin);
-    while (pProp)
-    {
+    PropertyPtr pProp;
+    int rc = BadMatch;
+    client->errorValue = propertyName;
+
+    for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
 	if (pProp->propertyName == propertyName)
 	    break;
-	pProp = pProp->next;
-    }
-    return pProp;
+
+    if (pProp)
+	rc = XaceHookPropertyAccess(client, pWin, pProp, access_mode);
+    *result = pProp;
+    return rc;
 }
 
 static void
@@ -125,65 +129,69 @@ ProcRotateProperties(ClientPtr client)
     WindowPtr pWin;
     Atom * atoms;
     PropertyPtr * props;               /* array of pointer */
-    PropertyPtr pProp;
+    PropertyPtr pProp, saved;
 
     REQUEST_FIXED_SIZE(xRotatePropertiesReq, stuff->nAtoms << 2);
     UpdateCurrentTime();
     rc = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess);
-    if (rc != Success)
+    if (rc != Success || stuff->nAtoms <= 0)
         return rc;
-    if (!stuff->nAtoms)
-	return(Success);
+
     atoms = (Atom *) & stuff[1];
     props = (PropertyPtr *)xalloc(stuff->nAtoms * sizeof(PropertyPtr));
-    if (!props)
-	return(BadAlloc);
+    saved = (PropertyPtr)xalloc(stuff->nAtoms * sizeof(PropertyRec));
+    if (!props || !saved) {
+	rc = BadAlloc;
+	goto out;
+    }
+
     for (i = 0; i < stuff->nAtoms; i++)
     {
         if (!ValidAtom(atoms[i])) {
-            xfree(props);
+	    rc = BadAtom;
 	    client->errorValue = atoms[i];
-            return BadAtom;
+	    goto out;
         }
         for (j = i + 1; j < stuff->nAtoms; j++)
             if (atoms[j] == atoms[i])
             {
-                xfree(props);
-                return BadMatch;
+		rc = BadMatch;
+		goto out;
             }
-	pProp = FindProperty(pWin, atoms[i]);
-	if (!pProp) {
-	    xfree(props);
-	    return BadMatch;
-	}
-	rc = XaceHookPropertyAccess(client, pWin, pProp,
-				    DixReadAccess|DixWriteAccess);
-	if (rc != Success) {
-	    xfree(props);
-	    client->errorValue = atoms[i];
-            return rc;
-	}
+
+	rc = dixLookupProperty(&pProp, pWin, atoms[i], client,
+			       DixReadAccess|DixWriteAccess);
+	if (rc != Success)
+	    goto out;
+
         props[i] = pProp;
+	saved[i] = *pProp;
     }
     delta = stuff->nPositions;
 
     /* If the rotation is a complete 360 degrees, then moving the properties
 	around and generating PropertyNotify events should be skipped. */
 
-    if ( (stuff->nAtoms != 0) && (abs(delta) % stuff->nAtoms) != 0 ) 
+    if (abs(delta) % stuff->nAtoms)
     {
 	while (delta < 0)                  /* faster if abs value is small */
             delta += stuff->nAtoms;
     	for (i = 0; i < stuff->nAtoms; i++)
  	{
-	    deliverPropertyNotifyEvent(pWin, PropertyNewValue,
-				       props[i]->propertyName);
- 
-            props[i]->propertyName = atoms[(i + delta) % stuff->nAtoms];
+	    j = (i + delta) % stuff->nAtoms;
+	    deliverPropertyNotifyEvent(pWin, PropertyNewValue, atoms[i]);
+
+	    /* Preserve name and devPrivates */
+	    props[j]->type = saved[i].type;
+	    props[j]->format = saved[i].format;
+	    props[j]->size = saved[i].size;
+	    props[j]->data = saved[i].data;
 	}
     }
+out:
+    xfree(saved);
     xfree(props);
-    return Success;
+    return rc;
 }
 
 int 
@@ -253,9 +261,9 @@ dixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
     totalSize = len * sizeInBytes;
 
     /* first see if property already exists */
-    pProp = FindProperty(pWin, property);
+    rc = dixLookupProperty(&pProp, pWin, property, pClient, DixWriteAccess);
 
-    if (!pProp)   /* just add to list */
+    if (rc == BadMatch)   /* just add to list */
     {
 	if (!pWin->optional && !MakeWindowOptional (pWin))
 	    return(BadAlloc);
@@ -287,13 +295,8 @@ dixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
         pProp->next = pWin->optional->userProps;
         pWin->optional->userProps = pProp;
     }
-    else
+    else if (rc == Success)
     {
-	rc = XaceHookPropertyAccess(pClient, pWin, pProp, DixWriteAccess);
-	if (rc != Success) {
-	    pClient->errorValue = property;
-	    return rc;
-	}
 	/* To append or prepend to a property the request format and type
 		must match those of the already defined property.  The
 		existing format and type are irrelevant when using the mode
@@ -347,6 +350,8 @@ dixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
             pProp->size += len;
 	}
     }
+    else
+	return rc;
 
     if (sendevent)
 	deliverPropertyNotifyEvent(pWin, PropertyNewValue, pProp->propertyName);
@@ -369,37 +374,29 @@ DeleteProperty(ClientPtr client, WindowPtr pWin, Atom propName)
     PropertyPtr pProp, prevProp;
     int rc;
 
-    if (!(pProp = wUserProps (pWin)))
-	return(Success);
-    prevProp = (PropertyPtr)NULL;
-    while (pProp)
-    {
-	if (pProp->propertyName == propName)
-	    break;
-        prevProp = pProp;
-	pProp = pProp->next;
-    }
-    if (pProp) 
-    {		    
-	rc = XaceHookPropertyAccess(client, pWin, pProp, DixDestroyAccess);
-	if (rc != Success)
-	    return rc;
+    rc = dixLookupProperty(&pProp, pWin, propName, client, DixDestroyAccess);
+    if (rc == BadMatch)
+	return Success; /* Succeed if property does not exist */
 
-        if (prevProp == (PropertyPtr)NULL)      /* takes care of head */
-        {
+    if (rc == Success) {
+	if (pWin->optional->userProps == pProp) {
+	    /* Takes care of head */
             if (!(pWin->optional->userProps = pProp->next))
 		CheckWindowOptionalNeed (pWin);
-        }
-	else
-        {
-            prevProp->next = pProp->next;
-        }
+	} else {
+	    /* Need to traverse to find the previous element */
+	    prevProp = pWin->optional->userProps;
+	    while (prevProp->next != pProp)
+		prevProp = prevProp->next;
+	    prevProp->next = pProp->next;
+	}
+
 	deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName);
 	dixFreePrivates(pProp->devPrivates);
 	xfree(pProp->data);
         xfree(pProp);
     }
-    return(Success);
+    return rc;
 }
 
 void
@@ -453,15 +450,16 @@ ProcGetProperty(ClientPtr client)
     int rc;
     WindowPtr pWin;
     xGetPropertyReply reply;
-    Mask access_mode = DixGetPropAccess;
+    Mask win_mode = DixGetPropAccess, prop_mode = DixReadAccess;
     REQUEST(xGetPropertyReq);
 
     REQUEST_SIZE_MATCH(xGetPropertyReq);
     if (stuff->delete) {
 	UpdateCurrentTime();
-	access_mode |= DixSetPropAccess;
+	win_mode |= DixSetPropAccess;
+	prop_mode |= DixDestroyAccess;
     }
-    rc = dixLookupWindow(&pWin, stuff->window, client, access_mode);
+    rc = dixLookupWindow(&pWin, stuff->window, client, win_mode);
     if (rc != Success)
 	return rc;
 
@@ -481,30 +479,14 @@ ProcGetProperty(ClientPtr client)
 	return(BadAtom);
     }
 
-    pProp = wUserProps (pWin);
-    prevProp = (PropertyPtr)NULL;
-    while (pProp)
-    {
-	if (pProp->propertyName == stuff->property) 
-	    break;
-	prevProp = pProp;
-	pProp = pProp->next;
-    }
-
     reply.type = X_Reply;
     reply.sequenceNumber = client->sequence;
-    if (!pProp) 
-	return NullPropertyReply(client, None, 0, &reply);
 
-    access_mode = DixReadAccess;
-    if (stuff->delete)
-	access_mode |= DixDestroyAccess;
-
-    rc = XaceHookPropertyAccess(client, pWin, pProp, access_mode);
-    if (rc != Success) {
-	client->errorValue = stuff->property;
+    rc = dixLookupProperty(&pProp, pWin, stuff->property, client, prop_mode);
+    if (rc == BadMatch)
+	return NullPropertyReply(client, None, 0, &reply);
+    else if (rc != Success)
 	return rc;
-    }
 
     /* If the request type and actual type don't match. Return the
     property information, but not the data. */
@@ -560,15 +542,20 @@ ProcGetProperty(ClientPtr client)
 				 (char *)pProp->data + ind);
     }
 
-    if (stuff->delete && (reply.bytesAfter == 0))
-    { /* delete the Property */
-	if (prevProp == (PropertyPtr)NULL) /* takes care of head */
-	{
-	    if (!(pWin->optional->userProps = pProp->next))
+    if (stuff->delete && (reply.bytesAfter == 0)) {
+	/* Delete the Property */
+	if (pWin->optional->userProps == pProp) {
+	    /* Takes care of head */
+            if (!(pWin->optional->userProps = pProp->next))
 		CheckWindowOptionalNeed (pWin);
-	}
-	else
+	} else {
+	    /* Need to traverse to find the previous element */
+	    prevProp = pWin->optional->userProps;
+	    while (prevProp->next != pProp)
+		prevProp = prevProp->next;
 	    prevProp->next = pProp->next;
+	}
+
 	dixFreePrivates(pProp->devPrivates);
 	xfree(pProp->data);
 	xfree(pProp);
@@ -583,7 +570,7 @@ ProcListProperties(ClientPtr client)
     xListPropertiesReply xlpr;
     int	rc, numProps = 0;
     WindowPtr pWin;
-    PropertyPtr pProp;
+    PropertyPtr pProp, realProp;
     REQUEST(xResourceReq);
 
     REQUEST_SIZE_MATCH(xResourceReq);
@@ -591,34 +578,34 @@ ProcListProperties(ClientPtr client)
     if (rc != Success)
         return rc;
 
-    pProp = wUserProps (pWin);
-    while (pProp)
-    {        
-        pProp = pProp->next;
+    for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
 	numProps++;
+
+    if (numProps && !(pAtoms = (Atom *)xalloc(numProps * sizeof(Atom))))
+	return BadAlloc;
+
+    numProps = 0;
+    temppAtoms = pAtoms;
+    for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) {
+	realProp = pProp;
+	rc = XaceHookPropertyAccess(client, pWin, pProp, DixGetAttrAccess);
+	if (rc == Success && realProp == pProp) {
+	    *temppAtoms++ = pProp->propertyName;
+	    numProps++;
+	}
     }
-    if (numProps)
-        if(!(pAtoms = (Atom *)xalloc(numProps * sizeof(Atom))))
-            return(BadAlloc);
 
     xlpr.type = X_Reply;
     xlpr.nProperties = numProps;
     xlpr.length = (numProps * sizeof(Atom)) >> 2;
     xlpr.sequenceNumber = client->sequence;
-    pProp = wUserProps (pWin);
-    temppAtoms = pAtoms;
-    while (pProp)
-    {
-	*temppAtoms++ = pProp->propertyName;
-	pProp = pProp->next;
-    }
     WriteReplyToClient(client, sizeof(xGenericReply), &xlpr);
     if (numProps)
     {
         client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
         WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms);
-        xfree(pAtoms);
     }
+    xfree(pAtoms);
     return(client->noClientException);
 }
 
diff --git a/hw/xfree86/loader/dixsym.c b/hw/xfree86/loader/dixsym.c
index 49c7d27..e6c37fe 100644
--- a/hw/xfree86/loader/dixsym.c
+++ b/hw/xfree86/loader/dixsym.c
@@ -193,6 +193,7 @@ _X_HIDDEN void *dixLookupTab[] = {
     SYMFUNC(XineramaGetCursorScreen)
 #endif
     /* property.c */
+    SYMFUNC(dixLookupProperty)
     SYMFUNC(ChangeWindowProperty)
     SYMFUNC(dixChangeWindowProperty)
     /* extension.c */
diff --git a/include/property.h b/include/property.h
index ba7d226..1207e81 100644
--- a/include/property.h
+++ b/include/property.h
@@ -52,6 +52,13 @@ SOFTWARE.
 
 typedef struct _Property *PropertyPtr;
 
+extern int dixLookupProperty(
+    PropertyPtr * /*result*/,
+    WindowPtr /*pWin*/,
+    Atom /*proprty*/,
+    ClientPtr /*pClient*/,
+    Mask /*access_mode*/);
+
 extern int dixChangeWindowProperty(
     ClientPtr /*pClient*/,
     WindowPtr /*pWin*/,


More information about the xorg-commit mailing list