14642e01fSmrg/************************************************************ 24642e01fSmrg 34642e01fSmrgCopyright 1987, 1989, 1998 The Open Group 44642e01fSmrg 54642e01fSmrgPermission to use, copy, modify, distribute, and sell this software and its 64642e01fSmrgdocumentation for any purpose is hereby granted without fee, provided that 74642e01fSmrgthe above copyright notice appear in all copies and that both that 84642e01fSmrgcopyright notice and this permission notice appear in supporting 94642e01fSmrgdocumentation. 104642e01fSmrg 114642e01fSmrgThe above copyright notice and this permission notice shall be included in 124642e01fSmrgall copies or substantial portions of the Software. 134642e01fSmrg 144642e01fSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 154642e01fSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 164642e01fSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 174642e01fSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 184642e01fSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 194642e01fSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 204642e01fSmrg 214642e01fSmrgExcept as contained in this notice, the name of The Open Group shall not be 224642e01fSmrgused in advertising or otherwise to promote the sale, use or other dealings 234642e01fSmrgin this Software without prior written authorization from The Open Group. 244642e01fSmrg 254642e01fSmrgCopyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. 264642e01fSmrg 274642e01fSmrg All Rights Reserved 284642e01fSmrg 2935c4bbdfSmrgPermission to use, copy, modify, and distribute this software and its 3035c4bbdfSmrgdocumentation for any purpose and without fee is hereby granted, 314642e01fSmrgprovided that the above copyright notice appear in all copies and that 3235c4bbdfSmrgboth that copyright notice and this permission notice appear in 334642e01fSmrgsupporting documentation, and that the name of Digital not be 344642e01fSmrgused in advertising or publicity pertaining to distribution of the 3535c4bbdfSmrgsoftware without specific, written prior permission. 364642e01fSmrg 374642e01fSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 384642e01fSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 394642e01fSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 404642e01fSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 414642e01fSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 424642e01fSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 434642e01fSmrgSOFTWARE. 444642e01fSmrg 454642e01fSmrg********************************************************/ 464642e01fSmrg 474642e01fSmrg#ifdef HAVE_DIX_CONFIG_H 484642e01fSmrg#include <dix-config.h> 494642e01fSmrg#endif 504642e01fSmrg 514642e01fSmrg#include "windowstr.h" 524642e01fSmrg#include "dixstruct.h" 534642e01fSmrg#include "dispatch.h" 544642e01fSmrg#include "selection.h" 554642e01fSmrg#include "xace.h" 564642e01fSmrg 574642e01fSmrg/***************************************************************** 584642e01fSmrg * Selection Stuff 594642e01fSmrg * 604642e01fSmrg * dixLookupSelection 614642e01fSmrg * 624642e01fSmrg * Selections are global to the server. The list of selections should 634642e01fSmrg * not be traversed directly. Instead, use the functions listed above. 644642e01fSmrg * 654642e01fSmrg *****************************************************************/ 664642e01fSmrg 676747b715SmrgSelection *CurrentSelections; 684642e01fSmrgCallbackListPtr SelectionCallback; 694642e01fSmrg 706747b715Smrgint 7135c4bbdfSmrgdixLookupSelection(Selection ** result, Atom selectionName, 7235c4bbdfSmrg ClientPtr client, Mask access_mode) 734642e01fSmrg{ 744642e01fSmrg Selection *pSel; 754642e01fSmrg int rc = BadMatch; 7635c4bbdfSmrg 774642e01fSmrg client->errorValue = selectionName; 784642e01fSmrg 794642e01fSmrg for (pSel = CurrentSelections; pSel; pSel = pSel->next) 8035c4bbdfSmrg if (pSel->selection == selectionName) 8135c4bbdfSmrg break; 824642e01fSmrg 834642e01fSmrg if (pSel) 8435c4bbdfSmrg rc = XaceHookSelectionAccess(client, &pSel, access_mode); 854642e01fSmrg *result = pSel; 864642e01fSmrg return rc; 874642e01fSmrg} 884642e01fSmrg 894642e01fSmrgvoid 904642e01fSmrgInitSelections(void) 914642e01fSmrg{ 924642e01fSmrg Selection *pSel, *pNextSel; 934642e01fSmrg 944642e01fSmrg pSel = CurrentSelections; 954642e01fSmrg while (pSel) { 9635c4bbdfSmrg pNextSel = pSel->next; 9735c4bbdfSmrg dixFreeObjectWithPrivates(pSel, PRIVATE_SELECTION); 9835c4bbdfSmrg pSel = pNextSel; 994642e01fSmrg } 1004642e01fSmrg 1014642e01fSmrg CurrentSelections = NULL; 1024642e01fSmrg} 1034642e01fSmrg 1044642e01fSmrgstatic _X_INLINE void 10535c4bbdfSmrgCallSelectionCallback(Selection * pSel, ClientPtr client, 10635c4bbdfSmrg SelectionCallbackKind kind) 1074642e01fSmrg{ 1084642e01fSmrg SelectionInfoRec info = { pSel, client, kind }; 1094642e01fSmrg CallCallbacks(&SelectionCallback, &info); 1104642e01fSmrg} 1114642e01fSmrg 1124642e01fSmrgvoid 1134642e01fSmrgDeleteWindowFromAnySelections(WindowPtr pWin) 1144642e01fSmrg{ 1154642e01fSmrg Selection *pSel; 1164642e01fSmrg 1174642e01fSmrg for (pSel = CurrentSelections; pSel; pSel = pSel->next) 1184642e01fSmrg if (pSel->pWin == pWin) { 11935c4bbdfSmrg CallSelectionCallback(pSel, NULL, SelectionWindowDestroy); 1204642e01fSmrg 12135c4bbdfSmrg pSel->pWin = (WindowPtr) NULL; 1224642e01fSmrg pSel->window = None; 12335c4bbdfSmrg pSel->client = NullClient; 12435c4bbdfSmrg } 1254642e01fSmrg} 1264642e01fSmrg 1274642e01fSmrgvoid 1284642e01fSmrgDeleteClientFromAnySelections(ClientPtr client) 1294642e01fSmrg{ 1304642e01fSmrg Selection *pSel; 1314642e01fSmrg 1324642e01fSmrg for (pSel = CurrentSelections; pSel; pSel = pSel->next) 1334642e01fSmrg if (pSel->client == client) { 13435c4bbdfSmrg CallSelectionCallback(pSel, NULL, SelectionClientClose); 1354642e01fSmrg 13635c4bbdfSmrg pSel->pWin = (WindowPtr) NULL; 1374642e01fSmrg pSel->window = None; 13835c4bbdfSmrg pSel->client = NullClient; 13935c4bbdfSmrg } 1404642e01fSmrg} 1414642e01fSmrg 1424642e01fSmrgint 1434642e01fSmrgProcSetSelectionOwner(ClientPtr client) 1444642e01fSmrg{ 1454642e01fSmrg WindowPtr pWin = NULL; 1464642e01fSmrg TimeStamp time; 1474642e01fSmrg Selection *pSel; 1484642e01fSmrg int rc; 1494642e01fSmrg 1504642e01fSmrg REQUEST(xSetSelectionOwnerReq); 1514642e01fSmrg REQUEST_SIZE_MATCH(xSetSelectionOwnerReq); 1524642e01fSmrg 1534642e01fSmrg UpdateCurrentTime(); 1544642e01fSmrg time = ClientTimeToServerTime(stuff->time); 1554642e01fSmrg 1564642e01fSmrg /* If the client's time stamp is in the future relative to the server's 15735c4bbdfSmrg time stamp, do not set the selection, just return success. */ 1584642e01fSmrg if (CompareTimeStamps(time, currentTime) == LATER) 15935c4bbdfSmrg return Success; 1604642e01fSmrg 1614642e01fSmrg if (stuff->window != None) { 16235c4bbdfSmrg rc = dixLookupWindow(&pWin, stuff->window, client, DixSetAttrAccess); 1634642e01fSmrg if (rc != Success) 1644642e01fSmrg return rc; 1654642e01fSmrg } 1664642e01fSmrg if (!ValidAtom(stuff->selection)) { 16735c4bbdfSmrg client->errorValue = stuff->selection; 1684642e01fSmrg return BadAtom; 1694642e01fSmrg } 1704642e01fSmrg 1714642e01fSmrg /* 1724642e01fSmrg * First, see if the selection is already set... 1734642e01fSmrg */ 1744642e01fSmrg rc = dixLookupSelection(&pSel, stuff->selection, client, DixSetAttrAccess); 1754642e01fSmrg 1764642e01fSmrg if (rc == Success) { 17735c4bbdfSmrg /* If the timestamp in client's request is in the past relative 17835c4bbdfSmrg to the time stamp indicating the last time the owner of the 17935c4bbdfSmrg selection was set, do not set the selection, just return 18035c4bbdfSmrg success. */ 18135c4bbdfSmrg if (CompareTimeStamps(time, pSel->lastTimeChanged) == EARLIER) 18235c4bbdfSmrg return Success; 18335c4bbdfSmrg if (pSel->client && (!pWin || (pSel->client != client))) { 18435c4bbdfSmrg xEvent event = { 18535c4bbdfSmrg .u.selectionClear.time = time.milliseconds, 18635c4bbdfSmrg .u.selectionClear.window = pSel->window, 18735c4bbdfSmrg .u.selectionClear.atom = pSel->selection 18835c4bbdfSmrg }; 18935c4bbdfSmrg event.u.u.type = SelectionClear; 19035c4bbdfSmrg WriteEventsToClient(pSel->client, 1, &event); 19135c4bbdfSmrg } 1924642e01fSmrg } 19335c4bbdfSmrg else if (rc == BadMatch) { 19435c4bbdfSmrg /* 19535c4bbdfSmrg * It doesn't exist, so add it... 19635c4bbdfSmrg */ 19735c4bbdfSmrg pSel = dixAllocateObjectWithPrivates(Selection, PRIVATE_SELECTION); 19835c4bbdfSmrg if (!pSel) 19935c4bbdfSmrg return BadAlloc; 20035c4bbdfSmrg 20135c4bbdfSmrg pSel->selection = stuff->selection; 20235c4bbdfSmrg 20335c4bbdfSmrg /* security creation/labeling check */ 20435c4bbdfSmrg rc = XaceHookSelectionAccess(client, &pSel, 20535c4bbdfSmrg DixCreateAccess | DixSetAttrAccess); 20635c4bbdfSmrg if (rc != Success) { 20735c4bbdfSmrg free(pSel); 20835c4bbdfSmrg return rc; 20935c4bbdfSmrg } 21035c4bbdfSmrg 21135c4bbdfSmrg pSel->next = CurrentSelections; 21235c4bbdfSmrg CurrentSelections = pSel; 2134642e01fSmrg } 2144642e01fSmrg else 21535c4bbdfSmrg return rc; 2164642e01fSmrg 2174642e01fSmrg pSel->lastTimeChanged = time; 2184642e01fSmrg pSel->window = stuff->window; 2194642e01fSmrg pSel->pWin = pWin; 2204642e01fSmrg pSel->client = (pWin ? client : NullClient); 2214642e01fSmrg 2224642e01fSmrg CallSelectionCallback(pSel, client, SelectionSetOwner); 2236747b715Smrg return Success; 2244642e01fSmrg} 2254642e01fSmrg 2264642e01fSmrgint 2274642e01fSmrgProcGetSelectionOwner(ClientPtr client) 2284642e01fSmrg{ 2294642e01fSmrg int rc; 2304642e01fSmrg Selection *pSel; 2314642e01fSmrg xGetSelectionOwnerReply reply; 2324642e01fSmrg 2334642e01fSmrg REQUEST(xResourceReq); 2344642e01fSmrg REQUEST_SIZE_MATCH(xResourceReq); 2354642e01fSmrg 2364642e01fSmrg if (!ValidAtom(stuff->id)) { 23735c4bbdfSmrg client->errorValue = stuff->id; 2384642e01fSmrg return BadAtom; 2394642e01fSmrg } 2404642e01fSmrg 24135c4bbdfSmrg reply = (xGetSelectionOwnerReply) { 24235c4bbdfSmrg .type = X_Reply, 24335c4bbdfSmrg .sequenceNumber = client->sequence, 24435c4bbdfSmrg .length = 0, 24535c4bbdfSmrg }; 2464642e01fSmrg 2474642e01fSmrg rc = dixLookupSelection(&pSel, stuff->id, client, DixGetAttrAccess); 2484642e01fSmrg if (rc == Success) 24935c4bbdfSmrg reply.owner = pSel->window; 2504642e01fSmrg else if (rc == BadMatch) 25135c4bbdfSmrg reply.owner = None; 2524642e01fSmrg else 25335c4bbdfSmrg return rc; 2544642e01fSmrg 2554642e01fSmrg WriteReplyToClient(client, sizeof(xGetSelectionOwnerReply), &reply); 2566747b715Smrg return Success; 2574642e01fSmrg} 2584642e01fSmrg 2594642e01fSmrgint 2604642e01fSmrgProcConvertSelection(ClientPtr client) 2614642e01fSmrg{ 2624642e01fSmrg Bool paramsOkay; 2634642e01fSmrg xEvent event; 2644642e01fSmrg WindowPtr pWin; 2654642e01fSmrg Selection *pSel; 2664642e01fSmrg int rc; 2674642e01fSmrg 2684642e01fSmrg REQUEST(xConvertSelectionReq); 2694642e01fSmrg REQUEST_SIZE_MATCH(xConvertSelectionReq); 2704642e01fSmrg 2714642e01fSmrg rc = dixLookupWindow(&pWin, stuff->requestor, client, DixSetAttrAccess); 2724642e01fSmrg if (rc != Success) 2734642e01fSmrg return rc; 2744642e01fSmrg 2754642e01fSmrg paramsOkay = ValidAtom(stuff->selection) && ValidAtom(stuff->target); 2764642e01fSmrg paramsOkay &= (stuff->property == None) || ValidAtom(stuff->property); 2774642e01fSmrg if (!paramsOkay) { 27835c4bbdfSmrg client->errorValue = stuff->property; 2794642e01fSmrg return BadAtom; 2804642e01fSmrg } 2814642e01fSmrg 2821b5d61b8Smrg if (stuff->time == CurrentTime) 2831b5d61b8Smrg UpdateCurrentTime(); 2841b5d61b8Smrg 2854642e01fSmrg rc = dixLookupSelection(&pSel, stuff->selection, client, DixReadAccess); 2864642e01fSmrg 2876747b715Smrg memset(&event, 0, sizeof(xEvent)); 2884642e01fSmrg if (rc != Success && rc != BadMatch) 28935c4bbdfSmrg return rc; 2904642e01fSmrg else if (rc == Success && pSel->window != None) { 29135c4bbdfSmrg event.u.u.type = SelectionRequest; 29235c4bbdfSmrg event.u.selectionRequest.owner = pSel->window; 29335c4bbdfSmrg event.u.selectionRequest.time = stuff->time; 29435c4bbdfSmrg event.u.selectionRequest.requestor = stuff->requestor; 29535c4bbdfSmrg event.u.selectionRequest.selection = stuff->selection; 29635c4bbdfSmrg event.u.selectionRequest.target = stuff->target; 29735c4bbdfSmrg event.u.selectionRequest.property = stuff->property; 29835c4bbdfSmrg if (pSel->client && pSel->client != serverClient && 29935c4bbdfSmrg !pSel->client->clientGone) { 30035c4bbdfSmrg WriteEventsToClient(pSel->client, 1, &event); 30135c4bbdfSmrg return Success; 30235c4bbdfSmrg } 3034642e01fSmrg } 3044642e01fSmrg 3054642e01fSmrg event.u.u.type = SelectionNotify; 3064642e01fSmrg event.u.selectionNotify.time = stuff->time; 3074642e01fSmrg event.u.selectionNotify.requestor = stuff->requestor; 3084642e01fSmrg event.u.selectionNotify.selection = stuff->selection; 3094642e01fSmrg event.u.selectionNotify.target = stuff->target; 3104642e01fSmrg event.u.selectionNotify.property = None; 3116747b715Smrg WriteEventsToClient(client, 1, &event); 3126747b715Smrg return Success; 3134642e01fSmrg} 314