1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright © 2000 Compaq Computer Corporation
3*4882a593Smuzhiyun * Copyright © 2002 Hewlett-Packard Company
4*4882a593Smuzhiyun * Copyright © 2006 Intel Corporation
5*4882a593Smuzhiyun * Copyright © 2017 Keith Packard
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Permission to use, copy, modify, distribute, and sell this software and its
8*4882a593Smuzhiyun * documentation for any purpose is hereby granted without fee, provided that
9*4882a593Smuzhiyun * the above copyright notice appear in all copies and that both that copyright
10*4882a593Smuzhiyun * notice and this permission notice appear in supporting documentation, and
11*4882a593Smuzhiyun * that the name of the copyright holders not be used in advertising or
12*4882a593Smuzhiyun * publicity pertaining to distribution of the software without specific,
13*4882a593Smuzhiyun * written prior permission. The copyright holders make no representations
14*4882a593Smuzhiyun * about the suitability of this software for any purpose. It is provided "as
15*4882a593Smuzhiyun * is" without express or implied warranty.
16*4882a593Smuzhiyun *
17*4882a593Smuzhiyun * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18*4882a593Smuzhiyun * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19*4882a593Smuzhiyun * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20*4882a593Smuzhiyun * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21*4882a593Smuzhiyun * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22*4882a593Smuzhiyun * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
23*4882a593Smuzhiyun * OF THIS SOFTWARE.
24*4882a593Smuzhiyun *
25*4882a593Smuzhiyun * Author: Jim Gettys, Hewlett-Packard Company, Inc.
26*4882a593Smuzhiyun * Keith Packard, Intel Corporation
27*4882a593Smuzhiyun */
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
30*4882a593Smuzhiyun #include <dix-config.h>
31*4882a593Smuzhiyun #endif
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun #include "randrstr.h"
34*4882a593Smuzhiyun #include "extinit.h"
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun /* From render.h */
37*4882a593Smuzhiyun #ifndef SubPixelUnknown
38*4882a593Smuzhiyun #define SubPixelUnknown 0
39*4882a593Smuzhiyun #endif
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun #define RR_VALIDATE
42*4882a593Smuzhiyun static int RRNScreens;
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun #define wrap(priv,real,mem,func) {\
45*4882a593Smuzhiyun priv->mem = real->mem; \
46*4882a593Smuzhiyun real->mem = func; \
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun #define unwrap(priv,real,mem) {\
50*4882a593Smuzhiyun real->mem = priv->mem; \
51*4882a593Smuzhiyun }
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun static int ProcRRDispatch(ClientPtr pClient);
54*4882a593Smuzhiyun static int SProcRRDispatch(ClientPtr pClient);
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun int RREventBase;
57*4882a593Smuzhiyun int RRErrorBase;
58*4882a593Smuzhiyun RESTYPE RRClientType, RREventType; /* resource types for event masks */
59*4882a593Smuzhiyun DevPrivateKeyRec RRClientPrivateKeyRec;
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun DevPrivateKeyRec rrPrivKeyRec;
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun static void
RRClientCallback(CallbackListPtr * list,void * closure,void * data)64*4882a593Smuzhiyun RRClientCallback(CallbackListPtr *list, void *closure, void *data)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
67*4882a593Smuzhiyun ClientPtr pClient = clientinfo->client;
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun rrClientPriv(pClient);
70*4882a593Smuzhiyun RRTimesPtr pTimes = (RRTimesPtr) (pRRClient + 1);
71*4882a593Smuzhiyun int i;
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun pRRClient->major_version = 0;
74*4882a593Smuzhiyun pRRClient->minor_version = 0;
75*4882a593Smuzhiyun for (i = 0; i < screenInfo.numScreens; i++) {
76*4882a593Smuzhiyun ScreenPtr pScreen = screenInfo.screens[i];
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun rrScrPriv(pScreen);
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun if (pScrPriv) {
81*4882a593Smuzhiyun pTimes[i].setTime = pScrPriv->lastSetTime;
82*4882a593Smuzhiyun pTimes[i].configTime = pScrPriv->lastConfigTime;
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun static Bool
RRCloseScreen(ScreenPtr pScreen)88*4882a593Smuzhiyun RRCloseScreen(ScreenPtr pScreen)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun rrScrPriv(pScreen);
91*4882a593Smuzhiyun int j;
92*4882a593Smuzhiyun RRLeasePtr lease, next;
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun unwrap(pScrPriv, pScreen, CloseScreen);
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun xorg_list_for_each_entry_safe(lease, next, &pScrPriv->leases, list)
97*4882a593Smuzhiyun RRTerminateLease(lease);
98*4882a593Smuzhiyun for (j = pScrPriv->numCrtcs - 1; j >= 0; j--)
99*4882a593Smuzhiyun RRCrtcDestroy(pScrPriv->crtcs[j]);
100*4882a593Smuzhiyun for (j = pScrPriv->numOutputs - 1; j >= 0; j--)
101*4882a593Smuzhiyun RROutputDestroy(pScrPriv->outputs[j]);
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun if (pScrPriv->provider)
104*4882a593Smuzhiyun RRProviderDestroy(pScrPriv->provider);
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun RRMonitorClose(pScreen);
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun free(pScrPriv->crtcs);
109*4882a593Smuzhiyun free(pScrPriv->outputs);
110*4882a593Smuzhiyun free(pScrPriv);
111*4882a593Smuzhiyun RRNScreens -= 1; /* ok, one fewer screen with RandR running */
112*4882a593Smuzhiyun return (*pScreen->CloseScreen) (pScreen);
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun static void
SRRScreenChangeNotifyEvent(xRRScreenChangeNotifyEvent * from,xRRScreenChangeNotifyEvent * to)116*4882a593Smuzhiyun SRRScreenChangeNotifyEvent(xRRScreenChangeNotifyEvent * from,
117*4882a593Smuzhiyun xRRScreenChangeNotifyEvent * to)
118*4882a593Smuzhiyun {
119*4882a593Smuzhiyun to->type = from->type;
120*4882a593Smuzhiyun to->rotation = from->rotation;
121*4882a593Smuzhiyun cpswaps(from->sequenceNumber, to->sequenceNumber);
122*4882a593Smuzhiyun cpswapl(from->timestamp, to->timestamp);
123*4882a593Smuzhiyun cpswapl(from->configTimestamp, to->configTimestamp);
124*4882a593Smuzhiyun cpswapl(from->root, to->root);
125*4882a593Smuzhiyun cpswapl(from->window, to->window);
126*4882a593Smuzhiyun cpswaps(from->sizeID, to->sizeID);
127*4882a593Smuzhiyun cpswaps(from->subpixelOrder, to->subpixelOrder);
128*4882a593Smuzhiyun cpswaps(from->widthInPixels, to->widthInPixels);
129*4882a593Smuzhiyun cpswaps(from->heightInPixels, to->heightInPixels);
130*4882a593Smuzhiyun cpswaps(from->widthInMillimeters, to->widthInMillimeters);
131*4882a593Smuzhiyun cpswaps(from->heightInMillimeters, to->heightInMillimeters);
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun static void
SRRCrtcChangeNotifyEvent(xRRCrtcChangeNotifyEvent * from,xRRCrtcChangeNotifyEvent * to)135*4882a593Smuzhiyun SRRCrtcChangeNotifyEvent(xRRCrtcChangeNotifyEvent * from,
136*4882a593Smuzhiyun xRRCrtcChangeNotifyEvent * to)
137*4882a593Smuzhiyun {
138*4882a593Smuzhiyun to->type = from->type;
139*4882a593Smuzhiyun to->subCode = from->subCode;
140*4882a593Smuzhiyun cpswaps(from->sequenceNumber, to->sequenceNumber);
141*4882a593Smuzhiyun cpswapl(from->timestamp, to->timestamp);
142*4882a593Smuzhiyun cpswapl(from->window, to->window);
143*4882a593Smuzhiyun cpswapl(from->crtc, to->crtc);
144*4882a593Smuzhiyun cpswapl(from->mode, to->mode);
145*4882a593Smuzhiyun cpswaps(from->rotation, to->rotation);
146*4882a593Smuzhiyun /* pad1 */
147*4882a593Smuzhiyun cpswaps(from->x, to->x);
148*4882a593Smuzhiyun cpswaps(from->y, to->y);
149*4882a593Smuzhiyun cpswaps(from->width, to->width);
150*4882a593Smuzhiyun cpswaps(from->height, to->height);
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun static void
SRROutputChangeNotifyEvent(xRROutputChangeNotifyEvent * from,xRROutputChangeNotifyEvent * to)154*4882a593Smuzhiyun SRROutputChangeNotifyEvent(xRROutputChangeNotifyEvent * from,
155*4882a593Smuzhiyun xRROutputChangeNotifyEvent * to)
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun to->type = from->type;
158*4882a593Smuzhiyun to->subCode = from->subCode;
159*4882a593Smuzhiyun cpswaps(from->sequenceNumber, to->sequenceNumber);
160*4882a593Smuzhiyun cpswapl(from->timestamp, to->timestamp);
161*4882a593Smuzhiyun cpswapl(from->configTimestamp, to->configTimestamp);
162*4882a593Smuzhiyun cpswapl(from->window, to->window);
163*4882a593Smuzhiyun cpswapl(from->output, to->output);
164*4882a593Smuzhiyun cpswapl(from->crtc, to->crtc);
165*4882a593Smuzhiyun cpswapl(from->mode, to->mode);
166*4882a593Smuzhiyun cpswaps(from->rotation, to->rotation);
167*4882a593Smuzhiyun to->connection = from->connection;
168*4882a593Smuzhiyun to->subpixelOrder = from->subpixelOrder;
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun static void
SRROutputPropertyNotifyEvent(xRROutputPropertyNotifyEvent * from,xRROutputPropertyNotifyEvent * to)172*4882a593Smuzhiyun SRROutputPropertyNotifyEvent(xRROutputPropertyNotifyEvent * from,
173*4882a593Smuzhiyun xRROutputPropertyNotifyEvent * to)
174*4882a593Smuzhiyun {
175*4882a593Smuzhiyun to->type = from->type;
176*4882a593Smuzhiyun to->subCode = from->subCode;
177*4882a593Smuzhiyun cpswaps(from->sequenceNumber, to->sequenceNumber);
178*4882a593Smuzhiyun cpswapl(from->window, to->window);
179*4882a593Smuzhiyun cpswapl(from->output, to->output);
180*4882a593Smuzhiyun cpswapl(from->atom, to->atom);
181*4882a593Smuzhiyun cpswapl(from->timestamp, to->timestamp);
182*4882a593Smuzhiyun to->state = from->state;
183*4882a593Smuzhiyun /* pad1 */
184*4882a593Smuzhiyun /* pad2 */
185*4882a593Smuzhiyun /* pad3 */
186*4882a593Smuzhiyun /* pad4 */
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun static void
SRRProviderChangeNotifyEvent(xRRProviderChangeNotifyEvent * from,xRRProviderChangeNotifyEvent * to)190*4882a593Smuzhiyun SRRProviderChangeNotifyEvent(xRRProviderChangeNotifyEvent * from,
191*4882a593Smuzhiyun xRRProviderChangeNotifyEvent * to)
192*4882a593Smuzhiyun {
193*4882a593Smuzhiyun to->type = from->type;
194*4882a593Smuzhiyun to->subCode = from->subCode;
195*4882a593Smuzhiyun cpswaps(from->sequenceNumber, to->sequenceNumber);
196*4882a593Smuzhiyun cpswapl(from->timestamp, to->timestamp);
197*4882a593Smuzhiyun cpswapl(from->window, to->window);
198*4882a593Smuzhiyun cpswapl(from->provider, to->provider);
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun static void
SRRProviderPropertyNotifyEvent(xRRProviderPropertyNotifyEvent * from,xRRProviderPropertyNotifyEvent * to)202*4882a593Smuzhiyun SRRProviderPropertyNotifyEvent(xRRProviderPropertyNotifyEvent * from,
203*4882a593Smuzhiyun xRRProviderPropertyNotifyEvent * to)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun to->type = from->type;
206*4882a593Smuzhiyun to->subCode = from->subCode;
207*4882a593Smuzhiyun cpswaps(from->sequenceNumber, to->sequenceNumber);
208*4882a593Smuzhiyun cpswapl(from->window, to->window);
209*4882a593Smuzhiyun cpswapl(from->provider, to->provider);
210*4882a593Smuzhiyun cpswapl(from->atom, to->atom);
211*4882a593Smuzhiyun cpswapl(from->timestamp, to->timestamp);
212*4882a593Smuzhiyun to->state = from->state;
213*4882a593Smuzhiyun /* pad1 */
214*4882a593Smuzhiyun /* pad2 */
215*4882a593Smuzhiyun /* pad3 */
216*4882a593Smuzhiyun /* pad4 */
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun static void _X_COLD
SRRResourceChangeNotifyEvent(xRRResourceChangeNotifyEvent * from,xRRResourceChangeNotifyEvent * to)220*4882a593Smuzhiyun SRRResourceChangeNotifyEvent(xRRResourceChangeNotifyEvent * from,
221*4882a593Smuzhiyun xRRResourceChangeNotifyEvent * to)
222*4882a593Smuzhiyun {
223*4882a593Smuzhiyun to->type = from->type;
224*4882a593Smuzhiyun to->subCode = from->subCode;
225*4882a593Smuzhiyun cpswaps(from->sequenceNumber, to->sequenceNumber);
226*4882a593Smuzhiyun cpswapl(from->timestamp, to->timestamp);
227*4882a593Smuzhiyun cpswapl(from->window, to->window);
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun static void _X_COLD
SRRLeaseNotifyEvent(xRRLeaseNotifyEvent * from,xRRLeaseNotifyEvent * to)231*4882a593Smuzhiyun SRRLeaseNotifyEvent(xRRLeaseNotifyEvent * from,
232*4882a593Smuzhiyun xRRLeaseNotifyEvent * to)
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun to->type = from->type;
235*4882a593Smuzhiyun to->subCode = from->subCode;
236*4882a593Smuzhiyun cpswaps(from->sequenceNumber, to->sequenceNumber);
237*4882a593Smuzhiyun cpswapl(from->timestamp, to->timestamp);
238*4882a593Smuzhiyun cpswapl(from->window, to->window);
239*4882a593Smuzhiyun cpswapl(from->lease, to->lease);
240*4882a593Smuzhiyun to->created = from->created;
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun static void _X_COLD
SRRNotifyEvent(xEvent * from,xEvent * to)244*4882a593Smuzhiyun SRRNotifyEvent(xEvent *from, xEvent *to)
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun switch (from->u.u.detail) {
247*4882a593Smuzhiyun case RRNotify_CrtcChange:
248*4882a593Smuzhiyun SRRCrtcChangeNotifyEvent((xRRCrtcChangeNotifyEvent *) from,
249*4882a593Smuzhiyun (xRRCrtcChangeNotifyEvent *) to);
250*4882a593Smuzhiyun break;
251*4882a593Smuzhiyun case RRNotify_OutputChange:
252*4882a593Smuzhiyun SRROutputChangeNotifyEvent((xRROutputChangeNotifyEvent *) from,
253*4882a593Smuzhiyun (xRROutputChangeNotifyEvent *) to);
254*4882a593Smuzhiyun break;
255*4882a593Smuzhiyun case RRNotify_OutputProperty:
256*4882a593Smuzhiyun SRROutputPropertyNotifyEvent((xRROutputPropertyNotifyEvent *) from,
257*4882a593Smuzhiyun (xRROutputPropertyNotifyEvent *) to);
258*4882a593Smuzhiyun break;
259*4882a593Smuzhiyun case RRNotify_ProviderChange:
260*4882a593Smuzhiyun SRRProviderChangeNotifyEvent((xRRProviderChangeNotifyEvent *) from,
261*4882a593Smuzhiyun (xRRProviderChangeNotifyEvent *) to);
262*4882a593Smuzhiyun break;
263*4882a593Smuzhiyun case RRNotify_ProviderProperty:
264*4882a593Smuzhiyun SRRProviderPropertyNotifyEvent((xRRProviderPropertyNotifyEvent *) from,
265*4882a593Smuzhiyun (xRRProviderPropertyNotifyEvent *) to);
266*4882a593Smuzhiyun break;
267*4882a593Smuzhiyun case RRNotify_ResourceChange:
268*4882a593Smuzhiyun SRRResourceChangeNotifyEvent((xRRResourceChangeNotifyEvent *) from,
269*4882a593Smuzhiyun (xRRResourceChangeNotifyEvent *) to);
270*4882a593Smuzhiyun break;
271*4882a593Smuzhiyun case RRNotify_Lease:
272*4882a593Smuzhiyun SRRLeaseNotifyEvent((xRRLeaseNotifyEvent *) from,
273*4882a593Smuzhiyun (xRRLeaseNotifyEvent *) to);
274*4882a593Smuzhiyun break;
275*4882a593Smuzhiyun default:
276*4882a593Smuzhiyun break;
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun static int RRGeneration;
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun Bool
RRInit(void)283*4882a593Smuzhiyun RRInit(void)
284*4882a593Smuzhiyun {
285*4882a593Smuzhiyun if (RRGeneration != serverGeneration) {
286*4882a593Smuzhiyun if (!RRModeInit())
287*4882a593Smuzhiyun return FALSE;
288*4882a593Smuzhiyun if (!RRCrtcInit())
289*4882a593Smuzhiyun return FALSE;
290*4882a593Smuzhiyun if (!RROutputInit())
291*4882a593Smuzhiyun return FALSE;
292*4882a593Smuzhiyun if (!RRProviderInit())
293*4882a593Smuzhiyun return FALSE;
294*4882a593Smuzhiyun if (!RRLeaseInit())
295*4882a593Smuzhiyun return FALSE;
296*4882a593Smuzhiyun RRGeneration = serverGeneration;
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun if (!dixRegisterPrivateKey(&rrPrivKeyRec, PRIVATE_SCREEN, 0))
299*4882a593Smuzhiyun return FALSE;
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun return TRUE;
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun Bool
RRScreenInit(ScreenPtr pScreen)305*4882a593Smuzhiyun RRScreenInit(ScreenPtr pScreen)
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun rrScrPrivPtr pScrPriv;
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun if (!RRInit())
310*4882a593Smuzhiyun return FALSE;
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun pScrPriv = (rrScrPrivPtr) calloc(1, sizeof(rrScrPrivRec));
313*4882a593Smuzhiyun if (!pScrPriv)
314*4882a593Smuzhiyun return FALSE;
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun SetRRScreen(pScreen, pScrPriv);
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun /*
319*4882a593Smuzhiyun * Calling function best set these function vectors
320*4882a593Smuzhiyun */
321*4882a593Smuzhiyun pScrPriv->rrGetInfo = 0;
322*4882a593Smuzhiyun pScrPriv->maxWidth = pScrPriv->minWidth = pScreen->width;
323*4882a593Smuzhiyun pScrPriv->maxHeight = pScrPriv->minHeight = pScreen->height;
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun pScrPriv->width = pScreen->width;
326*4882a593Smuzhiyun pScrPriv->height = pScreen->height;
327*4882a593Smuzhiyun pScrPriv->mmWidth = pScreen->mmWidth;
328*4882a593Smuzhiyun pScrPriv->mmHeight = pScreen->mmHeight;
329*4882a593Smuzhiyun #if RANDR_12_INTERFACE
330*4882a593Smuzhiyun pScrPriv->rrScreenSetSize = NULL;
331*4882a593Smuzhiyun pScrPriv->rrCrtcSet = NULL;
332*4882a593Smuzhiyun pScrPriv->rrCrtcSetGamma = NULL;
333*4882a593Smuzhiyun #endif
334*4882a593Smuzhiyun #if RANDR_10_INTERFACE
335*4882a593Smuzhiyun pScrPriv->rrSetConfig = 0;
336*4882a593Smuzhiyun pScrPriv->rotations = RR_Rotate_0;
337*4882a593Smuzhiyun pScrPriv->reqWidth = pScreen->width;
338*4882a593Smuzhiyun pScrPriv->reqHeight = pScreen->height;
339*4882a593Smuzhiyun pScrPriv->nSizes = 0;
340*4882a593Smuzhiyun pScrPriv->pSizes = NULL;
341*4882a593Smuzhiyun pScrPriv->rotation = RR_Rotate_0;
342*4882a593Smuzhiyun pScrPriv->rate = 0;
343*4882a593Smuzhiyun pScrPriv->size = 0;
344*4882a593Smuzhiyun #endif
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun /*
347*4882a593Smuzhiyun * This value doesn't really matter -- any client must call
348*4882a593Smuzhiyun * GetScreenInfo before reading it which will automatically update
349*4882a593Smuzhiyun * the time
350*4882a593Smuzhiyun */
351*4882a593Smuzhiyun pScrPriv->lastSetTime = currentTime;
352*4882a593Smuzhiyun pScrPriv->lastConfigTime = currentTime;
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun wrap(pScrPriv, pScreen, CloseScreen, RRCloseScreen);
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun pScreen->ConstrainCursorHarder = RRConstrainCursorHarder;
357*4882a593Smuzhiyun pScreen->ReplaceScanoutPixmap = RRReplaceScanoutPixmap;
358*4882a593Smuzhiyun pScrPriv->numOutputs = 0;
359*4882a593Smuzhiyun pScrPriv->outputs = NULL;
360*4882a593Smuzhiyun pScrPriv->numCrtcs = 0;
361*4882a593Smuzhiyun pScrPriv->crtcs = NULL;
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun xorg_list_init(&pScrPriv->leases);
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun RRMonitorInit(pScreen);
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun RRNScreens += 1; /* keep count of screens that implement randr */
368*4882a593Smuzhiyun return TRUE;
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun /*ARGSUSED*/ static int
RRFreeClient(void * data,XID id)372*4882a593Smuzhiyun RRFreeClient(void *data, XID id)
373*4882a593Smuzhiyun {
374*4882a593Smuzhiyun RREventPtr pRREvent;
375*4882a593Smuzhiyun WindowPtr pWin;
376*4882a593Smuzhiyun RREventPtr *pHead, pCur, pPrev;
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun pRREvent = (RREventPtr) data;
379*4882a593Smuzhiyun pWin = pRREvent->window;
380*4882a593Smuzhiyun dixLookupResourceByType((void **) &pHead, pWin->drawable.id,
381*4882a593Smuzhiyun RREventType, serverClient, DixDestroyAccess);
382*4882a593Smuzhiyun if (pHead) {
383*4882a593Smuzhiyun pPrev = 0;
384*4882a593Smuzhiyun for (pCur = *pHead; pCur && pCur != pRREvent; pCur = pCur->next)
385*4882a593Smuzhiyun pPrev = pCur;
386*4882a593Smuzhiyun if (pCur) {
387*4882a593Smuzhiyun if (pPrev)
388*4882a593Smuzhiyun pPrev->next = pRREvent->next;
389*4882a593Smuzhiyun else
390*4882a593Smuzhiyun *pHead = pRREvent->next;
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun free((void *) pRREvent);
394*4882a593Smuzhiyun return 1;
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun /*ARGSUSED*/ static int
RRFreeEvents(void * data,XID id)398*4882a593Smuzhiyun RRFreeEvents(void *data, XID id)
399*4882a593Smuzhiyun {
400*4882a593Smuzhiyun RREventPtr *pHead, pCur, pNext;
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun pHead = (RREventPtr *) data;
403*4882a593Smuzhiyun for (pCur = *pHead; pCur; pCur = pNext) {
404*4882a593Smuzhiyun pNext = pCur->next;
405*4882a593Smuzhiyun FreeResource(pCur->clientResource, RRClientType);
406*4882a593Smuzhiyun free((void *) pCur);
407*4882a593Smuzhiyun }
408*4882a593Smuzhiyun free((void *) pHead);
409*4882a593Smuzhiyun return 1;
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun void
RRExtensionInit(void)413*4882a593Smuzhiyun RRExtensionInit(void)
414*4882a593Smuzhiyun {
415*4882a593Smuzhiyun ExtensionEntry *extEntry;
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun if (RRNScreens == 0)
418*4882a593Smuzhiyun return;
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun if (!dixRegisterPrivateKey(&RRClientPrivateKeyRec, PRIVATE_CLIENT,
421*4882a593Smuzhiyun sizeof(RRClientRec) +
422*4882a593Smuzhiyun screenInfo.numScreens * sizeof(RRTimesRec)))
423*4882a593Smuzhiyun return;
424*4882a593Smuzhiyun if (!AddCallback(&ClientStateCallback, RRClientCallback, 0))
425*4882a593Smuzhiyun return;
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun RRClientType = CreateNewResourceType(RRFreeClient, "RandRClient");
428*4882a593Smuzhiyun if (!RRClientType)
429*4882a593Smuzhiyun return;
430*4882a593Smuzhiyun RREventType = CreateNewResourceType(RRFreeEvents, "RandREvent");
431*4882a593Smuzhiyun if (!RREventType)
432*4882a593Smuzhiyun return;
433*4882a593Smuzhiyun extEntry = AddExtension(RANDR_NAME, RRNumberEvents, RRNumberErrors,
434*4882a593Smuzhiyun ProcRRDispatch, SProcRRDispatch,
435*4882a593Smuzhiyun NULL, StandardMinorOpcode);
436*4882a593Smuzhiyun if (!extEntry)
437*4882a593Smuzhiyun return;
438*4882a593Smuzhiyun RRErrorBase = extEntry->errorBase;
439*4882a593Smuzhiyun RREventBase = extEntry->eventBase;
440*4882a593Smuzhiyun EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr)
441*4882a593Smuzhiyun SRRScreenChangeNotifyEvent;
442*4882a593Smuzhiyun EventSwapVector[RREventBase + RRNotify] = (EventSwapPtr)
443*4882a593Smuzhiyun SRRNotifyEvent;
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun RRModeInitErrorValue();
446*4882a593Smuzhiyun RRCrtcInitErrorValue();
447*4882a593Smuzhiyun RROutputInitErrorValue();
448*4882a593Smuzhiyun RRProviderInitErrorValue();
449*4882a593Smuzhiyun #ifdef PANORAMIX
450*4882a593Smuzhiyun RRXineramaExtensionInit();
451*4882a593Smuzhiyun #endif
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun void
RRResourcesChanged(ScreenPtr pScreen)455*4882a593Smuzhiyun RRResourcesChanged(ScreenPtr pScreen)
456*4882a593Smuzhiyun {
457*4882a593Smuzhiyun rrScrPriv(pScreen);
458*4882a593Smuzhiyun pScrPriv->resourcesChanged = TRUE;
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun RRSetChanged(pScreen);
461*4882a593Smuzhiyun }
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun static void
RRDeliverResourceEvent(ClientPtr client,WindowPtr pWin)464*4882a593Smuzhiyun RRDeliverResourceEvent(ClientPtr client, WindowPtr pWin)
465*4882a593Smuzhiyun {
466*4882a593Smuzhiyun ScreenPtr pScreen = pWin->drawable.pScreen;
467*4882a593Smuzhiyun
468*4882a593Smuzhiyun rrScrPriv(pScreen);
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun xRRResourceChangeNotifyEvent re = {
471*4882a593Smuzhiyun .type = RRNotify + RREventBase,
472*4882a593Smuzhiyun .subCode = RRNotify_ResourceChange,
473*4882a593Smuzhiyun .timestamp = pScrPriv->lastSetTime.milliseconds,
474*4882a593Smuzhiyun .window = pWin->drawable.id
475*4882a593Smuzhiyun };
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun WriteEventsToClient(client, 1, (xEvent *) &re);
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun static int
TellChanged(WindowPtr pWin,void * value)481*4882a593Smuzhiyun TellChanged(WindowPtr pWin, void *value)
482*4882a593Smuzhiyun {
483*4882a593Smuzhiyun RREventPtr *pHead, pRREvent;
484*4882a593Smuzhiyun ClientPtr client;
485*4882a593Smuzhiyun ScreenPtr pScreen = pWin->drawable.pScreen;
486*4882a593Smuzhiyun ScreenPtr iter;
487*4882a593Smuzhiyun rrScrPrivPtr pSlaveScrPriv;
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun rrScrPriv(pScreen);
490*4882a593Smuzhiyun int i;
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun dixLookupResourceByType((void **) &pHead, pWin->drawable.id,
493*4882a593Smuzhiyun RREventType, serverClient, DixReadAccess);
494*4882a593Smuzhiyun if (!pHead)
495*4882a593Smuzhiyun return WT_WALKCHILDREN;
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) {
498*4882a593Smuzhiyun client = pRREvent->client;
499*4882a593Smuzhiyun if (client == serverClient || client->clientGone)
500*4882a593Smuzhiyun continue;
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun if (pRREvent->mask & RRScreenChangeNotifyMask)
503*4882a593Smuzhiyun RRDeliverScreenEvent(client, pWin, pScreen);
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun if (pRREvent->mask & RRCrtcChangeNotifyMask) {
506*4882a593Smuzhiyun for (i = 0; i < pScrPriv->numCrtcs; i++) {
507*4882a593Smuzhiyun RRCrtcPtr crtc = pScrPriv->crtcs[i];
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun if (crtc->changed)
510*4882a593Smuzhiyun RRDeliverCrtcEvent(client, pWin, crtc);
511*4882a593Smuzhiyun }
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun xorg_list_for_each_entry(iter, &pScreen->slave_list, slave_head) {
514*4882a593Smuzhiyun if (!iter->is_output_slave)
515*4882a593Smuzhiyun continue;
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun pSlaveScrPriv = rrGetScrPriv(iter);
518*4882a593Smuzhiyun for (i = 0; i < pSlaveScrPriv->numCrtcs; i++) {
519*4882a593Smuzhiyun RRCrtcPtr crtc = pSlaveScrPriv->crtcs[i];
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun if (crtc->changed)
522*4882a593Smuzhiyun RRDeliverCrtcEvent(client, pWin, crtc);
523*4882a593Smuzhiyun }
524*4882a593Smuzhiyun }
525*4882a593Smuzhiyun }
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun if (pRREvent->mask & RROutputChangeNotifyMask) {
528*4882a593Smuzhiyun for (i = 0; i < pScrPriv->numOutputs; i++) {
529*4882a593Smuzhiyun RROutputPtr output = pScrPriv->outputs[i];
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun if (output->changed)
532*4882a593Smuzhiyun RRDeliverOutputEvent(client, pWin, output);
533*4882a593Smuzhiyun }
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun xorg_list_for_each_entry(iter, &pScreen->slave_list, slave_head) {
536*4882a593Smuzhiyun if (!iter->is_output_slave)
537*4882a593Smuzhiyun continue;
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun pSlaveScrPriv = rrGetScrPriv(iter);
540*4882a593Smuzhiyun for (i = 0; i < pSlaveScrPriv->numOutputs; i++) {
541*4882a593Smuzhiyun RROutputPtr output = pSlaveScrPriv->outputs[i];
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun if (output->changed)
544*4882a593Smuzhiyun RRDeliverOutputEvent(client, pWin, output);
545*4882a593Smuzhiyun }
546*4882a593Smuzhiyun }
547*4882a593Smuzhiyun }
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun if (pRREvent->mask & RRProviderChangeNotifyMask) {
550*4882a593Smuzhiyun xorg_list_for_each_entry(iter, &pScreen->slave_list, slave_head) {
551*4882a593Smuzhiyun pSlaveScrPriv = rrGetScrPriv(iter);
552*4882a593Smuzhiyun if (pSlaveScrPriv->provider->changed)
553*4882a593Smuzhiyun RRDeliverProviderEvent(client, pWin, pSlaveScrPriv->provider);
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun if (pRREvent->mask & RRResourceChangeNotifyMask) {
558*4882a593Smuzhiyun if (pScrPriv->resourcesChanged) {
559*4882a593Smuzhiyun RRDeliverResourceEvent(client, pWin);
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun }
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun if (pRREvent->mask & RRLeaseNotifyMask) {
564*4882a593Smuzhiyun if (pScrPriv->leasesChanged) {
565*4882a593Smuzhiyun RRDeliverLeaseEvent(client, pWin);
566*4882a593Smuzhiyun }
567*4882a593Smuzhiyun }
568*4882a593Smuzhiyun }
569*4882a593Smuzhiyun return WT_WALKCHILDREN;
570*4882a593Smuzhiyun }
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun void
RRSetChanged(ScreenPtr pScreen)573*4882a593Smuzhiyun RRSetChanged(ScreenPtr pScreen)
574*4882a593Smuzhiyun {
575*4882a593Smuzhiyun /* set changed bits on the master screen only */
576*4882a593Smuzhiyun ScreenPtr master;
577*4882a593Smuzhiyun rrScrPriv(pScreen);
578*4882a593Smuzhiyun rrScrPrivPtr mastersp;
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun if (pScreen->isGPU) {
581*4882a593Smuzhiyun master = pScreen->current_master;
582*4882a593Smuzhiyun if (!master)
583*4882a593Smuzhiyun return;
584*4882a593Smuzhiyun mastersp = rrGetScrPriv(master);
585*4882a593Smuzhiyun }
586*4882a593Smuzhiyun else {
587*4882a593Smuzhiyun master = pScreen;
588*4882a593Smuzhiyun mastersp = pScrPriv;
589*4882a593Smuzhiyun }
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun mastersp->changed = TRUE;
592*4882a593Smuzhiyun }
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun /*
595*4882a593Smuzhiyun * Something changed; send events and adjust pointer position
596*4882a593Smuzhiyun */
597*4882a593Smuzhiyun void
RRTellChanged(ScreenPtr pScreen)598*4882a593Smuzhiyun RRTellChanged(ScreenPtr pScreen)
599*4882a593Smuzhiyun {
600*4882a593Smuzhiyun ScreenPtr master;
601*4882a593Smuzhiyun rrScrPriv(pScreen);
602*4882a593Smuzhiyun rrScrPrivPtr mastersp;
603*4882a593Smuzhiyun int i;
604*4882a593Smuzhiyun ScreenPtr iter;
605*4882a593Smuzhiyun rrScrPrivPtr pSlaveScrPriv;
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun if (pScreen->isGPU) {
608*4882a593Smuzhiyun master = pScreen->current_master;
609*4882a593Smuzhiyun if (!master)
610*4882a593Smuzhiyun return;
611*4882a593Smuzhiyun mastersp = rrGetScrPriv(master);
612*4882a593Smuzhiyun }
613*4882a593Smuzhiyun else {
614*4882a593Smuzhiyun master = pScreen;
615*4882a593Smuzhiyun mastersp = pScrPriv;
616*4882a593Smuzhiyun }
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun xorg_list_for_each_entry(iter, &master->slave_list, slave_head) {
619*4882a593Smuzhiyun pSlaveScrPriv = rrGetScrPriv(iter);
620*4882a593Smuzhiyun
621*4882a593Smuzhiyun if (!iter->is_output_slave)
622*4882a593Smuzhiyun continue;
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun if (CompareTimeStamps(mastersp->lastSetTime,
625*4882a593Smuzhiyun pSlaveScrPriv->lastSetTime) == EARLIER) {
626*4882a593Smuzhiyun mastersp->lastSetTime = pSlaveScrPriv->lastSetTime;
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun }
629*4882a593Smuzhiyun
630*4882a593Smuzhiyun if (mastersp->changed) {
631*4882a593Smuzhiyun UpdateCurrentTimeIf();
632*4882a593Smuzhiyun if (mastersp->configChanged) {
633*4882a593Smuzhiyun mastersp->lastConfigTime = currentTime;
634*4882a593Smuzhiyun mastersp->configChanged = FALSE;
635*4882a593Smuzhiyun }
636*4882a593Smuzhiyun pScrPriv->changed = FALSE;
637*4882a593Smuzhiyun mastersp->changed = FALSE;
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun WalkTree(master, TellChanged, (void *) master);
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun mastersp->resourcesChanged = FALSE;
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun for (i = 0; i < pScrPriv->numOutputs; i++)
644*4882a593Smuzhiyun pScrPriv->outputs[i]->changed = FALSE;
645*4882a593Smuzhiyun for (i = 0; i < pScrPriv->numCrtcs; i++)
646*4882a593Smuzhiyun pScrPriv->crtcs[i]->changed = FALSE;
647*4882a593Smuzhiyun
648*4882a593Smuzhiyun xorg_list_for_each_entry(iter, &master->slave_list, slave_head) {
649*4882a593Smuzhiyun pSlaveScrPriv = rrGetScrPriv(iter);
650*4882a593Smuzhiyun pSlaveScrPriv->provider->changed = FALSE;
651*4882a593Smuzhiyun if (iter->is_output_slave) {
652*4882a593Smuzhiyun for (i = 0; i < pSlaveScrPriv->numOutputs; i++)
653*4882a593Smuzhiyun pSlaveScrPriv->outputs[i]->changed = FALSE;
654*4882a593Smuzhiyun for (i = 0; i < pSlaveScrPriv->numCrtcs; i++)
655*4882a593Smuzhiyun pSlaveScrPriv->crtcs[i]->changed = FALSE;
656*4882a593Smuzhiyun }
657*4882a593Smuzhiyun }
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun if (mastersp->layoutChanged) {
660*4882a593Smuzhiyun pScrPriv->layoutChanged = FALSE;
661*4882a593Smuzhiyun RRPointerScreenConfigured(master);
662*4882a593Smuzhiyun RRSendConfigNotify(master);
663*4882a593Smuzhiyun }
664*4882a593Smuzhiyun }
665*4882a593Smuzhiyun }
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun /*
668*4882a593Smuzhiyun * Return the first output which is connected to an active CRTC
669*4882a593Smuzhiyun * Used in emulating 1.0 behaviour
670*4882a593Smuzhiyun */
671*4882a593Smuzhiyun RROutputPtr
RRFirstOutput(ScreenPtr pScreen)672*4882a593Smuzhiyun RRFirstOutput(ScreenPtr pScreen)
673*4882a593Smuzhiyun {
674*4882a593Smuzhiyun rrScrPriv(pScreen);
675*4882a593Smuzhiyun RROutputPtr output;
676*4882a593Smuzhiyun int i, j;
677*4882a593Smuzhiyun
678*4882a593Smuzhiyun if (!pScrPriv)
679*4882a593Smuzhiyun return NULL;
680*4882a593Smuzhiyun
681*4882a593Smuzhiyun if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc)
682*4882a593Smuzhiyun return pScrPriv->primaryOutput;
683*4882a593Smuzhiyun
684*4882a593Smuzhiyun for (i = 0; i < pScrPriv->numCrtcs; i++) {
685*4882a593Smuzhiyun RRCrtcPtr crtc = pScrPriv->crtcs[i];
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun for (j = 0; j < pScrPriv->numOutputs; j++) {
688*4882a593Smuzhiyun output = pScrPriv->outputs[j];
689*4882a593Smuzhiyun if (output->crtc == crtc)
690*4882a593Smuzhiyun return output;
691*4882a593Smuzhiyun }
692*4882a593Smuzhiyun }
693*4882a593Smuzhiyun return NULL;
694*4882a593Smuzhiyun }
695*4882a593Smuzhiyun
696*4882a593Smuzhiyun CARD16
RRVerticalRefresh(xRRModeInfo * mode)697*4882a593Smuzhiyun RRVerticalRefresh(xRRModeInfo * mode)
698*4882a593Smuzhiyun {
699*4882a593Smuzhiyun CARD32 refresh;
700*4882a593Smuzhiyun CARD32 dots = mode->hTotal * mode->vTotal;
701*4882a593Smuzhiyun
702*4882a593Smuzhiyun if (!dots)
703*4882a593Smuzhiyun return 0;
704*4882a593Smuzhiyun refresh = (mode->dotClock + dots / 2) / dots;
705*4882a593Smuzhiyun if (refresh > 0xffff)
706*4882a593Smuzhiyun refresh = 0xffff;
707*4882a593Smuzhiyun return (CARD16) refresh;
708*4882a593Smuzhiyun }
709*4882a593Smuzhiyun
710*4882a593Smuzhiyun static int
ProcRRDispatch(ClientPtr client)711*4882a593Smuzhiyun ProcRRDispatch(ClientPtr client)
712*4882a593Smuzhiyun {
713*4882a593Smuzhiyun REQUEST(xReq);
714*4882a593Smuzhiyun if (stuff->data >= RRNumberRequests || !ProcRandrVector[stuff->data])
715*4882a593Smuzhiyun return BadRequest;
716*4882a593Smuzhiyun UpdateCurrentTimeIf();
717*4882a593Smuzhiyun return (*ProcRandrVector[stuff->data]) (client);
718*4882a593Smuzhiyun }
719*4882a593Smuzhiyun
720*4882a593Smuzhiyun static int _X_COLD
SProcRRDispatch(ClientPtr client)721*4882a593Smuzhiyun SProcRRDispatch(ClientPtr client)
722*4882a593Smuzhiyun {
723*4882a593Smuzhiyun REQUEST(xReq);
724*4882a593Smuzhiyun if (stuff->data >= RRNumberRequests || !SProcRandrVector[stuff->data])
725*4882a593Smuzhiyun return BadRequest;
726*4882a593Smuzhiyun UpdateCurrentTimeIf();
727*4882a593Smuzhiyun return (*SProcRandrVector[stuff->data]) (client);
728*4882a593Smuzhiyun }
729