dispatch.c revision 4e185dc0
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" 1306747b715Smrg#include "site.h" 131f7df2e56Smrg#include "client.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; 151f7df2e56Smrg 15205b261ecSmrg#define GrabNone 0 15305b261ecSmrg#define GrabActive 1 15405b261ecSmrgstatic int grabState = GrabNone; 15505b261ecSmrgstatic long grabWaiters[mskcnt]; 1566747b715SmrgCallbackListPtr ServerGrabCallback = NULL; 15705b261ecSmrgHWEventQueuePtr checkForInput[2]; 1586747b715Smrgint connBlockScreenStart; 15905b261ecSmrg 16005b261ecSmrgstatic void KillAllClients(void); 16105b261ecSmrg 162f7df2e56Smrgstatic int nextFreeClientID; /* always MIN free client ID */ 16305b261ecSmrg 164f7df2e56Smrgstatic int nClients; /* number of authorized clients */ 16505b261ecSmrg 1666747b715SmrgCallbackListPtr ClientStateCallback; 16705b261ecSmrg 16805b261ecSmrg/* dispatchException & isItTimeToYield must be declared volatile since they 16905b261ecSmrg * are modified by signal handlers - otherwise optimizer may assume it doesn't 17005b261ecSmrg * need to actually check value in memory when used and may miss changes from 17105b261ecSmrg * signal handlers. 17205b261ecSmrg */ 1736747b715Smrgvolatile char dispatchException = 0; 1746747b715Smrgvolatile char isItTimeToYield; 17505b261ecSmrg 17605b261ecSmrg#define SAME_SCREENS(a, b) (\ 17705b261ecSmrg (a.pScreen == b.pScreen)) 17805b261ecSmrg 1794642e01fSmrgvoid 18005b261ecSmrgSetInputCheck(HWEventQueuePtr c0, HWEventQueuePtr c1) 18105b261ecSmrg{ 18205b261ecSmrg checkForInput[0] = c0; 18305b261ecSmrg checkForInput[1] = c1; 18405b261ecSmrg} 18505b261ecSmrg 1866747b715Smrgvoid 18705b261ecSmrgUpdateCurrentTime(void) 18805b261ecSmrg{ 18905b261ecSmrg TimeStamp systime; 19005b261ecSmrg 19105b261ecSmrg /* To avoid time running backwards, we must call GetTimeInMillis before 19205b261ecSmrg * calling ProcessInputEvents. 19305b261ecSmrg */ 19405b261ecSmrg systime.months = currentTime.months; 19505b261ecSmrg systime.milliseconds = GetTimeInMillis(); 19605b261ecSmrg if (systime.milliseconds < currentTime.milliseconds) 197f7df2e56Smrg systime.months++; 1987e31ba66Smrg if (InputCheckPending()) 199f7df2e56Smrg ProcessInputEvents(); 20005b261ecSmrg if (CompareTimeStamps(systime, currentTime) == LATER) 201f7df2e56Smrg currentTime = systime; 20205b261ecSmrg} 20305b261ecSmrg 20405b261ecSmrg/* Like UpdateCurrentTime, but can't call ProcessInputEvents */ 2056747b715Smrgvoid 20605b261ecSmrgUpdateCurrentTimeIf(void) 20705b261ecSmrg{ 20805b261ecSmrg TimeStamp systime; 20905b261ecSmrg 21005b261ecSmrg systime.months = currentTime.months; 21105b261ecSmrg systime.milliseconds = GetTimeInMillis(); 21205b261ecSmrg if (systime.milliseconds < currentTime.milliseconds) 213f7df2e56Smrg systime.months++; 214f7df2e56Smrg if (CompareTimeStamps(systime, currentTime) == LATER) 215f7df2e56Smrg currentTime = systime; 21605b261ecSmrg} 21705b261ecSmrg 21805b261ecSmrg#undef SMART_DEBUG 21905b261ecSmrg 220f7df2e56Smrg/* in milliseconds */ 221f7df2e56Smrg#define SMART_SCHEDULE_DEFAULT_INTERVAL 5 222f7df2e56Smrg#define SMART_SCHEDULE_MAX_SLICE 15 22305b261ecSmrg 2247e31ba66Smrg#ifdef HAVE_SETITIMER 2257e31ba66SmrgBool SmartScheduleSignalEnable = TRUE; 226f7df2e56Smrg#endif 2277e31ba66Smrg 2286747b715Smrglong SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL; 2296747b715Smrglong SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL; 2306747b715Smrglong SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE; 2316747b715Smrglong SmartScheduleTime; 2326747b715Smrgint SmartScheduleLatencyLimited = 0; 233f7df2e56Smrgstatic ClientPtr SmartLastClient; 234f7df2e56Smrgstatic int SmartLastIndex[SMART_MAX_PRIORITY - SMART_MIN_PRIORITY + 1]; 23505b261ecSmrg 23605b261ecSmrg#ifdef SMART_DEBUG 237f7df2e56Smrglong SmartLastPrint; 23805b261ecSmrg#endif 23905b261ecSmrg 240f7df2e56Smrgvoid Dispatch(void); 24105b261ecSmrg 2427e31ba66Smrgstatic struct xorg_list ready_clients; 2437e31ba66Smrgstatic struct xorg_list saved_ready_clients; 2447e31ba66Smrgstruct xorg_list output_pending_clients; 2457e31ba66Smrg 2467e31ba66Smrgstatic void 2477e31ba66Smrginit_client_ready(void) 24805b261ecSmrg{ 2497e31ba66Smrg xorg_list_init(&ready_clients); 2507e31ba66Smrg xorg_list_init(&saved_ready_clients); 2517e31ba66Smrg xorg_list_init(&output_pending_clients); 2527e31ba66Smrg} 2537e31ba66Smrg 2547e31ba66SmrgBool 2557e31ba66Smrgclients_are_ready(void) 2567e31ba66Smrg{ 2577e31ba66Smrg return !xorg_list_is_empty(&ready_clients); 2587e31ba66Smrg} 2597e31ba66Smrg 2607e31ba66Smrg/* Client has requests queued or data on the network */ 2617e31ba66Smrgvoid 2627e31ba66Smrgmark_client_ready(ClientPtr client) 2637e31ba66Smrg{ 2647e31ba66Smrg if (xorg_list_is_empty(&client->ready)) 2657e31ba66Smrg xorg_list_append(&client->ready, &ready_clients); 2667e31ba66Smrg} 2677e31ba66Smrg 2687e31ba66Smrg/* 2697e31ba66Smrg * Client has requests queued or data on the network, but awaits a 2707e31ba66Smrg * server grab release 2717e31ba66Smrg */ 2727e31ba66Smrgvoid mark_client_saved_ready(ClientPtr client) 2737e31ba66Smrg{ 2747e31ba66Smrg if (xorg_list_is_empty(&client->ready)) 2757e31ba66Smrg xorg_list_append(&client->ready, &saved_ready_clients); 2767e31ba66Smrg} 2777e31ba66Smrg 2787e31ba66Smrg/* Client has no requests queued and no data on network */ 2797e31ba66Smrgvoid 2807e31ba66Smrgmark_client_not_ready(ClientPtr client) 2817e31ba66Smrg{ 2827e31ba66Smrg xorg_list_del(&client->ready); 2837e31ba66Smrg} 2847e31ba66Smrg 2857e31ba66Smrgstatic void 2867e31ba66Smrgmark_client_grab(ClientPtr grab) 2877e31ba66Smrg{ 2887e31ba66Smrg ClientPtr client, tmp; 2897e31ba66Smrg 2907e31ba66Smrg xorg_list_for_each_entry_safe(client, tmp, &ready_clients, ready) { 2917e31ba66Smrg if (client != grab) { 2927e31ba66Smrg xorg_list_del(&client->ready); 2937e31ba66Smrg xorg_list_append(&client->ready, &saved_ready_clients); 2947e31ba66Smrg } 2957e31ba66Smrg } 2967e31ba66Smrg} 2977e31ba66Smrg 2987e31ba66Smrgstatic void 2997e31ba66Smrgmark_client_ungrab(void) 3007e31ba66Smrg{ 3017e31ba66Smrg ClientPtr client, tmp; 3027e31ba66Smrg 3037e31ba66Smrg xorg_list_for_each_entry_safe(client, tmp, &saved_ready_clients, ready) { 3047e31ba66Smrg xorg_list_del(&client->ready); 3057e31ba66Smrg xorg_list_append(&client->ready, &ready_clients); 3067e31ba66Smrg } 3077e31ba66Smrg} 3087e31ba66Smrg 3097e31ba66Smrgstatic ClientPtr 3107e31ba66SmrgSmartScheduleClient(void) 3117e31ba66Smrg{ 3127e31ba66Smrg ClientPtr pClient, best = NULL; 313f7df2e56Smrg int bestRobin, robin; 314f7df2e56Smrg long now = SmartScheduleTime; 315f7df2e56Smrg long idle; 3167e31ba66Smrg int nready = 0; 31705b261ecSmrg 31805b261ecSmrg bestRobin = 0; 31905b261ecSmrg idle = 2 * SmartScheduleSlice; 3207e31ba66Smrg 3217e31ba66Smrg xorg_list_for_each_entry(pClient, &ready_clients, ready) { 3227e31ba66Smrg nready++; 3237e31ba66Smrg 324f7df2e56Smrg /* Praise clients which haven't run in a while */ 325f7df2e56Smrg if ((now - pClient->smart_stop_tick) >= idle) { 326f7df2e56Smrg if (pClient->smart_priority < 0) 327f7df2e56Smrg pClient->smart_priority++; 328f7df2e56Smrg } 329f7df2e56Smrg 330f7df2e56Smrg /* check priority to select best client */ 331f7df2e56Smrg robin = 332f7df2e56Smrg (pClient->index - 333f7df2e56Smrg SmartLastIndex[pClient->smart_priority - 334f7df2e56Smrg SMART_MIN_PRIORITY]) & 0xff; 3357e31ba66Smrg 3367e31ba66Smrg /* pick the best client */ 3377e31ba66Smrg if (!best || 3387e31ba66Smrg pClient->priority > best->priority || 3397e31ba66Smrg (pClient->priority == best->priority && 3407e31ba66Smrg (pClient->smart_priority > best->smart_priority || 3417e31ba66Smrg (pClient->smart_priority == best->smart_priority && robin > bestRobin)))) 3427e31ba66Smrg { 3437e31ba66Smrg best = pClient; 344f7df2e56Smrg bestRobin = robin; 345f7df2e56Smrg } 34605b261ecSmrg#ifdef SMART_DEBUG 347f7df2e56Smrg if ((now - SmartLastPrint) >= 5000) 3487e31ba66Smrg fprintf(stderr, " %2d: %3d", pClient->index, pClient->smart_priority); 34905b261ecSmrg#endif 35005b261ecSmrg } 35105b261ecSmrg#ifdef SMART_DEBUG 352f7df2e56Smrg if ((now - SmartLastPrint) >= 5000) { 3537e31ba66Smrg fprintf(stderr, " use %2d\n", best->index); 354f7df2e56Smrg SmartLastPrint = now; 35505b261ecSmrg } 35605b261ecSmrg#endif 3577e31ba66Smrg SmartLastIndex[best->smart_priority - SMART_MIN_PRIORITY] = best->index; 35805b261ecSmrg /* 35905b261ecSmrg * Set current client pointer 36005b261ecSmrg */ 3617e31ba66Smrg if (SmartLastClient != best) { 3627e31ba66Smrg best->smart_start_tick = now; 3637e31ba66Smrg SmartLastClient = best; 36405b261ecSmrg } 36505b261ecSmrg /* 36605b261ecSmrg * Adjust slice 36705b261ecSmrg */ 368f7df2e56Smrg if (nready == 1 && SmartScheduleLatencyLimited == 0) { 369f7df2e56Smrg /* 370f7df2e56Smrg * If it's been a long time since another client 371f7df2e56Smrg * has run, bump the slice up to get maximal 372f7df2e56Smrg * performance from a single client 373f7df2e56Smrg */ 3747e31ba66Smrg if ((now - best->smart_start_tick) > 1000 && 375f7df2e56Smrg SmartScheduleSlice < SmartScheduleMaxSlice) { 376f7df2e56Smrg SmartScheduleSlice += SmartScheduleInterval; 377f7df2e56Smrg } 37805b261ecSmrg } 379f7df2e56Smrg else { 380f7df2e56Smrg SmartScheduleSlice = SmartScheduleInterval; 38105b261ecSmrg } 38205b261ecSmrg return best; 38305b261ecSmrg} 38405b261ecSmrg 385b1d344b3Smrgvoid 386b1d344b3SmrgEnableLimitedSchedulingLatency(void) 387b1d344b3Smrg{ 388b1d344b3Smrg ++SmartScheduleLatencyLimited; 389b1d344b3Smrg SmartScheduleSlice = SmartScheduleInterval; 390b1d344b3Smrg} 391b1d344b3Smrg 392b1d344b3Smrgvoid 393b1d344b3SmrgDisableLimitedSchedulingLatency(void) 394b1d344b3Smrg{ 395b1d344b3Smrg --SmartScheduleLatencyLimited; 396b1d344b3Smrg 397b1d344b3Smrg /* protect against bugs */ 398b1d344b3Smrg if (SmartScheduleLatencyLimited < 0) 399f7df2e56Smrg SmartScheduleLatencyLimited = 0; 400b1d344b3Smrg} 401b1d344b3Smrg 40205b261ecSmrgvoid 40305b261ecSmrgDispatch(void) 40405b261ecSmrg{ 405f7df2e56Smrg int result; 406f7df2e56Smrg ClientPtr client; 407f7df2e56Smrg long start_tick; 40805b261ecSmrg 40905b261ecSmrg nextFreeClientID = 1; 41005b261ecSmrg nClients = 0; 41105b261ecSmrg 412b1d344b3Smrg SmartScheduleSlice = SmartScheduleInterval; 4137e31ba66Smrg init_client_ready(); 4147e31ba66Smrg 415f7df2e56Smrg while (!dispatchException) { 4167e31ba66Smrg if (InputCheckPending()) { 417f7df2e56Smrg ProcessInputEvents(); 418f7df2e56Smrg FlushIfCriticalOutputPending(); 419f7df2e56Smrg } 420f7df2e56Smrg 4217e31ba66Smrg if (!WaitForSomething(clients_are_ready())) 4227e31ba66Smrg continue; 423f7df2e56Smrg 424f7df2e56Smrg /***************** 425f7df2e56Smrg * Handle events in round robin fashion, doing input between 426f7df2e56Smrg * each round 42705b261ecSmrg *****************/ 42805b261ecSmrg 4297e31ba66Smrg if (!dispatchException && clients_are_ready()) { 4307e31ba66Smrg client = SmartScheduleClient(); 4317e31ba66Smrg 432f7df2e56Smrg isItTimeToYield = FALSE; 433f7df2e56Smrg 434f7df2e56Smrg start_tick = SmartScheduleTime; 435f7df2e56Smrg while (!isItTimeToYield) { 4367e31ba66Smrg if (InputCheckPending()) 437f7df2e56Smrg ProcessInputEvents(); 438f7df2e56Smrg 439f7df2e56Smrg FlushIfCriticalOutputPending(); 4407e31ba66Smrg if ((SmartScheduleTime - start_tick) >= SmartScheduleSlice) 4417e31ba66Smrg { 442f7df2e56Smrg /* Penalize clients which consume ticks */ 443f7df2e56Smrg if (client->smart_priority > SMART_MIN_PRIORITY) 444f7df2e56Smrg client->smart_priority--; 445f7df2e56Smrg break; 446f7df2e56Smrg } 447f7df2e56Smrg 4487e31ba66Smrg /* now, finally, deal with client requests */ 449f7df2e56Smrg result = ReadRequestFromClient(client); 450f7df2e56Smrg if (result <= 0) { 451f7df2e56Smrg if (result < 0) 452f7df2e56Smrg CloseDownClient(client); 453f7df2e56Smrg break; 454f7df2e56Smrg } 455f7df2e56Smrg 456f7df2e56Smrg client->sequence++; 457f7df2e56Smrg client->majorOp = ((xReq *) client->requestBuffer)->reqType; 458f7df2e56Smrg client->minorOp = 0; 459f7df2e56Smrg if (client->majorOp >= EXTENSION_BASE) { 460f7df2e56Smrg ExtensionEntry *ext = GetExtensionEntry(client->majorOp); 461f7df2e56Smrg 462f7df2e56Smrg if (ext) 463f7df2e56Smrg client->minorOp = ext->MinorOpcode(client); 464f7df2e56Smrg } 46505b261ecSmrg#ifdef XSERVER_DTRACE 466f7df2e56Smrg if (XSERVER_REQUEST_START_ENABLED()) 467f7df2e56Smrg XSERVER_REQUEST_START(LookupMajorName(client->majorOp), 468f7df2e56Smrg client->majorOp, 469f7df2e56Smrg ((xReq *) client->requestBuffer)->length, 470f7df2e56Smrg client->index, 471f7df2e56Smrg client->requestBuffer); 47205b261ecSmrg#endif 473f7df2e56Smrg if (result > (maxBigRequestSize << 2)) 474f7df2e56Smrg result = BadLength; 475f7df2e56Smrg else { 476f7df2e56Smrg result = XaceHookDispatch(client, client->majorOp); 477f7df2e56Smrg if (result == Success) 478f7df2e56Smrg result = 479f7df2e56Smrg (*client->requestVector[client->majorOp]) (client); 480f7df2e56Smrg } 4817e31ba66Smrg if (!SmartScheduleSignalEnable) 4827e31ba66Smrg SmartScheduleTime = GetTimeInMillis(); 4837e31ba66Smrg 48405b261ecSmrg#ifdef XSERVER_DTRACE 485f7df2e56Smrg if (XSERVER_REQUEST_DONE_ENABLED()) 486f7df2e56Smrg XSERVER_REQUEST_DONE(LookupMajorName(client->majorOp), 487f7df2e56Smrg client->majorOp, client->sequence, 488f7df2e56Smrg client->index, result); 48905b261ecSmrg#endif 49005b261ecSmrg 491f7df2e56Smrg if (client->noClientException != Success) { 492f7df2e56Smrg CloseDownClient(client); 493f7df2e56Smrg break; 494f7df2e56Smrg } 495f7df2e56Smrg else if (result != Success) { 496f7df2e56Smrg SendErrorToClient(client, client->majorOp, 497f7df2e56Smrg client->minorOp, 498f7df2e56Smrg client->errorValue, result); 499f7df2e56Smrg break; 500f7df2e56Smrg } 501f7df2e56Smrg } 502f7df2e56Smrg FlushAllOutput(); 5037e31ba66Smrg if (client == SmartLastClient) 504f7df2e56Smrg client->smart_stop_tick = SmartScheduleTime; 505f7df2e56Smrg } 506f7df2e56Smrg dispatchException &= ~DE_PRIORITYCHANGE; 50705b261ecSmrg } 50805b261ecSmrg#if defined(DDXBEFORERESET) 509f7df2e56Smrg ddxBeforeReset(); 51005b261ecSmrg#endif 51105b261ecSmrg KillAllClients(); 51205b261ecSmrg dispatchException &= ~DE_RESET; 513b1d344b3Smrg SmartScheduleLatencyLimited = 0; 514f7df2e56Smrg ResetOsBuffers(); 51505b261ecSmrg} 51605b261ecSmrg 517f7df2e56Smrgstatic int VendorRelease = VENDOR_RELEASE; 518f7df2e56Smrgstatic const char *VendorString = VENDOR_NAME; 5196747b715Smrg 5206747b715Smrgvoid 5216747b715SmrgSetVendorRelease(int release) 5226747b715Smrg{ 5236747b715Smrg VendorRelease = release; 5246747b715Smrg} 5256747b715Smrg 5266747b715Smrgvoid 527f7df2e56SmrgSetVendorString(const char *vendor) 5286747b715Smrg{ 529f7df2e56Smrg VendorString = vendor; 5306747b715Smrg} 5316747b715Smrg 5326747b715SmrgBool 5336747b715SmrgCreateConnectionBlock(void) 5346747b715Smrg{ 5356747b715Smrg xConnSetup setup; 5366747b715Smrg xWindowRoot root; 537f7df2e56Smrg xDepth depth; 5386747b715Smrg xVisualType visual; 5396747b715Smrg xPixmapFormat format; 5406747b715Smrg unsigned long vid; 541f7df2e56Smrg int i, j, k, lenofblock, sizesofar = 0; 5426747b715Smrg char *pBuf; 5436747b715Smrg 5446747b715Smrg memset(&setup, 0, sizeof(xConnSetup)); 5456747b715Smrg /* Leave off the ridBase and ridMask, these must be sent with 5466747b715Smrg connection */ 5476747b715Smrg 5486747b715Smrg setup.release = VendorRelease; 5496747b715Smrg /* 5506747b715Smrg * per-server image and bitmap parameters are defined in Xmd.h 5516747b715Smrg */ 5526747b715Smrg setup.imageByteOrder = screenInfo.imageByteOrder; 5536747b715Smrg 5546747b715Smrg setup.bitmapScanlineUnit = screenInfo.bitmapScanlineUnit; 5556747b715Smrg setup.bitmapScanlinePad = screenInfo.bitmapScanlinePad; 5566747b715Smrg 5576747b715Smrg setup.bitmapBitOrder = screenInfo.bitmapBitOrder; 5586747b715Smrg setup.motionBufferSize = NumMotionEvents(); 5596747b715Smrg setup.numRoots = screenInfo.numScreens; 5606747b715Smrg setup.nbytesVendor = strlen(VendorString); 5616747b715Smrg setup.numFormats = screenInfo.numPixmapFormats; 5626747b715Smrg setup.maxRequestSize = MAX_REQUEST_SIZE; 5636747b715Smrg QueryMinMaxKeyCodes(&setup.minKeyCode, &setup.maxKeyCode); 5646747b715Smrg 5656747b715Smrg lenofblock = sizeof(xConnSetup) + 566f7df2e56Smrg pad_to_int32(setup.nbytesVendor) + 567f7df2e56Smrg (setup.numFormats * sizeof(xPixmapFormat)) + 568f7df2e56Smrg (setup.numRoots * sizeof(xWindowRoot)); 5696747b715Smrg ConnectionInfo = malloc(lenofblock); 5706747b715Smrg if (!ConnectionInfo) 571f7df2e56Smrg return FALSE; 5726747b715Smrg 573f7df2e56Smrg memmove(ConnectionInfo, (char *) &setup, sizeof(xConnSetup)); 5746747b715Smrg sizesofar = sizeof(xConnSetup); 5756747b715Smrg pBuf = ConnectionInfo + sizeof(xConnSetup); 5766747b715Smrg 577f7df2e56Smrg memmove(pBuf, VendorString, (int) setup.nbytesVendor); 5786747b715Smrg sizesofar += setup.nbytesVendor; 5796747b715Smrg pBuf += setup.nbytesVendor; 580f7df2e56Smrg i = padding_for_int32(setup.nbytesVendor); 5816747b715Smrg sizesofar += i; 5826747b715Smrg while (--i >= 0) 583f7df2e56Smrg *pBuf++ = 0; 5846747b715Smrg 5856747b715Smrg memset(&format, 0, sizeof(xPixmapFormat)); 586f7df2e56Smrg for (i = 0; i < screenInfo.numPixmapFormats; i++) { 587f7df2e56Smrg format.depth = screenInfo.formats[i].depth; 588f7df2e56Smrg format.bitsPerPixel = screenInfo.formats[i].bitsPerPixel; 589f7df2e56Smrg format.scanLinePad = screenInfo.formats[i].scanlinePad; 590f7df2e56Smrg memmove(pBuf, (char *) &format, sizeof(xPixmapFormat)); 591f7df2e56Smrg pBuf += sizeof(xPixmapFormat); 592f7df2e56Smrg sizesofar += sizeof(xPixmapFormat); 5936747b715Smrg } 5946747b715Smrg 5956747b715Smrg connBlockScreenStart = sizesofar; 5966747b715Smrg memset(&depth, 0, sizeof(xDepth)); 5976747b715Smrg memset(&visual, 0, sizeof(xVisualType)); 598f7df2e56Smrg for (i = 0; i < screenInfo.numScreens; i++) { 599f7df2e56Smrg ScreenPtr pScreen; 600f7df2e56Smrg DepthPtr pDepth; 601f7df2e56Smrg VisualPtr pVisual; 602f7df2e56Smrg 603f7df2e56Smrg pScreen = screenInfo.screens[i]; 604f7df2e56Smrg root.windowId = pScreen->root->drawable.id; 605f7df2e56Smrg root.defaultColormap = pScreen->defColormap; 606f7df2e56Smrg root.whitePixel = pScreen->whitePixel; 607f7df2e56Smrg root.blackPixel = pScreen->blackPixel; 608f7df2e56Smrg root.currentInputMask = 0; /* filled in when sent */ 609f7df2e56Smrg root.pixWidth = pScreen->width; 610f7df2e56Smrg root.pixHeight = pScreen->height; 611f7df2e56Smrg root.mmWidth = pScreen->mmWidth; 612f7df2e56Smrg root.mmHeight = pScreen->mmHeight; 613f7df2e56Smrg root.minInstalledMaps = pScreen->minInstalledCmaps; 614f7df2e56Smrg root.maxInstalledMaps = pScreen->maxInstalledCmaps; 615f7df2e56Smrg root.rootVisualID = pScreen->rootVisual; 616f7df2e56Smrg root.backingStore = pScreen->backingStoreSupport; 617f7df2e56Smrg root.saveUnders = FALSE; 618f7df2e56Smrg root.rootDepth = pScreen->rootDepth; 619f7df2e56Smrg root.nDepths = pScreen->numDepths; 620f7df2e56Smrg memmove(pBuf, (char *) &root, sizeof(xWindowRoot)); 621f7df2e56Smrg sizesofar += sizeof(xWindowRoot); 622f7df2e56Smrg pBuf += sizeof(xWindowRoot); 623f7df2e56Smrg 624f7df2e56Smrg pDepth = pScreen->allowedDepths; 625f7df2e56Smrg for (j = 0; j < pScreen->numDepths; j++, pDepth++) { 626f7df2e56Smrg lenofblock += sizeof(xDepth) + 627f7df2e56Smrg (pDepth->numVids * sizeof(xVisualType)); 628f7df2e56Smrg pBuf = (char *) realloc(ConnectionInfo, lenofblock); 629f7df2e56Smrg if (!pBuf) { 630f7df2e56Smrg free(ConnectionInfo); 631f7df2e56Smrg return FALSE; 632f7df2e56Smrg } 633f7df2e56Smrg ConnectionInfo = pBuf; 634f7df2e56Smrg pBuf += sizesofar; 635f7df2e56Smrg depth.depth = pDepth->depth; 636f7df2e56Smrg depth.nVisuals = pDepth->numVids; 637f7df2e56Smrg memmove(pBuf, (char *) &depth, sizeof(xDepth)); 638f7df2e56Smrg pBuf += sizeof(xDepth); 639f7df2e56Smrg sizesofar += sizeof(xDepth); 640f7df2e56Smrg for (k = 0; k < pDepth->numVids; k++) { 641f7df2e56Smrg vid = pDepth->vids[k]; 642f7df2e56Smrg for (pVisual = pScreen->visuals; 643f7df2e56Smrg pVisual->vid != vid; pVisual++); 644f7df2e56Smrg visual.visualID = vid; 645f7df2e56Smrg visual.class = pVisual->class; 646f7df2e56Smrg visual.bitsPerRGB = pVisual->bitsPerRGBValue; 647f7df2e56Smrg visual.colormapEntries = pVisual->ColormapEntries; 648f7df2e56Smrg visual.redMask = pVisual->redMask; 649f7df2e56Smrg visual.greenMask = pVisual->greenMask; 650f7df2e56Smrg visual.blueMask = pVisual->blueMask; 651f7df2e56Smrg memmove(pBuf, (char *) &visual, sizeof(xVisualType)); 652f7df2e56Smrg pBuf += sizeof(xVisualType); 653f7df2e56Smrg sizesofar += sizeof(xVisualType); 654f7df2e56Smrg } 655f7df2e56Smrg } 6566747b715Smrg } 6576747b715Smrg connSetupPrefix.success = xTrue; 658f7df2e56Smrg connSetupPrefix.length = lenofblock / 4; 6596747b715Smrg connSetupPrefix.majorVersion = X_PROTOCOL; 6606747b715Smrg connSetupPrefix.minorVersion = X_PROTOCOL_REVISION; 6616747b715Smrg return TRUE; 6626747b715Smrg} 6636747b715Smrg 6646747b715Smrgint 66505b261ecSmrgProcBadRequest(ClientPtr client) 66605b261ecSmrg{ 6676747b715Smrg return BadRequest; 66805b261ecSmrg} 66905b261ecSmrg 67005b261ecSmrgint 67105b261ecSmrgProcCreateWindow(ClientPtr client) 67205b261ecSmrg{ 67305b261ecSmrg WindowPtr pParent, pWin; 674f7df2e56Smrg 67505b261ecSmrg REQUEST(xCreateWindowReq); 6764642e01fSmrg int len, rc; 67705b261ecSmrg 67805b261ecSmrg REQUEST_AT_LEAST_SIZE(xCreateWindowReq); 679f7df2e56Smrg 68005b261ecSmrg LEGAL_NEW_RESOURCE(stuff->wid, client); 6814642e01fSmrg rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess); 68205b261ecSmrg if (rc != Success) 68305b261ecSmrg return rc; 6846747b715Smrg len = client->req_len - bytes_to_int32(sizeof(xCreateWindowReq)); 68505b261ecSmrg if (Ones(stuff->mask) != len) 68605b261ecSmrg return BadLength; 687f7df2e56Smrg if (!stuff->width || !stuff->height) { 688f7df2e56Smrg client->errorValue = 0; 68905b261ecSmrg return BadValue; 69005b261ecSmrg } 69105b261ecSmrg pWin = CreateWindow(stuff->wid, pParent, stuff->x, 692f7df2e56Smrg stuff->y, stuff->width, stuff->height, 693f7df2e56Smrg stuff->borderWidth, stuff->class, 694f7df2e56Smrg stuff->mask, (XID *) &stuff[1], 695f7df2e56Smrg (int) stuff->depth, client, stuff->visual, &rc); 696f7df2e56Smrg if (pWin) { 697f7df2e56Smrg Mask mask = pWin->eventMask; 698f7df2e56Smrg 699f7df2e56Smrg pWin->eventMask = 0; /* subterfuge in case AddResource fails */ 700f7df2e56Smrg if (!AddResource(stuff->wid, RT_WINDOW, (void *) pWin)) 701f7df2e56Smrg return BadAlloc; 702f7df2e56Smrg pWin->eventMask = mask; 70305b261ecSmrg } 7046747b715Smrg return rc; 70505b261ecSmrg} 70605b261ecSmrg 70705b261ecSmrgint 70805b261ecSmrgProcChangeWindowAttributes(ClientPtr client) 70905b261ecSmrg{ 71005b261ecSmrg WindowPtr pWin; 711f7df2e56Smrg 71205b261ecSmrg REQUEST(xChangeWindowAttributesReq); 7136747b715Smrg int len, rc; 7144642e01fSmrg Mask access_mode = 0; 71505b261ecSmrg 71605b261ecSmrg REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); 7174642e01fSmrg access_mode |= (stuff->valueMask & CWEventMask) ? DixReceiveAccess : 0; 7184642e01fSmrg access_mode |= (stuff->valueMask & ~CWEventMask) ? DixSetAttrAccess : 0; 7194642e01fSmrg rc = dixLookupWindow(&pWin, stuff->window, client, access_mode); 72005b261ecSmrg if (rc != Success) 72105b261ecSmrg return rc; 7226747b715Smrg len = client->req_len - bytes_to_int32(sizeof(xChangeWindowAttributesReq)); 72305b261ecSmrg if (len != Ones(stuff->valueMask)) 72405b261ecSmrg return BadLength; 7256747b715Smrg return ChangeWindowAttributes(pWin, 726f7df2e56Smrg stuff->valueMask, (XID *) &stuff[1], client); 72705b261ecSmrg} 72805b261ecSmrg 72905b261ecSmrgint 73005b261ecSmrgProcGetWindowAttributes(ClientPtr client) 73105b261ecSmrg{ 73205b261ecSmrg WindowPtr pWin; 733f7df2e56Smrg 73405b261ecSmrg REQUEST(xResourceReq); 73505b261ecSmrg xGetWindowAttributesReply wa; 73605b261ecSmrg int rc; 73705b261ecSmrg 73805b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 7394642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess); 74005b261ecSmrg if (rc != Success) 741f7df2e56Smrg return rc; 7426747b715Smrg memset(&wa, 0, sizeof(xGetWindowAttributesReply)); 74305b261ecSmrg GetWindowAttributes(pWin, client, &wa); 74405b261ecSmrg WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa); 7456747b715Smrg return Success; 74605b261ecSmrg} 74705b261ecSmrg 74805b261ecSmrgint 74905b261ecSmrgProcDestroyWindow(ClientPtr client) 75005b261ecSmrg{ 75105b261ecSmrg WindowPtr pWin; 752f7df2e56Smrg 75305b261ecSmrg REQUEST(xResourceReq); 75405b261ecSmrg int rc; 75505b261ecSmrg 75605b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 75705b261ecSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixDestroyAccess); 75805b261ecSmrg if (rc != Success) 759f7df2e56Smrg return rc; 7604642e01fSmrg if (pWin->parent) { 761f7df2e56Smrg rc = dixLookupWindow(&pWin, pWin->parent->drawable.id, client, 762f7df2e56Smrg DixRemoveAccess); 763f7df2e56Smrg if (rc != Success) 764f7df2e56Smrg return rc; 765f7df2e56Smrg FreeResource(stuff->id, RT_NONE); 7664642e01fSmrg } 7676747b715Smrg return Success; 76805b261ecSmrg} 76905b261ecSmrg 77005b261ecSmrgint 77105b261ecSmrgProcDestroySubwindows(ClientPtr client) 77205b261ecSmrg{ 77305b261ecSmrg WindowPtr pWin; 774f7df2e56Smrg 77505b261ecSmrg REQUEST(xResourceReq); 77605b261ecSmrg int rc; 77705b261ecSmrg 77805b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 7794642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixRemoveAccess); 78005b261ecSmrg if (rc != Success) 781f7df2e56Smrg return rc; 78205b261ecSmrg DestroySubwindows(pWin, client); 7836747b715Smrg return Success; 78405b261ecSmrg} 78505b261ecSmrg 78605b261ecSmrgint 78705b261ecSmrgProcChangeSaveSet(ClientPtr client) 78805b261ecSmrg{ 78905b261ecSmrg WindowPtr pWin; 790f7df2e56Smrg 79105b261ecSmrg REQUEST(xChangeSaveSetReq); 7926747b715Smrg int rc; 793f7df2e56Smrg 79405b261ecSmrg REQUEST_SIZE_MATCH(xChangeSaveSetReq); 7954642e01fSmrg rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess); 79605b261ecSmrg if (rc != Success) 79705b261ecSmrg return rc; 79805b261ecSmrg if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id))) 79905b261ecSmrg return BadMatch; 80005b261ecSmrg if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete)) 8016747b715Smrg return AlterSaveSetForClient(client, pWin, stuff->mode, FALSE, TRUE); 8026747b715Smrg client->errorValue = stuff->mode; 8036747b715Smrg return BadValue; 80405b261ecSmrg} 80505b261ecSmrg 80605b261ecSmrgint 80705b261ecSmrgProcReparentWindow(ClientPtr client) 80805b261ecSmrg{ 80905b261ecSmrg WindowPtr pWin, pParent; 810f7df2e56Smrg 81105b261ecSmrg REQUEST(xReparentWindowReq); 8126747b715Smrg int rc; 81305b261ecSmrg 81405b261ecSmrg REQUEST_SIZE_MATCH(xReparentWindowReq); 8154642e01fSmrg rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess); 81605b261ecSmrg if (rc != Success) 81705b261ecSmrg return rc; 8184642e01fSmrg rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess); 81905b261ecSmrg if (rc != Success) 82005b261ecSmrg return rc; 8216747b715Smrg if (!SAME_SCREENS(pWin->drawable, pParent->drawable)) 822f7df2e56Smrg return BadMatch; 8236747b715Smrg if ((pWin->backgroundState == ParentRelative) && 824f7df2e56Smrg (pParent->drawable.depth != pWin->drawable.depth)) 825f7df2e56Smrg return BadMatch; 8266747b715Smrg if ((pWin->drawable.class != InputOnly) && 827f7df2e56Smrg (pParent->drawable.class == InputOnly)) 828f7df2e56Smrg return BadMatch; 8296747b715Smrg return ReparentWindow(pWin, pParent, 830f7df2e56Smrg (short) stuff->x, (short) stuff->y, client); 83105b261ecSmrg} 83205b261ecSmrg 83305b261ecSmrgint 83405b261ecSmrgProcMapWindow(ClientPtr client) 83505b261ecSmrg{ 83605b261ecSmrg WindowPtr pWin; 837f7df2e56Smrg 83805b261ecSmrg REQUEST(xResourceReq); 83905b261ecSmrg int rc; 84005b261ecSmrg 84105b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 8424642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixShowAccess); 84305b261ecSmrg if (rc != Success) 84405b261ecSmrg return rc; 84505b261ecSmrg MapWindow(pWin, client); 846f7df2e56Smrg /* update cache to say it is mapped */ 8476747b715Smrg return Success; 84805b261ecSmrg} 84905b261ecSmrg 85005b261ecSmrgint 85105b261ecSmrgProcMapSubwindows(ClientPtr client) 85205b261ecSmrg{ 85305b261ecSmrg WindowPtr pWin; 854f7df2e56Smrg 85505b261ecSmrg REQUEST(xResourceReq); 85605b261ecSmrg int rc; 85705b261ecSmrg 85805b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 8594642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess); 86005b261ecSmrg if (rc != Success) 86105b261ecSmrg return rc; 86205b261ecSmrg MapSubwindows(pWin, client); 863f7df2e56Smrg /* update cache to say it is mapped */ 8646747b715Smrg return Success; 86505b261ecSmrg} 86605b261ecSmrg 86705b261ecSmrgint 86805b261ecSmrgProcUnmapWindow(ClientPtr client) 86905b261ecSmrg{ 87005b261ecSmrg WindowPtr pWin; 871f7df2e56Smrg 87205b261ecSmrg REQUEST(xResourceReq); 87305b261ecSmrg int rc; 87405b261ecSmrg 87505b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 8764642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixHideAccess); 87705b261ecSmrg if (rc != Success) 87805b261ecSmrg return rc; 87905b261ecSmrg UnmapWindow(pWin, FALSE); 880f7df2e56Smrg /* update cache to say it is mapped */ 8816747b715Smrg return Success; 88205b261ecSmrg} 88305b261ecSmrg 88405b261ecSmrgint 88505b261ecSmrgProcUnmapSubwindows(ClientPtr client) 88605b261ecSmrg{ 88705b261ecSmrg WindowPtr pWin; 888f7df2e56Smrg 88905b261ecSmrg REQUEST(xResourceReq); 89005b261ecSmrg int rc; 89105b261ecSmrg 89205b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 8934642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess); 89405b261ecSmrg if (rc != Success) 89505b261ecSmrg return rc; 89605b261ecSmrg UnmapSubwindows(pWin); 8976747b715Smrg return Success; 89805b261ecSmrg} 89905b261ecSmrg 90005b261ecSmrgint 90105b261ecSmrgProcConfigureWindow(ClientPtr client) 90205b261ecSmrg{ 90305b261ecSmrg WindowPtr pWin; 904f7df2e56Smrg 90505b261ecSmrg REQUEST(xConfigureWindowReq); 90605b261ecSmrg int len, rc; 90705b261ecSmrg 90805b261ecSmrg REQUEST_AT_LEAST_SIZE(xConfigureWindowReq); 9094642e01fSmrg rc = dixLookupWindow(&pWin, stuff->window, client, 910f7df2e56Smrg DixManageAccess | DixSetAttrAccess); 91105b261ecSmrg if (rc != Success) 91205b261ecSmrg return rc; 9136747b715Smrg len = client->req_len - bytes_to_int32(sizeof(xConfigureWindowReq)); 914f7df2e56Smrg if (Ones((Mask) stuff->mask) != len) 91505b261ecSmrg return BadLength; 916f7df2e56Smrg return ConfigureWindow(pWin, (Mask) stuff->mask, (XID *) &stuff[1], client); 91705b261ecSmrg} 91805b261ecSmrg 91905b261ecSmrgint 92005b261ecSmrgProcCirculateWindow(ClientPtr client) 92105b261ecSmrg{ 92205b261ecSmrg WindowPtr pWin; 923f7df2e56Smrg 92405b261ecSmrg REQUEST(xCirculateWindowReq); 92505b261ecSmrg int rc; 92605b261ecSmrg 92705b261ecSmrg REQUEST_SIZE_MATCH(xCirculateWindowReq); 928f7df2e56Smrg if ((stuff->direction != RaiseLowest) && (stuff->direction != LowerHighest)) { 929f7df2e56Smrg client->errorValue = stuff->direction; 93005b261ecSmrg return BadValue; 93105b261ecSmrg } 9324642e01fSmrg rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess); 93305b261ecSmrg if (rc != Success) 93405b261ecSmrg return rc; 935f7df2e56Smrg CirculateWindow(pWin, (int) stuff->direction, client); 9366747b715Smrg return Success; 93705b261ecSmrg} 93805b261ecSmrg 93905b261ecSmrgstatic int 940f7df2e56SmrgGetGeometry(ClientPtr client, xGetGeometryReply * rep) 94105b261ecSmrg{ 94205b261ecSmrg DrawablePtr pDraw; 94305b261ecSmrg int rc; 944f7df2e56Smrg 94505b261ecSmrg REQUEST(xResourceReq); 94605b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 94705b261ecSmrg 9484642e01fSmrg rc = dixLookupDrawable(&pDraw, stuff->id, client, M_ANY, DixGetAttrAccess); 94905b261ecSmrg if (rc != Success) 950f7df2e56Smrg return rc; 95105b261ecSmrg 95205b261ecSmrg rep->type = X_Reply; 95305b261ecSmrg rep->length = 0; 95405b261ecSmrg rep->sequenceNumber = client->sequence; 9556747b715Smrg rep->root = pDraw->pScreen->root->drawable.id; 95605b261ecSmrg rep->depth = pDraw->depth; 95705b261ecSmrg rep->width = pDraw->width; 95805b261ecSmrg rep->height = pDraw->height; 95905b261ecSmrg 960f7df2e56Smrg if (WindowDrawable(pDraw->type)) { 961f7df2e56Smrg WindowPtr pWin = (WindowPtr) pDraw; 962f7df2e56Smrg 963f7df2e56Smrg rep->x = pWin->origin.x - wBorderWidth(pWin); 964f7df2e56Smrg rep->y = pWin->origin.y - wBorderWidth(pWin); 965f7df2e56Smrg rep->borderWidth = pWin->borderWidth; 96605b261ecSmrg } 967f7df2e56Smrg else { /* DRAWABLE_PIXMAP */ 968f7df2e56Smrg 969f7df2e56Smrg rep->x = rep->y = rep->borderWidth = 0; 97005b261ecSmrg } 97105b261ecSmrg 97205b261ecSmrg return Success; 97305b261ecSmrg} 97405b261ecSmrg 97505b261ecSmrgint 97605b261ecSmrgProcGetGeometry(ClientPtr client) 97705b261ecSmrg{ 978f7df2e56Smrg xGetGeometryReply rep = { .type = X_Reply }; 97905b261ecSmrg int status; 98005b261ecSmrg 98105b261ecSmrg if ((status = GetGeometry(client, &rep)) != Success) 982f7df2e56Smrg return status; 98305b261ecSmrg 98405b261ecSmrg WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep); 9856747b715Smrg return Success; 98605b261ecSmrg} 98705b261ecSmrg 98805b261ecSmrgint 98905b261ecSmrgProcQueryTree(ClientPtr client) 99005b261ecSmrg{ 99105b261ecSmrg xQueryTreeReply reply; 99205b261ecSmrg int rc, numChildren = 0; 99305b261ecSmrg WindowPtr pChild, pWin, pHead; 994f7df2e56Smrg Window *childIDs = (Window *) NULL; 995f7df2e56Smrg 99605b261ecSmrg REQUEST(xResourceReq); 99705b261ecSmrg 99805b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 9994642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess); 100005b261ecSmrg if (rc != Success) 100105b261ecSmrg return rc; 1002f7df2e56Smrg 1003f7df2e56Smrg reply = (xQueryTreeReply) { 1004f7df2e56Smrg .type = X_Reply, 1005f7df2e56Smrg .sequenceNumber = client->sequence, 1006f7df2e56Smrg .root = pWin->drawable.pScreen->root->drawable.id, 1007f7df2e56Smrg .parent = (pWin->parent) ? pWin->parent->drawable.id : (Window) None 1008f7df2e56Smrg }; 100905b261ecSmrg pHead = RealChildHead(pWin); 101005b261ecSmrg for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) 1011f7df2e56Smrg numChildren++; 1012f7df2e56Smrg if (numChildren) { 1013f7df2e56Smrg int curChild = 0; 101405b261ecSmrg 1015f7df2e56Smrg childIDs = xallocarray(numChildren, sizeof(Window)); 1016f7df2e56Smrg if (!childIDs) 1017f7df2e56Smrg return BadAlloc; 1018f7df2e56Smrg for (pChild = pWin->lastChild; pChild != pHead; 1019f7df2e56Smrg pChild = pChild->prevSib) 1020f7df2e56Smrg childIDs[curChild++] = pChild->drawable.id; 102105b261ecSmrg } 1022f7df2e56Smrg 102305b261ecSmrg reply.nChildren = numChildren; 10246747b715Smrg reply.length = bytes_to_int32(numChildren * sizeof(Window)); 1025f7df2e56Smrg 102605b261ecSmrg WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply); 1027f7df2e56Smrg if (numChildren) { 1028f7df2e56Smrg client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; 1029f7df2e56Smrg WriteSwappedDataToClient(client, numChildren * sizeof(Window), 1030f7df2e56Smrg childIDs); 1031f7df2e56Smrg free(childIDs); 103205b261ecSmrg } 103305b261ecSmrg 10346747b715Smrg return Success; 103505b261ecSmrg} 103605b261ecSmrg 103705b261ecSmrgint 103805b261ecSmrgProcInternAtom(ClientPtr client) 103905b261ecSmrg{ 104005b261ecSmrg Atom atom; 104105b261ecSmrg char *tchar; 1042f7df2e56Smrg 104305b261ecSmrg REQUEST(xInternAtomReq); 104405b261ecSmrg 104505b261ecSmrg REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes); 1046f7df2e56Smrg if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse)) { 1047f7df2e56Smrg client->errorValue = stuff->onlyIfExists; 10486747b715Smrg return BadValue; 104905b261ecSmrg } 105005b261ecSmrg tchar = (char *) &stuff[1]; 105105b261ecSmrg atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists); 1052f7df2e56Smrg if (atom != BAD_RESOURCE) { 1053f7df2e56Smrg xInternAtomReply reply = { 1054f7df2e56Smrg .type = X_Reply, 1055f7df2e56Smrg .sequenceNumber = client->sequence, 1056f7df2e56Smrg .length = 0, 1057f7df2e56Smrg .atom = atom 1058f7df2e56Smrg }; 1059f7df2e56Smrg WriteReplyToClient(client, sizeof(xInternAtomReply), &reply); 1060f7df2e56Smrg return Success; 106105b261ecSmrg } 106205b261ecSmrg else 1063f7df2e56Smrg return BadAlloc; 106405b261ecSmrg} 106505b261ecSmrg 106605b261ecSmrgint 106705b261ecSmrgProcGetAtomName(ClientPtr client) 106805b261ecSmrg{ 10696747b715Smrg const char *str; 1070f7df2e56Smrg 107105b261ecSmrg REQUEST(xResourceReq); 107205b261ecSmrg 107305b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 1074f7df2e56Smrg if ((str = NameForAtom(stuff->id))) { 1075f7df2e56Smrg int len = strlen(str); 1076f7df2e56Smrg xGetAtomNameReply reply = { 1077f7df2e56Smrg .type = X_Reply, 1078f7df2e56Smrg .sequenceNumber = client->sequence, 1079f7df2e56Smrg .length = bytes_to_int32(len), 1080f7df2e56Smrg .nameLength = len 1081f7df2e56Smrg }; 1082f7df2e56Smrg 1083f7df2e56Smrg WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply); 1084f7df2e56Smrg WriteToClient(client, len, str); 1085f7df2e56Smrg return Success; 108605b261ecSmrg } 1087f7df2e56Smrg else { 1088f7df2e56Smrg client->errorValue = stuff->id; 1089f7df2e56Smrg return BadAtom; 109005b261ecSmrg } 109105b261ecSmrg} 109205b261ecSmrg 109305b261ecSmrgint 109405b261ecSmrgProcGrabServer(ClientPtr client) 109505b261ecSmrg{ 10964642e01fSmrg int rc; 1097f7df2e56Smrg 109805b261ecSmrg REQUEST_SIZE_MATCH(xReq); 1099f7df2e56Smrg if (grabState != GrabNone && client != grabClient) { 1100f7df2e56Smrg ResetCurrentRequest(client); 1101f7df2e56Smrg client->sequence--; 1102f7df2e56Smrg BITSET(grabWaiters, client->index); 1103f7df2e56Smrg IgnoreClient(client); 1104f7df2e56Smrg return Success; 110505b261ecSmrg } 11064642e01fSmrg rc = OnlyListenToOneClient(client); 11074642e01fSmrg if (rc != Success) 1108f7df2e56Smrg return rc; 11097e31ba66Smrg grabState = GrabActive; 111005b261ecSmrg grabClient = client; 11117e31ba66Smrg mark_client_grab(client); 111205b261ecSmrg 1113f7df2e56Smrg if (ServerGrabCallback) { 1114f7df2e56Smrg ServerGrabInfoRec grabinfo; 1115f7df2e56Smrg 1116f7df2e56Smrg grabinfo.client = client; 1117f7df2e56Smrg grabinfo.grabstate = SERVER_GRABBED; 1118f7df2e56Smrg CallCallbacks(&ServerGrabCallback, (void *) &grabinfo); 111905b261ecSmrg } 112005b261ecSmrg 11216747b715Smrg return Success; 112205b261ecSmrg} 112305b261ecSmrg 112405b261ecSmrgstatic void 112505b261ecSmrgUngrabServer(ClientPtr client) 112605b261ecSmrg{ 112705b261ecSmrg int i; 112805b261ecSmrg 112905b261ecSmrg grabState = GrabNone; 113005b261ecSmrg ListenToAllClients(); 11317e31ba66Smrg mark_client_ungrab(); 1132f7df2e56Smrg for (i = mskcnt; --i >= 0 && !grabWaiters[i];); 1133f7df2e56Smrg if (i >= 0) { 1134f7df2e56Smrg i <<= 5; 1135f7df2e56Smrg while (!GETBIT(grabWaiters, i)) 1136f7df2e56Smrg i++; 1137f7df2e56Smrg BITCLEAR(grabWaiters, i); 1138f7df2e56Smrg AttendClient(clients[i]); 113905b261ecSmrg } 114005b261ecSmrg 1141f7df2e56Smrg if (ServerGrabCallback) { 1142f7df2e56Smrg ServerGrabInfoRec grabinfo; 1143f7df2e56Smrg 1144f7df2e56Smrg grabinfo.client = client; 1145f7df2e56Smrg grabinfo.grabstate = SERVER_UNGRABBED; 1146f7df2e56Smrg CallCallbacks(&ServerGrabCallback, (void *) &grabinfo); 114705b261ecSmrg } 114805b261ecSmrg} 114905b261ecSmrg 115005b261ecSmrgint 115105b261ecSmrgProcUngrabServer(ClientPtr client) 115205b261ecSmrg{ 115305b261ecSmrg REQUEST_SIZE_MATCH(xReq); 115405b261ecSmrg UngrabServer(client); 11556747b715Smrg return Success; 115605b261ecSmrg} 115705b261ecSmrg 115805b261ecSmrgint 115905b261ecSmrgProcTranslateCoords(ClientPtr client) 116005b261ecSmrg{ 116105b261ecSmrg REQUEST(xTranslateCoordsReq); 116205b261ecSmrg 116305b261ecSmrg WindowPtr pWin, pDst; 116405b261ecSmrg xTranslateCoordsReply rep; 116505b261ecSmrg int rc; 116605b261ecSmrg 116705b261ecSmrg REQUEST_SIZE_MATCH(xTranslateCoordsReq); 11684642e01fSmrg rc = dixLookupWindow(&pWin, stuff->srcWid, client, DixGetAttrAccess); 116905b261ecSmrg if (rc != Success) 117005b261ecSmrg return rc; 11714642e01fSmrg rc = dixLookupWindow(&pDst, stuff->dstWid, client, DixGetAttrAccess); 117205b261ecSmrg if (rc != Success) 117305b261ecSmrg return rc; 1174f7df2e56Smrg 1175f7df2e56Smrg rep = (xTranslateCoordsReply) { 1176f7df2e56Smrg .type = X_Reply, 1177f7df2e56Smrg .sequenceNumber = client->sequence, 1178f7df2e56Smrg .length = 0 1179f7df2e56Smrg }; 1180f7df2e56Smrg if (!SAME_SCREENS(pWin->drawable, pDst->drawable)) { 1181f7df2e56Smrg rep.sameScreen = xFalse; 118205b261ecSmrg rep.child = None; 1183f7df2e56Smrg rep.dstX = rep.dstY = 0; 118405b261ecSmrg } 1185f7df2e56Smrg else { 1186f7df2e56Smrg INT16 x, y; 1187f7df2e56Smrg 1188f7df2e56Smrg rep.sameScreen = xTrue; 1189f7df2e56Smrg rep.child = None; 1190f7df2e56Smrg /* computing absolute coordinates -- adjust to destination later */ 1191f7df2e56Smrg x = pWin->drawable.x + stuff->srcX; 1192f7df2e56Smrg y = pWin->drawable.y + stuff->srcY; 1193f7df2e56Smrg pWin = pDst->firstChild; 1194f7df2e56Smrg while (pWin) { 1195f7df2e56Smrg BoxRec box; 1196f7df2e56Smrg 1197f7df2e56Smrg if ((pWin->mapped) && 1198f7df2e56Smrg (x >= pWin->drawable.x - wBorderWidth(pWin)) && 1199f7df2e56Smrg (x < pWin->drawable.x + (int) pWin->drawable.width + 1200f7df2e56Smrg wBorderWidth(pWin)) && 1201f7df2e56Smrg (y >= pWin->drawable.y - wBorderWidth(pWin)) && 1202f7df2e56Smrg (y < pWin->drawable.y + (int) pWin->drawable.height + 1203f7df2e56Smrg wBorderWidth(pWin)) 1204f7df2e56Smrg /* When a window is shaped, a further check 1205f7df2e56Smrg * is made to see if the point is inside 1206f7df2e56Smrg * borderSize 1207f7df2e56Smrg */ 1208f7df2e56Smrg && (!wBoundingShape(pWin) || 1209f7df2e56Smrg RegionContainsPoint(&pWin->borderSize, x, y, &box)) 1210f7df2e56Smrg 1211f7df2e56Smrg && (!wInputShape(pWin) || 1212f7df2e56Smrg RegionContainsPoint(wInputShape(pWin), 1213f7df2e56Smrg x - pWin->drawable.x, 1214f7df2e56Smrg y - pWin->drawable.y, &box)) 1215f7df2e56Smrg ) { 1216f7df2e56Smrg rep.child = pWin->drawable.id; 1217f7df2e56Smrg pWin = (WindowPtr) NULL; 1218f7df2e56Smrg } 1219f7df2e56Smrg else 1220f7df2e56Smrg pWin = pWin->nextSib; 1221f7df2e56Smrg } 1222f7df2e56Smrg /* adjust to destination coordinates */ 1223f7df2e56Smrg rep.dstX = x - pDst->drawable.x; 1224f7df2e56Smrg rep.dstY = y - pDst->drawable.y; 122505b261ecSmrg } 122605b261ecSmrg WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep); 12276747b715Smrg return Success; 122805b261ecSmrg} 122905b261ecSmrg 123005b261ecSmrgint 123105b261ecSmrgProcOpenFont(ClientPtr client) 123205b261ecSmrg{ 1233f7df2e56Smrg int err; 1234f7df2e56Smrg 123505b261ecSmrg REQUEST(xOpenFontReq); 123605b261ecSmrg 123705b261ecSmrg REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes); 123805b261ecSmrg client->errorValue = stuff->fid; 123905b261ecSmrg LEGAL_NEW_RESOURCE(stuff->fid, client); 124005b261ecSmrg err = OpenFont(client, stuff->fid, (Mask) 0, 1241f7df2e56Smrg stuff->nbytes, (char *) &stuff[1]); 1242f7df2e56Smrg if (err == Success) { 1243f7df2e56Smrg return Success; 124405b261ecSmrg } 124505b261ecSmrg else 1246f7df2e56Smrg return err; 124705b261ecSmrg} 124805b261ecSmrg 124905b261ecSmrgint 125005b261ecSmrgProcCloseFont(ClientPtr client) 125105b261ecSmrg{ 125205b261ecSmrg FontPtr pFont; 12536747b715Smrg int rc; 1254f7df2e56Smrg 125505b261ecSmrg REQUEST(xResourceReq); 125605b261ecSmrg 125705b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 1258f7df2e56Smrg rc = dixLookupResourceByType((void **) &pFont, stuff->id, RT_FONT, 1259f7df2e56Smrg client, DixDestroyAccess); 1260f7df2e56Smrg if (rc == Success) { 126105b261ecSmrg FreeResource(stuff->id, RT_NONE); 1262f7df2e56Smrg return Success; 126305b261ecSmrg } 1264f7df2e56Smrg else { 1265f7df2e56Smrg client->errorValue = stuff->id; 12666747b715Smrg return rc; 126705b261ecSmrg } 126805b261ecSmrg} 126905b261ecSmrg 127005b261ecSmrgint 127105b261ecSmrgProcQueryFont(ClientPtr client) 127205b261ecSmrg{ 1273f7df2e56Smrg xQueryFontReply *reply; 127405b261ecSmrg FontPtr pFont; 12754642e01fSmrg int rc; 1276f7df2e56Smrg 127705b261ecSmrg REQUEST(xResourceReq); 127805b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 12794642e01fSmrg 12806747b715Smrg rc = dixLookupFontable(&pFont, stuff->id, client, DixGetAttrAccess); 12814642e01fSmrg if (rc != Success) 1282f7df2e56Smrg return rc; 128305b261ecSmrg 128405b261ecSmrg { 1285f7df2e56Smrg xCharInfo *pmax = FONTINKMAX(pFont); 1286f7df2e56Smrg xCharInfo *pmin = FONTINKMIN(pFont); 1287f7df2e56Smrg int nprotoxcistructs; 1288f7df2e56Smrg int rlength; 1289f7df2e56Smrg 1290f7df2e56Smrg nprotoxcistructs = (pmax->rightSideBearing == pmin->rightSideBearing && 1291f7df2e56Smrg pmax->leftSideBearing == pmin->leftSideBearing && 1292f7df2e56Smrg pmax->descent == pmin->descent && 1293f7df2e56Smrg pmax->ascent == pmin->ascent && 1294f7df2e56Smrg pmax->characterWidth == pmin->characterWidth) ? 1295f7df2e56Smrg 0 : N2dChars(pFont); 1296f7df2e56Smrg 1297f7df2e56Smrg rlength = sizeof(xQueryFontReply) + 1298f7df2e56Smrg FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) + 1299f7df2e56Smrg nprotoxcistructs * sizeof(xCharInfo); 1300f7df2e56Smrg reply = calloc(1, rlength); 1301f7df2e56Smrg if (!reply) { 1302f7df2e56Smrg return BadAlloc; 1303f7df2e56Smrg } 1304f7df2e56Smrg 1305f7df2e56Smrg reply->type = X_Reply; 1306f7df2e56Smrg reply->length = bytes_to_int32(rlength - sizeof(xGenericReply)); 1307f7df2e56Smrg reply->sequenceNumber = client->sequence; 1308f7df2e56Smrg QueryFont(pFont, reply, nprotoxcistructs); 130905b261ecSmrg 131005b261ecSmrg WriteReplyToClient(client, rlength, reply); 1311f7df2e56Smrg free(reply); 1312f7df2e56Smrg return Success; 131305b261ecSmrg } 131405b261ecSmrg} 131505b261ecSmrg 131605b261ecSmrgint 131705b261ecSmrgProcQueryTextExtents(ClientPtr client) 131805b261ecSmrg{ 131905b261ecSmrg xQueryTextExtentsReply reply; 132005b261ecSmrg FontPtr pFont; 132105b261ecSmrg ExtentInfoRec info; 132205b261ecSmrg unsigned long length; 13234642e01fSmrg int rc; 1324f7df2e56Smrg 13254642e01fSmrg REQUEST(xQueryTextExtentsReq); 132605b261ecSmrg REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq); 1327f7df2e56Smrg 13286747b715Smrg rc = dixLookupFontable(&pFont, stuff->fid, client, DixGetAttrAccess); 13294642e01fSmrg if (rc != Success) 1330f7df2e56Smrg return rc; 13314642e01fSmrg 13326747b715Smrg length = client->req_len - bytes_to_int32(sizeof(xQueryTextExtentsReq)); 133305b261ecSmrg length = length << 1; 1334f7df2e56Smrg if (stuff->oddLength) { 1335f7df2e56Smrg if (length == 0) 1336f7df2e56Smrg return BadLength; 133705b261ecSmrg length--; 133805b261ecSmrg } 13397e31ba66Smrg if (!xfont2_query_text_extents(pFont, length, (unsigned char *) &stuff[1], &info)) 1340f7df2e56Smrg return BadAlloc; 1341f7df2e56Smrg reply = (xQueryTextExtentsReply) { 1342f7df2e56Smrg .type = X_Reply, 1343f7df2e56Smrg .drawDirection = info.drawDirection, 1344f7df2e56Smrg .sequenceNumber = client->sequence, 1345f7df2e56Smrg .length = 0, 1346f7df2e56Smrg .fontAscent = info.fontAscent, 1347f7df2e56Smrg .fontDescent = info.fontDescent, 1348f7df2e56Smrg .overallAscent = info.overallAscent, 1349f7df2e56Smrg .overallDescent = info.overallDescent, 1350f7df2e56Smrg .overallWidth = info.overallWidth, 1351f7df2e56Smrg .overallLeft = info.overallLeft, 1352f7df2e56Smrg .overallRight = info.overallRight 1353f7df2e56Smrg }; 135405b261ecSmrg WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply); 13556747b715Smrg return Success; 135605b261ecSmrg} 135705b261ecSmrg 135805b261ecSmrgint 135905b261ecSmrgProcListFonts(ClientPtr client) 136005b261ecSmrg{ 136105b261ecSmrg REQUEST(xListFontsReq); 136205b261ecSmrg 136305b261ecSmrg REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes); 136405b261ecSmrg 1365f7df2e56Smrg return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes, 1366f7df2e56Smrg stuff->maxNames); 136705b261ecSmrg} 136805b261ecSmrg 136905b261ecSmrgint 137005b261ecSmrgProcListFontsWithInfo(ClientPtr client) 137105b261ecSmrg{ 137205b261ecSmrg REQUEST(xListFontsWithInfoReq); 137305b261ecSmrg 137405b261ecSmrg REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes); 137505b261ecSmrg 137605b261ecSmrg return StartListFontsWithInfo(client, stuff->nbytes, 1377f7df2e56Smrg (unsigned char *) &stuff[1], stuff->maxNames); 137805b261ecSmrg} 137905b261ecSmrg 138005b261ecSmrg/** 138105b261ecSmrg * 138205b261ecSmrg * \param value must conform to DeleteType 138305b261ecSmrg */ 138405b261ecSmrgint 1385f7df2e56SmrgdixDestroyPixmap(void *value, XID pid) 138605b261ecSmrg{ 1387f7df2e56Smrg PixmapPtr pPixmap = (PixmapPtr) value; 1388f7df2e56Smrg 1389f7df2e56Smrg return (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap); 139005b261ecSmrg} 139105b261ecSmrg 139205b261ecSmrgint 139305b261ecSmrgProcCreatePixmap(ClientPtr client) 139405b261ecSmrg{ 139505b261ecSmrg PixmapPtr pMap; 139605b261ecSmrg DrawablePtr pDraw; 1397f7df2e56Smrg 139805b261ecSmrg REQUEST(xCreatePixmapReq); 139905b261ecSmrg DepthPtr pDepth; 140005b261ecSmrg int i, rc; 140105b261ecSmrg 140205b261ecSmrg REQUEST_SIZE_MATCH(xCreatePixmapReq); 140305b261ecSmrg client->errorValue = stuff->pid; 140405b261ecSmrg LEGAL_NEW_RESOURCE(stuff->pid, client); 1405f7df2e56Smrg 140605b261ecSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, 1407f7df2e56Smrg DixGetAttrAccess); 140805b261ecSmrg if (rc != Success) 1409f7df2e56Smrg return rc; 141005b261ecSmrg 1411f7df2e56Smrg if (!stuff->width || !stuff->height) { 1412f7df2e56Smrg client->errorValue = 0; 141305b261ecSmrg return BadValue; 141405b261ecSmrg } 1415f7df2e56Smrg if (stuff->width > 32767 || stuff->height > 32767) { 1416f7df2e56Smrg /* It is allowed to try and allocate a pixmap which is larger than 1417f7df2e56Smrg * 32767 in either dimension. However, all of the framebuffer code 1418f7df2e56Smrg * is buggy and does not reliably draw to such big pixmaps, basically 1419f7df2e56Smrg * because the Region data structure operates with signed shorts 1420f7df2e56Smrg * for the rectangles in it. 1421f7df2e56Smrg * 1422f7df2e56Smrg * Furthermore, several places in the X server computes the 1423f7df2e56Smrg * size in bytes of the pixmap and tries to store it in an 1424f7df2e56Smrg * integer. This integer can overflow and cause the allocated size 1425f7df2e56Smrg * to be much smaller. 1426f7df2e56Smrg * 1427f7df2e56Smrg * So, such big pixmaps are rejected here with a BadAlloc 1428f7df2e56Smrg */ 1429f7df2e56Smrg return BadAlloc; 1430f7df2e56Smrg } 1431f7df2e56Smrg if (stuff->depth != 1) { 143205b261ecSmrg pDepth = pDraw->pScreen->allowedDepths; 1433f7df2e56Smrg for (i = 0; i < pDraw->pScreen->numDepths; i++, pDepth++) 1434f7df2e56Smrg if (pDepth->depth == stuff->depth) 1435f7df2e56Smrg goto CreatePmap; 1436f7df2e56Smrg client->errorValue = stuff->depth; 143705b261ecSmrg return BadValue; 143805b261ecSmrg } 1439f7df2e56Smrg CreatePmap: 1440f7df2e56Smrg pMap = (PixmapPtr) (*pDraw->pScreen->CreatePixmap) 1441f7df2e56Smrg (pDraw->pScreen, stuff->width, stuff->height, stuff->depth, 0); 1442f7df2e56Smrg if (pMap) { 1443f7df2e56Smrg pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; 1444f7df2e56Smrg pMap->drawable.id = stuff->pid; 1445f7df2e56Smrg /* security creation/labeling check */ 1446f7df2e56Smrg rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP, 1447f7df2e56Smrg pMap, RT_NONE, NULL, DixCreateAccess); 1448f7df2e56Smrg if (rc != Success) { 1449f7df2e56Smrg (*pDraw->pScreen->DestroyPixmap) (pMap); 1450f7df2e56Smrg return rc; 1451f7df2e56Smrg } 1452f7df2e56Smrg if (AddResource(stuff->pid, RT_PIXMAP, (void *) pMap)) 1453f7df2e56Smrg return Success; 145405b261ecSmrg } 14556747b715Smrg return BadAlloc; 145605b261ecSmrg} 145705b261ecSmrg 145805b261ecSmrgint 145905b261ecSmrgProcFreePixmap(ClientPtr client) 146005b261ecSmrg{ 146105b261ecSmrg PixmapPtr pMap; 14624642e01fSmrg int rc; 1463f7df2e56Smrg 146405b261ecSmrg REQUEST(xResourceReq); 146505b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 14664642e01fSmrg 1467f7df2e56Smrg rc = dixLookupResourceByType((void **) &pMap, stuff->id, RT_PIXMAP, 1468f7df2e56Smrg client, DixDestroyAccess); 1469f7df2e56Smrg if (rc == Success) { 1470f7df2e56Smrg FreeResource(stuff->id, RT_NONE); 1471f7df2e56Smrg return Success; 147205b261ecSmrg } 1473f7df2e56Smrg else { 1474f7df2e56Smrg client->errorValue = stuff->id; 1475f7df2e56Smrg return rc; 147605b261ecSmrg } 147705b261ecSmrg} 147805b261ecSmrg 147905b261ecSmrgint 148005b261ecSmrgProcCreateGC(ClientPtr client) 148105b261ecSmrg{ 148205b261ecSmrg int error, rc; 148305b261ecSmrg GC *pGC; 148405b261ecSmrg DrawablePtr pDraw; 148505b261ecSmrg unsigned len; 1486f7df2e56Smrg 148705b261ecSmrg REQUEST(xCreateGCReq); 148805b261ecSmrg 148905b261ecSmrg REQUEST_AT_LEAST_SIZE(xCreateGCReq); 149005b261ecSmrg client->errorValue = stuff->gc; 149105b261ecSmrg LEGAL_NEW_RESOURCE(stuff->gc, client); 14924642e01fSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, 1493f7df2e56Smrg DixGetAttrAccess); 149405b261ecSmrg if (rc != Success) 1495f7df2e56Smrg return rc; 149605b261ecSmrg 1497f7df2e56Smrg len = client->req_len - bytes_to_int32(sizeof(xCreateGCReq)); 149805b261ecSmrg if (len != Ones(stuff->mask)) 149905b261ecSmrg return BadLength; 1500f7df2e56Smrg pGC = (GC *) CreateGC(pDraw, stuff->mask, (XID *) &stuff[1], &error, 1501f7df2e56Smrg stuff->gc, client); 150205b261ecSmrg if (error != Success) 150305b261ecSmrg return error; 1504f7df2e56Smrg if (!AddResource(stuff->gc, RT_GC, (void *) pGC)) 1505f7df2e56Smrg return BadAlloc; 15066747b715Smrg return Success; 150705b261ecSmrg} 150805b261ecSmrg 150905b261ecSmrgint 151005b261ecSmrgProcChangeGC(ClientPtr client) 151105b261ecSmrg{ 151205b261ecSmrg GC *pGC; 151305b261ecSmrg int result; 151405b261ecSmrg unsigned len; 1515f7df2e56Smrg 151605b261ecSmrg REQUEST(xChangeGCReq); 151705b261ecSmrg REQUEST_AT_LEAST_SIZE(xChangeGCReq); 151805b261ecSmrg 15194642e01fSmrg result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess); 152005b261ecSmrg if (result != Success) 1521f7df2e56Smrg return result; 152205b261ecSmrg 1523f7df2e56Smrg len = client->req_len - bytes_to_int32(sizeof(xChangeGCReq)); 152405b261ecSmrg if (len != Ones(stuff->mask)) 152505b261ecSmrg return BadLength; 152605b261ecSmrg 15276747b715Smrg return ChangeGCXIDs(client, pGC, stuff->mask, (CARD32 *) &stuff[1]); 152805b261ecSmrg} 152905b261ecSmrg 153005b261ecSmrgint 153105b261ecSmrgProcCopyGC(ClientPtr client) 153205b261ecSmrg{ 153305b261ecSmrg GC *dstGC; 153405b261ecSmrg GC *pGC; 153505b261ecSmrg int result; 1536f7df2e56Smrg 153705b261ecSmrg REQUEST(xCopyGCReq); 153805b261ecSmrg REQUEST_SIZE_MATCH(xCopyGCReq); 153905b261ecSmrg 15404642e01fSmrg result = dixLookupGC(&pGC, stuff->srcGC, client, DixGetAttrAccess); 154105b261ecSmrg if (result != Success) 1542f7df2e56Smrg return result; 15434642e01fSmrg result = dixLookupGC(&dstGC, stuff->dstGC, client, DixSetAttrAccess); 154405b261ecSmrg if (result != Success) 1545f7df2e56Smrg return result; 154605b261ecSmrg if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth)) 15476747b715Smrg return BadMatch; 1548f7df2e56Smrg if (stuff->mask & ~GCAllBits) { 1549f7df2e56Smrg client->errorValue = stuff->mask; 1550f7df2e56Smrg return BadValue; 155105b261ecSmrg } 15526747b715Smrg return CopyGC(pGC, dstGC, stuff->mask); 155305b261ecSmrg} 155405b261ecSmrg 155505b261ecSmrgint 155605b261ecSmrgProcSetDashes(ClientPtr client) 155705b261ecSmrg{ 155805b261ecSmrg GC *pGC; 155905b261ecSmrg int result; 1560f7df2e56Smrg 156105b261ecSmrg REQUEST(xSetDashesReq); 156205b261ecSmrg 156305b261ecSmrg REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes); 1564f7df2e56Smrg if (stuff->nDashes == 0) { 1565f7df2e56Smrg client->errorValue = 0; 1566f7df2e56Smrg return BadValue; 156705b261ecSmrg } 156805b261ecSmrg 1569f7df2e56Smrg result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess); 157005b261ecSmrg if (result != Success) 1571f7df2e56Smrg return result; 157205b261ecSmrg 15736747b715Smrg /* If there's an error, either there's no sensible errorValue, 15746747b715Smrg * or there was a dash segment of 0. */ 15756747b715Smrg client->errorValue = 0; 15766747b715Smrg return SetDashes(pGC, stuff->dashOffset, stuff->nDashes, 1577f7df2e56Smrg (unsigned char *) &stuff[1]); 157805b261ecSmrg} 157905b261ecSmrg 158005b261ecSmrgint 158105b261ecSmrgProcSetClipRectangles(ClientPtr client) 158205b261ecSmrg{ 1583f7df2e56Smrg int nr, result; 158405b261ecSmrg GC *pGC; 1585f7df2e56Smrg 158605b261ecSmrg REQUEST(xSetClipRectanglesReq); 158705b261ecSmrg 158805b261ecSmrg REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq); 158905b261ecSmrg if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) && 1590f7df2e56Smrg (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) { 1591f7df2e56Smrg client->errorValue = stuff->ordering; 159205b261ecSmrg return BadValue; 159305b261ecSmrg } 1594f7df2e56Smrg result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess); 159505b261ecSmrg if (result != Success) 1596f7df2e56Smrg return result; 1597f7df2e56Smrg 159805b261ecSmrg nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq); 159905b261ecSmrg if (nr & 4) 1600f7df2e56Smrg return BadLength; 160105b261ecSmrg nr >>= 3; 16026747b715Smrg return SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin, 1603f7df2e56Smrg nr, (xRectangle *) &stuff[1], (int) stuff->ordering); 160405b261ecSmrg} 160505b261ecSmrg 160605b261ecSmrgint 160705b261ecSmrgProcFreeGC(ClientPtr client) 160805b261ecSmrg{ 160905b261ecSmrg GC *pGC; 161005b261ecSmrg int rc; 1611f7df2e56Smrg 161205b261ecSmrg REQUEST(xResourceReq); 161305b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 161405b261ecSmrg 161505b261ecSmrg rc = dixLookupGC(&pGC, stuff->id, client, DixDestroyAccess); 161605b261ecSmrg if (rc != Success) 1617f7df2e56Smrg return rc; 161805b261ecSmrg 161905b261ecSmrg FreeResource(stuff->id, RT_NONE); 16206747b715Smrg return Success; 162105b261ecSmrg} 162205b261ecSmrg 162305b261ecSmrgint 162405b261ecSmrgProcClearToBackground(ClientPtr client) 162505b261ecSmrg{ 162605b261ecSmrg REQUEST(xClearAreaReq); 162705b261ecSmrg WindowPtr pWin; 162805b261ecSmrg int rc; 162905b261ecSmrg 163005b261ecSmrg REQUEST_SIZE_MATCH(xClearAreaReq); 163105b261ecSmrg rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess); 163205b261ecSmrg if (rc != Success) 163305b261ecSmrg return rc; 1634f7df2e56Smrg if (pWin->drawable.class == InputOnly) { 1635f7df2e56Smrg client->errorValue = stuff->window; 1636f7df2e56Smrg return BadMatch; 1637f7df2e56Smrg } 1638f7df2e56Smrg if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) { 1639f7df2e56Smrg client->errorValue = stuff->exposures; 16406747b715Smrg return BadValue; 164105b261ecSmrg } 1642f7df2e56Smrg (*pWin->drawable.pScreen->ClearToBackground) (pWin, stuff->x, stuff->y, 1643f7df2e56Smrg stuff->width, stuff->height, 1644f7df2e56Smrg (Bool) stuff->exposures); 16456747b715Smrg return Success; 164605b261ecSmrg} 164705b261ecSmrg 1648f7df2e56Smrg/* send GraphicsExpose events, or a NoExpose event, based on the region */ 1649f7df2e56Smrgvoid 1650f7df2e56SmrgSendGraphicsExpose(ClientPtr client, RegionPtr pRgn, XID drawable, 1651f7df2e56Smrg int major, int minor) 1652f7df2e56Smrg{ 1653f7df2e56Smrg if (pRgn && !RegionNil(pRgn)) { 1654f7df2e56Smrg xEvent *pEvent; 1655f7df2e56Smrg xEvent *pe; 1656f7df2e56Smrg BoxPtr pBox; 1657f7df2e56Smrg int i; 1658f7df2e56Smrg int numRects; 1659f7df2e56Smrg 1660f7df2e56Smrg numRects = RegionNumRects(pRgn); 1661f7df2e56Smrg pBox = RegionRects(pRgn); 1662f7df2e56Smrg if (!(pEvent = calloc(numRects, sizeof(xEvent)))) 1663f7df2e56Smrg return; 1664f7df2e56Smrg pe = pEvent; 1665f7df2e56Smrg 1666f7df2e56Smrg for (i = 1; i <= numRects; i++, pe++, pBox++) { 1667f7df2e56Smrg pe->u.u.type = GraphicsExpose; 1668f7df2e56Smrg pe->u.graphicsExposure.drawable = drawable; 1669f7df2e56Smrg pe->u.graphicsExposure.x = pBox->x1; 1670f7df2e56Smrg pe->u.graphicsExposure.y = pBox->y1; 1671f7df2e56Smrg pe->u.graphicsExposure.width = pBox->x2 - pBox->x1; 1672f7df2e56Smrg pe->u.graphicsExposure.height = pBox->y2 - pBox->y1; 1673f7df2e56Smrg pe->u.graphicsExposure.count = numRects - i; 1674f7df2e56Smrg pe->u.graphicsExposure.majorEvent = major; 1675f7df2e56Smrg pe->u.graphicsExposure.minorEvent = minor; 1676f7df2e56Smrg } 1677f7df2e56Smrg /* GraphicsExpose is a "critical event", which TryClientEvents 1678f7df2e56Smrg * handles specially. */ 1679f7df2e56Smrg TryClientEvents(client, NULL, pEvent, numRects, 1680f7df2e56Smrg (Mask) 0, NoEventMask, NullGrab); 1681f7df2e56Smrg free(pEvent); 1682f7df2e56Smrg } 1683f7df2e56Smrg else { 1684f7df2e56Smrg xEvent event = { 1685f7df2e56Smrg .u.noExposure.drawable = drawable, 1686f7df2e56Smrg .u.noExposure.majorEvent = major, 1687f7df2e56Smrg .u.noExposure.minorEvent = minor 1688f7df2e56Smrg }; 1689f7df2e56Smrg event.u.u.type = NoExpose; 1690f7df2e56Smrg WriteEventsToClient(client, 1, &event); 1691f7df2e56Smrg } 1692f7df2e56Smrg} 1693f7df2e56Smrg 169405b261ecSmrgint 169505b261ecSmrgProcCopyArea(ClientPtr client) 169605b261ecSmrg{ 169705b261ecSmrg DrawablePtr pDst; 169805b261ecSmrg DrawablePtr pSrc; 169905b261ecSmrg GC *pGC; 1700f7df2e56Smrg 170105b261ecSmrg REQUEST(xCopyAreaReq); 170205b261ecSmrg RegionPtr pRgn; 170305b261ecSmrg int rc; 170405b261ecSmrg 170505b261ecSmrg REQUEST_SIZE_MATCH(xCopyAreaReq); 170605b261ecSmrg 1707f7df2e56Smrg VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, DixWriteAccess); 1708f7df2e56Smrg if (stuff->dstDrawable != stuff->srcDrawable) { 1709f7df2e56Smrg rc = dixLookupDrawable(&pSrc, stuff->srcDrawable, client, 0, 1710f7df2e56Smrg DixReadAccess); 1711f7df2e56Smrg if (rc != Success) 1712f7df2e56Smrg return rc; 1713f7df2e56Smrg if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) { 1714f7df2e56Smrg client->errorValue = stuff->dstDrawable; 1715f7df2e56Smrg return BadMatch; 1716f7df2e56Smrg } 171705b261ecSmrg } 171805b261ecSmrg else 171905b261ecSmrg pSrc = pDst; 172005b261ecSmrg 1721f7df2e56Smrg pRgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, stuff->srcX, stuff->srcY, 1722f7df2e56Smrg stuff->width, stuff->height, 1723f7df2e56Smrg stuff->dstX, stuff->dstY); 1724f7df2e56Smrg if (pGC->graphicsExposures) { 1725f7df2e56Smrg SendGraphicsExpose(client, pRgn, stuff->dstDrawable, X_CopyArea, 0); 1726f7df2e56Smrg if (pRgn) 1727f7df2e56Smrg RegionDestroy(pRgn); 172805b261ecSmrg } 172905b261ecSmrg 17306747b715Smrg return Success; 173105b261ecSmrg} 173205b261ecSmrg 173305b261ecSmrgint 173405b261ecSmrgProcCopyPlane(ClientPtr client) 173505b261ecSmrg{ 173605b261ecSmrg DrawablePtr psrcDraw, pdstDraw; 173705b261ecSmrg GC *pGC; 1738f7df2e56Smrg 173905b261ecSmrg REQUEST(xCopyPlaneReq); 174005b261ecSmrg RegionPtr pRgn; 174105b261ecSmrg int rc; 174205b261ecSmrg 174305b261ecSmrg REQUEST_SIZE_MATCH(xCopyPlaneReq); 174405b261ecSmrg 17454642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, DixWriteAccess); 1746f7df2e56Smrg if (stuff->dstDrawable != stuff->srcDrawable) { 1747f7df2e56Smrg rc = dixLookupDrawable(&psrcDraw, stuff->srcDrawable, client, 0, 1748f7df2e56Smrg DixReadAccess); 1749f7df2e56Smrg if (rc != Success) 1750f7df2e56Smrg return rc; 1751f7df2e56Smrg 1752f7df2e56Smrg if (pdstDraw->pScreen != psrcDraw->pScreen) { 1753f7df2e56Smrg client->errorValue = stuff->dstDrawable; 1754f7df2e56Smrg return BadMatch; 1755f7df2e56Smrg } 175605b261ecSmrg } 175705b261ecSmrg else 175805b261ecSmrg psrcDraw = pdstDraw; 175905b261ecSmrg 176005b261ecSmrg /* Check to see if stuff->bitPlane has exactly ONE good bit set */ 1761f7df2e56Smrg if (stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) || 1762f7df2e56Smrg (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) { 1763f7df2e56Smrg client->errorValue = stuff->bitPlane; 1764f7df2e56Smrg return BadValue; 176505b261ecSmrg } 176605b261ecSmrg 1767f7df2e56Smrg pRgn = 1768f7df2e56Smrg (*pGC->ops->CopyPlane) (psrcDraw, pdstDraw, pGC, stuff->srcX, 1769f7df2e56Smrg stuff->srcY, stuff->width, stuff->height, 1770f7df2e56Smrg stuff->dstX, stuff->dstY, stuff->bitPlane); 1771f7df2e56Smrg if (pGC->graphicsExposures) { 1772f7df2e56Smrg SendGraphicsExpose(client, pRgn, stuff->dstDrawable, X_CopyPlane, 0); 1773f7df2e56Smrg if (pRgn) 1774f7df2e56Smrg RegionDestroy(pRgn); 177505b261ecSmrg } 17766747b715Smrg return Success; 177705b261ecSmrg} 177805b261ecSmrg 177905b261ecSmrgint 178005b261ecSmrgProcPolyPoint(ClientPtr client) 178105b261ecSmrg{ 178205b261ecSmrg int npoint; 178305b261ecSmrg GC *pGC; 178405b261ecSmrg DrawablePtr pDraw; 1785f7df2e56Smrg 178605b261ecSmrg REQUEST(xPolyPointReq); 178705b261ecSmrg 178805b261ecSmrg REQUEST_AT_LEAST_SIZE(xPolyPointReq); 1789f7df2e56Smrg if ((stuff->coordMode != CoordModeOrigin) && 1790f7df2e56Smrg (stuff->coordMode != CoordModePrevious)) { 1791f7df2e56Smrg client->errorValue = stuff->coordMode; 179205b261ecSmrg return BadValue; 179305b261ecSmrg } 1794f7df2e56Smrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 17956747b715Smrg npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyPointReq)); 179605b261ecSmrg if (npoint) 1797f7df2e56Smrg (*pGC->ops->PolyPoint) (pDraw, pGC, stuff->coordMode, npoint, 1798f7df2e56Smrg (xPoint *) &stuff[1]); 17996747b715Smrg return Success; 180005b261ecSmrg} 180105b261ecSmrg 180205b261ecSmrgint 180305b261ecSmrgProcPolyLine(ClientPtr client) 180405b261ecSmrg{ 180505b261ecSmrg int npoint; 180605b261ecSmrg GC *pGC; 180705b261ecSmrg DrawablePtr pDraw; 1808f7df2e56Smrg 180905b261ecSmrg REQUEST(xPolyLineReq); 181005b261ecSmrg 181105b261ecSmrg REQUEST_AT_LEAST_SIZE(xPolyLineReq); 1812f7df2e56Smrg if ((stuff->coordMode != CoordModeOrigin) && 1813f7df2e56Smrg (stuff->coordMode != CoordModePrevious)) { 1814f7df2e56Smrg client->errorValue = stuff->coordMode; 181505b261ecSmrg return BadValue; 181605b261ecSmrg } 18174642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 18186747b715Smrg npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyLineReq)); 181905b261ecSmrg if (npoint > 1) 1820f7df2e56Smrg (*pGC->ops->Polylines) (pDraw, pGC, stuff->coordMode, npoint, 1821f7df2e56Smrg (DDXPointPtr) &stuff[1]); 18226747b715Smrg return Success; 182305b261ecSmrg} 182405b261ecSmrg 182505b261ecSmrgint 182605b261ecSmrgProcPolySegment(ClientPtr client) 182705b261ecSmrg{ 182805b261ecSmrg int nsegs; 182905b261ecSmrg GC *pGC; 183005b261ecSmrg DrawablePtr pDraw; 1831f7df2e56Smrg 183205b261ecSmrg REQUEST(xPolySegmentReq); 183305b261ecSmrg 183405b261ecSmrg REQUEST_AT_LEAST_SIZE(xPolySegmentReq); 18354642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 183605b261ecSmrg nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq); 183705b261ecSmrg if (nsegs & 4) 1838f7df2e56Smrg return BadLength; 183905b261ecSmrg nsegs >>= 3; 184005b261ecSmrg if (nsegs) 1841f7df2e56Smrg (*pGC->ops->PolySegment) (pDraw, pGC, nsegs, (xSegment *) &stuff[1]); 18426747b715Smrg return Success; 184305b261ecSmrg} 184405b261ecSmrg 184505b261ecSmrgint 1846f7df2e56SmrgProcPolyRectangle(ClientPtr client) 184705b261ecSmrg{ 184805b261ecSmrg int nrects; 184905b261ecSmrg GC *pGC; 185005b261ecSmrg DrawablePtr pDraw; 1851f7df2e56Smrg 185205b261ecSmrg REQUEST(xPolyRectangleReq); 185305b261ecSmrg 185405b261ecSmrg REQUEST_AT_LEAST_SIZE(xPolyRectangleReq); 18554642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 185605b261ecSmrg nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq); 185705b261ecSmrg if (nrects & 4) 1858f7df2e56Smrg return BadLength; 185905b261ecSmrg nrects >>= 3; 186005b261ecSmrg if (nrects) 1861f7df2e56Smrg (*pGC->ops->PolyRectangle) (pDraw, pGC, 1862f7df2e56Smrg nrects, (xRectangle *) &stuff[1]); 18636747b715Smrg return Success; 186405b261ecSmrg} 186505b261ecSmrg 186605b261ecSmrgint 186705b261ecSmrgProcPolyArc(ClientPtr client) 186805b261ecSmrg{ 1869f7df2e56Smrg int narcs; 187005b261ecSmrg GC *pGC; 187105b261ecSmrg DrawablePtr pDraw; 1872f7df2e56Smrg 187305b261ecSmrg REQUEST(xPolyArcReq); 187405b261ecSmrg 187505b261ecSmrg REQUEST_AT_LEAST_SIZE(xPolyArcReq); 18764642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 187705b261ecSmrg narcs = (client->req_len << 2) - sizeof(xPolyArcReq); 187805b261ecSmrg if (narcs % sizeof(xArc)) 1879f7df2e56Smrg return BadLength; 188005b261ecSmrg narcs /= sizeof(xArc); 188105b261ecSmrg if (narcs) 1882f7df2e56Smrg (*pGC->ops->PolyArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]); 18836747b715Smrg return Success; 188405b261ecSmrg} 188505b261ecSmrg 188605b261ecSmrgint 188705b261ecSmrgProcFillPoly(ClientPtr client) 188805b261ecSmrg{ 1889f7df2e56Smrg int things; 189005b261ecSmrg GC *pGC; 189105b261ecSmrg DrawablePtr pDraw; 1892f7df2e56Smrg 189305b261ecSmrg REQUEST(xFillPolyReq); 189405b261ecSmrg 189505b261ecSmrg REQUEST_AT_LEAST_SIZE(xFillPolyReq); 1896f7df2e56Smrg if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) && 1897f7df2e56Smrg (stuff->shape != Convex)) { 1898f7df2e56Smrg client->errorValue = stuff->shape; 189905b261ecSmrg return BadValue; 190005b261ecSmrg } 1901f7df2e56Smrg if ((stuff->coordMode != CoordModeOrigin) && 1902f7df2e56Smrg (stuff->coordMode != CoordModePrevious)) { 1903f7df2e56Smrg client->errorValue = stuff->coordMode; 190405b261ecSmrg return BadValue; 190505b261ecSmrg } 190605b261ecSmrg 19074642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 19086747b715Smrg things = bytes_to_int32((client->req_len << 2) - sizeof(xFillPolyReq)); 190905b261ecSmrg if (things) 191005b261ecSmrg (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape, 1911f7df2e56Smrg stuff->coordMode, things, 1912f7df2e56Smrg (DDXPointPtr) &stuff[1]); 19136747b715Smrg return Success; 191405b261ecSmrg} 191505b261ecSmrg 191605b261ecSmrgint 191705b261ecSmrgProcPolyFillRectangle(ClientPtr client) 191805b261ecSmrg{ 1919f7df2e56Smrg int things; 192005b261ecSmrg GC *pGC; 192105b261ecSmrg DrawablePtr pDraw; 1922f7df2e56Smrg 192305b261ecSmrg REQUEST(xPolyFillRectangleReq); 192405b261ecSmrg 192505b261ecSmrg REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq); 19264642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 192705b261ecSmrg things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq); 192805b261ecSmrg if (things & 4) 1929f7df2e56Smrg return BadLength; 193005b261ecSmrg things >>= 3; 193105b261ecSmrg 193205b261ecSmrg if (things) 193305b261ecSmrg (*pGC->ops->PolyFillRect) (pDraw, pGC, things, 1934f7df2e56Smrg (xRectangle *) &stuff[1]); 19356747b715Smrg return Success; 193605b261ecSmrg} 193705b261ecSmrg 193805b261ecSmrgint 193905b261ecSmrgProcPolyFillArc(ClientPtr client) 194005b261ecSmrg{ 1941f7df2e56Smrg int narcs; 194205b261ecSmrg GC *pGC; 194305b261ecSmrg DrawablePtr pDraw; 1944f7df2e56Smrg 194505b261ecSmrg REQUEST(xPolyFillArcReq); 194605b261ecSmrg 194705b261ecSmrg REQUEST_AT_LEAST_SIZE(xPolyFillArcReq); 19484642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 194905b261ecSmrg narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq); 195005b261ecSmrg if (narcs % sizeof(xArc)) 1951f7df2e56Smrg return BadLength; 195205b261ecSmrg narcs /= sizeof(xArc); 195305b261ecSmrg if (narcs) 195405b261ecSmrg (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]); 19556747b715Smrg return Success; 195605b261ecSmrg} 195705b261ecSmrg 195805b261ecSmrg#ifdef MATCH_CLIENT_ENDIAN 195905b261ecSmrg 196005b261ecSmrgint 1961f7df2e56SmrgServerOrder(void) 196205b261ecSmrg{ 1963f7df2e56Smrg int whichbyte = 1; 196405b261ecSmrg 196505b261ecSmrg if (*((char *) &whichbyte)) 1966f7df2e56Smrg return LSBFirst; 196705b261ecSmrg return MSBFirst; 196805b261ecSmrg} 196905b261ecSmrg 197005b261ecSmrg#define ClientOrder(client) ((client)->swapped ? !ServerOrder() : ServerOrder()) 197105b261ecSmrg 197205b261ecSmrgvoid 1973f7df2e56SmrgReformatImage(char *base, int nbytes, int bpp, int order) 197405b261ecSmrg{ 197505b261ecSmrg switch (bpp) { 1976f7df2e56Smrg case 1: /* yuck */ 1977f7df2e56Smrg if (BITMAP_BIT_ORDER != order) 1978f7df2e56Smrg BitOrderInvert((unsigned char *) base, nbytes); 197905b261ecSmrg#if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8 1980f7df2e56Smrg ReformatImage(base, nbytes, BITMAP_SCANLINE_UNIT, order); 198105b261ecSmrg#endif 1982f7df2e56Smrg break; 198305b261ecSmrg case 4: 1984f7df2e56Smrg break; /* yuck */ 198505b261ecSmrg case 8: 1986f7df2e56Smrg break; 198705b261ecSmrg case 16: 1988f7df2e56Smrg if (IMAGE_BYTE_ORDER != order) 1989f7df2e56Smrg TwoByteSwap((unsigned char *) base, nbytes); 1990f7df2e56Smrg break; 199105b261ecSmrg case 32: 1992f7df2e56Smrg if (IMAGE_BYTE_ORDER != order) 1993f7df2e56Smrg FourByteSwap((unsigned char *) base, nbytes); 1994f7df2e56Smrg break; 199505b261ecSmrg } 199605b261ecSmrg} 199705b261ecSmrg#else 199805b261ecSmrg#define ReformatImage(b,n,bpp,o) 199905b261ecSmrg#endif 200005b261ecSmrg 200105b261ecSmrg/* 64-bit server notes: the protocol restricts padding of images to 200205b261ecSmrg * 8-, 16-, or 32-bits. We would like to have 64-bits for the server 200305b261ecSmrg * to use internally. Removes need for internal alignment checking. 200405b261ecSmrg * All of the PutImage functions could be changed individually, but 200505b261ecSmrg * as currently written, they call other routines which require things 200605b261ecSmrg * to be 64-bit padded on scanlines, so we changed things here. 200705b261ecSmrg * If an image would be padded differently for 64- versus 32-, then 200805b261ecSmrg * copy each scanline to a 64-bit padded scanline. 200905b261ecSmrg * Also, we need to make sure that the image is aligned on a 64-bit 201005b261ecSmrg * boundary, even if the scanlines are padded to our satisfaction. 201105b261ecSmrg */ 201205b261ecSmrgint 201305b261ecSmrgProcPutImage(ClientPtr client) 201405b261ecSmrg{ 201505b261ecSmrg GC *pGC; 201605b261ecSmrg DrawablePtr pDraw; 2017f7df2e56Smrg long length; /* length of scanline server padded */ 2018f7df2e56Smrg long lengthProto; /* length of scanline protocol padded */ 2019f7df2e56Smrg char *tmpImage; 2020f7df2e56Smrg 202105b261ecSmrg REQUEST(xPutImageReq); 202205b261ecSmrg 202305b261ecSmrg REQUEST_AT_LEAST_SIZE(xPutImageReq); 20244642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 2025f7df2e56Smrg if (stuff->format == XYBitmap) { 202605b261ecSmrg if ((stuff->depth != 1) || 2027f7df2e56Smrg (stuff->leftPad >= (unsigned int) screenInfo.bitmapScanlinePad)) 202805b261ecSmrg return BadMatch; 2029f7df2e56Smrg length = BitmapBytePad(stuff->width + stuff->leftPad); 203005b261ecSmrg } 2031f7df2e56Smrg else if (stuff->format == XYPixmap) { 2032f7df2e56Smrg if ((pDraw->depth != stuff->depth) || 2033f7df2e56Smrg (stuff->leftPad >= (unsigned int) screenInfo.bitmapScanlinePad)) 203405b261ecSmrg return BadMatch; 2035f7df2e56Smrg length = BitmapBytePad(stuff->width + stuff->leftPad); 2036f7df2e56Smrg length *= stuff->depth; 203705b261ecSmrg } 2038f7df2e56Smrg else if (stuff->format == ZPixmap) { 203905b261ecSmrg if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0)) 204005b261ecSmrg return BadMatch; 2041f7df2e56Smrg length = PixmapBytePad(stuff->width, stuff->depth); 204205b261ecSmrg } 2043f7df2e56Smrg else { 2044f7df2e56Smrg client->errorValue = stuff->format; 204505b261ecSmrg return BadValue; 204605b261ecSmrg } 204705b261ecSmrg 2048f7df2e56Smrg tmpImage = (char *) &stuff[1]; 204905b261ecSmrg lengthProto = length; 20500b0d8713Smrg 2051f7df2e56Smrg if (stuff->height != 0 && lengthProto >= (INT32_MAX / stuff->height)) 20520b0d8713Smrg return BadLength; 2053f7df2e56Smrg 20546747b715Smrg if ((bytes_to_int32(lengthProto * stuff->height) + 2055f7df2e56Smrg bytes_to_int32(sizeof(xPutImageReq))) != client->req_len) 2056f7df2e56Smrg return BadLength; 2057f7df2e56Smrg 2058f7df2e56Smrg ReformatImage(tmpImage, lengthProto * stuff->height, 2059f7df2e56Smrg stuff->format == ZPixmap ? BitsPerPixel(stuff->depth) : 1, 2060f7df2e56Smrg ClientOrder(client)); 206105b261ecSmrg 206205b261ecSmrg (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY, 2063f7df2e56Smrg stuff->width, stuff->height, 2064f7df2e56Smrg stuff->leftPad, stuff->format, tmpImage); 206505b261ecSmrg 2066f7df2e56Smrg return Success; 206705b261ecSmrg} 206805b261ecSmrg 206905b261ecSmrgstatic int 2070f7df2e56SmrgDoGetImage(ClientPtr client, int format, Drawable drawable, 2071f7df2e56Smrg int x, int y, int width, int height, 2072f7df2e56Smrg Mask planemask) 207305b261ecSmrg{ 2074f7df2e56Smrg DrawablePtr pDraw, pBoundingDraw; 2075f7df2e56Smrg int nlines, linesPerBuf, rc; 2076f7df2e56Smrg int linesDone; 2077f7df2e56Smrg 20786747b715Smrg /* coordinates relative to the bounding drawable */ 2079f7df2e56Smrg int relx, rely; 2080f7df2e56Smrg long widthBytesLine, length; 2081f7df2e56Smrg Mask plane = 0; 2082f7df2e56Smrg char *pBuf; 2083f7df2e56Smrg xGetImageReply xgi; 208405b261ecSmrg RegionPtr pVisibleRegion = NULL; 208505b261ecSmrg 2086f7df2e56Smrg if ((format != XYPixmap) && (format != ZPixmap)) { 2087f7df2e56Smrg client->errorValue = format; 20886747b715Smrg return BadValue; 208905b261ecSmrg } 209005b261ecSmrg rc = dixLookupDrawable(&pDraw, drawable, client, 0, DixReadAccess); 209105b261ecSmrg if (rc != Success) 2092f7df2e56Smrg return rc; 209305b261ecSmrg 20946747b715Smrg memset(&xgi, 0, sizeof(xGetImageReply)); 20956747b715Smrg 20966747b715Smrg relx = x; 20976747b715Smrg rely = y; 20986747b715Smrg 2099f7df2e56Smrg if (pDraw->type == DRAWABLE_WINDOW) { 2100f7df2e56Smrg WindowPtr pWin = (WindowPtr) pDraw; 2101f7df2e56Smrg 2102f7df2e56Smrg /* "If the drawable is a window, the window must be viewable ... or a 2103f7df2e56Smrg * BadMatch error results" */ 2104f7df2e56Smrg if (!pWin->viewable) 2105f7df2e56Smrg return BadMatch; 21066747b715Smrg 2107f7df2e56Smrg /* If the drawable is a window, the rectangle must be contained within 2108f7df2e56Smrg * its bounds (including the border). */ 2109f7df2e56Smrg if (x < -wBorderWidth(pWin) || 2110f7df2e56Smrg x + width > wBorderWidth(pWin) + (int) pDraw->width || 2111f7df2e56Smrg y < -wBorderWidth(pWin) || 2112f7df2e56Smrg y + height > wBorderWidth(pWin) + (int) pDraw->height) 2113f7df2e56Smrg return BadMatch; 21146747b715Smrg 2115f7df2e56Smrg relx += pDraw->x; 2116f7df2e56Smrg rely += pDraw->y; 21176747b715Smrg 2118f7df2e56Smrg if (pDraw->pScreen->GetWindowPixmap) { 2119f7df2e56Smrg PixmapPtr pPix = (*pDraw->pScreen->GetWindowPixmap) (pWin); 21206747b715Smrg 2121f7df2e56Smrg pBoundingDraw = &pPix->drawable; 21226747b715Smrg#ifdef COMPOSITE 2123f7df2e56Smrg relx -= pPix->screen_x; 2124f7df2e56Smrg rely -= pPix->screen_y; 21256747b715Smrg#endif 2126f7df2e56Smrg } 2127f7df2e56Smrg else { 2128f7df2e56Smrg pBoundingDraw = (DrawablePtr) pDraw->pScreen->root; 2129f7df2e56Smrg } 21306747b715Smrg 2131f7df2e56Smrg xgi.visual = wVisual(pWin); 213205b261ecSmrg } 2133f7df2e56Smrg else { 2134f7df2e56Smrg pBoundingDraw = pDraw; 2135f7df2e56Smrg xgi.visual = None; 213605b261ecSmrg } 213705b261ecSmrg 21386747b715Smrg /* "If the drawable is a pixmap, the given rectangle must be wholly 21396747b715Smrg * contained within the pixmap, or a BadMatch error results. If the 21406747b715Smrg * drawable is a window [...] it must be the case that if there were no 21416747b715Smrg * inferiors or overlapping windows, the specified rectangle of the window 21426747b715Smrg * would be fully visible on the screen and wholly contained within the 21436747b715Smrg * outside edges of the window, or a BadMatch error results." 21446747b715Smrg * 21456747b715Smrg * We relax the window case slightly to mean that the rectangle must exist 21466747b715Smrg * within the bounds of the window's backing pixmap. In particular, this 21476747b715Smrg * means that a GetImage request may succeed or fail with BadMatch depending 21486747b715Smrg * on whether any of its ancestor windows are redirected. */ 2149f7df2e56Smrg if (relx < 0 || relx + width > (int) pBoundingDraw->width || 2150f7df2e56Smrg rely < 0 || rely + height > (int) pBoundingDraw->height) 2151f7df2e56Smrg return BadMatch; 21526747b715Smrg 215305b261ecSmrg xgi.type = X_Reply; 215405b261ecSmrg xgi.sequenceNumber = client->sequence; 215505b261ecSmrg xgi.depth = pDraw->depth; 2156f7df2e56Smrg if (format == ZPixmap) { 2157f7df2e56Smrg widthBytesLine = PixmapBytePad(width, pDraw->depth); 2158f7df2e56Smrg length = widthBytesLine * height; 215905b261ecSmrg 216005b261ecSmrg } 2161f7df2e56Smrg else { 2162f7df2e56Smrg widthBytesLine = BitmapBytePad(width); 2163f7df2e56Smrg plane = ((Mask) 1) << (pDraw->depth - 1); 2164f7df2e56Smrg /* only planes asked for */ 2165f7df2e56Smrg length = widthBytesLine * height * 2166f7df2e56Smrg Ones(planemask & (plane | (plane - 1))); 216705b261ecSmrg 216805b261ecSmrg } 216905b261ecSmrg 217005b261ecSmrg xgi.length = length; 217105b261ecSmrg 2172f7df2e56Smrg xgi.length = bytes_to_int32(xgi.length); 2173f7df2e56Smrg if (widthBytesLine == 0 || height == 0) 2174f7df2e56Smrg linesPerBuf = 0; 2175f7df2e56Smrg else if (widthBytesLine >= IMAGE_BUFSIZE) 2176f7df2e56Smrg linesPerBuf = 1; 2177f7df2e56Smrg else { 2178f7df2e56Smrg linesPerBuf = IMAGE_BUFSIZE / widthBytesLine; 2179f7df2e56Smrg if (linesPerBuf > height) 2180f7df2e56Smrg linesPerBuf = height; 2181f7df2e56Smrg } 2182f7df2e56Smrg length = linesPerBuf * widthBytesLine; 2183f7df2e56Smrg if (linesPerBuf < height) { 2184f7df2e56Smrg /* we have to make sure intermediate buffers don't need padding */ 2185f7df2e56Smrg while ((linesPerBuf > 1) && 2186f7df2e56Smrg (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD) - 1))) { 2187f7df2e56Smrg linesPerBuf--; 2188f7df2e56Smrg length -= widthBytesLine; 2189f7df2e56Smrg } 2190f7df2e56Smrg while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD) - 1)) { 2191f7df2e56Smrg linesPerBuf++; 2192f7df2e56Smrg length += widthBytesLine; 2193f7df2e56Smrg } 219405b261ecSmrg } 2195f7df2e56Smrg if (!(pBuf = calloc(1, length))) 2196f7df2e56Smrg return BadAlloc; 2197f7df2e56Smrg WriteReplyToClient(client, sizeof(xGetImageReply), &xgi); 219805b261ecSmrg 21994e185dc0Smrg if (pDraw->type == DRAWABLE_WINDOW) { 22007e31ba66Smrg pVisibleRegion = &((WindowPtr) pDraw)->borderClip; 22014e185dc0Smrg pDraw->pScreen->SourceValidate(pDraw, x, y, width, height, 22024e185dc0Smrg IncludeInferiors); 22034e185dc0Smrg } 2204f7df2e56Smrg 2205f7df2e56Smrg if (linesPerBuf == 0) { 2206f7df2e56Smrg /* nothing to do */ 2207f7df2e56Smrg } 2208f7df2e56Smrg else if (format == ZPixmap) { 220905b261ecSmrg linesDone = 0; 2210f7df2e56Smrg while (height - linesDone > 0) { 2211f7df2e56Smrg nlines = min(linesPerBuf, height - linesDone); 2212f7df2e56Smrg (*pDraw->pScreen->GetImage) (pDraw, 2213f7df2e56Smrg x, 2214f7df2e56Smrg y + linesDone, 2215f7df2e56Smrg width, 2216f7df2e56Smrg nlines, 2217f7df2e56Smrg format, planemask, (void *) pBuf); 2218f7df2e56Smrg if (pVisibleRegion) 2219f7df2e56Smrg XaceCensorImage(client, pVisibleRegion, widthBytesLine, 2220f7df2e56Smrg pDraw, x, y + linesDone, width, 2221f7df2e56Smrg nlines, format, pBuf); 2222f7df2e56Smrg 2223f7df2e56Smrg /* Note that this is NOT a call to WriteSwappedDataToClient, 222405b261ecSmrg as we do NOT byte swap */ 2225f7df2e56Smrg ReformatImage(pBuf, (int) (nlines * widthBytesLine), 2226f7df2e56Smrg BitsPerPixel(pDraw->depth), ClientOrder(client)); 2227f7df2e56Smrg 2228f7df2e56Smrg WriteToClient(client, (int) (nlines * widthBytesLine), pBuf); 2229f7df2e56Smrg linesDone += nlines; 223005b261ecSmrg } 223105b261ecSmrg } 2232f7df2e56Smrg else { /* XYPixmap */ 2233f7df2e56Smrg 2234f7df2e56Smrg for (; plane; plane >>= 1) { 2235f7df2e56Smrg if (planemask & plane) { 2236f7df2e56Smrg linesDone = 0; 2237f7df2e56Smrg while (height - linesDone > 0) { 2238f7df2e56Smrg nlines = min(linesPerBuf, height - linesDone); 2239f7df2e56Smrg (*pDraw->pScreen->GetImage) (pDraw, 2240f7df2e56Smrg x, 2241f7df2e56Smrg y + linesDone, 2242f7df2e56Smrg width, 2243f7df2e56Smrg nlines, 2244f7df2e56Smrg format, plane, (void *) pBuf); 2245f7df2e56Smrg if (pVisibleRegion) 2246f7df2e56Smrg XaceCensorImage(client, pVisibleRegion, 2247f7df2e56Smrg widthBytesLine, 2248f7df2e56Smrg pDraw, x, y + linesDone, width, 2249f7df2e56Smrg nlines, format, pBuf); 2250f7df2e56Smrg 2251f7df2e56Smrg /* Note: NOT a call to WriteSwappedDataToClient, 2252f7df2e56Smrg as we do NOT byte swap */ 2253f7df2e56Smrg ReformatImage(pBuf, (int) (nlines * widthBytesLine), 2254f7df2e56Smrg 1, ClientOrder(client)); 2255f7df2e56Smrg 2256f7df2e56Smrg WriteToClient(client, (int)(nlines * widthBytesLine), pBuf); 2257f7df2e56Smrg linesDone += nlines; 2258f7df2e56Smrg } 225905b261ecSmrg } 2260f7df2e56Smrg } 226105b261ecSmrg } 2262f7df2e56Smrg free(pBuf); 22636747b715Smrg return Success; 226405b261ecSmrg} 226505b261ecSmrg 226605b261ecSmrgint 226705b261ecSmrgProcGetImage(ClientPtr client) 226805b261ecSmrg{ 226905b261ecSmrg REQUEST(xGetImageReq); 227005b261ecSmrg 227105b261ecSmrg REQUEST_SIZE_MATCH(xGetImageReq); 227205b261ecSmrg 227305b261ecSmrg return DoGetImage(client, stuff->format, stuff->drawable, 2274f7df2e56Smrg stuff->x, stuff->y, 2275f7df2e56Smrg (int) stuff->width, (int) stuff->height, 2276f7df2e56Smrg stuff->planeMask); 227705b261ecSmrg} 227805b261ecSmrg 227905b261ecSmrgint 228005b261ecSmrgProcPolyText(ClientPtr client) 228105b261ecSmrg{ 2282f7df2e56Smrg int err; 2283f7df2e56Smrg 228405b261ecSmrg REQUEST(xPolyTextReq); 228505b261ecSmrg DrawablePtr pDraw; 228605b261ecSmrg GC *pGC; 228705b261ecSmrg 228805b261ecSmrg REQUEST_AT_LEAST_SIZE(xPolyTextReq); 22894642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 229005b261ecSmrg 229105b261ecSmrg err = PolyText(client, 2292f7df2e56Smrg pDraw, 2293f7df2e56Smrg pGC, 2294f7df2e56Smrg (unsigned char *) &stuff[1], 2295f7df2e56Smrg ((unsigned char *) stuff) + (client->req_len << 2), 2296f7df2e56Smrg stuff->x, stuff->y, stuff->reqType, stuff->drawable); 2297f7df2e56Smrg 2298f7df2e56Smrg if (err == Success) { 2299f7df2e56Smrg return Success; 230005b261ecSmrg } 230105b261ecSmrg else 2302f7df2e56Smrg return err; 230305b261ecSmrg} 230405b261ecSmrg 230505b261ecSmrgint 230605b261ecSmrgProcImageText8(ClientPtr client) 230705b261ecSmrg{ 2308f7df2e56Smrg int err; 230905b261ecSmrg DrawablePtr pDraw; 231005b261ecSmrg GC *pGC; 231105b261ecSmrg 231205b261ecSmrg REQUEST(xImageTextReq); 231305b261ecSmrg 231405b261ecSmrg REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars); 23154642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 231605b261ecSmrg 231705b261ecSmrg err = ImageText(client, 2318f7df2e56Smrg pDraw, 2319f7df2e56Smrg pGC, 2320f7df2e56Smrg stuff->nChars, 2321f7df2e56Smrg (unsigned char *) &stuff[1], 2322f7df2e56Smrg stuff->x, stuff->y, stuff->reqType, stuff->drawable); 2323f7df2e56Smrg 2324f7df2e56Smrg if (err == Success) { 2325f7df2e56Smrg return Success; 232605b261ecSmrg } 232705b261ecSmrg else 2328f7df2e56Smrg return err; 232905b261ecSmrg} 233005b261ecSmrg 233105b261ecSmrgint 233205b261ecSmrgProcImageText16(ClientPtr client) 233305b261ecSmrg{ 2334f7df2e56Smrg int err; 233505b261ecSmrg DrawablePtr pDraw; 233605b261ecSmrg GC *pGC; 233705b261ecSmrg 233805b261ecSmrg REQUEST(xImageTextReq); 233905b261ecSmrg 234005b261ecSmrg REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1); 23414642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 234205b261ecSmrg 234305b261ecSmrg err = ImageText(client, 2344f7df2e56Smrg pDraw, 2345f7df2e56Smrg pGC, 2346f7df2e56Smrg stuff->nChars, 2347f7df2e56Smrg (unsigned char *) &stuff[1], 2348f7df2e56Smrg stuff->x, stuff->y, stuff->reqType, stuff->drawable); 2349f7df2e56Smrg 2350f7df2e56Smrg if (err == Success) { 2351f7df2e56Smrg return Success; 235205b261ecSmrg } 235305b261ecSmrg else 2354f7df2e56Smrg return err; 235505b261ecSmrg} 235605b261ecSmrg 235705b261ecSmrgint 235805b261ecSmrgProcCreateColormap(ClientPtr client) 235905b261ecSmrg{ 2360f7df2e56Smrg VisualPtr pVisual; 2361f7df2e56Smrg ColormapPtr pmap; 2362f7df2e56Smrg Colormap mid; 2363f7df2e56Smrg WindowPtr pWin; 236405b261ecSmrg ScreenPtr pScreen; 2365f7df2e56Smrg 236605b261ecSmrg REQUEST(xCreateColormapReq); 236705b261ecSmrg int i, result; 236805b261ecSmrg 236905b261ecSmrg REQUEST_SIZE_MATCH(xCreateColormapReq); 237005b261ecSmrg 2371f7df2e56Smrg if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll)) { 2372f7df2e56Smrg client->errorValue = stuff->alloc; 23736747b715Smrg return BadValue; 237405b261ecSmrg } 237505b261ecSmrg mid = stuff->mid; 237605b261ecSmrg LEGAL_NEW_RESOURCE(mid, client); 23774642e01fSmrg result = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 237805b261ecSmrg if (result != Success) 237905b261ecSmrg return result; 238005b261ecSmrg 238105b261ecSmrg pScreen = pWin->drawable.pScreen; 238205b261ecSmrg for (i = 0, pVisual = pScreen->visuals; 2383f7df2e56Smrg i < pScreen->numVisuals; i++, pVisual++) { 2384f7df2e56Smrg if (pVisual->vid != stuff->visual) 2385f7df2e56Smrg continue; 2386f7df2e56Smrg return CreateColormap(mid, pScreen, pVisual, &pmap, 2387f7df2e56Smrg (int) stuff->alloc, client->index); 238805b261ecSmrg } 238905b261ecSmrg client->errorValue = stuff->visual; 23906747b715Smrg return BadMatch; 239105b261ecSmrg} 239205b261ecSmrg 239305b261ecSmrgint 239405b261ecSmrgProcFreeColormap(ClientPtr client) 239505b261ecSmrg{ 239605b261ecSmrg ColormapPtr pmap; 23974642e01fSmrg int rc; 2398f7df2e56Smrg 239905b261ecSmrg REQUEST(xResourceReq); 240005b261ecSmrg 240105b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 2402f7df2e56Smrg rc = dixLookupResourceByType((void **) &pmap, stuff->id, RT_COLORMAP, 2403f7df2e56Smrg client, DixDestroyAccess); 2404f7df2e56Smrg if (rc == Success) { 2405f7df2e56Smrg /* Freeing a default colormap is a no-op */ 2406f7df2e56Smrg if (!(pmap->flags & IsDefault)) 2407f7df2e56Smrg FreeResource(stuff->id, RT_NONE); 2408f7df2e56Smrg return Success; 240905b261ecSmrg } 2410f7df2e56Smrg else { 2411f7df2e56Smrg client->errorValue = stuff->id; 2412f7df2e56Smrg return rc; 241305b261ecSmrg } 241405b261ecSmrg} 241505b261ecSmrg 241605b261ecSmrgint 241705b261ecSmrgProcCopyColormapAndFree(ClientPtr client) 241805b261ecSmrg{ 2419f7df2e56Smrg Colormap mid; 2420f7df2e56Smrg ColormapPtr pSrcMap; 2421f7df2e56Smrg 242205b261ecSmrg REQUEST(xCopyColormapAndFreeReq); 24234642e01fSmrg int rc; 242405b261ecSmrg 242505b261ecSmrg REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq); 242605b261ecSmrg mid = stuff->mid; 242705b261ecSmrg LEGAL_NEW_RESOURCE(mid, client); 2428f7df2e56Smrg rc = dixLookupResourceByType((void **) &pSrcMap, stuff->srcCmap, 2429f7df2e56Smrg RT_COLORMAP, client, 2430f7df2e56Smrg DixReadAccess | DixRemoveAccess); 24314642e01fSmrg if (rc == Success) 2432f7df2e56Smrg return CopyColormapAndFree(mid, pSrcMap, client->index); 24336747b715Smrg client->errorValue = stuff->srcCmap; 24346747b715Smrg return rc; 243505b261ecSmrg} 243605b261ecSmrg 243705b261ecSmrgint 243805b261ecSmrgProcInstallColormap(ClientPtr client) 243905b261ecSmrg{ 244005b261ecSmrg ColormapPtr pcmp; 24414642e01fSmrg int rc; 2442f7df2e56Smrg 244305b261ecSmrg REQUEST(xResourceReq); 244405b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 24454642e01fSmrg 2446f7df2e56Smrg rc = dixLookupResourceByType((void **) &pcmp, stuff->id, RT_COLORMAP, 2447f7df2e56Smrg client, DixInstallAccess); 24484642e01fSmrg if (rc != Success) 2449f7df2e56Smrg goto out; 24504642e01fSmrg 24514642e01fSmrg rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess); 24526747b715Smrg if (rc != Success) { 2453f7df2e56Smrg if (rc == BadValue) 2454f7df2e56Smrg rc = BadColor; 2455f7df2e56Smrg goto out; 24566747b715Smrg } 24574642e01fSmrg 24584642e01fSmrg (*(pcmp->pScreen->InstallColormap)) (pcmp); 24596747b715Smrg return Success; 24604642e01fSmrg 2461f7df2e56Smrg out: 24624642e01fSmrg client->errorValue = stuff->id; 24636747b715Smrg return rc; 246405b261ecSmrg} 246505b261ecSmrg 246605b261ecSmrgint 246705b261ecSmrgProcUninstallColormap(ClientPtr client) 246805b261ecSmrg{ 246905b261ecSmrg ColormapPtr pcmp; 24704642e01fSmrg int rc; 2471f7df2e56Smrg 247205b261ecSmrg REQUEST(xResourceReq); 247305b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 24744642e01fSmrg 2475f7df2e56Smrg rc = dixLookupResourceByType((void **) &pcmp, stuff->id, RT_COLORMAP, 2476f7df2e56Smrg client, DixUninstallAccess); 24774642e01fSmrg if (rc != Success) 2478f7df2e56Smrg goto out; 24794642e01fSmrg 24804642e01fSmrg rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess); 24816747b715Smrg if (rc != Success) { 2482f7df2e56Smrg if (rc == BadValue) 2483f7df2e56Smrg rc = BadColor; 2484f7df2e56Smrg goto out; 24856747b715Smrg } 24864642e01fSmrg 2487f7df2e56Smrg if (pcmp->mid != pcmp->pScreen->defColormap) 2488f7df2e56Smrg (*(pcmp->pScreen->UninstallColormap)) (pcmp); 24896747b715Smrg return Success; 24904642e01fSmrg 2491f7df2e56Smrg out: 24924642e01fSmrg client->errorValue = stuff->id; 24936747b715Smrg return rc; 249405b261ecSmrg} 249505b261ecSmrg 249605b261ecSmrgint 249705b261ecSmrgProcListInstalledColormaps(ClientPtr client) 249805b261ecSmrg{ 2499f7df2e56Smrg xListInstalledColormapsReply *preply; 250005b261ecSmrg int nummaps, rc; 250105b261ecSmrg WindowPtr pWin; 2502f7df2e56Smrg 250305b261ecSmrg REQUEST(xResourceReq); 250405b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 25054642e01fSmrg 25064642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess); 250705b261ecSmrg if (rc != Success) 2508f7df2e56Smrg return rc; 25094642e01fSmrg 25104642e01fSmrg rc = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen, 2511f7df2e56Smrg DixGetAttrAccess); 25124642e01fSmrg if (rc != Success) 2513f7df2e56Smrg return rc; 251405b261ecSmrg 25156747b715Smrg preply = malloc(sizeof(xListInstalledColormapsReply) + 2516f7df2e56Smrg pWin->drawable.pScreen->maxInstalledCmaps * 2517f7df2e56Smrg sizeof(Colormap)); 2518f7df2e56Smrg if (!preply) 25196747b715Smrg return BadAlloc; 252005b261ecSmrg 252105b261ecSmrg preply->type = X_Reply; 252205b261ecSmrg preply->sequenceNumber = client->sequence; 252305b261ecSmrg nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps) 2524f7df2e56Smrg (pWin->drawable.pScreen, (Colormap *) &preply[1]); 252505b261ecSmrg preply->nColormaps = nummaps; 252605b261ecSmrg preply->length = nummaps; 2527f7df2e56Smrg WriteReplyToClient(client, sizeof(xListInstalledColormapsReply), preply); 252805b261ecSmrg client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; 252905b261ecSmrg WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]); 25306747b715Smrg free(preply); 25316747b715Smrg return Success; 253205b261ecSmrg} 253305b261ecSmrg 253405b261ecSmrgint 2535f7df2e56SmrgProcAllocColor(ClientPtr client) 253605b261ecSmrg{ 253705b261ecSmrg ColormapPtr pmap; 25384642e01fSmrg int rc; 2539f7df2e56Smrg 254005b261ecSmrg REQUEST(xAllocColorReq); 254105b261ecSmrg 254205b261ecSmrg REQUEST_SIZE_MATCH(xAllocColorReq); 2543f7df2e56Smrg rc = dixLookupResourceByType((void **) &pmap, stuff->cmap, RT_COLORMAP, 2544f7df2e56Smrg client, DixAddAccess); 2545f7df2e56Smrg if (rc == Success) { 2546f7df2e56Smrg xAllocColorReply acr = { 2547f7df2e56Smrg .type = X_Reply, 2548f7df2e56Smrg .sequenceNumber = client->sequence, 2549f7df2e56Smrg .length = 0, 2550f7df2e56Smrg .red = stuff->red, 2551f7df2e56Smrg .green = stuff->green, 2552f7df2e56Smrg .blue = stuff->blue, 2553f7df2e56Smrg .pixel = 0 2554f7df2e56Smrg }; 2555f7df2e56Smrg if ((rc = AllocColor(pmap, &acr.red, &acr.green, &acr.blue, 2556f7df2e56Smrg &acr.pixel, client->index))) 2557f7df2e56Smrg return rc; 255805b261ecSmrg#ifdef PANORAMIX 2559f7df2e56Smrg if (noPanoramiXExtension || !pmap->pScreen->myNum) 256005b261ecSmrg#endif 2561f7df2e56Smrg WriteReplyToClient(client, sizeof(xAllocColorReply), &acr); 2562f7df2e56Smrg return Success; 256305b261ecSmrg 256405b261ecSmrg } 2565f7df2e56Smrg else { 256605b261ecSmrg client->errorValue = stuff->cmap; 25676747b715Smrg return rc; 256805b261ecSmrg } 256905b261ecSmrg} 257005b261ecSmrg 257105b261ecSmrgint 2572f7df2e56SmrgProcAllocNamedColor(ClientPtr client) 257305b261ecSmrg{ 257405b261ecSmrg ColormapPtr pcmp; 25754642e01fSmrg int rc; 2576f7df2e56Smrg 257705b261ecSmrg REQUEST(xAllocNamedColorReq); 257805b261ecSmrg 257905b261ecSmrg REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes); 2580f7df2e56Smrg rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, 2581f7df2e56Smrg client, DixAddAccess); 2582f7df2e56Smrg if (rc == Success) { 2583f7df2e56Smrg xAllocNamedColorReply ancr = { 2584f7df2e56Smrg .type = X_Reply, 2585f7df2e56Smrg .sequenceNumber = client->sequence, 2586f7df2e56Smrg .length = 0 2587f7df2e56Smrg }; 2588f7df2e56Smrg if (OsLookupColor 2589f7df2e56Smrg (pcmp->pScreen->myNum, (char *) &stuff[1], stuff->nbytes, 2590f7df2e56Smrg &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue)) { 2591f7df2e56Smrg ancr.screenRed = ancr.exactRed; 2592f7df2e56Smrg ancr.screenGreen = ancr.exactGreen; 2593f7df2e56Smrg ancr.screenBlue = ancr.exactBlue; 2594f7df2e56Smrg ancr.pixel = 0; 2595f7df2e56Smrg if ((rc = AllocColor(pcmp, 2596f7df2e56Smrg &ancr.screenRed, &ancr.screenGreen, 2597f7df2e56Smrg &ancr.screenBlue, &ancr.pixel, client->index))) 2598f7df2e56Smrg return rc; 259905b261ecSmrg#ifdef PANORAMIX 2600f7df2e56Smrg if (noPanoramiXExtension || !pcmp->pScreen->myNum) 260105b261ecSmrg#endif 2602f7df2e56Smrg WriteReplyToClient(client, sizeof(xAllocNamedColorReply), 2603f7df2e56Smrg &ancr); 2604f7df2e56Smrg return Success; 2605f7df2e56Smrg } 2606f7df2e56Smrg else 2607f7df2e56Smrg return BadName; 2608f7df2e56Smrg 260905b261ecSmrg } 2610f7df2e56Smrg else { 261105b261ecSmrg client->errorValue = stuff->cmap; 26126747b715Smrg return rc; 261305b261ecSmrg } 261405b261ecSmrg} 261505b261ecSmrg 261605b261ecSmrgint 2617f7df2e56SmrgProcAllocColorCells(ClientPtr client) 261805b261ecSmrg{ 261905b261ecSmrg ColormapPtr pcmp; 26204642e01fSmrg int rc; 2621f7df2e56Smrg 262205b261ecSmrg REQUEST(xAllocColorCellsReq); 262305b261ecSmrg 262405b261ecSmrg REQUEST_SIZE_MATCH(xAllocColorCellsReq); 2625f7df2e56Smrg rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, 2626f7df2e56Smrg client, DixAddAccess); 2627f7df2e56Smrg if (rc == Success) { 2628f7df2e56Smrg int npixels, nmasks; 2629f7df2e56Smrg long length; 2630f7df2e56Smrg Pixel *ppixels, *pmasks; 2631f7df2e56Smrg 2632f7df2e56Smrg npixels = stuff->colors; 2633f7df2e56Smrg if (!npixels) { 2634f7df2e56Smrg client->errorValue = npixels; 2635f7df2e56Smrg return BadValue; 2636f7df2e56Smrg } 2637f7df2e56Smrg if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) { 2638f7df2e56Smrg client->errorValue = stuff->contiguous; 2639f7df2e56Smrg return BadValue; 2640f7df2e56Smrg } 2641f7df2e56Smrg nmasks = stuff->planes; 2642f7df2e56Smrg length = ((long) npixels + (long) nmasks) * sizeof(Pixel); 2643f7df2e56Smrg ppixels = malloc(length); 2644f7df2e56Smrg if (!ppixels) 26456747b715Smrg return BadAlloc; 2646f7df2e56Smrg pmasks = ppixels + npixels; 2647f7df2e56Smrg 2648f7df2e56Smrg if ((rc = AllocColorCells(client->index, pcmp, npixels, nmasks, 2649f7df2e56Smrg (Bool) stuff->contiguous, ppixels, pmasks))) { 2650f7df2e56Smrg free(ppixels); 2651f7df2e56Smrg return rc; 2652f7df2e56Smrg } 265305b261ecSmrg#ifdef PANORAMIX 2654f7df2e56Smrg if (noPanoramiXExtension || !pcmp->pScreen->myNum) 265505b261ecSmrg#endif 2656f7df2e56Smrg { 2657f7df2e56Smrg xAllocColorCellsReply accr = { 2658f7df2e56Smrg .type = X_Reply, 2659f7df2e56Smrg .sequenceNumber = client->sequence, 2660f7df2e56Smrg .length = bytes_to_int32(length), 2661f7df2e56Smrg .nPixels = npixels, 2662f7df2e56Smrg .nMasks = nmasks 2663f7df2e56Smrg }; 2664f7df2e56Smrg WriteReplyToClient(client, sizeof(xAllocColorCellsReply), &accr); 2665f7df2e56Smrg client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; 2666f7df2e56Smrg WriteSwappedDataToClient(client, length, ppixels); 2667f7df2e56Smrg } 2668f7df2e56Smrg free(ppixels); 26696747b715Smrg return Success; 267005b261ecSmrg } 2671f7df2e56Smrg else { 267205b261ecSmrg client->errorValue = stuff->cmap; 26736747b715Smrg return rc; 267405b261ecSmrg } 267505b261ecSmrg} 267605b261ecSmrg 267705b261ecSmrgint 267805b261ecSmrgProcAllocColorPlanes(ClientPtr client) 267905b261ecSmrg{ 268005b261ecSmrg ColormapPtr pcmp; 26814642e01fSmrg int rc; 2682f7df2e56Smrg 268305b261ecSmrg REQUEST(xAllocColorPlanesReq); 268405b261ecSmrg 268505b261ecSmrg REQUEST_SIZE_MATCH(xAllocColorPlanesReq); 2686f7df2e56Smrg rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, 2687f7df2e56Smrg client, DixAddAccess); 2688f7df2e56Smrg if (rc == Success) { 2689f7df2e56Smrg xAllocColorPlanesReply acpr; 2690f7df2e56Smrg int npixels; 2691f7df2e56Smrg long length; 2692f7df2e56Smrg Pixel *ppixels; 2693f7df2e56Smrg 2694f7df2e56Smrg npixels = stuff->colors; 2695f7df2e56Smrg if (!npixels) { 2696f7df2e56Smrg client->errorValue = npixels; 2697f7df2e56Smrg return BadValue; 2698f7df2e56Smrg } 2699f7df2e56Smrg if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) { 2700f7df2e56Smrg client->errorValue = stuff->contiguous; 2701f7df2e56Smrg return BadValue; 2702f7df2e56Smrg } 2703f7df2e56Smrg acpr = (xAllocColorPlanesReply) { 2704f7df2e56Smrg .type = X_Reply, 2705f7df2e56Smrg .sequenceNumber = client->sequence, 2706f7df2e56Smrg .nPixels = npixels 2707f7df2e56Smrg }; 2708f7df2e56Smrg length = (long) npixels *sizeof(Pixel); 2709f7df2e56Smrg 2710f7df2e56Smrg ppixels = malloc(length); 2711f7df2e56Smrg if (!ppixels) 27126747b715Smrg return BadAlloc; 2713f7df2e56Smrg if ((rc = AllocColorPlanes(client->index, pcmp, npixels, 2714f7df2e56Smrg (int) stuff->red, (int) stuff->green, 2715f7df2e56Smrg (int) stuff->blue, (Bool) stuff->contiguous, 2716f7df2e56Smrg ppixels, &acpr.redMask, &acpr.greenMask, 2717f7df2e56Smrg &acpr.blueMask))) { 27186747b715Smrg free(ppixels); 2719f7df2e56Smrg return rc; 2720f7df2e56Smrg } 2721f7df2e56Smrg acpr.length = bytes_to_int32(length); 272205b261ecSmrg#ifdef PANORAMIX 2723f7df2e56Smrg if (noPanoramiXExtension || !pcmp->pScreen->myNum) 272405b261ecSmrg#endif 2725f7df2e56Smrg { 2726f7df2e56Smrg WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr); 2727f7df2e56Smrg client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; 2728f7df2e56Smrg WriteSwappedDataToClient(client, length, ppixels); 2729f7df2e56Smrg } 2730f7df2e56Smrg free(ppixels); 27316747b715Smrg return Success; 273205b261ecSmrg } 2733f7df2e56Smrg else { 273405b261ecSmrg client->errorValue = stuff->cmap; 27356747b715Smrg return rc; 273605b261ecSmrg } 273705b261ecSmrg} 273805b261ecSmrg 273905b261ecSmrgint 274005b261ecSmrgProcFreeColors(ClientPtr client) 274105b261ecSmrg{ 274205b261ecSmrg ColormapPtr pcmp; 27434642e01fSmrg int rc; 2744f7df2e56Smrg 274505b261ecSmrg REQUEST(xFreeColorsReq); 274605b261ecSmrg 274705b261ecSmrg REQUEST_AT_LEAST_SIZE(xFreeColorsReq); 2748f7df2e56Smrg rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, 2749f7df2e56Smrg client, DixRemoveAccess); 2750f7df2e56Smrg if (rc == Success) { 2751f7df2e56Smrg int count; 275205b261ecSmrg 2753f7df2e56Smrg if (pcmp->flags & AllAllocated) 2754f7df2e56Smrg return BadAccess; 2755f7df2e56Smrg count = bytes_to_int32((client->req_len << 2) - sizeof(xFreeColorsReq)); 2756f7df2e56Smrg return FreeColors(pcmp, client->index, count, 2757f7df2e56Smrg (Pixel *) &stuff[1], (Pixel) stuff->planeMask); 275805b261ecSmrg } 2759f7df2e56Smrg else { 276005b261ecSmrg client->errorValue = stuff->cmap; 27616747b715Smrg return rc; 276205b261ecSmrg } 276305b261ecSmrg} 276405b261ecSmrg 276505b261ecSmrgint 2766f7df2e56SmrgProcStoreColors(ClientPtr client) 276705b261ecSmrg{ 276805b261ecSmrg ColormapPtr pcmp; 27694642e01fSmrg int rc; 2770f7df2e56Smrg 277105b261ecSmrg REQUEST(xStoreColorsReq); 277205b261ecSmrg 277305b261ecSmrg REQUEST_AT_LEAST_SIZE(xStoreColorsReq); 2774f7df2e56Smrg rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, 2775f7df2e56Smrg client, DixWriteAccess); 2776f7df2e56Smrg if (rc == Success) { 2777f7df2e56Smrg int count; 277805b261ecSmrg 277905b261ecSmrg count = (client->req_len << 2) - sizeof(xStoreColorsReq); 2780f7df2e56Smrg if (count % sizeof(xColorItem)) 2781f7df2e56Smrg return BadLength; 2782f7df2e56Smrg count /= sizeof(xColorItem); 2783f7df2e56Smrg return StoreColors(pcmp, count, (xColorItem *) &stuff[1], client); 278405b261ecSmrg } 2785f7df2e56Smrg else { 278605b261ecSmrg client->errorValue = stuff->cmap; 27876747b715Smrg return rc; 278805b261ecSmrg } 278905b261ecSmrg} 279005b261ecSmrg 279105b261ecSmrgint 2792f7df2e56SmrgProcStoreNamedColor(ClientPtr client) 279305b261ecSmrg{ 279405b261ecSmrg ColormapPtr pcmp; 27954642e01fSmrg int rc; 2796f7df2e56Smrg 279705b261ecSmrg REQUEST(xStoreNamedColorReq); 279805b261ecSmrg 279905b261ecSmrg REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes); 2800f7df2e56Smrg rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, 2801f7df2e56Smrg client, DixWriteAccess); 2802f7df2e56Smrg if (rc == Success) { 2803f7df2e56Smrg xColorItem def; 2804f7df2e56Smrg 2805f7df2e56Smrg if (OsLookupColor(pcmp->pScreen->myNum, (char *) &stuff[1], 2806f7df2e56Smrg stuff->nbytes, &def.red, &def.green, &def.blue)) { 2807f7df2e56Smrg def.flags = stuff->flags; 2808f7df2e56Smrg def.pixel = stuff->pixel; 2809f7df2e56Smrg return StoreColors(pcmp, 1, &def, client); 2810f7df2e56Smrg } 28116747b715Smrg return BadName; 281205b261ecSmrg } 2813f7df2e56Smrg else { 281405b261ecSmrg client->errorValue = stuff->cmap; 28156747b715Smrg return rc; 281605b261ecSmrg } 281705b261ecSmrg} 281805b261ecSmrg 281905b261ecSmrgint 282005b261ecSmrgProcQueryColors(ClientPtr client) 282105b261ecSmrg{ 282205b261ecSmrg ColormapPtr pcmp; 28234642e01fSmrg int rc; 2824f7df2e56Smrg 282505b261ecSmrg REQUEST(xQueryColorsReq); 282605b261ecSmrg 282705b261ecSmrg REQUEST_AT_LEAST_SIZE(xQueryColorsReq); 2828f7df2e56Smrg rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, 2829f7df2e56Smrg client, DixReadAccess); 2830f7df2e56Smrg if (rc == Success) { 2831f7df2e56Smrg int count; 2832f7df2e56Smrg xrgb *prgbs; 2833f7df2e56Smrg xQueryColorsReply qcr; 2834f7df2e56Smrg 2835f7df2e56Smrg count = 2836f7df2e56Smrg bytes_to_int32((client->req_len << 2) - sizeof(xQueryColorsReq)); 2837f7df2e56Smrg prgbs = calloc(count, sizeof(xrgb)); 2838f7df2e56Smrg if (!prgbs && count) 28396747b715Smrg return BadAlloc; 2840f7df2e56Smrg if ((rc = 2841f7df2e56Smrg QueryColors(pcmp, count, (Pixel *) &stuff[1], prgbs, client))) { 2842f7df2e56Smrg free(prgbs); 2843f7df2e56Smrg return rc; 2844f7df2e56Smrg } 2845f7df2e56Smrg qcr = (xQueryColorsReply) { 2846f7df2e56Smrg .type = X_Reply, 2847f7df2e56Smrg .sequenceNumber = client->sequence, 2848f7df2e56Smrg .length = bytes_to_int32(count * sizeof(xrgb)), 2849f7df2e56Smrg .nColors = count 2850f7df2e56Smrg }; 2851f7df2e56Smrg WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr); 2852f7df2e56Smrg if (count) { 2853f7df2e56Smrg client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend; 2854f7df2e56Smrg WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs); 2855f7df2e56Smrg } 2856f7df2e56Smrg free(prgbs); 2857f7df2e56Smrg return Success; 2858f7df2e56Smrg 285905b261ecSmrg } 2860f7df2e56Smrg else { 286105b261ecSmrg client->errorValue = stuff->cmap; 28626747b715Smrg return rc; 286305b261ecSmrg } 2864f7df2e56Smrg} 286505b261ecSmrg 286605b261ecSmrgint 286705b261ecSmrgProcLookupColor(ClientPtr client) 286805b261ecSmrg{ 286905b261ecSmrg ColormapPtr pcmp; 28704642e01fSmrg int rc; 2871f7df2e56Smrg 287205b261ecSmrg REQUEST(xLookupColorReq); 287305b261ecSmrg 287405b261ecSmrg REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes); 2875f7df2e56Smrg rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, 2876f7df2e56Smrg client, DixReadAccess); 2877f7df2e56Smrg if (rc == Success) { 2878f7df2e56Smrg CARD16 exactRed, exactGreen, exactBlue; 2879f7df2e56Smrg 2880f7df2e56Smrg if (OsLookupColor 2881f7df2e56Smrg (pcmp->pScreen->myNum, (char *) &stuff[1], stuff->nbytes, 2882f7df2e56Smrg &exactRed, &exactGreen, &exactBlue)) { 2883f7df2e56Smrg xLookupColorReply lcr = { 2884f7df2e56Smrg .type = X_Reply, 2885f7df2e56Smrg .sequenceNumber = client->sequence, 2886f7df2e56Smrg .length = 0, 2887f7df2e56Smrg .exactRed = exactRed, 2888f7df2e56Smrg .exactGreen = exactGreen, 2889f7df2e56Smrg .exactBlue = exactBlue, 2890f7df2e56Smrg .screenRed = exactRed, 2891f7df2e56Smrg .screenGreen = exactGreen, 2892f7df2e56Smrg .screenBlue = exactBlue 2893f7df2e56Smrg }; 2894f7df2e56Smrg (*pcmp->pScreen->ResolveColor) (&lcr.screenRed, 2895f7df2e56Smrg &lcr.screenGreen, 2896f7df2e56Smrg &lcr.screenBlue, pcmp->pVisual); 2897f7df2e56Smrg WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr); 2898f7df2e56Smrg return Success; 2899f7df2e56Smrg } 29006747b715Smrg return BadName; 290105b261ecSmrg } 2902f7df2e56Smrg else { 290305b261ecSmrg client->errorValue = stuff->cmap; 29046747b715Smrg return rc; 290505b261ecSmrg } 290605b261ecSmrg} 290705b261ecSmrg 290805b261ecSmrgint 2909f7df2e56SmrgProcCreateCursor(ClientPtr client) 291005b261ecSmrg{ 2911f7df2e56Smrg CursorPtr pCursor; 2912f7df2e56Smrg PixmapPtr src; 2913f7df2e56Smrg PixmapPtr msk; 2914f7df2e56Smrg unsigned char *srcbits; 2915f7df2e56Smrg unsigned char *mskbits; 2916f7df2e56Smrg unsigned short width, height; 2917f7df2e56Smrg long n; 2918f7df2e56Smrg CursorMetricRec cm; 29194642e01fSmrg int rc; 292005b261ecSmrg 292105b261ecSmrg REQUEST(xCreateCursorReq); 292205b261ecSmrg 292305b261ecSmrg REQUEST_SIZE_MATCH(xCreateCursorReq); 292405b261ecSmrg LEGAL_NEW_RESOURCE(stuff->cid, client); 292505b261ecSmrg 2926f7df2e56Smrg rc = dixLookupResourceByType((void **) &src, stuff->source, RT_PIXMAP, 2927f7df2e56Smrg client, DixReadAccess); 29284642e01fSmrg if (rc != Success) { 2929f7df2e56Smrg client->errorValue = stuff->source; 2930f7df2e56Smrg return rc; 293105b261ecSmrg } 29324642e01fSmrg 2933f7df2e56Smrg if (src->drawable.depth != 1) 2934f7df2e56Smrg return (BadMatch); 2935f7df2e56Smrg 2936f7df2e56Smrg /* Find and validate cursor mask pixmap, if one is provided */ 2937f7df2e56Smrg if (stuff->mask != None) { 2938f7df2e56Smrg rc = dixLookupResourceByType((void **) &msk, stuff->mask, RT_PIXMAP, 2939f7df2e56Smrg client, DixReadAccess); 2940f7df2e56Smrg if (rc != Success) { 2941f7df2e56Smrg client->errorValue = stuff->mask; 2942f7df2e56Smrg return rc; 2943f7df2e56Smrg } 2944f7df2e56Smrg 2945f7df2e56Smrg if (src->drawable.width != msk->drawable.width 2946f7df2e56Smrg || src->drawable.height != msk->drawable.height 2947f7df2e56Smrg || src->drawable.depth != 1 || msk->drawable.depth != 1) 2948f7df2e56Smrg return BadMatch; 2949f7df2e56Smrg } 2950f7df2e56Smrg else 2951f7df2e56Smrg msk = NULL; 295205b261ecSmrg 295305b261ecSmrg width = src->drawable.width; 295405b261ecSmrg height = src->drawable.height; 295505b261ecSmrg 2956f7df2e56Smrg if (stuff->x > width || stuff->y > height) 2957f7df2e56Smrg return BadMatch; 295805b261ecSmrg 2959f7df2e56Smrg srcbits = calloc(BitmapBytePad(width), height); 296005b261ecSmrg if (!srcbits) 2961f7df2e56Smrg return BadAlloc; 2962f7df2e56Smrg n = BitmapBytePad(width) * height; 29636747b715Smrg mskbits = malloc(n); 2964f7df2e56Smrg if (!mskbits) { 2965f7df2e56Smrg free(srcbits); 2966f7df2e56Smrg return BadAlloc; 296705b261ecSmrg } 296805b261ecSmrg 2969f7df2e56Smrg (*src->drawable.pScreen->GetImage) ((DrawablePtr) src, 0, 0, width, height, 2970f7df2e56Smrg XYPixmap, 1, (void *) srcbits); 2971f7df2e56Smrg if (msk == (PixmapPtr) NULL) { 2972f7df2e56Smrg unsigned char *bits = mskbits; 2973f7df2e56Smrg 2974f7df2e56Smrg while (--n >= 0) 2975f7df2e56Smrg *bits++ = ~0; 297605b261ecSmrg } 2977f7df2e56Smrg else { 2978f7df2e56Smrg /* zeroing the (pad) bits helps some ddx cursor handling */ 2979f7df2e56Smrg memset((char *) mskbits, 0, n); 2980f7df2e56Smrg (*msk->drawable.pScreen->GetImage) ((DrawablePtr) msk, 0, 0, width, 2981f7df2e56Smrg height, XYPixmap, 1, 2982f7df2e56Smrg (void *) mskbits); 298305b261ecSmrg } 298405b261ecSmrg cm.width = width; 298505b261ecSmrg cm.height = height; 298605b261ecSmrg cm.xhot = stuff->x; 298705b261ecSmrg cm.yhot = stuff->y; 29884642e01fSmrg rc = AllocARGBCursor(srcbits, mskbits, NULL, &cm, 2989f7df2e56Smrg stuff->foreRed, stuff->foreGreen, stuff->foreBlue, 2990f7df2e56Smrg stuff->backRed, stuff->backGreen, stuff->backBlue, 2991f7df2e56Smrg &pCursor, client, stuff->cid); 299205b261ecSmrg 29934642e01fSmrg if (rc != Success) 2994f7df2e56Smrg goto bail; 2995f7df2e56Smrg if (!AddResource(stuff->cid, RT_CURSOR, (void *) pCursor)) { 2996f7df2e56Smrg rc = BadAlloc; 2997f7df2e56Smrg goto bail; 2998f7df2e56Smrg } 29994642e01fSmrg 30006747b715Smrg return Success; 3001f7df2e56Smrg bail: 3002f7df2e56Smrg free(srcbits); 3003f7df2e56Smrg free(mskbits); 3004f7df2e56Smrg return rc; 300505b261ecSmrg} 300605b261ecSmrg 300705b261ecSmrgint 3008f7df2e56SmrgProcCreateGlyphCursor(ClientPtr client) 300905b261ecSmrg{ 301005b261ecSmrg CursorPtr pCursor; 301105b261ecSmrg int res; 301205b261ecSmrg 301305b261ecSmrg REQUEST(xCreateGlyphCursorReq); 301405b261ecSmrg 301505b261ecSmrg REQUEST_SIZE_MATCH(xCreateGlyphCursorReq); 301605b261ecSmrg LEGAL_NEW_RESOURCE(stuff->cid, client); 301705b261ecSmrg 301805b261ecSmrg res = AllocGlyphCursor(stuff->source, stuff->sourceChar, 3019f7df2e56Smrg stuff->mask, stuff->maskChar, 3020f7df2e56Smrg stuff->foreRed, stuff->foreGreen, stuff->foreBlue, 3021f7df2e56Smrg stuff->backRed, stuff->backGreen, stuff->backBlue, 3022f7df2e56Smrg &pCursor, client, stuff->cid); 302305b261ecSmrg if (res != Success) 3024f7df2e56Smrg return res; 3025f7df2e56Smrg if (AddResource(stuff->cid, RT_CURSOR, (void *) pCursor)) 3026f7df2e56Smrg return Success; 302705b261ecSmrg return BadAlloc; 302805b261ecSmrg} 302905b261ecSmrg 303005b261ecSmrgint 3031f7df2e56SmrgProcFreeCursor(ClientPtr client) 303205b261ecSmrg{ 303305b261ecSmrg CursorPtr pCursor; 30344642e01fSmrg int rc; 3035f7df2e56Smrg 303605b261ecSmrg REQUEST(xResourceReq); 303705b261ecSmrg 303805b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 3039f7df2e56Smrg rc = dixLookupResourceByType((void **) &pCursor, stuff->id, RT_CURSOR, 3040f7df2e56Smrg client, DixDestroyAccess); 3041f7df2e56Smrg if (rc == Success) { 3042f7df2e56Smrg FreeResource(stuff->id, RT_NONE); 3043f7df2e56Smrg return Success; 304405b261ecSmrg } 3045f7df2e56Smrg else { 3046f7df2e56Smrg client->errorValue = stuff->id; 3047f7df2e56Smrg return rc; 304805b261ecSmrg } 304905b261ecSmrg} 305005b261ecSmrg 305105b261ecSmrgint 3052f7df2e56SmrgProcQueryBestSize(ClientPtr client) 305305b261ecSmrg{ 3054f7df2e56Smrg xQueryBestSizeReply reply; 305505b261ecSmrg DrawablePtr pDraw; 305605b261ecSmrg ScreenPtr pScreen; 305705b261ecSmrg int rc; 3058f7df2e56Smrg 305905b261ecSmrg REQUEST(xQueryBestSizeReq); 306005b261ecSmrg REQUEST_SIZE_MATCH(xQueryBestSizeReq); 306105b261ecSmrg 3062f7df2e56Smrg if ((stuff->class != CursorShape) && 3063f7df2e56Smrg (stuff->class != TileShape) && (stuff->class != StippleShape)) { 3064f7df2e56Smrg client->errorValue = stuff->class; 30656747b715Smrg return BadValue; 306605b261ecSmrg } 306705b261ecSmrg 306805b261ecSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, 3069f7df2e56Smrg DixGetAttrAccess); 307005b261ecSmrg if (rc != Success) 3071f7df2e56Smrg return rc; 307205b261ecSmrg if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW) 3073f7df2e56Smrg return BadMatch; 307405b261ecSmrg pScreen = pDraw->pScreen; 30754642e01fSmrg rc = XaceHook(XACE_SCREEN_ACCESS, client, pScreen, DixGetAttrAccess); 30764642e01fSmrg if (rc != Success) 3077f7df2e56Smrg return rc; 3078f7df2e56Smrg (*pScreen->QueryBestSize) (stuff->class, &stuff->width, 3079f7df2e56Smrg &stuff->height, pScreen); 3080f7df2e56Smrg reply = (xQueryBestSizeReply) { 3081f7df2e56Smrg .type = X_Reply, 3082f7df2e56Smrg .sequenceNumber = client->sequence, 3083f7df2e56Smrg .length = 0, 3084f7df2e56Smrg .width = stuff->width, 3085f7df2e56Smrg .height = stuff->height 3086f7df2e56Smrg }; 308705b261ecSmrg WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply); 30886747b715Smrg return Success; 308905b261ecSmrg} 309005b261ecSmrg 309105b261ecSmrgint 3092f7df2e56SmrgProcSetScreenSaver(ClientPtr client) 309305b261ecSmrg{ 30944642e01fSmrg int rc, i, blankingOption, exposureOption; 3095f7df2e56Smrg 309605b261ecSmrg REQUEST(xSetScreenSaverReq); 309705b261ecSmrg REQUEST_SIZE_MATCH(xSetScreenSaverReq); 30984642e01fSmrg 30994642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) { 3100f7df2e56Smrg rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i], 3101f7df2e56Smrg DixSetAttrAccess); 3102f7df2e56Smrg if (rc != Success) 3103f7df2e56Smrg return rc; 31044642e01fSmrg } 31054642e01fSmrg 310605b261ecSmrg blankingOption = stuff->preferBlank; 310705b261ecSmrg if ((blankingOption != DontPreferBlanking) && 310805b261ecSmrg (blankingOption != PreferBlanking) && 3109f7df2e56Smrg (blankingOption != DefaultBlanking)) { 3110f7df2e56Smrg client->errorValue = blankingOption; 311105b261ecSmrg return BadValue; 311205b261ecSmrg } 311305b261ecSmrg exposureOption = stuff->allowExpose; 311405b261ecSmrg if ((exposureOption != DontAllowExposures) && 311505b261ecSmrg (exposureOption != AllowExposures) && 3116f7df2e56Smrg (exposureOption != DefaultExposures)) { 3117f7df2e56Smrg client->errorValue = exposureOption; 311805b261ecSmrg return BadValue; 311905b261ecSmrg } 3120f7df2e56Smrg if (stuff->timeout < -1) { 3121f7df2e56Smrg client->errorValue = stuff->timeout; 312205b261ecSmrg return BadValue; 312305b261ecSmrg } 3124f7df2e56Smrg if (stuff->interval < -1) { 3125f7df2e56Smrg client->errorValue = stuff->interval; 312605b261ecSmrg return BadValue; 312705b261ecSmrg } 312805b261ecSmrg 312905b261ecSmrg if (blankingOption == DefaultBlanking) 3130f7df2e56Smrg ScreenSaverBlanking = defaultScreenSaverBlanking; 313105b261ecSmrg else 3132f7df2e56Smrg ScreenSaverBlanking = blankingOption; 313305b261ecSmrg if (exposureOption == DefaultExposures) 3134f7df2e56Smrg ScreenSaverAllowExposures = defaultScreenSaverAllowExposures; 313505b261ecSmrg else 3136f7df2e56Smrg ScreenSaverAllowExposures = exposureOption; 313705b261ecSmrg 313805b261ecSmrg if (stuff->timeout >= 0) 3139f7df2e56Smrg ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND; 3140f7df2e56Smrg else 3141f7df2e56Smrg ScreenSaverTime = defaultScreenSaverTime; 314205b261ecSmrg if (stuff->interval >= 0) 3143f7df2e56Smrg ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND; 314405b261ecSmrg else 3145f7df2e56Smrg ScreenSaverInterval = defaultScreenSaverInterval; 314605b261ecSmrg 314705b261ecSmrg SetScreenSaverTimer(); 31486747b715Smrg return Success; 314905b261ecSmrg} 315005b261ecSmrg 315105b261ecSmrgint 315205b261ecSmrgProcGetScreenSaver(ClientPtr client) 315305b261ecSmrg{ 315405b261ecSmrg xGetScreenSaverReply rep; 31554642e01fSmrg int rc, i; 3156f7df2e56Smrg 315705b261ecSmrg REQUEST_SIZE_MATCH(xReq); 31584642e01fSmrg 31594642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) { 3160f7df2e56Smrg rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i], 3161f7df2e56Smrg DixGetAttrAccess); 3162f7df2e56Smrg if (rc != Success) 3163f7df2e56Smrg return rc; 3164f7df2e56Smrg } 3165f7df2e56Smrg 3166f7df2e56Smrg rep = (xGetScreenSaverReply) { 3167f7df2e56Smrg .type = X_Reply, 3168f7df2e56Smrg .sequenceNumber = client->sequence, 3169f7df2e56Smrg .length = 0, 3170f7df2e56Smrg .timeout = ScreenSaverTime / MILLI_PER_SECOND, 3171f7df2e56Smrg .interval = ScreenSaverInterval / MILLI_PER_SECOND, 3172f7df2e56Smrg .preferBlanking = ScreenSaverBlanking, 3173f7df2e56Smrg .allowExposures = ScreenSaverAllowExposures 3174f7df2e56Smrg }; 317505b261ecSmrg WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep); 31766747b715Smrg return Success; 317705b261ecSmrg} 317805b261ecSmrg 317905b261ecSmrgint 318005b261ecSmrgProcChangeHosts(ClientPtr client) 318105b261ecSmrg{ 318205b261ecSmrg REQUEST(xChangeHostsReq); 318305b261ecSmrg 318405b261ecSmrg REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength); 318505b261ecSmrg 3186f7df2e56Smrg if (stuff->mode == HostInsert) 3187f7df2e56Smrg return AddHost(client, (int) stuff->hostFamily, 3188f7df2e56Smrg stuff->hostLength, (void *) &stuff[1]); 31896747b715Smrg if (stuff->mode == HostDelete) 3190f7df2e56Smrg return RemoveHost(client, (int) stuff->hostFamily, 3191f7df2e56Smrg stuff->hostLength, (void *) &stuff[1]); 31926747b715Smrg client->errorValue = stuff->mode; 31936747b715Smrg return BadValue; 319405b261ecSmrg} 319505b261ecSmrg 319605b261ecSmrgint 319705b261ecSmrgProcListHosts(ClientPtr client) 319805b261ecSmrg{ 319905b261ecSmrg xListHostsReply reply; 3200f7df2e56Smrg int len, nHosts, result; 3201f7df2e56Smrg BOOL enabled; 3202f7df2e56Smrg void *pdata; 3203f7df2e56Smrg 320405b261ecSmrg /* REQUEST(xListHostsReq); */ 320505b261ecSmrg 320605b261ecSmrg REQUEST_SIZE_MATCH(xListHostsReq); 320705b261ecSmrg 320805b261ecSmrg /* untrusted clients can't list hosts */ 32094642e01fSmrg result = XaceHook(XACE_SERVER_ACCESS, client, DixReadAccess); 32104642e01fSmrg if (result != Success) 3211f7df2e56Smrg return result; 321205b261ecSmrg 3213f7df2e56Smrg result = GetHosts(&pdata, &nHosts, &len, &enabled); 321405b261ecSmrg if (result != Success) 3215f7df2e56Smrg return result; 3216f7df2e56Smrg 3217f7df2e56Smrg reply = (xListHostsReply) { 3218f7df2e56Smrg .type = X_Reply, 3219f7df2e56Smrg .enabled = enabled, 3220f7df2e56Smrg .sequenceNumber = client->sequence, 3221f7df2e56Smrg .length = bytes_to_int32(len), 3222f7df2e56Smrg .nHosts = nHosts 3223f7df2e56Smrg }; 322405b261ecSmrg WriteReplyToClient(client, sizeof(xListHostsReply), &reply); 3225f7df2e56Smrg if (nHosts) { 3226f7df2e56Smrg client->pSwapReplyFunc = (ReplySwapPtr) SLHostsExtend; 3227f7df2e56Smrg WriteSwappedDataToClient(client, len, pdata); 322805b261ecSmrg } 32296747b715Smrg free(pdata); 32306747b715Smrg return Success; 323105b261ecSmrg} 323205b261ecSmrg 323305b261ecSmrgint 323405b261ecSmrgProcChangeAccessControl(ClientPtr client) 323505b261ecSmrg{ 323605b261ecSmrg REQUEST(xSetAccessControlReq); 323705b261ecSmrg 323805b261ecSmrg REQUEST_SIZE_MATCH(xSetAccessControlReq); 3239f7df2e56Smrg if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess)) { 3240f7df2e56Smrg client->errorValue = stuff->mode; 324105b261ecSmrg return BadValue; 324205b261ecSmrg } 32436747b715Smrg return ChangeAccessControl(client, stuff->mode == EnableAccess); 324405b261ecSmrg} 324505b261ecSmrg 324605b261ecSmrg/********************* 324705b261ecSmrg * CloseDownRetainedResources 324805b261ecSmrg * 3249f7df2e56Smrg * Find all clients that are gone and have terminated in RetainTemporary 325005b261ecSmrg * and destroy their resources. 325105b261ecSmrg *********************/ 325205b261ecSmrg 325305b261ecSmrgstatic void 325405b261ecSmrgCloseDownRetainedResources(void) 325505b261ecSmrg{ 325605b261ecSmrg int i; 325705b261ecSmrg ClientPtr client; 325805b261ecSmrg 3259f7df2e56Smrg for (i = 1; i < currentMaxClients; i++) { 326005b261ecSmrg client = clients[i]; 326105b261ecSmrg if (client && (client->closeDownMode == RetainTemporary) 3262f7df2e56Smrg && (client->clientGone)) 3263f7df2e56Smrg CloseDownClient(client); 326405b261ecSmrg } 326505b261ecSmrg} 326605b261ecSmrg 326705b261ecSmrgint 326805b261ecSmrgProcKillClient(ClientPtr client) 326905b261ecSmrg{ 327005b261ecSmrg REQUEST(xResourceReq); 327105b261ecSmrg ClientPtr killclient; 327205b261ecSmrg int rc; 327305b261ecSmrg 327405b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 3275f7df2e56Smrg if (stuff->id == AllTemporary) { 3276f7df2e56Smrg CloseDownRetainedResources(); 32776747b715Smrg return Success; 327805b261ecSmrg } 327905b261ecSmrg 328005b261ecSmrg rc = dixLookupClient(&killclient, stuff->id, client, DixDestroyAccess); 328105b261ecSmrg if (rc == Success) { 3282f7df2e56Smrg CloseDownClient(killclient); 3283f7df2e56Smrg if (client == killclient) { 3284f7df2e56Smrg /* force yield and return Success, so that Dispatch() 3285f7df2e56Smrg * doesn't try to touch client 3286f7df2e56Smrg */ 3287f7df2e56Smrg isItTimeToYield = TRUE; 3288f7df2e56Smrg } 3289f7df2e56Smrg return Success; 329005b261ecSmrg } 329105b261ecSmrg else 3292f7df2e56Smrg return rc; 329305b261ecSmrg} 329405b261ecSmrg 329505b261ecSmrgint 329605b261ecSmrgProcSetFontPath(ClientPtr client) 329705b261ecSmrg{ 329805b261ecSmrg unsigned char *ptr; 329905b261ecSmrg unsigned long nbytes, total; 330005b261ecSmrg long nfonts; 33016747b715Smrg int n; 3302f7df2e56Smrg 330305b261ecSmrg REQUEST(xSetFontPathReq); 3304f7df2e56Smrg 330505b261ecSmrg REQUEST_AT_LEAST_SIZE(xSetFontPathReq); 3306f7df2e56Smrg 330705b261ecSmrg nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq); 330805b261ecSmrg total = nbytes; 3309f7df2e56Smrg ptr = (unsigned char *) &stuff[1]; 331005b261ecSmrg nfonts = stuff->nFonts; 3311f7df2e56Smrg while (--nfonts >= 0) { 3312f7df2e56Smrg if ((total == 0) || (total < (n = (*ptr + 1)))) 3313f7df2e56Smrg return BadLength; 3314f7df2e56Smrg total -= n; 3315f7df2e56Smrg ptr += n; 331605b261ecSmrg } 331705b261ecSmrg if (total >= 4) 3318f7df2e56Smrg return BadLength; 3319f7df2e56Smrg return SetFontPath(client, stuff->nFonts, (unsigned char *) &stuff[1]); 332005b261ecSmrg} 332105b261ecSmrg 332205b261ecSmrgint 332305b261ecSmrgProcGetFontPath(ClientPtr client) 332405b261ecSmrg{ 332505b261ecSmrg xGetFontPathReply reply; 33264642e01fSmrg int rc, stringLens, numpaths; 332705b261ecSmrg unsigned char *bufferStart; 3328f7df2e56Smrg 332905b261ecSmrg /* REQUEST (xReq); */ 333005b261ecSmrg 333105b261ecSmrg REQUEST_SIZE_MATCH(xReq); 33324642e01fSmrg rc = GetFontPath(client, &numpaths, &stringLens, &bufferStart); 33334642e01fSmrg if (rc != Success) 3334f7df2e56Smrg return rc; 333505b261ecSmrg 3336f7df2e56Smrg reply = (xGetFontPathReply) { 3337f7df2e56Smrg .type = X_Reply, 3338f7df2e56Smrg .sequenceNumber = client->sequence, 3339f7df2e56Smrg .length = bytes_to_int32(stringLens + numpaths), 3340f7df2e56Smrg .nPaths = numpaths 3341f7df2e56Smrg }; 334205b261ecSmrg 334305b261ecSmrg WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply); 334405b261ecSmrg if (stringLens || numpaths) 3345f7df2e56Smrg WriteToClient(client, stringLens + numpaths, bufferStart); 33466747b715Smrg return Success; 334705b261ecSmrg} 334805b261ecSmrg 334905b261ecSmrgint 335005b261ecSmrgProcChangeCloseDownMode(ClientPtr client) 335105b261ecSmrg{ 33524642e01fSmrg int rc; 3353f7df2e56Smrg 335405b261ecSmrg REQUEST(xSetCloseDownModeReq); 335505b261ecSmrg REQUEST_SIZE_MATCH(xSetCloseDownModeReq); 33564642e01fSmrg 33574642e01fSmrg rc = XaceHook(XACE_CLIENT_ACCESS, client, client, DixManageAccess); 33584642e01fSmrg if (rc != Success) 3359f7df2e56Smrg return rc; 33604642e01fSmrg 336105b261ecSmrg if ((stuff->mode == AllTemporary) || 3362f7df2e56Smrg (stuff->mode == RetainPermanent) || (stuff->mode == RetainTemporary)) { 3363f7df2e56Smrg client->closeDownMode = stuff->mode; 3364f7df2e56Smrg return Success; 336505b261ecSmrg } 3366f7df2e56Smrg else { 3367f7df2e56Smrg client->errorValue = stuff->mode; 3368f7df2e56Smrg return BadValue; 336905b261ecSmrg } 337005b261ecSmrg} 337105b261ecSmrg 3372f7df2e56Smrgint 3373f7df2e56SmrgProcForceScreenSaver(ClientPtr client) 3374f7df2e56Smrg{ 33754642e01fSmrg int rc; 3376f7df2e56Smrg 337705b261ecSmrg REQUEST(xForceScreenSaverReq); 337805b261ecSmrg 337905b261ecSmrg REQUEST_SIZE_MATCH(xForceScreenSaverReq); 3380f7df2e56Smrg 3381f7df2e56Smrg if ((stuff->mode != ScreenSaverReset) && (stuff->mode != ScreenSaverActive)) { 3382f7df2e56Smrg client->errorValue = stuff->mode; 338305b261ecSmrg return BadValue; 338405b261ecSmrg } 3385f7df2e56Smrg rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, (int) stuff->mode); 33864642e01fSmrg if (rc != Success) 3387f7df2e56Smrg return rc; 33886747b715Smrg return Success; 338905b261ecSmrg} 339005b261ecSmrg 3391f7df2e56Smrgint 3392f7df2e56SmrgProcNoOperation(ClientPtr client) 339305b261ecSmrg{ 339405b261ecSmrg REQUEST_AT_LEAST_SIZE(xReq); 3395f7df2e56Smrg 339605b261ecSmrg /* noop -- don't do anything */ 33976747b715Smrg return Success; 339805b261ecSmrg} 339905b261ecSmrg 340005b261ecSmrg/********************** 340105b261ecSmrg * CloseDownClient 340205b261ecSmrg * 340305b261ecSmrg * Client can either mark his resources destroy or retain. If retained and 340405b261ecSmrg * then killed again, the client is really destroyed. 340505b261ecSmrg *********************/ 340605b261ecSmrg 340705b261ecSmrgchar dispatchExceptionAtReset = DE_RESET; 340805b261ecSmrg 340905b261ecSmrgvoid 341005b261ecSmrgCloseDownClient(ClientPtr client) 341105b261ecSmrg{ 341205b261ecSmrg Bool really_close_down = client->clientGone || 3413f7df2e56Smrg client->closeDownMode == DestroyAll; 341405b261ecSmrg 3415f7df2e56Smrg if (!client->clientGone) { 3416f7df2e56Smrg /* ungrab server if grabbing client dies */ 3417f7df2e56Smrg if (grabState != GrabNone && grabClient == client) { 3418f7df2e56Smrg UngrabServer(client); 3419f7df2e56Smrg } 3420f7df2e56Smrg BITCLEAR(grabWaiters, client->index); 3421f7df2e56Smrg DeleteClientFromAnySelections(client); 3422f7df2e56Smrg ReleaseActiveGrabs(client); 3423f7df2e56Smrg DeleteClientFontStuff(client); 3424f7df2e56Smrg if (!really_close_down) { 3425f7df2e56Smrg /* This frees resources that should never be retained 3426f7df2e56Smrg * no matter what the close down mode is. Actually we 3427f7df2e56Smrg * could do this unconditionally, but it's probably 3428f7df2e56Smrg * better not to traverse all the client's resources 3429f7df2e56Smrg * twice (once here, once a few lines down in 3430f7df2e56Smrg * FreeClientResources) in the common case of 3431f7df2e56Smrg * really_close_down == TRUE. 3432f7df2e56Smrg */ 3433f7df2e56Smrg FreeClientNeverRetainResources(client); 3434f7df2e56Smrg client->clientState = ClientStateRetained; 3435f7df2e56Smrg if (ClientStateCallback) { 3436f7df2e56Smrg NewClientInfoRec clientinfo; 3437f7df2e56Smrg 3438f7df2e56Smrg clientinfo.client = client; 3439f7df2e56Smrg clientinfo.prefix = (xConnSetupPrefix *) NULL; 3440f7df2e56Smrg clientinfo.setup = (xConnSetup *) NULL; 3441f7df2e56Smrg CallCallbacks((&ClientStateCallback), (void *) &clientinfo); 3442f7df2e56Smrg } 3443f7df2e56Smrg } 3444f7df2e56Smrg client->clientGone = TRUE; /* so events aren't sent to client */ 3445f7df2e56Smrg if (ClientIsAsleep(client)) 3446f7df2e56Smrg ClientSignal(client); 3447f7df2e56Smrg ProcessWorkQueueZombies(); 3448f7df2e56Smrg CloseDownConnection(client); 34497e31ba66Smrg output_pending_clear(client); 34507e31ba66Smrg mark_client_not_ready(client); 3451f7df2e56Smrg 3452f7df2e56Smrg /* If the client made it to the Running stage, nClients has 3453f7df2e56Smrg * been incremented on its behalf, so we need to decrement it 3454f7df2e56Smrg * now. If it hasn't gotten to Running, nClients has *not* 3455f7df2e56Smrg * been incremented, so *don't* decrement it. 3456f7df2e56Smrg */ 3457f7df2e56Smrg if (client->clientState != ClientStateInitial) { 3458f7df2e56Smrg --nClients; 3459f7df2e56Smrg } 3460f7df2e56Smrg } 3461f7df2e56Smrg 3462f7df2e56Smrg if (really_close_down) { 3463f7df2e56Smrg if (client->clientState == ClientStateRunning && nClients == 0) 3464f7df2e56Smrg dispatchException |= dispatchExceptionAtReset; 3465f7df2e56Smrg 3466f7df2e56Smrg client->clientState = ClientStateGone; 3467f7df2e56Smrg if (ClientStateCallback) { 3468f7df2e56Smrg NewClientInfoRec clientinfo; 3469f7df2e56Smrg 3470f7df2e56Smrg clientinfo.client = client; 3471f7df2e56Smrg clientinfo.prefix = (xConnSetupPrefix *) NULL; 3472f7df2e56Smrg clientinfo.setup = (xConnSetup *) NULL; 3473f7df2e56Smrg CallCallbacks((&ClientStateCallback), (void *) &clientinfo); 3474f7df2e56Smrg } 3475f7df2e56Smrg TouchListenerGone(client->clientAsMask); 3476f7df2e56Smrg FreeClientResources(client); 3477f7df2e56Smrg /* Disable client ID tracking. This must be done after 3478f7df2e56Smrg * ClientStateCallback. */ 3479f7df2e56Smrg ReleaseClientIds(client); 348005b261ecSmrg#ifdef XSERVER_DTRACE 3481f7df2e56Smrg XSERVER_CLIENT_DISCONNECT(client->index); 3482f7df2e56Smrg#endif 3483f7df2e56Smrg if (client->index < nextFreeClientID) 3484f7df2e56Smrg nextFreeClientID = client->index; 3485f7df2e56Smrg clients[client->index] = NullClient; 3486f7df2e56Smrg SmartLastClient = NullClient; 3487f7df2e56Smrg dixFreeObjectWithPrivates(client, PRIVATE_CLIENT); 348805b261ecSmrg 3489f7df2e56Smrg while (!clients[currentMaxClients - 1]) 3490f7df2e56Smrg currentMaxClients--; 349105b261ecSmrg } 349205b261ecSmrg} 349305b261ecSmrg 349405b261ecSmrgstatic void 349505b261ecSmrgKillAllClients(void) 349605b261ecSmrg{ 349705b261ecSmrg int i; 3498f7df2e56Smrg 3499f7df2e56Smrg for (i = 1; i < currentMaxClients; i++) 350005b261ecSmrg if (clients[i]) { 350105b261ecSmrg /* Make sure Retained clients are released. */ 350205b261ecSmrg clients[i]->closeDownMode = DestroyAll; 3503f7df2e56Smrg CloseDownClient(clients[i]); 350405b261ecSmrg } 350505b261ecSmrg} 350605b261ecSmrg 3507f7df2e56Smrgvoid 3508f7df2e56SmrgInitClient(ClientPtr client, int i, void *ospriv) 350905b261ecSmrg{ 351005b261ecSmrg client->index = i; 35117e31ba66Smrg xorg_list_init(&client->ready); 35127e31ba66Smrg xorg_list_init(&client->output_pending); 3513f7df2e56Smrg client->clientAsMask = ((Mask) i) << CLIENTOFFSET; 35144642e01fSmrg client->closeDownMode = i ? DestroyAll : RetainPermanent; 351505b261ecSmrg client->requestVector = InitialVector; 351605b261ecSmrg client->osPrivate = ospriv; 3517f7df2e56Smrg QueryMinMaxKeyCodes(&client->minKC, &client->maxKC); 351805b261ecSmrg client->smart_start_tick = SmartScheduleTime; 351905b261ecSmrg client->smart_stop_tick = SmartScheduleTime; 3520f7df2e56Smrg client->clientIds = NULL; 352105b261ecSmrg} 352205b261ecSmrg 352305b261ecSmrg/************************ 352405b261ecSmrg * int NextAvailableClient(ospriv) 352505b261ecSmrg * 352605b261ecSmrg * OS dependent portion can't assign client id's because of CloseDownModes. 352705b261ecSmrg * Returns NULL if there are no free clients. 352805b261ecSmrg *************************/ 352905b261ecSmrg 3530f7df2e56SmrgClientPtr 3531f7df2e56SmrgNextAvailableClient(void *ospriv) 353205b261ecSmrg{ 353305b261ecSmrg int i; 353405b261ecSmrg ClientPtr client; 353505b261ecSmrg xReq data; 353605b261ecSmrg 353705b261ecSmrg i = nextFreeClientID; 3538f7df2e56Smrg if (i == LimitClients) 3539f7df2e56Smrg return (ClientPtr) NULL; 3540f7df2e56Smrg clients[i] = client = 3541f7df2e56Smrg dixAllocateObjectWithPrivates(ClientRec, PRIVATE_CLIENT); 354205b261ecSmrg if (!client) 3543f7df2e56Smrg return (ClientPtr) NULL; 354405b261ecSmrg InitClient(client, i, ospriv); 3545f7df2e56Smrg if (!InitClientResources(client)) { 3546f7df2e56Smrg dixFreeObjectWithPrivates(client, PRIVATE_CLIENT); 3547f7df2e56Smrg return (ClientPtr) NULL; 354805b261ecSmrg } 354905b261ecSmrg data.reqType = 1; 35506747b715Smrg data.length = bytes_to_int32(sz_xReq + sz_xConnClientPrefix); 3551f7df2e56Smrg if (!InsertFakeRequest(client, (char *) &data, sz_xReq)) { 3552f7df2e56Smrg FreeClientResources(client); 3553f7df2e56Smrg dixFreeObjectWithPrivates(client, PRIVATE_CLIENT); 3554f7df2e56Smrg return (ClientPtr) NULL; 355505b261ecSmrg } 355605b261ecSmrg if (i == currentMaxClients) 3557f7df2e56Smrg currentMaxClients++; 3558f7df2e56Smrg while ((nextFreeClientID < LimitClients) && clients[nextFreeClientID]) 3559f7df2e56Smrg nextFreeClientID++; 3560f7df2e56Smrg 3561f7df2e56Smrg /* Enable client ID tracking. This must be done before 3562f7df2e56Smrg * ClientStateCallback. */ 3563f7df2e56Smrg ReserveClientIds(client); 3564f7df2e56Smrg 3565f7df2e56Smrg if (ClientStateCallback) { 3566f7df2e56Smrg NewClientInfoRec clientinfo; 356705b261ecSmrg 3568f7df2e56Smrg clientinfo.client = client; 3569f7df2e56Smrg clientinfo.prefix = (xConnSetupPrefix *) NULL; 357005b261ecSmrg clientinfo.setup = (xConnSetup *) NULL; 3571f7df2e56Smrg CallCallbacks((&ClientStateCallback), (void *) &clientinfo); 3572f7df2e56Smrg } 35736747b715Smrg return client; 357405b261ecSmrg} 357505b261ecSmrg 357605b261ecSmrgint 357705b261ecSmrgProcInitialConnection(ClientPtr client) 357805b261ecSmrg{ 357905b261ecSmrg REQUEST(xReq); 358005b261ecSmrg xConnClientPrefix *prefix; 358105b261ecSmrg int whichbyte = 1; 3582f7df2e56Smrg char order; 358305b261ecSmrg 3584f7df2e56Smrg prefix = (xConnClientPrefix *) ((char *)stuff + sz_xReq); 3585f7df2e56Smrg order = prefix->byteOrder; 3586f7df2e56Smrg if (order != 'l' && order != 'B' && order != 'r' && order != 'R') 35876747b715Smrg return client->noClientException = -1; 3588f7df2e56Smrg if (((*(char *) &whichbyte) && (order == 'B' || order == 'R')) || 3589f7df2e56Smrg (!(*(char *) &whichbyte) && (order == 'l' || order == 'r'))) { 359005b261ecSmrg client->swapped = TRUE; 359105b261ecSmrg SwapConnClientPrefix(prefix); 359205b261ecSmrg } 359305b261ecSmrg stuff->reqType = 2; 35946747b715Smrg stuff->length += bytes_to_int32(prefix->nbytesAuthProto) + 3595f7df2e56Smrg bytes_to_int32(prefix->nbytesAuthString); 3596f7df2e56Smrg if (client->swapped) { 3597f7df2e56Smrg swaps(&stuff->length); 3598f7df2e56Smrg } 3599f7df2e56Smrg if (order == 'r' || order == 'R') { 3600f7df2e56Smrg client->local = FALSE; 360105b261ecSmrg } 360205b261ecSmrg ResetCurrentRequest(client); 36036747b715Smrg return Success; 360405b261ecSmrg} 360505b261ecSmrg 36064642e01fSmrgstatic int 3607f7df2e56SmrgSendConnSetup(ClientPtr client, const char *reason) 360805b261ecSmrg{ 360905b261ecSmrg xWindowRoot *root; 361005b261ecSmrg int i; 361105b261ecSmrg int numScreens; 3612f7df2e56Smrg char *lConnectionInfo; 3613f7df2e56Smrg xConnSetupPrefix *lconnSetupPrefix; 361405b261ecSmrg 3615f7df2e56Smrg if (reason) { 3616f7df2e56Smrg xConnSetupPrefix csp; 3617f7df2e56Smrg 3618f7df2e56Smrg csp.success = xFalse; 3619f7df2e56Smrg csp.lengthReason = strlen(reason); 3620f7df2e56Smrg csp.length = bytes_to_int32(csp.lengthReason); 3621f7df2e56Smrg csp.majorVersion = X_PROTOCOL; 3622f7df2e56Smrg csp.minorVersion = X_PROTOCOL_REVISION; 3623f7df2e56Smrg if (client->swapped) 3624f7df2e56Smrg WriteSConnSetupPrefix(client, &csp); 3625f7df2e56Smrg else 3626f7df2e56Smrg WriteToClient(client, sz_xConnSetupPrefix, &csp); 3627f7df2e56Smrg WriteToClient(client, (int) csp.lengthReason, reason); 3628f7df2e56Smrg return client->noClientException = -1; 362905b261ecSmrg } 363005b261ecSmrg 363105b261ecSmrg numScreens = screenInfo.numScreens; 363205b261ecSmrg lConnectionInfo = ConnectionInfo; 363305b261ecSmrg lconnSetupPrefix = &connSetupPrefix; 363405b261ecSmrg 363505b261ecSmrg /* We're about to start speaking X protocol back to the client by 363605b261ecSmrg * sending the connection setup info. This means the authorization 363705b261ecSmrg * step is complete, and we can count the client as an 363805b261ecSmrg * authorized one. 363905b261ecSmrg */ 364005b261ecSmrg nClients++; 364105b261ecSmrg 364205b261ecSmrg client->requestVector = client->swapped ? SwappedProcVector : ProcVector; 364305b261ecSmrg client->sequence = 0; 3644f7df2e56Smrg ((xConnSetup *) lConnectionInfo)->ridBase = client->clientAsMask; 3645f7df2e56Smrg ((xConnSetup *) lConnectionInfo)->ridMask = RESOURCE_ID_MASK; 364605b261ecSmrg#ifdef MATCH_CLIENT_ENDIAN 3647f7df2e56Smrg ((xConnSetup *) lConnectionInfo)->imageByteOrder = ClientOrder(client); 3648f7df2e56Smrg ((xConnSetup *) lConnectionInfo)->bitmapBitOrder = ClientOrder(client); 364905b261ecSmrg#endif 365005b261ecSmrg /* fill in the "currentInputMask" */ 3651f7df2e56Smrg root = (xWindowRoot *) (lConnectionInfo + connBlockScreenStart); 365205b261ecSmrg#ifdef PANORAMIX 365305b261ecSmrg if (noPanoramiXExtension) 3654f7df2e56Smrg numScreens = screenInfo.numScreens; 3655f7df2e56Smrg else 3656f7df2e56Smrg numScreens = ((xConnSetup *) ConnectionInfo)->numRoots; 365705b261ecSmrg#endif 365805b261ecSmrg 3659f7df2e56Smrg for (i = 0; i < numScreens; i++) { 3660f7df2e56Smrg unsigned int j; 3661f7df2e56Smrg xDepth *pDepth; 3662f7df2e56Smrg WindowPtr pRoot = screenInfo.screens[i]->root; 366305b261ecSmrg 36646747b715Smrg root->currentInputMask = pRoot->eventMask | wOtherEventMasks(pRoot); 3665f7df2e56Smrg pDepth = (xDepth *) (root + 1); 3666f7df2e56Smrg for (j = 0; j < root->nDepths; j++) { 3667f7df2e56Smrg pDepth = (xDepth *) (((char *) (pDepth + 1)) + 3668f7df2e56Smrg pDepth->nVisuals * sizeof(xVisualType)); 3669f7df2e56Smrg } 3670f7df2e56Smrg root = (xWindowRoot *) pDepth; 367105b261ecSmrg } 367205b261ecSmrg 3673f7df2e56Smrg if (client->swapped) { 3674f7df2e56Smrg WriteSConnSetupPrefix(client, lconnSetupPrefix); 3675f7df2e56Smrg WriteSConnectionInfo(client, 3676f7df2e56Smrg (unsigned long) (lconnSetupPrefix->length << 2), 3677f7df2e56Smrg lConnectionInfo); 367805b261ecSmrg } 3679f7df2e56Smrg else { 3680f7df2e56Smrg WriteToClient(client, sizeof(xConnSetupPrefix), lconnSetupPrefix); 3681f7df2e56Smrg WriteToClient(client, (int) (lconnSetupPrefix->length << 2), 3682f7df2e56Smrg lConnectionInfo); 368305b261ecSmrg } 368405b261ecSmrg client->clientState = ClientStateRunning; 3685f7df2e56Smrg if (ClientStateCallback) { 3686f7df2e56Smrg NewClientInfoRec clientinfo; 368705b261ecSmrg 3688f7df2e56Smrg clientinfo.client = client; 3689f7df2e56Smrg clientinfo.prefix = lconnSetupPrefix; 3690f7df2e56Smrg clientinfo.setup = (xConnSetup *) lConnectionInfo; 3691f7df2e56Smrg CallCallbacks((&ClientStateCallback), (void *) &clientinfo); 3692f7df2e56Smrg } 36936747b715Smrg return Success; 369405b261ecSmrg} 369505b261ecSmrg 369605b261ecSmrgint 369705b261ecSmrgProcEstablishConnection(ClientPtr client) 369805b261ecSmrg{ 3699f7df2e56Smrg const char *reason; 3700f7df2e56Smrg char *auth_proto, *auth_string; 370105b261ecSmrg xConnClientPrefix *prefix; 3702f7df2e56Smrg 370305b261ecSmrg REQUEST(xReq); 370405b261ecSmrg 3705f7df2e56Smrg prefix = (xConnClientPrefix *) ((char *) stuff + sz_xReq); 3706f7df2e56Smrg auth_proto = (char *) prefix + sz_xConnClientPrefix; 37076747b715Smrg auth_string = auth_proto + pad_to_int32(prefix->nbytesAuthProto); 37086e78d31fSmrg 37096e78d31fSmrg if ((client->req_len << 2) != sz_xReq + sz_xConnClientPrefix + 37106e78d31fSmrg pad_to_int32(prefix->nbytesAuthProto) + 37116e78d31fSmrg pad_to_int32(prefix->nbytesAuthString)) 37126e78d31fSmrg reason = "Bad length"; 37136e78d31fSmrg else if ((prefix->majorVersion != X_PROTOCOL) || 3714f7df2e56Smrg (prefix->minorVersion != X_PROTOCOL_REVISION)) 3715f7df2e56Smrg reason = "Protocol version mismatch"; 371605b261ecSmrg else 3717f7df2e56Smrg reason = ClientAuthorized(client, 3718f7df2e56Smrg (unsigned short) prefix->nbytesAuthProto, 3719f7df2e56Smrg auth_proto, 3720f7df2e56Smrg (unsigned short) prefix->nbytesAuthString, 3721f7df2e56Smrg auth_string); 3722f7df2e56Smrg 3723f7df2e56Smrg return (SendConnSetup(client, reason)); 372405b261ecSmrg} 372505b261ecSmrg 37266747b715Smrgvoid 3727f7df2e56SmrgSendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode, 372805b261ecSmrg XID resId, int errorCode) 372905b261ecSmrg{ 3730f7df2e56Smrg xError rep = { 3731f7df2e56Smrg .type = X_Error, 3732f7df2e56Smrg .errorCode = errorCode, 3733f7df2e56Smrg .resourceID = resId, 3734f7df2e56Smrg .minorCode = minorCode, 3735f7df2e56Smrg .majorCode = majorCode 3736f7df2e56Smrg }; 373705b261ecSmrg 3738f7df2e56Smrg WriteEventsToClient(client, 1, (xEvent *) &rep); 373905b261ecSmrg} 374005b261ecSmrg 374105b261ecSmrgvoid 374205b261ecSmrgMarkClientException(ClientPtr client) 374305b261ecSmrg{ 374405b261ecSmrg client->noClientException = -1; 374505b261ecSmrg} 37466747b715Smrg 37476747b715Smrg/* 37486747b715Smrg * This array encodes the answer to the question "what is the log base 2 37496747b715Smrg * of the number of pixels that fit in a scanline pad unit?" 37506747b715Smrg * Note that ~0 is an invalid entry (mostly for the benefit of the reader). 37516747b715Smrg */ 37526747b715Smrgstatic int answer[6][4] = { 3753f7df2e56Smrg /* pad pad pad pad */ 3754f7df2e56Smrg /* 8 16 32 64 */ 3755f7df2e56Smrg 3756f7df2e56Smrg {3, 4, 5, 6}, /* 1 bit per pixel */ 3757f7df2e56Smrg {1, 2, 3, 4}, /* 4 bits per pixel */ 3758f7df2e56Smrg {0, 1, 2, 3}, /* 8 bits per pixel */ 3759f7df2e56Smrg {~0, 0, 1, 2}, /* 16 bits per pixel */ 3760f7df2e56Smrg {~0, ~0, 0, 1}, /* 24 bits per pixel */ 3761f7df2e56Smrg {~0, ~0, 0, 1} /* 32 bits per pixel */ 37626747b715Smrg}; 37636747b715Smrg 37646747b715Smrg/* 37656747b715Smrg * This array gives the answer to the question "what is the first index for 37666747b715Smrg * the answer array above given the number of bits per pixel?" 37676747b715Smrg * Note that ~0 is an invalid entry (mostly for the benefit of the reader). 37686747b715Smrg */ 3769f7df2e56Smrgstatic int indexForBitsPerPixel[33] = { 3770f7df2e56Smrg ~0, 0, ~0, ~0, /* 1 bit per pixel */ 3771f7df2e56Smrg 1, ~0, ~0, ~0, /* 4 bits per pixel */ 3772f7df2e56Smrg 2, ~0, ~0, ~0, /* 8 bits per pixel */ 3773f7df2e56Smrg ~0, ~0, ~0, ~0, 3774f7df2e56Smrg 3, ~0, ~0, ~0, /* 16 bits per pixel */ 3775f7df2e56Smrg ~0, ~0, ~0, ~0, 3776f7df2e56Smrg 4, ~0, ~0, ~0, /* 24 bits per pixel */ 3777f7df2e56Smrg ~0, ~0, ~0, ~0, 3778f7df2e56Smrg 5 /* 32 bits per pixel */ 37796747b715Smrg}; 37806747b715Smrg 37816747b715Smrg/* 37826747b715Smrg * This array gives the bytesperPixel value for cases where the number 37836747b715Smrg * of bits per pixel is a multiple of 8 but not a power of 2. 37846747b715Smrg */ 3785f7df2e56Smrgstatic int answerBytesPerPixel[33] = { 3786f7df2e56Smrg ~0, 0, ~0, ~0, /* 1 bit per pixel */ 3787f7df2e56Smrg 0, ~0, ~0, ~0, /* 4 bits per pixel */ 3788f7df2e56Smrg 0, ~0, ~0, ~0, /* 8 bits per pixel */ 3789f7df2e56Smrg ~0, ~0, ~0, ~0, 3790f7df2e56Smrg 0, ~0, ~0, ~0, /* 16 bits per pixel */ 3791f7df2e56Smrg ~0, ~0, ~0, ~0, 3792f7df2e56Smrg 3, ~0, ~0, ~0, /* 24 bits per pixel */ 3793f7df2e56Smrg ~0, ~0, ~0, ~0, 3794f7df2e56Smrg 0 /* 32 bits per pixel */ 37956747b715Smrg}; 37966747b715Smrg 37976747b715Smrg/* 37986747b715Smrg * This array gives the answer to the question "what is the second index for 37996747b715Smrg * the answer array above given the number of bits per scanline pad unit?" 38006747b715Smrg * Note that ~0 is an invalid entry (mostly for the benefit of the reader). 38016747b715Smrg */ 3802f7df2e56Smrgstatic int indexForScanlinePad[65] = { 3803f7df2e56Smrg ~0, ~0, ~0, ~0, 3804f7df2e56Smrg ~0, ~0, ~0, ~0, 3805f7df2e56Smrg 0, ~0, ~0, ~0, /* 8 bits per scanline pad unit */ 3806f7df2e56Smrg ~0, ~0, ~0, ~0, 3807f7df2e56Smrg 1, ~0, ~0, ~0, /* 16 bits per scanline pad unit */ 3808f7df2e56Smrg ~0, ~0, ~0, ~0, 3809f7df2e56Smrg ~0, ~0, ~0, ~0, 3810f7df2e56Smrg ~0, ~0, ~0, ~0, 3811f7df2e56Smrg 2, ~0, ~0, ~0, /* 32 bits per scanline pad unit */ 3812f7df2e56Smrg ~0, ~0, ~0, ~0, 3813f7df2e56Smrg ~0, ~0, ~0, ~0, 3814f7df2e56Smrg ~0, ~0, ~0, ~0, 3815f7df2e56Smrg ~0, ~0, ~0, ~0, 3816f7df2e56Smrg ~0, ~0, ~0, ~0, 3817f7df2e56Smrg ~0, ~0, ~0, ~0, 3818f7df2e56Smrg ~0, ~0, ~0, ~0, 3819f7df2e56Smrg 3 /* 64 bits per scanline pad unit */ 38206747b715Smrg}; 38216747b715Smrg 38226747b715Smrg/* 38236747b715Smrg grow the array of screenRecs if necessary. 38246747b715Smrg call the device-supplied initialization procedure 38256747b715Smrgwith its screen number, a pointer to its ScreenRec, argc, and argv. 38266747b715Smrg return the number of successfully installed screens. 38276747b715Smrg 38286747b715Smrg*/ 38296747b715Smrg 3830f7df2e56Smrgstatic int init_screen(ScreenPtr pScreen, int i, Bool gpu) 38316747b715Smrg{ 38326747b715Smrg int scanlinepad, format, depth, bitsPerPixel, j, k; 38336747b715Smrg 3834f7df2e56Smrg dixInitScreenSpecificPrivates(pScreen); 38356747b715Smrg 38366747b715Smrg if (!dixAllocatePrivates(&pScreen->devPrivates, PRIVATE_SCREEN)) { 3837f7df2e56Smrg return -1; 38386747b715Smrg } 38396747b715Smrg pScreen->myNum = i; 3840f7df2e56Smrg if (gpu) { 3841f7df2e56Smrg pScreen->myNum += GPU_SCREEN_OFFSET; 3842f7df2e56Smrg pScreen->isGPU = TRUE; 3843f7df2e56Smrg } 3844f7df2e56Smrg pScreen->totalPixmapSize = 0; /* computed in CreateScratchPixmapForScreen */ 3845f7df2e56Smrg pScreen->ClipNotify = 0; /* for R4 ddx compatibility */ 38466747b715Smrg pScreen->CreateScreenResources = 0; 38476747b715Smrg 3848f7df2e56Smrg xorg_list_init(&pScreen->pixmap_dirty_list); 38497e31ba66Smrg xorg_list_init(&pScreen->slave_list); 3850f7df2e56Smrg 38516747b715Smrg /* 38526747b715Smrg * This loop gets run once for every Screen that gets added, 38536747b715Smrg * but thats ok. If the ddx layer initializes the formats 38546747b715Smrg * one at a time calling AddScreen() after each, then each 38556747b715Smrg * iteration will make it a little more accurate. Worst case 38566747b715Smrg * we do this loop N * numPixmapFormats where N is # of screens. 38576747b715Smrg * Anyway, this must be called after InitOutput and before the 38586747b715Smrg * screen init routine is called. 38596747b715Smrg */ 3860f7df2e56Smrg for (format = 0; format < screenInfo.numPixmapFormats; format++) { 3861f7df2e56Smrg depth = screenInfo.formats[format].depth; 3862f7df2e56Smrg bitsPerPixel = screenInfo.formats[format].bitsPerPixel; 3863f7df2e56Smrg scanlinepad = screenInfo.formats[format].scanlinePad; 3864f7df2e56Smrg j = indexForBitsPerPixel[bitsPerPixel]; 3865f7df2e56Smrg k = indexForScanlinePad[scanlinepad]; 3866f7df2e56Smrg PixmapWidthPaddingInfo[depth].padPixelsLog2 = answer[j][k]; 3867f7df2e56Smrg PixmapWidthPaddingInfo[depth].padRoundUp = 3868f7df2e56Smrg (scanlinepad / bitsPerPixel) - 1; 3869f7df2e56Smrg j = indexForBitsPerPixel[8]; /* bits per byte */ 3870f7df2e56Smrg PixmapWidthPaddingInfo[depth].padBytesLog2 = answer[j][k]; 3871f7df2e56Smrg PixmapWidthPaddingInfo[depth].bitsPerPixel = bitsPerPixel; 3872f7df2e56Smrg if (answerBytesPerPixel[bitsPerPixel]) { 3873f7df2e56Smrg PixmapWidthPaddingInfo[depth].notPower2 = 1; 3874f7df2e56Smrg PixmapWidthPaddingInfo[depth].bytesPerPixel = 3875f7df2e56Smrg answerBytesPerPixel[bitsPerPixel]; 3876f7df2e56Smrg } 3877f7df2e56Smrg else { 3878f7df2e56Smrg PixmapWidthPaddingInfo[depth].notPower2 = 0; 3879f7df2e56Smrg } 38806747b715Smrg } 3881f7df2e56Smrg return 0; 3882f7df2e56Smrg} 3883f7df2e56Smrg 3884f7df2e56Smrgint 3885f7df2e56SmrgAddScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ , 3886f7df2e56Smrg int /*argc */ , 3887f7df2e56Smrg char ** /*argv */ 3888f7df2e56Smrg ), int argc, char **argv) 3889f7df2e56Smrg{ 3890f7df2e56Smrg 3891f7df2e56Smrg int i; 3892f7df2e56Smrg ScreenPtr pScreen; 3893f7df2e56Smrg Bool ret; 3894f7df2e56Smrg 3895f7df2e56Smrg i = screenInfo.numScreens; 3896f7df2e56Smrg if (i == MAXSCREENS) 3897f7df2e56Smrg return -1; 3898f7df2e56Smrg 3899f7df2e56Smrg pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec)); 3900f7df2e56Smrg if (!pScreen) 3901f7df2e56Smrg return -1; 39026747b715Smrg 3903f7df2e56Smrg ret = init_screen(pScreen, i, FALSE); 3904f7df2e56Smrg if (ret != 0) { 3905f7df2e56Smrg free(pScreen); 3906f7df2e56Smrg return ret; 3907f7df2e56Smrg } 39086747b715Smrg /* This is where screen specific stuff gets initialized. Load the 39096747b715Smrg screen structure, call the hardware, whatever. 39106747b715Smrg This is also where the default colormap should be allocated and 39116747b715Smrg also pixel values for blackPixel, whitePixel, and the cursor 39126747b715Smrg Note that InitScreen is NOT allowed to modify argc, argv, or 39136747b715Smrg any of the strings pointed to by argv. They may be passed to 39146747b715Smrg multiple screens. 3915f7df2e56Smrg */ 39166747b715Smrg screenInfo.screens[i] = pScreen; 39176747b715Smrg screenInfo.numScreens++; 3918f7df2e56Smrg if (!(*pfnInit) (pScreen, argc, argv)) { 3919f7df2e56Smrg dixFreeScreenSpecificPrivates(pScreen); 3920f7df2e56Smrg dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN); 3921f7df2e56Smrg free(pScreen); 3922f7df2e56Smrg screenInfo.numScreens--; 3923f7df2e56Smrg return -1; 39246747b715Smrg } 39256747b715Smrg 3926f7df2e56Smrg update_desktop_dimensions(); 3927f7df2e56Smrg 3928f7df2e56Smrg dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen, PRIVATE_CURSOR, 3929f7df2e56Smrg 0); 39306747b715Smrg 39316747b715Smrg return i; 39326747b715Smrg} 3933f7df2e56Smrg 3934f7df2e56Smrgint 3935f7df2e56SmrgAddGPUScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ , 3936f7df2e56Smrg int /*argc */ , 3937f7df2e56Smrg char ** /*argv */ 3938f7df2e56Smrg ), 3939f7df2e56Smrg int argc, char **argv) 3940f7df2e56Smrg{ 3941f7df2e56Smrg int i; 3942f7df2e56Smrg ScreenPtr pScreen; 3943f7df2e56Smrg Bool ret; 3944f7df2e56Smrg 3945f7df2e56Smrg i = screenInfo.numGPUScreens; 3946f7df2e56Smrg if (i == MAXGPUSCREENS) 3947f7df2e56Smrg return -1; 3948f7df2e56Smrg 3949f7df2e56Smrg pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec)); 3950f7df2e56Smrg if (!pScreen) 3951f7df2e56Smrg return -1; 3952f7df2e56Smrg 3953f7df2e56Smrg ret = init_screen(pScreen, i, TRUE); 3954f7df2e56Smrg if (ret != 0) { 3955f7df2e56Smrg free(pScreen); 3956f7df2e56Smrg return ret; 3957f7df2e56Smrg } 3958f7df2e56Smrg 3959f7df2e56Smrg /* This is where screen specific stuff gets initialized. Load the 3960f7df2e56Smrg screen structure, call the hardware, whatever. 3961f7df2e56Smrg This is also where the default colormap should be allocated and 3962f7df2e56Smrg also pixel values for blackPixel, whitePixel, and the cursor 3963f7df2e56Smrg Note that InitScreen is NOT allowed to modify argc, argv, or 3964f7df2e56Smrg any of the strings pointed to by argv. They may be passed to 3965f7df2e56Smrg multiple screens. 3966f7df2e56Smrg */ 3967f7df2e56Smrg screenInfo.gpuscreens[i] = pScreen; 3968f7df2e56Smrg screenInfo.numGPUScreens++; 3969f7df2e56Smrg if (!(*pfnInit) (pScreen, argc, argv)) { 3970f7df2e56Smrg dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN); 3971f7df2e56Smrg free(pScreen); 3972f7df2e56Smrg screenInfo.numGPUScreens--; 3973f7df2e56Smrg return -1; 3974f7df2e56Smrg } 3975f7df2e56Smrg 3976f7df2e56Smrg update_desktop_dimensions(); 3977f7df2e56Smrg 39787e31ba66Smrg /* 39797e31ba66Smrg * We cannot register the Screen PRIVATE_CURSOR key if cursors are already 39807e31ba66Smrg * created, because dix/privates.c does not have relocation code for 39817e31ba66Smrg * PRIVATE_CURSOR. Once this is fixed the if() can be removed and we can 39827e31ba66Smrg * register the Screen PRIVATE_CURSOR key unconditionally. 39837e31ba66Smrg */ 39847e31ba66Smrg if (!dixPrivatesCreated(PRIVATE_CURSOR)) 39857e31ba66Smrg dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen, 39867e31ba66Smrg PRIVATE_CURSOR, 0); 39877e31ba66Smrg 3988f7df2e56Smrg return i; 3989f7df2e56Smrg} 3990f7df2e56Smrg 3991f7df2e56Smrgvoid 3992f7df2e56SmrgRemoveGPUScreen(ScreenPtr pScreen) 3993f7df2e56Smrg{ 3994f7df2e56Smrg int idx, j; 3995f7df2e56Smrg if (!pScreen->isGPU) 3996f7df2e56Smrg return; 3997f7df2e56Smrg 3998f7df2e56Smrg idx = pScreen->myNum - GPU_SCREEN_OFFSET; 3999f7df2e56Smrg for (j = idx; j < screenInfo.numGPUScreens - 1; j++) { 4000f7df2e56Smrg screenInfo.gpuscreens[j] = screenInfo.gpuscreens[j + 1]; 4001f7df2e56Smrg screenInfo.gpuscreens[j]->myNum = j + GPU_SCREEN_OFFSET; 4002f7df2e56Smrg } 4003f7df2e56Smrg screenInfo.numGPUScreens--; 4004f7df2e56Smrg 4005f7df2e56Smrg /* this gets freed later in the resource list, but without 4006f7df2e56Smrg * the screen existing it causes crashes - so remove it here */ 4007f7df2e56Smrg if (pScreen->defColormap) 4008f7df2e56Smrg FreeResource(pScreen->defColormap, RT_COLORMAP); 4009f7df2e56Smrg free(pScreen); 4010f7df2e56Smrg 4011f7df2e56Smrg} 4012f7df2e56Smrg 4013f7df2e56Smrgvoid 4014f7df2e56SmrgAttachUnboundGPU(ScreenPtr pScreen, ScreenPtr new) 4015f7df2e56Smrg{ 4016f7df2e56Smrg assert(new->isGPU); 4017f7df2e56Smrg assert(!new->current_master); 40187e31ba66Smrg xorg_list_add(&new->slave_head, &pScreen->slave_list); 4019f7df2e56Smrg new->current_master = pScreen; 4020f7df2e56Smrg} 4021f7df2e56Smrg 4022f7df2e56Smrgvoid 4023f7df2e56SmrgDetachUnboundGPU(ScreenPtr slave) 4024f7df2e56Smrg{ 4025f7df2e56Smrg assert(slave->isGPU); 40267e31ba66Smrg assert(!slave->is_output_slave); 40277e31ba66Smrg assert(!slave->is_offload_slave); 40287e31ba66Smrg xorg_list_del(&slave->slave_head); 4029f7df2e56Smrg slave->current_master = NULL; 4030f7df2e56Smrg} 4031f7df2e56Smrg 4032f7df2e56Smrgvoid 4033f7df2e56SmrgAttachOutputGPU(ScreenPtr pScreen, ScreenPtr new) 4034f7df2e56Smrg{ 4035f7df2e56Smrg assert(new->isGPU); 40367e31ba66Smrg assert(!new->is_output_slave); 40377e31ba66Smrg assert(new->current_master == pScreen); 40387e31ba66Smrg new->is_output_slave = TRUE; 40397e31ba66Smrg new->current_master->output_slaves++; 4040f7df2e56Smrg} 4041f7df2e56Smrg 4042f7df2e56Smrgvoid 4043f7df2e56SmrgDetachOutputGPU(ScreenPtr slave) 4044f7df2e56Smrg{ 4045f7df2e56Smrg assert(slave->isGPU); 40467e31ba66Smrg assert(slave->is_output_slave); 40477e31ba66Smrg slave->current_master->output_slaves--; 40487e31ba66Smrg slave->is_output_slave = FALSE; 4049f7df2e56Smrg} 4050f7df2e56Smrg 4051f7df2e56Smrgvoid 4052f7df2e56SmrgAttachOffloadGPU(ScreenPtr pScreen, ScreenPtr new) 4053f7df2e56Smrg{ 4054f7df2e56Smrg assert(new->isGPU); 40557e31ba66Smrg assert(!new->is_offload_slave); 40567e31ba66Smrg assert(new->current_master == pScreen); 40577e31ba66Smrg new->is_offload_slave = TRUE; 4058f7df2e56Smrg} 4059f7df2e56Smrg 4060f7df2e56Smrgvoid 4061f7df2e56SmrgDetachOffloadGPU(ScreenPtr slave) 4062f7df2e56Smrg{ 4063f7df2e56Smrg assert(slave->isGPU); 40647e31ba66Smrg assert(slave->is_offload_slave); 40657e31ba66Smrg slave->is_offload_slave = FALSE; 4066f7df2e56Smrg} 4067f7df2e56Smrg 4068