2013-11-30 13:51:10 +00:00
|
|
|
/************************************************************
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
********************************************************/
|
|
|
|
|
|
|
|
/* The panoramix components contained the following notice */
|
|
|
|
/*****************************************************************
|
|
|
|
|
|
|
|
Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
copies of the Software.
|
|
|
|
|
|
|
|
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
|
|
|
|
DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
|
|
|
|
BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL 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 Digital Equipment Corporation
|
|
|
|
shall not be used in advertising or otherwise to promote the sale, use or other
|
|
|
|
dealings in this Software without prior written authorization from Digital
|
|
|
|
Equipment Corporation.
|
|
|
|
|
|
|
|
******************************************************************/
|
|
|
|
|
|
|
|
#ifdef HAVE_DIX_CONFIG_H
|
|
|
|
#include <dix-config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#include "windowstr.h"
|
|
|
|
#include <X11/fonts/fontstruct.h>
|
|
|
|
#include "dixfontstr.h"
|
|
|
|
#include "gcstruct.h"
|
|
|
|
#include "selection.h"
|
|
|
|
#include "colormapst.h"
|
|
|
|
#include "cursorstr.h"
|
|
|
|
#include "scrnintstr.h"
|
|
|
|
#include "opaque.h"
|
|
|
|
#include "input.h"
|
|
|
|
#include "servermd.h"
|
|
|
|
#include "extnsionst.h"
|
|
|
|
#include "dixfont.h"
|
|
|
|
#include "dispatch.h"
|
|
|
|
#include "swaprep.h"
|
|
|
|
#include "swapreq.h"
|
|
|
|
|
|
|
|
#define mskcnt ((MAXCLIENTS + 31) / 32)
|
|
|
|
#define BITMASK(i) (1U << ((i) & 31))
|
|
|
|
#define MASKIDX(i) ((i) >> 5)
|
|
|
|
#define MASKWORD(buf, i) buf[MASKIDX(i)]
|
|
|
|
#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i)
|
|
|
|
#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
|
|
|
|
#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
|
|
|
|
|
|
|
|
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
|
|
|
|
#define GrabKickout 2
|
|
|
|
static int grabState = GrabNone;
|
|
|
|
|
|
|
|
static long grabWaiters[mskcnt];
|
|
|
|
|
|
|
|
_X_EXPORT CallbackListPtr ServerGrabCallback = NULL;
|
|
|
|
|
|
|
|
HWEventQueuePtr checkForInput[2];
|
|
|
|
|
|
|
|
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 */
|
|
|
|
|
|
|
|
_X_EXPORT CallbackListPtr ClientStateCallback;
|
|
|
|
|
|
|
|
/* dispatchException & isItTimeToYield must be declared volatile since they
|
|
|
|
* are modified by signal handlers - otherwise optimizer may assume it doesn't
|
|
|
|
* need to actually check value in memory when used and may miss changes from
|
|
|
|
* signal handlers.
|
|
|
|
*/
|
|
|
|
_X_EXPORT volatile char dispatchException = 0;
|
|
|
|
|
|
|
|
_X_EXPORT volatile char isItTimeToYield;
|
|
|
|
|
|
|
|
/* Various of the DIX function interfaces were not designed to allow
|
|
|
|
* the client->errorValue to be set on BadValue and other errors.
|
|
|
|
* Rather than changing interfaces and breaking untold code we introduce
|
|
|
|
* a new global that dispatch can use.
|
|
|
|
*/
|
|
|
|
XID clientErrorValue; /* XXX this is a kludge */
|
|
|
|
|
|
|
|
#define SAME_SCREENS(a, b) (\
|
|
|
|
(a.pScreen == b.pScreen))
|
|
|
|
|
|
|
|
_X_EXPORT void
|
|
|
|
SetInputCheck(HWEventQueuePtr c0, HWEventQueuePtr c1)
|
|
|
|
{
|
|
|
|
checkForInput[0] = c0;
|
|
|
|
checkForInput[1] = c1;
|
|
|
|
}
|
|
|
|
|
|
|
|
_X_EXPORT void
|
|
|
|
UpdateCurrentTime()
|
|
|
|
{
|
|
|
|
TimeStamp systime;
|
|
|
|
|
|
|
|
/* To avoid time running backwards, we must call GetTimeInMillis before
|
|
|
|
* calling ProcessInputEvents.
|
|
|
|
*/
|
|
|
|
systime.months = currentTime.months;
|
|
|
|
systime.milliseconds = GetTimeInMillis();
|
|
|
|
if (systime.milliseconds < currentTime.milliseconds)
|
|
|
|
systime.months++;
|
|
|
|
if (*checkForInput[0] != *checkForInput[1])
|
|
|
|
ProcessInputEvents();
|
|
|
|
if (CompareTimeStamps(systime, currentTime) == LATER)
|
|
|
|
currentTime = systime;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Like UpdateCurrentTime, but can't call ProcessInputEvents */
|
|
|
|
_X_EXPORT void
|
|
|
|
UpdateCurrentTimeIf()
|
|
|
|
{
|
|
|
|
TimeStamp systime;
|
|
|
|
|
|
|
|
systime.months = currentTime.months;
|
|
|
|
systime.milliseconds = GetTimeInMillis();
|
|
|
|
if (systime.milliseconds < currentTime.milliseconds)
|
|
|
|
systime.months++;
|
|
|
|
if (*checkForInput[0] == *checkForInput[1])
|
|
|
|
currentTime = systime;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
InitSelections()
|
|
|
|
{
|
|
|
|
if (CurrentSelections)
|
|
|
|
free(CurrentSelections);
|
|
|
|
CurrentSelections = (Selection *) NULL;
|
|
|
|
NumCurrentSelections = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FlushClientCaches(XID id)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
ClientPtr client;
|
|
|
|
|
|
|
|
client = clients[CLIENT_ID(id)];
|
|
|
|
if (client == NullClient)
|
|
|
|
return;
|
|
|
|
for (i = 0; i < currentMaxClients; i++) {
|
|
|
|
client = clients[i];
|
|
|
|
if (client != NullClient) {
|
|
|
|
if (client->lastDrawableID == id) {
|
|
|
|
client->lastDrawableID = WindowTable[0]->drawable.id;
|
|
|
|
client->lastDrawable = (DrawablePtr) WindowTable[0];
|
|
|
|
}
|
|
|
|
else if (client->lastGCID == id) {
|
|
|
|
client->lastGCID = INVALID;
|
|
|
|
client->lastGC = (GCPtr) NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef SMART_SCHEDULE
|
|
|
|
|
|
|
|
#undef SMART_DEBUG
|
|
|
|
|
|
|
|
#define SMART_SCHEDULE_DEFAULT_INTERVAL 7 /* ms */
|
|
|
|
#define SMART_SCHEDULE_MAX_SLICE 20 /* ms */
|
|
|
|
|
|
|
|
Bool SmartScheduleDisable = FALSE;
|
|
|
|
|
|
|
|
long SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL;
|
|
|
|
|
|
|
|
long SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL;
|
|
|
|
|
|
|
|
long SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE;
|
|
|
|
|
|
|
|
long SmartScheduleTime;
|
|
|
|
|
|
|
|
ClientPtr SmartLastClient;
|
|
|
|
|
|
|
|
int SmartLastIndex[SMART_MAX_PRIORITY - SMART_MIN_PRIORITY + 1];
|
|
|
|
|
|
|
|
int SmartScheduleClient(int *clientReady, int nready);
|
|
|
|
|
|
|
|
#ifdef SMART_DEBUG
|
|
|
|
long SmartLastPrint;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void Dispatch(void);
|
|
|
|
|
|
|
|
int
|
|
|
|
SmartScheduleClient(int *clientReady, int nready)
|
|
|
|
{
|
|
|
|
ClientPtr pClient;
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
int client;
|
|
|
|
|
|
|
|
int bestPrio, best = 0;
|
|
|
|
|
|
|
|
int bestRobin, robin;
|
|
|
|
|
|
|
|
long now = SmartScheduleTime;
|
|
|
|
|
|
|
|
long idle;
|
|
|
|
|
|
|
|
bestPrio = -0x7fffffff;
|
|
|
|
bestRobin = 0;
|
|
|
|
idle = 2 * SmartScheduleSlice;
|
|
|
|
for (i = 0; i < nready; i++) {
|
|
|
|
client = clientReady[i];
|
|
|
|
pClient = clients[client];
|
|
|
|
/* Praise clients which are idle */
|
|
|
|
if ((now - pClient->smart_check_tick) >= idle) {
|
|
|
|
if (pClient->smart_priority < 0)
|
|
|
|
pClient->smart_priority++;
|
|
|
|
}
|
|
|
|
pClient->smart_check_tick = now;
|
|
|
|
|
|
|
|
/* check priority to select best client */
|
|
|
|
robin =
|
|
|
|
(pClient->index -
|
|
|
|
SmartLastIndex[pClient->smart_priority -
|
|
|
|
SMART_MIN_PRIORITY]) & 0xff;
|
|
|
|
if (pClient->smart_priority > bestPrio ||
|
|
|
|
(pClient->smart_priority == bestPrio && robin > bestRobin)) {
|
|
|
|
bestPrio = pClient->smart_priority;
|
|
|
|
bestRobin = robin;
|
|
|
|
best = client;
|
|
|
|
}
|
|
|
|
#ifdef SMART_DEBUG
|
|
|
|
if ((now - SmartLastPrint) >= 5000)
|
|
|
|
fprintf(stderr, " %2d: %3d", client, pClient->smart_priority);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#ifdef SMART_DEBUG
|
|
|
|
if ((now - SmartLastPrint) >= 5000) {
|
|
|
|
fprintf(stderr, " use %2d\n", best);
|
|
|
|
SmartLastPrint = now;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
pClient = clients[best];
|
|
|
|
SmartLastIndex[bestPrio - SMART_MIN_PRIORITY] = pClient->index;
|
|
|
|
/*
|
|
|
|
* Set current client pointer
|
|
|
|
*/
|
|
|
|
if (SmartLastClient != pClient) {
|
|
|
|
pClient->smart_start_tick = now;
|
|
|
|
SmartLastClient = pClient;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Adjust slice
|
|
|
|
*/
|
|
|
|
if (nready == 1) {
|
|
|
|
/*
|
|
|
|
* If it's been a long time since another client
|
|
|
|
* has run, bump the slice up to get maximal
|
|
|
|
* performance from a single client
|
|
|
|
*/
|
|
|
|
if ((now - pClient->smart_start_tick) > 1000 &&
|
|
|
|
SmartScheduleSlice < SmartScheduleMaxSlice) {
|
|
|
|
SmartScheduleSlice += SmartScheduleInterval;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
SmartScheduleSlice = SmartScheduleInterval;
|
|
|
|
}
|
|
|
|
return best;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define MAJOROP ((xReq *)client->requestBuffer)->reqType
|
|
|
|
|
|
|
|
void
|
|
|
|
Dispatch(void)
|
|
|
|
{
|
|
|
|
int *clientReady; /* array of request ready clients */
|
|
|
|
|
|
|
|
int result;
|
|
|
|
|
|
|
|
ClientPtr client;
|
|
|
|
|
|
|
|
int nready;
|
|
|
|
|
|
|
|
HWEventQueuePtr *icheck = checkForInput;
|
|
|
|
|
|
|
|
#ifdef SMART_SCHEDULE
|
|
|
|
long start_tick;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
nextFreeClientID = 1;
|
|
|
|
InitSelections();
|
|
|
|
nClients = 0;
|
|
|
|
|
|
|
|
clientReady = (int *) ALLOCATE_LOCAL(sizeof(int) * MaxClients);
|
|
|
|
if (!clientReady)
|
|
|
|
return;
|
|
|
|
|
|
|
|
while (!dispatchException) {
|
|
|
|
if (*icheck[0] != *icheck[1]) {
|
|
|
|
ProcessInputEvents();
|
|
|
|
FlushIfCriticalOutputPending();
|
|
|
|
}
|
|
|
|
|
|
|
|
nready = WaitForSomething(clientReady);
|
|
|
|
|
|
|
|
#ifdef SMART_SCHEDULE
|
|
|
|
if (nready && !SmartScheduleDisable) {
|
|
|
|
clientReady[0] = SmartScheduleClient(clientReady, nready);
|
|
|
|
nready = 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
/*****************
|
|
|
|
* Handle events in round robin fashion, doing input between
|
|
|
|
* each round
|
|
|
|
*****************/
|
|
|
|
|
|
|
|
while (!dispatchException && (--nready >= 0)) {
|
|
|
|
client = clients[clientReady[nready]];
|
|
|
|
if (!client) {
|
|
|
|
/* KillClient can cause this to happen */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/* GrabServer activation can cause this to be true */
|
|
|
|
if (grabState == GrabKickout) {
|
|
|
|
grabState = GrabActive;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
isItTimeToYield = FALSE;
|
|
|
|
|
|
|
|
requestingClient = client;
|
|
|
|
#ifdef SMART_SCHEDULE
|
|
|
|
start_tick = SmartScheduleTime;
|
|
|
|
#endif
|
|
|
|
while (!isItTimeToYield) {
|
|
|
|
if (*icheck[0] != *icheck[1]) {
|
|
|
|
ProcessInputEvents();
|
|
|
|
FlushIfCriticalOutputPending();
|
|
|
|
}
|
|
|
|
#ifdef SMART_SCHEDULE
|
|
|
|
if (!SmartScheduleDisable &&
|
|
|
|
(SmartScheduleTime - start_tick) >= SmartScheduleSlice) {
|
|
|
|
/* Penalize clients which consume ticks */
|
|
|
|
if (client->smart_priority > SMART_MIN_PRIORITY)
|
|
|
|
client->smart_priority--;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
/* now, finally, deal with client requests */
|
|
|
|
|
|
|
|
result = ReadRequestFromClient(client);
|
|
|
|
if (result <= 0) {
|
|
|
|
if (result < 0)
|
|
|
|
CloseDownClient(client);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
client->sequence++;
|
|
|
|
#ifdef DEBUG
|
|
|
|
if (client->requestLogIndex == MAX_REQUEST_LOG)
|
|
|
|
client->requestLogIndex = 0;
|
|
|
|
client->requestLog[client->requestLogIndex] = MAJOROP;
|
|
|
|
client->requestLogIndex++;
|
|
|
|
#endif
|
|
|
|
if (result > (maxBigRequestSize << 2))
|
|
|
|
result = BadLength;
|
|
|
|
else
|
|
|
|
result = (*client->requestVector[MAJOROP]) (client);
|
|
|
|
|
|
|
|
if (result != Success) {
|
|
|
|
if (client->noClientException != Success)
|
|
|
|
CloseDownClient(client);
|
|
|
|
else
|
|
|
|
SendErrorToClient(client, MAJOROP,
|
|
|
|
MinorOpcodeOfRequest(client),
|
|
|
|
client->errorValue, result);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FlushAllOutput();
|
|
|
|
#ifdef SMART_SCHEDULE
|
|
|
|
client = clients[clientReady[nready]];
|
|
|
|
if (client)
|
|
|
|
client->smart_stop_tick = SmartScheduleTime;
|
|
|
|
#endif
|
|
|
|
requestingClient = NULL;
|
|
|
|
}
|
|
|
|
dispatchException &= ~DE_PRIORITYCHANGE;
|
|
|
|
}
|
|
|
|
KillAllClients();
|
|
|
|
DEALLOCATE_LOCAL(clientReady);
|
|
|
|
dispatchException &= ~DE_RESET;
|
|
|
|
ResetOsBuffers();
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef MAJOROP
|
|
|
|
|
|
|
|
_X_EXPORT int
|
|
|
|
ProcBadRequest(ClientPtr client)
|
|
|
|
{
|
|
|
|
return (BadRequest);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ProcCreateWindow(ClientPtr client)
|
|
|
|
{
|
|
|
|
WindowPtr pParent, pWin;
|
|
|
|
|
|
|
|
REQUEST(xCreateWindowReq);
|
|
|
|
int result;
|
|
|
|
|
|
|
|
int len;
|
|
|
|
|
|
|
|
REQUEST_AT_LEAST_SIZE(xCreateWindowReq);
|
|
|
|
|
|
|
|
LEGAL_NEW_RESOURCE(stuff->wid, client);
|
|
|
|
if (!(pParent = (WindowPtr) SecurityLookupWindow(stuff->parent, client,
|
|
|
|
SecurityWriteAccess)))
|
|
|
|
return BadWindow;
|
|
|
|
len = client->req_len - (sizeof(xCreateWindowReq) >> 2);
|
|
|
|
if (Ones(stuff->mask) != len)
|
|
|
|
return BadLength;
|
|
|
|
if (!stuff->width || !stuff->height) {
|
|
|
|
client->errorValue = 0;
|
|
|
|
return BadValue;
|
|
|
|
}
|
|
|
|
pWin = CreateWindow(stuff->wid, pParent, stuff->x,
|
|
|
|
stuff->y, stuff->width, stuff->height,
|
|
|
|
stuff->borderWidth, stuff->class,
|
|
|
|
stuff->mask, (XID *) &stuff[1],
|
|
|
|
(int) stuff->depth, client, stuff->visual, &result);
|
|
|
|
if (pWin) {
|
|
|
|
Mask mask = pWin->eventMask;
|
|
|
|
|
|
|
|
pWin->eventMask = 0; /* subterfuge in case AddResource fails */
|
|
|
|
if (!AddResource(stuff->wid, RT_WINDOW, (pointer) pWin))
|
|
|
|
return BadAlloc;
|
|
|
|
pWin->eventMask = mask;
|
|
|
|
}
|
|
|
|
if (client->noClientException != Success)
|
|
|
|
return (client->noClientException);
|
|
|
|
else
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ProcChangeWindowAttributes(register ClientPtr client)
|
|
|
|
{
|
|
|
|
WindowPtr pWin;
|
|
|
|
|
|
|
|
REQUEST(xChangeWindowAttributesReq);
|
|
|
|
int result;
|
|
|
|
|
|
|
|
int len;
|
|
|
|
|
|
|
|
REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq);
|
|
|
|
pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client,
|
|
|
|
SecurityWriteAccess);
|
|
|
|
if (!pWin)
|
|
|
|
return (BadWindow);
|
|
|
|
len = client->req_len - (sizeof(xChangeWindowAttributesReq) >> 2);
|
|
|
|
if (len != Ones(stuff->valueMask))
|
|
|
|
return BadLength;
|
|
|
|
result = ChangeWindowAttributes(pWin,
|
|
|
|
stuff->valueMask,
|
|
|
|
(XID *) &stuff[1], client);
|
|
|
|
if (client->noClientException != Success)
|
|
|
|
return (client->noClientException);
|
|
|
|
else
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ProcGetWindowAttributes(register ClientPtr client)
|
|
|
|
{
|
|
|
|
WindowPtr pWin;
|
|
|
|
|
|
|
|
REQUEST(xResourceReq);
|
|
|
|
xGetWindowAttributesReply wa = {0};
|
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xResourceReq);
|
|
|
|
pWin = (WindowPtr) SecurityLookupWindow(stuff->id, client,
|
|
|
|
SecurityReadAccess);
|
|
|
|
if (!pWin)
|
|
|
|
return (BadWindow);
|
2015-05-27 12:54:39 +00:00
|
|
|
memset(&wa, 0, sizeof(xGetWindowAttributesReply));
|
2013-11-30 13:51:10 +00:00
|
|
|
GetWindowAttributes(pWin, client, &wa);
|
|
|
|
WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa);
|
|
|
|
return (client->noClientException);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ProcDestroyWindow(register ClientPtr client)
|
|
|
|
{
|
|
|
|
WindowPtr pWin;
|
|
|
|
|
|
|
|
REQUEST(xResourceReq);
|
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xResourceReq);
|
|
|
|
pWin = (WindowPtr) SecurityLookupWindow(stuff->id, client,
|
|
|
|
SecurityDestroyAccess);
|
|
|
|
if (!pWin)
|
|
|
|
return (BadWindow);
|
|
|
|
if (pWin->parent)
|
|
|
|
FreeResource(stuff->id, RT_NONE);
|
|
|
|
return (client->noClientException);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ProcDestroySubwindows(register ClientPtr client)
|
|
|
|
{
|
|
|
|
WindowPtr pWin;
|
|
|
|
|
|
|
|
REQUEST(xResourceReq);
|
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xResourceReq);
|
|
|
|
pWin = (WindowPtr) SecurityLookupWindow(stuff->id, client,
|
|
|
|
SecurityDestroyAccess);
|
|
|
|
if (!pWin)
|
|
|
|
return (BadWindow);
|
|
|
|
DestroySubwindows(pWin, client);
|
|
|
|
return (client->noClientException);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ProcChangeSaveSet(register ClientPtr client)
|
|
|
|
{
|
|
|
|
WindowPtr pWin;
|
|
|
|
|
|
|
|
REQUEST(xChangeSaveSetReq);
|
|
|
|
int result;
|
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xChangeSaveSetReq);
|
|
|
|
pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client,
|
|
|
|
SecurityReadAccess);
|
|
|
|
if (!pWin)
|
|
|
|
return (BadWindow);
|
|
|
|
if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id)))
|
|
|
|
return BadMatch;
|
|
|
|
if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete)) {
|
|
|
|
result = AlterSaveSetForClient(client, pWin, stuff->mode, FALSE, TRUE);
|
|
|
|
if (client->noClientException != Success)
|
|
|
|
return (client->noClientException);
|
|
|
|
else
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
client->errorValue = stuff->mode;
|
|
|
|
return (BadValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ProcReparentWindow(register ClientPtr client)
|
|
|
|
{
|
|
|
|
WindowPtr pWin, pParent;
|
|
|
|
|
|
|
|
REQUEST(xReparentWindowReq);
|
|
|
|
int result;
|
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xReparentWindowReq);
|
|
|
|
pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client,
|
|
|
|
SecurityWriteAccess);
|
|
|
|
if (!pWin)
|
|
|
|
return (BadWindow);
|
|
|
|
pParent = (WindowPtr) SecurityLookupWindow(stuff->parent, client,
|
|
|
|
SecurityWriteAccess);
|
|
|
|
if (!pParent)
|
|
|
|
return (BadWindow);
|
|
|
|
if (SAME_SCREENS(pWin->drawable, pParent->drawable)) {
|
|
|
|
if ((pWin->backgroundState == ParentRelative) &&
|
|
|
|
(pParent->drawable.depth != pWin->drawable.depth))
|
|
|
|
return BadMatch;
|
|
|
|
if ((pWin->drawable.class != InputOnly) &&
|
|
|
|
(pParent->drawable.class == InputOnly))
|
|
|
|
return BadMatch;
|
|
|
|
result = ReparentWindow(pWin, pParent,
|
|
|
|
(short) stuff->x, (short) stuff->y, client);
|
|
|
|
if (client->noClientException != Success)
|
|
|
|
return (client->noClientException);
|
|
|
|
else
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return (BadMatch);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ProcMapWindow(register ClientPtr client)
|
|
|
|
{
|
|
|
|
WindowPtr pWin;
|
|
|
|
|
|
|
|
REQUEST(xResourceReq);
|
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xResourceReq);
|
|
|
|
pWin = (WindowPtr) SecurityLookupWindow(stuff->id, client,
|
|
|
|
SecurityReadAccess);
|
|
|
|
if (!pWin)
|
|
|
|
return (BadWindow);
|
|
|
|
MapWindow(pWin, client);
|
|
|
|
/* update cache to say it is mapped */
|
|
|
|
return (client->noClientException);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ProcMapSubwindows(register ClientPtr client)
|
|
|
|
{
|
|
|
|
WindowPtr pWin;
|
|
|
|
|
|
|
|
REQUEST(xResourceReq);
|
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xResourceReq);
|
|
|
|
pWin = (WindowPtr) SecurityLookupWindow(stuff->id, client,
|
|
|
|
SecurityReadAccess);
|
|
|
|
if (!pWin)
|
|
|
|
return (BadWindow);
|
|
|
|
MapSubwindows(pWin, client);
|
|
|
|
/* update cache to say it is mapped */
|
|
|
|
return (client->noClientException);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ProcUnmapWindow(register ClientPtr client)
|
|
|
|
{
|
|
|
|
WindowPtr pWin;
|
|
|
|
|
|
|
|
REQUEST(xResourceReq);
|
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xResourceReq);
|
|
|
|
pWin = (WindowPtr) SecurityLookupWindow(stuff->id, client,
|
|
|
|
SecurityReadAccess);
|
|
|
|
if (!pWin)
|
|
|
|
return (BadWindow);
|
|
|
|
UnmapWindow(pWin, FALSE);
|
|
|
|
/* update cache to say it is mapped */
|
|
|
|
return (client->noClientException);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ProcUnmapSubwindows(register ClientPtr client)
|
|
|
|
{
|
|
|
|
WindowPtr pWin;
|
|
|
|
|
|
|
|
REQUEST(xResourceReq);
|
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xResourceReq);
|
|
|
|
pWin = (WindowPtr) SecurityLookupWindow(stuff->id, client,
|
|
|
|
SecurityReadAccess);
|
|
|
|
if (!pWin)
|
|
|
|
return (BadWindow);
|
|
|
|
UnmapSubwindows(pWin);
|
|
|
|
return (client->noClientException);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ProcConfigureWindow(register ClientPtr client)
|
|
|
|
{
|
|
|
|
WindowPtr pWin;
|
|
|
|
|
|
|
|
REQUEST(xConfigureWindowReq);
|
|
|
|
int result;
|
|
|
|
|
|
|
|
int len;
|
|
|
|
|
|
|
|
REQUEST_AT_LEAST_SIZE(xConfigureWindowReq);
|
|
|
|
pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client,
|
|
|
|
SecurityWriteAccess);
|
|
|
|
if (!pWin)
|
|
|
|
return (BadWindow);
|
|
|
|
len = client->req_len - (sizeof(xConfigureWindowReq) >> 2);
|
|
|
|
if (Ones((Mask) stuff->mask) != len)
|
|
|
|
return BadLength;
|
|
|
|
result = ConfigureWindow(pWin, (Mask) stuff->mask, (XID *) &stuff[1],
|
|
|
|
client);
|
|
|
|
if (client->noClientException != Success)
|
|
|
|
return (client->noClientException);
|
|
|
|
else
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ProcCirculateWindow(register ClientPtr client)
|
|
|
|
{
|
|
|
|
WindowPtr pWin;
|
|
|
|
|
|
|
|
REQUEST(xCirculateWindowReq);
|
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xCirculateWindowReq);
|
|
|
|
if ((stuff->direction != RaiseLowest) && (stuff->direction != LowerHighest)) {
|
|
|
|
client->errorValue = stuff->direction;
|
|
|
|
return BadValue;
|
|
|
|
}
|
|
|
|
pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client,
|
|
|
|
SecurityWriteAccess);
|
|
|
|
if (!pWin)
|
|
|
|
return (BadWindow);
|
|
|
|
CirculateWindow(pWin, (int) stuff->direction, client);
|
|
|
|
return (client->noClientException);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
GetGeometry(register ClientPtr client, xGetGeometryReply * rep)
|
|
|
|
{
|
|
|
|
DrawablePtr pDraw;
|
|
|
|
|
|
|
|
REQUEST(xResourceReq);
|
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xResourceReq);
|
|
|
|
SECURITY_VERIFY_GEOMETRABLE(pDraw, stuff->id, client, SecurityReadAccess);
|
|
|
|
rep->type = X_Reply;
|
|
|
|
rep->length = 0;
|
|
|
|
rep->sequenceNumber = client->sequence;
|
|
|
|
rep->root = WindowTable[pDraw->pScreen->myNum]->drawable.id;
|
|
|
|
rep->depth = pDraw->depth;
|
|
|
|
rep->width = pDraw->width;
|
|
|
|
rep->height = pDraw->height;
|
|
|
|
|
|
|
|
/* XXX - Because the pixmap-implementation of the multibuffer extension
|
|
|
|
* may have the buffer-id's drawable resource value be a pointer
|
|
|
|
* to the buffer's window instead of the buffer itself
|
|
|
|
* (this happens if the buffer is the displayed buffer),
|
|
|
|
* we also have to check that the id matches before we can
|
|
|
|
* truly say that it is a DRAWABLE_WINDOW.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if ((pDraw->type == UNDRAWABLE_WINDOW) ||
|
|
|
|
((pDraw->type == DRAWABLE_WINDOW) && (stuff->id == pDraw->id))) {
|
|
|
|
WindowPtr pWin = (WindowPtr) pDraw;
|
|
|
|
|
|
|
|
rep->x = pWin->origin.x - wBorderWidth(pWin);
|
|
|
|
rep->y = pWin->origin.y - wBorderWidth(pWin);
|
|
|
|
rep->borderWidth = pWin->borderWidth;
|
|
|
|
}
|
|
|
|
else { /* DRAWABLE_PIXMAP or DRAWABLE_BUFFER */
|
|
|
|
|
|
|
|
rep->x = rep->y = rep->borderWidth = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ProcGetGeometry(register ClientPtr client)
|
|
|
|
{
|
|
|
|
xGetGeometryReply rep = {0};
|
|
|
|
|
|
|
|
int status;
|
|
|
|
|
2015-05-27 12:54:39 +00:00
|
|
|
memset(&rep, 0, sizeof(xGetGeometryReply));
|
2013-11-30 13:51:10 +00:00
|
|
|
if ((status = GetGeometry(client, &rep)) != Success)
|
|
|
|
return status;
|
|
|
|
|
|
|
|
WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep);
|
|
|
|
return (client->noClientException);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ProcQueryTree(register ClientPtr client)
|
|
|
|
{
|
|
|
|
xQueryTreeReply reply;
|
|
|
|
|
|
|
|
int numChildren = 0;
|
|
|
|
|
|
|
|
WindowPtr pChild, pWin, pHead;
|
|
|
|
|
|
|
|
Window *childIDs = (Window *) NULL;
|
|
|
|
|
|
|
|
REQUEST(xResourceReq);
|
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xResourceReq);
|
|
|
|
pWin = (WindowPtr) SecurityLookupWindow(stuff->id, client,
|
|
|
|
SecurityReadAccess);
|
|
|
|
if (!pWin)
|
|
|
|
return (BadWindow);
|
2015-05-27 12:54:39 +00:00
|
|
|
memset(&reply, 0, sizeof(xQueryTreeReply));
|
2013-11-30 13:51:10 +00:00
|
|
|
reply.type = X_Reply;
|
|
|
|
reply.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
|
|
|
|
reply.sequenceNumber = client->sequence;
|
|
|
|
if (pWin->parent)
|
|
|
|
reply.parent = pWin->parent->drawable.id;
|
|
|
|
else
|
|
|
|
reply.parent = (Window) None;
|
|
|
|
pHead = RealChildHead(pWin);
|
|
|
|
for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
|
|
|
|
numChildren++;
|
|
|
|
if (numChildren) {
|
|
|
|
int curChild = 0;
|
|
|
|
|
|
|
|
childIDs = (Window *) ALLOCATE_LOCAL(numChildren * sizeof(Window));
|
|
|
|
if (!childIDs)
|
|
|
|
return BadAlloc;
|
|
|
|
for (pChild = pWin->lastChild; pChild != pHead;
|
|
|
|
pChild = pChild->prevSib)
|
|
|
|
childIDs[curChild++] = pChild->drawable.id;
|
|
|
|
}
|
|
|
|
|
|
|
|
reply.nChildren = numChildren;
|
|
|
|
reply.length = (numChildren * sizeof(Window)) >> 2;
|
|
|
|
|
|
|
|
WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply);
|
|
|
|
if (numChildren) {
|
|
|
|
client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
|
|
|
|
WriteSwappedDataToClient(client, numChildren * sizeof(Window),
|
|
|
|
childIDs);
|
|
|
|
DEALLOCATE_LOCAL(childIDs);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (client->noClientException);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ProcInternAtom(register ClientPtr client)
|
|
|
|
{
|
|
|
|
Atom atom;
|
|
|
|
|
|
|
|
char *tchar;
|
|
|
|
|
|
|
|
REQUEST(xInternAtomReq);
|
|
|
|
|
|
|
|
REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes);
|
|
|
|
if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse)) {
|
|
|
|
client->errorValue = stuff->onlyIfExists;
|
|
|
|
return (BadValue);
|
|
|
|
}
|
|
|
|
tchar = (char *) &stuff[1];
|
|
|
|
atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists);
|
|
|
|
if (atom != BAD_RESOURCE) {
|
|
|
|
xInternAtomReply reply = {0};
|
|
|
|
|
2015-05-27 12:54:39 +00:00
|
|
|
memset(&reply, 0, sizeof(xInternAtomReply));
|
2013-11-30 13:51:10 +00:00
|
|
|
reply.type = X_Reply;
|
|
|
|
reply.length = 0;
|
|
|
|
reply.sequenceNumber = client->sequence;
|
|
|
|
reply.atom = atom;
|
|
|
|
WriteReplyToClient(client, sizeof(xInternAtomReply), &reply);
|
|
|
|
return (client->noClientException);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return (BadAlloc);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ProcGetAtomName(register ClientPtr client)
|
|
|
|
{
|
|
|
|
char *str;
|
|
|
|
|
|
|
|
xGetAtomNameReply reply;
|
|
|
|
|
|
|
|
int len;
|
|
|
|
|
|
|
|
REQUEST(xResourceReq);
|
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xResourceReq);
|
|
|
|
if ((str = NameForAtom(stuff->id))) {
|
|
|
|
len = strlen(str);
|
2015-05-27 12:54:39 +00:00
|
|
|
memset(&reply, 0, sizeof(xGetAtomNameReply));
|
2013-11-30 13:51:10 +00:00
|
|
|
reply.type = X_Reply;
|
|
|
|
reply.length = (len + 3) >> 2;
|
|
|
|
reply.sequenceNumber = client->sequence;
|
|
|
|
reply.nameLength = len;
|
|
|
|
WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply);
|
|
|
|
(void) WriteToClient(client, len, str);
|
|
|
|
return (client->noClientException);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
client->errorValue = stuff->id;
|
|
|
|
return (BadAtom);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
ProcSetSelectionOwner(register ClientPtr client)
|
|
|
|
{
|
|
|
|
WindowPtr pWin;
|
|
|
|
|
|
|
|
TimeStamp time;
|
|
|
|
|
|
|
|
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) {
|
|
|
|
pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client,
|
|
|
|
SecurityReadAccess);
|
|
|
|
if (!pWin)
|
|
|
|
return (BadWindow);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pWin = (WindowPtr) None;
|
|
|
|
if (ValidAtom(stuff->selection)) {
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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 = malloc(sizeof(Selection));
|
|
|
|
else
|
|
|
|
newsels = (Selection *) realloc(CurrentSelections,
|
|
|
|
(NumCurrentSelections +
|
|
|
|
1) * sizeof(Selection));
|
|
|
|
if (!newsels)
|
|
|
|
return BadAlloc;
|
|
|
|
NumCurrentSelections++;
|
|
|
|
CurrentSelections = newsels;
|
|
|
|
CurrentSelections[i].selection = stuff->selection;
|
|
|
|
}
|
|
|
|
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.kind = SelectionSetOwner;
|
|
|
|
CallCallbacks(&SelectionCallback, &info);
|
|
|
|
}
|
|
|
|
return (client->noClientException);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
client->errorValue = stuff->selection;
|
|
|
|
return (BadAtom);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
ProcGetSelectionOwner(register ClientPtr client)
|
|
|
|
{
|
|
|
|
REQUEST(xResourceReq);
|
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xResourceReq);
|
|
|
|
if (ValidAtom(stuff->id)) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
xGetSelectionOwnerReply reply;
|
|
|
|
|
|
|
|
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)
|
|
|
|
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(register ClientPtr client)
|
|
|
|
{
|
|
|
|
Bool paramsOkay;
|
|
|
|
|
|
|
|
xEvent event;
|
|
|
|
|
|
|
|
WindowPtr pWin;
|
|
|
|
|
|
|
|
REQUEST(xConvertSelectionReq);
|
|
|
|
|
|
|
|
REQUEST_SIZE_MATCH(xConvertSelectionReq);
|
|
|
|
pWin = (WindowPtr) SecurityLookupWindow(stuff->requestor, client,
|
|
|
|
SecurityReadAccess);
|
|
|
|
if (!pWin)
|
|
|
|
return (BadWindow);
|
|
|
|
|
|
|
|
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)
|
|
|
|
) {
|
|
|
|
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(register ClientPtr client)
|
|
|
|
{
|
|
|
|
REQUEST_SIZE_MATCH(xReq);
|
|
|
|
if (grabState != GrabNone && client != grabClient) {
|
|
|
|
ResetCurrentRequest(client);
|
|
|
|
client->sequence--;
|
|
|
|
BITSET(grabWaiters, client->index);
|
|
|
|
IgnoreClient(client);
|
|
|
|
return (client->noClientException);
|
|
|
|
}
|
|
|
|
OnlyListenToOneClient(client);
|
|
|
|
grabState = GrabKickout;
|
|
|
|
grabClient = client;
|
|
|
|
|
|
|
|
if (ServerGrabCallback) {
|
|
|
|
ServerGrabInfoRec grabinfo;
|
|
|
|
|
|
|
|
grabinfo.client = client;
|
|
|
|
grabinfo.grabstate = SERVER_GRABBED;
|
|
|
|
CallCallbacks(&ServerGrabCallback, (pointer) &grabinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (client->noClientException);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
UngrabServer(ClientPtr client)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
grabState = GrabNone;
|
|
|
|
ListenToAllClients();
|
|
|
|
for (i = mskcnt; --i >= 0 && !grabWaiters[i];);
|
|
|
|
if (i >= 0) {
|
< |