dispatch.c revision 5a112b11
105b261ecSmrg/************************************************************
205b261ecSmrg
305b261ecSmrgCopyright 1987, 1989, 1998  The Open Group
405b261ecSmrg
505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its
605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that
705b261ecSmrgthe above copyright notice appear in all copies and that both that
805b261ecSmrgcopyright notice and this permission notice appear in supporting
905b261ecSmrgdocumentation.
1005b261ecSmrg
1105b261ecSmrgThe above copyright notice and this permission notice shall be included in
1205b261ecSmrgall copies or substantial portions of the Software.
1305b261ecSmrg
1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2005b261ecSmrg
2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be
2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings
2305b261ecSmrgin this Software without prior written authorization from The Open Group.
2405b261ecSmrg
2505b261ecSmrgCopyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
2605b261ecSmrg
2705b261ecSmrg                        All Rights Reserved
2805b261ecSmrg
29f7df2e56SmrgPermission to use, copy, modify, and distribute this software and its
30f7df2e56Smrgdocumentation for any purpose and without fee is hereby granted,
3105b261ecSmrgprovided that the above copyright notice appear in all copies and that
32f7df2e56Smrgboth that copyright notice and this permission notice appear in
3305b261ecSmrgsupporting documentation, and that the name of Digital not be
3405b261ecSmrgused in advertising or publicity pertaining to distribution of the
35f7df2e56Smrgsoftware without specific, written prior permission.
3605b261ecSmrg
3705b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
3805b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
3905b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
4005b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
4105b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
4205b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
4305b261ecSmrgSOFTWARE.
4405b261ecSmrg
4505b261ecSmrg********************************************************/
4605b261ecSmrg
4705b261ecSmrg/* The panoramix components contained the following notice */
4805b261ecSmrg/*****************************************************************
4905b261ecSmrg
5005b261ecSmrgCopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
5105b261ecSmrg
5205b261ecSmrgPermission is hereby granted, free of charge, to any person obtaining a copy
5305b261ecSmrgof this software and associated documentation files (the "Software"), to deal
5405b261ecSmrgin the Software without restriction, including without limitation the rights
5505b261ecSmrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5605b261ecSmrgcopies of the Software.
5705b261ecSmrg
5805b261ecSmrgThe above copyright notice and this permission notice shall be included in
5905b261ecSmrgall copies or substantial portions of the Software.
6005b261ecSmrg
6105b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6205b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6305b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
6405b261ecSmrgDIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
6505b261ecSmrgBUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
6605b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
6705b261ecSmrgIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6805b261ecSmrg
6905b261ecSmrgExcept as contained in this notice, the name of Digital Equipment Corporation
7005b261ecSmrgshall not be used in advertising or otherwise to promote the sale, use or other
7105b261ecSmrgdealings in this Software without prior written authorization from Digital
7205b261ecSmrgEquipment Corporation.
7305b261ecSmrg
7405b261ecSmrg******************************************************************/
7505b261ecSmrg
7605b261ecSmrg/* XSERVER_DTRACE additions:
779ace9065Smrg * Copyright (c) 2005-2006, Oracle and/or its affiliates. All rights reserved.
7805b261ecSmrg *
7905b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a
806747b715Smrg * copy of this software and associated documentation files (the "Software"),
816747b715Smrg * to deal in the Software without restriction, including without limitation
826747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
836747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the
846747b715Smrg * Software is furnished to do so, subject to the following conditions:
856747b715Smrg *
866747b715Smrg * The above copyright notice and this permission notice (including the next
876747b715Smrg * paragraph) shall be included in all copies or substantial portions of the
886747b715Smrg * Software.
896747b715Smrg *
906747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
916747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
926747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
936747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
946747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
956747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
966747b715Smrg * DEALINGS IN THE SOFTWARE.
9705b261ecSmrg */
9805b261ecSmrg
9905b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
10005b261ecSmrg#include <dix-config.h>
1016747b715Smrg#include <version-config.h>
10205b261ecSmrg#endif
10305b261ecSmrg
10405b261ecSmrg#ifdef PANORAMIX_DEBUG
10505b261ecSmrg#include <stdio.h>
10605b261ecSmrgint ProcInitialConnection();
10705b261ecSmrg#endif
10805b261ecSmrg
10905b261ecSmrg#include "windowstr.h"
11005b261ecSmrg#include <X11/fonts/fontstruct.h>
1117e31ba66Smrg#include <X11/fonts/libxfont2.h>
11205b261ecSmrg#include "dixfontstr.h"
11305b261ecSmrg#include "gcstruct.h"
11405b261ecSmrg#include "selection.h"
11505b261ecSmrg#include "colormapst.h"
11605b261ecSmrg#include "cursorstr.h"
11705b261ecSmrg#include "scrnintstr.h"
11805b261ecSmrg#include "opaque.h"
11905b261ecSmrg#include "input.h"
12005b261ecSmrg#include "servermd.h"
12105b261ecSmrg#include "extnsionst.h"
12205b261ecSmrg#include "dixfont.h"
12305b261ecSmrg#include "dispatch.h"
12405b261ecSmrg#include "swaprep.h"
12505b261ecSmrg#include "swapreq.h"
1264642e01fSmrg#include "privates.h"
12705b261ecSmrg#include "xace.h"
12805b261ecSmrg#include "inputstr.h"
1296747b715Smrg#include "xkbsrv.h"
130f7df2e56Smrg#include "client.h"
1315a112b11Smrg#include "xfixesint.h"
13205b261ecSmrg
13305b261ecSmrg#ifdef XSERVER_DTRACE
1344642e01fSmrg#include "registry.h"
135f7df2e56Smrg#include "probes.h"
13605b261ecSmrg#endif
13705b261ecSmrg
13805b261ecSmrg#define mskcnt ((MAXCLIENTS + 31) / 32)
13905b261ecSmrg#define BITMASK(i) (1U << ((i) & 31))
14005b261ecSmrg#define MASKIDX(i) ((i) >> 5)
14105b261ecSmrg#define MASKWORD(buf, i) buf[MASKIDX(i)]
14205b261ecSmrg#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i)
14305b261ecSmrg#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
14405b261ecSmrg#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
14505b261ecSmrg
1466747b715SmrgxConnSetupPrefix connSetupPrefix;
1476747b715Smrg
1486747b715SmrgPaddingInfo PixmapWidthPaddingInfo[33];
14905b261ecSmrg
15005b261ecSmrgstatic ClientPtr grabClient;
1515a112b11Smrgstatic ClientPtr currentClient; /* Client for the request currently being dispatched */
152f7df2e56Smrg
15305b261ecSmrg#define GrabNone 0
15405b261ecSmrg#define GrabActive 1
15505b261ecSmrgstatic int grabState = GrabNone;
15605b261ecSmrgstatic long grabWaiters[mskcnt];
1576747b715SmrgCallbackListPtr ServerGrabCallback = NULL;
15805b261ecSmrgHWEventQueuePtr checkForInput[2];
1596747b715Smrgint connBlockScreenStart;
16005b261ecSmrg
16105b261ecSmrgstatic void KillAllClients(void);
16205b261ecSmrg
163f7df2e56Smrgstatic int nextFreeClientID;    /* always MIN free client ID */
16405b261ecSmrg
165f7df2e56Smrgstatic int nClients;            /* number of authorized clients */
16605b261ecSmrg
1676747b715SmrgCallbackListPtr ClientStateCallback;
1685a112b11SmrgOsTimerPtr dispatchExceptionTimer;
16905b261ecSmrg
17005b261ecSmrg/* dispatchException & isItTimeToYield must be declared volatile since they
17105b261ecSmrg * are modified by signal handlers - otherwise optimizer may assume it doesn't
17205b261ecSmrg * need to actually check value in memory when used and may miss changes from
17305b261ecSmrg * signal handlers.
17405b261ecSmrg */
1756747b715Smrgvolatile char dispatchException = 0;
1766747b715Smrgvolatile char isItTimeToYield;
17705b261ecSmrg
17805b261ecSmrg#define SAME_SCREENS(a, b) (\
17905b261ecSmrg    (a.pScreen == b.pScreen))
18005b261ecSmrg
1815a112b11SmrgClientPtr
1825a112b11SmrgGetCurrentClient(void)
1835a112b11Smrg{
1845a112b11Smrg    if (in_input_thread()) {
1855a112b11Smrg        static Bool warned;
1865a112b11Smrg
1875a112b11Smrg        if (!warned) {
1885a112b11Smrg            ErrorF("[dix] Error GetCurrentClient called from input-thread\n");
1895a112b11Smrg            warned = TRUE;
1905a112b11Smrg        }
1915a112b11Smrg
1925a112b11Smrg        return NULL;
1935a112b11Smrg    }
1945a112b11Smrg
1955a112b11Smrg    return currentClient;
1965a112b11Smrg}
1975a112b11Smrg
1984642e01fSmrgvoid
19905b261ecSmrgSetInputCheck(HWEventQueuePtr c0, HWEventQueuePtr c1)
20005b261ecSmrg{
20105b261ecSmrg    checkForInput[0] = c0;
20205b261ecSmrg    checkForInput[1] = c1;
20305b261ecSmrg}
20405b261ecSmrg
2056747b715Smrgvoid
20605b261ecSmrgUpdateCurrentTime(void)
20705b261ecSmrg{
20805b261ecSmrg    TimeStamp systime;
20905b261ecSmrg
21005b261ecSmrg    /* To avoid time running backwards, we must call GetTimeInMillis before
21105b261ecSmrg     * calling ProcessInputEvents.
21205b261ecSmrg     */
21305b261ecSmrg    systime.months = currentTime.months;
21405b261ecSmrg    systime.milliseconds = GetTimeInMillis();
21505b261ecSmrg    if (systime.milliseconds < currentTime.milliseconds)
216f7df2e56Smrg        systime.months++;
2177e31ba66Smrg    if (InputCheckPending())
218f7df2e56Smrg        ProcessInputEvents();
21905b261ecSmrg    if (CompareTimeStamps(systime, currentTime) == LATER)
220f7df2e56Smrg        currentTime = systime;
22105b261ecSmrg}
22205b261ecSmrg
22305b261ecSmrg/* Like UpdateCurrentTime, but can't call ProcessInputEvents */
2246747b715Smrgvoid
22505b261ecSmrgUpdateCurrentTimeIf(void)
22605b261ecSmrg{
22705b261ecSmrg    TimeStamp systime;
22805b261ecSmrg
22905b261ecSmrg    systime.months = currentTime.months;
23005b261ecSmrg    systime.milliseconds = GetTimeInMillis();
23105b261ecSmrg    if (systime.milliseconds < currentTime.milliseconds)
232f7df2e56Smrg        systime.months++;
233f7df2e56Smrg    if (CompareTimeStamps(systime, currentTime) == LATER)
234f7df2e56Smrg        currentTime = systime;
23505b261ecSmrg}
23605b261ecSmrg
23705b261ecSmrg#undef SMART_DEBUG
23805b261ecSmrg
239f7df2e56Smrg/* in milliseconds */
240f7df2e56Smrg#define SMART_SCHEDULE_DEFAULT_INTERVAL	5
241f7df2e56Smrg#define SMART_SCHEDULE_MAX_SLICE	15
24205b261ecSmrg
2437e31ba66Smrg#ifdef HAVE_SETITIMER
2447e31ba66SmrgBool SmartScheduleSignalEnable = TRUE;
245f7df2e56Smrg#endif
2467e31ba66Smrg
2476747b715Smrglong SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL;
2486747b715Smrglong SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL;
2496747b715Smrglong SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE;
2506747b715Smrglong SmartScheduleTime;
2516747b715Smrgint SmartScheduleLatencyLimited = 0;
252f7df2e56Smrgstatic ClientPtr SmartLastClient;
253f7df2e56Smrgstatic int SmartLastIndex[SMART_MAX_PRIORITY - SMART_MIN_PRIORITY + 1];
25405b261ecSmrg
25505b261ecSmrg#ifdef SMART_DEBUG
256f7df2e56Smrglong SmartLastPrint;
25705b261ecSmrg#endif
25805b261ecSmrg
259f7df2e56Smrgvoid Dispatch(void);
26005b261ecSmrg
2617e31ba66Smrgstatic struct xorg_list ready_clients;
2627e31ba66Smrgstatic struct xorg_list saved_ready_clients;
2637e31ba66Smrgstruct xorg_list output_pending_clients;
2647e31ba66Smrg
2657e31ba66Smrgstatic void
2667e31ba66Smrginit_client_ready(void)
26705b261ecSmrg{
2687e31ba66Smrg    xorg_list_init(&ready_clients);
2697e31ba66Smrg    xorg_list_init(&saved_ready_clients);
2707e31ba66Smrg    xorg_list_init(&output_pending_clients);
2717e31ba66Smrg}
2727e31ba66Smrg
2737e31ba66SmrgBool
2747e31ba66Smrgclients_are_ready(void)
2757e31ba66Smrg{
2767e31ba66Smrg    return !xorg_list_is_empty(&ready_clients);
2777e31ba66Smrg}
2787e31ba66Smrg
2797e31ba66Smrg/* Client has requests queued or data on the network */
2807e31ba66Smrgvoid
2817e31ba66Smrgmark_client_ready(ClientPtr client)
2827e31ba66Smrg{
2837e31ba66Smrg    if (xorg_list_is_empty(&client->ready))
2847e31ba66Smrg        xorg_list_append(&client->ready, &ready_clients);
2857e31ba66Smrg}
2867e31ba66Smrg
2877e31ba66Smrg/*
2887e31ba66Smrg * Client has requests queued or data on the network, but awaits a
2897e31ba66Smrg * server grab release
2907e31ba66Smrg */
2917e31ba66Smrgvoid mark_client_saved_ready(ClientPtr client)
2927e31ba66Smrg{
2937e31ba66Smrg    if (xorg_list_is_empty(&client->ready))
2947e31ba66Smrg        xorg_list_append(&client->ready, &saved_ready_clients);
2957e31ba66Smrg}
2967e31ba66Smrg
2977e31ba66Smrg/* Client has no requests queued and no data on network */
2987e31ba66Smrgvoid
2997e31ba66Smrgmark_client_not_ready(ClientPtr client)
3007e31ba66Smrg{
3017e31ba66Smrg    xorg_list_del(&client->ready);
3027e31ba66Smrg}
3037e31ba66Smrg
3047e31ba66Smrgstatic void
3057e31ba66Smrgmark_client_grab(ClientPtr grab)
3067e31ba66Smrg{
3077e31ba66Smrg    ClientPtr   client, tmp;
3087e31ba66Smrg
3097e31ba66Smrg    xorg_list_for_each_entry_safe(client, tmp, &ready_clients, ready) {
3107e31ba66Smrg        if (client != grab) {
3117e31ba66Smrg            xorg_list_del(&client->ready);
3127e31ba66Smrg            xorg_list_append(&client->ready, &saved_ready_clients);
3137e31ba66Smrg        }
3147e31ba66Smrg    }
3157e31ba66Smrg}
3167e31ba66Smrg
3177e31ba66Smrgstatic void
3187e31ba66Smrgmark_client_ungrab(void)
3197e31ba66Smrg{
3207e31ba66Smrg    ClientPtr   client, tmp;
3217e31ba66Smrg
3227e31ba66Smrg    xorg_list_for_each_entry_safe(client, tmp, &saved_ready_clients, ready) {
3237e31ba66Smrg        xorg_list_del(&client->ready);
3247e31ba66Smrg        xorg_list_append(&client->ready, &ready_clients);
3257e31ba66Smrg    }
3267e31ba66Smrg}
3277e31ba66Smrg
3287e31ba66Smrgstatic ClientPtr
3297e31ba66SmrgSmartScheduleClient(void)
3307e31ba66Smrg{
3317e31ba66Smrg    ClientPtr pClient, best = NULL;
332f7df2e56Smrg    int bestRobin, robin;
333f7df2e56Smrg    long now = SmartScheduleTime;
334f7df2e56Smrg    long idle;
3357e31ba66Smrg    int nready = 0;
33605b261ecSmrg
33705b261ecSmrg    bestRobin = 0;
33805b261ecSmrg    idle = 2 * SmartScheduleSlice;
3397e31ba66Smrg
3407e31ba66Smrg    xorg_list_for_each_entry(pClient, &ready_clients, ready) {
3417e31ba66Smrg        nready++;
3427e31ba66Smrg
343f7df2e56Smrg        /* Praise clients which haven't run in a while */
344f7df2e56Smrg        if ((now - pClient->smart_stop_tick) >= idle) {
345f7df2e56Smrg            if (pClient->smart_priority < 0)
346f7df2e56Smrg                pClient->smart_priority++;
347f7df2e56Smrg        }
348f7df2e56Smrg
349f7df2e56Smrg        /* check priority to select best client */
350f7df2e56Smrg        robin =
351f7df2e56Smrg            (pClient->index -
352f7df2e56Smrg             SmartLastIndex[pClient->smart_priority -
353f7df2e56Smrg                            SMART_MIN_PRIORITY]) & 0xff;
3547e31ba66Smrg
3557e31ba66Smrg        /* pick the best client */
3567e31ba66Smrg        if (!best ||
3577e31ba66Smrg            pClient->priority > best->priority ||
3587e31ba66Smrg            (pClient->priority == best->priority &&
3597e31ba66Smrg             (pClient->smart_priority > best->smart_priority ||
3607e31ba66Smrg              (pClient->smart_priority == best->smart_priority && robin > bestRobin))))
3617e31ba66Smrg        {
3627e31ba66Smrg            best = pClient;
363f7df2e56Smrg            bestRobin = robin;
364f7df2e56Smrg        }
36505b261ecSmrg#ifdef SMART_DEBUG
366f7df2e56Smrg        if ((now - SmartLastPrint) >= 5000)
3677e31ba66Smrg            fprintf(stderr, " %2d: %3d", pClient->index, pClient->smart_priority);
36805b261ecSmrg#endif
36905b261ecSmrg    }
37005b261ecSmrg#ifdef SMART_DEBUG
371f7df2e56Smrg    if ((now - SmartLastPrint) >= 5000) {
3727e31ba66Smrg        fprintf(stderr, " use %2d\n", best->index);
373f7df2e56Smrg        SmartLastPrint = now;
37405b261ecSmrg    }
37505b261ecSmrg#endif
3767e31ba66Smrg    SmartLastIndex[best->smart_priority - SMART_MIN_PRIORITY] = best->index;
37705b261ecSmrg    /*
37805b261ecSmrg     * Set current client pointer
37905b261ecSmrg     */
3807e31ba66Smrg    if (SmartLastClient != best) {
3817e31ba66Smrg        best->smart_start_tick = now;
3827e31ba66Smrg        SmartLastClient = best;
38305b261ecSmrg    }
38405b261ecSmrg    /*
38505b261ecSmrg     * Adjust slice
38605b261ecSmrg     */
387f7df2e56Smrg    if (nready == 1 && SmartScheduleLatencyLimited == 0) {
388f7df2e56Smrg        /*
389f7df2e56Smrg         * If it's been a long time since another client
390f7df2e56Smrg         * has run, bump the slice up to get maximal
391f7df2e56Smrg         * performance from a single client
392f7df2e56Smrg         */
3937e31ba66Smrg        if ((now - best->smart_start_tick) > 1000 &&
394f7df2e56Smrg            SmartScheduleSlice < SmartScheduleMaxSlice) {
395f7df2e56Smrg            SmartScheduleSlice += SmartScheduleInterval;
396f7df2e56Smrg        }
39705b261ecSmrg    }
398f7df2e56Smrg    else {
399f7df2e56Smrg        SmartScheduleSlice = SmartScheduleInterval;
40005b261ecSmrg    }
40105b261ecSmrg    return best;
40205b261ecSmrg}
40305b261ecSmrg
4045a112b11Smrgstatic CARD32
4055a112b11SmrgDispatchExceptionCallback(OsTimerPtr timer, CARD32 time, void *arg)
4065a112b11Smrg{
4075a112b11Smrg    dispatchException |= dispatchExceptionAtReset;
4085a112b11Smrg
4095a112b11Smrg    /* Don't re-arm the timer */
4105a112b11Smrg    return 0;
4115a112b11Smrg}
4125a112b11Smrg
4135a112b11Smrgstatic void
4145a112b11SmrgCancelDispatchExceptionTimer(void)
4155a112b11Smrg{
4165a112b11Smrg    TimerFree(dispatchExceptionTimer);
4175a112b11Smrg    dispatchExceptionTimer = NULL;
4185a112b11Smrg}
4195a112b11Smrg
4205a112b11Smrgstatic void
4215a112b11SmrgSetDispatchExceptionTimer(void)
4225a112b11Smrg{
4235a112b11Smrg    /* The timer delay is only for terminate, not reset */
4245a112b11Smrg    if (!(dispatchExceptionAtReset & DE_TERMINATE)) {
4255a112b11Smrg        dispatchException |= dispatchExceptionAtReset;
4265a112b11Smrg        return;
4275a112b11Smrg    }
4285a112b11Smrg
4295a112b11Smrg    CancelDispatchExceptionTimer();
4305a112b11Smrg
4315a112b11Smrg    if (terminateDelay == 0)
4325a112b11Smrg        dispatchException |= dispatchExceptionAtReset;
4335a112b11Smrg    else
4345a112b11Smrg        dispatchExceptionTimer = TimerSet(dispatchExceptionTimer,
4355a112b11Smrg                                          0, terminateDelay * 1000 /* msec */,
4365a112b11Smrg                                          &DispatchExceptionCallback,
4375a112b11Smrg                                          NULL);
4385a112b11Smrg}
4395a112b11Smrg
4405a112b11Smrgstatic Bool
4415a112b11SmrgShouldDisconnectRemainingClients(void)
4425a112b11Smrg{
4435a112b11Smrg    int i;
4445a112b11Smrg
4455a112b11Smrg    for (i = 1; i < currentMaxClients; i++) {
4465a112b11Smrg        if (clients[i]) {
4475a112b11Smrg            if (!XFixesShouldDisconnectClient(clients[i]))
4485a112b11Smrg                return FALSE;
4495a112b11Smrg        }
4505a112b11Smrg    }
4515a112b11Smrg
4525a112b11Smrg    /* All remaining clients can be safely ignored */
4535a112b11Smrg    return TRUE;
4545a112b11Smrg}
4555a112b11Smrg
456b1d344b3Smrgvoid
457b1d344b3SmrgEnableLimitedSchedulingLatency(void)
458b1d344b3Smrg{
459b1d344b3Smrg    ++SmartScheduleLatencyLimited;
460b1d344b3Smrg    SmartScheduleSlice = SmartScheduleInterval;
461b1d344b3Smrg}
462b1d344b3Smrg
463b1d344b3Smrgvoid
464b1d344b3SmrgDisableLimitedSchedulingLatency(void)
465b1d344b3Smrg{
466b1d344b3Smrg    --SmartScheduleLatencyLimited;
467b1d344b3Smrg
468b1d344b3Smrg    /* protect against bugs */
469b1d344b3Smrg    if (SmartScheduleLatencyLimited < 0)
470f7df2e56Smrg        SmartScheduleLatencyLimited = 0;
471b1d344b3Smrg}
472b1d344b3Smrg
47305b261ecSmrgvoid
47405b261ecSmrgDispatch(void)
47505b261ecSmrg{
476f7df2e56Smrg    int result;
477f7df2e56Smrg    ClientPtr client;
478f7df2e56Smrg    long start_tick;
47905b261ecSmrg
48005b261ecSmrg    nextFreeClientID = 1;
48105b261ecSmrg    nClients = 0;
48205b261ecSmrg
483b1d344b3Smrg    SmartScheduleSlice = SmartScheduleInterval;
4847e31ba66Smrg    init_client_ready();
4857e31ba66Smrg
486f7df2e56Smrg    while (!dispatchException) {
4877e31ba66Smrg        if (InputCheckPending()) {
488f7df2e56Smrg            ProcessInputEvents();
489f7df2e56Smrg            FlushIfCriticalOutputPending();
490f7df2e56Smrg        }
491f7df2e56Smrg
4927e31ba66Smrg        if (!WaitForSomething(clients_are_ready()))
4937e31ba66Smrg            continue;
494f7df2e56Smrg
495f7df2e56Smrg       /*****************
496f7df2e56Smrg	*  Handle events in round robin fashion, doing input between
497f7df2e56Smrg	*  each round
49805b261ecSmrg	*****************/
49905b261ecSmrg
5007e31ba66Smrg        if (!dispatchException && clients_are_ready()) {
5017e31ba66Smrg            client = SmartScheduleClient();
5027e31ba66Smrg
503f7df2e56Smrg            isItTimeToYield = FALSE;
504f7df2e56Smrg
505f7df2e56Smrg            start_tick = SmartScheduleTime;
506f7df2e56Smrg            while (!isItTimeToYield) {
5077e31ba66Smrg                if (InputCheckPending())
508f7df2e56Smrg                    ProcessInputEvents();
509f7df2e56Smrg
510f7df2e56Smrg                FlushIfCriticalOutputPending();
5117e31ba66Smrg                if ((SmartScheduleTime - start_tick) >= SmartScheduleSlice)
5127e31ba66Smrg                {
513f7df2e56Smrg                    /* Penalize clients which consume ticks */
514f7df2e56Smrg                    if (client->smart_priority > SMART_MIN_PRIORITY)
515f7df2e56Smrg                        client->smart_priority--;
516f7df2e56Smrg                    break;
517f7df2e56Smrg                }
518f7df2e56Smrg
5197e31ba66Smrg                /* now, finally, deal with client requests */
520f7df2e56Smrg                result = ReadRequestFromClient(client);
521f7df2e56Smrg                if (result <= 0) {
522f7df2e56Smrg                    if (result < 0)
523f7df2e56Smrg                        CloseDownClient(client);
524f7df2e56Smrg                    break;
525f7df2e56Smrg                }
526f7df2e56Smrg
527f7df2e56Smrg                client->sequence++;
528f7df2e56Smrg                client->majorOp = ((xReq *) client->requestBuffer)->reqType;
529f7df2e56Smrg                client->minorOp = 0;
530f7df2e56Smrg                if (client->majorOp >= EXTENSION_BASE) {
531f7df2e56Smrg                    ExtensionEntry *ext = GetExtensionEntry(client->majorOp);
532f7df2e56Smrg
533f7df2e56Smrg                    if (ext)
534f7df2e56Smrg                        client->minorOp = ext->MinorOpcode(client);
535f7df2e56Smrg                }
53605b261ecSmrg#ifdef XSERVER_DTRACE
537f7df2e56Smrg                if (XSERVER_REQUEST_START_ENABLED())
538f7df2e56Smrg                    XSERVER_REQUEST_START(LookupMajorName(client->majorOp),
539f7df2e56Smrg                                          client->majorOp,
540f7df2e56Smrg                                          ((xReq *) client->requestBuffer)->length,
541f7df2e56Smrg                                          client->index,
542f7df2e56Smrg                                          client->requestBuffer);
54305b261ecSmrg#endif
544f7df2e56Smrg                if (result > (maxBigRequestSize << 2))
545f7df2e56Smrg                    result = BadLength;
546f7df2e56Smrg                else {
547f7df2e56Smrg                    result = XaceHookDispatch(client, client->majorOp);
5485a112b11Smrg                    if (result == Success) {
5495a112b11Smrg                        currentClient = client;
550f7df2e56Smrg                        result =
551f7df2e56Smrg                            (*client->requestVector[client->majorOp]) (client);
5525a112b11Smrg                        currentClient = NULL;
5535a112b11Smrg                    }
554f7df2e56Smrg                }
5557e31ba66Smrg                if (!SmartScheduleSignalEnable)
5567e31ba66Smrg                    SmartScheduleTime = GetTimeInMillis();
5577e31ba66Smrg
55805b261ecSmrg#ifdef XSERVER_DTRACE
559f7df2e56Smrg                if (XSERVER_REQUEST_DONE_ENABLED())
560f7df2e56Smrg                    XSERVER_REQUEST_DONE(LookupMajorName(client->majorOp),
561f7df2e56Smrg                                         client->majorOp, client->sequence,
562f7df2e56Smrg                                         client->index, result);
56305b261ecSmrg#endif
56405b261ecSmrg
565f7df2e56Smrg                if (client->noClientException != Success) {
566f7df2e56Smrg                    CloseDownClient(client);
567f7df2e56Smrg                    break;
568f7df2e56Smrg                }
569f7df2e56Smrg                else if (result != Success) {
570f7df2e56Smrg                    SendErrorToClient(client, client->majorOp,
571f7df2e56Smrg                                      client->minorOp,
572f7df2e56Smrg                                      client->errorValue, result);
573f7df2e56Smrg                    break;
574f7df2e56Smrg                }
575f7df2e56Smrg            }
576f7df2e56Smrg            FlushAllOutput();
5777e31ba66Smrg            if (client == SmartLastClient)
578f7df2e56Smrg                client->smart_stop_tick = SmartScheduleTime;
579f7df2e56Smrg        }
580f7df2e56Smrg        dispatchException &= ~DE_PRIORITYCHANGE;
58105b261ecSmrg    }
58205b261ecSmrg#if defined(DDXBEFORERESET)
583f7df2e56Smrg    ddxBeforeReset();
58405b261ecSmrg#endif
58505b261ecSmrg    KillAllClients();
58605b261ecSmrg    dispatchException &= ~DE_RESET;
587b1d344b3Smrg    SmartScheduleLatencyLimited = 0;
588f7df2e56Smrg    ResetOsBuffers();
58905b261ecSmrg}
59005b261ecSmrg
591f7df2e56Smrgstatic int VendorRelease = VENDOR_RELEASE;
5926747b715Smrg
5936747b715Smrgvoid
5946747b715SmrgSetVendorRelease(int release)
5956747b715Smrg{
5966747b715Smrg    VendorRelease = release;
5976747b715Smrg}
5986747b715Smrg
5996747b715SmrgBool
6006747b715SmrgCreateConnectionBlock(void)
6016747b715Smrg{
6026747b715Smrg    xConnSetup setup;
6036747b715Smrg    xWindowRoot root;
604f7df2e56Smrg    xDepth depth;
6056747b715Smrg    xVisualType visual;
6066747b715Smrg    xPixmapFormat format;
6076747b715Smrg    unsigned long vid;
608f7df2e56Smrg    int i, j, k, lenofblock, sizesofar = 0;
6096747b715Smrg    char *pBuf;
6105a112b11Smrg    const char VendorString[] = VENDOR_NAME;
6116747b715Smrg
6126747b715Smrg    memset(&setup, 0, sizeof(xConnSetup));
6136747b715Smrg    /* Leave off the ridBase and ridMask, these must be sent with
6146747b715Smrg       connection */
6156747b715Smrg
6166747b715Smrg    setup.release = VendorRelease;
6176747b715Smrg    /*
6186747b715Smrg     * per-server image and bitmap parameters are defined in Xmd.h
6196747b715Smrg     */
6206747b715Smrg    setup.imageByteOrder = screenInfo.imageByteOrder;
6216747b715Smrg
6226747b715Smrg    setup.bitmapScanlineUnit = screenInfo.bitmapScanlineUnit;
6236747b715Smrg    setup.bitmapScanlinePad = screenInfo.bitmapScanlinePad;
6246747b715Smrg
6256747b715Smrg    setup.bitmapBitOrder = screenInfo.bitmapBitOrder;
6266747b715Smrg    setup.motionBufferSize = NumMotionEvents();
6276747b715Smrg    setup.numRoots = screenInfo.numScreens;
6286747b715Smrg    setup.nbytesVendor = strlen(VendorString);
6296747b715Smrg    setup.numFormats = screenInfo.numPixmapFormats;
6306747b715Smrg    setup.maxRequestSize = MAX_REQUEST_SIZE;
6316747b715Smrg    QueryMinMaxKeyCodes(&setup.minKeyCode, &setup.maxKeyCode);
6326747b715Smrg
6336747b715Smrg    lenofblock = sizeof(xConnSetup) +
634f7df2e56Smrg        pad_to_int32(setup.nbytesVendor) +
635f7df2e56Smrg        (setup.numFormats * sizeof(xPixmapFormat)) +
636f7df2e56Smrg        (setup.numRoots * sizeof(xWindowRoot));
6376747b715Smrg    ConnectionInfo = malloc(lenofblock);
6386747b715Smrg    if (!ConnectionInfo)
639f7df2e56Smrg        return FALSE;
6406747b715Smrg
641f7df2e56Smrg    memmove(ConnectionInfo, (char *) &setup, sizeof(xConnSetup));
6426747b715Smrg    sizesofar = sizeof(xConnSetup);
6436747b715Smrg    pBuf = ConnectionInfo + sizeof(xConnSetup);
6446747b715Smrg
645f7df2e56Smrg    memmove(pBuf, VendorString, (int) setup.nbytesVendor);
6466747b715Smrg    sizesofar += setup.nbytesVendor;
6476747b715Smrg    pBuf += setup.nbytesVendor;
648f7df2e56Smrg    i = padding_for_int32(setup.nbytesVendor);
6496747b715Smrg    sizesofar += i;
6506747b715Smrg    while (--i >= 0)
651f7df2e56Smrg        *pBuf++ = 0;
6526747b715Smrg
6536747b715Smrg    memset(&format, 0, sizeof(xPixmapFormat));
654f7df2e56Smrg    for (i = 0; i < screenInfo.numPixmapFormats; i++) {
655f7df2e56Smrg        format.depth = screenInfo.formats[i].depth;
656f7df2e56Smrg        format.bitsPerPixel = screenInfo.formats[i].bitsPerPixel;
657f7df2e56Smrg        format.scanLinePad = screenInfo.formats[i].scanlinePad;
658f7df2e56Smrg        memmove(pBuf, (char *) &format, sizeof(xPixmapFormat));
659f7df2e56Smrg        pBuf += sizeof(xPixmapFormat);
660f7df2e56Smrg        sizesofar += sizeof(xPixmapFormat);
6616747b715Smrg    }
6626747b715Smrg
6636747b715Smrg    connBlockScreenStart = sizesofar;
6646747b715Smrg    memset(&depth, 0, sizeof(xDepth));
6656747b715Smrg    memset(&visual, 0, sizeof(xVisualType));
666f7df2e56Smrg    for (i = 0; i < screenInfo.numScreens; i++) {
667f7df2e56Smrg        ScreenPtr pScreen;
668f7df2e56Smrg        DepthPtr pDepth;
669f7df2e56Smrg        VisualPtr pVisual;
670f7df2e56Smrg
671f7df2e56Smrg        pScreen = screenInfo.screens[i];
672f7df2e56Smrg        root.windowId = pScreen->root->drawable.id;
673f7df2e56Smrg        root.defaultColormap = pScreen->defColormap;
674f7df2e56Smrg        root.whitePixel = pScreen->whitePixel;
675f7df2e56Smrg        root.blackPixel = pScreen->blackPixel;
676f7df2e56Smrg        root.currentInputMask = 0;      /* filled in when sent */
677f7df2e56Smrg        root.pixWidth = pScreen->width;
678f7df2e56Smrg        root.pixHeight = pScreen->height;
679f7df2e56Smrg        root.mmWidth = pScreen->mmWidth;
680f7df2e56Smrg        root.mmHeight = pScreen->mmHeight;
681f7df2e56Smrg        root.minInstalledMaps = pScreen->minInstalledCmaps;
682f7df2e56Smrg        root.maxInstalledMaps = pScreen->maxInstalledCmaps;
683f7df2e56Smrg        root.rootVisualID = pScreen->rootVisual;
684f7df2e56Smrg        root.backingStore = pScreen->backingStoreSupport;
685f7df2e56Smrg        root.saveUnders = FALSE;
686f7df2e56Smrg        root.rootDepth = pScreen->rootDepth;
687f7df2e56Smrg        root.nDepths = pScreen->numDepths;
688f7df2e56Smrg        memmove(pBuf, (char *) &root, sizeof(xWindowRoot));
689f7df2e56Smrg        sizesofar += sizeof(xWindowRoot);
690f7df2e56Smrg        pBuf += sizeof(xWindowRoot);
691f7df2e56Smrg
692f7df2e56Smrg        pDepth = pScreen->allowedDepths;
693f7df2e56Smrg        for (j = 0; j < pScreen->numDepths; j++, pDepth++) {
694f7df2e56Smrg            lenofblock += sizeof(xDepth) +
695f7df2e56Smrg                (pDepth->numVids * sizeof(xVisualType));
696f7df2e56Smrg            pBuf = (char *) realloc(ConnectionInfo, lenofblock);
697f7df2e56Smrg            if (!pBuf) {
698f7df2e56Smrg                free(ConnectionInfo);
699f7df2e56Smrg                return FALSE;
700f7df2e56Smrg            }
701f7df2e56Smrg            ConnectionInfo = pBuf;
702f7df2e56Smrg            pBuf += sizesofar;
703f7df2e56Smrg            depth.depth = pDepth->depth;
704f7df2e56Smrg            depth.nVisuals = pDepth->numVids;
705f7df2e56Smrg            memmove(pBuf, (char *) &depth, sizeof(xDepth));
706f7df2e56Smrg            pBuf += sizeof(xDepth);
707f7df2e56Smrg            sizesofar += sizeof(xDepth);
708f7df2e56Smrg            for (k = 0; k < pDepth->numVids; k++) {
709f7df2e56Smrg                vid = pDepth->vids[k];
710f7df2e56Smrg                for (pVisual = pScreen->visuals;
711f7df2e56Smrg                     pVisual->vid != vid; pVisual++);
712f7df2e56Smrg                visual.visualID = vid;
713f7df2e56Smrg                visual.class = pVisual->class;
714f7df2e56Smrg                visual.bitsPerRGB = pVisual->bitsPerRGBValue;
715f7df2e56Smrg                visual.colormapEntries = pVisual->ColormapEntries;
716f7df2e56Smrg                visual.redMask = pVisual->redMask;
717f7df2e56Smrg                visual.greenMask = pVisual->greenMask;
718f7df2e56Smrg                visual.blueMask = pVisual->blueMask;
719f7df2e56Smrg                memmove(pBuf, (char *) &visual, sizeof(xVisualType));
720f7df2e56Smrg                pBuf += sizeof(xVisualType);
721f7df2e56Smrg                sizesofar += sizeof(xVisualType);
722f7df2e56Smrg            }
723f7df2e56Smrg        }
7246747b715Smrg    }
7256747b715Smrg    connSetupPrefix.success = xTrue;
726f7df2e56Smrg    connSetupPrefix.length = lenofblock / 4;
7276747b715Smrg    connSetupPrefix.majorVersion = X_PROTOCOL;
7286747b715Smrg    connSetupPrefix.minorVersion = X_PROTOCOL_REVISION;
7296747b715Smrg    return TRUE;
7306747b715Smrg}
7316747b715Smrg
7326747b715Smrgint
73305b261ecSmrgProcBadRequest(ClientPtr client)
73405b261ecSmrg{
7356747b715Smrg    return BadRequest;
73605b261ecSmrg}
73705b261ecSmrg
73805b261ecSmrgint
73905b261ecSmrgProcCreateWindow(ClientPtr client)
74005b261ecSmrg{
74105b261ecSmrg    WindowPtr pParent, pWin;
742f7df2e56Smrg
74305b261ecSmrg    REQUEST(xCreateWindowReq);
7444642e01fSmrg    int len, rc;
74505b261ecSmrg
74605b261ecSmrg    REQUEST_AT_LEAST_SIZE(xCreateWindowReq);
747f7df2e56Smrg
74805b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->wid, client);
7494642e01fSmrg    rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess);
75005b261ecSmrg    if (rc != Success)
75105b261ecSmrg        return rc;
7526747b715Smrg    len = client->req_len - bytes_to_int32(sizeof(xCreateWindowReq));
75305b261ecSmrg    if (Ones(stuff->mask) != len)
75405b261ecSmrg        return BadLength;
755f7df2e56Smrg    if (!stuff->width || !stuff->height) {
756f7df2e56Smrg        client->errorValue = 0;
75705b261ecSmrg        return BadValue;
75805b261ecSmrg    }
75905b261ecSmrg    pWin = CreateWindow(stuff->wid, pParent, stuff->x,
760f7df2e56Smrg                        stuff->y, stuff->width, stuff->height,
761f7df2e56Smrg                        stuff->borderWidth, stuff->class,
762f7df2e56Smrg                        stuff->mask, (XID *) &stuff[1],
763f7df2e56Smrg                        (int) stuff->depth, client, stuff->visual, &rc);
764f7df2e56Smrg    if (pWin) {
765f7df2e56Smrg        Mask mask = pWin->eventMask;
766f7df2e56Smrg
767f7df2e56Smrg        pWin->eventMask = 0;    /* subterfuge in case AddResource fails */
768f7df2e56Smrg        if (!AddResource(stuff->wid, RT_WINDOW, (void *) pWin))
769f7df2e56Smrg            return BadAlloc;
770f7df2e56Smrg        pWin->eventMask = mask;
77105b261ecSmrg    }
7726747b715Smrg    return rc;
77305b261ecSmrg}
77405b261ecSmrg
77505b261ecSmrgint
77605b261ecSmrgProcChangeWindowAttributes(ClientPtr client)
77705b261ecSmrg{
77805b261ecSmrg    WindowPtr pWin;
779f7df2e56Smrg
78005b261ecSmrg    REQUEST(xChangeWindowAttributesReq);
7816747b715Smrg    int len, rc;
7824642e01fSmrg    Mask access_mode = 0;
78305b261ecSmrg
78405b261ecSmrg    REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq);
7854642e01fSmrg    access_mode |= (stuff->valueMask & CWEventMask) ? DixReceiveAccess : 0;
7864642e01fSmrg    access_mode |= (stuff->valueMask & ~CWEventMask) ? DixSetAttrAccess : 0;
7874642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, access_mode);
78805b261ecSmrg    if (rc != Success)
78905b261ecSmrg        return rc;
7906747b715Smrg    len = client->req_len - bytes_to_int32(sizeof(xChangeWindowAttributesReq));
79105b261ecSmrg    if (len != Ones(stuff->valueMask))
79205b261ecSmrg        return BadLength;
7936747b715Smrg    return ChangeWindowAttributes(pWin,
794f7df2e56Smrg                                  stuff->valueMask, (XID *) &stuff[1], client);
79505b261ecSmrg}
79605b261ecSmrg
79705b261ecSmrgint
79805b261ecSmrgProcGetWindowAttributes(ClientPtr client)
79905b261ecSmrg{
80005b261ecSmrg    WindowPtr pWin;
801f7df2e56Smrg
80205b261ecSmrg    REQUEST(xResourceReq);
80305b261ecSmrg    xGetWindowAttributesReply wa;
80405b261ecSmrg    int rc;
80505b261ecSmrg
80605b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
8074642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
80805b261ecSmrg    if (rc != Success)
809f7df2e56Smrg        return rc;
8106747b715Smrg    memset(&wa, 0, sizeof(xGetWindowAttributesReply));
81105b261ecSmrg    GetWindowAttributes(pWin, client, &wa);
81205b261ecSmrg    WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa);
8136747b715Smrg    return Success;
81405b261ecSmrg}
81505b261ecSmrg
81605b261ecSmrgint
81705b261ecSmrgProcDestroyWindow(ClientPtr client)
81805b261ecSmrg{
81905b261ecSmrg    WindowPtr pWin;
820f7df2e56Smrg
82105b261ecSmrg    REQUEST(xResourceReq);
82205b261ecSmrg    int rc;
82305b261ecSmrg
82405b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
82505b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixDestroyAccess);
82605b261ecSmrg    if (rc != Success)
827f7df2e56Smrg        return rc;
8284642e01fSmrg    if (pWin->parent) {
829f7df2e56Smrg        rc = dixLookupWindow(&pWin, pWin->parent->drawable.id, client,
830f7df2e56Smrg                             DixRemoveAccess);
831f7df2e56Smrg        if (rc != Success)
832f7df2e56Smrg            return rc;
833f7df2e56Smrg        FreeResource(stuff->id, RT_NONE);
8344642e01fSmrg    }
8356747b715Smrg    return Success;
83605b261ecSmrg}
83705b261ecSmrg
83805b261ecSmrgint
83905b261ecSmrgProcDestroySubwindows(ClientPtr client)
84005b261ecSmrg{
84105b261ecSmrg    WindowPtr pWin;
842f7df2e56Smrg
84305b261ecSmrg    REQUEST(xResourceReq);
84405b261ecSmrg    int rc;
84505b261ecSmrg
84605b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
8474642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixRemoveAccess);
84805b261ecSmrg    if (rc != Success)
849f7df2e56Smrg        return rc;
85005b261ecSmrg    DestroySubwindows(pWin, client);
8516747b715Smrg    return Success;
85205b261ecSmrg}
85305b261ecSmrg
85405b261ecSmrgint
85505b261ecSmrgProcChangeSaveSet(ClientPtr client)
85605b261ecSmrg{
85705b261ecSmrg    WindowPtr pWin;
858f7df2e56Smrg
85905b261ecSmrg    REQUEST(xChangeSaveSetReq);
8606747b715Smrg    int rc;
861f7df2e56Smrg
86205b261ecSmrg    REQUEST_SIZE_MATCH(xChangeSaveSetReq);
8634642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
86405b261ecSmrg    if (rc != Success)
86505b261ecSmrg        return rc;
86605b261ecSmrg    if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id)))
86705b261ecSmrg        return BadMatch;
86805b261ecSmrg    if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete))
8696747b715Smrg        return AlterSaveSetForClient(client, pWin, stuff->mode, FALSE, TRUE);
8706747b715Smrg    client->errorValue = stuff->mode;
8716747b715Smrg    return BadValue;
87205b261ecSmrg}
87305b261ecSmrg
87405b261ecSmrgint
87505b261ecSmrgProcReparentWindow(ClientPtr client)
87605b261ecSmrg{
87705b261ecSmrg    WindowPtr pWin, pParent;
878f7df2e56Smrg
87905b261ecSmrg    REQUEST(xReparentWindowReq);
8806747b715Smrg    int rc;
88105b261ecSmrg
88205b261ecSmrg    REQUEST_SIZE_MATCH(xReparentWindowReq);
8834642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
88405b261ecSmrg    if (rc != Success)
88505b261ecSmrg        return rc;
8864642e01fSmrg    rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess);
88705b261ecSmrg    if (rc != Success)
88805b261ecSmrg        return rc;
8896747b715Smrg    if (!SAME_SCREENS(pWin->drawable, pParent->drawable))
890f7df2e56Smrg        return BadMatch;
8916747b715Smrg    if ((pWin->backgroundState == ParentRelative) &&
892f7df2e56Smrg        (pParent->drawable.depth != pWin->drawable.depth))
893f7df2e56Smrg        return BadMatch;
8946747b715Smrg    if ((pWin->drawable.class != InputOnly) &&
895f7df2e56Smrg        (pParent->drawable.class == InputOnly))
896f7df2e56Smrg        return BadMatch;
8976747b715Smrg    return ReparentWindow(pWin, pParent,
898f7df2e56Smrg                          (short) stuff->x, (short) stuff->y, client);
89905b261ecSmrg}
90005b261ecSmrg
90105b261ecSmrgint
90205b261ecSmrgProcMapWindow(ClientPtr client)
90305b261ecSmrg{
90405b261ecSmrg    WindowPtr pWin;
905f7df2e56Smrg
90605b261ecSmrg    REQUEST(xResourceReq);
90705b261ecSmrg    int rc;
90805b261ecSmrg
90905b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
9104642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixShowAccess);
91105b261ecSmrg    if (rc != Success)
91205b261ecSmrg        return rc;
91305b261ecSmrg    MapWindow(pWin, client);
914f7df2e56Smrg    /* update cache to say it is mapped */
9156747b715Smrg    return Success;
91605b261ecSmrg}
91705b261ecSmrg
91805b261ecSmrgint
91905b261ecSmrgProcMapSubwindows(ClientPtr client)
92005b261ecSmrg{
92105b261ecSmrg    WindowPtr pWin;
922f7df2e56Smrg
92305b261ecSmrg    REQUEST(xResourceReq);
92405b261ecSmrg    int rc;
92505b261ecSmrg
92605b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
9274642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
92805b261ecSmrg    if (rc != Success)
92905b261ecSmrg        return rc;
93005b261ecSmrg    MapSubwindows(pWin, client);
931f7df2e56Smrg    /* update cache to say it is mapped */
9326747b715Smrg    return Success;
93305b261ecSmrg}
93405b261ecSmrg
93505b261ecSmrgint
93605b261ecSmrgProcUnmapWindow(ClientPtr client)
93705b261ecSmrg{
93805b261ecSmrg    WindowPtr pWin;
939f7df2e56Smrg
94005b261ecSmrg    REQUEST(xResourceReq);
94105b261ecSmrg    int rc;
94205b261ecSmrg
94305b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
9444642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixHideAccess);
94505b261ecSmrg    if (rc != Success)
94605b261ecSmrg        return rc;
94705b261ecSmrg    UnmapWindow(pWin, FALSE);
948f7df2e56Smrg    /* update cache to say it is mapped */
9496747b715Smrg    return Success;
95005b261ecSmrg}
95105b261ecSmrg
95205b261ecSmrgint
95305b261ecSmrgProcUnmapSubwindows(ClientPtr client)
95405b261ecSmrg{
95505b261ecSmrg    WindowPtr pWin;
956f7df2e56Smrg
95705b261ecSmrg    REQUEST(xResourceReq);
95805b261ecSmrg    int rc;
95905b261ecSmrg
96005b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
9614642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
96205b261ecSmrg    if (rc != Success)
96305b261ecSmrg        return rc;
96405b261ecSmrg    UnmapSubwindows(pWin);
9656747b715Smrg    return Success;
96605b261ecSmrg}
96705b261ecSmrg
96805b261ecSmrgint
96905b261ecSmrgProcConfigureWindow(ClientPtr client)
97005b261ecSmrg{
97105b261ecSmrg    WindowPtr pWin;
972f7df2e56Smrg
97305b261ecSmrg    REQUEST(xConfigureWindowReq);
97405b261ecSmrg    int len, rc;
97505b261ecSmrg
97605b261ecSmrg    REQUEST_AT_LEAST_SIZE(xConfigureWindowReq);
9774642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client,
978f7df2e56Smrg                         DixManageAccess | DixSetAttrAccess);
97905b261ecSmrg    if (rc != Success)
98005b261ecSmrg        return rc;
9816747b715Smrg    len = client->req_len - bytes_to_int32(sizeof(xConfigureWindowReq));
982f7df2e56Smrg    if (Ones((Mask) stuff->mask) != len)
98305b261ecSmrg        return BadLength;
984f7df2e56Smrg    return ConfigureWindow(pWin, (Mask) stuff->mask, (XID *) &stuff[1], client);
98505b261ecSmrg}
98605b261ecSmrg
98705b261ecSmrgint
98805b261ecSmrgProcCirculateWindow(ClientPtr client)
98905b261ecSmrg{
99005b261ecSmrg    WindowPtr pWin;
991f7df2e56Smrg
99205b261ecSmrg    REQUEST(xCirculateWindowReq);
99305b261ecSmrg    int rc;
99405b261ecSmrg
99505b261ecSmrg    REQUEST_SIZE_MATCH(xCirculateWindowReq);
996f7df2e56Smrg    if ((stuff->direction != RaiseLowest) && (stuff->direction != LowerHighest)) {
997f7df2e56Smrg        client->errorValue = stuff->direction;
99805b261ecSmrg        return BadValue;
99905b261ecSmrg    }
10004642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
100105b261ecSmrg    if (rc != Success)
100205b261ecSmrg        return rc;
1003f7df2e56Smrg    CirculateWindow(pWin, (int) stuff->direction, client);
10046747b715Smrg    return Success;
100505b261ecSmrg}
100605b261ecSmrg
100705b261ecSmrgstatic int
1008f7df2e56SmrgGetGeometry(ClientPtr client, xGetGeometryReply * rep)
100905b261ecSmrg{
101005b261ecSmrg    DrawablePtr pDraw;
101105b261ecSmrg    int rc;
1012f7df2e56Smrg
101305b261ecSmrg    REQUEST(xResourceReq);
101405b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
101505b261ecSmrg
10164642e01fSmrg    rc = dixLookupDrawable(&pDraw, stuff->id, client, M_ANY, DixGetAttrAccess);
101705b261ecSmrg    if (rc != Success)
1018f7df2e56Smrg        return rc;
101905b261ecSmrg
102005b261ecSmrg    rep->type = X_Reply;
102105b261ecSmrg    rep->length = 0;
102205b261ecSmrg    rep->sequenceNumber = client->sequence;
10236747b715Smrg    rep->root = pDraw->pScreen->root->drawable.id;
102405b261ecSmrg    rep->depth = pDraw->depth;
102505b261ecSmrg    rep->width = pDraw->width;
102605b261ecSmrg    rep->height = pDraw->height;
102705b261ecSmrg
1028f7df2e56Smrg    if (WindowDrawable(pDraw->type)) {
1029f7df2e56Smrg        WindowPtr pWin = (WindowPtr) pDraw;
1030f7df2e56Smrg
1031f7df2e56Smrg        rep->x = pWin->origin.x - wBorderWidth(pWin);
1032f7df2e56Smrg        rep->y = pWin->origin.y - wBorderWidth(pWin);
1033f7df2e56Smrg        rep->borderWidth = pWin->borderWidth;
103405b261ecSmrg    }
1035f7df2e56Smrg    else {                      /* DRAWABLE_PIXMAP */
1036f7df2e56Smrg
1037f7df2e56Smrg        rep->x = rep->y = rep->borderWidth = 0;
103805b261ecSmrg    }
103905b261ecSmrg
104005b261ecSmrg    return Success;
104105b261ecSmrg}
104205b261ecSmrg
104305b261ecSmrgint
104405b261ecSmrgProcGetGeometry(ClientPtr client)
104505b261ecSmrg{
1046f7df2e56Smrg    xGetGeometryReply rep = { .type = X_Reply };
104705b261ecSmrg    int status;
104805b261ecSmrg
104905b261ecSmrg    if ((status = GetGeometry(client, &rep)) != Success)
1050f7df2e56Smrg        return status;
105105b261ecSmrg
105205b261ecSmrg    WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep);
10536747b715Smrg    return Success;
105405b261ecSmrg}
105505b261ecSmrg
105605b261ecSmrgint
105705b261ecSmrgProcQueryTree(ClientPtr client)
105805b261ecSmrg{
105905b261ecSmrg    xQueryTreeReply reply;
106005b261ecSmrg    int rc, numChildren = 0;
106105b261ecSmrg    WindowPtr pChild, pWin, pHead;
1062f7df2e56Smrg    Window *childIDs = (Window *) NULL;
1063f7df2e56Smrg
106405b261ecSmrg    REQUEST(xResourceReq);
106505b261ecSmrg
106605b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
10674642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
106805b261ecSmrg    if (rc != Success)
106905b261ecSmrg        return rc;
1070f7df2e56Smrg
1071f7df2e56Smrg    reply = (xQueryTreeReply) {
1072f7df2e56Smrg        .type = X_Reply,
1073f7df2e56Smrg        .sequenceNumber = client->sequence,
1074f7df2e56Smrg        .root = pWin->drawable.pScreen->root->drawable.id,
1075f7df2e56Smrg        .parent = (pWin->parent) ? pWin->parent->drawable.id : (Window) None
1076f7df2e56Smrg    };
107705b261ecSmrg    pHead = RealChildHead(pWin);
107805b261ecSmrg    for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
1079f7df2e56Smrg        numChildren++;
1080f7df2e56Smrg    if (numChildren) {
1081f7df2e56Smrg        int curChild = 0;
108205b261ecSmrg
1083f7df2e56Smrg        childIDs = xallocarray(numChildren, sizeof(Window));
1084f7df2e56Smrg        if (!childIDs)
1085f7df2e56Smrg            return BadAlloc;
1086f7df2e56Smrg        for (pChild = pWin->lastChild; pChild != pHead;
1087f7df2e56Smrg             pChild = pChild->prevSib)
1088f7df2e56Smrg            childIDs[curChild++] = pChild->drawable.id;
108905b261ecSmrg    }
1090f7df2e56Smrg
109105b261ecSmrg    reply.nChildren = numChildren;
10926747b715Smrg    reply.length = bytes_to_int32(numChildren * sizeof(Window));
1093f7df2e56Smrg
109405b261ecSmrg    WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply);
1095f7df2e56Smrg    if (numChildren) {
1096f7df2e56Smrg        client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
1097f7df2e56Smrg        WriteSwappedDataToClient(client, numChildren * sizeof(Window),
1098f7df2e56Smrg                                 childIDs);
1099f7df2e56Smrg        free(childIDs);
110005b261ecSmrg    }
110105b261ecSmrg
11026747b715Smrg    return Success;
110305b261ecSmrg}
110405b261ecSmrg
110505b261ecSmrgint
110605b261ecSmrgProcInternAtom(ClientPtr client)
110705b261ecSmrg{
110805b261ecSmrg    Atom atom;
110905b261ecSmrg    char *tchar;
1110f7df2e56Smrg
111105b261ecSmrg    REQUEST(xInternAtomReq);
111205b261ecSmrg
111305b261ecSmrg    REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes);
1114f7df2e56Smrg    if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse)) {
1115f7df2e56Smrg        client->errorValue = stuff->onlyIfExists;
11166747b715Smrg        return BadValue;
111705b261ecSmrg    }
111805b261ecSmrg    tchar = (char *) &stuff[1];
111905b261ecSmrg    atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists);
1120f7df2e56Smrg    if (atom != BAD_RESOURCE) {
1121f7df2e56Smrg        xInternAtomReply reply = {
1122f7df2e56Smrg            .type = X_Reply,
1123f7df2e56Smrg            .sequenceNumber = client->sequence,
1124f7df2e56Smrg            .length = 0,
1125f7df2e56Smrg            .atom = atom
1126f7df2e56Smrg        };
1127f7df2e56Smrg        WriteReplyToClient(client, sizeof(xInternAtomReply), &reply);
1128f7df2e56Smrg        return Success;
112905b261ecSmrg    }
113005b261ecSmrg    else
1131f7df2e56Smrg        return BadAlloc;
113205b261ecSmrg}
113305b261ecSmrg
113405b261ecSmrgint
113505b261ecSmrgProcGetAtomName(ClientPtr client)
113605b261ecSmrg{
11376747b715Smrg    const char *str;
1138f7df2e56Smrg
113905b261ecSmrg    REQUEST(xResourceReq);
114005b261ecSmrg
114105b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
1142f7df2e56Smrg    if ((str = NameForAtom(stuff->id))) {
1143f7df2e56Smrg        int len = strlen(str);
1144f7df2e56Smrg        xGetAtomNameReply reply = {
1145f7df2e56Smrg            .type = X_Reply,
1146f7df2e56Smrg            .sequenceNumber = client->sequence,
1147f7df2e56Smrg            .length = bytes_to_int32(len),
1148f7df2e56Smrg            .nameLength = len
1149f7df2e56Smrg        };
1150f7df2e56Smrg
1151f7df2e56Smrg        WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply);
1152f7df2e56Smrg        WriteToClient(client, len, str);
1153f7df2e56Smrg        return Success;
115405b261ecSmrg    }
1155f7df2e56Smrg    else {
1156f7df2e56Smrg        client->errorValue = stuff->id;
1157f7df2e56Smrg        return BadAtom;
115805b261ecSmrg    }
115905b261ecSmrg}
116005b261ecSmrg
116105b261ecSmrgint
116205b261ecSmrgProcGrabServer(ClientPtr client)
116305b261ecSmrg{
11644642e01fSmrg    int rc;
1165f7df2e56Smrg
116605b261ecSmrg    REQUEST_SIZE_MATCH(xReq);
1167f7df2e56Smrg    if (grabState != GrabNone && client != grabClient) {
1168f7df2e56Smrg        ResetCurrentRequest(client);
1169f7df2e56Smrg        client->sequence--;
1170f7df2e56Smrg        BITSET(grabWaiters, client->index);
1171f7df2e56Smrg        IgnoreClient(client);
1172f7df2e56Smrg        return Success;
117305b261ecSmrg    }
11744642e01fSmrg    rc = OnlyListenToOneClient(client);
11754642e01fSmrg    if (rc != Success)
1176f7df2e56Smrg        return rc;
11777e31ba66Smrg    grabState = GrabActive;
117805b261ecSmrg    grabClient = client;
11797e31ba66Smrg    mark_client_grab(client);
118005b261ecSmrg
1181f7df2e56Smrg    if (ServerGrabCallback) {
1182f7df2e56Smrg        ServerGrabInfoRec grabinfo;
1183f7df2e56Smrg
1184f7df2e56Smrg        grabinfo.client = client;
1185f7df2e56Smrg        grabinfo.grabstate = SERVER_GRABBED;
1186f7df2e56Smrg        CallCallbacks(&ServerGrabCallback, (void *) &grabinfo);
118705b261ecSmrg    }
118805b261ecSmrg
11896747b715Smrg    return Success;
119005b261ecSmrg}
119105b261ecSmrg
119205b261ecSmrgstatic void
119305b261ecSmrgUngrabServer(ClientPtr client)
119405b261ecSmrg{
119505b261ecSmrg    int i;
119605b261ecSmrg
119705b261ecSmrg    grabState = GrabNone;
119805b261ecSmrg    ListenToAllClients();
11997e31ba66Smrg    mark_client_ungrab();
1200f7df2e56Smrg    for (i = mskcnt; --i >= 0 && !grabWaiters[i];);
1201f7df2e56Smrg    if (i >= 0) {
1202f7df2e56Smrg        i <<= 5;
1203f7df2e56Smrg        while (!GETBIT(grabWaiters, i))
1204f7df2e56Smrg            i++;
1205f7df2e56Smrg        BITCLEAR(grabWaiters, i);
1206f7df2e56Smrg        AttendClient(clients[i]);
120705b261ecSmrg    }
120805b261ecSmrg
1209f7df2e56Smrg    if (ServerGrabCallback) {
1210f7df2e56Smrg        ServerGrabInfoRec grabinfo;
1211f7df2e56Smrg
1212f7df2e56Smrg        grabinfo.client = client;
1213f7df2e56Smrg        grabinfo.grabstate = SERVER_UNGRABBED;
1214f7df2e56Smrg        CallCallbacks(&ServerGrabCallback, (void *) &grabinfo);
121505b261ecSmrg    }
121605b261ecSmrg}
121705b261ecSmrg
121805b261ecSmrgint
121905b261ecSmrgProcUngrabServer(ClientPtr client)
122005b261ecSmrg{
122105b261ecSmrg    REQUEST_SIZE_MATCH(xReq);
122205b261ecSmrg    UngrabServer(client);
12236747b715Smrg    return Success;
122405b261ecSmrg}
122505b261ecSmrg
122605b261ecSmrgint
122705b261ecSmrgProcTranslateCoords(ClientPtr client)
122805b261ecSmrg{
122905b261ecSmrg    REQUEST(xTranslateCoordsReq);
123005b261ecSmrg
123105b261ecSmrg    WindowPtr pWin, pDst;
123205b261ecSmrg    xTranslateCoordsReply rep;
123305b261ecSmrg    int rc;
123405b261ecSmrg
123505b261ecSmrg    REQUEST_SIZE_MATCH(xTranslateCoordsReq);
12364642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->srcWid, client, DixGetAttrAccess);
123705b261ecSmrg    if (rc != Success)
123805b261ecSmrg        return rc;
12394642e01fSmrg    rc = dixLookupWindow(&pDst, stuff->dstWid, client, DixGetAttrAccess);
124005b261ecSmrg    if (rc != Success)
124105b261ecSmrg        return rc;
1242f7df2e56Smrg
1243f7df2e56Smrg    rep = (xTranslateCoordsReply) {
1244f7df2e56Smrg        .type = X_Reply,
1245f7df2e56Smrg        .sequenceNumber = client->sequence,
1246f7df2e56Smrg        .length = 0
1247f7df2e56Smrg    };
1248f7df2e56Smrg    if (!SAME_SCREENS(pWin->drawable, pDst->drawable)) {
1249f7df2e56Smrg        rep.sameScreen = xFalse;
125005b261ecSmrg        rep.child = None;
1251f7df2e56Smrg        rep.dstX = rep.dstY = 0;
125205b261ecSmrg    }
1253f7df2e56Smrg    else {
1254f7df2e56Smrg        INT16 x, y;
1255f7df2e56Smrg
1256f7df2e56Smrg        rep.sameScreen = xTrue;
1257f7df2e56Smrg        rep.child = None;
1258f7df2e56Smrg        /* computing absolute coordinates -- adjust to destination later */
1259f7df2e56Smrg        x = pWin->drawable.x + stuff->srcX;
1260f7df2e56Smrg        y = pWin->drawable.y + stuff->srcY;
1261f7df2e56Smrg        pWin = pDst->firstChild;
1262f7df2e56Smrg        while (pWin) {
1263f7df2e56Smrg            BoxRec box;
1264f7df2e56Smrg
1265f7df2e56Smrg            if ((pWin->mapped) &&
1266f7df2e56Smrg                (x >= pWin->drawable.x - wBorderWidth(pWin)) &&
1267f7df2e56Smrg                (x < pWin->drawable.x + (int) pWin->drawable.width +
1268f7df2e56Smrg                 wBorderWidth(pWin)) &&
1269f7df2e56Smrg                (y >= pWin->drawable.y - wBorderWidth(pWin)) &&
1270f7df2e56Smrg                (y < pWin->drawable.y + (int) pWin->drawable.height +
1271f7df2e56Smrg                 wBorderWidth(pWin))
1272f7df2e56Smrg                /* When a window is shaped, a further check
1273f7df2e56Smrg                 * is made to see if the point is inside
1274f7df2e56Smrg                 * borderSize
1275f7df2e56Smrg                 */
1276f7df2e56Smrg                && (!wBoundingShape(pWin) ||
1277f7df2e56Smrg                    RegionContainsPoint(&pWin->borderSize, x, y, &box))
1278f7df2e56Smrg
1279f7df2e56Smrg                && (!wInputShape(pWin) ||
1280f7df2e56Smrg                    RegionContainsPoint(wInputShape(pWin),
1281f7df2e56Smrg                                        x - pWin->drawable.x,
1282f7df2e56Smrg                                        y - pWin->drawable.y, &box))
1283f7df2e56Smrg                ) {
1284f7df2e56Smrg                rep.child = pWin->drawable.id;
1285f7df2e56Smrg                pWin = (WindowPtr) NULL;
1286f7df2e56Smrg            }
1287f7df2e56Smrg            else
1288f7df2e56Smrg                pWin = pWin->nextSib;
1289f7df2e56Smrg        }
1290f7df2e56Smrg        /* adjust to destination coordinates */
1291f7df2e56Smrg        rep.dstX = x - pDst->drawable.x;
1292f7df2e56Smrg        rep.dstY = y - pDst->drawable.y;
129305b261ecSmrg    }
129405b261ecSmrg    WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep);
12956747b715Smrg    return Success;
129605b261ecSmrg}
129705b261ecSmrg
129805b261ecSmrgint
129905b261ecSmrgProcOpenFont(ClientPtr client)
130005b261ecSmrg{
1301f7df2e56Smrg    int err;
1302f7df2e56Smrg
130305b261ecSmrg    REQUEST(xOpenFontReq);
130405b261ecSmrg
130505b261ecSmrg    REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes);
130605b261ecSmrg    client->errorValue = stuff->fid;
130705b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->fid, client);
130805b261ecSmrg    err = OpenFont(client, stuff->fid, (Mask) 0,
1309f7df2e56Smrg                   stuff->nbytes, (char *) &stuff[1]);
1310f7df2e56Smrg    if (err == Success) {
1311f7df2e56Smrg        return Success;
131205b261ecSmrg    }
131305b261ecSmrg    else
1314f7df2e56Smrg        return err;
131505b261ecSmrg}
131605b261ecSmrg
131705b261ecSmrgint
131805b261ecSmrgProcCloseFont(ClientPtr client)
131905b261ecSmrg{
132005b261ecSmrg    FontPtr pFont;
13216747b715Smrg    int rc;
1322f7df2e56Smrg
132305b261ecSmrg    REQUEST(xResourceReq);
132405b261ecSmrg
132505b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
1326f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pFont, stuff->id, RT_FONT,
1327f7df2e56Smrg                                 client, DixDestroyAccess);
1328f7df2e56Smrg    if (rc == Success) {
132905b261ecSmrg        FreeResource(stuff->id, RT_NONE);
1330f7df2e56Smrg        return Success;
133105b261ecSmrg    }
1332f7df2e56Smrg    else {
1333f7df2e56Smrg        client->errorValue = stuff->id;
13346747b715Smrg        return rc;
133505b261ecSmrg    }
133605b261ecSmrg}
133705b261ecSmrg
133805b261ecSmrgint
133905b261ecSmrgProcQueryFont(ClientPtr client)
134005b261ecSmrg{
1341f7df2e56Smrg    xQueryFontReply *reply;
134205b261ecSmrg    FontPtr pFont;
13434642e01fSmrg    int rc;
1344f7df2e56Smrg
134505b261ecSmrg    REQUEST(xResourceReq);
134605b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
13474642e01fSmrg
13486747b715Smrg    rc = dixLookupFontable(&pFont, stuff->id, client, DixGetAttrAccess);
13494642e01fSmrg    if (rc != Success)
1350f7df2e56Smrg        return rc;
135105b261ecSmrg
135205b261ecSmrg    {
1353f7df2e56Smrg        xCharInfo *pmax = FONTINKMAX(pFont);
1354f7df2e56Smrg        xCharInfo *pmin = FONTINKMIN(pFont);
1355f7df2e56Smrg        int nprotoxcistructs;
1356f7df2e56Smrg        int rlength;
1357f7df2e56Smrg
1358f7df2e56Smrg        nprotoxcistructs = (pmax->rightSideBearing == pmin->rightSideBearing &&
1359f7df2e56Smrg                            pmax->leftSideBearing == pmin->leftSideBearing &&
1360f7df2e56Smrg                            pmax->descent == pmin->descent &&
1361f7df2e56Smrg                            pmax->ascent == pmin->ascent &&
1362f7df2e56Smrg                            pmax->characterWidth == pmin->characterWidth) ?
1363f7df2e56Smrg            0 : N2dChars(pFont);
1364f7df2e56Smrg
1365f7df2e56Smrg        rlength = sizeof(xQueryFontReply) +
1366f7df2e56Smrg            FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) +
1367f7df2e56Smrg            nprotoxcistructs * sizeof(xCharInfo);
1368f7df2e56Smrg        reply = calloc(1, rlength);
1369f7df2e56Smrg        if (!reply) {
1370f7df2e56Smrg            return BadAlloc;
1371f7df2e56Smrg        }
1372f7df2e56Smrg
1373f7df2e56Smrg        reply->type = X_Reply;
1374f7df2e56Smrg        reply->length = bytes_to_int32(rlength - sizeof(xGenericReply));
1375f7df2e56Smrg        reply->sequenceNumber = client->sequence;
1376f7df2e56Smrg        QueryFont(pFont, reply, nprotoxcistructs);
137705b261ecSmrg
137805b261ecSmrg        WriteReplyToClient(client, rlength, reply);
1379f7df2e56Smrg        free(reply);
1380f7df2e56Smrg        return Success;
138105b261ecSmrg    }
138205b261ecSmrg}
138305b261ecSmrg
138405b261ecSmrgint
138505b261ecSmrgProcQueryTextExtents(ClientPtr client)
138605b261ecSmrg{
138705b261ecSmrg    xQueryTextExtentsReply reply;
138805b261ecSmrg    FontPtr pFont;
138905b261ecSmrg    ExtentInfoRec info;
139005b261ecSmrg    unsigned long length;
13914642e01fSmrg    int rc;
1392f7df2e56Smrg
13934642e01fSmrg    REQUEST(xQueryTextExtentsReq);
139405b261ecSmrg    REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq);
1395f7df2e56Smrg
13966747b715Smrg    rc = dixLookupFontable(&pFont, stuff->fid, client, DixGetAttrAccess);
13974642e01fSmrg    if (rc != Success)
1398f7df2e56Smrg        return rc;
13994642e01fSmrg
14006747b715Smrg    length = client->req_len - bytes_to_int32(sizeof(xQueryTextExtentsReq));
140105b261ecSmrg    length = length << 1;
1402f7df2e56Smrg    if (stuff->oddLength) {
1403f7df2e56Smrg        if (length == 0)
1404f7df2e56Smrg            return BadLength;
140505b261ecSmrg        length--;
140605b261ecSmrg    }
14077e31ba66Smrg    if (!xfont2_query_text_extents(pFont, length, (unsigned char *) &stuff[1], &info))
1408f7df2e56Smrg        return BadAlloc;
1409f7df2e56Smrg    reply = (xQueryTextExtentsReply) {
1410f7df2e56Smrg        .type = X_Reply,
1411f7df2e56Smrg        .drawDirection = info.drawDirection,
1412f7df2e56Smrg        .sequenceNumber = client->sequence,
1413f7df2e56Smrg        .length = 0,
1414f7df2e56Smrg        .fontAscent = info.fontAscent,
1415f7df2e56Smrg        .fontDescent = info.fontDescent,
1416f7df2e56Smrg        .overallAscent = info.overallAscent,
1417f7df2e56Smrg        .overallDescent = info.overallDescent,
1418f7df2e56Smrg        .overallWidth = info.overallWidth,
1419f7df2e56Smrg        .overallLeft = info.overallLeft,
1420f7df2e56Smrg        .overallRight = info.overallRight
1421f7df2e56Smrg    };
142205b261ecSmrg    WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply);
14236747b715Smrg    return Success;
142405b261ecSmrg}
142505b261ecSmrg
142605b261ecSmrgint
142705b261ecSmrgProcListFonts(ClientPtr client)
142805b261ecSmrg{
142905b261ecSmrg    REQUEST(xListFontsReq);
143005b261ecSmrg
143105b261ecSmrg    REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes);
143205b261ecSmrg
1433f7df2e56Smrg    return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes,
1434f7df2e56Smrg                     stuff->maxNames);
143505b261ecSmrg}
143605b261ecSmrg
143705b261ecSmrgint
143805b261ecSmrgProcListFontsWithInfo(ClientPtr client)
143905b261ecSmrg{
144005b261ecSmrg    REQUEST(xListFontsWithInfoReq);
144105b261ecSmrg
144205b261ecSmrg    REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes);
144305b261ecSmrg
144405b261ecSmrg    return StartListFontsWithInfo(client, stuff->nbytes,
1445f7df2e56Smrg                                  (unsigned char *) &stuff[1], stuff->maxNames);
144605b261ecSmrg}
144705b261ecSmrg
144805b261ecSmrg/**
144905b261ecSmrg *
145005b261ecSmrg *  \param value must conform to DeleteType
145105b261ecSmrg */
145205b261ecSmrgint
1453f7df2e56SmrgdixDestroyPixmap(void *value, XID pid)
145405b261ecSmrg{
1455f7df2e56Smrg    PixmapPtr pPixmap = (PixmapPtr) value;
1456f7df2e56Smrg
1457f7df2e56Smrg    return (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap);
145805b261ecSmrg}
145905b261ecSmrg
146005b261ecSmrgint
146105b261ecSmrgProcCreatePixmap(ClientPtr client)
146205b261ecSmrg{
146305b261ecSmrg    PixmapPtr pMap;
146405b261ecSmrg    DrawablePtr pDraw;
1465f7df2e56Smrg
146605b261ecSmrg    REQUEST(xCreatePixmapReq);
146705b261ecSmrg    DepthPtr pDepth;
146805b261ecSmrg    int i, rc;
146905b261ecSmrg
147005b261ecSmrg    REQUEST_SIZE_MATCH(xCreatePixmapReq);
147105b261ecSmrg    client->errorValue = stuff->pid;
147205b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->pid, client);
1473f7df2e56Smrg
147405b261ecSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
1475f7df2e56Smrg                           DixGetAttrAccess);
147605b261ecSmrg    if (rc != Success)
1477f7df2e56Smrg        return rc;
147805b261ecSmrg
1479f7df2e56Smrg    if (!stuff->width || !stuff->height) {
1480f7df2e56Smrg        client->errorValue = 0;
148105b261ecSmrg        return BadValue;
148205b261ecSmrg    }
1483f7df2e56Smrg    if (stuff->width > 32767 || stuff->height > 32767) {
1484f7df2e56Smrg        /* It is allowed to try and allocate a pixmap which is larger than
1485f7df2e56Smrg         * 32767 in either dimension. However, all of the framebuffer code
1486f7df2e56Smrg         * is buggy and does not reliably draw to such big pixmaps, basically
1487f7df2e56Smrg         * because the Region data structure operates with signed shorts
1488f7df2e56Smrg         * for the rectangles in it.
1489f7df2e56Smrg         *
1490f7df2e56Smrg         * Furthermore, several places in the X server computes the
1491f7df2e56Smrg         * size in bytes of the pixmap and tries to store it in an
1492f7df2e56Smrg         * integer. This integer can overflow and cause the allocated size
1493f7df2e56Smrg         * to be much smaller.
1494f7df2e56Smrg         *
1495f7df2e56Smrg         * So, such big pixmaps are rejected here with a BadAlloc
1496f7df2e56Smrg         */
1497f7df2e56Smrg        return BadAlloc;
1498f7df2e56Smrg    }
1499f7df2e56Smrg    if (stuff->depth != 1) {
150005b261ecSmrg        pDepth = pDraw->pScreen->allowedDepths;
1501f7df2e56Smrg        for (i = 0; i < pDraw->pScreen->numDepths; i++, pDepth++)
1502f7df2e56Smrg            if (pDepth->depth == stuff->depth)
1503f7df2e56Smrg                goto CreatePmap;
1504f7df2e56Smrg        client->errorValue = stuff->depth;
150505b261ecSmrg        return BadValue;
150605b261ecSmrg    }
1507f7df2e56Smrg CreatePmap:
1508f7df2e56Smrg    pMap = (PixmapPtr) (*pDraw->pScreen->CreatePixmap)
1509f7df2e56Smrg        (pDraw->pScreen, stuff->width, stuff->height, stuff->depth, 0);
1510f7df2e56Smrg    if (pMap) {
1511f7df2e56Smrg        pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
1512f7df2e56Smrg        pMap->drawable.id = stuff->pid;
1513f7df2e56Smrg        /* security creation/labeling check */
1514f7df2e56Smrg        rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP,
1515f7df2e56Smrg                      pMap, RT_NONE, NULL, DixCreateAccess);
1516f7df2e56Smrg        if (rc != Success) {
1517f7df2e56Smrg            (*pDraw->pScreen->DestroyPixmap) (pMap);
1518f7df2e56Smrg            return rc;
1519f7df2e56Smrg        }
1520f7df2e56Smrg        if (AddResource(stuff->pid, RT_PIXMAP, (void *) pMap))
1521f7df2e56Smrg            return Success;
152205b261ecSmrg    }
15236747b715Smrg    return BadAlloc;
152405b261ecSmrg}
152505b261ecSmrg
152605b261ecSmrgint
152705b261ecSmrgProcFreePixmap(ClientPtr client)
152805b261ecSmrg{
152905b261ecSmrg    PixmapPtr pMap;
15304642e01fSmrg    int rc;
1531f7df2e56Smrg
153205b261ecSmrg    REQUEST(xResourceReq);
153305b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
15344642e01fSmrg
1535f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pMap, stuff->id, RT_PIXMAP,
1536f7df2e56Smrg                                 client, DixDestroyAccess);
1537f7df2e56Smrg    if (rc == Success) {
1538f7df2e56Smrg        FreeResource(stuff->id, RT_NONE);
1539f7df2e56Smrg        return Success;
154005b261ecSmrg    }
1541f7df2e56Smrg    else {
1542f7df2e56Smrg        client->errorValue = stuff->id;
1543f7df2e56Smrg        return rc;
154405b261ecSmrg    }
154505b261ecSmrg}
154605b261ecSmrg
154705b261ecSmrgint
154805b261ecSmrgProcCreateGC(ClientPtr client)
154905b261ecSmrg{
155005b261ecSmrg    int error, rc;
155105b261ecSmrg    GC *pGC;
155205b261ecSmrg    DrawablePtr pDraw;
155305b261ecSmrg    unsigned len;
1554f7df2e56Smrg
155505b261ecSmrg    REQUEST(xCreateGCReq);
155605b261ecSmrg
155705b261ecSmrg    REQUEST_AT_LEAST_SIZE(xCreateGCReq);
155805b261ecSmrg    client->errorValue = stuff->gc;
155905b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->gc, client);
15604642e01fSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
1561f7df2e56Smrg                           DixGetAttrAccess);
156205b261ecSmrg    if (rc != Success)
1563f7df2e56Smrg        return rc;
156405b261ecSmrg
1565f7df2e56Smrg    len = client->req_len - bytes_to_int32(sizeof(xCreateGCReq));
156605b261ecSmrg    if (len != Ones(stuff->mask))
156705b261ecSmrg        return BadLength;
1568f7df2e56Smrg    pGC = (GC *) CreateGC(pDraw, stuff->mask, (XID *) &stuff[1], &error,
1569f7df2e56Smrg                          stuff->gc, client);
157005b261ecSmrg    if (error != Success)
157105b261ecSmrg        return error;
1572f7df2e56Smrg    if (!AddResource(stuff->gc, RT_GC, (void *) pGC))
1573f7df2e56Smrg        return BadAlloc;
15746747b715Smrg    return Success;
157505b261ecSmrg}
157605b261ecSmrg
157705b261ecSmrgint
157805b261ecSmrgProcChangeGC(ClientPtr client)
157905b261ecSmrg{
158005b261ecSmrg    GC *pGC;
158105b261ecSmrg    int result;
158205b261ecSmrg    unsigned len;
1583f7df2e56Smrg
158405b261ecSmrg    REQUEST(xChangeGCReq);
158505b261ecSmrg    REQUEST_AT_LEAST_SIZE(xChangeGCReq);
158605b261ecSmrg
15874642e01fSmrg    result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
158805b261ecSmrg    if (result != Success)
1589f7df2e56Smrg        return result;
159005b261ecSmrg
1591f7df2e56Smrg    len = client->req_len - bytes_to_int32(sizeof(xChangeGCReq));
159205b261ecSmrg    if (len != Ones(stuff->mask))
159305b261ecSmrg        return BadLength;
159405b261ecSmrg
15956747b715Smrg    return ChangeGCXIDs(client, pGC, stuff->mask, (CARD32 *) &stuff[1]);
159605b261ecSmrg}
159705b261ecSmrg
159805b261ecSmrgint
159905b261ecSmrgProcCopyGC(ClientPtr client)
160005b261ecSmrg{
160105b261ecSmrg    GC *dstGC;
160205b261ecSmrg    GC *pGC;
160305b261ecSmrg    int result;
1604f7df2e56Smrg
160505b261ecSmrg    REQUEST(xCopyGCReq);
160605b261ecSmrg    REQUEST_SIZE_MATCH(xCopyGCReq);
160705b261ecSmrg
16084642e01fSmrg    result = dixLookupGC(&pGC, stuff->srcGC, client, DixGetAttrAccess);
160905b261ecSmrg    if (result != Success)
1610f7df2e56Smrg        return result;
16114642e01fSmrg    result = dixLookupGC(&dstGC, stuff->dstGC, client, DixSetAttrAccess);
161205b261ecSmrg    if (result != Success)
1613f7df2e56Smrg        return result;
161405b261ecSmrg    if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth))
16156747b715Smrg        return BadMatch;
1616f7df2e56Smrg    if (stuff->mask & ~GCAllBits) {
1617f7df2e56Smrg        client->errorValue = stuff->mask;
1618f7df2e56Smrg        return BadValue;
161905b261ecSmrg    }
16206747b715Smrg    return CopyGC(pGC, dstGC, stuff->mask);
162105b261ecSmrg}
162205b261ecSmrg
162305b261ecSmrgint
162405b261ecSmrgProcSetDashes(ClientPtr client)
162505b261ecSmrg{
162605b261ecSmrg    GC *pGC;
162705b261ecSmrg    int result;
1628f7df2e56Smrg
162905b261ecSmrg    REQUEST(xSetDashesReq);
163005b261ecSmrg
163105b261ecSmrg    REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes);
1632f7df2e56Smrg    if (stuff->nDashes == 0) {
1633f7df2e56Smrg        client->errorValue = 0;
1634f7df2e56Smrg        return BadValue;
163505b261ecSmrg    }
163605b261ecSmrg
1637f7df2e56Smrg    result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
163805b261ecSmrg    if (result != Success)
1639f7df2e56Smrg        return result;
164005b261ecSmrg
16416747b715Smrg    /* If there's an error, either there's no sensible errorValue,
16426747b715Smrg     * or there was a dash segment of 0. */
16436747b715Smrg    client->errorValue = 0;
16446747b715Smrg    return SetDashes(pGC, stuff->dashOffset, stuff->nDashes,
1645f7df2e56Smrg                     (unsigned char *) &stuff[1]);
164605b261ecSmrg}
164705b261ecSmrg
164805b261ecSmrgint
164905b261ecSmrgProcSetClipRectangles(ClientPtr client)
165005b261ecSmrg{
1651f7df2e56Smrg    int nr, result;
165205b261ecSmrg    GC *pGC;
1653f7df2e56Smrg
165405b261ecSmrg    REQUEST(xSetClipRectanglesReq);
165505b261ecSmrg
165605b261ecSmrg    REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq);
165705b261ecSmrg    if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) &&
1658f7df2e56Smrg        (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) {
1659f7df2e56Smrg        client->errorValue = stuff->ordering;
166005b261ecSmrg        return BadValue;
166105b261ecSmrg    }
1662f7df2e56Smrg    result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
166305b261ecSmrg    if (result != Success)
1664f7df2e56Smrg        return result;
1665f7df2e56Smrg
166605b261ecSmrg    nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq);
166705b261ecSmrg    if (nr & 4)
1668f7df2e56Smrg        return BadLength;
166905b261ecSmrg    nr >>= 3;
16706747b715Smrg    return SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin,
1671f7df2e56Smrg                        nr, (xRectangle *) &stuff[1], (int) stuff->ordering);
167205b261ecSmrg}
167305b261ecSmrg
167405b261ecSmrgint
167505b261ecSmrgProcFreeGC(ClientPtr client)
167605b261ecSmrg{
167705b261ecSmrg    GC *pGC;
167805b261ecSmrg    int rc;
1679f7df2e56Smrg
168005b261ecSmrg    REQUEST(xResourceReq);
168105b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
168205b261ecSmrg
168305b261ecSmrg    rc = dixLookupGC(&pGC, stuff->id, client, DixDestroyAccess);
168405b261ecSmrg    if (rc != Success)
1685f7df2e56Smrg        return rc;
168605b261ecSmrg
168705b261ecSmrg    FreeResource(stuff->id, RT_NONE);
16886747b715Smrg    return Success;
168905b261ecSmrg}
169005b261ecSmrg
169105b261ecSmrgint
169205b261ecSmrgProcClearToBackground(ClientPtr client)
169305b261ecSmrg{
169405b261ecSmrg    REQUEST(xClearAreaReq);
169505b261ecSmrg    WindowPtr pWin;
169605b261ecSmrg    int rc;
169705b261ecSmrg
169805b261ecSmrg    REQUEST_SIZE_MATCH(xClearAreaReq);
169905b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
170005b261ecSmrg    if (rc != Success)
170105b261ecSmrg        return rc;
1702f7df2e56Smrg    if (pWin->drawable.class == InputOnly) {
1703f7df2e56Smrg        client->errorValue = stuff->window;
1704f7df2e56Smrg        return BadMatch;
1705f7df2e56Smrg    }
1706f7df2e56Smrg    if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) {
1707f7df2e56Smrg        client->errorValue = stuff->exposures;
17086747b715Smrg        return BadValue;
170905b261ecSmrg    }
1710f7df2e56Smrg    (*pWin->drawable.pScreen->ClearToBackground) (pWin, stuff->x, stuff->y,
1711f7df2e56Smrg                                                  stuff->width, stuff->height,
1712f7df2e56Smrg                                                  (Bool) stuff->exposures);
17136747b715Smrg    return Success;
171405b261ecSmrg}
171505b261ecSmrg
1716f7df2e56Smrg/* send GraphicsExpose events, or a NoExpose event, based on the region */
1717f7df2e56Smrgvoid
1718f7df2e56SmrgSendGraphicsExpose(ClientPtr client, RegionPtr pRgn, XID drawable,
1719f7df2e56Smrg                     int major, int minor)
1720f7df2e56Smrg{
1721f7df2e56Smrg    if (pRgn && !RegionNil(pRgn)) {
1722f7df2e56Smrg        xEvent *pEvent;
1723f7df2e56Smrg        xEvent *pe;
1724f7df2e56Smrg        BoxPtr pBox;
1725f7df2e56Smrg        int i;
1726f7df2e56Smrg        int numRects;
1727f7df2e56Smrg
1728f7df2e56Smrg        numRects = RegionNumRects(pRgn);
1729f7df2e56Smrg        pBox = RegionRects(pRgn);
1730f7df2e56Smrg        if (!(pEvent = calloc(numRects, sizeof(xEvent))))
1731f7df2e56Smrg            return;
1732f7df2e56Smrg        pe = pEvent;
1733f7df2e56Smrg
1734f7df2e56Smrg        for (i = 1; i <= numRects; i++, pe++, pBox++) {
1735f7df2e56Smrg            pe->u.u.type = GraphicsExpose;
1736f7df2e56Smrg            pe->u.graphicsExposure.drawable = drawable;
1737f7df2e56Smrg            pe->u.graphicsExposure.x = pBox->x1;
1738f7df2e56Smrg            pe->u.graphicsExposure.y = pBox->y1;
1739f7df2e56Smrg            pe->u.graphicsExposure.width = pBox->x2 - pBox->x1;
1740f7df2e56Smrg            pe->u.graphicsExposure.height = pBox->y2 - pBox->y1;
1741f7df2e56Smrg            pe->u.graphicsExposure.count = numRects - i;
1742f7df2e56Smrg            pe->u.graphicsExposure.majorEvent = major;
1743f7df2e56Smrg            pe->u.graphicsExposure.minorEvent = minor;
1744f7df2e56Smrg        }
1745f7df2e56Smrg        /* GraphicsExpose is a "critical event", which TryClientEvents
1746f7df2e56Smrg         * handles specially. */
1747f7df2e56Smrg        TryClientEvents(client, NULL, pEvent, numRects,
1748f7df2e56Smrg                        (Mask) 0, NoEventMask, NullGrab);
1749f7df2e56Smrg        free(pEvent);
1750f7df2e56Smrg    }
1751f7df2e56Smrg    else {
1752f7df2e56Smrg        xEvent event = {
1753f7df2e56Smrg            .u.noExposure.drawable = drawable,
1754f7df2e56Smrg            .u.noExposure.majorEvent = major,
1755f7df2e56Smrg            .u.noExposure.minorEvent = minor
1756f7df2e56Smrg        };
1757f7df2e56Smrg        event.u.u.type = NoExpose;
1758f7df2e56Smrg        WriteEventsToClient(client, 1, &event);
1759f7df2e56Smrg    }
1760f7df2e56Smrg}
1761f7df2e56Smrg
176205b261ecSmrgint
176305b261ecSmrgProcCopyArea(ClientPtr client)
176405b261ecSmrg{
176505b261ecSmrg    DrawablePtr pDst;
176605b261ecSmrg    DrawablePtr pSrc;
176705b261ecSmrg    GC *pGC;
1768f7df2e56Smrg
176905b261ecSmrg    REQUEST(xCopyAreaReq);
177005b261ecSmrg    RegionPtr pRgn;
177105b261ecSmrg    int rc;
177205b261ecSmrg
177305b261ecSmrg    REQUEST_SIZE_MATCH(xCopyAreaReq);
177405b261ecSmrg
1775f7df2e56Smrg    VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, DixWriteAccess);
1776f7df2e56Smrg    if (stuff->dstDrawable != stuff->srcDrawable) {
1777f7df2e56Smrg        rc = dixLookupDrawable(&pSrc, stuff->srcDrawable, client, 0,
1778f7df2e56Smrg                               DixReadAccess);
1779f7df2e56Smrg        if (rc != Success)
1780f7df2e56Smrg            return rc;
1781f7df2e56Smrg        if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) {
1782f7df2e56Smrg            client->errorValue = stuff->dstDrawable;
1783f7df2e56Smrg            return BadMatch;
1784f7df2e56Smrg        }
178505b261ecSmrg    }
178605b261ecSmrg    else
178705b261ecSmrg        pSrc = pDst;
178805b261ecSmrg
1789f7df2e56Smrg    pRgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, stuff->srcX, stuff->srcY,
1790f7df2e56Smrg                                  stuff->width, stuff->height,
1791f7df2e56Smrg                                  stuff->dstX, stuff->dstY);
1792f7df2e56Smrg    if (pGC->graphicsExposures) {
1793f7df2e56Smrg        SendGraphicsExpose(client, pRgn, stuff->dstDrawable, X_CopyArea, 0);
1794f7df2e56Smrg        if (pRgn)
1795f7df2e56Smrg            RegionDestroy(pRgn);
179605b261ecSmrg    }
179705b261ecSmrg
17986747b715Smrg    return Success;
179905b261ecSmrg}
180005b261ecSmrg
180105b261ecSmrgint
180205b261ecSmrgProcCopyPlane(ClientPtr client)
180305b261ecSmrg{
180405b261ecSmrg    DrawablePtr psrcDraw, pdstDraw;
180505b261ecSmrg    GC *pGC;
1806f7df2e56Smrg
180705b261ecSmrg    REQUEST(xCopyPlaneReq);
180805b261ecSmrg    RegionPtr pRgn;
180905b261ecSmrg    int rc;
181005b261ecSmrg
181105b261ecSmrg    REQUEST_SIZE_MATCH(xCopyPlaneReq);
181205b261ecSmrg
18134642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, DixWriteAccess);
1814f7df2e56Smrg    if (stuff->dstDrawable != stuff->srcDrawable) {
1815f7df2e56Smrg        rc = dixLookupDrawable(&psrcDraw, stuff->srcDrawable, client, 0,
1816f7df2e56Smrg                               DixReadAccess);
1817f7df2e56Smrg        if (rc != Success)
1818f7df2e56Smrg            return rc;
1819f7df2e56Smrg
1820f7df2e56Smrg        if (pdstDraw->pScreen != psrcDraw->pScreen) {
1821f7df2e56Smrg            client->errorValue = stuff->dstDrawable;
1822f7df2e56Smrg            return BadMatch;
1823f7df2e56Smrg        }
182405b261ecSmrg    }
182505b261ecSmrg    else
182605b261ecSmrg        psrcDraw = pdstDraw;
182705b261ecSmrg
182805b261ecSmrg    /* Check to see if stuff->bitPlane has exactly ONE good bit set */
1829f7df2e56Smrg    if (stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) ||
1830f7df2e56Smrg        (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) {
1831f7df2e56Smrg        client->errorValue = stuff->bitPlane;
1832f7df2e56Smrg        return BadValue;
183305b261ecSmrg    }
183405b261ecSmrg
1835f7df2e56Smrg    pRgn =
1836f7df2e56Smrg        (*pGC->ops->CopyPlane) (psrcDraw, pdstDraw, pGC, stuff->srcX,
1837f7df2e56Smrg                                stuff->srcY, stuff->width, stuff->height,
1838f7df2e56Smrg                                stuff->dstX, stuff->dstY, stuff->bitPlane);
1839f7df2e56Smrg    if (pGC->graphicsExposures) {
1840f7df2e56Smrg        SendGraphicsExpose(client, pRgn, stuff->dstDrawable, X_CopyPlane, 0);
1841f7df2e56Smrg        if (pRgn)
1842f7df2e56Smrg            RegionDestroy(pRgn);
184305b261ecSmrg    }
18446747b715Smrg    return Success;
184505b261ecSmrg}
184605b261ecSmrg
184705b261ecSmrgint
184805b261ecSmrgProcPolyPoint(ClientPtr client)
184905b261ecSmrg{
185005b261ecSmrg    int npoint;
185105b261ecSmrg    GC *pGC;
185205b261ecSmrg    DrawablePtr pDraw;
1853f7df2e56Smrg
185405b261ecSmrg    REQUEST(xPolyPointReq);
185505b261ecSmrg
185605b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyPointReq);
1857f7df2e56Smrg    if ((stuff->coordMode != CoordModeOrigin) &&
1858f7df2e56Smrg        (stuff->coordMode != CoordModePrevious)) {
1859f7df2e56Smrg        client->errorValue = stuff->coordMode;
186005b261ecSmrg        return BadValue;
186105b261ecSmrg    }
1862f7df2e56Smrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
18636747b715Smrg    npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyPointReq));
186405b261ecSmrg    if (npoint)
1865f7df2e56Smrg        (*pGC->ops->PolyPoint) (pDraw, pGC, stuff->coordMode, npoint,
1866f7df2e56Smrg                                (xPoint *) &stuff[1]);
18676747b715Smrg    return Success;
186805b261ecSmrg}
186905b261ecSmrg
187005b261ecSmrgint
187105b261ecSmrgProcPolyLine(ClientPtr client)
187205b261ecSmrg{
187305b261ecSmrg    int npoint;
187405b261ecSmrg    GC *pGC;
187505b261ecSmrg    DrawablePtr pDraw;
1876f7df2e56Smrg
187705b261ecSmrg    REQUEST(xPolyLineReq);
187805b261ecSmrg
187905b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyLineReq);
1880f7df2e56Smrg    if ((stuff->coordMode != CoordModeOrigin) &&
1881f7df2e56Smrg        (stuff->coordMode != CoordModePrevious)) {
1882f7df2e56Smrg        client->errorValue = stuff->coordMode;
188305b261ecSmrg        return BadValue;
188405b261ecSmrg    }
18854642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
18866747b715Smrg    npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyLineReq));
188705b261ecSmrg    if (npoint > 1)
1888f7df2e56Smrg        (*pGC->ops->Polylines) (pDraw, pGC, stuff->coordMode, npoint,
1889f7df2e56Smrg                                (DDXPointPtr) &stuff[1]);
18906747b715Smrg    return Success;
189105b261ecSmrg}
189205b261ecSmrg
189305b261ecSmrgint
189405b261ecSmrgProcPolySegment(ClientPtr client)
189505b261ecSmrg{
189605b261ecSmrg    int nsegs;
189705b261ecSmrg    GC *pGC;
189805b261ecSmrg    DrawablePtr pDraw;
1899f7df2e56Smrg
190005b261ecSmrg    REQUEST(xPolySegmentReq);
190105b261ecSmrg
190205b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolySegmentReq);
19034642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
190405b261ecSmrg    nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq);
190505b261ecSmrg    if (nsegs & 4)
1906f7df2e56Smrg        return BadLength;
190705b261ecSmrg    nsegs >>= 3;
190805b261ecSmrg    if (nsegs)
1909f7df2e56Smrg        (*pGC->ops->PolySegment) (pDraw, pGC, nsegs, (xSegment *) &stuff[1]);
19106747b715Smrg    return Success;
191105b261ecSmrg}
191205b261ecSmrg
191305b261ecSmrgint
1914f7df2e56SmrgProcPolyRectangle(ClientPtr client)
191505b261ecSmrg{
191605b261ecSmrg    int nrects;
191705b261ecSmrg    GC *pGC;
191805b261ecSmrg    DrawablePtr pDraw;
1919f7df2e56Smrg
192005b261ecSmrg    REQUEST(xPolyRectangleReq);
192105b261ecSmrg
192205b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyRectangleReq);
19234642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
192405b261ecSmrg    nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq);
192505b261ecSmrg    if (nrects & 4)
1926f7df2e56Smrg        return BadLength;
192705b261ecSmrg    nrects >>= 3;
192805b261ecSmrg    if (nrects)
1929f7df2e56Smrg        (*pGC->ops->PolyRectangle) (pDraw, pGC,
1930f7df2e56Smrg                                    nrects, (xRectangle *) &stuff[1]);
19316747b715Smrg    return Success;
193205b261ecSmrg}
193305b261ecSmrg
193405b261ecSmrgint
193505b261ecSmrgProcPolyArc(ClientPtr client)
193605b261ecSmrg{
1937f7df2e56Smrg    int narcs;
193805b261ecSmrg    GC *pGC;
193905b261ecSmrg    DrawablePtr pDraw;
1940f7df2e56Smrg
194105b261ecSmrg    REQUEST(xPolyArcReq);
194205b261ecSmrg
194305b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyArcReq);
19444642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
194505b261ecSmrg    narcs = (client->req_len << 2) - sizeof(xPolyArcReq);
194605b261ecSmrg    if (narcs % sizeof(xArc))
1947f7df2e56Smrg        return BadLength;
194805b261ecSmrg    narcs /= sizeof(xArc);
194905b261ecSmrg    if (narcs)
1950f7df2e56Smrg        (*pGC->ops->PolyArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]);
19516747b715Smrg    return Success;
195205b261ecSmrg}
195305b261ecSmrg
195405b261ecSmrgint
195505b261ecSmrgProcFillPoly(ClientPtr client)
195605b261ecSmrg{
1957f7df2e56Smrg    int things;
195805b261ecSmrg    GC *pGC;
195905b261ecSmrg    DrawablePtr pDraw;
1960f7df2e56Smrg
196105b261ecSmrg    REQUEST(xFillPolyReq);
196205b261ecSmrg
196305b261ecSmrg    REQUEST_AT_LEAST_SIZE(xFillPolyReq);
1964f7df2e56Smrg    if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) &&
1965f7df2e56Smrg        (stuff->shape != Convex)) {
1966f7df2e56Smrg        client->errorValue = stuff->shape;
196705b261ecSmrg        return BadValue;
196805b261ecSmrg    }
1969f7df2e56Smrg    if ((stuff->coordMode != CoordModeOrigin) &&
1970f7df2e56Smrg        (stuff->coordMode != CoordModePrevious)) {
1971f7df2e56Smrg        client->errorValue = stuff->coordMode;
197205b261ecSmrg        return BadValue;
197305b261ecSmrg    }
197405b261ecSmrg
19754642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
19766747b715Smrg    things = bytes_to_int32((client->req_len << 2) - sizeof(xFillPolyReq));
197705b261ecSmrg    if (things)
197805b261ecSmrg        (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape,
1979f7df2e56Smrg                                  stuff->coordMode, things,
1980f7df2e56Smrg                                  (DDXPointPtr) &stuff[1]);
19816747b715Smrg    return Success;
198205b261ecSmrg}
198305b261ecSmrg
198405b261ecSmrgint
198505b261ecSmrgProcPolyFillRectangle(ClientPtr client)
198605b261ecSmrg{
1987f7df2e56Smrg    int things;
198805b261ecSmrg    GC *pGC;
198905b261ecSmrg    DrawablePtr pDraw;
1990f7df2e56Smrg
199105b261ecSmrg    REQUEST(xPolyFillRectangleReq);
199205b261ecSmrg
199305b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq);
19944642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
199505b261ecSmrg    things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq);
199605b261ecSmrg    if (things & 4)
1997f7df2e56Smrg        return BadLength;
199805b261ecSmrg    things >>= 3;
199905b261ecSmrg
200005b261ecSmrg    if (things)
200105b261ecSmrg        (*pGC->ops->PolyFillRect) (pDraw, pGC, things,
2002f7df2e56Smrg                                   (xRectangle *) &stuff[1]);
20036747b715Smrg    return Success;
200405b261ecSmrg}
200505b261ecSmrg
200605b261ecSmrgint
200705b261ecSmrgProcPolyFillArc(ClientPtr client)
200805b261ecSmrg{
2009f7df2e56Smrg    int narcs;
201005b261ecSmrg    GC *pGC;
201105b261ecSmrg    DrawablePtr pDraw;
2012f7df2e56Smrg
201305b261ecSmrg    REQUEST(xPolyFillArcReq);
201405b261ecSmrg
201505b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyFillArcReq);
20164642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
201705b261ecSmrg    narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq);
201805b261ecSmrg    if (narcs % sizeof(xArc))
2019f7df2e56Smrg        return BadLength;
202005b261ecSmrg    narcs /= sizeof(xArc);
202105b261ecSmrg    if (narcs)
202205b261ecSmrg        (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]);
20236747b715Smrg    return Success;
202405b261ecSmrg}
202505b261ecSmrg
202605b261ecSmrg#ifdef MATCH_CLIENT_ENDIAN
202705b261ecSmrg
202805b261ecSmrgint
2029f7df2e56SmrgServerOrder(void)
203005b261ecSmrg{
2031f7df2e56Smrg    int whichbyte = 1;
203205b261ecSmrg
203305b261ecSmrg    if (*((char *) &whichbyte))
2034f7df2e56Smrg        return LSBFirst;
203505b261ecSmrg    return MSBFirst;
203605b261ecSmrg}
203705b261ecSmrg
203805b261ecSmrg#define ClientOrder(client) ((client)->swapped ? !ServerOrder() : ServerOrder())
203905b261ecSmrg
204005b261ecSmrgvoid
2041f7df2e56SmrgReformatImage(char *base, int nbytes, int bpp, int order)
204205b261ecSmrg{
204305b261ecSmrg    switch (bpp) {
2044f7df2e56Smrg    case 1:                    /* yuck */
2045f7df2e56Smrg        if (BITMAP_BIT_ORDER != order)
2046f7df2e56Smrg            BitOrderInvert((unsigned char *) base, nbytes);
204705b261ecSmrg#if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8
2048f7df2e56Smrg        ReformatImage(base, nbytes, BITMAP_SCANLINE_UNIT, order);
204905b261ecSmrg#endif
2050f7df2e56Smrg        break;
205105b261ecSmrg    case 4:
2052f7df2e56Smrg        break;                  /* yuck */
205305b261ecSmrg    case 8:
2054f7df2e56Smrg        break;
205505b261ecSmrg    case 16:
2056f7df2e56Smrg        if (IMAGE_BYTE_ORDER != order)
2057f7df2e56Smrg            TwoByteSwap((unsigned char *) base, nbytes);
2058f7df2e56Smrg        break;
205905b261ecSmrg    case 32:
2060f7df2e56Smrg        if (IMAGE_BYTE_ORDER != order)
2061f7df2e56Smrg            FourByteSwap((unsigned char *) base, nbytes);
2062f7df2e56Smrg        break;
206305b261ecSmrg    }
206405b261ecSmrg}
206505b261ecSmrg#else
206605b261ecSmrg#define ReformatImage(b,n,bpp,o)
206705b261ecSmrg#endif
206805b261ecSmrg
206905b261ecSmrg/* 64-bit server notes: the protocol restricts padding of images to
207005b261ecSmrg * 8-, 16-, or 32-bits. We would like to have 64-bits for the server
207105b261ecSmrg * to use internally. Removes need for internal alignment checking.
207205b261ecSmrg * All of the PutImage functions could be changed individually, but
207305b261ecSmrg * as currently written, they call other routines which require things
207405b261ecSmrg * to be 64-bit padded on scanlines, so we changed things here.
207505b261ecSmrg * If an image would be padded differently for 64- versus 32-, then
207605b261ecSmrg * copy each scanline to a 64-bit padded scanline.
207705b261ecSmrg * Also, we need to make sure that the image is aligned on a 64-bit
207805b261ecSmrg * boundary, even if the scanlines are padded to our satisfaction.
207905b261ecSmrg */
208005b261ecSmrgint
208105b261ecSmrgProcPutImage(ClientPtr client)
208205b261ecSmrg{
208305b261ecSmrg    GC *pGC;
208405b261ecSmrg    DrawablePtr pDraw;
2085f7df2e56Smrg    long length;                /* length of scanline server padded */
2086f7df2e56Smrg    long lengthProto;           /* length of scanline protocol padded */
2087f7df2e56Smrg    char *tmpImage;
2088f7df2e56Smrg
208905b261ecSmrg    REQUEST(xPutImageReq);
209005b261ecSmrg
209105b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPutImageReq);
20924642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
2093f7df2e56Smrg    if (stuff->format == XYBitmap) {
209405b261ecSmrg        if ((stuff->depth != 1) ||
2095f7df2e56Smrg            (stuff->leftPad >= (unsigned int) screenInfo.bitmapScanlinePad))
209605b261ecSmrg            return BadMatch;
2097f7df2e56Smrg        length = BitmapBytePad(stuff->width + stuff->leftPad);
209805b261ecSmrg    }
2099f7df2e56Smrg    else if (stuff->format == XYPixmap) {
2100f7df2e56Smrg        if ((pDraw->depth != stuff->depth) ||
2101f7df2e56Smrg            (stuff->leftPad >= (unsigned int) screenInfo.bitmapScanlinePad))
210205b261ecSmrg            return BadMatch;
2103f7df2e56Smrg        length = BitmapBytePad(stuff->width + stuff->leftPad);
2104f7df2e56Smrg        length *= stuff->depth;
210505b261ecSmrg    }
2106f7df2e56Smrg    else if (stuff->format == ZPixmap) {
210705b261ecSmrg        if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0))
210805b261ecSmrg            return BadMatch;
2109f7df2e56Smrg        length = PixmapBytePad(stuff->width, stuff->depth);
211005b261ecSmrg    }
2111f7df2e56Smrg    else {
2112f7df2e56Smrg        client->errorValue = stuff->format;
211305b261ecSmrg        return BadValue;
211405b261ecSmrg    }
211505b261ecSmrg
2116f7df2e56Smrg    tmpImage = (char *) &stuff[1];
211705b261ecSmrg    lengthProto = length;
21180b0d8713Smrg
2119f7df2e56Smrg    if (stuff->height != 0 && lengthProto >= (INT32_MAX / stuff->height))
21200b0d8713Smrg        return BadLength;
2121f7df2e56Smrg
21226747b715Smrg    if ((bytes_to_int32(lengthProto * stuff->height) +
2123f7df2e56Smrg         bytes_to_int32(sizeof(xPutImageReq))) != client->req_len)
2124f7df2e56Smrg        return BadLength;
2125f7df2e56Smrg
2126f7df2e56Smrg    ReformatImage(tmpImage, lengthProto * stuff->height,
2127f7df2e56Smrg                  stuff->format == ZPixmap ? BitsPerPixel(stuff->depth) : 1,
2128f7df2e56Smrg                  ClientOrder(client));
212905b261ecSmrg
213005b261ecSmrg    (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY,
2131f7df2e56Smrg                           stuff->width, stuff->height,
2132f7df2e56Smrg                           stuff->leftPad, stuff->format, tmpImage);
213305b261ecSmrg
2134f7df2e56Smrg    return Success;
213505b261ecSmrg}
213605b261ecSmrg
213705b261ecSmrgstatic int
2138f7df2e56SmrgDoGetImage(ClientPtr client, int format, Drawable drawable,
2139f7df2e56Smrg           int x, int y, int width, int height,
2140f7df2e56Smrg           Mask planemask)
214105b261ecSmrg{
2142f7df2e56Smrg    DrawablePtr pDraw, pBoundingDraw;
2143f7df2e56Smrg    int nlines, linesPerBuf, rc;
2144f7df2e56Smrg    int linesDone;
2145f7df2e56Smrg
21466747b715Smrg    /* coordinates relative to the bounding drawable */
2147f7df2e56Smrg    int relx, rely;
2148f7df2e56Smrg    long widthBytesLine, length;
2149f7df2e56Smrg    Mask plane = 0;
2150f7df2e56Smrg    char *pBuf;
2151f7df2e56Smrg    xGetImageReply xgi;
215205b261ecSmrg    RegionPtr pVisibleRegion = NULL;
215305b261ecSmrg
2154f7df2e56Smrg    if ((format != XYPixmap) && (format != ZPixmap)) {
2155f7df2e56Smrg        client->errorValue = format;
21566747b715Smrg        return BadValue;
215705b261ecSmrg    }
215805b261ecSmrg    rc = dixLookupDrawable(&pDraw, drawable, client, 0, DixReadAccess);
215905b261ecSmrg    if (rc != Success)
2160f7df2e56Smrg        return rc;
216105b261ecSmrg
21626747b715Smrg    memset(&xgi, 0, sizeof(xGetImageReply));
21636747b715Smrg
21646747b715Smrg    relx = x;
21656747b715Smrg    rely = y;
21666747b715Smrg
2167f7df2e56Smrg    if (pDraw->type == DRAWABLE_WINDOW) {
2168f7df2e56Smrg        WindowPtr pWin = (WindowPtr) pDraw;
2169f7df2e56Smrg
2170f7df2e56Smrg        /* "If the drawable is a window, the window must be viewable ... or a
2171f7df2e56Smrg         * BadMatch error results" */
2172f7df2e56Smrg        if (!pWin->viewable)
2173f7df2e56Smrg            return BadMatch;
21746747b715Smrg
2175f7df2e56Smrg        /* If the drawable is a window, the rectangle must be contained within
2176f7df2e56Smrg         * its bounds (including the border). */
2177f7df2e56Smrg        if (x < -wBorderWidth(pWin) ||
2178f7df2e56Smrg            x + width > wBorderWidth(pWin) + (int) pDraw->width ||
2179f7df2e56Smrg            y < -wBorderWidth(pWin) ||
2180f7df2e56Smrg            y + height > wBorderWidth(pWin) + (int) pDraw->height)
2181f7df2e56Smrg            return BadMatch;
21826747b715Smrg
2183f7df2e56Smrg        relx += pDraw->x;
2184f7df2e56Smrg        rely += pDraw->y;
21856747b715Smrg
2186f7df2e56Smrg        if (pDraw->pScreen->GetWindowPixmap) {
2187f7df2e56Smrg            PixmapPtr pPix = (*pDraw->pScreen->GetWindowPixmap) (pWin);
21886747b715Smrg
2189f7df2e56Smrg            pBoundingDraw = &pPix->drawable;
21906747b715Smrg#ifdef COMPOSITE
2191f7df2e56Smrg            relx -= pPix->screen_x;
2192f7df2e56Smrg            rely -= pPix->screen_y;
21936747b715Smrg#endif
2194f7df2e56Smrg        }
2195f7df2e56Smrg        else {
2196f7df2e56Smrg            pBoundingDraw = (DrawablePtr) pDraw->pScreen->root;
2197f7df2e56Smrg        }
21986747b715Smrg
2199f7df2e56Smrg        xgi.visual = wVisual(pWin);
220005b261ecSmrg    }
2201f7df2e56Smrg    else {
2202f7df2e56Smrg        pBoundingDraw = pDraw;
2203f7df2e56Smrg        xgi.visual = None;
220405b261ecSmrg    }
220505b261ecSmrg
22066747b715Smrg    /* "If the drawable is a pixmap, the given rectangle must be wholly
22076747b715Smrg     *  contained within the pixmap, or a BadMatch error results.  If the
22086747b715Smrg     *  drawable is a window [...] it must be the case that if there were no
22096747b715Smrg     *  inferiors or overlapping windows, the specified rectangle of the window
22106747b715Smrg     *  would be fully visible on the screen and wholly contained within the
22116747b715Smrg     *  outside edges of the window, or a BadMatch error results."
22126747b715Smrg     *
22136747b715Smrg     * We relax the window case slightly to mean that the rectangle must exist
22146747b715Smrg     * within the bounds of the window's backing pixmap.  In particular, this
22156747b715Smrg     * means that a GetImage request may succeed or fail with BadMatch depending
22166747b715Smrg     * on whether any of its ancestor windows are redirected.  */
2217f7df2e56Smrg    if (relx < 0 || relx + width > (int) pBoundingDraw->width ||
2218f7df2e56Smrg        rely < 0 || rely + height > (int) pBoundingDraw->height)
2219f7df2e56Smrg        return BadMatch;
22206747b715Smrg
222105b261ecSmrg    xgi.type = X_Reply;
222205b261ecSmrg    xgi.sequenceNumber = client->sequence;
222305b261ecSmrg    xgi.depth = pDraw->depth;
2224f7df2e56Smrg    if (format == ZPixmap) {
2225f7df2e56Smrg        widthBytesLine = PixmapBytePad(width, pDraw->depth);
2226f7df2e56Smrg        length = widthBytesLine * height;
222705b261ecSmrg
222805b261ecSmrg    }
2229f7df2e56Smrg    else {
2230f7df2e56Smrg        widthBytesLine = BitmapBytePad(width);
2231f7df2e56Smrg        plane = ((Mask) 1) << (pDraw->depth - 1);
2232f7df2e56Smrg        /* only planes asked for */
2233f7df2e56Smrg        length = widthBytesLine * height *
2234f7df2e56Smrg            Ones(planemask & (plane | (plane - 1)));
223505b261ecSmrg
223605b261ecSmrg    }
223705b261ecSmrg
223805b261ecSmrg    xgi.length = length;
223905b261ecSmrg
2240f7df2e56Smrg    xgi.length = bytes_to_int32(xgi.length);
2241f7df2e56Smrg    if (widthBytesLine == 0 || height == 0)
2242f7df2e56Smrg        linesPerBuf = 0;
2243f7df2e56Smrg    else if (widthBytesLine >= IMAGE_BUFSIZE)
2244f7df2e56Smrg        linesPerBuf = 1;
2245f7df2e56Smrg    else {
2246f7df2e56Smrg        linesPerBuf = IMAGE_BUFSIZE / widthBytesLine;
2247f7df2e56Smrg        if (linesPerBuf > height)
2248f7df2e56Smrg            linesPerBuf = height;
2249f7df2e56Smrg    }
2250f7df2e56Smrg    length = linesPerBuf * widthBytesLine;
2251f7df2e56Smrg    if (linesPerBuf < height) {
2252f7df2e56Smrg        /* we have to make sure intermediate buffers don't need padding */
2253f7df2e56Smrg        while ((linesPerBuf > 1) &&
2254f7df2e56Smrg               (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD) - 1))) {
2255f7df2e56Smrg            linesPerBuf--;
2256f7df2e56Smrg            length -= widthBytesLine;
2257f7df2e56Smrg        }
2258f7df2e56Smrg        while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD) - 1)) {
2259f7df2e56Smrg            linesPerBuf++;
2260f7df2e56Smrg            length += widthBytesLine;
2261f7df2e56Smrg        }
226205b261ecSmrg    }
2263f7df2e56Smrg    if (!(pBuf = calloc(1, length)))
2264f7df2e56Smrg        return BadAlloc;
2265f7df2e56Smrg    WriteReplyToClient(client, sizeof(xGetImageReply), &xgi);
226605b261ecSmrg
22674e185dc0Smrg    if (pDraw->type == DRAWABLE_WINDOW) {
22687e31ba66Smrg        pVisibleRegion = &((WindowPtr) pDraw)->borderClip;
22694e185dc0Smrg        pDraw->pScreen->SourceValidate(pDraw, x, y, width, height,
22704e185dc0Smrg                                       IncludeInferiors);
22714e185dc0Smrg    }
2272f7df2e56Smrg
2273f7df2e56Smrg    if (linesPerBuf == 0) {
2274f7df2e56Smrg        /* nothing to do */
2275f7df2e56Smrg    }
2276f7df2e56Smrg    else if (format == ZPixmap) {
227705b261ecSmrg        linesDone = 0;
2278f7df2e56Smrg        while (height - linesDone > 0) {
2279f7df2e56Smrg            nlines = min(linesPerBuf, height - linesDone);
2280f7df2e56Smrg            (*pDraw->pScreen->GetImage) (pDraw,
2281f7df2e56Smrg                                         x,
2282f7df2e56Smrg                                         y + linesDone,
2283f7df2e56Smrg                                         width,
2284f7df2e56Smrg                                         nlines,
2285f7df2e56Smrg                                         format, planemask, (void *) pBuf);
2286f7df2e56Smrg            if (pVisibleRegion)
2287f7df2e56Smrg                XaceCensorImage(client, pVisibleRegion, widthBytesLine,
2288f7df2e56Smrg                                pDraw, x, y + linesDone, width,
2289f7df2e56Smrg                                nlines, format, pBuf);
2290f7df2e56Smrg
2291f7df2e56Smrg            /* Note that this is NOT a call to WriteSwappedDataToClient,
229205b261ecSmrg               as we do NOT byte swap */
2293f7df2e56Smrg            ReformatImage(pBuf, (int) (nlines * widthBytesLine),
2294f7df2e56Smrg                          BitsPerPixel(pDraw->depth), ClientOrder(client));
2295f7df2e56Smrg
2296f7df2e56Smrg            WriteToClient(client, (int) (nlines * widthBytesLine), pBuf);
2297f7df2e56Smrg            linesDone += nlines;
229805b261ecSmrg        }
229905b261ecSmrg    }
2300f7df2e56Smrg    else {                      /* XYPixmap */
2301f7df2e56Smrg
2302f7df2e56Smrg        for (; plane; plane >>= 1) {
2303f7df2e56Smrg            if (planemask & plane) {
2304f7df2e56Smrg                linesDone = 0;
2305f7df2e56Smrg                while (height - linesDone > 0) {
2306f7df2e56Smrg                    nlines = min(linesPerBuf, height - linesDone);
2307f7df2e56Smrg                    (*pDraw->pScreen->GetImage) (pDraw,
2308f7df2e56Smrg                                                 x,
2309f7df2e56Smrg                                                 y + linesDone,
2310f7df2e56Smrg                                                 width,
2311f7df2e56Smrg                                                 nlines,
2312f7df2e56Smrg                                                 format, plane, (void *) pBuf);
2313f7df2e56Smrg                    if (pVisibleRegion)
2314f7df2e56Smrg                        XaceCensorImage(client, pVisibleRegion,
2315f7df2e56Smrg                                        widthBytesLine,
2316f7df2e56Smrg                                        pDraw, x, y + linesDone, width,
2317f7df2e56Smrg                                        nlines, format, pBuf);
2318f7df2e56Smrg
2319f7df2e56Smrg                    /* Note: NOT a call to WriteSwappedDataToClient,
2320f7df2e56Smrg                       as we do NOT byte swap */
2321f7df2e56Smrg                    ReformatImage(pBuf, (int) (nlines * widthBytesLine),
2322f7df2e56Smrg                                  1, ClientOrder(client));
2323f7df2e56Smrg
2324f7df2e56Smrg                    WriteToClient(client, (int)(nlines * widthBytesLine), pBuf);
2325f7df2e56Smrg                    linesDone += nlines;
2326f7df2e56Smrg                }
232705b261ecSmrg            }
2328f7df2e56Smrg        }
232905b261ecSmrg    }
2330f7df2e56Smrg    free(pBuf);
23316747b715Smrg    return Success;
233205b261ecSmrg}
233305b261ecSmrg
233405b261ecSmrgint
233505b261ecSmrgProcGetImage(ClientPtr client)
233605b261ecSmrg{
233705b261ecSmrg    REQUEST(xGetImageReq);
233805b261ecSmrg
233905b261ecSmrg    REQUEST_SIZE_MATCH(xGetImageReq);
234005b261ecSmrg
234105b261ecSmrg    return DoGetImage(client, stuff->format, stuff->drawable,
2342f7df2e56Smrg                      stuff->x, stuff->y,
2343f7df2e56Smrg                      (int) stuff->width, (int) stuff->height,
2344f7df2e56Smrg                      stuff->planeMask);
234505b261ecSmrg}
234605b261ecSmrg
234705b261ecSmrgint
234805b261ecSmrgProcPolyText(ClientPtr client)
234905b261ecSmrg{
2350f7df2e56Smrg    int err;
2351f7df2e56Smrg
235205b261ecSmrg    REQUEST(xPolyTextReq);
235305b261ecSmrg    DrawablePtr pDraw;
235405b261ecSmrg    GC *pGC;
235505b261ecSmrg
235605b261ecSmrg    REQUEST_AT_LEAST_SIZE(xPolyTextReq);
23574642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
235805b261ecSmrg
235905b261ecSmrg    err = PolyText(client,
2360f7df2e56Smrg                   pDraw,
2361f7df2e56Smrg                   pGC,
2362f7df2e56Smrg                   (unsigned char *) &stuff[1],
2363f7df2e56Smrg                   ((unsigned char *) stuff) + (client->req_len << 2),
2364f7df2e56Smrg                   stuff->x, stuff->y, stuff->reqType, stuff->drawable);
2365f7df2e56Smrg
2366f7df2e56Smrg    if (err == Success) {
2367f7df2e56Smrg        return Success;
236805b261ecSmrg    }
236905b261ecSmrg    else
2370f7df2e56Smrg        return err;
237105b261ecSmrg}
237205b261ecSmrg
237305b261ecSmrgint
237405b261ecSmrgProcImageText8(ClientPtr client)
237505b261ecSmrg{
2376f7df2e56Smrg    int err;
237705b261ecSmrg    DrawablePtr pDraw;
237805b261ecSmrg    GC *pGC;
237905b261ecSmrg
238005b261ecSmrg    REQUEST(xImageTextReq);
238105b261ecSmrg
238205b261ecSmrg    REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars);
23834642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
238405b261ecSmrg
238505b261ecSmrg    err = ImageText(client,
2386f7df2e56Smrg                    pDraw,
2387f7df2e56Smrg                    pGC,
2388f7df2e56Smrg                    stuff->nChars,
2389f7df2e56Smrg                    (unsigned char *) &stuff[1],
2390f7df2e56Smrg                    stuff->x, stuff->y, stuff->reqType, stuff->drawable);
2391f7df2e56Smrg
2392f7df2e56Smrg    if (err == Success) {
2393f7df2e56Smrg        return Success;
239405b261ecSmrg    }
239505b261ecSmrg    else
2396f7df2e56Smrg        return err;
239705b261ecSmrg}
239805b261ecSmrg
239905b261ecSmrgint
240005b261ecSmrgProcImageText16(ClientPtr client)
240105b261ecSmrg{
2402f7df2e56Smrg    int err;
240305b261ecSmrg    DrawablePtr pDraw;
240405b261ecSmrg    GC *pGC;
240505b261ecSmrg
240605b261ecSmrg    REQUEST(xImageTextReq);
240705b261ecSmrg
240805b261ecSmrg    REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1);
24094642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
241005b261ecSmrg
241105b261ecSmrg    err = ImageText(client,
2412f7df2e56Smrg                    pDraw,
2413f7df2e56Smrg                    pGC,
2414f7df2e56Smrg                    stuff->nChars,
2415f7df2e56Smrg                    (unsigned char *) &stuff[1],
2416f7df2e56Smrg                    stuff->x, stuff->y, stuff->reqType, stuff->drawable);
2417f7df2e56Smrg
2418f7df2e56Smrg    if (err == Success) {
2419f7df2e56Smrg        return Success;
242005b261ecSmrg    }
242105b261ecSmrg    else
2422f7df2e56Smrg        return err;
242305b261ecSmrg}
242405b261ecSmrg
242505b261ecSmrgint
242605b261ecSmrgProcCreateColormap(ClientPtr client)
242705b261ecSmrg{
2428f7df2e56Smrg    VisualPtr pVisual;
2429f7df2e56Smrg    ColormapPtr pmap;
2430f7df2e56Smrg    Colormap mid;
2431f7df2e56Smrg    WindowPtr pWin;
243205b261ecSmrg    ScreenPtr pScreen;
2433f7df2e56Smrg
243405b261ecSmrg    REQUEST(xCreateColormapReq);
243505b261ecSmrg    int i, result;
243605b261ecSmrg
243705b261ecSmrg    REQUEST_SIZE_MATCH(xCreateColormapReq);
243805b261ecSmrg
2439f7df2e56Smrg    if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll)) {
2440f7df2e56Smrg        client->errorValue = stuff->alloc;
24416747b715Smrg        return BadValue;
244205b261ecSmrg    }
244305b261ecSmrg    mid = stuff->mid;
244405b261ecSmrg    LEGAL_NEW_RESOURCE(mid, client);
24454642e01fSmrg    result = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
244605b261ecSmrg    if (result != Success)
244705b261ecSmrg        return result;
244805b261ecSmrg
244905b261ecSmrg    pScreen = pWin->drawable.pScreen;
245005b261ecSmrg    for (i = 0, pVisual = pScreen->visuals;
2451f7df2e56Smrg         i < pScreen->numVisuals; i++, pVisual++) {
2452f7df2e56Smrg        if (pVisual->vid != stuff->visual)
2453f7df2e56Smrg            continue;
2454f7df2e56Smrg        return CreateColormap(mid, pScreen, pVisual, &pmap,
2455f7df2e56Smrg                              (int) stuff->alloc, client->index);
245605b261ecSmrg    }
245705b261ecSmrg    client->errorValue = stuff->visual;
24586747b715Smrg    return BadMatch;
245905b261ecSmrg}
246005b261ecSmrg
246105b261ecSmrgint
246205b261ecSmrgProcFreeColormap(ClientPtr client)
246305b261ecSmrg{
246405b261ecSmrg    ColormapPtr pmap;
24654642e01fSmrg    int rc;
2466f7df2e56Smrg
246705b261ecSmrg    REQUEST(xResourceReq);
246805b261ecSmrg
246905b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
2470f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pmap, stuff->id, RT_COLORMAP,
2471f7df2e56Smrg                                 client, DixDestroyAccess);
2472f7df2e56Smrg    if (rc == Success) {
2473f7df2e56Smrg        /* Freeing a default colormap is a no-op */
2474f7df2e56Smrg        if (!(pmap->flags & IsDefault))
2475f7df2e56Smrg            FreeResource(stuff->id, RT_NONE);
2476f7df2e56Smrg        return Success;
247705b261ecSmrg    }
2478f7df2e56Smrg    else {
2479f7df2e56Smrg        client->errorValue = stuff->id;
2480f7df2e56Smrg        return rc;
248105b261ecSmrg    }
248205b261ecSmrg}
248305b261ecSmrg
248405b261ecSmrgint
248505b261ecSmrgProcCopyColormapAndFree(ClientPtr client)
248605b261ecSmrg{
2487f7df2e56Smrg    Colormap mid;
2488f7df2e56Smrg    ColormapPtr pSrcMap;
2489f7df2e56Smrg
249005b261ecSmrg    REQUEST(xCopyColormapAndFreeReq);
24914642e01fSmrg    int rc;
249205b261ecSmrg
249305b261ecSmrg    REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq);
249405b261ecSmrg    mid = stuff->mid;
249505b261ecSmrg    LEGAL_NEW_RESOURCE(mid, client);
2496f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pSrcMap, stuff->srcCmap,
2497f7df2e56Smrg                                 RT_COLORMAP, client,
2498f7df2e56Smrg                                 DixReadAccess | DixRemoveAccess);
24994642e01fSmrg    if (rc == Success)
2500f7df2e56Smrg        return CopyColormapAndFree(mid, pSrcMap, client->index);
25016747b715Smrg    client->errorValue = stuff->srcCmap;
25026747b715Smrg    return rc;
250305b261ecSmrg}
250405b261ecSmrg
250505b261ecSmrgint
250605b261ecSmrgProcInstallColormap(ClientPtr client)
250705b261ecSmrg{
250805b261ecSmrg    ColormapPtr pcmp;
25094642e01fSmrg    int rc;
2510f7df2e56Smrg
251105b261ecSmrg    REQUEST(xResourceReq);
251205b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
25134642e01fSmrg
2514f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->id, RT_COLORMAP,
2515f7df2e56Smrg                                 client, DixInstallAccess);
25164642e01fSmrg    if (rc != Success)
2517f7df2e56Smrg        goto out;
25184642e01fSmrg
25194642e01fSmrg    rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess);
25206747b715Smrg    if (rc != Success) {
2521f7df2e56Smrg        if (rc == BadValue)
2522f7df2e56Smrg            rc = BadColor;
2523f7df2e56Smrg        goto out;
25246747b715Smrg    }
25254642e01fSmrg
25264642e01fSmrg    (*(pcmp->pScreen->InstallColormap)) (pcmp);
25276747b715Smrg    return Success;
25284642e01fSmrg
2529f7df2e56Smrg out:
25304642e01fSmrg    client->errorValue = stuff->id;
25316747b715Smrg    return rc;
253205b261ecSmrg}
253305b261ecSmrg
253405b261ecSmrgint
253505b261ecSmrgProcUninstallColormap(ClientPtr client)
253605b261ecSmrg{
253705b261ecSmrg    ColormapPtr pcmp;
25384642e01fSmrg    int rc;
2539f7df2e56Smrg
254005b261ecSmrg    REQUEST(xResourceReq);
254105b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
25424642e01fSmrg
2543f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->id, RT_COLORMAP,
2544f7df2e56Smrg                                 client, DixUninstallAccess);
25454642e01fSmrg    if (rc != Success)
2546f7df2e56Smrg        goto out;
25474642e01fSmrg
25484642e01fSmrg    rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess);
25496747b715Smrg    if (rc != Success) {
2550f7df2e56Smrg        if (rc == BadValue)
2551f7df2e56Smrg            rc = BadColor;
2552f7df2e56Smrg        goto out;
25536747b715Smrg    }
25544642e01fSmrg
2555f7df2e56Smrg    if (pcmp->mid != pcmp->pScreen->defColormap)
2556f7df2e56Smrg        (*(pcmp->pScreen->UninstallColormap)) (pcmp);
25576747b715Smrg    return Success;
25584642e01fSmrg
2559f7df2e56Smrg out:
25604642e01fSmrg    client->errorValue = stuff->id;
25616747b715Smrg    return rc;
256205b261ecSmrg}
256305b261ecSmrg
256405b261ecSmrgint
256505b261ecSmrgProcListInstalledColormaps(ClientPtr client)
256605b261ecSmrg{
2567f7df2e56Smrg    xListInstalledColormapsReply *preply;
256805b261ecSmrg    int nummaps, rc;
256905b261ecSmrg    WindowPtr pWin;
2570f7df2e56Smrg
257105b261ecSmrg    REQUEST(xResourceReq);
257205b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
25734642e01fSmrg
25744642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
257505b261ecSmrg    if (rc != Success)
2576f7df2e56Smrg        return rc;
25774642e01fSmrg
25784642e01fSmrg    rc = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen,
2579f7df2e56Smrg                  DixGetAttrAccess);
25804642e01fSmrg    if (rc != Success)
2581f7df2e56Smrg        return rc;
258205b261ecSmrg
25836747b715Smrg    preply = malloc(sizeof(xListInstalledColormapsReply) +
2584f7df2e56Smrg                    pWin->drawable.pScreen->maxInstalledCmaps *
2585f7df2e56Smrg                    sizeof(Colormap));
2586f7df2e56Smrg    if (!preply)
25876747b715Smrg        return BadAlloc;
258805b261ecSmrg
258905b261ecSmrg    preply->type = X_Reply;
259005b261ecSmrg    preply->sequenceNumber = client->sequence;
259105b261ecSmrg    nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps)
2592f7df2e56Smrg        (pWin->drawable.pScreen, (Colormap *) &preply[1]);
259305b261ecSmrg    preply->nColormaps = nummaps;
259405b261ecSmrg    preply->length = nummaps;
2595f7df2e56Smrg    WriteReplyToClient(client, sizeof(xListInstalledColormapsReply), preply);
259605b261ecSmrg    client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
259705b261ecSmrg    WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]);
25986747b715Smrg    free(preply);
25996747b715Smrg    return Success;
260005b261ecSmrg}
260105b261ecSmrg
260205b261ecSmrgint
2603f7df2e56SmrgProcAllocColor(ClientPtr client)
260405b261ecSmrg{
260505b261ecSmrg    ColormapPtr pmap;
26064642e01fSmrg    int rc;
2607f7df2e56Smrg
260805b261ecSmrg    REQUEST(xAllocColorReq);
260905b261ecSmrg
261005b261ecSmrg    REQUEST_SIZE_MATCH(xAllocColorReq);
2611f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pmap, stuff->cmap, RT_COLORMAP,
2612f7df2e56Smrg                                 client, DixAddAccess);
2613f7df2e56Smrg    if (rc == Success) {
2614f7df2e56Smrg        xAllocColorReply acr = {
2615f7df2e56Smrg            .type = X_Reply,
2616f7df2e56Smrg            .sequenceNumber = client->sequence,
2617f7df2e56Smrg            .length = 0,
2618f7df2e56Smrg            .red = stuff->red,
2619f7df2e56Smrg            .green = stuff->green,
2620f7df2e56Smrg            .blue = stuff->blue,
2621f7df2e56Smrg            .pixel = 0
2622f7df2e56Smrg        };
2623f7df2e56Smrg        if ((rc = AllocColor(pmap, &acr.red, &acr.green, &acr.blue,
2624f7df2e56Smrg                             &acr.pixel, client->index)))
2625f7df2e56Smrg            return rc;
262605b261ecSmrg#ifdef PANORAMIX
2627f7df2e56Smrg        if (noPanoramiXExtension || !pmap->pScreen->myNum)
262805b261ecSmrg#endif
2629f7df2e56Smrg            WriteReplyToClient(client, sizeof(xAllocColorReply), &acr);
2630f7df2e56Smrg        return Success;
263105b261ecSmrg
263205b261ecSmrg    }
2633f7df2e56Smrg    else {
263405b261ecSmrg        client->errorValue = stuff->cmap;
26356747b715Smrg        return rc;
263605b261ecSmrg    }
263705b261ecSmrg}
263805b261ecSmrg
263905b261ecSmrgint
2640f7df2e56SmrgProcAllocNamedColor(ClientPtr client)
264105b261ecSmrg{
264205b261ecSmrg    ColormapPtr pcmp;
26434642e01fSmrg    int rc;
2644f7df2e56Smrg
264505b261ecSmrg    REQUEST(xAllocNamedColorReq);
264605b261ecSmrg
264705b261ecSmrg    REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes);
2648f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2649f7df2e56Smrg                                 client, DixAddAccess);
2650f7df2e56Smrg    if (rc == Success) {
2651f7df2e56Smrg        xAllocNamedColorReply ancr = {
2652f7df2e56Smrg            .type = X_Reply,
2653f7df2e56Smrg            .sequenceNumber = client->sequence,
2654f7df2e56Smrg            .length = 0
2655f7df2e56Smrg        };
2656f7df2e56Smrg        if (OsLookupColor
2657f7df2e56Smrg            (pcmp->pScreen->myNum, (char *) &stuff[1], stuff->nbytes,
2658f7df2e56Smrg             &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue)) {
2659f7df2e56Smrg            ancr.screenRed = ancr.exactRed;
2660f7df2e56Smrg            ancr.screenGreen = ancr.exactGreen;
2661f7df2e56Smrg            ancr.screenBlue = ancr.exactBlue;
2662f7df2e56Smrg            ancr.pixel = 0;
2663f7df2e56Smrg            if ((rc = AllocColor(pcmp,
2664f7df2e56Smrg                                 &ancr.screenRed, &ancr.screenGreen,
2665f7df2e56Smrg                                 &ancr.screenBlue, &ancr.pixel, client->index)))
2666f7df2e56Smrg                return rc;
266705b261ecSmrg#ifdef PANORAMIX
2668f7df2e56Smrg            if (noPanoramiXExtension || !pcmp->pScreen->myNum)
266905b261ecSmrg#endif
2670f7df2e56Smrg                WriteReplyToClient(client, sizeof(xAllocNamedColorReply),
2671f7df2e56Smrg                                   &ancr);
2672f7df2e56Smrg            return Success;
2673f7df2e56Smrg        }
2674f7df2e56Smrg        else
2675f7df2e56Smrg            return BadName;
2676f7df2e56Smrg
267705b261ecSmrg    }
2678f7df2e56Smrg    else {
267905b261ecSmrg        client->errorValue = stuff->cmap;
26806747b715Smrg        return rc;
268105b261ecSmrg    }
268205b261ecSmrg}
268305b261ecSmrg
268405b261ecSmrgint
2685f7df2e56SmrgProcAllocColorCells(ClientPtr client)
268605b261ecSmrg{
268705b261ecSmrg    ColormapPtr pcmp;
26884642e01fSmrg    int rc;
2689f7df2e56Smrg
269005b261ecSmrg    REQUEST(xAllocColorCellsReq);
269105b261ecSmrg
269205b261ecSmrg    REQUEST_SIZE_MATCH(xAllocColorCellsReq);
2693f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2694f7df2e56Smrg                                 client, DixAddAccess);
2695f7df2e56Smrg    if (rc == Success) {
2696f7df2e56Smrg        int npixels, nmasks;
2697f7df2e56Smrg        long length;
2698f7df2e56Smrg        Pixel *ppixels, *pmasks;
2699f7df2e56Smrg
2700f7df2e56Smrg        npixels = stuff->colors;
2701f7df2e56Smrg        if (!npixels) {
2702f7df2e56Smrg            client->errorValue = npixels;
2703f7df2e56Smrg            return BadValue;
2704f7df2e56Smrg        }
2705f7df2e56Smrg        if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) {
2706f7df2e56Smrg            client->errorValue = stuff->contiguous;
2707f7df2e56Smrg            return BadValue;
2708f7df2e56Smrg        }
2709f7df2e56Smrg        nmasks = stuff->planes;
2710f7df2e56Smrg        length = ((long) npixels + (long) nmasks) * sizeof(Pixel);
2711f7df2e56Smrg        ppixels = malloc(length);
2712f7df2e56Smrg        if (!ppixels)
27136747b715Smrg            return BadAlloc;
2714f7df2e56Smrg        pmasks = ppixels + npixels;
2715f7df2e56Smrg
2716f7df2e56Smrg        if ((rc = AllocColorCells(client->index, pcmp, npixels, nmasks,
2717f7df2e56Smrg                                  (Bool) stuff->contiguous, ppixels, pmasks))) {
2718f7df2e56Smrg            free(ppixels);
2719f7df2e56Smrg            return rc;
2720f7df2e56Smrg        }
272105b261ecSmrg#ifdef PANORAMIX
2722f7df2e56Smrg        if (noPanoramiXExtension || !pcmp->pScreen->myNum)
272305b261ecSmrg#endif
2724f7df2e56Smrg        {
2725f7df2e56Smrg            xAllocColorCellsReply accr = {
2726f7df2e56Smrg                .type = X_Reply,
2727f7df2e56Smrg                .sequenceNumber = client->sequence,
2728f7df2e56Smrg                .length = bytes_to_int32(length),
2729f7df2e56Smrg                .nPixels = npixels,
2730f7df2e56Smrg                .nMasks = nmasks
2731f7df2e56Smrg            };
2732f7df2e56Smrg            WriteReplyToClient(client, sizeof(xAllocColorCellsReply), &accr);
2733f7df2e56Smrg            client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
2734f7df2e56Smrg            WriteSwappedDataToClient(client, length, ppixels);
2735f7df2e56Smrg        }
2736f7df2e56Smrg        free(ppixels);
27376747b715Smrg        return Success;
273805b261ecSmrg    }
2739f7df2e56Smrg    else {
274005b261ecSmrg        client->errorValue = stuff->cmap;
27416747b715Smrg        return rc;
274205b261ecSmrg    }
274305b261ecSmrg}
274405b261ecSmrg
274505b261ecSmrgint
274605b261ecSmrgProcAllocColorPlanes(ClientPtr client)
274705b261ecSmrg{
274805b261ecSmrg    ColormapPtr pcmp;
27494642e01fSmrg    int rc;
2750f7df2e56Smrg
275105b261ecSmrg    REQUEST(xAllocColorPlanesReq);
275205b261ecSmrg
275305b261ecSmrg    REQUEST_SIZE_MATCH(xAllocColorPlanesReq);
2754f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2755f7df2e56Smrg                                 client, DixAddAccess);
2756f7df2e56Smrg    if (rc == Success) {
2757f7df2e56Smrg        xAllocColorPlanesReply acpr;
2758f7df2e56Smrg        int npixels;
2759f7df2e56Smrg        long length;
2760f7df2e56Smrg        Pixel *ppixels;
2761f7df2e56Smrg
2762f7df2e56Smrg        npixels = stuff->colors;
2763f7df2e56Smrg        if (!npixels) {
2764f7df2e56Smrg            client->errorValue = npixels;
2765f7df2e56Smrg            return BadValue;
2766f7df2e56Smrg        }
2767f7df2e56Smrg        if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) {
2768f7df2e56Smrg            client->errorValue = stuff->contiguous;
2769f7df2e56Smrg            return BadValue;
2770f7df2e56Smrg        }
2771f7df2e56Smrg        acpr = (xAllocColorPlanesReply) {
2772f7df2e56Smrg            .type = X_Reply,
2773f7df2e56Smrg            .sequenceNumber = client->sequence,
2774f7df2e56Smrg            .nPixels = npixels
2775f7df2e56Smrg        };
2776f7df2e56Smrg        length = (long) npixels *sizeof(Pixel);
2777f7df2e56Smrg
2778f7df2e56Smrg        ppixels = malloc(length);
2779f7df2e56Smrg        if (!ppixels)
27806747b715Smrg            return BadAlloc;
2781f7df2e56Smrg        if ((rc = AllocColorPlanes(client->index, pcmp, npixels,
2782f7df2e56Smrg                                   (int) stuff->red, (int) stuff->green,
2783f7df2e56Smrg                                   (int) stuff->blue, (Bool) stuff->contiguous,
2784f7df2e56Smrg                                   ppixels, &acpr.redMask, &acpr.greenMask,
2785f7df2e56Smrg                                   &acpr.blueMask))) {
27866747b715Smrg            free(ppixels);
2787f7df2e56Smrg            return rc;
2788f7df2e56Smrg        }
2789f7df2e56Smrg        acpr.length = bytes_to_int32(length);
279005b261ecSmrg#ifdef PANORAMIX
2791f7df2e56Smrg        if (noPanoramiXExtension || !pcmp->pScreen->myNum)
279205b261ecSmrg#endif
2793f7df2e56Smrg        {
2794f7df2e56Smrg            WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr);
2795f7df2e56Smrg            client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
2796f7df2e56Smrg            WriteSwappedDataToClient(client, length, ppixels);
2797f7df2e56Smrg        }
2798f7df2e56Smrg        free(ppixels);
27996747b715Smrg        return Success;
280005b261ecSmrg    }
2801f7df2e56Smrg    else {
280205b261ecSmrg        client->errorValue = stuff->cmap;
28036747b715Smrg        return rc;
280405b261ecSmrg    }
280505b261ecSmrg}
280605b261ecSmrg
280705b261ecSmrgint
280805b261ecSmrgProcFreeColors(ClientPtr client)
280905b261ecSmrg{
281005b261ecSmrg    ColormapPtr pcmp;
28114642e01fSmrg    int rc;
2812f7df2e56Smrg
281305b261ecSmrg    REQUEST(xFreeColorsReq);
281405b261ecSmrg
281505b261ecSmrg    REQUEST_AT_LEAST_SIZE(xFreeColorsReq);
2816f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2817f7df2e56Smrg                                 client, DixRemoveAccess);
2818f7df2e56Smrg    if (rc == Success) {
2819f7df2e56Smrg        int count;
282005b261ecSmrg
2821f7df2e56Smrg        if (pcmp->flags & AllAllocated)
2822f7df2e56Smrg            return BadAccess;
2823f7df2e56Smrg        count = bytes_to_int32((client->req_len << 2) - sizeof(xFreeColorsReq));
2824f7df2e56Smrg        return FreeColors(pcmp, client->index, count,
2825f7df2e56Smrg                          (Pixel *) &stuff[1], (Pixel) stuff->planeMask);
282605b261ecSmrg    }
2827f7df2e56Smrg    else {
282805b261ecSmrg        client->errorValue = stuff->cmap;
28296747b715Smrg        return rc;
283005b261ecSmrg    }
283105b261ecSmrg}
283205b261ecSmrg
283305b261ecSmrgint
2834f7df2e56SmrgProcStoreColors(ClientPtr client)
283505b261ecSmrg{
283605b261ecSmrg    ColormapPtr pcmp;
28374642e01fSmrg    int rc;
2838f7df2e56Smrg
283905b261ecSmrg    REQUEST(xStoreColorsReq);
284005b261ecSmrg
284105b261ecSmrg    REQUEST_AT_LEAST_SIZE(xStoreColorsReq);
2842f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2843f7df2e56Smrg                                 client, DixWriteAccess);
2844f7df2e56Smrg    if (rc == Success) {
2845f7df2e56Smrg        int count;
284605b261ecSmrg
284705b261ecSmrg        count = (client->req_len << 2) - sizeof(xStoreColorsReq);
2848f7df2e56Smrg        if (count % sizeof(xColorItem))
2849f7df2e56Smrg            return BadLength;
2850f7df2e56Smrg        count /= sizeof(xColorItem);
2851f7df2e56Smrg        return StoreColors(pcmp, count, (xColorItem *) &stuff[1], client);
285205b261ecSmrg    }
2853f7df2e56Smrg    else {
285405b261ecSmrg        client->errorValue = stuff->cmap;
28556747b715Smrg        return rc;
285605b261ecSmrg    }
285705b261ecSmrg}
285805b261ecSmrg
285905b261ecSmrgint
2860f7df2e56SmrgProcStoreNamedColor(ClientPtr client)
286105b261ecSmrg{
286205b261ecSmrg    ColormapPtr pcmp;
28634642e01fSmrg    int rc;
2864f7df2e56Smrg
286505b261ecSmrg    REQUEST(xStoreNamedColorReq);
286605b261ecSmrg
286705b261ecSmrg    REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes);
2868f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2869f7df2e56Smrg                                 client, DixWriteAccess);
2870f7df2e56Smrg    if (rc == Success) {
2871f7df2e56Smrg        xColorItem def;
2872f7df2e56Smrg
2873f7df2e56Smrg        if (OsLookupColor(pcmp->pScreen->myNum, (char *) &stuff[1],
2874f7df2e56Smrg                          stuff->nbytes, &def.red, &def.green, &def.blue)) {
2875f7df2e56Smrg            def.flags = stuff->flags;
2876f7df2e56Smrg            def.pixel = stuff->pixel;
2877f7df2e56Smrg            return StoreColors(pcmp, 1, &def, client);
2878f7df2e56Smrg        }
28796747b715Smrg        return BadName;
288005b261ecSmrg    }
2881f7df2e56Smrg    else {
288205b261ecSmrg        client->errorValue = stuff->cmap;
28836747b715Smrg        return rc;
288405b261ecSmrg    }
288505b261ecSmrg}
288605b261ecSmrg
288705b261ecSmrgint
288805b261ecSmrgProcQueryColors(ClientPtr client)
288905b261ecSmrg{
289005b261ecSmrg    ColormapPtr pcmp;
28914642e01fSmrg    int rc;
2892f7df2e56Smrg
289305b261ecSmrg    REQUEST(xQueryColorsReq);
289405b261ecSmrg
289505b261ecSmrg    REQUEST_AT_LEAST_SIZE(xQueryColorsReq);
2896f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2897f7df2e56Smrg                                 client, DixReadAccess);
2898f7df2e56Smrg    if (rc == Success) {
2899f7df2e56Smrg        int count;
2900f7df2e56Smrg        xrgb *prgbs;
2901f7df2e56Smrg        xQueryColorsReply qcr;
2902f7df2e56Smrg
2903f7df2e56Smrg        count =
2904f7df2e56Smrg            bytes_to_int32((client->req_len << 2) - sizeof(xQueryColorsReq));
2905f7df2e56Smrg        prgbs = calloc(count, sizeof(xrgb));
2906f7df2e56Smrg        if (!prgbs && count)
29076747b715Smrg            return BadAlloc;
2908f7df2e56Smrg        if ((rc =
2909f7df2e56Smrg             QueryColors(pcmp, count, (Pixel *) &stuff[1], prgbs, client))) {
2910f7df2e56Smrg            free(prgbs);
2911f7df2e56Smrg            return rc;
2912f7df2e56Smrg        }
2913f7df2e56Smrg        qcr = (xQueryColorsReply) {
2914f7df2e56Smrg            .type = X_Reply,
2915f7df2e56Smrg            .sequenceNumber = client->sequence,
2916f7df2e56Smrg            .length = bytes_to_int32(count * sizeof(xrgb)),
2917f7df2e56Smrg            .nColors = count
2918f7df2e56Smrg        };
2919f7df2e56Smrg        WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr);
2920f7df2e56Smrg        if (count) {
2921f7df2e56Smrg            client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend;
2922f7df2e56Smrg            WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs);
2923f7df2e56Smrg        }
2924f7df2e56Smrg        free(prgbs);
2925f7df2e56Smrg        return Success;
2926f7df2e56Smrg
292705b261ecSmrg    }
2928f7df2e56Smrg    else {
292905b261ecSmrg        client->errorValue = stuff->cmap;
29306747b715Smrg        return rc;
293105b261ecSmrg    }
2932f7df2e56Smrg}
293305b261ecSmrg
293405b261ecSmrgint
293505b261ecSmrgProcLookupColor(ClientPtr client)
293605b261ecSmrg{
293705b261ecSmrg    ColormapPtr pcmp;
29384642e01fSmrg    int rc;
2939f7df2e56Smrg
294005b261ecSmrg    REQUEST(xLookupColorReq);
294105b261ecSmrg
294205b261ecSmrg    REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes);
2943f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2944f7df2e56Smrg                                 client, DixReadAccess);
2945f7df2e56Smrg    if (rc == Success) {
2946f7df2e56Smrg        CARD16 exactRed, exactGreen, exactBlue;
2947f7df2e56Smrg
2948f7df2e56Smrg        if (OsLookupColor
2949f7df2e56Smrg            (pcmp->pScreen->myNum, (char *) &stuff[1], stuff->nbytes,
2950f7df2e56Smrg             &exactRed, &exactGreen, &exactBlue)) {
2951f7df2e56Smrg            xLookupColorReply lcr = {
2952f7df2e56Smrg                .type = X_Reply,
2953f7df2e56Smrg                .sequenceNumber = client->sequence,
2954f7df2e56Smrg                .length = 0,
2955f7df2e56Smrg                .exactRed = exactRed,
2956f7df2e56Smrg                .exactGreen = exactGreen,
2957f7df2e56Smrg                .exactBlue = exactBlue,
2958f7df2e56Smrg                .screenRed = exactRed,
2959f7df2e56Smrg                .screenGreen = exactGreen,
2960f7df2e56Smrg                .screenBlue = exactBlue
2961f7df2e56Smrg            };
2962f7df2e56Smrg            (*pcmp->pScreen->ResolveColor) (&lcr.screenRed,
2963f7df2e56Smrg                                            &lcr.screenGreen,
2964f7df2e56Smrg                                            &lcr.screenBlue, pcmp->pVisual);
2965f7df2e56Smrg            WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr);
2966f7df2e56Smrg            return Success;
2967f7df2e56Smrg        }
29686747b715Smrg        return BadName;
296905b261ecSmrg    }
2970f7df2e56Smrg    else {
297105b261ecSmrg        client->errorValue = stuff->cmap;
29726747b715Smrg        return rc;
297305b261ecSmrg    }
297405b261ecSmrg}
297505b261ecSmrg
297605b261ecSmrgint
2977f7df2e56SmrgProcCreateCursor(ClientPtr client)
297805b261ecSmrg{
2979f7df2e56Smrg    CursorPtr pCursor;
2980f7df2e56Smrg    PixmapPtr src;
2981f7df2e56Smrg    PixmapPtr msk;
2982f7df2e56Smrg    unsigned char *srcbits;
2983f7df2e56Smrg    unsigned char *mskbits;
2984f7df2e56Smrg    unsigned short width, height;
2985f7df2e56Smrg    long n;
2986f7df2e56Smrg    CursorMetricRec cm;
29874642e01fSmrg    int rc;
298805b261ecSmrg
298905b261ecSmrg    REQUEST(xCreateCursorReq);
299005b261ecSmrg
299105b261ecSmrg    REQUEST_SIZE_MATCH(xCreateCursorReq);
299205b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->cid, client);
299305b261ecSmrg
2994f7df2e56Smrg    rc = dixLookupResourceByType((void **) &src, stuff->source, RT_PIXMAP,
2995f7df2e56Smrg                                 client, DixReadAccess);
29964642e01fSmrg    if (rc != Success) {
2997f7df2e56Smrg        client->errorValue = stuff->source;
2998f7df2e56Smrg        return rc;
299905b261ecSmrg    }
30004642e01fSmrg
3001f7df2e56Smrg    if (src->drawable.depth != 1)
3002f7df2e56Smrg        return (BadMatch);
3003f7df2e56Smrg
3004f7df2e56Smrg    /* Find and validate cursor mask pixmap, if one is provided */
3005f7df2e56Smrg    if (stuff->mask != None) {
3006f7df2e56Smrg        rc = dixLookupResourceByType((void **) &msk, stuff->mask, RT_PIXMAP,
3007f7df2e56Smrg                                     client, DixReadAccess);
3008f7df2e56Smrg        if (rc != Success) {
3009f7df2e56Smrg            client->errorValue = stuff->mask;
3010f7df2e56Smrg            return rc;
3011f7df2e56Smrg        }
3012f7df2e56Smrg
3013f7df2e56Smrg        if (src->drawable.width != msk->drawable.width
3014f7df2e56Smrg            || src->drawable.height != msk->drawable.height
3015f7df2e56Smrg            || src->drawable.depth != 1 || msk->drawable.depth != 1)
3016f7df2e56Smrg            return BadMatch;
3017f7df2e56Smrg    }
3018f7df2e56Smrg    else
3019f7df2e56Smrg        msk = NULL;
302005b261ecSmrg
302105b261ecSmrg    width = src->drawable.width;
302205b261ecSmrg    height = src->drawable.height;
302305b261ecSmrg
3024f7df2e56Smrg    if (stuff->x > width || stuff->y > height)
3025f7df2e56Smrg        return BadMatch;
302605b261ecSmrg
3027f7df2e56Smrg    srcbits = calloc(BitmapBytePad(width), height);
302805b261ecSmrg    if (!srcbits)
3029f7df2e56Smrg        return BadAlloc;
3030f7df2e56Smrg    n = BitmapBytePad(width) * height;
30316747b715Smrg    mskbits = malloc(n);
3032f7df2e56Smrg    if (!mskbits) {
3033f7df2e56Smrg        free(srcbits);
3034f7df2e56Smrg        return BadAlloc;
303505b261ecSmrg    }
303605b261ecSmrg
3037f7df2e56Smrg    (*src->drawable.pScreen->GetImage) ((DrawablePtr) src, 0, 0, width, height,
3038f7df2e56Smrg                                        XYPixmap, 1, (void *) srcbits);
3039f7df2e56Smrg    if (msk == (PixmapPtr) NULL) {
3040f7df2e56Smrg        unsigned char *bits = mskbits;
3041f7df2e56Smrg
3042f7df2e56Smrg        while (--n >= 0)
3043f7df2e56Smrg            *bits++ = ~0;
304405b261ecSmrg    }
3045f7df2e56Smrg    else {
3046f7df2e56Smrg        /* zeroing the (pad) bits helps some ddx cursor handling */
3047f7df2e56Smrg        memset((char *) mskbits, 0, n);
3048f7df2e56Smrg        (*msk->drawable.pScreen->GetImage) ((DrawablePtr) msk, 0, 0, width,
3049f7df2e56Smrg                                            height, XYPixmap, 1,
3050f7df2e56Smrg                                            (void *) mskbits);
305105b261ecSmrg    }
305205b261ecSmrg    cm.width = width;
305305b261ecSmrg    cm.height = height;
305405b261ecSmrg    cm.xhot = stuff->x;
305505b261ecSmrg    cm.yhot = stuff->y;
30564642e01fSmrg    rc = AllocARGBCursor(srcbits, mskbits, NULL, &cm,
3057f7df2e56Smrg                         stuff->foreRed, stuff->foreGreen, stuff->foreBlue,
3058f7df2e56Smrg                         stuff->backRed, stuff->backGreen, stuff->backBlue,
3059f7df2e56Smrg                         &pCursor, client, stuff->cid);
306005b261ecSmrg
30614642e01fSmrg    if (rc != Success)
3062f7df2e56Smrg        goto bail;
3063f7df2e56Smrg    if (!AddResource(stuff->cid, RT_CURSOR, (void *) pCursor)) {
3064f7df2e56Smrg        rc = BadAlloc;
3065f7df2e56Smrg        goto bail;
3066f7df2e56Smrg    }
30674642e01fSmrg
30686747b715Smrg    return Success;
3069f7df2e56Smrg bail:
3070f7df2e56Smrg    free(srcbits);
3071f7df2e56Smrg    free(mskbits);
3072f7df2e56Smrg    return rc;
307305b261ecSmrg}
307405b261ecSmrg
307505b261ecSmrgint
3076f7df2e56SmrgProcCreateGlyphCursor(ClientPtr client)
307705b261ecSmrg{
307805b261ecSmrg    CursorPtr pCursor;
307905b261ecSmrg    int res;
308005b261ecSmrg
308105b261ecSmrg    REQUEST(xCreateGlyphCursorReq);
308205b261ecSmrg
308305b261ecSmrg    REQUEST_SIZE_MATCH(xCreateGlyphCursorReq);
308405b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->cid, client);
308505b261ecSmrg
308605b261ecSmrg    res = AllocGlyphCursor(stuff->source, stuff->sourceChar,
3087f7df2e56Smrg                           stuff->mask, stuff->maskChar,
3088f7df2e56Smrg                           stuff->foreRed, stuff->foreGreen, stuff->foreBlue,
3089f7df2e56Smrg                           stuff->backRed, stuff->backGreen, stuff->backBlue,
3090f7df2e56Smrg                           &pCursor, client, stuff->cid);
309105b261ecSmrg    if (res != Success)
3092f7df2e56Smrg        return res;
3093f7df2e56Smrg    if (AddResource(stuff->cid, RT_CURSOR, (void *) pCursor))
3094f7df2e56Smrg        return Success;
309505b261ecSmrg    return BadAlloc;
309605b261ecSmrg}
309705b261ecSmrg
309805b261ecSmrgint
3099f7df2e56SmrgProcFreeCursor(ClientPtr client)
310005b261ecSmrg{
310105b261ecSmrg    CursorPtr pCursor;
31024642e01fSmrg    int rc;
3103f7df2e56Smrg
310405b261ecSmrg    REQUEST(xResourceReq);
310505b261ecSmrg
310605b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
3107f7df2e56Smrg    rc = dixLookupResourceByType((void **) &pCursor, stuff->id, RT_CURSOR,
3108f7df2e56Smrg                                 client, DixDestroyAccess);
3109f7df2e56Smrg    if (rc == Success) {
3110f7df2e56Smrg        FreeResource(stuff->id, RT_NONE);
3111f7df2e56Smrg        return Success;
311205b261ecSmrg    }
3113f7df2e56Smrg    else {
3114f7df2e56Smrg        client->errorValue = stuff->id;
3115f7df2e56Smrg        return rc;
311605b261ecSmrg    }
311705b261ecSmrg}
311805b261ecSmrg
311905b261ecSmrgint
3120f7df2e56SmrgProcQueryBestSize(ClientPtr client)
312105b261ecSmrg{
3122f7df2e56Smrg    xQueryBestSizeReply reply;
312305b261ecSmrg    DrawablePtr pDraw;
312405b261ecSmrg    ScreenPtr pScreen;
312505b261ecSmrg    int rc;
3126f7df2e56Smrg
312705b261ecSmrg    REQUEST(xQueryBestSizeReq);
312805b261ecSmrg    REQUEST_SIZE_MATCH(xQueryBestSizeReq);
312905b261ecSmrg
3130f7df2e56Smrg    if ((stuff->class != CursorShape) &&
3131f7df2e56Smrg        (stuff->class != TileShape) && (stuff->class != StippleShape)) {
3132f7df2e56Smrg        client->errorValue = stuff->class;
31336747b715Smrg        return BadValue;
313405b261ecSmrg    }
313505b261ecSmrg
313605b261ecSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
3137f7df2e56Smrg                           DixGetAttrAccess);
313805b261ecSmrg    if (rc != Success)
3139f7df2e56Smrg        return rc;
314005b261ecSmrg    if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW)
3141f7df2e56Smrg        return BadMatch;
314205b261ecSmrg    pScreen = pDraw->pScreen;
31434642e01fSmrg    rc = XaceHook(XACE_SCREEN_ACCESS, client, pScreen, DixGetAttrAccess);
31444642e01fSmrg    if (rc != Success)
3145f7df2e56Smrg        return rc;
3146f7df2e56Smrg    (*pScreen->QueryBestSize) (stuff->class, &stuff->width,
3147f7df2e56Smrg                               &stuff->height, pScreen);
3148f7df2e56Smrg    reply = (xQueryBestSizeReply) {
3149f7df2e56Smrg        .type = X_Reply,
3150f7df2e56Smrg        .sequenceNumber = client->sequence,
3151f7df2e56Smrg        .length = 0,
3152f7df2e56Smrg        .width = stuff->width,
3153f7df2e56Smrg        .height = stuff->height
3154f7df2e56Smrg    };
315505b261ecSmrg    WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply);
31566747b715Smrg    return Success;
315705b261ecSmrg}
315805b261ecSmrg
315905b261ecSmrgint
3160f7df2e56SmrgProcSetScreenSaver(ClientPtr client)
316105b261ecSmrg{
31624642e01fSmrg    int rc, i, blankingOption, exposureOption;
3163f7df2e56Smrg
316405b261ecSmrg    REQUEST(xSetScreenSaverReq);
316505b261ecSmrg    REQUEST_SIZE_MATCH(xSetScreenSaverReq);
31664642e01fSmrg
31674642e01fSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
3168f7df2e56Smrg        rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i],
3169f7df2e56Smrg                      DixSetAttrAccess);
3170f7df2e56Smrg        if (rc != Success)
3171f7df2e56Smrg            return rc;
31724642e01fSmrg    }
31734642e01fSmrg
317405b261ecSmrg    blankingOption = stuff->preferBlank;
317505b261ecSmrg    if ((blankingOption != DontPreferBlanking) &&
317605b261ecSmrg        (blankingOption != PreferBlanking) &&
3177f7df2e56Smrg        (blankingOption != DefaultBlanking)) {
3178f7df2e56Smrg        client->errorValue = blankingOption;
317905b261ecSmrg        return BadValue;
318005b261ecSmrg    }
318105b261ecSmrg    exposureOption = stuff->allowExpose;
318205b261ecSmrg    if ((exposureOption != DontAllowExposures) &&
318305b261ecSmrg        (exposureOption != AllowExposures) &&
3184f7df2e56Smrg        (exposureOption != DefaultExposures)) {
3185f7df2e56Smrg        client->errorValue = exposureOption;
318605b261ecSmrg        return BadValue;
318705b261ecSmrg    }
3188f7df2e56Smrg    if (stuff->timeout < -1) {
3189f7df2e56Smrg        client->errorValue = stuff->timeout;
319005b261ecSmrg        return BadValue;
319105b261ecSmrg    }
3192f7df2e56Smrg    if (stuff->interval < -1) {
3193f7df2e56Smrg        client->errorValue = stuff->interval;
319405b261ecSmrg        return BadValue;
319505b261ecSmrg    }
319605b261ecSmrg
319705b261ecSmrg    if (blankingOption == DefaultBlanking)
3198f7df2e56Smrg        ScreenSaverBlanking = defaultScreenSaverBlanking;
319905b261ecSmrg    else
3200f7df2e56Smrg        ScreenSaverBlanking = blankingOption;
320105b261ecSmrg    if (exposureOption == DefaultExposures)
3202f7df2e56Smrg        ScreenSaverAllowExposures = defaultScreenSaverAllowExposures;
320305b261ecSmrg    else
3204f7df2e56Smrg        ScreenSaverAllowExposures = exposureOption;
320505b261ecSmrg
320605b261ecSmrg    if (stuff->timeout >= 0)
3207f7df2e56Smrg        ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND;
3208f7df2e56Smrg    else
3209f7df2e56Smrg        ScreenSaverTime = defaultScreenSaverTime;
321005b261ecSmrg    if (stuff->interval >= 0)
3211f7df2e56Smrg        ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND;
321205b261ecSmrg    else
3213f7df2e56Smrg        ScreenSaverInterval = defaultScreenSaverInterval;
321405b261ecSmrg
321505b261ecSmrg    SetScreenSaverTimer();
32166747b715Smrg    return Success;
321705b261ecSmrg}
321805b261ecSmrg
321905b261ecSmrgint
322005b261ecSmrgProcGetScreenSaver(ClientPtr client)
322105b261ecSmrg{
322205b261ecSmrg    xGetScreenSaverReply rep;
32234642e01fSmrg    int rc, i;
3224f7df2e56Smrg
322505b261ecSmrg    REQUEST_SIZE_MATCH(xReq);
32264642e01fSmrg
32274642e01fSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
3228f7df2e56Smrg        rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i],
3229f7df2e56Smrg                      DixGetAttrAccess);
3230f7df2e56Smrg        if (rc != Success)
3231f7df2e56Smrg            return rc;
3232f7df2e56Smrg    }
3233f7df2e56Smrg
3234f7df2e56Smrg    rep = (xGetScreenSaverReply) {
3235f7df2e56Smrg        .type = X_Reply,
3236f7df2e56Smrg        .sequenceNumber = client->sequence,
3237f7df2e56Smrg        .length = 0,
3238f7df2e56Smrg        .timeout = ScreenSaverTime / MILLI_PER_SECOND,
3239f7df2e56Smrg        .interval = ScreenSaverInterval / MILLI_PER_SECOND,
3240f7df2e56Smrg        .preferBlanking = ScreenSaverBlanking,
3241f7df2e56Smrg        .allowExposures = ScreenSaverAllowExposures
3242f7df2e56Smrg    };
324305b261ecSmrg    WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep);
32446747b715Smrg    return Success;
324505b261ecSmrg}
324605b261ecSmrg
324705b261ecSmrgint
324805b261ecSmrgProcChangeHosts(ClientPtr client)
324905b261ecSmrg{
325005b261ecSmrg    REQUEST(xChangeHostsReq);
325105b261ecSmrg
325205b261ecSmrg    REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength);
325305b261ecSmrg
3254f7df2e56Smrg    if (stuff->mode == HostInsert)
3255f7df2e56Smrg        return AddHost(client, (int) stuff->hostFamily,
3256f7df2e56Smrg                       stuff->hostLength, (void *) &stuff[1]);
32576747b715Smrg    if (stuff->mode == HostDelete)
3258f7df2e56Smrg        return RemoveHost(client, (int) stuff->hostFamily,
3259f7df2e56Smrg                          stuff->hostLength, (void *) &stuff[1]);
32606747b715Smrg    client->errorValue = stuff->mode;
32616747b715Smrg    return BadValue;
326205b261ecSmrg}
326305b261ecSmrg
326405b261ecSmrgint
326505b261ecSmrgProcListHosts(ClientPtr client)
326605b261ecSmrg{
326705b261ecSmrg    xListHostsReply reply;
3268f7df2e56Smrg    int len, nHosts, result;
3269f7df2e56Smrg    BOOL enabled;
3270f7df2e56Smrg    void *pdata;
3271f7df2e56Smrg
327205b261ecSmrg    /* REQUEST(xListHostsReq); */
327305b261ecSmrg
327405b261ecSmrg    REQUEST_SIZE_MATCH(xListHostsReq);
327505b261ecSmrg
327605b261ecSmrg    /* untrusted clients can't list hosts */
32774642e01fSmrg    result = XaceHook(XACE_SERVER_ACCESS, client, DixReadAccess);
32784642e01fSmrg    if (result != Success)
3279f7df2e56Smrg        return result;
328005b261ecSmrg
3281f7df2e56Smrg    result = GetHosts(&pdata, &nHosts, &len, &enabled);
328205b261ecSmrg    if (result != Success)
3283f7df2e56Smrg        return result;
3284f7df2e56Smrg
3285f7df2e56Smrg    reply = (xListHostsReply) {
3286f7df2e56Smrg        .type = X_Reply,
3287f7df2e56Smrg        .enabled = enabled,
3288f7df2e56Smrg        .sequenceNumber = client->sequence,
3289f7df2e56Smrg        .length = bytes_to_int32(len),
3290f7df2e56Smrg        .nHosts = nHosts
3291f7df2e56Smrg    };
329205b261ecSmrg    WriteReplyToClient(client, sizeof(xListHostsReply), &reply);
3293f7df2e56Smrg    if (nHosts) {
3294f7df2e56Smrg        client->pSwapReplyFunc = (ReplySwapPtr) SLHostsExtend;
3295f7df2e56Smrg        WriteSwappedDataToClient(client, len, pdata);
329605b261ecSmrg    }
32976747b715Smrg    free(pdata);
32986747b715Smrg    return Success;
329905b261ecSmrg}
330005b261ecSmrg
330105b261ecSmrgint
330205b261ecSmrgProcChangeAccessControl(ClientPtr client)
330305b261ecSmrg{
330405b261ecSmrg    REQUEST(xSetAccessControlReq);
330505b261ecSmrg
330605b261ecSmrg    REQUEST_SIZE_MATCH(xSetAccessControlReq);
3307f7df2e56Smrg    if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess)) {
3308f7df2e56Smrg        client->errorValue = stuff->mode;
330905b261ecSmrg        return BadValue;
331005b261ecSmrg    }
33116747b715Smrg    return ChangeAccessControl(client, stuff->mode == EnableAccess);
331205b261ecSmrg}
331305b261ecSmrg
331405b261ecSmrg/*********************
331505b261ecSmrg * CloseDownRetainedResources
331605b261ecSmrg *
3317f7df2e56Smrg *    Find all clients that are gone and have terminated in RetainTemporary
331805b261ecSmrg *    and destroy their resources.
331905b261ecSmrg *********************/
332005b261ecSmrg
332105b261ecSmrgstatic void
332205b261ecSmrgCloseDownRetainedResources(void)
332305b261ecSmrg{
332405b261ecSmrg    int i;
332505b261ecSmrg    ClientPtr client;
332605b261ecSmrg
3327f7df2e56Smrg    for (i = 1; i < currentMaxClients; i++) {
332805b261ecSmrg        client = clients[i];
332905b261ecSmrg        if (client && (client->closeDownMode == RetainTemporary)
3330f7df2e56Smrg            && (client->clientGone))
3331f7df2e56Smrg            CloseDownClient(client);
333205b261ecSmrg    }
333305b261ecSmrg}
333405b261ecSmrg
333505b261ecSmrgint
333605b261ecSmrgProcKillClient(ClientPtr client)
333705b261ecSmrg{
333805b261ecSmrg    REQUEST(xResourceReq);
333905b261ecSmrg    ClientPtr killclient;
334005b261ecSmrg    int rc;
334105b261ecSmrg
334205b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
3343f7df2e56Smrg    if (stuff->id == AllTemporary) {
3344f7df2e56Smrg        CloseDownRetainedResources();
33456747b715Smrg        return Success;
334605b261ecSmrg    }
334705b261ecSmrg
334805b261ecSmrg    rc = dixLookupClient(&killclient, stuff->id, client, DixDestroyAccess);
334905b261ecSmrg    if (rc == Success) {
3350f7df2e56Smrg        CloseDownClient(killclient);
3351f7df2e56Smrg        if (client == killclient) {
3352f7df2e56Smrg            /* force yield and return Success, so that Dispatch()
3353f7df2e56Smrg             * doesn't try to touch client
3354f7df2e56Smrg             */
3355f7df2e56Smrg            isItTimeToYield = TRUE;
3356f7df2e56Smrg        }
3357f7df2e56Smrg        return Success;
335805b261ecSmrg    }
335905b261ecSmrg    else
3360f7df2e56Smrg        return rc;
336105b261ecSmrg}
336205b261ecSmrg
336305b261ecSmrgint
336405b261ecSmrgProcSetFontPath(ClientPtr client)
336505b261ecSmrg{
336605b261ecSmrg    unsigned char *ptr;
336705b261ecSmrg    unsigned long nbytes, total;
336805b261ecSmrg    long nfonts;
33696747b715Smrg    int n;
3370f7df2e56Smrg
337105b261ecSmrg    REQUEST(xSetFontPathReq);
3372f7df2e56Smrg
337305b261ecSmrg    REQUEST_AT_LEAST_SIZE(xSetFontPathReq);
3374f7df2e56Smrg
337505b261ecSmrg    nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq);
337605b261ecSmrg    total = nbytes;
3377f7df2e56Smrg    ptr = (unsigned char *) &stuff[1];
337805b261ecSmrg    nfonts = stuff->nFonts;
3379f7df2e56Smrg    while (--nfonts >= 0) {
3380f7df2e56Smrg        if ((total == 0) || (total < (n = (*ptr + 1))))
3381f7df2e56Smrg            return BadLength;
3382f7df2e56Smrg        total -= n;
3383f7df2e56Smrg        ptr += n;
338405b261ecSmrg    }
338505b261ecSmrg    if (total >= 4)
3386f7df2e56Smrg        return BadLength;
3387f7df2e56Smrg    return SetFontPath(client, stuff->nFonts, (unsigned char *) &stuff[1]);
338805b261ecSmrg}
338905b261ecSmrg
339005b261ecSmrgint
339105b261ecSmrgProcGetFontPath(ClientPtr client)
339205b261ecSmrg{
339305b261ecSmrg    xGetFontPathReply reply;
33944642e01fSmrg    int rc, stringLens, numpaths;
339505b261ecSmrg    unsigned char *bufferStart;
3396f7df2e56Smrg
339705b261ecSmrg    /* REQUEST (xReq); */
339805b261ecSmrg
339905b261ecSmrg    REQUEST_SIZE_MATCH(xReq);
34004642e01fSmrg    rc = GetFontPath(client, &numpaths, &stringLens, &bufferStart);
34014642e01fSmrg    if (rc != Success)
3402f7df2e56Smrg        return rc;
340305b261ecSmrg
3404f7df2e56Smrg    reply = (xGetFontPathReply) {
3405f7df2e56Smrg        .type = X_Reply,
3406f7df2e56Smrg        .sequenceNumber = client->sequence,
3407f7df2e56Smrg        .length = bytes_to_int32(stringLens + numpaths),
3408f7df2e56Smrg        .nPaths = numpaths
3409f7df2e56Smrg    };
341005b261ecSmrg
341105b261ecSmrg    WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply);
341205b261ecSmrg    if (stringLens || numpaths)
3413f7df2e56Smrg        WriteToClient(client, stringLens + numpaths, bufferStart);
34146747b715Smrg    return Success;
341505b261ecSmrg}
341605b261ecSmrg
341705b261ecSmrgint
341805b261ecSmrgProcChangeCloseDownMode(ClientPtr client)
341905b261ecSmrg{
34204642e01fSmrg    int rc;
3421f7df2e56Smrg
342205b261ecSmrg    REQUEST(xSetCloseDownModeReq);
342305b261ecSmrg    REQUEST_SIZE_MATCH(xSetCloseDownModeReq);
34244642e01fSmrg
34254642e01fSmrg    rc = XaceHook(XACE_CLIENT_ACCESS, client, client, DixManageAccess);
34264642e01fSmrg    if (rc != Success)
3427f7df2e56Smrg        return rc;
34284642e01fSmrg
342905b261ecSmrg    if ((stuff->mode == AllTemporary) ||
3430f7df2e56Smrg        (stuff->mode == RetainPermanent) || (stuff->mode == RetainTemporary)) {
3431f7df2e56Smrg        client->closeDownMode = stuff->mode;
3432f7df2e56Smrg        return Success;
343305b261ecSmrg    }
3434f7df2e56Smrg    else {
3435f7df2e56Smrg        client->errorValue = stuff->mode;
3436f7df2e56Smrg        return BadValue;
343705b261ecSmrg    }
343805b261ecSmrg}
343905b261ecSmrg
3440f7df2e56Smrgint
3441f7df2e56SmrgProcForceScreenSaver(ClientPtr client)
3442f7df2e56Smrg{
34434642e01fSmrg    int rc;
3444f7df2e56Smrg
344505b261ecSmrg    REQUEST(xForceScreenSaverReq);
344605b261ecSmrg
344705b261ecSmrg    REQUEST_SIZE_MATCH(xForceScreenSaverReq);
3448f7df2e56Smrg
3449f7df2e56Smrg    if ((stuff->mode != ScreenSaverReset) && (stuff->mode != ScreenSaverActive)) {
3450f7df2e56Smrg        client->errorValue = stuff->mode;
345105b261ecSmrg        return BadValue;
345205b261ecSmrg    }
3453f7df2e56Smrg    rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, (int) stuff->mode);
34544642e01fSmrg    if (rc != Success)
3455f7df2e56Smrg        return rc;
34566747b715Smrg    return Success;
345705b261ecSmrg}
345805b261ecSmrg
3459f7df2e56Smrgint
3460f7df2e56SmrgProcNoOperation(ClientPtr client)
346105b261ecSmrg{
346205b261ecSmrg    REQUEST_AT_LEAST_SIZE(xReq);
3463f7df2e56Smrg
346405b261ecSmrg    /* noop -- don't do anything */
34656747b715Smrg    return Success;
346605b261ecSmrg}
346705b261ecSmrg
346805b261ecSmrg/**********************
346905b261ecSmrg * CloseDownClient
347005b261ecSmrg *
347105b261ecSmrg *  Client can either mark his resources destroy or retain.  If retained and
347205b261ecSmrg *  then killed again, the client is really destroyed.
347305b261ecSmrg *********************/
347405b261ecSmrg
347505b261ecSmrgchar dispatchExceptionAtReset = DE_RESET;
34765a112b11Smrgint terminateDelay = 0;
347705b261ecSmrg
347805b261ecSmrgvoid
347905b261ecSmrgCloseDownClient(ClientPtr client)
348005b261ecSmrg{
348105b261ecSmrg    Bool really_close_down = client->clientGone ||
3482f7df2e56Smrg        client->closeDownMode == DestroyAll;
348305b261ecSmrg
3484f7df2e56Smrg    if (!client->clientGone) {
3485f7df2e56Smrg        /* ungrab server if grabbing client dies */
3486f7df2e56Smrg        if (grabState != GrabNone && grabClient == client) {
3487f7df2e56Smrg            UngrabServer(client);
3488f7df2e56Smrg        }
3489f7df2e56Smrg        BITCLEAR(grabWaiters, client->index);
3490f7df2e56Smrg        DeleteClientFromAnySelections(client);
3491f7df2e56Smrg        ReleaseActiveGrabs(client);
3492f7df2e56Smrg        DeleteClientFontStuff(client);
3493f7df2e56Smrg        if (!really_close_down) {
3494f7df2e56Smrg            /*  This frees resources that should never be retained
3495f7df2e56Smrg             *  no matter what the close down mode is.  Actually we
3496f7df2e56Smrg             *  could do this unconditionally, but it's probably
3497f7df2e56Smrg             *  better not to traverse all the client's resources
3498f7df2e56Smrg             *  twice (once here, once a few lines down in
3499f7df2e56Smrg             *  FreeClientResources) in the common case of
3500f7df2e56Smrg             *  really_close_down == TRUE.
3501f7df2e56Smrg             */
3502f7df2e56Smrg            FreeClientNeverRetainResources(client);
3503f7df2e56Smrg            client->clientState = ClientStateRetained;
3504f7df2e56Smrg            if (ClientStateCallback) {
3505f7df2e56Smrg                NewClientInfoRec clientinfo;
3506f7df2e56Smrg
3507f7df2e56Smrg                clientinfo.client = client;
3508f7df2e56Smrg                clientinfo.prefix = (xConnSetupPrefix *) NULL;
3509f7df2e56Smrg                clientinfo.setup = (xConnSetup *) NULL;
3510f7df2e56Smrg                CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
3511f7df2e56Smrg            }
3512f7df2e56Smrg        }
3513f7df2e56Smrg        client->clientGone = TRUE;      /* so events aren't sent to client */
3514f7df2e56Smrg        if (ClientIsAsleep(client))
3515f7df2e56Smrg            ClientSignal(client);
3516f7df2e56Smrg        ProcessWorkQueueZombies();
3517f7df2e56Smrg        CloseDownConnection(client);
35187e31ba66Smrg        output_pending_clear(client);
35197e31ba66Smrg        mark_client_not_ready(client);
3520f7df2e56Smrg
3521f7df2e56Smrg        /* If the client made it to the Running stage, nClients has
3522f7df2e56Smrg         * been incremented on its behalf, so we need to decrement it
3523f7df2e56Smrg         * now.  If it hasn't gotten to Running, nClients has *not*
3524f7df2e56Smrg         * been incremented, so *don't* decrement it.
3525f7df2e56Smrg         */
3526f7df2e56Smrg        if (client->clientState != ClientStateInitial) {
3527f7df2e56Smrg            --nClients;
3528f7df2e56Smrg        }
3529f7df2e56Smrg    }
3530f7df2e56Smrg
3531f7df2e56Smrg    if (really_close_down) {
3532f7df2e56Smrg        if (client->clientState == ClientStateRunning && nClients == 0)
35335a112b11Smrg            SetDispatchExceptionTimer();
3534f7df2e56Smrg
3535f7df2e56Smrg        client->clientState = ClientStateGone;
3536f7df2e56Smrg        if (ClientStateCallback) {
3537f7df2e56Smrg            NewClientInfoRec clientinfo;
3538f7df2e56Smrg
3539f7df2e56Smrg            clientinfo.client = client;
3540f7df2e56Smrg            clientinfo.prefix = (xConnSetupPrefix *) NULL;
3541f7df2e56Smrg            clientinfo.setup = (xConnSetup *) NULL;
3542f7df2e56Smrg            CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
3543f7df2e56Smrg        }
3544f7df2e56Smrg        TouchListenerGone(client->clientAsMask);
35455a112b11Smrg        GestureListenerGone(client->clientAsMask);
3546f7df2e56Smrg        FreeClientResources(client);
3547f7df2e56Smrg        /* Disable client ID tracking. This must be done after
3548f7df2e56Smrg         * ClientStateCallback. */
3549f7df2e56Smrg        ReleaseClientIds(client);
355005b261ecSmrg#ifdef XSERVER_DTRACE
3551f7df2e56Smrg        XSERVER_CLIENT_DISCONNECT(client->index);
3552f7df2e56Smrg#endif
3553f7df2e56Smrg        if (client->index < nextFreeClientID)
3554f7df2e56Smrg            nextFreeClientID = client->index;
3555f7df2e56Smrg        clients[client->index] = NullClient;
3556f7df2e56Smrg        SmartLastClient = NullClient;
3557f7df2e56Smrg        dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
355805b261ecSmrg
3559f7df2e56Smrg        while (!clients[currentMaxClients - 1])
3560f7df2e56Smrg            currentMaxClients--;
356105b261ecSmrg    }
35625a112b11Smrg
35635a112b11Smrg    if (ShouldDisconnectRemainingClients())
35645a112b11Smrg        SetDispatchExceptionTimer();
356505b261ecSmrg}
356605b261ecSmrg
356705b261ecSmrgstatic void
356805b261ecSmrgKillAllClients(void)
356905b261ecSmrg{
357005b261ecSmrg    int i;
3571f7df2e56Smrg
3572f7df2e56Smrg    for (i = 1; i < currentMaxClients; i++)
357305b261ecSmrg        if (clients[i]) {
357405b261ecSmrg            /* Make sure Retained clients are released. */
357505b261ecSmrg            clients[i]->closeDownMode = DestroyAll;
3576f7df2e56Smrg            CloseDownClient(clients[i]);
357705b261ecSmrg        }
357805b261ecSmrg}
357905b261ecSmrg
3580f7df2e56Smrgvoid
3581f7df2e56SmrgInitClient(ClientPtr client, int i, void *ospriv)
358205b261ecSmrg{
358305b261ecSmrg    client->index = i;
35847e31ba66Smrg    xorg_list_init(&client->ready);
35857e31ba66Smrg    xorg_list_init(&client->output_pending);
3586f7df2e56Smrg    client->clientAsMask = ((Mask) i) << CLIENTOFFSET;
35874642e01fSmrg    client->closeDownMode = i ? DestroyAll : RetainPermanent;
358805b261ecSmrg    client->requestVector = InitialVector;
358905b261ecSmrg    client->osPrivate = ospriv;
3590f7df2e56Smrg    QueryMinMaxKeyCodes(&client->minKC, &client->maxKC);
359105b261ecSmrg    client->smart_start_tick = SmartScheduleTime;
359205b261ecSmrg    client->smart_stop_tick = SmartScheduleTime;
3593f7df2e56Smrg    client->clientIds = NULL;
359405b261ecSmrg}
359505b261ecSmrg
359605b261ecSmrg/************************
359705b261ecSmrg * int NextAvailableClient(ospriv)
359805b261ecSmrg *
359905b261ecSmrg * OS dependent portion can't assign client id's because of CloseDownModes.
360005b261ecSmrg * Returns NULL if there are no free clients.
360105b261ecSmrg *************************/
360205b261ecSmrg
3603f7df2e56SmrgClientPtr
3604f7df2e56SmrgNextAvailableClient(void *ospriv)
360505b261ecSmrg{
360605b261ecSmrg    int i;
360705b261ecSmrg    ClientPtr client;
360805b261ecSmrg    xReq data;
360905b261ecSmrg
361005b261ecSmrg    i = nextFreeClientID;
3611f7df2e56Smrg    if (i == LimitClients)
3612f7df2e56Smrg        return (ClientPtr) NULL;
3613f7df2e56Smrg    clients[i] = client =
3614f7df2e56Smrg        dixAllocateObjectWithPrivates(ClientRec, PRIVATE_CLIENT);
361505b261ecSmrg    if (!client)
3616f7df2e56Smrg        return (ClientPtr) NULL;
361705b261ecSmrg    InitClient(client, i, ospriv);
3618f7df2e56Smrg    if (!InitClientResources(client)) {
3619f7df2e56Smrg        dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
3620f7df2e56Smrg        return (ClientPtr) NULL;
362105b261ecSmrg    }
362205b261ecSmrg    data.reqType = 1;
36236747b715Smrg    data.length = bytes_to_int32(sz_xReq + sz_xConnClientPrefix);
3624f7df2e56Smrg    if (!InsertFakeRequest(client, (char *) &data, sz_xReq)) {
3625f7df2e56Smrg        FreeClientResources(client);
3626f7df2e56Smrg        dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
3627f7df2e56Smrg        return (ClientPtr) NULL;
362805b261ecSmrg    }
362905b261ecSmrg    if (i == currentMaxClients)
3630f7df2e56Smrg        currentMaxClients++;
3631f7df2e56Smrg    while ((nextFreeClientID < LimitClients) && clients[nextFreeClientID])
3632f7df2e56Smrg        nextFreeClientID++;
3633f7df2e56Smrg
3634f7df2e56Smrg    /* Enable client ID tracking. This must be done before
3635f7df2e56Smrg     * ClientStateCallback. */
3636f7df2e56Smrg    ReserveClientIds(client);
3637f7df2e56Smrg
3638f7df2e56Smrg    if (ClientStateCallback) {
3639f7df2e56Smrg        NewClientInfoRec clientinfo;
364005b261ecSmrg
3641f7df2e56Smrg        clientinfo.client = client;
3642f7df2e56Smrg        clientinfo.prefix = (xConnSetupPrefix *) NULL;
364305b261ecSmrg        clientinfo.setup = (xConnSetup *) NULL;
3644f7df2e56Smrg        CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
3645f7df2e56Smrg    }
36466747b715Smrg    return client;
364705b261ecSmrg}
364805b261ecSmrg
364905b261ecSmrgint
365005b261ecSmrgProcInitialConnection(ClientPtr client)
365105b261ecSmrg{
365205b261ecSmrg    REQUEST(xReq);
365305b261ecSmrg    xConnClientPrefix *prefix;
365405b261ecSmrg    int whichbyte = 1;
3655f7df2e56Smrg    char order;
365605b261ecSmrg
3657f7df2e56Smrg    prefix = (xConnClientPrefix *) ((char *)stuff + sz_xReq);
3658f7df2e56Smrg    order = prefix->byteOrder;
3659f7df2e56Smrg    if (order != 'l' && order != 'B' && order != 'r' && order != 'R')
36606747b715Smrg	return client->noClientException = -1;
3661f7df2e56Smrg    if (((*(char *) &whichbyte) && (order == 'B' || order == 'R')) ||
3662f7df2e56Smrg	(!(*(char *) &whichbyte) && (order == 'l' || order == 'r'))) {
366305b261ecSmrg	client->swapped = TRUE;
366405b261ecSmrg	SwapConnClientPrefix(prefix);
366505b261ecSmrg    }
366605b261ecSmrg    stuff->reqType = 2;
36676747b715Smrg    stuff->length += bytes_to_int32(prefix->nbytesAuthProto) +
3668f7df2e56Smrg        bytes_to_int32(prefix->nbytesAuthString);
3669f7df2e56Smrg    if (client->swapped) {
3670f7df2e56Smrg        swaps(&stuff->length);
3671f7df2e56Smrg    }
3672f7df2e56Smrg    if (order == 'r' || order == 'R') {
3673f7df2e56Smrg	client->local = FALSE;
367405b261ecSmrg    }
367505b261ecSmrg    ResetCurrentRequest(client);
36766747b715Smrg    return Success;
367705b261ecSmrg}
367805b261ecSmrg
36794642e01fSmrgstatic int
3680f7df2e56SmrgSendConnSetup(ClientPtr client, const char *reason)
368105b261ecSmrg{
368205b261ecSmrg    xWindowRoot *root;
368305b261ecSmrg    int i;
368405b261ecSmrg    int numScreens;
3685f7df2e56Smrg    char *lConnectionInfo;
3686f7df2e56Smrg    xConnSetupPrefix *lconnSetupPrefix;
368705b261ecSmrg
3688f7df2e56Smrg    if (reason) {
3689f7df2e56Smrg        xConnSetupPrefix csp;
3690f7df2e56Smrg
3691f7df2e56Smrg        csp.success = xFalse;
3692f7df2e56Smrg        csp.lengthReason = strlen(reason);
3693f7df2e56Smrg        csp.length = bytes_to_int32(csp.lengthReason);
3694f7df2e56Smrg        csp.majorVersion = X_PROTOCOL;
3695f7df2e56Smrg        csp.minorVersion = X_PROTOCOL_REVISION;
3696f7df2e56Smrg        if (client->swapped)
3697f7df2e56Smrg            WriteSConnSetupPrefix(client, &csp);
3698f7df2e56Smrg        else
3699f7df2e56Smrg            WriteToClient(client, sz_xConnSetupPrefix, &csp);
3700f7df2e56Smrg        WriteToClient(client, (int) csp.lengthReason, reason);
3701f7df2e56Smrg        return client->noClientException = -1;
370205b261ecSmrg    }
370305b261ecSmrg
370405b261ecSmrg    numScreens = screenInfo.numScreens;
370505b261ecSmrg    lConnectionInfo = ConnectionInfo;
370605b261ecSmrg    lconnSetupPrefix = &connSetupPrefix;
370705b261ecSmrg
370805b261ecSmrg    /* We're about to start speaking X protocol back to the client by
370905b261ecSmrg     * sending the connection setup info.  This means the authorization
371005b261ecSmrg     * step is complete, and we can count the client as an
371105b261ecSmrg     * authorized one.
371205b261ecSmrg     */
371305b261ecSmrg    nClients++;
371405b261ecSmrg
371505b261ecSmrg    client->requestVector = client->swapped ? SwappedProcVector : ProcVector;
371605b261ecSmrg    client->sequence = 0;
3717f7df2e56Smrg    ((xConnSetup *) lConnectionInfo)->ridBase = client->clientAsMask;
3718f7df2e56Smrg    ((xConnSetup *) lConnectionInfo)->ridMask = RESOURCE_ID_MASK;
371905b261ecSmrg#ifdef MATCH_CLIENT_ENDIAN
3720f7df2e56Smrg    ((xConnSetup *) lConnectionInfo)->imageByteOrder = ClientOrder(client);
3721f7df2e56Smrg    ((xConnSetup *) lConnectionInfo)->bitmapBitOrder = ClientOrder(client);
372205b261ecSmrg#endif
372305b261ecSmrg    /* fill in the "currentInputMask" */
3724f7df2e56Smrg    root = (xWindowRoot *) (lConnectionInfo + connBlockScreenStart);
372505b261ecSmrg#ifdef PANORAMIX
372605b261ecSmrg    if (noPanoramiXExtension)
3727f7df2e56Smrg        numScreens = screenInfo.numScreens;
3728f7df2e56Smrg    else
3729f7df2e56Smrg        numScreens = ((xConnSetup *) ConnectionInfo)->numRoots;
373005b261ecSmrg#endif
373105b261ecSmrg
3732f7df2e56Smrg    for (i = 0; i < numScreens; i++) {
3733f7df2e56Smrg        unsigned int j;
3734f7df2e56Smrg        xDepth *pDepth;
3735f7df2e56Smrg        WindowPtr pRoot = screenInfo.screens[i]->root;
373605b261ecSmrg
37376747b715Smrg        root->currentInputMask = pRoot->eventMask | wOtherEventMasks(pRoot);
3738f7df2e56Smrg        pDepth = (xDepth *) (root + 1);
3739f7df2e56Smrg        for (j = 0; j < root->nDepths; j++) {
3740f7df2e56Smrg            pDepth = (xDepth *) (((char *) (pDepth + 1)) +
3741f7df2e56Smrg                                 pDepth->nVisuals * sizeof(xVisualType));
3742f7df2e56Smrg        }
3743f7df2e56Smrg        root = (xWindowRoot *) pDepth;
374405b261ecSmrg    }
374505b261ecSmrg
3746f7df2e56Smrg    if (client->swapped) {
3747f7df2e56Smrg        WriteSConnSetupPrefix(client, lconnSetupPrefix);
3748f7df2e56Smrg        WriteSConnectionInfo(client,
3749f7df2e56Smrg                             (unsigned long) (lconnSetupPrefix->length << 2),
3750f7df2e56Smrg                             lConnectionInfo);
375105b261ecSmrg    }
3752f7df2e56Smrg    else {
3753f7df2e56Smrg        WriteToClient(client, sizeof(xConnSetupPrefix), lconnSetupPrefix);
3754f7df2e56Smrg        WriteToClient(client, (int) (lconnSetupPrefix->length << 2),
3755f7df2e56Smrg		      lConnectionInfo);
375605b261ecSmrg    }
375705b261ecSmrg    client->clientState = ClientStateRunning;
3758f7df2e56Smrg    if (ClientStateCallback) {
3759f7df2e56Smrg        NewClientInfoRec clientinfo;
376005b261ecSmrg
3761f7df2e56Smrg        clientinfo.client = client;
3762f7df2e56Smrg        clientinfo.prefix = lconnSetupPrefix;
3763f7df2e56Smrg        clientinfo.setup = (xConnSetup *) lConnectionInfo;
3764f7df2e56Smrg        CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
3765f7df2e56Smrg    }
37665a112b11Smrg    CancelDispatchExceptionTimer();
37676747b715Smrg    return Success;
376805b261ecSmrg}
376905b261ecSmrg
377005b261ecSmrgint
377105b261ecSmrgProcEstablishConnection(ClientPtr client)
377205b261ecSmrg{
3773f7df2e56Smrg    const char *reason;
3774f7df2e56Smrg    char *auth_proto, *auth_string;
377505b261ecSmrg    xConnClientPrefix *prefix;
3776f7df2e56Smrg
377705b261ecSmrg    REQUEST(xReq);
377805b261ecSmrg
3779f7df2e56Smrg    prefix = (xConnClientPrefix *) ((char *) stuff + sz_xReq);
3780f7df2e56Smrg    auth_proto = (char *) prefix + sz_xConnClientPrefix;
37816747b715Smrg    auth_string = auth_proto + pad_to_int32(prefix->nbytesAuthProto);
37826e78d31fSmrg
37836e78d31fSmrg    if ((client->req_len << 2) != sz_xReq + sz_xConnClientPrefix +
37846e78d31fSmrg	pad_to_int32(prefix->nbytesAuthProto) +
37856e78d31fSmrg	pad_to_int32(prefix->nbytesAuthString))
37866e78d31fSmrg        reason = "Bad length";
37876e78d31fSmrg    else if ((prefix->majorVersion != X_PROTOCOL) ||
3788f7df2e56Smrg        (prefix->minorVersion != X_PROTOCOL_REVISION))
3789f7df2e56Smrg        reason = "Protocol version mismatch";
379005b261ecSmrg    else
3791f7df2e56Smrg        reason = ClientAuthorized(client,
3792f7df2e56Smrg                                  (unsigned short) prefix->nbytesAuthProto,
3793f7df2e56Smrg                                  auth_proto,
3794f7df2e56Smrg                                  (unsigned short) prefix->nbytesAuthString,
3795f7df2e56Smrg                                  auth_string);
3796f7df2e56Smrg
3797f7df2e56Smrg    return (SendConnSetup(client, reason));
379805b261ecSmrg}
379905b261ecSmrg
38006747b715Smrgvoid
3801f7df2e56SmrgSendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode,
380205b261ecSmrg                  XID resId, int errorCode)
380305b261ecSmrg{
3804f7df2e56Smrg    xError rep = {
3805f7df2e56Smrg        .type = X_Error,
3806f7df2e56Smrg        .errorCode = errorCode,
3807f7df2e56Smrg        .resourceID = resId,
3808f7df2e56Smrg        .minorCode = minorCode,
3809f7df2e56Smrg        .majorCode = majorCode
3810f7df2e56Smrg    };
381105b261ecSmrg
3812f7df2e56Smrg    WriteEventsToClient(client, 1, (xEvent *) &rep);
381305b261ecSmrg}
381405b261ecSmrg
381505b261ecSmrgvoid
381605b261ecSmrgMarkClientException(ClientPtr client)
381705b261ecSmrg{
381805b261ecSmrg    client->noClientException = -1;
381905b261ecSmrg}
38206747b715Smrg
38216747b715Smrg/*
38226747b715Smrg * This array encodes the answer to the question "what is the log base 2
38236747b715Smrg * of the number of pixels that fit in a scanline pad unit?"
38246747b715Smrg * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
38256747b715Smrg */
38266747b715Smrgstatic int answer[6][4] = {
3827f7df2e56Smrg    /* pad   pad   pad     pad */
3828f7df2e56Smrg    /*  8     16    32    64 */
3829f7df2e56Smrg
3830f7df2e56Smrg    {3, 4, 5, 6},               /* 1 bit per pixel */
3831f7df2e56Smrg    {1, 2, 3, 4},               /* 4 bits per pixel */
3832f7df2e56Smrg    {0, 1, 2, 3},               /* 8 bits per pixel */
3833f7df2e56Smrg    {~0, 0, 1, 2},              /* 16 bits per pixel */
3834f7df2e56Smrg    {~0, ~0, 0, 1},             /* 24 bits per pixel */
3835f7df2e56Smrg    {~0, ~0, 0, 1}              /* 32 bits per pixel */
38366747b715Smrg};
38376747b715Smrg
38386747b715Smrg/*
38396747b715Smrg * This array gives the answer to the question "what is the first index for
38406747b715Smrg * the answer array above given the number of bits per pixel?"
38416747b715Smrg * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
38426747b715Smrg */
3843f7df2e56Smrgstatic int indexForBitsPerPixel[33] = {
3844f7df2e56Smrg    ~0, 0, ~0, ~0,              /* 1 bit per pixel */
3845f7df2e56Smrg    1, ~0, ~0, ~0,              /* 4 bits per pixel */
3846f7df2e56Smrg    2, ~0, ~0, ~0,              /* 8 bits per pixel */
3847f7df2e56Smrg    ~0, ~0, ~0, ~0,
3848f7df2e56Smrg    3, ~0, ~0, ~0,              /* 16 bits per pixel */
3849f7df2e56Smrg    ~0, ~0, ~0, ~0,
3850f7df2e56Smrg    4, ~0, ~0, ~0,              /* 24 bits per pixel */
3851f7df2e56Smrg    ~0, ~0, ~0, ~0,
3852f7df2e56Smrg    5                           /* 32 bits per pixel */
38536747b715Smrg};
38546747b715Smrg
38556747b715Smrg/*
38566747b715Smrg * This array gives the bytesperPixel value for cases where the number
38576747b715Smrg * of bits per pixel is a multiple of 8 but not a power of 2.
38586747b715Smrg */
3859f7df2e56Smrgstatic int answerBytesPerPixel[33] = {
3860f7df2e56Smrg    ~0, 0, ~0, ~0,              /* 1 bit per pixel */
3861f7df2e56Smrg    0, ~0, ~0, ~0,              /* 4 bits per pixel */
3862f7df2e56Smrg    0, ~0, ~0, ~0,              /* 8 bits per pixel */
3863f7df2e56Smrg    ~0, ~0, ~0, ~0,
3864f7df2e56Smrg    0, ~0, ~0, ~0,              /* 16 bits per pixel */
3865f7df2e56Smrg    ~0, ~0, ~0, ~0,
3866f7df2e56Smrg    3, ~0, ~0, ~0,              /* 24 bits per pixel */
3867f7df2e56Smrg    ~0, ~0, ~0, ~0,
3868f7df2e56Smrg    0                           /* 32 bits per pixel */
38696747b715Smrg};
38706747b715Smrg
38716747b715Smrg/*
38726747b715Smrg * This array gives the answer to the question "what is the second index for
38736747b715Smrg * the answer array above given the number of bits per scanline pad unit?"
38746747b715Smrg * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
38756747b715Smrg */
3876f7df2e56Smrgstatic int indexForScanlinePad[65] = {
3877f7df2e56Smrg    ~0, ~0, ~0, ~0,
3878f7df2e56Smrg    ~0, ~0, ~0, ~0,
3879f7df2e56Smrg    0, ~0, ~0, ~0,              /* 8 bits per scanline pad unit */
3880f7df2e56Smrg    ~0, ~0, ~0, ~0,
3881f7df2e56Smrg    1, ~0, ~0, ~0,              /* 16 bits per scanline pad unit */
3882f7df2e56Smrg    ~0, ~0, ~0, ~0,
3883f7df2e56Smrg    ~0, ~0, ~0, ~0,
3884f7df2e56Smrg    ~0, ~0, ~0, ~0,
3885f7df2e56Smrg    2, ~0, ~0, ~0,              /* 32 bits per scanline pad unit */
3886f7df2e56Smrg    ~0, ~0, ~0, ~0,
3887f7df2e56Smrg    ~0, ~0, ~0, ~0,
3888f7df2e56Smrg    ~0, ~0, ~0, ~0,
3889f7df2e56Smrg    ~0, ~0, ~0, ~0,
3890f7df2e56Smrg    ~0, ~0, ~0, ~0,
3891f7df2e56Smrg    ~0, ~0, ~0, ~0,
3892f7df2e56Smrg    ~0, ~0, ~0, ~0,
3893f7df2e56Smrg    3                           /* 64 bits per scanline pad unit */
38946747b715Smrg};
38956747b715Smrg
38966747b715Smrg/*
38976747b715Smrg	grow the array of screenRecs if necessary.
38986747b715Smrg	call the device-supplied initialization procedure
38996747b715Smrgwith its screen number, a pointer to its ScreenRec, argc, and argv.
39006747b715Smrg	return the number of successfully installed screens.
39016747b715Smrg
39026747b715Smrg*/
39036747b715Smrg
3904f7df2e56Smrgstatic int init_screen(ScreenPtr pScreen, int i, Bool gpu)
39056747b715Smrg{
39066747b715Smrg    int scanlinepad, format, depth, bitsPerPixel, j, k;
39076747b715Smrg
3908f7df2e56Smrg    dixInitScreenSpecificPrivates(pScreen);
39096747b715Smrg
39106747b715Smrg    if (!dixAllocatePrivates(&pScreen->devPrivates, PRIVATE_SCREEN)) {
3911f7df2e56Smrg        return -1;
39126747b715Smrg    }
39136747b715Smrg    pScreen->myNum = i;
3914f7df2e56Smrg    if (gpu) {
3915f7df2e56Smrg        pScreen->myNum += GPU_SCREEN_OFFSET;
3916f7df2e56Smrg        pScreen->isGPU = TRUE;
3917f7df2e56Smrg    }
3918f7df2e56Smrg    pScreen->totalPixmapSize = 0;       /* computed in CreateScratchPixmapForScreen */
3919f7df2e56Smrg    pScreen->ClipNotify = 0;    /* for R4 ddx compatibility */
39206747b715Smrg    pScreen->CreateScreenResources = 0;
39216747b715Smrg
3922f7df2e56Smrg    xorg_list_init(&pScreen->pixmap_dirty_list);
39235a112b11Smrg    xorg_list_init(&pScreen->secondary_list);
3924f7df2e56Smrg
39256747b715Smrg    /*
39266747b715Smrg     * This loop gets run once for every Screen that gets added,
39275a112b11Smrg     * but that's ok.  If the ddx layer initializes the formats
39286747b715Smrg     * one at a time calling AddScreen() after each, then each
39296747b715Smrg     * iteration will make it a little more accurate.  Worst case
39306747b715Smrg     * we do this loop N * numPixmapFormats where N is # of screens.
39316747b715Smrg     * Anyway, this must be called after InitOutput and before the
39326747b715Smrg     * screen init routine is called.
39336747b715Smrg     */
3934f7df2e56Smrg    for (format = 0; format < screenInfo.numPixmapFormats; format++) {
3935f7df2e56Smrg        depth = screenInfo.formats[format].depth;
3936f7df2e56Smrg        bitsPerPixel = screenInfo.formats[format].bitsPerPixel;
3937f7df2e56Smrg        scanlinepad = screenInfo.formats[format].scanlinePad;
3938f7df2e56Smrg        j = indexForBitsPerPixel[bitsPerPixel];
3939f7df2e56Smrg        k = indexForScanlinePad[scanlinepad];
3940f7df2e56Smrg        PixmapWidthPaddingInfo[depth].padPixelsLog2 = answer[j][k];
3941f7df2e56Smrg        PixmapWidthPaddingInfo[depth].padRoundUp =
3942f7df2e56Smrg            (scanlinepad / bitsPerPixel) - 1;
3943f7df2e56Smrg        j = indexForBitsPerPixel[8];    /* bits per byte */
3944f7df2e56Smrg        PixmapWidthPaddingInfo[depth].padBytesLog2 = answer[j][k];
3945f7df2e56Smrg        PixmapWidthPaddingInfo[depth].bitsPerPixel = bitsPerPixel;
3946f7df2e56Smrg        if (answerBytesPerPixel[bitsPerPixel]) {
3947f7df2e56Smrg            PixmapWidthPaddingInfo[depth].notPower2 = 1;
3948f7df2e56Smrg            PixmapWidthPaddingInfo[depth].bytesPerPixel =
3949f7df2e56Smrg                answerBytesPerPixel[bitsPerPixel];
3950f7df2e56Smrg        }
3951f7df2e56Smrg        else {
3952f7df2e56Smrg            PixmapWidthPaddingInfo[depth].notPower2 = 0;
3953f7df2e56Smrg        }
39546747b715Smrg    }
3955f7df2e56Smrg    return 0;
3956f7df2e56Smrg}
3957f7df2e56Smrg
3958f7df2e56Smrgint
3959f7df2e56SmrgAddScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
3960f7df2e56Smrg                           int /*argc */ ,
3961f7df2e56Smrg                           char **      /*argv */
3962f7df2e56Smrg          ), int argc, char **argv)
3963f7df2e56Smrg{
3964f7df2e56Smrg
3965f7df2e56Smrg    int i;
3966f7df2e56Smrg    ScreenPtr pScreen;
3967f7df2e56Smrg    Bool ret;
3968f7df2e56Smrg
3969f7df2e56Smrg    i = screenInfo.numScreens;
3970f7df2e56Smrg    if (i == MAXSCREENS)
3971f7df2e56Smrg        return -1;
3972f7df2e56Smrg
3973f7df2e56Smrg    pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec));
3974f7df2e56Smrg    if (!pScreen)
3975f7df2e56Smrg        return -1;
39766747b715Smrg
3977f7df2e56Smrg    ret = init_screen(pScreen, i, FALSE);
3978f7df2e56Smrg    if (ret != 0) {
3979f7df2e56Smrg        free(pScreen);
3980f7df2e56Smrg        return ret;
3981f7df2e56Smrg    }
39826747b715Smrg    /* This is where screen specific stuff gets initialized.  Load the
39836747b715Smrg       screen structure, call the hardware, whatever.
39846747b715Smrg       This is also where the default colormap should be allocated and
39856747b715Smrg       also pixel values for blackPixel, whitePixel, and the cursor
39866747b715Smrg       Note that InitScreen is NOT allowed to modify argc, argv, or
39876747b715Smrg       any of the strings pointed to by argv.  They may be passed to
39886747b715Smrg       multiple screens.
3989f7df2e56Smrg     */
39906747b715Smrg    screenInfo.screens[i] = pScreen;
39916747b715Smrg    screenInfo.numScreens++;
3992f7df2e56Smrg    if (!(*pfnInit) (pScreen, argc, argv)) {
3993f7df2e56Smrg        dixFreeScreenSpecificPrivates(pScreen);
3994f7df2e56Smrg        dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
3995f7df2e56Smrg        free(pScreen);
3996f7df2e56Smrg        screenInfo.numScreens--;
3997f7df2e56Smrg        return -1;
39986747b715Smrg    }
39996747b715Smrg
4000f7df2e56Smrg    update_desktop_dimensions();
4001f7df2e56Smrg
4002f7df2e56Smrg    dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen, PRIVATE_CURSOR,
4003f7df2e56Smrg                                0);
40046747b715Smrg
40056747b715Smrg    return i;
40066747b715Smrg}
4007f7df2e56Smrg
4008f7df2e56Smrgint
4009f7df2e56SmrgAddGPUScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
4010f7df2e56Smrg                              int /*argc */ ,
4011f7df2e56Smrg                              char **      /*argv */
4012f7df2e56Smrg                              ),
4013f7df2e56Smrg             int argc, char **argv)
4014f7df2e56Smrg{
4015f7df2e56Smrg    int i;
4016f7df2e56Smrg    ScreenPtr pScreen;
4017f7df2e56Smrg    Bool ret;
4018f7df2e56Smrg
4019f7df2e56Smrg    i = screenInfo.numGPUScreens;
4020f7df2e56Smrg    if (i == MAXGPUSCREENS)
4021f7df2e56Smrg        return -1;
4022f7df2e56Smrg
4023f7df2e56Smrg    pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec));
4024f7df2e56Smrg    if (!pScreen)
4025f7df2e56Smrg        return -1;
4026f7df2e56Smrg
4027f7df2e56Smrg    ret = init_screen(pScreen, i, TRUE);
4028f7df2e56Smrg    if (ret != 0) {
4029f7df2e56Smrg        free(pScreen);
4030f7df2e56Smrg        return ret;
4031f7df2e56Smrg    }
4032f7df2e56Smrg
4033f7df2e56Smrg    /* This is where screen specific stuff gets initialized.  Load the
4034f7df2e56Smrg       screen structure, call the hardware, whatever.
4035f7df2e56Smrg       This is also where the default colormap should be allocated and
4036f7df2e56Smrg       also pixel values for blackPixel, whitePixel, and the cursor
4037f7df2e56Smrg       Note that InitScreen is NOT allowed to modify argc, argv, or
4038f7df2e56Smrg       any of the strings pointed to by argv.  They may be passed to
4039f7df2e56Smrg       multiple screens.
4040f7df2e56Smrg     */
4041f7df2e56Smrg    screenInfo.gpuscreens[i] = pScreen;
4042f7df2e56Smrg    screenInfo.numGPUScreens++;
4043f7df2e56Smrg    if (!(*pfnInit) (pScreen, argc, argv)) {
4044f7df2e56Smrg        dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
4045f7df2e56Smrg        free(pScreen);
4046f7df2e56Smrg        screenInfo.numGPUScreens--;
4047f7df2e56Smrg        return -1;
4048f7df2e56Smrg    }
4049f7df2e56Smrg
4050f7df2e56Smrg    update_desktop_dimensions();
4051f7df2e56Smrg
40527e31ba66Smrg    /*
40537e31ba66Smrg     * We cannot register the Screen PRIVATE_CURSOR key if cursors are already
40547e31ba66Smrg     * created, because dix/privates.c does not have relocation code for
40557e31ba66Smrg     * PRIVATE_CURSOR. Once this is fixed the if() can be removed and we can
40567e31ba66Smrg     * register the Screen PRIVATE_CURSOR key unconditionally.
40577e31ba66Smrg     */
40587e31ba66Smrg    if (!dixPrivatesCreated(PRIVATE_CURSOR))
40597e31ba66Smrg        dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen,
40607e31ba66Smrg                                    PRIVATE_CURSOR, 0);
40617e31ba66Smrg
4062f7df2e56Smrg    return i;
4063f7df2e56Smrg}
4064f7df2e56Smrg
4065f7df2e56Smrgvoid
4066f7df2e56SmrgRemoveGPUScreen(ScreenPtr pScreen)
4067f7df2e56Smrg{
4068f7df2e56Smrg    int idx, j;
4069f7df2e56Smrg    if (!pScreen->isGPU)
4070f7df2e56Smrg        return;
4071f7df2e56Smrg
4072f7df2e56Smrg    idx = pScreen->myNum - GPU_SCREEN_OFFSET;
4073f7df2e56Smrg    for (j = idx; j < screenInfo.numGPUScreens - 1; j++) {
4074f7df2e56Smrg        screenInfo.gpuscreens[j] = screenInfo.gpuscreens[j + 1];
4075f7df2e56Smrg        screenInfo.gpuscreens[j]->myNum = j + GPU_SCREEN_OFFSET;
4076f7df2e56Smrg    }
4077f7df2e56Smrg    screenInfo.numGPUScreens--;
4078f7df2e56Smrg
4079f7df2e56Smrg    /* this gets freed later in the resource list, but without
4080f7df2e56Smrg     * the screen existing it causes crashes - so remove it here */
4081f7df2e56Smrg    if (pScreen->defColormap)
4082f7df2e56Smrg        FreeResource(pScreen->defColormap, RT_COLORMAP);
4083f7df2e56Smrg    free(pScreen);
4084f7df2e56Smrg
4085f7df2e56Smrg}
4086f7df2e56Smrg
4087f7df2e56Smrgvoid
4088f7df2e56SmrgAttachUnboundGPU(ScreenPtr pScreen, ScreenPtr new)
4089f7df2e56Smrg{
4090f7df2e56Smrg    assert(new->isGPU);
40915a112b11Smrg    assert(!new->current_primary);
40925a112b11Smrg    xorg_list_add(&new->secondary_head, &pScreen->secondary_list);
40935a112b11Smrg    new->current_primary = pScreen;
4094f7df2e56Smrg}
4095f7df2e56Smrg
4096f7df2e56Smrgvoid
40975a112b11SmrgDetachUnboundGPU(ScreenPtr secondary)
4098f7df2e56Smrg{
40995a112b11Smrg    assert(secondary->isGPU);
41005a112b11Smrg    assert(!secondary->is_output_secondary);
41015a112b11Smrg    assert(!secondary->is_offload_secondary);
41025a112b11Smrg    xorg_list_del(&secondary->secondary_head);
41035a112b11Smrg    secondary->current_primary = NULL;
4104f7df2e56Smrg}
4105f7df2e56Smrg
4106f7df2e56Smrgvoid
4107f7df2e56SmrgAttachOutputGPU(ScreenPtr pScreen, ScreenPtr new)
4108f7df2e56Smrg{
4109f7df2e56Smrg    assert(new->isGPU);
41105a112b11Smrg    assert(!new->is_output_secondary);
41115a112b11Smrg    assert(new->current_primary == pScreen);
41125a112b11Smrg    new->is_output_secondary = TRUE;
41135a112b11Smrg    new->current_primary->output_secondarys++;
4114f7df2e56Smrg}
4115f7df2e56Smrg
4116f7df2e56Smrgvoid
41175a112b11SmrgDetachOutputGPU(ScreenPtr secondary)
4118f7df2e56Smrg{
41195a112b11Smrg    assert(secondary->isGPU);
41205a112b11Smrg    assert(secondary->is_output_secondary);
41215a112b11Smrg    secondary->current_primary->output_secondarys--;
41225a112b11Smrg    secondary->is_output_secondary = FALSE;
4123f7df2e56Smrg}
4124f7df2e56Smrg
4125f7df2e56Smrgvoid
4126f7df2e56SmrgAttachOffloadGPU(ScreenPtr pScreen, ScreenPtr new)
4127f7df2e56Smrg{
4128f7df2e56Smrg    assert(new->isGPU);
41295a112b11Smrg    assert(!new->is_offload_secondary);
41305a112b11Smrg    assert(new->current_primary == pScreen);
41315a112b11Smrg    new->is_offload_secondary = TRUE;
4132f7df2e56Smrg}
4133f7df2e56Smrg
4134f7df2e56Smrgvoid
41355a112b11SmrgDetachOffloadGPU(ScreenPtr secondary)
4136f7df2e56Smrg{
41375a112b11Smrg    assert(secondary->isGPU);
41385a112b11Smrg    assert(secondary->is_offload_secondary);
41395a112b11Smrg    secondary->is_offload_secondary = FALSE;
4140f7df2e56Smrg}
4141f7df2e56Smrg
4142