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