dispatch.c 119 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/************************************************************

Copyright 1987, 1989, 1998  The Open Group

Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.

Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.

                        All Rights Reserved

Peter Hutterer's avatar
Peter Hutterer committed
29 30
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
31
provided that the above copyright notice appear in all copies and that
Peter Hutterer's avatar
Peter Hutterer committed
32
both that copyright notice and this permission notice appear in
33 34
supporting documentation, and that the name of Digital not be
used in advertising or publicity pertaining to distribution of the
Peter Hutterer's avatar
Peter Hutterer committed
35
software without specific, written prior permission.
36 37 38 39 40 41 42 43 44 45 46

DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.

********************************************************/

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
47
/* The panoramix components contained the following notice */
Egbert Eich's avatar
Egbert Eich committed
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
/*****************************************************************

Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software.

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Except as contained in this notice, the name of Digital Equipment Corporation
shall not be used in advertising or otherwise to promote the sale, use or other
dealings in this Software without prior written authorization from Digital
Equipment Corporation.

******************************************************************/

76
/* XSERVER_DTRACE additions:
77
 * Copyright (c) 2005-2006, Oracle and/or its affiliates. All rights reserved.
78 79
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
97 98
 */

99 100
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
101
#include <version-config.h>
102 103
#endif

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
104 105 106 107 108
#ifdef PANORAMIX_DEBUG
#include <stdio.h>
int ProcInitialConnection();
#endif

109
#include "windowstr.h"
110
#include <X11/fonts/fontstruct.h>
111
#include <X11/fonts/libxfont2.h>
112 113 114 115 116 117 118 119 120 121 122
#include "dixfontstr.h"
#include "gcstruct.h"
#include "selection.h"
#include "colormapst.h"
#include "cursorstr.h"
#include "scrnintstr.h"
#include "opaque.h"
#include "input.h"
#include "servermd.h"
#include "extnsionst.h"
#include "dixfont.h"
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
123 124 125
#include "dispatch.h"
#include "swaprep.h"
#include "swapreq.h"
126
#include "privates.h"
127
#include "xace.h"
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
128
#include "inputstr.h"
Daniel Stone's avatar
Daniel Stone committed
129
#include "xkbsrv.h"
130
#include "site.h"
131
#include "client.h"
132

133
#ifdef XSERVER_DTRACE
134
#include "registry.h"
135
#include "probes.h"
136 137
#endif

Roman Gilg's avatar
Roman Gilg committed
138 139 140 141
#ifdef COMPOSITE
#include "compint.h"
#endif

142
#define mskcnt ((MAXCLIENTS + 31) / 32)
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
143
#define BITMASK(i) (1U << ((i) & 31))
144 145 146 147 148 149
#define MASKIDX(i) ((i) >> 5)
#define MASKWORD(buf, i) buf[MASKIDX(i)]
#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i)
#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))

150 151 152
xConnSetupPrefix connSetupPrefix;

PaddingInfo PixmapWidthPaddingInfo[33];
153 154

static ClientPtr grabClient;
155

156 157 158 159
#define GrabNone 0
#define GrabActive 1
static int grabState = GrabNone;
static long grabWaiters[mskcnt];
160 161
CallbackListPtr ServerGrabCallback = NULL;
HWEventQueuePtr checkForInput[2];
162
int connBlockScreenStart;
163

Roland Mainz's avatar
Roland Mainz committed
164
static void KillAllClients(void);
165

166
static int nextFreeClientID;    /* always MIN free client ID */
167

168
static int nClients;            /* number of authorized clients */
169

170
CallbackListPtr ClientStateCallback;
171 172 173 174 175 176

/* dispatchException & isItTimeToYield must be declared volatile since they
 * are modified by signal handlers - otherwise optimizer may assume it doesn't
 * need to actually check value in memory when used and may miss changes from
 * signal handlers.
 */
177 178
volatile char dispatchException = 0;
volatile char isItTimeToYield;
179 180 181 182

#define SAME_SCREENS(a, b) (\
    (a.pScreen == b.pScreen))

183
void
Roland Mainz's avatar
Roland Mainz committed
184
SetInputCheck(HWEventQueuePtr c0, HWEventQueuePtr c1)
185 186 187 188 189
{
    checkForInput[0] = c0;
    checkForInput[1] = c1;
}

190
void
191
UpdateCurrentTime(void)
192 193 194 195 196 197 198 199 200
{
    TimeStamp systime;

    /* To avoid time running backwards, we must call GetTimeInMillis before
     * calling ProcessInputEvents.
     */
    systime.months = currentTime.months;
    systime.milliseconds = GetTimeInMillis();
    if (systime.milliseconds < currentTime.milliseconds)
201
        systime.months++;
202
    if (InputCheckPending())
203
        ProcessInputEvents();
204
    if (CompareTimeStamps(systime, currentTime) == LATER)
205
        currentTime = systime;
206 207 208
}

/* Like UpdateCurrentTime, but can't call ProcessInputEvents */
209
void
210
UpdateCurrentTimeIf(void)
211 212 213 214 215 216
{
    TimeStamp systime;

    systime.months = currentTime.months;
    systime.milliseconds = GetTimeInMillis();
    if (systime.milliseconds < currentTime.milliseconds)
217
        systime.months++;
218
    if (CompareTimeStamps(systime, currentTime) == LATER)
219
        currentTime = systime;
220 221
}

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
222 223
#undef SMART_DEBUG

224 225 226
/* in milliseconds */
#define SMART_SCHEDULE_DEFAULT_INTERVAL	5
#define SMART_SCHEDULE_MAX_SLICE	15
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
227

228
#ifdef HAVE_SETITIMER
Emma Anholt's avatar
Emma Anholt committed
229
Bool SmartScheduleSignalEnable = TRUE;
230
#endif
231

232 233 234 235
long SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL;
long SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL;
long SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE;
long SmartScheduleTime;
236
int SmartScheduleLatencyLimited = 0;
237 238
static ClientPtr SmartLastClient;
static int SmartLastIndex[SMART_MAX_PRIORITY - SMART_MIN_PRIORITY + 1];
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
239 240

#ifdef SMART_DEBUG
241
long SmartLastPrint;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
242 243
#endif

244
void Dispatch(void);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
245

246 247
static struct xorg_list ready_clients;
static struct xorg_list saved_ready_clients;
248
struct xorg_list output_pending_clients;
249 250 251 252 253 254

static void
init_client_ready(void)
{
    xorg_list_init(&ready_clients);
    xorg_list_init(&saved_ready_clients);
255
    xorg_list_init(&output_pending_clients);
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
}

Bool
clients_are_ready(void)
{
    return !xorg_list_is_empty(&ready_clients);
}

/* Client has requests queued or data on the network */
void
mark_client_ready(ClientPtr client)
{
    if (xorg_list_is_empty(&client->ready))
        xorg_list_append(&client->ready, &ready_clients);
}

272 273 274 275 276 277 278 279 280 281
/*
 * Client has requests queued or data on the network, but awaits a
 * server grab release
 */
void mark_client_saved_ready(ClientPtr client)
{
    if (xorg_list_is_empty(&client->ready))
        xorg_list_append(&client->ready, &saved_ready_clients);
}

282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
/* Client has no requests queued and no data on network */
void
mark_client_not_ready(ClientPtr client)
{
    xorg_list_del(&client->ready);
}

static void
mark_client_grab(ClientPtr grab)
{
    ClientPtr   client, tmp;

    xorg_list_for_each_entry_safe(client, tmp, &ready_clients, ready) {
        if (client != grab) {
            xorg_list_del(&client->ready);
            xorg_list_append(&client->ready, &saved_ready_clients);
        }
    }
}

static void
mark_client_ungrab(void)
{
    ClientPtr   client, tmp;

    xorg_list_for_each_entry_safe(client, tmp, &saved_ready_clients, ready) {
        xorg_list_del(&client->ready);
        xorg_list_append(&client->ready, &ready_clients);
    }
}

static ClientPtr
SmartScheduleClient(void)
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
315
{
316
    ClientPtr pClient, best = NULL;
317 318 319
    int bestRobin, robin;
    long now = SmartScheduleTime;
    long idle;
320
    int nready = 0;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
321 322 323

    bestRobin = 0;
    idle = 2 * SmartScheduleSlice;
324 325 326 327

    xorg_list_for_each_entry(pClient, &ready_clients, ready) {
        nready++;

328 329
        /* Praise clients which haven't run in a while */
        if ((now - pClient->smart_stop_tick) >= idle) {
330 331 332 333 334 335 336 337 338
            if (pClient->smart_priority < 0)
                pClient->smart_priority++;
        }

        /* check priority to select best client */
        robin =
            (pClient->index -
             SmartLastIndex[pClient->smart_priority -
                            SMART_MIN_PRIORITY]) & 0xff;
339 340 341 342 343 344 345 346 347

        /* pick the best client */
        if (!best ||
            pClient->priority > best->priority ||
            (pClient->priority == best->priority &&
             (pClient->smart_priority > best->smart_priority ||
              (pClient->smart_priority == best->smart_priority && robin > bestRobin))))
        {
            best = pClient;
348 349
            bestRobin = robin;
        }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
350
#ifdef SMART_DEBUG
351
        if ((now - SmartLastPrint) >= 5000)
352
            fprintf(stderr, " %2d: %3d", pClient->index, pClient->smart_priority);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
353 354 355
#endif
    }
#ifdef SMART_DEBUG
356
    if ((now - SmartLastPrint) >= 5000) {
357
        fprintf(stderr, " use %2d\n", best->index);
358
        SmartLastPrint = now;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
359 360
    }
#endif
361
    SmartLastIndex[best->smart_priority - SMART_MIN_PRIORITY] = best->index;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
362 363 364
    /*
     * Set current client pointer
     */
365 366 367
    if (SmartLastClient != best) {
        best->smart_start_tick = now;
        SmartLastClient = best;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
368 369 370 371
    }
    /*
     * Adjust slice
     */
372 373 374 375 376 377
    if (nready == 1 && SmartScheduleLatencyLimited == 0) {
        /*
         * If it's been a long time since another client
         * has run, bump the slice up to get maximal
         * performance from a single client
         */
378
        if ((now - best->smart_start_tick) > 1000 &&
379 380 381
            SmartScheduleSlice < SmartScheduleMaxSlice) {
            SmartScheduleSlice += SmartScheduleInterval;
        }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
382
    }
383 384
    else {
        SmartScheduleSlice = SmartScheduleInterval;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
385
    }
386
    return best;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
387
}
388

389 390 391 392 393 394 395 396 397 398 399 400 401 402
void
EnableLimitedSchedulingLatency(void)
{
    ++SmartScheduleLatencyLimited;
    SmartScheduleSlice = SmartScheduleInterval;
}

void
DisableLimitedSchedulingLatency(void)
{
    --SmartScheduleLatencyLimited;

    /* protect against bugs */
    if (SmartScheduleLatencyLimited < 0)
403
        SmartScheduleLatencyLimited = 0;
404 405
}

406
void
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
407
Dispatch(void)
408
{
409 410 411
    int result;
    ClientPtr client;
    long start_tick;
412 413 414 415

    nextFreeClientID = 1;
    nClients = 0;

416
    SmartScheduleSlice = SmartScheduleInterval;
417 418
    init_client_ready();

419
    while (!dispatchException) {
420
        if (InputCheckPending()) {
421 422 423 424
            ProcessInputEvents();
            FlushIfCriticalOutputPending();
        }

425 426
        if (!WaitForSomething(clients_are_ready()))
            continue;
427

Peter Hutterer's avatar
Peter Hutterer committed
428 429 430
       /*****************
	*  Handle events in round robin fashion, doing input between
	*  each round
431 432
	*****************/

433 434 435
        if (!dispatchException && clients_are_ready()) {
            client = SmartScheduleClient();

436 437 438 439
            isItTimeToYield = FALSE;

            start_tick = SmartScheduleTime;
            while (!isItTimeToYield) {
440
                if (InputCheckPending())
441 442 443
                    ProcessInputEvents();

                FlushIfCriticalOutputPending();
444 445
                if ((SmartScheduleTime - start_tick) >= SmartScheduleSlice)
                {
446 447 448 449 450 451
                    /* Penalize clients which consume ticks */
                    if (client->smart_priority > SMART_MIN_PRIORITY)
                        client->smart_priority--;
                    break;
                }

452
                /* now, finally, deal with client requests */
453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468
                result = ReadRequestFromClient(client);
                if (result <= 0) {
                    if (result < 0)
                        CloseDownClient(client);
                    break;
                }

                client->sequence++;
                client->majorOp = ((xReq *) client->requestBuffer)->reqType;
                client->minorOp = 0;
                if (client->majorOp >= EXTENSION_BASE) {
                    ExtensionEntry *ext = GetExtensionEntry(client->majorOp);

                    if (ext)
                        client->minorOp = ext->MinorOpcode(client);
                }
469
#ifdef XSERVER_DTRACE
470 471 472
                if (XSERVER_REQUEST_START_ENABLED())
                    XSERVER_REQUEST_START(LookupMajorName(client->majorOp),
                                          client->majorOp,
Peter Hutterer's avatar
Peter Hutterer committed
473 474
                                          ((xReq *) client->requestBuffer)->length,
                                          client->index,
475
                                          client->requestBuffer);
476
#endif
477 478 479 480 481 482 483 484
                if (result > (maxBigRequestSize << 2))
                    result = BadLength;
                else {
                    result = XaceHookDispatch(client, client->majorOp);
                    if (result == Success)
                        result =
                            (*client->requestVector[client->majorOp]) (client);
                }
485 486 487
                if (!SmartScheduleSignalEnable)
                    SmartScheduleTime = GetTimeInMillis();

488
#ifdef XSERVER_DTRACE
489 490 491 492
                if (XSERVER_REQUEST_DONE_ENABLED())
                    XSERVER_REQUEST_DONE(LookupMajorName(client->majorOp),
                                         client->majorOp, client->sequence,
                                         client->index, result);
493 494
#endif

495 496 497 498 499 500 501 502 503 504 505 506
                if (client->noClientException != Success) {
                    CloseDownClient(client);
                    break;
                }
                else if (result != Success) {
                    SendErrorToClient(client, client->majorOp,
                                      client->minorOp,
                                      client->errorValue, result);
                    break;
                }
            }
            FlushAllOutput();
507
            if (client == SmartLastClient)
508 509 510
                client->smart_stop_tick = SmartScheduleTime;
        }
        dispatchException &= ~DE_PRIORITYCHANGE;
511
    }
512
#if defined(DDXBEFORERESET)
513
    ddxBeforeReset();
514
#endif
515 516
    KillAllClients();
    dispatchException &= ~DE_RESET;
517
    SmartScheduleLatencyLimited = 0;
518
    ResetOsBuffers();
519 520
}

521
static int VendorRelease = VENDOR_RELEASE;
Keith Packard's avatar
Keith Packard committed
522
static const char *VendorString = VENDOR_NAME;
523 524 525 526 527 528 529 530

void
SetVendorRelease(int release)
{
    VendorRelease = release;
}

void
Peter Hutterer's avatar
Peter Hutterer committed
531
SetVendorString(const char *vendor)
532
{
Peter Hutterer's avatar
Peter Hutterer committed
533
    VendorString = vendor;
534 535 536 537 538 539 540
}

Bool
CreateConnectionBlock(void)
{
    xConnSetup setup;
    xWindowRoot root;
541
    xDepth depth;
542 543 544
    xVisualType visual;
    xPixmapFormat format;
    unsigned long vid;
545
    int i, j, k, lenofblock, sizesofar = 0;
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569
    char *pBuf;

    memset(&setup, 0, sizeof(xConnSetup));
    /* Leave off the ridBase and ridMask, these must be sent with
       connection */

    setup.release = VendorRelease;
    /*
     * per-server image and bitmap parameters are defined in Xmd.h
     */
    setup.imageByteOrder = screenInfo.imageByteOrder;

    setup.bitmapScanlineUnit = screenInfo.bitmapScanlineUnit;
    setup.bitmapScanlinePad = screenInfo.bitmapScanlinePad;

    setup.bitmapBitOrder = screenInfo.bitmapBitOrder;
    setup.motionBufferSize = NumMotionEvents();
    setup.numRoots = screenInfo.numScreens;
    setup.nbytesVendor = strlen(VendorString);
    setup.numFormats = screenInfo.numPixmapFormats;
    setup.maxRequestSize = MAX_REQUEST_SIZE;
    QueryMinMaxKeyCodes(&setup.minKeyCode, &setup.maxKeyCode);

    lenofblock = sizeof(xConnSetup) +
570 571 572
        pad_to_int32(setup.nbytesVendor) +
        (setup.numFormats * sizeof(xPixmapFormat)) +
        (setup.numRoots * sizeof(xWindowRoot));
573
    ConnectionInfo = malloc(lenofblock);
574
    if (!ConnectionInfo)
575
        return FALSE;
576

577
    memmove(ConnectionInfo, (char *) &setup, sizeof(xConnSetup));
578 579 580
    sizesofar = sizeof(xConnSetup);
    pBuf = ConnectionInfo + sizeof(xConnSetup);

581
    memmove(pBuf, VendorString, (int) setup.nbytesVendor);
582 583
    sizesofar += setup.nbytesVendor;
    pBuf += setup.nbytesVendor;
584
    i = padding_for_int32(setup.nbytesVendor);
585 586
    sizesofar += i;
    while (--i >= 0)
587
        *pBuf++ = 0;
588 589

    memset(&format, 0, sizeof(xPixmapFormat));
590 591 592 593 594 595 596
    for (i = 0; i < screenInfo.numPixmapFormats; i++) {
        format.depth = screenInfo.formats[i].depth;
        format.bitsPerPixel = screenInfo.formats[i].bitsPerPixel;
        format.scanLinePad = screenInfo.formats[i].scanlinePad;
        memmove(pBuf, (char *) &format, sizeof(xPixmapFormat));
        pBuf += sizeof(xPixmapFormat);
        sizesofar += sizeof(xPixmapFormat);
597 598 599 600 601
    }

    connBlockScreenStart = sizesofar;
    memset(&depth, 0, sizeof(xDepth));
    memset(&visual, 0, sizeof(xVisualType));
602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659
    for (i = 0; i < screenInfo.numScreens; i++) {
        ScreenPtr pScreen;
        DepthPtr pDepth;
        VisualPtr pVisual;

        pScreen = screenInfo.screens[i];
        root.windowId = pScreen->root->drawable.id;
        root.defaultColormap = pScreen->defColormap;
        root.whitePixel = pScreen->whitePixel;
        root.blackPixel = pScreen->blackPixel;
        root.currentInputMask = 0;      /* filled in when sent */
        root.pixWidth = pScreen->width;
        root.pixHeight = pScreen->height;
        root.mmWidth = pScreen->mmWidth;
        root.mmHeight = pScreen->mmHeight;
        root.minInstalledMaps = pScreen->minInstalledCmaps;
        root.maxInstalledMaps = pScreen->maxInstalledCmaps;
        root.rootVisualID = pScreen->rootVisual;
        root.backingStore = pScreen->backingStoreSupport;
        root.saveUnders = FALSE;
        root.rootDepth = pScreen->rootDepth;
        root.nDepths = pScreen->numDepths;
        memmove(pBuf, (char *) &root, sizeof(xWindowRoot));
        sizesofar += sizeof(xWindowRoot);
        pBuf += sizeof(xWindowRoot);

        pDepth = pScreen->allowedDepths;
        for (j = 0; j < pScreen->numDepths; j++, pDepth++) {
            lenofblock += sizeof(xDepth) +
                (pDepth->numVids * sizeof(xVisualType));
            pBuf = (char *) realloc(ConnectionInfo, lenofblock);
            if (!pBuf) {
                free(ConnectionInfo);
                return FALSE;
            }
            ConnectionInfo = pBuf;
            pBuf += sizesofar;
            depth.depth = pDepth->depth;
            depth.nVisuals = pDepth->numVids;
            memmove(pBuf, (char *) &depth, sizeof(xDepth));
            pBuf += sizeof(xDepth);
            sizesofar += sizeof(xDepth);
            for (k = 0; k < pDepth->numVids; k++) {
                vid = pDepth->vids[k];
                for (pVisual = pScreen->visuals;
                     pVisual->vid != vid; pVisual++);
                visual.visualID = vid;
                visual.class = pVisual->class;
                visual.bitsPerRGB = pVisual->bitsPerRGBValue;
                visual.colormapEntries = pVisual->ColormapEntries;
                visual.redMask = pVisual->redMask;
                visual.greenMask = pVisual->greenMask;
                visual.blueMask = pVisual->blueMask;
                memmove(pBuf, (char *) &visual, sizeof(xVisualType));
                pBuf += sizeof(xVisualType);
                sizesofar += sizeof(xVisualType);
            }
        }
660 661
    }
    connSetupPrefix.success = xTrue;
662
    connSetupPrefix.length = lenofblock / 4;
663 664 665 666 667
    connSetupPrefix.majorVersion = X_PROTOCOL;
    connSetupPrefix.minorVersion = X_PROTOCOL_REVISION;
    return TRUE;
}

668
int
Roland Mainz's avatar
Roland Mainz committed
669
ProcBadRequest(ClientPtr client)
670
{
671
    return BadRequest;
672 673 674
}

int
Roland Mainz's avatar
Roland Mainz committed
675
ProcCreateWindow(ClientPtr client)
676
{
677
    WindowPtr pParent, pWin;
678

679
    REQUEST(xCreateWindowReq);
680
    int len, rc;
681 682

    REQUEST_AT_LEAST_SIZE(xCreateWindowReq);
683

684
    LEGAL_NEW_RESOURCE(stuff->wid, client);
685
    rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess);
686 687
    if (rc != Success)
        return rc;
688
    len = client->req_len - bytes_to_int32(sizeof(xCreateWindowReq));
689 690
    if (Ones(stuff->mask) != len)
        return BadLength;
691 692
    if (!stuff->width || !stuff->height) {
        client->errorValue = 0;
693 694 695
        return BadValue;
    }
    pWin = CreateWindow(stuff->wid, pParent, stuff->x,
696 697 698 699 700 701 702 703
                        stuff->y, stuff->width, stuff->height,
                        stuff->borderWidth, stuff->class,
                        stuff->mask, (XID *) &stuff[1],
                        (int) stuff->depth, client, stuff->visual, &rc);
    if (pWin) {
        Mask mask = pWin->eventMask;

        pWin->eventMask = 0;    /* subterfuge in case AddResource fails */
704
        if (!AddResource(stuff->wid, RT_WINDOW, (void *) pWin))
705 706
            return BadAlloc;
        pWin->eventMask = mask;
707
    }
708
    return rc;
709 710 711
}

int
712
ProcChangeWindowAttributes(ClientPtr client)
713
{
714
    WindowPtr pWin;
715

716
    REQUEST(xChangeWindowAttributesReq);
717
    int len, rc;
718
    Mask access_mode = 0;
719 720

    REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq);
721 722
    access_mode |= (stuff->valueMask & CWEventMask) ? DixReceiveAccess : 0;
    access_mode |= (stuff->valueMask & ~CWEventMask) ? DixSetAttrAccess : 0;
723
    rc = dixLookupWindow(&pWin, stuff->window, client, access_mode);
724 725
    if (rc != Success)
        return rc;
726
    len = client->req_len - bytes_to_int32(sizeof(xChangeWindowAttributesReq));
727 728
    if (len != Ones(stuff->valueMask))
        return BadLength;
729
    return ChangeWindowAttributes(pWin,
730
                                  stuff->valueMask, (XID *) &stuff[1], client);
731 732 733
}

int
734
ProcGetWindowAttributes(ClientPtr client)
735
{
736
    WindowPtr pWin;
737

738 739
    REQUEST(xResourceReq);
    xGetWindowAttributesReply wa;
740
    int rc;
741 742

    REQUEST_SIZE_MATCH(xResourceReq);
743
    rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
744
    if (rc != Success)
745
        return rc;
746
    memset(&wa, 0, sizeof(xGetWindowAttributesReply));
747 748
    GetWindowAttributes(pWin, client, &wa);
    WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa);
749
    return Success;
750 751 752
}

int
753
ProcDestroyWindow(ClientPtr client)
754
{
755
    WindowPtr pWin;
756

757
    REQUEST(xResourceReq);
758
    int rc;
759 760

    REQUEST_SIZE_MATCH(xResourceReq);
761 762
    rc = dixLookupWindow(&pWin, stuff->id, client, DixDestroyAccess);
    if (rc != Success)
763
        return rc;
764
    if (pWin->parent) {
765 766 767 768 769
        rc = dixLookupWindow(&pWin, pWin->parent->drawable.id, client,
                             DixRemoveAccess);
        if (rc != Success)
            return rc;
        FreeResource(stuff->id, RT_NONE);
770
    }
771
    return Success;
772 773 774
}

int
775
ProcDestroySubwindows(ClientPtr client)
776
{
777
    WindowPtr pWin;
778

779
    REQUEST(xResourceReq);
780
    int rc;
781 782

    REQUEST_SIZE_MATCH(xResourceReq);
783
    rc = dixLookupWindow(&pWin, stuff->id, client, DixRemoveAccess);
784
    if (rc != Success)
785
        return rc;
786
    DestroySubwindows(pWin, client);
787
    return Success;
788 789 790
}

int
791
ProcChangeSaveSet(ClientPtr client)
792
{
793
    WindowPtr pWin;
794

795
    REQUEST(xChangeSaveSetReq);
796
    int rc;
797

798
    REQUEST_SIZE_MATCH(xChangeSaveSetReq);
799
    rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
800 801
    if (rc != Success)
        return rc;
802 803 804
    if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id)))
        return BadMatch;
    if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete))
805 806 807
        return AlterSaveSetForClient(client, pWin, stuff->mode, FALSE, TRUE);
    client->errorValue = stuff->mode;
    return BadValue;
808 809 810
}

int
811
ProcReparentWindow(ClientPtr client)
812
{
813
    WindowPtr pWin, pParent;
814

815
    REQUEST(xReparentWindowReq);
816
    int rc;
817 818

    REQUEST_SIZE_MATCH(xReparentWindowReq);
819
    rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
820 821
    if (rc != Success)
        return rc;
822
    rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess);
823 824
    if (rc != Success)
        return rc;
825
    if (!SAME_SCREENS(pWin->drawable, pParent->drawable))
826
        return BadMatch;
827
    if ((pWin->backgroundState == ParentRelative) &&
828 829
        (pParent->drawable.depth != pWin->drawable.depth))
        return BadMatch;
830
    if ((pWin->drawable.class != InputOnly) &&
831 832
        (pParent->drawable.class == InputOnly))
        return BadMatch;
833
    return ReparentWindow(pWin, pParent,
834
                          (short) stuff->x, (short) stuff->y, client);
835 836 837
}

int
838
ProcMapWindow(ClientPtr client)
839
{
840
    WindowPtr pWin;
841

842
    REQUEST(xResourceReq);
843
    int rc;
844 845

    REQUEST_SIZE_MATCH(xResourceReq);
846
    rc = dixLookupWindow(&pWin, stuff->id, client, DixShowAccess);
847 848
    if (rc != Success)
        return rc;
849
    MapWindow(pWin, client);
850
    /* update cache to say it is mapped */
851
    return Success;
852 853 854
}

int
855
ProcMapSubwindows(ClientPtr client)
856
{
857
    WindowPtr pWin;
858

859
    REQUEST(xResourceReq);
860
    int rc;
861 862

    REQUEST_SIZE_MATCH(xResourceReq);
863
    rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
864 865
    if (rc != Success)
        return rc;
866
    MapSubwindows(pWin, client);
867
    /* update cache to say it is mapped */
868
    return Success;
869 870 871
}

int
872
ProcUnmapWindow(ClientPtr client)
873
{
874
    WindowPtr pWin;
875

876
    REQUEST(xResourceReq);
877
    int rc;
878 879

    REQUEST_SIZE_MATCH(xResourceReq);
880
    rc = dixLookupWindow(&pWin, stuff->id, client, DixHideAccess);
881 882
    if (rc != Success)
        return rc;
883
    UnmapWindow(pWin, FALSE);
884
    /* update cache to say it is mapped */
885
    return Success;
886 887 888
}

int
889
ProcUnmapSubwindows(ClientPtr client)
890
{
891
    WindowPtr pWin;
892

893
    REQUEST(xResourceReq);
894
    int rc;
895 896

    REQUEST_SIZE_MATCH(xResourceReq);
897
    rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
898 899
    if (rc != Success)
        return rc;
900
    UnmapSubwindows(pWin);
901
    return Success;
902 903 904
}

int
905
ProcConfigureWindow(ClientPtr client)
906
{
907
    WindowPtr pWin;
908

909
    REQUEST(xConfigureWindowReq);
910
    int len, rc;
911 912

    REQUEST_AT_LEAST_SIZE(xConfigureWindowReq);
913
    rc = dixLookupWindow(&pWin, stuff->window, client,
914
                         DixManageAccess | DixSetAttrAccess);
915 916
    if (rc != Success)
        return rc;
917
    len = client->req_len - bytes_to_int32(sizeof(xConfigureWindowReq));
918
    if (Ones((Mask) stuff->mask) != len)
919
        return BadLength;
920
    return ConfigureWindow(pWin, (Mask) stuff->mask, (