dispatch.c revision 7e31ba66
105b261ecSmrg/************************************************************ 205b261ecSmrg 305b261ecSmrgCopyright 1987, 1989, 1998 The Open Group 405b261ecSmrg 505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its 605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that 705b261ecSmrgthe above copyright notice appear in all copies and that both that 805b261ecSmrgcopyright notice and this permission notice appear in supporting 905b261ecSmrgdocumentation. 1005b261ecSmrg 1105b261ecSmrgThe above copyright notice and this permission notice shall be included in 1205b261ecSmrgall copies or substantial portions of the Software. 1305b261ecSmrg 1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2005b261ecSmrg 2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be 2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings 2305b261ecSmrgin this Software without prior written authorization from The Open Group. 2405b261ecSmrg 2505b261ecSmrgCopyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. 2605b261ecSmrg 2705b261ecSmrg All Rights Reserved 2805b261ecSmrg 29f7df2e56SmrgPermission to use, copy, modify, and distribute this software and its 30f7df2e56Smrgdocumentation for any purpose and without fee is hereby granted, 3105b261ecSmrgprovided that the above copyright notice appear in all copies and that 32f7df2e56Smrgboth that copyright notice and this permission notice appear in 3305b261ecSmrgsupporting documentation, and that the name of Digital not be 3405b261ecSmrgused in advertising or publicity pertaining to distribution of the 35f7df2e56Smrgsoftware without specific, written prior permission. 3605b261ecSmrg 3705b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 3805b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 3905b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 4005b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 4105b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 4205b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 4305b261ecSmrgSOFTWARE. 4405b261ecSmrg 4505b261ecSmrg********************************************************/ 4605b261ecSmrg 4705b261ecSmrg/* The panoramix components contained the following notice */ 4805b261ecSmrg/***************************************************************** 4905b261ecSmrg 5005b261ecSmrgCopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. 5105b261ecSmrg 5205b261ecSmrgPermission is hereby granted, free of charge, to any person obtaining a copy 5305b261ecSmrgof this software and associated documentation files (the "Software"), to deal 5405b261ecSmrgin the Software without restriction, including without limitation the rights 5505b261ecSmrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell 5605b261ecSmrgcopies of the Software. 5705b261ecSmrg 5805b261ecSmrgThe above copyright notice and this permission notice shall be included in 5905b261ecSmrgall copies or substantial portions of the Software. 6005b261ecSmrg 6105b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 6205b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6305b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 6405b261ecSmrgDIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, 6505b261ecSmrgBUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, 6605b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 6705b261ecSmrgIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 6805b261ecSmrg 6905b261ecSmrgExcept as contained in this notice, the name of Digital Equipment Corporation 7005b261ecSmrgshall not be used in advertising or otherwise to promote the sale, use or other 7105b261ecSmrgdealings in this Software without prior written authorization from Digital 7205b261ecSmrgEquipment Corporation. 7305b261ecSmrg 7405b261ecSmrg******************************************************************/ 7505b261ecSmrg 7605b261ecSmrg/* XSERVER_DTRACE additions: 779ace9065Smrg * Copyright (c) 2005-2006, Oracle and/or its affiliates. All rights reserved. 7805b261ecSmrg * 7905b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a 806747b715Smrg * copy of this software and associated documentation files (the "Software"), 816747b715Smrg * to deal in the Software without restriction, including without limitation 826747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 836747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the 846747b715Smrg * Software is furnished to do so, subject to the following conditions: 856747b715Smrg * 866747b715Smrg * The above copyright notice and this permission notice (including the next 876747b715Smrg * paragraph) shall be included in all copies or substantial portions of the 886747b715Smrg * Software. 896747b715Smrg * 906747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 916747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 926747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 936747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 946747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 956747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 966747b715Smrg * DEALINGS IN THE SOFTWARE. 9705b261ecSmrg */ 9805b261ecSmrg 9905b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 10005b261ecSmrg#include <dix-config.h> 1016747b715Smrg#include <version-config.h> 10205b261ecSmrg#endif 10305b261ecSmrg 10405b261ecSmrg#ifdef PANORAMIX_DEBUG 10505b261ecSmrg#include <stdio.h> 10605b261ecSmrgint ProcInitialConnection(); 10705b261ecSmrg#endif 10805b261ecSmrg 10905b261ecSmrg#include "windowstr.h" 11005b261ecSmrg#include <X11/fonts/fontstruct.h> 1117e31ba66Smrg#include <X11/fonts/libxfont2.h> 11205b261ecSmrg#include "dixfontstr.h" 11305b261ecSmrg#include "gcstruct.h" 11405b261ecSmrg#include "selection.h" 11505b261ecSmrg#include "colormapst.h" 11605b261ecSmrg#include "cursorstr.h" 11705b261ecSmrg#include "scrnintstr.h" 11805b261ecSmrg#include "opaque.h" 11905b261ecSmrg#include "input.h" 12005b261ecSmrg#include "servermd.h" 12105b261ecSmrg#include "extnsionst.h" 12205b261ecSmrg#include "dixfont.h" 12305b261ecSmrg#include "dispatch.h" 12405b261ecSmrg#include "swaprep.h" 12505b261ecSmrg#include "swapreq.h" 1264642e01fSmrg#include "privates.h" 12705b261ecSmrg#include "xace.h" 12805b261ecSmrg#include "inputstr.h" 1296747b715Smrg#include "xkbsrv.h" 1306747b715Smrg#include "site.h" 131f7df2e56Smrg#include "client.h" 13205b261ecSmrg 13305b261ecSmrg#ifdef XSERVER_DTRACE 1344642e01fSmrg#include "registry.h" 135f7df2e56Smrg#include "probes.h" 13605b261ecSmrg#endif 13705b261ecSmrg 13805b261ecSmrg#define mskcnt ((MAXCLIENTS + 31) / 32) 13905b261ecSmrg#define BITMASK(i) (1U << ((i) & 31)) 14005b261ecSmrg#define MASKIDX(i) ((i) >> 5) 14105b261ecSmrg#define MASKWORD(buf, i) buf[MASKIDX(i)] 14205b261ecSmrg#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i) 14305b261ecSmrg#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i) 14405b261ecSmrg#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i)) 14505b261ecSmrg 1466747b715SmrgxConnSetupPrefix connSetupPrefix; 1476747b715Smrg 1486747b715SmrgPaddingInfo PixmapWidthPaddingInfo[33]; 14905b261ecSmrg 15005b261ecSmrgstatic ClientPtr grabClient; 151f7df2e56Smrg 15205b261ecSmrg#define GrabNone 0 15305b261ecSmrg#define GrabActive 1 15405b261ecSmrgstatic int grabState = GrabNone; 15505b261ecSmrgstatic long grabWaiters[mskcnt]; 1566747b715SmrgCallbackListPtr ServerGrabCallback = NULL; 15705b261ecSmrgHWEventQueuePtr checkForInput[2]; 1586747b715Smrgint connBlockScreenStart; 15905b261ecSmrg 16005b261ecSmrgstatic void KillAllClients(void); 16105b261ecSmrg 162f7df2e56Smrgstatic int nextFreeClientID; /* always MIN free client ID */ 16305b261ecSmrg 164f7df2e56Smrgstatic int nClients; /* number of authorized clients */ 16505b261ecSmrg 1666747b715SmrgCallbackListPtr ClientStateCallback; 16705b261ecSmrg 16805b261ecSmrg/* dispatchException & isItTimeToYield must be declared volatile since they 16905b261ecSmrg * are modified by signal handlers - otherwise optimizer may assume it doesn't 17005b261ecSmrg * need to actually check value in memory when used and may miss changes from 17105b261ecSmrg * signal handlers. 17205b261ecSmrg */ 1736747b715Smrgvolatile char dispatchException = 0; 1746747b715Smrgvolatile char isItTimeToYield; 17505b261ecSmrg 17605b261ecSmrg#define SAME_SCREENS(a, b) (\ 17705b261ecSmrg (a.pScreen == b.pScreen)) 17805b261ecSmrg 1794642e01fSmrgvoid 18005b261ecSmrgSetInputCheck(HWEventQueuePtr c0, HWEventQueuePtr c1) 18105b261ecSmrg{ 18205b261ecSmrg checkForInput[0] = c0; 18305b261ecSmrg checkForInput[1] = c1; 18405b261ecSmrg} 18505b261ecSmrg 1866747b715Smrgvoid 18705b261ecSmrgUpdateCurrentTime(void) 18805b261ecSmrg{ 18905b261ecSmrg TimeStamp systime; 19005b261ecSmrg 19105b261ecSmrg /* To avoid time running backwards, we must call GetTimeInMillis before 19205b261ecSmrg * calling ProcessInputEvents. 19305b261ecSmrg */ 19405b261ecSmrg systime.months = currentTime.months; 19505b261ecSmrg systime.milliseconds = GetTimeInMillis(); 19605b261ecSmrg if (systime.milliseconds < currentTime.milliseconds) 197f7df2e56Smrg systime.months++; 1987e31ba66Smrg if (InputCheckPending()) 199f7df2e56Smrg ProcessInputEvents(); 20005b261ecSmrg if (CompareTimeStamps(systime, currentTime) == LATER) 201f7df2e56Smrg currentTime = systime; 20205b261ecSmrg} 20305b261ecSmrg 20405b261ecSmrg/* Like UpdateCurrentTime, but can't call ProcessInputEvents */ 2056747b715Smrgvoid 20605b261ecSmrgUpdateCurrentTimeIf(void) 20705b261ecSmrg{ 20805b261ecSmrg TimeStamp systime; 20905b261ecSmrg 21005b261ecSmrg systime.months = currentTime.months; 21105b261ecSmrg systime.milliseconds = GetTimeInMillis(); 21205b261ecSmrg if (systime.milliseconds < currentTime.milliseconds) 213f7df2e56Smrg systime.months++; 214f7df2e56Smrg if (CompareTimeStamps(systime, currentTime) == LATER) 215f7df2e56Smrg currentTime = systime; 21605b261ecSmrg} 21705b261ecSmrg 21805b261ecSmrg#undef SMART_DEBUG 21905b261ecSmrg 220f7df2e56Smrg/* in milliseconds */ 221f7df2e56Smrg#define SMART_SCHEDULE_DEFAULT_INTERVAL 5 222f7df2e56Smrg#define SMART_SCHEDULE_MAX_SLICE 15 22305b261ecSmrg 2247e31ba66Smrg#ifdef HAVE_SETITIMER 2257e31ba66SmrgBool SmartScheduleSignalEnable = TRUE; 226f7df2e56Smrg#endif 2277e31ba66Smrg 2286747b715Smrglong SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL; 2296747b715Smrglong SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL; 2306747b715Smrglong SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE; 2316747b715Smrglong SmartScheduleTime; 2326747b715Smrgint SmartScheduleLatencyLimited = 0; 233f7df2e56Smrgstatic ClientPtr SmartLastClient; 234f7df2e56Smrgstatic int SmartLastIndex[SMART_MAX_PRIORITY - SMART_MIN_PRIORITY + 1]; 23505b261ecSmrg 23605b261ecSmrg#ifdef SMART_DEBUG 237f7df2e56Smrglong SmartLastPrint; 23805b261ecSmrg#endif 23905b261ecSmrg 240f7df2e56Smrgvoid Dispatch(void); 24105b261ecSmrg 2427e31ba66Smrgstatic struct xorg_list ready_clients; 2437e31ba66Smrgstatic struct xorg_list saved_ready_clients; 2447e31ba66Smrgstruct xorg_list output_pending_clients; 2457e31ba66Smrg 2467e31ba66Smrgstatic void 2477e31ba66Smrginit_client_ready(void) 24805b261ecSmrg{ 2497e31ba66Smrg xorg_list_init(&ready_clients); 2507e31ba66Smrg xorg_list_init(&saved_ready_clients); 2517e31ba66Smrg xorg_list_init(&output_pending_clients); 2527e31ba66Smrg} 2537e31ba66Smrg 2547e31ba66SmrgBool 2557e31ba66Smrgclients_are_ready(void) 2567e31ba66Smrg{ 2577e31ba66Smrg return !xorg_list_is_empty(&ready_clients); 2587e31ba66Smrg} 2597e31ba66Smrg 2607e31ba66Smrg/* Client has requests queued or data on the network */ 2617e31ba66Smrgvoid 2627e31ba66Smrgmark_client_ready(ClientPtr client) 2637e31ba66Smrg{ 2647e31ba66Smrg if (xorg_list_is_empty(&client->ready)) 2657e31ba66Smrg xorg_list_append(&client->ready, &ready_clients); 2667e31ba66Smrg} 2677e31ba66Smrg 2687e31ba66Smrg/* 2697e31ba66Smrg * Client has requests queued or data on the network, but awaits a 2707e31ba66Smrg * server grab release 2717e31ba66Smrg */ 2727e31ba66Smrgvoid mark_client_saved_ready(ClientPtr client) 2737e31ba66Smrg{ 2747e31ba66Smrg if (xorg_list_is_empty(&client->ready)) 2757e31ba66Smrg xorg_list_append(&client->ready, &saved_ready_clients); 2767e31ba66Smrg} 2777e31ba66Smrg 2787e31ba66Smrg/* Client has no requests queued and no data on network */ 2797e31ba66Smrgvoid 2807e31ba66Smrgmark_client_not_ready(ClientPtr client) 2817e31ba66Smrg{ 2827e31ba66Smrg xorg_list_del(&client->ready); 2837e31ba66Smrg} 2847e31ba66Smrg 2857e31ba66Smrgstatic void 2867e31ba66Smrgmark_client_grab(ClientPtr grab) 2877e31ba66Smrg{ 2887e31ba66Smrg ClientPtr client, tmp; 2897e31ba66Smrg 2907e31ba66Smrg xorg_list_for_each_entry_safe(client, tmp, &ready_clients, ready) { 2917e31ba66Smrg if (client != grab) { 2927e31ba66Smrg xorg_list_del(&client->ready); 2937e31ba66Smrg xorg_list_append(&client->ready, &saved_ready_clients); 2947e31ba66Smrg } 2957e31ba66Smrg } 2967e31ba66Smrg} 2977e31ba66Smrg 2987e31ba66Smrgstatic void 2997e31ba66Smrgmark_client_ungrab(void) 3007e31ba66Smrg{ 3017e31ba66Smrg ClientPtr client, tmp; 3027e31ba66Smrg 3037e31ba66Smrg xorg_list_for_each_entry_safe(client, tmp, &saved_ready_clients, ready) { 3047e31ba66Smrg xorg_list_del(&client->ready); 3057e31ba66Smrg xorg_list_append(&client->ready, &ready_clients); 3067e31ba66Smrg } 3077e31ba66Smrg} 3087e31ba66Smrg 3097e31ba66Smrgstatic ClientPtr 3107e31ba66SmrgSmartScheduleClient(void) 3117e31ba66Smrg{ 3127e31ba66Smrg ClientPtr pClient, best = NULL; 313f7df2e56Smrg int bestRobin, robin; 314f7df2e56Smrg long now = SmartScheduleTime; 315f7df2e56Smrg long idle; 3167e31ba66Smrg int nready = 0; 31705b261ecSmrg 31805b261ecSmrg bestRobin = 0; 31905b261ecSmrg idle = 2 * SmartScheduleSlice; 3207e31ba66Smrg 3217e31ba66Smrg xorg_list_for_each_entry(pClient, &ready_clients, ready) { 3227e31ba66Smrg nready++; 3237e31ba66Smrg 324f7df2e56Smrg /* Praise clients which haven't run in a while */ 325f7df2e56Smrg if ((now - pClient->smart_stop_tick) >= idle) { 326f7df2e56Smrg if (pClient->smart_priority < 0) 327f7df2e56Smrg pClient->smart_priority++; 328f7df2e56Smrg } 329f7df2e56Smrg 330f7df2e56Smrg /* check priority to select best client */ 331f7df2e56Smrg robin = 332f7df2e56Smrg (pClient->index - 333f7df2e56Smrg SmartLastIndex[pClient->smart_priority - 334f7df2e56Smrg SMART_MIN_PRIORITY]) & 0xff; 3357e31ba66Smrg 3367e31ba66Smrg /* pick the best client */ 3377e31ba66Smrg if (!best || 3387e31ba66Smrg pClient->priority > best->priority || 3397e31ba66Smrg (pClient->priority == best->priority && 3407e31ba66Smrg (pClient->smart_priority > best->smart_priority || 3417e31ba66Smrg (pClient->smart_priority == best->smart_priority && robin > bestRobin)))) 3427e31ba66Smrg { 3437e31ba66Smrg best = pClient; 344f7df2e56Smrg bestRobin = robin; 345f7df2e56Smrg } 34605b261ecSmrg#ifdef SMART_DEBUG 347f7df2e56Smrg if ((now - SmartLastPrint) >= 5000) 3487e31ba66Smrg fprintf(stderr, " %2d: %3d", pClient->index, pClient->smart_priority); 34905b261ecSmrg#endif 35005b261ecSmrg } 35105b261ecSmrg#ifdef SMART_DEBUG 352f7df2e56Smrg if ((now - SmartLastPrint) >= 5000) { 3537e31ba66Smrg fprintf(stderr, " use %2d\n", best->index); 354f7df2e56Smrg SmartLastPrint = now; 35505b261ecSmrg } 35605b261ecSmrg#endif 3577e31ba66Smrg SmartLastIndex[best->smart_priority - SMART_MIN_PRIORITY] = best->index; 35805b261ecSmrg /* 35905b261ecSmrg * Set current client pointer 36005b261ecSmrg */ 3617e31ba66Smrg if (SmartLastClient != best) { 3627e31ba66Smrg best->smart_start_tick = now; 3637e31ba66Smrg SmartLastClient = best; 36405b261ecSmrg } 36505b261ecSmrg /* 36605b261ecSmrg * Adjust slice 36705b261ecSmrg */ 368f7df2e56Smrg if (nready == 1 && SmartScheduleLatencyLimited == 0) { 369f7df2e56Smrg /* 370f7df2e56Smrg * If it's been a long time since another client 371f7df2e56Smrg * has run, bump the slice up to get maximal 372f7df2e56Smrg * performance from a single client 373f7df2e56Smrg */ 3747e31ba66Smrg if ((now - best->smart_start_tick) > 1000 && 375f7df2e56Smrg SmartScheduleSlice < SmartScheduleMaxSlice) { 376f7df2e56Smrg SmartScheduleSlice += SmartScheduleInterval; 377f7df2e56Smrg } 37805b261ecSmrg } 379f7df2e56Smrg else { 380f7df2e56Smrg SmartScheduleSlice = SmartScheduleInterval; 38105b261ecSmrg } 38205b261ecSmrg return best; 38305b261ecSmrg} 38405b261ecSmrg 385b1d344b3Smrgvoid 386b1d344b3SmrgEnableLimitedSchedulingLatency(void) 387b1d344b3Smrg{ 388b1d344b3Smrg ++SmartScheduleLatencyLimited; 389b1d344b3Smrg SmartScheduleSlice = SmartScheduleInterval; 390b1d344b3Smrg} 391b1d344b3Smrg 392b1d344b3Smrgvoid 393b1d344b3SmrgDisableLimitedSchedulingLatency(void) 394b1d344b3Smrg{ 395b1d344b3Smrg --SmartScheduleLatencyLimited; 396b1d344b3Smrg 397b1d344b3Smrg /* protect against bugs */ 398b1d344b3Smrg if (SmartScheduleLatencyLimited < 0) 399f7df2e56Smrg SmartScheduleLatencyLimited = 0; 400b1d344b3Smrg} 401b1d344b3Smrg 40205b261ecSmrgvoid 40305b261ecSmrgDispatch(void) 40405b261ecSmrg{ 405f7df2e56Smrg int result; 406f7df2e56Smrg ClientPtr client; 407f7df2e56Smrg long start_tick; 40805b261ecSmrg 40905b261ecSmrg nextFreeClientID = 1; 41005b261ecSmrg nClients = 0; 41105b261ecSmrg 412b1d344b3Smrg SmartScheduleSlice = SmartScheduleInterval; 4137e31ba66Smrg init_client_ready(); 4147e31ba66Smrg 415f7df2e56Smrg while (!dispatchException) { 4167e31ba66Smrg if (InputCheckPending()) { 417f7df2e56Smrg ProcessInputEvents(); 418f7df2e56Smrg FlushIfCriticalOutputPending(); 419f7df2e56Smrg } 420f7df2e56Smrg 4217e31ba66Smrg if (!WaitForSomething(clients_are_ready())) 4227e31ba66Smrg continue; 423f7df2e56Smrg 424f7df2e56Smrg /***************** 425f7df2e56Smrg * Handle events in round robin fashion, doing input between 426f7df2e56Smrg * each round 42705b261ecSmrg *****************/ 42805b261ecSmrg 4297e31ba66Smrg if (!dispatchException && clients_are_ready()) { 4307e31ba66Smrg client = SmartScheduleClient(); 4317e31ba66Smrg 432f7df2e56Smrg isItTimeToYield = FALSE; 433f7df2e56Smrg 434f7df2e56Smrg start_tick = SmartScheduleTime; 435f7df2e56Smrg while (!isItTimeToYield) { 4367e31ba66Smrg if (InputCheckPending()) 437f7df2e56Smrg ProcessInputEvents(); 438f7df2e56Smrg 439f7df2e56Smrg FlushIfCriticalOutputPending(); 4407e31ba66Smrg if ((SmartScheduleTime - start_tick) >= SmartScheduleSlice) 4417e31ba66Smrg { 442f7df2e56Smrg /* Penalize clients which consume ticks */ 443f7df2e56Smrg if (client->smart_priority > SMART_MIN_PRIORITY) 444f7df2e56Smrg client->smart_priority--; 445f7df2e56Smrg break; 446f7df2e56Smrg } 447f7df2e56Smrg 4487e31ba66Smrg /* now, finally, deal with client requests */ 449f7df2e56Smrg result = ReadRequestFromClient(client); 450f7df2e56Smrg if (result <= 0) { 451f7df2e56Smrg if (result < 0) 452f7df2e56Smrg CloseDownClient(client); 453f7df2e56Smrg break; 454f7df2e56Smrg } 455f7df2e56Smrg 456f7df2e56Smrg client->sequence++; 457f7df2e56Smrg client->majorOp = ((xReq *) client->requestBuffer)->reqType; 458f7df2e56Smrg client->minorOp = 0; 459f7df2e56Smrg if (client->majorOp >= EXTENSION_BASE) { 460f7df2e56Smrg ExtensionEntry *ext = GetExtensionEntry(client->majorOp); 461f7df2e56Smrg 462f7df2e56Smrg if (ext) 463f7df2e56Smrg client->minorOp = ext->MinorOpcode(client); 464f7df2e56Smrg } 46505b261ecSmrg#ifdef XSERVER_DTRACE 466f7df2e56Smrg if (XSERVER_REQUEST_START_ENABLED()) 467f7df2e56Smrg XSERVER_REQUEST_START(LookupMajorName(client->majorOp), 468f7df2e56Smrg client->majorOp, 469f7df2e56Smrg ((xReq *) client->requestBuffer)->length, 470f7df2e56Smrg client->index, 471f7df2e56Smrg client->requestBuffer); 47205b261ecSmrg#endif 473f7df2e56Smrg if (result > (maxBigRequestSize << 2)) 474f7df2e56Smrg result = BadLength; 475f7df2e56Smrg else { 476f7df2e56Smrg result = XaceHookDispatch(client, client->majorOp); 477f7df2e56Smrg if (result == Success) 478f7df2e56Smrg result = 479f7df2e56Smrg (*client->requestVector[client->majorOp]) (client); 480f7df2e56Smrg } 4817e31ba66Smrg if (!SmartScheduleSignalEnable) 4827e31ba66Smrg SmartScheduleTime = GetTimeInMillis(); 4837e31ba66Smrg 48405b261ecSmrg#ifdef XSERVER_DTRACE 485f7df2e56Smrg if (XSERVER_REQUEST_DONE_ENABLED()) 486f7df2e56Smrg XSERVER_REQUEST_DONE(LookupMajorName(client->majorOp), 487f7df2e56Smrg client->majorOp, client->sequence, 488f7df2e56Smrg client->index, result); 48905b261ecSmrg#endif 49005b261ecSmrg 491f7df2e56Smrg if (client->noClientException != Success) { 492f7df2e56Smrg CloseDownClient(client); 493f7df2e56Smrg break; 494f7df2e56Smrg } 495f7df2e56Smrg else if (result != Success) { 496f7df2e56Smrg SendErrorToClient(client, client->majorOp, 497f7df2e56Smrg client->minorOp, 498f7df2e56Smrg client->errorValue, result); 499f7df2e56Smrg break; 500f7df2e56Smrg } 501f7df2e56Smrg } 502f7df2e56Smrg FlushAllOutput(); 5037e31ba66Smrg if (client == SmartLastClient) 504f7df2e56Smrg client->smart_stop_tick = SmartScheduleTime; 505f7df2e56Smrg } 506f7df2e56Smrg dispatchException &= ~DE_PRIORITYCHANGE; 50705b261ecSmrg } 50805b261ecSmrg#if defined(DDXBEFORERESET) 509f7df2e56Smrg ddxBeforeReset(); 51005b261ecSmrg#endif 51105b261ecSmrg KillAllClients(); 51205b261ecSmrg dispatchException &= ~DE_RESET; 513b1d344b3Smrg SmartScheduleLatencyLimited = 0; 514f7df2e56Smrg ResetOsBuffers(); 51505b261ecSmrg} 51605b261ecSmrg 517f7df2e56Smrgstatic int VendorRelease = VENDOR_RELEASE; 518f7df2e56Smrgstatic const char *VendorString = VENDOR_NAME; 5196747b715Smrg 5206747b715Smrgvoid 5216747b715SmrgSetVendorRelease(int release) 5226747b715Smrg{ 5236747b715Smrg VendorRelease = release; 5246747b715Smrg} 5256747b715Smrg 5266747b715Smrgvoid 527f7df2e56SmrgSetVendorString(const char *vendor) 5286747b715Smrg{ 529f7df2e56Smrg VendorString = vendor; 5306747b715Smrg} 5316747b715Smrg 5326747b715SmrgBool 5336747b715SmrgCreateConnectionBlock(void) 5346747b715Smrg{ 5356747b715Smrg xConnSetup setup; 5366747b715Smrg xWindowRoot root; 537f7df2e56Smrg xDepth depth; 5386747b715Smrg xVisualType visual; 5396747b715Smrg xPixmapFormat format; 5406747b715Smrg unsigned long vid; 541f7df2e56Smrg int i, j, k, lenofblock, sizesofar = 0; 5426747b715Smrg char *pBuf; 5436747b715Smrg 5446747b715Smrg memset(&setup, 0, sizeof(xConnSetup)); 5456747b715Smrg /* Leave off the ridBase and ridMask, these must be sent with 5466747b715Smrg connection */ 5476747b715Smrg 5486747b715Smrg setup.release = VendorRelease; 5496747b715Smrg /* 5506747b715Smrg * per-server image and bitmap parameters are defined in Xmd.h 5516747b715Smrg */ 5526747b715Smrg setup.imageByteOrder = screenInfo.imageByteOrder; 5536747b715Smrg 5546747b715Smrg setup.bitmapScanlineUnit = screenInfo.bitmapScanlineUnit; 5556747b715Smrg setup.bitmapScanlinePad = screenInfo.bitmapScanlinePad; 5566747b715Smrg 5576747b715Smrg setup.bitmapBitOrder = screenInfo.bitmapBitOrder; 5586747b715Smrg setup.motionBufferSize = NumMotionEvents(); 5596747b715Smrg setup.numRoots = screenInfo.numScreens; 5606747b715Smrg setup.nbytesVendor = strlen(VendorString); 5616747b715Smrg setup.numFormats = screenInfo.numPixmapFormats; 5626747b715Smrg setup.maxRequestSize = MAX_REQUEST_SIZE; 5636747b715Smrg QueryMinMaxKeyCodes(&setup.minKeyCode, &setup.maxKeyCode); 5646747b715Smrg 5656747b715Smrg lenofblock = sizeof(xConnSetup) + 566f7df2e56Smrg pad_to_int32(setup.nbytesVendor) + 567f7df2e56Smrg (setup.numFormats * sizeof(xPixmapFormat)) + 568f7df2e56Smrg (setup.numRoots * sizeof(xWindowRoot)); 5696747b715Smrg ConnectionInfo = malloc(lenofblock); 5706747b715Smrg if (!ConnectionInfo) 571f7df2e56Smrg return FALSE; 5726747b715Smrg 573f7df2e56Smrg memmove(ConnectionInfo, (char *) &setup, sizeof(xConnSetup)); 5746747b715Smrg sizesofar = sizeof(xConnSetup); 5756747b715Smrg pBuf = ConnectionInfo + sizeof(xConnSetup); 5766747b715Smrg 577f7df2e56Smrg memmove(pBuf, VendorString, (int) setup.nbytesVendor); 5786747b715Smrg sizesofar += setup.nbytesVendor; 5796747b715Smrg pBuf += setup.nbytesVendor; 580f7df2e56Smrg i = padding_for_int32(setup.nbytesVendor); 5816747b715Smrg sizesofar += i; 5826747b715Smrg while (--i >= 0) 583f7df2e56Smrg *pBuf++ = 0; 5846747b715Smrg 5856747b715Smrg memset(&format, 0, sizeof(xPixmapFormat)); 586f7df2e56Smrg for (i = 0; i < screenInfo.numPixmapFormats; i++) { 587f7df2e56Smrg format.depth = screenInfo.formats[i].depth; 588f7df2e56Smrg format.bitsPerPixel = screenInfo.formats[i].bitsPerPixel; 589f7df2e56Smrg format.scanLinePad = screenInfo.formats[i].scanlinePad; 590f7df2e56Smrg memmove(pBuf, (char *) &format, sizeof(xPixmapFormat)); 591f7df2e56Smrg pBuf += sizeof(xPixmapFormat); 592f7df2e56Smrg sizesofar += sizeof(xPixmapFormat); 5936747b715Smrg } 5946747b715Smrg 5956747b715Smrg connBlockScreenStart = sizesofar; 5966747b715Smrg memset(&depth, 0, sizeof(xDepth)); 5976747b715Smrg memset(&visual, 0, sizeof(xVisualType)); 598f7df2e56Smrg for (i = 0; i < screenInfo.numScreens; i++) { 599f7df2e56Smrg ScreenPtr pScreen; 600f7df2e56Smrg DepthPtr pDepth; 601f7df2e56Smrg VisualPtr pVisual; 602f7df2e56Smrg 603f7df2e56Smrg pScreen = screenInfo.screens[i]; 604f7df2e56Smrg root.windowId = pScreen->root->drawable.id; 605f7df2e56Smrg root.defaultColormap = pScreen->defColormap; 606f7df2e56Smrg root.whitePixel = pScreen->whitePixel; 607f7df2e56Smrg root.blackPixel = pScreen->blackPixel; 608f7df2e56Smrg root.currentInputMask = 0; /* filled in when sent */ 609f7df2e56Smrg root.pixWidth = pScreen->width; 610f7df2e56Smrg root.pixHeight = pScreen->height; 611f7df2e56Smrg root.mmWidth = pScreen->mmWidth; 612f7df2e56Smrg root.mmHeight = pScreen->mmHeight; 613f7df2e56Smrg root.minInstalledMaps = pScreen->minInstalledCmaps; 614f7df2e56Smrg root.maxInstalledMaps = pScreen->maxInstalledCmaps; 615f7df2e56Smrg root.rootVisualID = pScreen->rootVisual; 616f7df2e56Smrg root.backingStore = pScreen->backingStoreSupport; 617f7df2e56Smrg root.saveUnders = FALSE; 618f7df2e56Smrg root.rootDepth = pScreen->rootDepth; 619f7df2e56Smrg root.nDepths = pScreen->numDepths; 620f7df2e56Smrg memmove(pBuf, (char *) &root, sizeof(xWindowRoot)); 621f7df2e56Smrg sizesofar += sizeof(xWindowRoot); 622f7df2e56Smrg pBuf += sizeof(xWindowRoot); 623f7df2e56Smrg 624f7df2e56Smrg pDepth = pScreen->allowedDepths; 625f7df2e56Smrg for (j = 0; j < pScreen->numDepths; j++, pDepth++) { 626f7df2e56Smrg lenofblock += sizeof(xDepth) + 627f7df2e56Smrg (pDepth->numVids * sizeof(xVisualType)); 628f7df2e56Smrg pBuf = (char *) realloc(ConnectionInfo, lenofblock); 629f7df2e56Smrg if (!pBuf) { 630f7df2e56Smrg free(ConnectionInfo); 631f7df2e56Smrg return FALSE; 632f7df2e56Smrg } 633f7df2e56Smrg ConnectionInfo = pBuf; 634f7df2e56Smrg pBuf += sizesofar; 635f7df2e56Smrg depth.depth = pDepth->depth; 636f7df2e56Smrg depth.nVisuals = pDepth->numVids; 637f7df2e56Smrg memmove(pBuf, (char *) &depth, sizeof(xDepth)); 638f7df2e56Smrg pBuf += sizeof(xDepth); 639f7df2e56Smrg sizesofar += sizeof(xDepth); 640f7df2e56Smrg for (k = 0; k < pDepth->numVids; k++) { 641f7df2e56Smrg vid = pDepth->vids[k]; 642f7df2e56Smrg for (pVisual = pScreen->visuals; 643f7df2e56Smrg pVisual->vid != vid; pVisual++); 644f7df2e56Smrg visual.visualID = vid; 645f7df2e56Smrg visual.class = pVisual->class; 646f7df2e56Smrg visual.bitsPerRGB = pVisual->bitsPerRGBValue; 647f7df2e56Smrg visual.colormapEntries = pVisual->ColormapEntries; 648f7df2e56Smrg visual.redMask = pVisual->redMask; 649f7df2e56Smrg visual.greenMask = pVisual->greenMask; 650f7df2e56Smrg visual.blueMask = pVisual->blueMask; 651f7df2e56Smrg memmove(pBuf, (char *) &visual, sizeof(xVisualType)); 652f7df2e56Smrg pBuf += sizeof(xVisualType); 653f7df2e56Smrg sizesofar += sizeof(xVisualType); 654f7df2e56Smrg } 655f7df2e56Smrg } 6566747b715Smrg } 6576747b715Smrg connSetupPrefix.success = xTrue; 658f7df2e56Smrg connSetupPrefix.length = lenofblock / 4; 6596747b715Smrg connSetupPrefix.majorVersion = X_PROTOCOL; 6606747b715Smrg connSetupPrefix.minorVersion = X_PROTOCOL_REVISION; 6616747b715Smrg return TRUE; 6626747b715Smrg} 6636747b715Smrg 6646747b715Smrgint 66505b261ecSmrgProcBadRequest(ClientPtr client) 66605b261ecSmrg{ 6676747b715Smrg return BadRequest; 66805b261ecSmrg} 66905b261ecSmrg 67005b261ecSmrgint 67105b261ecSmrgProcCreateWindow(ClientPtr client) 67205b261ecSmrg{ 67305b261ecSmrg WindowPtr pParent, pWin; 674f7df2e56Smrg 67505b261ecSmrg REQUEST(xCreateWindowReq); 6764642e01fSmrg int len, rc; 67705b261ecSmrg 67805b261ecSmrg REQUEST_AT_LEAST_SIZE(xCreateWindowReq); 679f7df2e56Smrg 68005b261ecSmrg LEGAL_NEW_RESOURCE(stuff->wid, client); 6814642e01fSmrg rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess); 68205b261ecSmrg if (rc != Success) 68305b261ecSmrg return rc; 6846747b715Smrg len = client->req_len - bytes_to_int32(sizeof(xCreateWindowReq)); 68505b261ecSmrg if (Ones(stuff->mask) != len) 68605b261ecSmrg return BadLength; 687f7df2e56Smrg if (!stuff->width || !stuff->height) { 688f7df2e56Smrg client->errorValue = 0; 68905b261ecSmrg return BadValue; 69005b261ecSmrg } 69105b261ecSmrg pWin = CreateWindow(stuff->wid, pParent, stuff->x, 692f7df2e56Smrg stuff->y, stuff->width, stuff->height, 693f7df2e56Smrg stuff->borderWidth, stuff->class, 694f7df2e56Smrg stuff->mask, (XID *) &stuff[1], 695f7df2e56Smrg (int) stuff->depth, client, stuff->visual, &rc); 696f7df2e56Smrg if (pWin) { 697f7df2e56Smrg Mask mask = pWin->eventMask; 698f7df2e56Smrg 699f7df2e56Smrg pWin->eventMask = 0; /* subterfuge in case AddResource fails */ 700f7df2e56Smrg if (!AddResource(stuff->wid, RT_WINDOW, (void *) pWin)) 701f7df2e56Smrg return BadAlloc; 702f7df2e56Smrg pWin->eventMask = mask; 70305b261ecSmrg } 7046747b715Smrg return rc; 70505b261ecSmrg} 70605b261ecSmrg 70705b261ecSmrgint 70805b261ecSmrgProcChangeWindowAttributes(ClientPtr client) 70905b261ecSmrg{ 71005b261ecSmrg WindowPtr pWin; 711f7df2e56Smrg 71205b261ecSmrg REQUEST(xChangeWindowAttributesReq); 7136747b715Smrg int len, rc; 7144642e01fSmrg Mask access_mode = 0; 71505b261ecSmrg 71605b261ecSmrg REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); 7174642e01fSmrg access_mode |= (stuff->valueMask & CWEventMask) ? DixReceiveAccess : 0; 7184642e01fSmrg access_mode |= (stuff->valueMask & ~CWEventMask) ? DixSetAttrAccess : 0; 7194642e01fSmrg rc = dixLookupWindow(&pWin, stuff->window, client, access_mode); 72005b261ecSmrg if (rc != Success) 72105b261ecSmrg return rc; 7226747b715Smrg len = client->req_len - bytes_to_int32(sizeof(xChangeWindowAttributesReq)); 72305b261ecSmrg if (len != Ones(stuff->valueMask)) 72405b261ecSmrg return BadLength; 7256747b715Smrg return ChangeWindowAttributes(pWin, 726f7df2e56Smrg stuff->valueMask, (XID *) &stuff[1], client); 72705b261ecSmrg} 72805b261ecSmrg 72905b261ecSmrgint 73005b261ecSmrgProcGetWindowAttributes(ClientPtr client) 73105b261ecSmrg{ 73205b261ecSmrg WindowPtr pWin; 733f7df2e56Smrg 73405b261ecSmrg REQUEST(xResourceReq); 73505b261ecSmrg xGetWindowAttributesReply wa; 73605b261ecSmrg int rc; 73705b261ecSmrg 73805b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 7394642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess); 74005b261ecSmrg if (rc != Success) 741f7df2e56Smrg return rc; 7426747b715Smrg memset(&wa, 0, sizeof(xGetWindowAttributesReply)); 74305b261ecSmrg GetWindowAttributes(pWin, client, &wa); 74405b261ecSmrg WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa); 7456747b715Smrg return Success; 74605b261ecSmrg} 74705b261ecSmrg 74805b261ecSmrgint 74905b261ecSmrgProcDestroyWindow(ClientPtr client) 75005b261ecSmrg{ 75105b261ecSmrg WindowPtr pWin; 752f7df2e56Smrg 75305b261ecSmrg REQUEST(xResourceReq); 75405b261ecSmrg int rc; 75505b261ecSmrg 75605b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 75705b261ecSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixDestroyAccess); 75805b261ecSmrg if (rc != Success) 759f7df2e56Smrg return rc; 7604642e01fSmrg if (pWin->parent) { 761f7df2e56Smrg rc = dixLookupWindow(&pWin, pWin->parent->drawable.id, client, 762f7df2e56Smrg DixRemoveAccess); 763f7df2e56Smrg if (rc != Success) 764f7df2e56Smrg return rc; 765f7df2e56Smrg FreeResource(stuff->id, RT_NONE); 7664642e01fSmrg } 7676747b715Smrg return Success; 76805b261ecSmrg} 76905b261ecSmrg 77005b261ecSmrgint 77105b261ecSmrgProcDestroySubwindows(ClientPtr client) 77205b261ecSmrg{ 77305b261ecSmrg WindowPtr pWin; 774f7df2e56Smrg 77505b261ecSmrg REQUEST(xResourceReq); 77605b261ecSmrg int rc; 77705b261ecSmrg 77805b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 7794642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixRemoveAccess); 78005b261ecSmrg if (rc != Success) 781f7df2e56Smrg return rc; 78205b261ecSmrg DestroySubwindows(pWin, client); 7836747b715Smrg return Success; 78405b261ecSmrg} 78505b261ecSmrg 78605b261ecSmrgint 78705b261ecSmrgProcChangeSaveSet(ClientPtr client) 78805b261ecSmrg{ 78905b261ecSmrg WindowPtr pWin; 790f7df2e56Smrg 79105b261ecSmrg REQUEST(xChangeSaveSetReq); 7926747b715Smrg int rc; 793f7df2e56Smrg 79405b261ecSmrg REQUEST_SIZE_MATCH(xChangeSaveSetReq); 7954642e01fSmrg rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess); 79605b261ecSmrg if (rc != Success) 79705b261ecSmrg return rc; 79805b261ecSmrg if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id))) 79905b261ecSmrg return BadMatch; 80005b261ecSmrg if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete)) 8016747b715Smrg return AlterSaveSetForClient(client, pWin, stuff->mode, FALSE, TRUE); 8026747b715Smrg client->errorValue = stuff->mode; 8036747b715Smrg return BadValue; 80405b261ecSmrg} 80505b261ecSmrg 80605b261ecSmrgint 80705b261ecSmrgProcReparentWindow(ClientPtr client) 80805b261ecSmrg{ 80905b261ecSmrg WindowPtr pWin, pParent; 810f7df2e56Smrg 81105b261ecSmrg REQUEST(xReparentWindowReq); 8126747b715Smrg int rc; 81305b261ecSmrg 81405b261ecSmrg REQUEST_SIZE_MATCH(xReparentWindowReq); 8154642e01fSmrg rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess); 81605b261ecSmrg if (rc != Success) 81705b261ecSmrg return rc; 8184642e01fSmrg rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess); 81905b261ecSmrg if (rc != Success) 82005b261ecSmrg return rc; 8216747b715Smrg if (!SAME_SCREENS(pWin->drawable, pParent->drawable)) 822f7df2e56Smrg return BadMatch; 8236747b715Smrg if ((pWin->backgroundState == ParentRelative) && 824f7df2e56Smrg (pParent->drawable.depth != pWin->drawable.depth)) 825f7df2e56Smrg return BadMatch; 8266747b715Smrg if ((pWin->drawable.class != InputOnly) && 827f7df2e56Smrg (pParent->drawable.class == InputOnly)) 828f7df2e56Smrg return BadMatch; 8296747b715Smrg return ReparentWindow(pWin, pParent, 830f7df2e56Smrg (short) stuff->x, (short) stuff->y, client); 83105b261ecSmrg} 83205b261ecSmrg 83305b261ecSmrgint 83405b261ecSmrgProcMapWindow(ClientPtr client) 83505b261ecSmrg{ 83605b261ecSmrg WindowPtr pWin; 837f7df2e56Smrg 83805b261ecSmrg REQUEST(xResourceReq); 83905b261ecSmrg int rc; 84005b261ecSmrg 84105b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 8424642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixShowAccess); 84305b261ecSmrg if (rc != Success) 84405b261ecSmrg return rc; 84505b261ecSmrg MapWindow(pWin, client); 846f7df2e56Smrg /* update cache to say it is mapped */ 8476747b715Smrg return Success; 84805b261ecSmrg} 84905b261ecSmrg 85005b261ecSmrgint 85105b261ecSmrgProcMapSubwindows(ClientPtr client) 85205b261ecSmrg{ 85305b261ecSmrg WindowPtr pWin; 854f7df2e56Smrg 85505b261ecSmrg REQUEST(xResourceReq); 85605b261ecSmrg int rc; 85705b261ecSmrg 85805b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 8594642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess); 86005b261ecSmrg if (rc != Success) 86105b261ecSmrg return rc; 86205b261ecSmrg MapSubwindows(pWin, client); 863f7df2e56Smrg /* update cache to say it is mapped */ 8646747b715Smrg return Success; 86505b261ecSmrg} 86605b261ecSmrg 86705b261ecSmrgint 86805b261ecSmrgProcUnmapWindow(ClientPtr client) 86905b261ecSmrg{ 87005b261ecSmrg WindowPtr pWin; 871f7df2e56Smrg 87205b261ecSmrg REQUEST(xResourceReq); 87305b261ecSmrg int rc; 87405b261ecSmrg 87505b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 8764642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixHideAccess); 87705b261ecSmrg if (rc != Success) 87805b261ecSmrg return rc; 87905b261ecSmrg UnmapWindow(pWin, FALSE); 880f7df2e56Smrg /* update cache to say it is mapped */ 8816747b715Smrg return Success; 88205b261ecSmrg} 88305b261ecSmrg 88405b261ecSmrgint 88505b261ecSmrgProcUnmapSubwindows(ClientPtr client) 88605b261ecSmrg{ 88705b261ecSmrg WindowPtr pWin; 888f7df2e56Smrg 88905b261ecSmrg REQUEST(xResourceReq); 89005b261ecSmrg int rc; 89105b261ecSmrg 89205b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 8934642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess); 89405b261ecSmrg if (rc != Success) 89505b261ecSmrg return rc; 89605b261ecSmrg UnmapSubwindows(pWin); 8976747b715Smrg return Success; 89805b261ecSmrg} 89905b261ecSmrg 90005b261ecSmrgint 90105b261ecSmrgProcConfigureWindow(ClientPtr client) 90205b261ecSmrg{ 90305b261ecSmrg WindowPtr pWin; 904f7df2e56Smrg 90505b261ecSmrg REQUEST(xConfigureWindowReq); 90605b261ecSmrg int len, rc; 90705b261ecSmrg 90805b261ecSmrg REQUEST_AT_LEAST_SIZE(xConfigureWindowReq); 9094642e01fSmrg rc = dixLookupWindow(&pWin, stuff->window, client, 910f7df2e56Smrg DixManageAccess | DixSetAttrAccess); 91105b261ecSmrg if (rc != Success) 91205b261ecSmrg return rc; 9136747b715Smrg len = client->req_len - bytes_to_int32(sizeof(xConfigureWindowReq)); 914f7df2e56Smrg if (Ones((Mask) stuff->mask) != len) 91505b261ecSmrg return BadLength; 916f7df2e56Smrg return ConfigureWindow(pWin, (Mask) stuff->mask, (XID *) &stuff[1], client); 91705b261ecSmrg} 91805b261ecSmrg 91905b261ecSmrgint 92005b261ecSmrgProcCirculateWindow(ClientPtr client) 92105b261ecSmrg{ 92205b261ecSmrg WindowPtr pWin; 923f7df2e56Smrg 92405b261ecSmrg REQUEST(xCirculateWindowReq); 92505b261ecSmrg int rc; 92605b261ecSmrg 92705b261ecSmrg REQUEST_SIZE_MATCH(xCirculateWindowReq); 928f7df2e56Smrg if ((stuff->direction != RaiseLowest) && (stuff->direction != LowerHighest)) { 929f7df2e56Smrg client->errorValue = stuff->direction; 93005b261ecSmrg return BadValue; 93105b261ecSmrg } 9324642e01fSmrg rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess); 93305b261ecSmrg if (rc != Success) 93405b261ecSmrg return rc; 935f7df2e56Smrg CirculateWindow(pWin, (int) stuff->direction, client); 9366747b715Smrg return Success; 93705b261ecSmrg} 93805b261ecSmrg 93905b261ecSmrgstatic int 940f7df2e56SmrgGetGeometry(ClientPtr client, xGetGeometryReply * rep) 94105b261ecSmrg{ 94205b261ecSmrg DrawablePtr pDraw; 94305b261ecSmrg int rc; 944f7df2e56Smrg 94505b261ecSmrg REQUEST(xResourceReq); 94605b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 94705b261ecSmrg 9484642e01fSmrg rc = dixLookupDrawable(&pDraw, stuff->id, client, M_ANY, DixGetAttrAccess); 94905b261ecSmrg if (rc != Success) 950f7df2e56Smrg return rc; 95105b261ecSmrg 95205b261ecSmrg rep->type = X_Reply; 95305b261ecSmrg rep->length = 0; 95405b261ecSmrg rep->sequenceNumber = client->sequence; 9556747b715Smrg rep->root = pDraw->pScreen->root->drawable.id; 95605b261ecSmrg rep->depth = pDraw->depth; 95705b261ecSmrg rep->width = pDraw->width; 95805b261ecSmrg rep->height = pDraw->height; 95905b261ecSmrg 960f7df2e56Smrg if (WindowDrawable(pDraw->type)) { 961f7df2e56Smrg WindowPtr pWin = (WindowPtr) pDraw; 962f7df2e56Smrg 963f7df2e56Smrg rep->x = pWin->origin.x - wBorderWidth(pWin); 964f7df2e56Smrg rep->y = pWin->origin.y - wBorderWidth(pWin); 965f7df2e56Smrg rep->borderWidth = pWin->borderWidth; 96605b261ecSmrg } 967f7df2e56Smrg else { /* DRAWABLE_PIXMAP */ 968f7df2e56Smrg 969f7df2e56Smrg rep->x = rep->y = rep->borderWidth = 0; 97005b261ecSmrg } 97105b261ecSmrg 97205b261ecSmrg return Success; 97305b261ecSmrg} 97405b261ecSmrg 97505b261ecSmrgint 97605b261ecSmrgProcGetGeometry(ClientPtr client) 97705b261ecSmrg{ 978f7df2e56Smrg xGetGeometryReply rep = { .type = X_Reply }; 97905b261ecSmrg int status; 98005b261ecSmrg 98105b261ecSmrg if ((status = GetGeometry(client, &rep)) != Success) 982f7df2e56Smrg return status; 98305b261ecSmrg 98405b261ecSmrg WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep); 9856747b715Smrg return Success; 98605b261ecSmrg} 98705b261ecSmrg 98805b261ecSmrgint 98905b261ecSmrgProcQueryTree(ClientPtr client) 99005b261ecSmrg{ 99105b261ecSmrg xQueryTreeReply reply; 99205b261ecSmrg int rc, numChildren = 0; 99305b261ecSmrg WindowPtr pChild, pWin, pHead; 994f7df2e56Smrg Window *childIDs = (Window *) NULL; 995f7df2e56Smrg 99605b261ecSmrg REQUEST(xResourceReq); 99705b261ecSmrg 99805b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 9994642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess); 100005b261ecSmrg if (rc != Success) 100105b261ecSmrg return rc; 1002f7df2e56Smrg 1003f7df2e56Smrg reply = (xQueryTreeReply) { 1004f7df2e56Smrg .type = X_Reply, 1005f7df2e56Smrg .sequenceNumber = client->sequence, 1006f7df2e56Smrg .root = pWin->drawable.pScreen->root->drawable.id, 1007f7df2e56Smrg .parent = (pWin->parent) ? pWin->parent->drawable.id : (Window) None 1008f7df2e56Smrg }; 100905b261ecSmrg pHead = RealChildHead(pWin); 101005b261ecSmrg for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) 1011f7df2e56Smrg numChildren++; 1012f7df2e56Smrg if (numChildren) { 1013f7df2e56Smrg int curChild = 0; 101405b261ecSmrg 1015f7df2e56Smrg childIDs = xallocarray(numChildren, sizeof(Window)); 1016f7df2e56Smrg if (!childIDs) 1017f7df2e56Smrg return BadAlloc; 1018f7df2e56Smrg for (pChild = pWin->lastChild; pChild != pHead; 1019f7df2e56Smrg pChild = pChild->prevSib) 1020f7df2e56Smrg childIDs[curChild++] = pChild->drawable.id; 102105b261ecSmrg } 1022f7df2e56Smrg 102305b261ecSmrg reply.nChildren = numChildren; 10246747b715Smrg reply.length = bytes_to_int32(numChildren * sizeof(Window)); 1025f7df2e56Smrg 102605b261ecSmrg WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply); 1027f7df2e56Smrg if (numChildren) { 1028f7df2e56Smrg client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; 1029f7df2e56Smrg WriteSwappedDataToClient(client, numChildren * sizeof(Window), 1030f7df2e56Smrg childIDs); 1031f7df2e56Smrg free(childIDs); 103205b261ecSmrg } 103305b261ecSmrg 10346747b715Smrg return Success; 103505b261ecSmrg} 103605b261ecSmrg 103705b261ecSmrgint 103805b261ecSmrgProcInternAtom(ClientPtr client) 103905b261ecSmrg{ 104005b261ecSmrg Atom atom; 104105b261ecSmrg char *tchar; 1042f7df2e56Smrg 104305b261ecSmrg REQUEST(xInternAtomReq); 104405b261ecSmrg 104505b261ecSmrg REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes); 1046f7df2e56Smrg if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse)) { 1047f7df2e56Smrg client->errorValue = stuff->onlyIfExists; 10486747b715Smrg return BadValue; 104905b261ecSmrg } 105005b261ecSmrg tchar = (char *) &stuff[1]; 105105b261ecSmrg atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists); 1052f7df2e56Smrg if (atom != BAD_RESOURCE) { 1053f7df2e56Smrg xInternAtomReply reply = { 1054f7df2e56Smrg .type = X_Reply, 1055f7df2e56Smrg .sequenceNumber = client->sequence, 1056f7df2e56Smrg .length = 0, 1057f7df2e56Smrg .atom = atom 1058f7df2e56Smrg }; 1059f7df2e56Smrg WriteReplyToClient(client, sizeof(xInternAtomReply), &reply); 1060f7df2e56Smrg return Success; 106105b261ecSmrg } 106205b261ecSmrg else 1063f7df2e56Smrg return BadAlloc; 106405b261ecSmrg} 106505b261ecSmrg 106605b261ecSmrgint 106705b261ecSmrgProcGetAtomName(ClientPtr client) 106805b261ecSmrg{ 10696747b715Smrg const char *str; 1070f7df2e56Smrg 107105b261ecSmrg REQUEST(xResourceReq); 107205b261ecSmrg 107305b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 1074f7df2e56Smrg if ((str = NameForAtom(stuff->id))) { 1075f7df2e56Smrg int len = strlen(str); 1076f7df2e56Smrg xGetAtomNameReply reply = { 1077f7df2e56Smrg .type = X_Reply, 1078f7df2e56Smrg .sequenceNumber = client->sequence, 1079f7df2e56Smrg .length = bytes_to_int32(len), 1080f7df2e56Smrg .nameLength = len 1081f7df2e56Smrg }; 1082f7df2e56Smrg 1083f7df2e56Smrg WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply); 1084f7df2e56Smrg WriteToClient(client, len, str); 1085f7df2e56Smrg return Success; 108605b261ecSmrg } 1087f7df2e56Smrg else { 1088f7df2e56Smrg client->errorValue = stuff->id; 1089f7df2e56Smrg return BadAtom; 109005b261ecSmrg } 109105b261ecSmrg} 109205b261ecSmrg 109305b261ecSmrgint 109405b261ecSmrgProcGrabServer(ClientPtr client) 109505b261ecSmrg{ 10964642e01fSmrg int rc; 1097f7df2e56Smrg 109805b261ecSmrg REQUEST_SIZE_MATCH(xReq); 1099f7df2e56Smrg if (grabState != GrabNone && client != grabClient) { 1100f7df2e56Smrg ResetCurrentRequest(client); 1101f7df2e56Smrg client->sequence--; 1102f7df2e56Smrg BITSET(grabWaiters, client->index); 1103f7df2e56Smrg IgnoreClient(client); 1104f7df2e56Smrg return Success; 110505b261ecSmrg } 11064642e01fSmrg rc = OnlyListenToOneClient(client); 11074642e01fSmrg if (rc != Success) 1108f7df2e56Smrg return rc; 11097e31ba66Smrg grabState = GrabActive; 111005b261ecSmrg grabClient = client; 11117e31ba66Smrg mark_client_grab(client); 111205b261ecSmrg 1113f7df2e56Smrg if (ServerGrabCallback) { 1114f7df2e56Smrg ServerGrabInfoRec grabinfo; 1115f7df2e56Smrg 1116f7df2e56Smrg grabinfo.client = client; 1117f7df2e56Smrg grabinfo.grabstate = SERVER_GRABBED; 1118f7df2e56Smrg CallCallbacks(&ServerGrabCallback, (void *) &grabinfo); 111905b261ecSmrg } 112005b261ecSmrg 11216747b715Smrg return Success; 112205b261ecSmrg} 112305b261ecSmrg 112405b261ecSmrgstatic void 112505b261ecSmrgUngrabServer(ClientPtr client) 112605b261ecSmrg{ 112705b261ecSmrg int i; 112805b261ecSmrg 112905b261ecSmrg grabState = GrabNone; 113005b261ecSmrg ListenToAllClients(); 11317e31ba66Smrg mark_client_ungrab(); 1132f7df2e56Smrg for (i = mskcnt; --i >= 0 && !grabWaiters[i];); 1133f7df2e56Smrg if (i >= 0) { 1134f7df2e56Smrg i <<= 5; 1135f7df2e56Smrg while (!GETBIT(grabWaiters, i)) 1136f7df2e56Smrg i++; 1137f7df2e56Smrg BITCLEAR(grabWaiters, i); 1138f7df2e56Smrg AttendClient(clients[i]); 113905b261ecSmrg } 114005b261ecSmrg 1141f7df2e56Smrg if (ServerGrabCallback) { 1142f7df2e56Smrg ServerGrabInfoRec grabinfo; 1143f7df2e56Smrg 1144f7df2e56Smrg grabinfo.client = client; 1145f7df2e56Smrg grabinfo.grabstate = SERVER_UNGRABBED; 1146f7df2e56Smrg CallCallbacks(&ServerGrabCallback, (void *) &grabinfo); 114705b261ecSmrg } 114805b261ecSmrg} 114905b261ecSmrg 115005b261ecSmrgint 115105b261ecSmrgProcUngrabServer(ClientPtr client) 115205b261ecSmrg{ 115305b261ecSmrg REQUEST_SIZE_MATCH(xReq); 115405b261ecSmrg UngrabServer(client); 11556747b715Smrg return Success; 115605b261ecSmrg} 115705b261ecSmrg 115805b261ecSmrgint 115905b261ecSmrgProcTranslateCoords(ClientPtr client) 116005b261ecSmrg{ 116105b261ecSmrg REQUEST(xTranslateCoordsReq); 116205b261ecSmrg 116305b261ecSmrg WindowPtr pWin, pDst; 116405b261ecSmrg xTranslateCoordsReply rep; 116505b261ecSmrg int rc; 116605b261ecSmrg 116705b261ecSmrg REQUEST_SIZE_MATCH(xTranslateCoordsReq); 11684642e01fSmrg rc = dixLookupWindow(&pWin, stuff->srcWid, client, DixGetAttrAccess); 116905b261ecSmrg if (rc != Success) 117005b261ecSmrg return rc; 11714642e01fSmrg rc = dixLookupWindow(&pDst, stuff->dstWid, client, DixGetAttrAccess); 117205b261ecSmrg if (rc != Success) 117305b261ecSmrg return rc; 1174f7df2e56Smrg 1175f7df2e56Smrg rep = (xTranslateCoordsReply) { 1176f7df2e56Smrg .type = X_Reply, 1177f7df2e56Smrg .sequenceNumber = client->sequence, 1178f7df2e56Smrg .length = 0 1179f7df2e56Smrg }; 1180f7df2e56Smrg if (!SAME_SCREENS(pWin->drawable, pDst->drawable)) { 1181f7df2e56Smrg rep.sameScreen = xFalse; 118205b261ecSmrg rep.child = None; 1183f7df2e56Smrg rep.dstX = rep.dstY = 0; 118405b261ecSmrg } 1185f7df2e56Smrg else { 1186f7df2e56Smrg INT16 x, y; 1187f7df2e56Smrg 1188f7df2e56Smrg rep.sameScreen = xTrue; 1189f7df2e56Smrg rep.child = None; 1190f7df2e56Smrg /* computing absolute coordinates -- adjust to destination later */ 1191f7df2e56Smrg x = pWin->drawable.x + stuff->srcX; 1192f7df2e56Smrg y = pWin->drawable.y + stuff->srcY; 1193f7df2e56Smrg pWin = pDst->firstChild; 1194f7df2e56Smrg while (pWin) { 1195f7df2e56Smrg BoxRec box; 1196f7df2e56Smrg 1197f7df2e56Smrg if ((pWin->mapped) && 1198f7df2e56Smrg (x >= pWin->drawable.x - wBorderWidth(pWin)) && 1199f7df2e56Smrg (x < pWin->drawable.x + (int) pWin->drawable.width + 1200f7df2e56Smrg wBorderWidth(pWin)) && 1201f7df2e56Smrg (y >= pWin->drawable.y - wBorderWidth(pWin)) && 1202f7df2e56Smrg (y < pWin->drawable.y + (int) pWin->drawable.height + 1203f7df2e56Smrg wBorderWidth(pWin)) 1204f7df2e56Smrg /* When a window is shaped, a further check 1205f7df2e56Smrg * is made to see if the point is inside 1206f7df2e56Smrg * borderSize 1207f7df2e56Smrg */ 1208f7df2e56Smrg && (!wBoundingShape(pWin) || 1209f7df2e56Smrg RegionContainsPoint(&pWin->borderSize, x, y, &box)) 1210f7df2e56Smrg 1211f7df2e56Smrg && (!wInputShape(pWin) || 1212f7df2e56Smrg RegionContainsPoint(wInputShape(pWin), 1213f7df2e56Smrg x - pWin->drawable.x, 1214f7df2e56Smrg y - pWin->drawable.y, &box)) 1215f7df2e56Smrg ) { 1216f7df2e56Smrg rep.child = pWin->drawable.id; 1217f7df2e56Smrg pWin = (WindowPtr) NULL; 1218f7df2e56Smrg } 1219f7df2e56Smrg else 1220f7df2e56Smrg pWin = pWin->nextSib; 1221f7df2e56Smrg } 1222f7df2e56Smrg /* adjust to destination coordinates */ 1223f7df2e56Smrg rep.dstX = x - pDst->drawable.x; 1224f7df2e56Smrg rep.dstY = y - pDst->drawable.y; 122505b261ecSmrg } 122605b261ecSmrg WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep); 12276747b715Smrg return Success; 122805b261ecSmrg} 122905b261ecSmrg 123005b261ecSmrgint 123105b261ecSmrgProcOpenFont(ClientPtr client) 123205b261ecSmrg{ 1233f7df2e56Smrg int err; 1234f7df2e56Smrg 123505b261ecSmrg REQUEST(xOpenFontReq); 123605b261ecSmrg 123705b261ecSmrg REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes); 123805b261ecSmrg client->errorValue = stuff->fid; 123905b261ecSmrg LEGAL_NEW_RESOURCE(stuff->fid, client); 124005b261ecSmrg err = OpenFont(client, stuff->fid, (Mask) 0, 1241f7df2e56Smrg stuff->nbytes, (char *) &stuff[1]); 1242f7df2e56Smrg if (err == Success) { 1243f7df2e56Smrg return Success; 124405b261ecSmrg } 124505b261ecSmrg else 1246f7df2e56Smrg return err; 124705b261ecSmrg} 124805b261ecSmrg 124905b261ecSmrgint 125005b261ecSmrgProcCloseFont(ClientPtr client) 125105b261ecSmrg{ 125205b261ecSmrg FontPtr pFont; 12536747b715Smrg int rc; 1254f7df2e56Smrg 125505b261ecSmrg REQUEST(xResourceReq); 125605b261ecSmrg 125705b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 1258f7df2e56Smrg rc = dixLookupResourceByType((void **) &pFont, stuff->id, RT_FONT, 1259f7df2e56Smrg client, DixDestroyAccess); 1260f7df2e56Smrg if (rc == Success) { 126105b261ecSmrg FreeResource(stuff->id, RT_NONE); 1262f7df2e56Smrg return Success; 126305b261ecSmrg } 1264f7df2e56Smrg else { 1265f7df2e56Smrg client->errorValue = stuff->id; 12666747b715Smrg return rc; 126705b261ecSmrg } 126805b261ecSmrg} 126905b261ecSmrg 127005b261ecSmrgint 127105b261ecSmrgProcQueryFont(ClientPtr client) 127205b261ecSmrg{ 1273f7df2e56Smrg xQueryFontReply *reply; 127405b261ecSmrg FontPtr pFont; 12754642e01fSmrg int rc; 1276f7df2e56Smrg 127705b261ecSmrg REQUEST(xResourceReq); 127805b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 12794642e01fSmrg 12806747b715Smrg rc = dixLookupFontable(&pFont, stuff->id, client, DixGetAttrAccess); 12814642e01fSmrg if (rc != Success) 1282f7df2e56Smrg return rc; 128305b261ecSmrg 128405b261ecSmrg { 1285f7df2e56Smrg xCharInfo *pmax = FONTINKMAX(pFont); 1286f7df2e56Smrg xCharInfo *pmin = FONTINKMIN(pFont); 1287f7df2e56Smrg int nprotoxcistructs; 1288f7df2e56Smrg int rlength; 1289f7df2e56Smrg 1290f7df2e56Smrg nprotoxcistructs = (pmax->rightSideBearing == pmin->rightSideBearing && 1291f7df2e56Smrg pmax->leftSideBearing == pmin->leftSideBearing && 1292f7df2e56Smrg pmax->descent == pmin->descent && 1293f7df2e56Smrg pmax->ascent == pmin->ascent && 1294f7df2e56Smrg pmax->characterWidth == pmin->characterWidth) ? 1295f7df2e56Smrg 0 : N2dChars(pFont); 1296f7df2e56Smrg 1297f7df2e56Smrg rlength = sizeof(xQueryFontReply) + 1298f7df2e56Smrg FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) + 1299f7df2e56Smrg nprotoxcistructs * sizeof(xCharInfo); 1300f7df2e56Smrg reply = calloc(1, rlength); 1301f7df2e56Smrg if (!reply) { 1302f7df2e56Smrg return BadAlloc; 1303f7df2e56Smrg } 1304f7df2e56Smrg 1305f7df2e56Smrg reply->type = X_Reply; 1306f7df2e56Smrg reply->length = bytes_to_int32(rlength - sizeof(xGenericReply)); 1307f7df2e56Smrg reply->sequenceNumber = client->sequence; 1308f7df2e56Smrg QueryFont(pFont, reply, nprotoxcistructs); 130905b261ecSmrg 131005b261ecSmrg WriteReplyToClient(client, rlength, reply); 1311f7df2e56Smrg free(reply); 1312f7df2e56Smrg return Success; 131305b261ecSmrg } 131405b261ecSmrg} 131505b261ecSmrg 131605b261ecSmrgint 131705b261ecSmrgProcQueryTextExtents(ClientPtr client) 131805b261ecSmrg{ 131905b261ecSmrg xQueryTextExtentsReply reply; 132005b261ecSmrg FontPtr pFont; 132105b261ecSmrg ExtentInfoRec info; 132205b261ecSmrg unsigned long length; 13234642e01fSmrg int rc; 1324f7df2e56Smrg 13254642e01fSmrg REQUEST(xQueryTextExtentsReq); 132605b261ecSmrg REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq); 1327f7df2e56Smrg 13286747b715Smrg rc = dixLookupFontable(&pFont, stuff->fid, client, DixGetAttrAccess); 13294642e01fSmrg if (rc != Success) 1330f7df2e56Smrg return rc; 13314642e01fSmrg 13326747b715Smrg length = client->req_len - bytes_to_int32(sizeof(xQueryTextExtentsReq)); 133305b261ecSmrg length = length << 1; 1334f7df2e56Smrg if (stuff->oddLength) { 1335f7df2e56Smrg if (length == 0) 1336f7df2e56Smrg return BadLength; 133705b261ecSmrg length--; 133805b261ecSmrg } 13397e31ba66Smrg if (!xfont2_query_text_extents(pFont, length, (unsigned char *) &stuff[1], &info)) 1340f7df2e56Smrg return BadAlloc; 1341f7df2e56Smrg reply = (xQueryTextExtentsReply) { 1342f7df2e56Smrg .type = X_Reply, 1343f7df2e56Smrg .drawDirection = info.drawDirection, 1344f7df2e56Smrg .sequenceNumber = client->sequence, 1345f7df2e56Smrg .length = 0, 1346f7df2e56Smrg .fontAscent = info.fontAscent, 1347f7df2e56Smrg .fontDescent = info.fontDescent, 1348f7df2e56Smrg .overallAscent = info.overallAscent, 1349f7df2e56Smrg .overallDescent = info.overallDescent, 1350f7df2e56Smrg .overallWidth = info.overallWidth, 1351f7df2e56Smrg .overallLeft = info.overallLeft, 1352f7df2e56Smrg .overallRight = info.overallRight 1353f7df2e56Smrg }; 135405b261ecSmrg WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply); 13556747b715Smrg return Success; 135605b261ecSmrg} 135705b261ecSmrg 135805b261ecSmrgint 135905b261ecSmrgProcListFonts(ClientPtr client) 136005b261ecSmrg{ 136105b261ecSmrg REQUEST(xListFontsReq); 136205b261ecSmrg 136305b261ecSmrg REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes); 136405b261ecSmrg 1365f7df2e56Smrg return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes, 1366f7df2e56Smrg stuff->maxNames); 136705b261ecSmrg} 136805b261ecSmrg 136905b261ecSmrgint 137005b261ecSmrgProcListFontsWithInfo(ClientPtr client) 137105b261ecSmrg{ 137205b261ecSmrg REQUEST(xListFontsWithInfoReq); 137305b261ecSmrg 137405b261ecSmrg REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes); 137505b261ecSmrg 137605b261ecSmrg return StartListFontsWithInfo(client, stuff->nbytes, 1377f7df2e56Smrg (unsigned char *) &stuff[1], stuff->maxNames); 137805b261ecSmrg} 137905b261ecSmrg 138005b261ecSmrg/** 138105b261ecSmrg * 138205b261ecSmrg * \param value must conform to DeleteType 138305b261ecSmrg */ 138405b261ecSmrgint 1385f7df2e56SmrgdixDestroyPixmap(void *value, XID pid) 138605b261ecSmrg{ 1387f7df2e56Smrg PixmapPtr pPixmap = (PixmapPtr) value; 1388f7df2e56Smrg 1389f7df2e56Smrg return (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap); 139005b261ecSmrg} 139105b261ecSmrg 139205b261ecSmrgint 139305b261ecSmrgProcCreatePixmap(ClientPtr client) 139405b261ecSmrg{ 139505b261ecSmrg PixmapPtr pMap; 139605b261ecSmrg DrawablePtr pDraw; 1397f7df2e56Smrg 139805b261ecSmrg REQUEST(xCreatePixmapReq); 139905b261ecSmrg DepthPtr pDepth; 140005b261ecSmrg int i, rc; 140105b261ecSmrg 140205b261ecSmrg REQUEST_SIZE_MATCH(xCreatePixmapReq); 140305b261ecSmrg client->errorValue = stuff->pid; 140405b261ecSmrg LEGAL_NEW_RESOURCE(stuff->pid, client); 1405f7df2e56Smrg 140605b261ecSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, 1407f7df2e56Smrg DixGetAttrAccess); 140805b261ecSmrg if (rc != Success) 1409f7df2e56Smrg return rc; 141005b261ecSmrg 1411f7df2e56Smrg if (!stuff->width || !stuff->height) { 1412f7df2e56Smrg client->errorValue = 0; 141305b261ecSmrg return BadValue; 141405b261ecSmrg } 1415f7df2e56Smrg if (stuff->width > 32767 || stuff->height > 32767) { 1416f7df2e56Smrg /* It is allowed to try and allocate a pixmap which is larger than 1417f7df2e56Smrg * 32767 in either dimension. However, all of the framebuffer code 1418f7df2e56Smrg * is buggy and does not reliably draw to such big pixmaps, basically 1419f7df2e56Smrg * because the Region data structure operates with signed shorts 1420f7df2e56Smrg * for the rectangles in it. 1421f7df2e56Smrg * 1422f7df2e56Smrg * Furthermore, several places in the X server computes the 1423f7df2e56Smrg * size in bytes of the pixmap and tries to store it in an 1424f7df2e56Smrg * integer. This integer can overflow and cause the allocated size 1425f7df2e56Smrg * to be much smaller. 1426f7df2e56Smrg * 1427f7df2e56Smrg * So, such big pixmaps are rejected here with a BadAlloc 1428f7df2e56Smrg */ 1429f7df2e56Smrg return BadAlloc; 1430f7df2e56Smrg } 1431f7df2e56Smrg if (stuff->depth != 1) { 143205b261ecSmrg pDepth = pDraw->pScreen->allowedDepths; 1433f7df2e56Smrg for (i = 0; i < pDraw->pScreen->numDepths; i++, pDepth++) 1434f7df2e56Smrg if (pDepth->depth == stuff->depth) 1435f7df2e56Smrg goto CreatePmap; 1436f7df2e56Smrg client->errorValue = stuff->depth; 143705b261ecSmrg return BadValue; 143805b261ecSmrg } 1439f7df2e56Smrg CreatePmap: 1440f7df2e56Smrg pMap = (PixmapPtr) (*pDraw->pScreen->CreatePixmap) 1441f7df2e56Smrg (pDraw->pScreen, stuff->width, stuff->height, stuff->depth, 0); 1442f7df2e56Smrg if (pMap) { 1443f7df2e56Smrg pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; 1444f7df2e56Smrg pMap->drawable.id = stuff->pid; 1445f7df2e56Smrg /* security creation/labeling check */ 1446f7df2e56Smrg rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP, 1447f7df2e56Smrg pMap, RT_NONE, NULL, DixCreateAccess); 1448f7df2e56Smrg if (rc != Success) { 1449f7df2e56Smrg (*pDraw->pScreen->DestroyPixmap) (pMap); 1450f7df2e56Smrg return rc; 1451f7df2e56Smrg } 1452f7df2e56Smrg if (AddResource(stuff->pid, RT_PIXMAP, (void *) pMap)) 1453f7df2e56Smrg return Success; 145405b261ecSmrg } 14556747b715Smrg return BadAlloc; 145605b261ecSmrg} 145705b261ecSmrg 145805b261ecSmrgint 145905b261ecSmrgProcFreePixmap(ClientPtr client) 146005b261ecSmrg{ 146105b261ecSmrg PixmapPtr pMap; 14624642e01fSmrg int rc; 1463f7df2e56Smrg 146405b261ecSmrg REQUEST(xResourceReq); 146505b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 14664642e01fSmrg 1467f7df2e56Smrg rc = dixLookupResourceByType((void **) &pMap, stuff->id, RT_PIXMAP, 1468f7df2e56Smrg client, DixDestroyAccess); 1469f7df2e56Smrg if (rc == Success) { 1470f7df2e56Smrg FreeResource(stuff->id, RT_NONE); 1471f7df2e56Smrg return Success; 147205b261ecSmrg } 1473f7df2e56Smrg else { 1474f7df2e56Smrg client->errorValue = stuff->id; 1475f7df2e56Smrg return rc; 147605b261ecSmrg } 147705b261ecSmrg} 147805b261ecSmrg 147905b261ecSmrgint 148005b261ecSmrgProcCreateGC(ClientPtr client) 148105b261ecSmrg{ 148205b261ecSmrg int error, rc; 148305b261ecSmrg GC *pGC; 148405b261ecSmrg DrawablePtr pDraw; 148505b261ecSmrg unsigned len; 1486f7df2e56Smrg 148705b261ecSmrg REQUEST(xCreateGCReq); 148805b261ecSmrg 148905b261ecSmrg REQUEST_AT_LEAST_SIZE(xCreateGCReq); 149005b261ecSmrg client->errorValue = stuff->gc; 149105b261ecSmrg LEGAL_NEW_RESOURCE(stuff->gc, client); 14924642e01fSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, 1493f7df2e56Smrg DixGetAttrAccess); 149405b261ecSmrg if (rc != Success) 1495f7df2e56Smrg return rc; 149605b261ecSmrg 1497f7df2e56Smrg len = client->req_len - bytes_to_int32(sizeof(xCreateGCReq)); 149805b261ecSmrg if (len != Ones(stuff->mask)) 149905b261ecSmrg return BadLength; 1500f7df2e56Smrg pGC = (GC *) CreateGC(pDraw, stuff->mask, (XID *) &stuff[1], &error, 1501f7df2e56Smrg stuff->gc, client); 150205b261ecSmrg if (error != Success) 150305b261ecSmrg return error; 1504f7df2e56Smrg if (!AddResource(stuff->gc, RT_GC, (void *) pGC)) 1505f7df2e56Smrg return BadAlloc; 15066747b715Smrg return Success; 150705b261ecSmrg} 150805b261ecSmrg 150905b261ecSmrgint 151005b261ecSmrgProcChangeGC(ClientPtr client) 151105b261ecSmrg{ 151205b261ecSmrg GC *pGC; 151305b261ecSmrg int result; 151405b261ecSmrg unsigned len; 1515f7df2e56Smrg 151605b261ecSmrg REQUEST(xChangeGCReq); 151705b261ecSmrg REQUEST_AT_LEAST_SIZE(xChangeGCReq); 151805b261ecSmrg 15194642e01fSmrg result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess); 152005b261ecSmrg if (result != Success) 1521f7df2e56Smrg return result; 152205b261ecSmrg 1523f7df2e56Smrg len = client->req_len - bytes_to_int32(sizeof(xChangeGCReq)); 152405b261ecSmrg if (len != Ones(stuff->mask)) 152505b261ecSmrg return BadLength; 152605b261ecSmrg 15276747b715Smrg return ChangeGCXIDs(client, pGC, stuff->mask, (CARD32 *) &stuff[1]); 152805b261ecSmrg} 152905b261ecSmrg 153005b261ecSmrgint 153105b261ecSmrgProcCopyGC(ClientPtr client) 153205b261ecSmrg{ 153305b261ecSmrg GC *dstGC; 153405b261ecSmrg GC *pGC; 153505b261ecSmrg int result; 1536f7df2e56Smrg 153705b261ecSmrg REQUEST(xCopyGCReq); 153805b261ecSmrg REQUEST_SIZE_MATCH(xCopyGCReq); 153905b261ecSmrg 15404642e01fSmrg result = dixLookupGC(&pGC, stuff->srcGC, client, DixGetAttrAccess); 154105b261ecSmrg if (result != Success) 1542f7df2e56Smrg return result; 15434642e01fSmrg result = dixLookupGC(&dstGC, stuff->dstGC, client, DixSetAttrAccess); 154405b261ecSmrg if (result != Success) 1545f7df2e56Smrg return result; 154605b261ecSmrg if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth)) 15476747b715Smrg return BadMatch; 1548f7df2e56Smrg if (stuff->mask & ~GCAllBits) { 1549f7df2e56Smrg client->errorValue = stuff->mask; 1550f7df2e56Smrg return BadValue; 155105b261ecSmrg } 15526747b715Smrg return CopyGC(pGC, dstGC, stuff->mask); 155305b261ecSmrg} 155405b261ecSmrg 155505b261ecSmrgint 155605b261ecSmrgProcSetDashes(ClientPtr client) 155705b261ecSmrg{ 155805b261ecSmrg GC *pGC; 155905b261ecSmrg int result; 1560f7df2e56Smrg 156105b261ecSmrg REQUEST(xSetDashesReq); 156205b261ecSmrg 156305b261ecSmrg REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes); 1564f7df2e56Smrg if (stuff->nDashes == 0) { 1565f7df2e56Smrg client->errorValue = 0; 1566f7df2e56Smrg return BadValue; 156705b261ecSmrg } 156805b261ecSmrg 1569f7df2e56Smrg result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess); 157005b261ecSmrg if (result != Success) 1571f7df2e56Smrg return result; 157205b261ecSmrg 15736747b715Smrg /* If there's an error, either there's no sensible errorValue, 15746747b715Smrg * or there was a dash segment of 0. */ 15756747b715Smrg client->errorValue = 0; 15766747b715Smrg return SetDashes(pGC, stuff->dashOffset, stuff->nDashes, 1577f7df2e56Smrg (unsigned char *) &stuff[1]); 157805b261ecSmrg} 157905b261ecSmrg 158005b261ecSmrgint 158105b261ecSmrgProcSetClipRectangles(ClientPtr client) 158205b261ecSmrg{ 1583f7df2e56Smrg int nr, result; 158405b261ecSmrg GC *pGC; 1585f7df2e56Smrg 158605b261ecSmrg REQUEST(xSetClipRectanglesReq); 158705b261ecSmrg 158805b261ecSmrg REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq); 158905b261ecSmrg if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) && 1590f7df2e56Smrg (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) { 1591f7df2e56Smrg client->errorValue = stuff->ordering; 159205b261ecSmrg return BadValue; 159305b261ecSmrg } 1594f7df2e56Smrg result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess); 159505b261ecSmrg if (result != Success) 1596f7df2e56Smrg return result; 1597f7df2e56Smrg 159805b261ecSmrg nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq); 159905b261ecSmrg if (nr & 4) 1600f7df2e56Smrg return BadLength; 160105b261ecSmrg nr >>= 3; 16026747b715Smrg return SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin, 1603f7df2e56Smrg nr, (xRectangle *) &stuff[1], (int) stuff->ordering); 160405b261ecSmrg} 160505b261ecSmrg 160605b261ecSmrgint 160705b261ecSmrgProcFreeGC(ClientPtr client) 160805b261ecSmrg{ 160905b261ecSmrg GC *pGC; 161005b261ecSmrg int rc; 1611f7df2e56Smrg 161205b261ecSmrg REQUEST(xResourceReq); 161305b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 161405b261ecSmrg 161505b261ecSmrg rc = dixLookupGC(&pGC, stuff->id, client, DixDestroyAccess); 161605b261ecSmrg if (rc != Success) 1617f7df2e56Smrg return rc; 161805b261ecSmrg 161905b261ecSmrg FreeResource(stuff->id, RT_NONE); 16206747b715Smrg return Success; 162105b261ecSmrg} 162205b261ecSmrg 162305b261ecSmrgint 162405b261ecSmrgProcClearToBackground(ClientPtr client) 162505b261ecSmrg{ 162605b261ecSmrg REQUEST(xClearAreaReq); 162705b261ecSmrg WindowPtr pWin; 162805b261ecSmrg int rc; 162905b261ecSmrg 163005b261ecSmrg REQUEST_SIZE_MATCH(xClearAreaReq); 163105b261ecSmrg rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess); 163205b261ecSmrg if (rc != Success) 163305b261ecSmrg return rc; 1634f7df2e56Smrg if (pWin->drawable.class == InputOnly) { 1635f7df2e56Smrg client->errorValue = stuff->window; 1636f7df2e56Smrg return BadMatch; 1637f7df2e56Smrg } 1638f7df2e56Smrg if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) { 1639f7df2e56Smrg client->errorValue = stuff->exposures; 16406747b715Smrg return BadValue; 164105b261ecSmrg } 1642f7df2e56Smrg (*pWin->drawable.pScreen->ClearToBackground) (pWin, stuff->x, stuff->y, 1643f7df2e56Smrg stuff->width, stuff->height, 1644f7df2e56Smrg (Bool) stuff->exposures); 16456747b715Smrg return Success; 164605b261ecSmrg} 164705b261ecSmrg 1648f7df2e56Smrg/* send GraphicsExpose events, or a NoExpose event, based on the region */ 1649f7df2e56Smrgvoid 1650f7df2e56SmrgSendGraphicsExpose(ClientPtr client, RegionPtr pRgn, XID drawable, 1651f7df2e56Smrg int major, int minor) 1652f7df2e56Smrg{ 1653f7df2e56Smrg if (pRgn && !RegionNil(pRgn)) { 1654f7df2e56Smrg xEvent *pEvent; 1655f7df2e56Smrg xEvent *pe; 1656f7df2e56Smrg BoxPtr pBox; 1657f7df2e56Smrg int i; 1658f7df2e56Smrg int numRects; 1659f7df2e56Smrg 1660f7df2e56Smrg numRects = RegionNumRects(pRgn); 1661f7df2e56Smrg pBox = RegionRects(pRgn); 1662f7df2e56Smrg if (!(pEvent = calloc(numRects, sizeof(xEvent)))) 1663f7df2e56Smrg return; 1664f7df2e56Smrg pe = pEvent; 1665f7df2e56Smrg 1666f7df2e56Smrg for (i = 1; i <= numRects; i++, pe++, pBox++) { 1667f7df2e56Smrg pe->u.u.type = GraphicsExpose; 1668f7df2e56Smrg pe->u.graphicsExposure.drawable = drawable; 1669f7df2e56Smrg pe->u.graphicsExposure.x = pBox->x1; 1670f7df2e56Smrg pe->u.graphicsExposure.y = pBox->y1; 1671f7df2e56Smrg pe->u.graphicsExposure.width = pBox->x2 - pBox->x1; 1672f7df2e56Smrg pe->u.graphicsExposure.height = pBox->y2 - pBox->y1; 1673f7df2e56Smrg pe->u.graphicsExposure.count = numRects - i; 1674f7df2e56Smrg pe->u.graphicsExposure.majorEvent = major; 1675f7df2e56Smrg pe->u.graphicsExposure.minorEvent = minor; 1676f7df2e56Smrg } 1677f7df2e56Smrg /* GraphicsExpose is a "critical event", which TryClientEvents 1678f7df2e56Smrg * handles specially. */ 1679f7df2e56Smrg TryClientEvents(client, NULL, pEvent, numRects, 1680f7df2e56Smrg (Mask) 0, NoEventMask, NullGrab); 1681f7df2e56Smrg free(pEvent); 1682f7df2e56Smrg } 1683f7df2e56Smrg else { 1684f7df2e56Smrg xEvent event = { 1685f7df2e56Smrg .u.noExposure.drawable = drawable, 1686f7df2e56Smrg .u.noExposure.majorEvent = major, 1687f7df2e56Smrg .u.noExposure.minorEvent = minor 1688f7df2e56Smrg }; 1689f7df2e56Smrg event.u.u.type = NoExpose; 1690f7df2e56Smrg WriteEventsToClient(client, 1, &event); 1691f7df2e56Smrg } 1692f7df2e56Smrg} 1693f7df2e56Smrg 169405b261ecSmrgint 169505b261ecSmrgProcCopyArea(ClientPtr client) 169605b261ecSmrg{ 169705b261ecSmrg DrawablePtr pDst; 169805b261ecSmrg DrawablePtr pSrc; 169905b261ecSmrg GC *pGC; 1700f7df2e56Smrg 170105b261ecSmrg REQUEST(xCopyAreaReq); 170205b261ecSmrg RegionPtr pRgn; 170305b261ecSmrg int rc; 170405b261ecSmrg 170505b261ecSmrg REQUEST_SIZE_MATCH(xCopyAreaReq); 170605b261ecSmrg 1707f7df2e56Smrg VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, DixWriteAccess); 1708f7df2e56Smrg if (stuff->dstDrawable != stuff->srcDrawable) { 1709f7df2e56Smrg rc = dixLookupDrawable(&pSrc, stuff->srcDrawable, client, 0, 1710f7df2e56Smrg DixReadAccess); 1711f7df2e56Smrg if (rc != Success) 1712f7df2e56Smrg return rc; 1713f7df2e56Smrg if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) { 1714f7df2e56Smrg client->errorValue = stuff->dstDrawable; 1715f7df2e56Smrg return BadMatch; 1716f7df2e56Smrg } 171705b261ecSmrg } 171805b261ecSmrg else 171905b261ecSmrg pSrc = pDst; 172005b261ecSmrg 1721f7df2e56Smrg pRgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, stuff->srcX, stuff->srcY, 1722f7df2e56Smrg stuff->width, stuff->height, 1723f7df2e56Smrg stuff->dstX, stuff->dstY); 1724f7df2e56Smrg if (pGC->graphicsExposures) { 1725f7df2e56Smrg SendGraphicsExpose(client, pRgn, stuff->dstDrawable, X_CopyArea, 0); 1726f7df2e56Smrg if (pRgn) 1727f7df2e56Smrg RegionDestroy(pRgn); 172805b261ecSmrg } 172905b261ecSmrg 17306747b715Smrg return Success; 173105b261ecSmrg} 173205b261ecSmrg 173305b261ecSmrgint 173405b261ecSmrgProcCopyPlane(ClientPtr client) 173505b261ecSmrg{ 173605b261ecSmrg DrawablePtr psrcDraw, pdstDraw; 173705b261ecSmrg GC *pGC; 1738f7df2e56Smrg 173905b261ecSmrg REQUEST(xCopyPlaneReq); 174005b261ecSmrg RegionPtr pRgn; 174105b261ecSmrg int rc; 174205b261ecSmrg 174305b261ecSmrg REQUEST_SIZE_MATCH(xCopyPlaneReq); 174405b261ecSmrg 17454642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, DixWriteAccess); 1746f7df2e56Smrg if (stuff->dstDrawable != stuff->srcDrawable) { 1747f7df2e56Smrg rc = dixLookupDrawable(&psrcDraw, stuff->srcDrawable, client, 0, 1748f7df2e56Smrg DixReadAccess); 1749f7df2e56Smrg if (rc != Success) 1750f7df2e56Smrg return rc; 1751f7df2e56Smrg 1752f7df2e56Smrg if (pdstDraw->pScreen != psrcDraw->pScreen) { 1753f7df2e56Smrg client->errorValue = stuff->dstDrawable; 1754f7df2e56Smrg return BadMatch; 1755f7df2e56Smrg } 175605b261ecSmrg } 175705b261ecSmrg else 175805b261ecSmrg psrcDraw = pdstDraw; 175905b261ecSmrg 176005b261ecSmrg /* Check to see if stuff->bitPlane has exactly ONE good bit set */ 1761f7df2e56Smrg if (stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) || 1762f7df2e56Smrg (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) { 1763f7df2e56Smrg client->errorValue = stuff->bitPlane; 1764f7df2e56Smrg return BadValue; 176505b261ecSmrg } 176605b261ecSmrg 1767f7df2e56Smrg pRgn = 1768f7df2e56Smrg (*pGC->ops->CopyPlane) (psrcDraw, pdstDraw, pGC, stuff->srcX, 1769f7df2e56Smrg stuff->srcY, stuff->width, stuff->height, 1770f7df2e56Smrg stuff->dstX, stuff->dstY, stuff->bitPlane); 1771f7df2e56Smrg if (pGC->graphicsExposures) { 1772f7df2e56Smrg SendGraphicsExpose(client, pRgn, stuff->dstDrawable, X_CopyPlane, 0); 1773f7df2e56Smrg if (pRgn) 1774f7df2e56Smrg RegionDestroy(pRgn); 177505b261ecSmrg } 17766747b715Smrg return Success; 177705b261ecSmrg} 177805b261ecSmrg 177905b261ecSmrgint 178005b261ecSmrgProcPolyPoint(ClientPtr client) 178105b261ecSmrg{ 178205b261ecSmrg int npoint; 178305b261ecSmrg GC *pGC; 178405b261ecSmrg DrawablePtr pDraw; 1785f7df2e56Smrg 178605b261ecSmrg REQUEST(xPolyPointReq); 178705b261ecSmrg 178805b261ecSmrg REQUEST_AT_LEAST_SIZE(xPolyPointReq); 1789f7df2e56Smrg if ((stuff->coordMode != CoordModeOrigin) && 1790f7df2e56Smrg (stuff->coordMode != CoordModePrevious)) { 1791f7df2e56Smrg client->errorValue = stuff->coordMode; 179205b261ecSmrg return BadValue; 179305b261ecSmrg } 1794f7df2e56Smrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 17956747b715Smrg npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyPointReq)); 179605b261ecSmrg if (npoint) 1797f7df2e56Smrg (*pGC->ops->PolyPoint) (pDraw, pGC, stuff->coordMode, npoint, 1798f7df2e56Smrg (xPoint *) &stuff[1]); 17996747b715Smrg return Success; 180005b261ecSmrg} 180105b261ecSmrg 180205b261ecSmrgint 180305b261ecSmrgProcPolyLine(ClientPtr client) 180405b261ecSmrg{ 180505b261ecSmrg int npoint; 180605b261ecSmrg GC *pGC; 180705b261ecSmrg DrawablePtr pDraw; 1808f7df2e56Smrg 180905b261ecSmrg REQUEST(xPolyLineReq); 181005b261ecSmrg 181105b261ecSmrg REQUEST_AT_LEAST_SIZE(xPolyLineReq); 1812f7df2e56Smrg if ((stuff->coordMode != CoordModeOrigin) && 1813f7df2e56Smrg (stuff->coordMode != CoordModePrevious)) { 1814f7df2e56Smrg client->errorValue = stuff->coordMode; 181505b261ecSmrg return BadValue; 181605b261ecSmrg } 18174642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 18186747b715Smrg npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyLineReq)); 181905b261ecSmrg if (npoint > 1) 1820f7df2e56Smrg (*pGC->ops->Polylines) (pDraw, pGC, stuff->coordMode, npoint, 1821f7df2e56Smrg (DDXPointPtr) &stuff[1]); 18226747b715Smrg return Success; 182305b261ecSmrg} 182405b261ecSmrg 182505b261ecSmrgint 182605b261ecSmrgProcPolySegment(ClientPtr client) 182705b261ecSmrg{ 182805b261ecSmrg int nsegs; 182905b261ecSmrg GC *pGC; 183005b261ecSmrg DrawablePtr pDraw; 1831f7df2e56Smrg 183205b261ecSmrg REQUEST(xPolySegmentReq); 183305b261ecSmrg 183405b261ecSmrg REQUEST_AT_LEAST_SIZE(xPolySegmentReq); 18354642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 183605b261ecSmrg nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq); 183705b261ecSmrg if (nsegs & 4) 1838f7df2e56Smrg return BadLength; 183905b261ecSmrg nsegs >>= 3; 184005b261ecSmrg if (nsegs) 1841f7df2e56Smrg (*pGC->ops->PolySegment) (pDraw, pGC, nsegs, (xSegment *) &stuff[1]); 18426747b715Smrg return Success; 184305b261ecSmrg} 184405b261ecSmrg 184505b261ecSmrgint 1846f7df2e56SmrgProcPolyRectangle(ClientPtr client) 184705b261ecSmrg{ 184805b261ecSmrg int nrects; 184905b261ecSmrg GC *pGC; 185005b261ecSmrg DrawablePtr pDraw; 1851f7df2e56Smrg 185205b261ecSmrg REQUEST(xPolyRectangleReq); 185305b261ecSmrg 185405b261ecSmrg REQUEST_AT_LEAST_SIZE(xPolyRectangleReq); 18554642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 185605b261ecSmrg nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq); 185705b261ecSmrg if (nrects & 4) 1858f7df2e56Smrg return BadLength; 185905b261ecSmrg nrects >>= 3; 186005b261ecSmrg if (nrects) 1861f7df2e56Smrg (*pGC->ops->PolyRectangle) (pDraw, pGC, 1862f7df2e56Smrg nrects, (xRectangle *) &stuff[1]); 18636747b715Smrg return Success; 186405b261ecSmrg} 186505b261ecSmrg 186605b261ecSmrgint 186705b261ecSmrgProcPolyArc(ClientPtr client) 186805b261ecSmrg{ 1869f7df2e56Smrg int narcs; 187005b261ecSmrg GC *pGC; 187105b261ecSmrg DrawablePtr pDraw; 1872f7df2e56Smrg 187305b261ecSmrg REQUEST(xPolyArcReq); 187405b261ecSmrg 187505b261ecSmrg REQUEST_AT_LEAST_SIZE(xPolyArcReq); 18764642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 187705b261ecSmrg narcs = (client->req_len << 2) - sizeof(xPolyArcReq); 187805b261ecSmrg if (narcs % sizeof(xArc)) 1879f7df2e56Smrg return BadLength; 188005b261ecSmrg narcs /= sizeof(xArc); 188105b261ecSmrg if (narcs) 1882f7df2e56Smrg (*pGC->ops->PolyArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]); 18836747b715Smrg return Success; 188405b261ecSmrg} 188505b261ecSmrg 188605b261ecSmrgint 188705b261ecSmrgProcFillPoly(ClientPtr client) 188805b261ecSmrg{ 1889f7df2e56Smrg int things; 189005b261ecSmrg GC *pGC; 189105b261ecSmrg DrawablePtr pDraw; 1892f7df2e56Smrg 189305b261ecSmrg REQUEST(xFillPolyReq); 189405b261ecSmrg 189505b261ecSmrg REQUEST_AT_LEAST_SIZE(xFillPolyReq); 1896f7df2e56Smrg if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) && 1897f7df2e56Smrg (stuff->shape != Convex)) { 1898f7df2e56Smrg client->errorValue = stuff->shape; 189905b261ecSmrg return BadValue; 190005b261ecSmrg } 1901f7df2e56Smrg if ((stuff->coordMode != CoordModeOrigin) && 1902f7df2e56Smrg (stuff->coordMode != CoordModePrevious)) { 1903f7df2e56Smrg client->errorValue = stuff->coordMode; 190405b261ecSmrg return BadValue; 190505b261ecSmrg } 190605b261ecSmrg 19074642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 19086747b715Smrg things = bytes_to_int32((client->req_len << 2) - sizeof(xFillPolyReq)); 190905b261ecSmrg if (things) 191005b261ecSmrg (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape, 1911f7df2e56Smrg stuff->coordMode, things, 1912f7df2e56Smrg (DDXPointPtr) &stuff[1]); 19136747b715Smrg return Success; 191405b261ecSmrg} 191505b261ecSmrg 191605b261ecSmrgint 191705b261ecSmrgProcPolyFillRectangle(ClientPtr client) 191805b261ecSmrg{ 1919f7df2e56Smrg int things; 192005b261ecSmrg GC *pGC; 192105b261ecSmrg DrawablePtr pDraw; 1922f7df2e56Smrg 192305b261ecSmrg REQUEST(xPolyFillRectangleReq); 192405b261ecSmrg 192505b261ecSmrg REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq); 19264642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 192705b261ecSmrg things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq); 192805b261ecSmrg if (things & 4) 1929f7df2e56Smrg return BadLength; 193005b261ecSmrg things >>= 3; 193105b261ecSmrg 193205b261ecSmrg if (things) 193305b261ecSmrg (*pGC->ops->PolyFillRect) (pDraw, pGC, things, 1934f7df2e56Smrg (xRectangle *) &stuff[1]); 19356747b715Smrg return Success; 193605b261ecSmrg} 193705b261ecSmrg 193805b261ecSmrgint 193905b261ecSmrgProcPolyFillArc(ClientPtr client) 194005b261ecSmrg{ 1941f7df2e56Smrg int narcs; 194205b261ecSmrg GC *pGC; 194305b261ecSmrg DrawablePtr pDraw; 1944f7df2e56Smrg 194505b261ecSmrg REQUEST(xPolyFillArcReq); 194605b261ecSmrg 194705b261ecSmrg REQUEST_AT_LEAST_SIZE(xPolyFillArcReq); 19484642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 194905b261ecSmrg narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq); 195005b261ecSmrg if (narcs % sizeof(xArc)) 1951f7df2e56Smrg return BadLength; 195205b261ecSmrg narcs /= sizeof(xArc); 195305b261ecSmrg if (narcs) 195405b261ecSmrg (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]); 19556747b715Smrg return Success; 195605b261ecSmrg} 195705b261ecSmrg 195805b261ecSmrg#ifdef MATCH_CLIENT_ENDIAN 195905b261ecSmrg 196005b261ecSmrgint 1961f7df2e56SmrgServerOrder(void) 196205b261ecSmrg{ 1963f7df2e56Smrg int whichbyte = 1; 196405b261ecSmrg 196505b261ecSmrg if (*((char *) &whichbyte)) 1966f7df2e56Smrg return LSBFirst; 196705b261ecSmrg return MSBFirst; 196805b261ecSmrg} 196905b261ecSmrg 197005b261ecSmrg#define ClientOrder(client) ((client)->swapped ? !ServerOrder() : ServerOrder()) 197105b261ecSmrg 197205b261ecSmrgvoid 1973f7df2e56SmrgReformatImage(char *base, int nbytes, int bpp, int order) 197405b261ecSmrg{ 197505b261ecSmrg switch (bpp) { 1976f7df2e56Smrg case 1: /* yuck */ 1977f7df2e56Smrg if (BITMAP_BIT_ORDER != order) 1978f7df2e56Smrg BitOrderInvert((unsigned char *) base, nbytes); 197905b261ecSmrg#if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8 1980f7df2e56Smrg ReformatImage(base, nbytes, BITMAP_SCANLINE_UNIT, order); 198105b261ecSmrg#endif 1982f7df2e56Smrg break; 198305b261ecSmrg case 4: 1984f7df2e56Smrg break; /* yuck */ 198505b261ecSmrg case 8: 1986f7df2e56Smrg break; 198705b261ecSmrg case 16: 1988f7df2e56Smrg if (IMAGE_BYTE_ORDER != order) 1989f7df2e56Smrg TwoByteSwap((unsigned char *) base, nbytes); 1990f7df2e56Smrg break; 199105b261ecSmrg case 32: 1992f7df2e56Smrg if (IMAGE_BYTE_ORDER != order) 1993f7df2e56Smrg FourByteSwap((unsigned char *) base, nbytes); 1994f7df2e56Smrg break; 199505b261ecSmrg } 199605b261ecSmrg} 199705b261ecSmrg#else 199805b261ecSmrg#define ReformatImage(b,n,bpp,o) 199905b261ecSmrg#endif 200005b261ecSmrg 200105b261ecSmrg/* 64-bit server notes: the protocol restricts padding of images to 200205b261ecSmrg * 8-, 16-, or 32-bits. We would like to have 64-bits for the server 200305b261ecSmrg * to use internally. Removes need for internal alignment checking. 200405b261ecSmrg * All of the PutImage functions could be changed individually, but 200505b261ecSmrg * as currently written, they call other routines which require things 200605b261ecSmrg * to be 64-bit padded on scanlines, so we changed things here. 200705b261ecSmrg * If an image would be padded differently for 64- versus 32-, then 200805b261ecSmrg * copy each scanline to a 64-bit padded scanline. 200905b261ecSmrg * Also, we need to make sure that the image is aligned on a 64-bit 201005b261ecSmrg * boundary, even if the scanlines are padded to our satisfaction. 201105b261ecSmrg */ 201205b261ecSmrgint 201305b261ecSmrgProcPutImage(ClientPtr client) 201405b261ecSmrg{ 201505b261ecSmrg GC *pGC; 201605b261ecSmrg DrawablePtr pDraw; 2017f7df2e56Smrg long length; /* length of scanline server padded */ 2018f7df2e56Smrg long lengthProto; /* length of scanline protocol padded */ 2019f7df2e56Smrg char *tmpImage; 2020f7df2e56Smrg 202105b261ecSmrg REQUEST(xPutImageReq); 202205b261ecSmrg 202305b261ecSmrg REQUEST_AT_LEAST_SIZE(xPutImageReq); 20244642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 2025f7df2e56Smrg if (stuff->format == XYBitmap) { 202605b261ecSmrg if ((stuff->depth != 1) || 2027f7df2e56Smrg (stuff->leftPad >= (unsigned int) screenInfo.bitmapScanlinePad)) 202805b261ecSmrg return BadMatch; 2029f7df2e56Smrg length = BitmapBytePad(stuff->width + stuff->leftPad); 203005b261ecSmrg } 2031f7df2e56Smrg else if (stuff->format == XYPixmap) { 2032f7df2e56Smrg if ((pDraw->depth != stuff->depth) || 2033f7df2e56Smrg (stuff->leftPad >= (unsigned int) screenInfo.bitmapScanlinePad)) 203405b261ecSmrg return BadMatch; 2035f7df2e56Smrg length = BitmapBytePad(stuff->width + stuff->leftPad); 2036f7df2e56Smrg length *= stuff->depth; 203705b261ecSmrg } 2038f7df2e56Smrg else if (stuff->format == ZPixmap) { 203905b261ecSmrg if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0)) 204005b261ecSmrg return BadMatch; 2041f7df2e56Smrg length = PixmapBytePad(stuff->width, stuff->depth); 204205b261ecSmrg } 2043f7df2e56Smrg else { 2044f7df2e56Smrg client->errorValue = stuff->format; 204505b261ecSmrg return BadValue; 204605b261ecSmrg } 204705b261ecSmrg 2048f7df2e56Smrg tmpImage = (char *) &stuff[1]; 204905b261ecSmrg lengthProto = length; 20500b0d8713Smrg 2051f7df2e56Smrg if (stuff->height != 0 && lengthProto >= (INT32_MAX / stuff->height)) 20520b0d8713Smrg return BadLength; 2053f7df2e56Smrg 20546747b715Smrg if ((bytes_to_int32(lengthProto * stuff->height) + 2055f7df2e56Smrg bytes_to_int32(sizeof(xPutImageReq))) != client->req_len) 2056f7df2e56Smrg return BadLength; 2057f7df2e56Smrg 2058f7df2e56Smrg ReformatImage(tmpImage, lengthProto * stuff->height, 2059f7df2e56Smrg stuff->format == ZPixmap ? BitsPerPixel(stuff->depth) : 1, 2060f7df2e56Smrg ClientOrder(client)); 206105b261ecSmrg 206205b261ecSmrg (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY, 2063f7df2e56Smrg stuff->width, stuff->height, 2064f7df2e56Smrg stuff->leftPad, stuff->format, tmpImage); 206505b261ecSmrg 2066f7df2e56Smrg return Success; 206705b261ecSmrg} 206805b261ecSmrg 206905b261ecSmrgstatic int 2070f7df2e56SmrgDoGetImage(ClientPtr client, int format, Drawable drawable, 2071f7df2e56Smrg int x, int y, int width, int height, 2072f7df2e56Smrg Mask planemask) 207305b261ecSmrg{ 2074f7df2e56Smrg DrawablePtr pDraw, pBoundingDraw; 2075f7df2e56Smrg int nlines, linesPerBuf, rc; 2076f7df2e56Smrg int linesDone; 2077f7df2e56Smrg 20786747b715Smrg /* coordinates relative to the bounding drawable */ 2079f7df2e56Smrg int relx, rely; 2080f7df2e56Smrg long widthBytesLine, length; 2081f7df2e56Smrg Mask plane = 0; 2082f7df2e56Smrg char *pBuf; 2083f7df2e56Smrg xGetImageReply xgi; 208405b261ecSmrg RegionPtr pVisibleRegion = NULL; 208505b261ecSmrg 2086f7df2e56Smrg if ((format != XYPixmap) && (format != ZPixmap)) { 2087f7df2e56Smrg client->errorValue = format; 20886747b715Smrg return BadValue; 208905b261ecSmrg } 209005b261ecSmrg rc = dixLookupDrawable(&pDraw, drawable, client, 0, DixReadAccess); 209105b261ecSmrg if (rc != Success) 2092f7df2e56Smrg return rc; 209305b261ecSmrg 20946747b715Smrg memset(&xgi, 0, sizeof(xGetImageReply)); 20956747b715Smrg 20966747b715Smrg relx = x; 20976747b715Smrg rely = y; 20986747b715Smrg 2099f7df2e56Smrg if (pDraw->type == DRAWABLE_WINDOW) { 2100f7df2e56Smrg WindowPtr pWin = (WindowPtr) pDraw; 2101f7df2e56Smrg 2102f7df2e56Smrg /* "If the drawable is a window, the window must be viewable ... or a 2103f7df2e56Smrg * BadMatch error results" */ 2104f7df2e56Smrg if (!pWin->viewable) 2105f7df2e56Smrg return BadMatch; 21066747b715Smrg 2107f7df2e56Smrg /* If the drawable is a window, the rectangle must be contained within 2108f7df2e56Smrg * its bounds (including the border). */ 2109f7df2e56Smrg if (x < -wBorderWidth(pWin) || 2110f7df2e56Smrg x + width > wBorderWidth(pWin) + (int) pDraw->width || 2111f7df2e56Smrg y < -wBorderWidth(pWin) || 2112f7df2e56Smrg y + height > wBorderWidth(pWin) + (int) pDraw->height) 2113f7df2e56Smrg return BadMatch; 21146747b715Smrg 2115f7df2e56Smrg relx += pDraw->x; 2116f7df2e56Smrg rely += pDraw->y; 21176747b715Smrg 2118f7df2e56Smrg if (pDraw->pScreen->GetWindowPixmap) { 2119f7df2e56Smrg PixmapPtr pPix = (*pDraw->pScreen->GetWindowPixmap) (pWin); 21206747b715Smrg 2121f7df2e56Smrg pBoundingDraw = &pPix->drawable; 21226747b715Smrg#ifdef COMPOSITE 2123f7df2e56Smrg relx -= pPix->screen_x; 2124f7df2e56Smrg rely -= pPix->screen_y; 21256747b715Smrg#endif 2126f7df2e56Smrg } 2127f7df2e56Smrg else { 2128f7df2e56Smrg pBoundingDraw = (DrawablePtr) pDraw->pScreen->root; 2129f7df2e56Smrg } 21306747b715Smrg 2131f7df2e56Smrg xgi.visual = wVisual(pWin); 213205b261ecSmrg } 2133f7df2e56Smrg else { 2134f7df2e56Smrg pBoundingDraw = pDraw; 2135f7df2e56Smrg xgi.visual = None; 213605b261ecSmrg } 213705b261ecSmrg 21386747b715Smrg /* "If the drawable is a pixmap, the given rectangle must be wholly 21396747b715Smrg * contained within the pixmap, or a BadMatch error results. If the 21406747b715Smrg * drawable is a window [...] it must be the case that if there were no 21416747b715Smrg * inferiors or overlapping windows, the specified rectangle of the window 21426747b715Smrg * would be fully visible on the screen and wholly contained within the 21436747b715Smrg * outside edges of the window, or a BadMatch error results." 21446747b715Smrg * 21456747b715Smrg * We relax the window case slightly to mean that the rectangle must exist 21466747b715Smrg * within the bounds of the window's backing pixmap. In particular, this 21476747b715Smrg * means that a GetImage request may succeed or fail with BadMatch depending 21486747b715Smrg * on whether any of its ancestor windows are redirected. */ 2149f7df2e56Smrg if (relx < 0 || relx + width > (int) pBoundingDraw->width || 2150f7df2e56Smrg rely < 0 || rely + height > (int) pBoundingDraw->height) 2151f7df2e56Smrg return BadMatch; 21526747b715Smrg 215305b261ecSmrg xgi.type = X_Reply; 215405b261ecSmrg xgi.sequenceNumber = client->sequence; 215505b261ecSmrg xgi.depth = pDraw->depth; 2156f7df2e56Smrg if (format == ZPixmap) { 2157f7df2e56Smrg widthBytesLine = PixmapBytePad(width, pDraw->depth); 2158f7df2e56Smrg length = widthBytesLine * height; 215905b261ecSmrg 216005b261ecSmrg } 2161f7df2e56Smrg else { 2162f7df2e56Smrg widthBytesLine = BitmapBytePad(width); 2163f7df2e56Smrg plane = ((Mask) 1) << (pDraw->depth - 1); 2164f7df2e56Smrg /* only planes asked for */ 2165f7df2e56Smrg length = widthBytesLine * height * 2166f7df2e56Smrg Ones(planemask & (plane | (plane - 1))); 216705b261ecSmrg 216805b261ecSmrg } 216905b261ecSmrg 217005b261ecSmrg xgi.length = length; 217105b261ecSmrg 2172f7df2e56Smrg xgi.length = bytes_to_int32(xgi.length); 2173f7df2e56Smrg if (widthBytesLine == 0 || height == 0) 2174f7df2e56Smrg linesPerBuf = 0; 2175f7df2e56Smrg else if (widthBytesLine >= IMAGE_BUFSIZE) 2176f7df2e56Smrg linesPerBuf = 1; 2177f7df2e56Smrg else { 2178f7df2e56Smrg linesPerBuf = IMAGE_BUFSIZE / widthBytesLine; 2179f7df2e56Smrg if (linesPerBuf > height) 2180f7df2e56Smrg linesPerBuf = height; 2181f7df2e56Smrg } 2182f7df2e56Smrg length = linesPerBuf * widthBytesLine; 2183f7df2e56Smrg if (linesPerBuf < height) { 2184f7df2e56Smrg /* we have to make sure intermediate buffers don't need padding */ 2185f7df2e56Smrg while ((linesPerBuf > 1) && 2186f7df2e56Smrg (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD) - 1))) { 2187f7df2e56Smrg linesPerBuf--; 2188f7df2e56Smrg length -= widthBytesLine; 2189f7df2e56Smrg } 2190f7df2e56Smrg while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD) - 1)) { 2191f7df2e56Smrg linesPerBuf++; 2192f7df2e56Smrg length += widthBytesLine; 2193f7df2e56Smrg } 219405b261ecSmrg } 2195f7df2e56Smrg if (!(pBuf = calloc(1, length))) 2196f7df2e56Smrg return BadAlloc; 2197f7df2e56Smrg WriteReplyToClient(client, sizeof(xGetImageReply), &xgi); 219805b261ecSmrg 21997e31ba66Smrg if (pDraw->type == DRAWABLE_WINDOW) 22007e31ba66Smrg pVisibleRegion = &((WindowPtr) pDraw)->borderClip; 2201f7df2e56Smrg 2202f7df2e56Smrg if (linesPerBuf == 0) { 2203f7df2e56Smrg /* nothing to do */ 2204f7df2e56Smrg } 2205f7df2e56Smrg else if (format == ZPixmap) { 220605b261ecSmrg linesDone = 0; 2207f7df2e56Smrg while (height - linesDone > 0) { 2208f7df2e56Smrg nlines = min(linesPerBuf, height - linesDone); 2209f7df2e56Smrg (*pDraw->pScreen->GetImage) (pDraw, 2210f7df2e56Smrg x, 2211f7df2e56Smrg y + linesDone, 2212f7df2e56Smrg width, 2213f7df2e56Smrg nlines, 2214f7df2e56Smrg format, planemask, (void *) pBuf); 2215f7df2e56Smrg if (pVisibleRegion) 2216f7df2e56Smrg XaceCensorImage(client, pVisibleRegion, widthBytesLine, 2217f7df2e56Smrg pDraw, x, y + linesDone, width, 2218f7df2e56Smrg nlines, format, pBuf); 2219f7df2e56Smrg 2220f7df2e56Smrg /* Note that this is NOT a call to WriteSwappedDataToClient, 222105b261ecSmrg as we do NOT byte swap */ 2222f7df2e56Smrg ReformatImage(pBuf, (int) (nlines * widthBytesLine), 2223f7df2e56Smrg BitsPerPixel(pDraw->depth), ClientOrder(client)); 2224f7df2e56Smrg 2225f7df2e56Smrg WriteToClient(client, (int) (nlines * widthBytesLine), pBuf); 2226f7df2e56Smrg linesDone += nlines; 222705b261ecSmrg } 222805b261ecSmrg } 2229f7df2e56Smrg else { /* XYPixmap */ 2230f7df2e56Smrg 2231f7df2e56Smrg for (; plane; plane >>= 1) { 2232f7df2e56Smrg if (planemask & plane) { 2233f7df2e56Smrg linesDone = 0; 2234f7df2e56Smrg while (height - linesDone > 0) { 2235f7df2e56Smrg nlines = min(linesPerBuf, height - linesDone); 2236f7df2e56Smrg (*pDraw->pScreen->GetImage) (pDraw, 2237f7df2e56Smrg x, 2238f7df2e56Smrg y + linesDone, 2239f7df2e56Smrg width, 2240f7df2e56Smrg nlines, 2241f7df2e56Smrg format, plane, (void *) pBuf); 2242f7df2e56Smrg if (pVisibleRegion) 2243f7df2e56Smrg XaceCensorImage(client, pVisibleRegion, 2244f7df2e56Smrg widthBytesLine, 2245f7df2e56Smrg pDraw, x, y + linesDone, width, 2246f7df2e56Smrg nlines, format, pBuf); 2247f7df2e56Smrg 2248f7df2e56Smrg /* Note: NOT a call to WriteSwappedDataToClient, 2249f7df2e56Smrg as we do NOT byte swap */ 2250f7df2e56Smrg ReformatImage(pBuf, (int) (nlines * widthBytesLine), 2251f7df2e56Smrg 1, ClientOrder(client)); 2252f7df2e56Smrg 2253f7df2e56Smrg WriteToClient(client, (int)(nlines * widthBytesLine), pBuf); 2254f7df2e56Smrg linesDone += nlines; 2255f7df2e56Smrg } 225605b261ecSmrg } 2257f7df2e56Smrg } 225805b261ecSmrg } 2259f7df2e56Smrg free(pBuf); 22606747b715Smrg return Success; 226105b261ecSmrg} 226205b261ecSmrg 226305b261ecSmrgint 226405b261ecSmrgProcGetImage(ClientPtr client) 226505b261ecSmrg{ 226605b261ecSmrg REQUEST(xGetImageReq); 226705b261ecSmrg 226805b261ecSmrg REQUEST_SIZE_MATCH(xGetImageReq); 226905b261ecSmrg 227005b261ecSmrg return DoGetImage(client, stuff->format, stuff->drawable, 2271f7df2e56Smrg stuff->x, stuff->y, 2272f7df2e56Smrg (int) stuff->width, (int) stuff->height, 2273f7df2e56Smrg stuff->planeMask); 227405b261ecSmrg} 227505b261ecSmrg 227605b261ecSmrgint 227705b261ecSmrgProcPolyText(ClientPtr client) 227805b261ecSmrg{ 2279f7df2e56Smrg int err; 2280f7df2e56Smrg 228105b261ecSmrg REQUEST(xPolyTextReq); 228205b261ecSmrg DrawablePtr pDraw; 228305b261ecSmrg GC *pGC; 228405b261ecSmrg 228505b261ecSmrg REQUEST_AT_LEAST_SIZE(xPolyTextReq); 22864642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 228705b261ecSmrg 228805b261ecSmrg err = PolyText(client, 2289f7df2e56Smrg pDraw, 2290f7df2e56Smrg pGC, 2291f7df2e56Smrg (unsigned char *) &stuff[1], 2292f7df2e56Smrg ((unsigned char *) stuff) + (client->req_len << 2), 2293f7df2e56Smrg stuff->x, stuff->y, stuff->reqType, stuff->drawable); 2294f7df2e56Smrg 2295f7df2e56Smrg if (err == Success) { 2296f7df2e56Smrg return Success; 229705b261ecSmrg } 229805b261ecSmrg else 2299f7df2e56Smrg return err; 230005b261ecSmrg} 230105b261ecSmrg 230205b261ecSmrgint 230305b261ecSmrgProcImageText8(ClientPtr client) 230405b261ecSmrg{ 2305f7df2e56Smrg int err; 230605b261ecSmrg DrawablePtr pDraw; 230705b261ecSmrg GC *pGC; 230805b261ecSmrg 230905b261ecSmrg REQUEST(xImageTextReq); 231005b261ecSmrg 231105b261ecSmrg REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars); 23124642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 231305b261ecSmrg 231405b261ecSmrg err = ImageText(client, 2315f7df2e56Smrg pDraw, 2316f7df2e56Smrg pGC, 2317f7df2e56Smrg stuff->nChars, 2318f7df2e56Smrg (unsigned char *) &stuff[1], 2319f7df2e56Smrg stuff->x, stuff->y, stuff->reqType, stuff->drawable); 2320f7df2e56Smrg 2321f7df2e56Smrg if (err == Success) { 2322f7df2e56Smrg return Success; 232305b261ecSmrg } 232405b261ecSmrg else 2325f7df2e56Smrg return err; 232605b261ecSmrg} 232705b261ecSmrg 232805b261ecSmrgint 232905b261ecSmrgProcImageText16(ClientPtr client) 233005b261ecSmrg{ 2331f7df2e56Smrg int err; 233205b261ecSmrg DrawablePtr pDraw; 233305b261ecSmrg GC *pGC; 233405b261ecSmrg 233505b261ecSmrg REQUEST(xImageTextReq); 233605b261ecSmrg 233705b261ecSmrg REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1); 23384642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 233905b261ecSmrg 234005b261ecSmrg err = ImageText(client, 2341f7df2e56Smrg pDraw, 2342f7df2e56Smrg pGC, 2343f7df2e56Smrg stuff->nChars, 2344f7df2e56Smrg (unsigned char *) &stuff[1], 2345f7df2e56Smrg stuff->x, stuff->y, stuff->reqType, stuff->drawable); 2346f7df2e56Smrg 2347f7df2e56Smrg if (err == Success) { 2348f7df2e56Smrg return Success; 234905b261ecSmrg } 235005b261ecSmrg else 2351f7df2e56Smrg return err; 235205b261ecSmrg} 235305b261ecSmrg 235405b261ecSmrgint 235505b261ecSmrgProcCreateColormap(ClientPtr client) 235605b261ecSmrg{ 2357f7df2e56Smrg VisualPtr pVisual; 2358f7df2e56Smrg ColormapPtr pmap; 2359f7df2e56Smrg Colormap mid; 2360f7df2e56Smrg WindowPtr pWin; 236105b261ecSmrg ScreenPtr pScreen; 2362f7df2e56Smrg 236305b261ecSmrg REQUEST(xCreateColormapReq); 236405b261ecSmrg int i, result; 236505b261ecSmrg 236605b261ecSmrg REQUEST_SIZE_MATCH(xCreateColormapReq); 236705b261ecSmrg 2368f7df2e56Smrg if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll)) { 2369f7df2e56Smrg client->errorValue = stuff->alloc; 23706747b715Smrg return BadValue; 237105b261ecSmrg } 237205b261ecSmrg mid = stuff->mid; 237305b261ecSmrg LEGAL_NEW_RESOURCE(mid, client); 23744642e01fSmrg result = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 237505b261ecSmrg if (result != Success) 237605b261ecSmrg return result; 237705b261ecSmrg 237805b261ecSmrg pScreen = pWin->drawable.pScreen; 237905b261ecSmrg for (i = 0, pVisual = pScreen->visuals; 2380f7df2e56Smrg i < pScreen->numVisuals; i++, pVisual++) { 2381f7df2e56Smrg if (pVisual->vid != stuff->visual) 2382f7df2e56Smrg continue; 2383f7df2e56Smrg return CreateColormap(mid, pScreen, pVisual, &pmap, 2384f7df2e56Smrg (int) stuff->alloc, client->index); 238505b261ecSmrg } 238605b261ecSmrg client->errorValue = stuff->visual; 23876747b715Smrg return BadMatch; 238805b261ecSmrg} 238905b261ecSmrg 239005b261ecSmrgint 239105b261ecSmrgProcFreeColormap(ClientPtr client) 239205b261ecSmrg{ 239305b261ecSmrg ColormapPtr pmap; 23944642e01fSmrg int rc; 2395f7df2e56Smrg 239605b261ecSmrg REQUEST(xResourceReq); 239705b261ecSmrg 239805b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 2399f7df2e56Smrg rc = dixLookupResourceByType((void **) &pmap, stuff->id, RT_COLORMAP, 2400f7df2e56Smrg client, DixDestroyAccess); 2401f7df2e56Smrg if (rc == Success) { 2402f7df2e56Smrg /* Freeing a default colormap is a no-op */ 2403f7df2e56Smrg if (!(pmap->flags & IsDefault)) 2404f7df2e56Smrg FreeResource(stuff->id, RT_NONE); 2405f7df2e56Smrg return Success; 240605b261ecSmrg } 2407f7df2e56Smrg else { 2408f7df2e56Smrg client->errorValue = stuff->id; 2409f7df2e56Smrg return rc; 241005b261ecSmrg } 241105b261ecSmrg} 241205b261ecSmrg 241305b261ecSmrgint 241405b261ecSmrgProcCopyColormapAndFree(ClientPtr client) 241505b261ecSmrg{ 2416f7df2e56Smrg Colormap mid; 2417f7df2e56Smrg ColormapPtr pSrcMap; 2418f7df2e56Smrg 241905b261ecSmrg REQUEST(xCopyColormapAndFreeReq); 24204642e01fSmrg int rc; 242105b261ecSmrg 242205b261ecSmrg REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq); 242305b261ecSmrg mid = stuff->mid; 242405b261ecSmrg LEGAL_NEW_RESOURCE(mid, client); 2425f7df2e56Smrg rc = dixLookupResourceByType((void **) &pSrcMap, stuff->srcCmap, 2426f7df2e56Smrg RT_COLORMAP, client, 2427f7df2e56Smrg DixReadAccess | DixRemoveAccess); 24284642e01fSmrg if (rc == Success) 2429f7df2e56Smrg return CopyColormapAndFree(mid, pSrcMap, client->index); 24306747b715Smrg client->errorValue = stuff->srcCmap; 24316747b715Smrg return rc; 243205b261ecSmrg} 243305b261ecSmrg 243405b261ecSmrgint 243505b261ecSmrgProcInstallColormap(ClientPtr client) 243605b261ecSmrg{ 243705b261ecSmrg ColormapPtr pcmp; 24384642e01fSmrg int rc; 2439f7df2e56Smrg 244005b261ecSmrg REQUEST(xResourceReq); 244105b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 24424642e01fSmrg 2443f7df2e56Smrg rc = dixLookupResourceByType((void **) &pcmp, stuff->id, RT_COLORMAP, 2444f7df2e56Smrg client, DixInstallAccess); 24454642e01fSmrg if (rc != Success) 2446f7df2e56Smrg goto out; 24474642e01fSmrg 24484642e01fSmrg rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess); 24496747b715Smrg if (rc != Success) { 2450f7df2e56Smrg if (rc == BadValue) 2451f7df2e56Smrg rc = BadColor; 2452f7df2e56Smrg goto out; 24536747b715Smrg } 24544642e01fSmrg 24554642e01fSmrg (*(pcmp->pScreen->InstallColormap)) (pcmp); 24566747b715Smrg return Success; 24574642e01fSmrg 2458f7df2e56Smrg out: 24594642e01fSmrg client->errorValue = stuff->id; 24606747b715Smrg return rc; 246105b261ecSmrg} 246205b261ecSmrg 246305b261ecSmrgint 246405b261ecSmrgProcUninstallColormap(ClientPtr client) 246505b261ecSmrg{ 246605b261ecSmrg ColormapPtr pcmp; 24674642e01fSmrg int rc; 2468f7df2e56Smrg 246905b261ecSmrg REQUEST(xResourceReq); 247005b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 24714642e01fSmrg 2472f7df2e56Smrg rc = dixLookupResourceByType((void **) &pcmp, stuff->id, RT_COLORMAP, 2473f7df2e56Smrg client, DixUninstallAccess); 24744642e01fSmrg if (rc != Success) 2475f7df2e56Smrg goto out; 24764642e01fSmrg 24774642e01fSmrg rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess); 24786747b715Smrg if (rc != Success) { 2479f7df2e56Smrg if (rc == BadValue) 2480f7df2e56Smrg rc = BadColor; 2481f7df2e56Smrg goto out; 24826747b715Smrg } 24834642e01fSmrg 2484f7df2e56Smrg if (pcmp->mid != pcmp->pScreen->defColormap) 2485f7df2e56Smrg (*(pcmp->pScreen->UninstallColormap)) (pcmp); 24866747b715Smrg return Success; 24874642e01fSmrg 2488f7df2e56Smrg out: 24894642e01fSmrg client->errorValue = stuff->id; 24906747b715Smrg return rc; 249105b261ecSmrg} 249205b261ecSmrg 249305b261ecSmrgint 249405b261ecSmrgProcListInstalledColormaps(ClientPtr client) 249505b261ecSmrg{ 2496f7df2e56Smrg xListInstalledColormapsReply *preply; 249705b261ecSmrg int nummaps, rc; 249805b261ecSmrg WindowPtr pWin; 2499f7df2e56Smrg 250005b261ecSmrg REQUEST(xResourceReq); 250105b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 25024642e01fSmrg 25034642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess); 250405b261ecSmrg if (rc != Success) 2505f7df2e56Smrg return rc; 25064642e01fSmrg 25074642e01fSmrg rc = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen, 2508f7df2e56Smrg DixGetAttrAccess); 25094642e01fSmrg if (rc != Success) 2510f7df2e56Smrg return rc; 251105b261ecSmrg 25126747b715Smrg preply = malloc(sizeof(xListInstalledColormapsReply) + 2513f7df2e56Smrg pWin->drawable.pScreen->maxInstalledCmaps * 2514f7df2e56Smrg sizeof(Colormap)); 2515f7df2e56Smrg if (!preply) 25166747b715Smrg return BadAlloc; 251705b261ecSmrg 251805b261ecSmrg preply->type = X_Reply; 251905b261ecSmrg preply->sequenceNumber = client->sequence; 252005b261ecSmrg nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps) 2521f7df2e56Smrg (pWin->drawable.pScreen, (Colormap *) &preply[1]); 252205b261ecSmrg preply->nColormaps = nummaps; 252305b261ecSmrg preply->length = nummaps; 2524f7df2e56Smrg WriteReplyToClient(client, sizeof(xListInstalledColormapsReply), preply); 252505b261ecSmrg client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; 252605b261ecSmrg WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]); 25276747b715Smrg free(preply); 25286747b715Smrg return Success; 252905b261ecSmrg} 253005b261ecSmrg 253105b261ecSmrgint 2532f7df2e56SmrgProcAllocColor(ClientPtr client) 253305b261ecSmrg{ 253405b261ecSmrg ColormapPtr pmap; 25354642e01fSmrg int rc; 2536f7df2e56Smrg 253705b261ecSmrg REQUEST(xAllocColorReq); 253805b261ecSmrg 253905b261ecSmrg REQUEST_SIZE_MATCH(xAllocColorReq); 2540f7df2e56Smrg rc = dixLookupResourceByType((void **) &pmap, stuff->cmap, RT_COLORMAP, 2541f7df2e56Smrg client, DixAddAccess); 2542f7df2e56Smrg if (rc == Success) { 2543f7df2e56Smrg xAllocColorReply acr = { 2544f7df2e56Smrg .type = X_Reply, 2545f7df2e56Smrg .sequenceNumber = client->sequence, 2546f7df2e56Smrg .length = 0, 2547f7df2e56Smrg .red = stuff->red, 2548f7df2e56Smrg .green = stuff->green, 2549f7df2e56Smrg .blue = stuff->blue, 2550f7df2e56Smrg .pixel = 0 2551f7df2e56Smrg }; 2552f7df2e56Smrg if ((rc = AllocColor(pmap, &acr.red, &acr.green, &acr.blue, 2553f7df2e56Smrg &acr.pixel, client->index))) 2554f7df2e56Smrg return rc; 255505b261ecSmrg#ifdef PANORAMIX 2556f7df2e56Smrg if (noPanoramiXExtension || !pmap->pScreen->myNum) 255705b261ecSmrg#endif 2558f7df2e56Smrg WriteReplyToClient(client, sizeof(xAllocColorReply), &acr); 2559f7df2e56Smrg return Success; 256005b261ecSmrg 256105b261ecSmrg } 2562f7df2e56Smrg else { 256305b261ecSmrg client->errorValue = stuff->cmap; 25646747b715Smrg return rc; 256505b261ecSmrg } 256605b261ecSmrg} 256705b261ecSmrg 256805b261ecSmrgint 2569f7df2e56SmrgProcAllocNamedColor(ClientPtr client) 257005b261ecSmrg{ 257105b261ecSmrg ColormapPtr pcmp; 25724642e01fSmrg int rc; 2573f7df2e56Smrg 257405b261ecSmrg REQUEST(xAllocNamedColorReq); 257505b261ecSmrg 257605b261ecSmrg REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes); 2577f7df2e56Smrg rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, 2578f7df2e56Smrg client, DixAddAccess); 2579f7df2e56Smrg if (rc == Success) { 2580f7df2e56Smrg xAllocNamedColorReply ancr = { 2581f7df2e56Smrg .type = X_Reply, 2582f7df2e56Smrg .sequenceNumber = client->sequence, 2583f7df2e56Smrg .length = 0 2584f7df2e56Smrg }; 2585f7df2e56Smrg if (OsLookupColor 2586f7df2e56Smrg (pcmp->pScreen->myNum, (char *) &stuff[1], stuff->nbytes, 2587f7df2e56Smrg &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue)) { 2588f7df2e56Smrg ancr.screenRed = ancr.exactRed; 2589f7df2e56Smrg ancr.screenGreen = ancr.exactGreen; 2590f7df2e56Smrg ancr.screenBlue = ancr.exactBlue; 2591f7df2e56Smrg ancr.pixel = 0; 2592f7df2e56Smrg if ((rc = AllocColor(pcmp, 2593f7df2e56Smrg &ancr.screenRed, &ancr.screenGreen, 2594f7df2e56Smrg &ancr.screenBlue, &ancr.pixel, client->index))) 2595f7df2e56Smrg return rc; 259605b261ecSmrg#ifdef PANORAMIX 2597f7df2e56Smrg if (noPanoramiXExtension || !pcmp->pScreen->myNum) 259805b261ecSmrg#endif 2599f7df2e56Smrg WriteReplyToClient(client, sizeof(xAllocNamedColorReply), 2600f7df2e56Smrg &ancr); 2601f7df2e56Smrg return Success; 2602f7df2e56Smrg } 2603f7df2e56Smrg else 2604f7df2e56Smrg return BadName; 2605f7df2e56Smrg 260605b261ecSmrg } 2607f7df2e56Smrg else { 260805b261ecSmrg client->errorValue = stuff->cmap; 26096747b715Smrg return rc; 261005b261ecSmrg } 261105b261ecSmrg} 261205b261ecSmrg 261305b261ecSmrgint 2614f7df2e56SmrgProcAllocColorCells(ClientPtr client) 261505b261ecSmrg{ 261605b261ecSmrg ColormapPtr pcmp; 26174642e01fSmrg int rc; 2618f7df2e56Smrg 261905b261ecSmrg REQUEST(xAllocColorCellsReq); 262005b261ecSmrg 262105b261ecSmrg REQUEST_SIZE_MATCH(xAllocColorCellsReq); 2622f7df2e56Smrg rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, 2623f7df2e56Smrg client, DixAddAccess); 2624f7df2e56Smrg if (rc == Success) { 2625f7df2e56Smrg int npixels, nmasks; 2626f7df2e56Smrg long length; 2627f7df2e56Smrg Pixel *ppixels, *pmasks; 2628f7df2e56Smrg 2629f7df2e56Smrg npixels = stuff->colors; 2630f7df2e56Smrg if (!npixels) { 2631f7df2e56Smrg client->errorValue = npixels; 2632f7df2e56Smrg return BadValue; 2633f7df2e56Smrg } 2634f7df2e56Smrg if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) { 2635f7df2e56Smrg client->errorValue = stuff->contiguous; 2636f7df2e56Smrg return BadValue; 2637f7df2e56Smrg } 2638f7df2e56Smrg nmasks = stuff->planes; 2639f7df2e56Smrg length = ((long) npixels + (long) nmasks) * sizeof(Pixel); 2640f7df2e56Smrg ppixels = malloc(length); 2641f7df2e56Smrg if (!ppixels) 26426747b715Smrg return BadAlloc; 2643f7df2e56Smrg pmasks = ppixels + npixels; 2644f7df2e56Smrg 2645f7df2e56Smrg if ((rc = AllocColorCells(client->index, pcmp, npixels, nmasks, 2646f7df2e56Smrg (Bool) stuff->contiguous, ppixels, pmasks))) { 2647f7df2e56Smrg free(ppixels); 2648f7df2e56Smrg return rc; 2649f7df2e56Smrg } 265005b261ecSmrg#ifdef PANORAMIX 2651f7df2e56Smrg if (noPanoramiXExtension || !pcmp->pScreen->myNum) 265205b261ecSmrg#endif 2653f7df2e56Smrg { 2654f7df2e56Smrg xAllocColorCellsReply accr = { 2655f7df2e56Smrg .type = X_Reply, 2656f7df2e56Smrg .sequenceNumber = client->sequence, 2657f7df2e56Smrg .length = bytes_to_int32(length), 2658f7df2e56Smrg .nPixels = npixels, 2659f7df2e56Smrg .nMasks = nmasks 2660f7df2e56Smrg }; 2661f7df2e56Smrg WriteReplyToClient(client, sizeof(xAllocColorCellsReply), &accr); 2662f7df2e56Smrg client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; 2663f7df2e56Smrg WriteSwappedDataToClient(client, length, ppixels); 2664f7df2e56Smrg } 2665f7df2e56Smrg free(ppixels); 26666747b715Smrg return Success; 266705b261ecSmrg } 2668f7df2e56Smrg else { 266905b261ecSmrg client->errorValue = stuff->cmap; 26706747b715Smrg return rc; 267105b261ecSmrg } 267205b261ecSmrg} 267305b261ecSmrg 267405b261ecSmrgint 267505b261ecSmrgProcAllocColorPlanes(ClientPtr client) 267605b261ecSmrg{ 267705b261ecSmrg ColormapPtr pcmp; 26784642e01fSmrg int rc; 2679f7df2e56Smrg 268005b261ecSmrg REQUEST(xAllocColorPlanesReq); 268105b261ecSmrg 268205b261ecSmrg REQUEST_SIZE_MATCH(xAllocColorPlanesReq); 2683f7df2e56Smrg rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, 2684f7df2e56Smrg client, DixAddAccess); 2685f7df2e56Smrg if (rc == Success) { 2686f7df2e56Smrg xAllocColorPlanesReply acpr; 2687f7df2e56Smrg int npixels; 2688f7df2e56Smrg long length; 2689f7df2e56Smrg Pixel *ppixels; 2690f7df2e56Smrg 2691f7df2e56Smrg npixels = stuff->colors; 2692f7df2e56Smrg if (!npixels) { 2693f7df2e56Smrg client->errorValue = npixels; 2694f7df2e56Smrg return BadValue; 2695f7df2e56Smrg } 2696f7df2e56Smrg if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) { 2697f7df2e56Smrg client->errorValue = stuff->contiguous; 2698f7df2e56Smrg return BadValue; 2699f7df2e56Smrg } 2700f7df2e56Smrg acpr = (xAllocColorPlanesReply) { 2701f7df2e56Smrg .type = X_Reply, 2702f7df2e56Smrg .sequenceNumber = client->sequence, 2703f7df2e56Smrg .nPixels = npixels 2704f7df2e56Smrg }; 2705f7df2e56Smrg length = (long) npixels *sizeof(Pixel); 2706f7df2e56Smrg 2707f7df2e56Smrg ppixels = malloc(length); 2708f7df2e56Smrg if (!ppixels) 27096747b715Smrg return BadAlloc; 2710f7df2e56Smrg if ((rc = AllocColorPlanes(client->index, pcmp, npixels, 2711f7df2e56Smrg (int) stuff->red, (int) stuff->green, 2712f7df2e56Smrg (int) stuff->blue, (Bool) stuff->contiguous, 2713f7df2e56Smrg ppixels, &acpr.redMask, &acpr.greenMask, 2714f7df2e56Smrg &acpr.blueMask))) { 27156747b715Smrg free(ppixels); 2716f7df2e56Smrg return rc; 2717f7df2e56Smrg } 2718f7df2e56Smrg acpr.length = bytes_to_int32(length); 271905b261ecSmrg#ifdef PANORAMIX 2720f7df2e56Smrg if (noPanoramiXExtension || !pcmp->pScreen->myNum) 272105b261ecSmrg#endif 2722f7df2e56Smrg { 2723f7df2e56Smrg WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr); 2724f7df2e56Smrg client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; 2725f7df2e56Smrg WriteSwappedDataToClient(client, length, ppixels); 2726f7df2e56Smrg } 2727f7df2e56Smrg free(ppixels); 27286747b715Smrg return Success; 272905b261ecSmrg } 2730f7df2e56Smrg else { 273105b261ecSmrg client->errorValue = stuff->cmap; 27326747b715Smrg return rc; 273305b261ecSmrg } 273405b261ecSmrg} 273505b261ecSmrg 273605b261ecSmrgint 273705b261ecSmrgProcFreeColors(ClientPtr client) 273805b261ecSmrg{ 273905b261ecSmrg ColormapPtr pcmp; 27404642e01fSmrg int rc; 2741f7df2e56Smrg 274205b261ecSmrg REQUEST(xFreeColorsReq); 274305b261ecSmrg 274405b261ecSmrg REQUEST_AT_LEAST_SIZE(xFreeColorsReq); 2745f7df2e56Smrg rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, 2746f7df2e56Smrg client, DixRemoveAccess); 2747f7df2e56Smrg if (rc == Success) { 2748f7df2e56Smrg int count; 274905b261ecSmrg 2750f7df2e56Smrg if (pcmp->flags & AllAllocated) 2751f7df2e56Smrg return BadAccess; 2752f7df2e56Smrg count = bytes_to_int32((client->req_len << 2) - sizeof(xFreeColorsReq)); 2753f7df2e56Smrg return FreeColors(pcmp, client->index, count, 2754f7df2e56Smrg (Pixel *) &stuff[1], (Pixel) stuff->planeMask); 275505b261ecSmrg } 2756f7df2e56Smrg else { 275705b261ecSmrg client->errorValue = stuff->cmap; 27586747b715Smrg return rc; 275905b261ecSmrg } 276005b261ecSmrg} 276105b261ecSmrg 276205b261ecSmrgint 2763f7df2e56SmrgProcStoreColors(ClientPtr client) 276405b261ecSmrg{ 276505b261ecSmrg ColormapPtr pcmp; 27664642e01fSmrg int rc; 2767f7df2e56Smrg 276805b261ecSmrg REQUEST(xStoreColorsReq); 276905b261ecSmrg 277005b261ecSmrg REQUEST_AT_LEAST_SIZE(xStoreColorsReq); 2771f7df2e56Smrg rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, 2772f7df2e56Smrg client, DixWriteAccess); 2773f7df2e56Smrg if (rc == Success) { 2774f7df2e56Smrg int count; 277505b261ecSmrg 277605b261ecSmrg count = (client->req_len << 2) - sizeof(xStoreColorsReq); 2777f7df2e56Smrg if (count % sizeof(xColorItem)) 2778f7df2e56Smrg return BadLength; 2779f7df2e56Smrg count /= sizeof(xColorItem); 2780f7df2e56Smrg return StoreColors(pcmp, count, (xColorItem *) &stuff[1], client); 278105b261ecSmrg } 2782f7df2e56Smrg else { 278305b261ecSmrg client->errorValue = stuff->cmap; 27846747b715Smrg return rc; 278505b261ecSmrg } 278605b261ecSmrg} 278705b261ecSmrg 278805b261ecSmrgint 2789f7df2e56SmrgProcStoreNamedColor(ClientPtr client) 279005b261ecSmrg{ 279105b261ecSmrg ColormapPtr pcmp; 27924642e01fSmrg int rc; 2793f7df2e56Smrg 279405b261ecSmrg REQUEST(xStoreNamedColorReq); 279505b261ecSmrg 279605b261ecSmrg REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes); 2797f7df2e56Smrg rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, 2798f7df2e56Smrg client, DixWriteAccess); 2799f7df2e56Smrg if (rc == Success) { 2800f7df2e56Smrg xColorItem def; 2801f7df2e56Smrg 2802f7df2e56Smrg if (OsLookupColor(pcmp->pScreen->myNum, (char *) &stuff[1], 2803f7df2e56Smrg stuff->nbytes, &def.red, &def.green, &def.blue)) { 2804f7df2e56Smrg def.flags = stuff->flags; 2805f7df2e56Smrg def.pixel = stuff->pixel; 2806f7df2e56Smrg return StoreColors(pcmp, 1, &def, client); 2807f7df2e56Smrg } 28086747b715Smrg return BadName; 280905b261ecSmrg } 2810f7df2e56Smrg else { 281105b261ecSmrg client->errorValue = stuff->cmap; 28126747b715Smrg return rc; 281305b261ecSmrg } 281405b261ecSmrg} 281505b261ecSmrg 281605b261ecSmrgint 281705b261ecSmrgProcQueryColors(ClientPtr client) 281805b261ecSmrg{ 281905b261ecSmrg ColormapPtr pcmp; 28204642e01fSmrg int rc; 2821f7df2e56Smrg 282205b261ecSmrg REQUEST(xQueryColorsReq); 282305b261ecSmrg 282405b261ecSmrg REQUEST_AT_LEAST_SIZE(xQueryColorsReq); 2825f7df2e56Smrg rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, 2826f7df2e56Smrg client, DixReadAccess); 2827f7df2e56Smrg if (rc == Success) { 2828f7df2e56Smrg int count; 2829f7df2e56Smrg xrgb *prgbs; 2830f7df2e56Smrg xQueryColorsReply qcr; 2831f7df2e56Smrg 2832f7df2e56Smrg count = 2833f7df2e56Smrg bytes_to_int32((client->req_len << 2) - sizeof(xQueryColorsReq)); 2834f7df2e56Smrg prgbs = calloc(count, sizeof(xrgb)); 2835f7df2e56Smrg if (!prgbs && count) 28366747b715Smrg return BadAlloc; 2837f7df2e56Smrg if ((rc = 2838f7df2e56Smrg QueryColors(pcmp, count, (Pixel *) &stuff[1], prgbs, client))) { 2839f7df2e56Smrg free(prgbs); 2840f7df2e56Smrg return rc; 2841f7df2e56Smrg } 2842f7df2e56Smrg qcr = (xQueryColorsReply) { 2843f7df2e56Smrg .type = X_Reply, 2844f7df2e56Smrg .sequenceNumber = client->sequence, 2845f7df2e56Smrg .length = bytes_to_int32(count * sizeof(xrgb)), 2846f7df2e56Smrg .nColors = count 2847f7df2e56Smrg }; 2848f7df2e56Smrg WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr); 2849f7df2e56Smrg if (count) { 2850f7df2e56Smrg client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend; 2851f7df2e56Smrg WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs); 2852f7df2e56Smrg } 2853f7df2e56Smrg free(prgbs); 2854f7df2e56Smrg return Success; 2855f7df2e56Smrg 285605b261ecSmrg } 2857f7df2e56Smrg else { 285805b261ecSmrg client->errorValue = stuff->cmap; 28596747b715Smrg return rc; 286005b261ecSmrg } 2861f7df2e56Smrg} 286205b261ecSmrg 286305b261ecSmrgint 286405b261ecSmrgProcLookupColor(ClientPtr client) 286505b261ecSmrg{ 286605b261ecSmrg ColormapPtr pcmp; 28674642e01fSmrg int rc; 2868f7df2e56Smrg 286905b261ecSmrg REQUEST(xLookupColorReq); 287005b261ecSmrg 287105b261ecSmrg REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes); 2872f7df2e56Smrg rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, 2873f7df2e56Smrg client, DixReadAccess); 2874f7df2e56Smrg if (rc == Success) { 2875f7df2e56Smrg CARD16 exactRed, exactGreen, exactBlue; 2876f7df2e56Smrg 2877f7df2e56Smrg if (OsLookupColor 2878f7df2e56Smrg (pcmp->pScreen->myNum, (char *) &stuff[1], stuff->nbytes, 2879f7df2e56Smrg &exactRed, &exactGreen, &exactBlue)) { 2880f7df2e56Smrg xLookupColorReply lcr = { 2881f7df2e56Smrg .type = X_Reply, 2882f7df2e56Smrg .sequenceNumber = client->sequence, 2883f7df2e56Smrg .length = 0, 2884f7df2e56Smrg .exactRed = exactRed, 2885f7df2e56Smrg .exactGreen = exactGreen, 2886f7df2e56Smrg .exactBlue = exactBlue, 2887f7df2e56Smrg .screenRed = exactRed, 2888f7df2e56Smrg .screenGreen = exactGreen, 2889f7df2e56Smrg .screenBlue = exactBlue 2890f7df2e56Smrg }; 2891f7df2e56Smrg (*pcmp->pScreen->ResolveColor) (&lcr.screenRed, 2892f7df2e56Smrg &lcr.screenGreen, 2893f7df2e56Smrg &lcr.screenBlue, pcmp->pVisual); 2894f7df2e56Smrg WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr); 2895f7df2e56Smrg return Success; 2896f7df2e56Smrg } 28976747b715Smrg return BadName; 289805b261ecSmrg } 2899f7df2e56Smrg else { 290005b261ecSmrg client->errorValue = stuff->cmap; 29016747b715Smrg return rc; 290205b261ecSmrg } 290305b261ecSmrg} 290405b261ecSmrg 290505b261ecSmrgint 2906f7df2e56SmrgProcCreateCursor(ClientPtr client) 290705b261ecSmrg{ 2908f7df2e56Smrg CursorPtr pCursor; 2909f7df2e56Smrg PixmapPtr src; 2910f7df2e56Smrg PixmapPtr msk; 2911f7df2e56Smrg unsigned char *srcbits; 2912f7df2e56Smrg unsigned char *mskbits; 2913f7df2e56Smrg unsigned short width, height; 2914f7df2e56Smrg long n; 2915f7df2e56Smrg CursorMetricRec cm; 29164642e01fSmrg int rc; 291705b261ecSmrg 291805b261ecSmrg REQUEST(xCreateCursorReq); 291905b261ecSmrg 292005b261ecSmrg REQUEST_SIZE_MATCH(xCreateCursorReq); 292105b261ecSmrg LEGAL_NEW_RESOURCE(stuff->cid, client); 292205b261ecSmrg 2923f7df2e56Smrg rc = dixLookupResourceByType((void **) &src, stuff->source, RT_PIXMAP, 2924f7df2e56Smrg client, DixReadAccess); 29254642e01fSmrg if (rc != Success) { 2926f7df2e56Smrg client->errorValue = stuff->source; 2927f7df2e56Smrg return rc; 292805b261ecSmrg } 29294642e01fSmrg 2930f7df2e56Smrg if (src->drawable.depth != 1) 2931f7df2e56Smrg return (BadMatch); 2932f7df2e56Smrg 2933f7df2e56Smrg /* Find and validate cursor mask pixmap, if one is provided */ 2934f7df2e56Smrg if (stuff->mask != None) { 2935f7df2e56Smrg rc = dixLookupResourceByType((void **) &msk, stuff->mask, RT_PIXMAP, 2936f7df2e56Smrg client, DixReadAccess); 2937f7df2e56Smrg if (rc != Success) { 2938f7df2e56Smrg client->errorValue = stuff->mask; 2939f7df2e56Smrg return rc; 2940f7df2e56Smrg } 2941f7df2e56Smrg 2942f7df2e56Smrg if (src->drawable.width != msk->drawable.width 2943f7df2e56Smrg || src->drawable.height != msk->drawable.height 2944f7df2e56Smrg || src->drawable.depth != 1 || msk->drawable.depth != 1) 2945f7df2e56Smrg return BadMatch; 2946f7df2e56Smrg } 2947f7df2e56Smrg else 2948f7df2e56Smrg msk = NULL; 294905b261ecSmrg 295005b261ecSmrg width = src->drawable.width; 295105b261ecSmrg height = src->drawable.height; 295205b261ecSmrg 2953f7df2e56Smrg if (stuff->x > width || stuff->y > height) 2954f7df2e56Smrg return BadMatch; 295505b261ecSmrg 2956f7df2e56Smrg srcbits = calloc(BitmapBytePad(width), height); 295705b261ecSmrg if (!srcbits) 2958f7df2e56Smrg return BadAlloc; 2959f7df2e56Smrg n = BitmapBytePad(width) * height; 29606747b715Smrg mskbits = malloc(n); 2961f7df2e56Smrg if (!mskbits) { 2962f7df2e56Smrg free(srcbits); 2963f7df2e56Smrg return BadAlloc; 296405b261ecSmrg } 296505b261ecSmrg 2966f7df2e56Smrg (*src->drawable.pScreen->GetImage) ((DrawablePtr) src, 0, 0, width, height, 2967f7df2e56Smrg XYPixmap, 1, (void *) srcbits); 2968f7df2e56Smrg if (msk == (PixmapPtr) NULL) { 2969f7df2e56Smrg unsigned char *bits = mskbits; 2970f7df2e56Smrg 2971f7df2e56Smrg while (--n >= 0) 2972f7df2e56Smrg *bits++ = ~0; 297305b261ecSmrg } 2974f7df2e56Smrg else { 2975f7df2e56Smrg /* zeroing the (pad) bits helps some ddx cursor handling */ 2976f7df2e56Smrg memset((char *) mskbits, 0, n); 2977f7df2e56Smrg (*msk->drawable.pScreen->GetImage) ((DrawablePtr) msk, 0, 0, width, 2978f7df2e56Smrg height, XYPixmap, 1, 2979f7df2e56Smrg (void *) mskbits); 298005b261ecSmrg } 298105b261ecSmrg cm.width = width; 298205b261ecSmrg cm.height = height; 298305b261ecSmrg cm.xhot = stuff->x; 298405b261ecSmrg cm.yhot = stuff->y; 29854642e01fSmrg rc = AllocARGBCursor(srcbits, mskbits, NULL, &cm, 2986f7df2e56Smrg stuff->foreRed, stuff->foreGreen, stuff->foreBlue, 2987f7df2e56Smrg stuff->backRed, stuff->backGreen, stuff->backBlue, 2988f7df2e56Smrg &pCursor, client, stuff->cid); 298905b261ecSmrg 29904642e01fSmrg if (rc != Success) 2991f7df2e56Smrg goto bail; 2992f7df2e56Smrg if (!AddResource(stuff->cid, RT_CURSOR, (void *) pCursor)) { 2993f7df2e56Smrg rc = BadAlloc; 2994f7df2e56Smrg goto bail; 2995f7df2e56Smrg } 29964642e01fSmrg 29976747b715Smrg return Success; 2998f7df2e56Smrg bail: 2999f7df2e56Smrg free(srcbits); 3000f7df2e56Smrg free(mskbits); 3001f7df2e56Smrg return rc; 300205b261ecSmrg} 300305b261ecSmrg 300405b261ecSmrgint 3005f7df2e56SmrgProcCreateGlyphCursor(ClientPtr client) 300605b261ecSmrg{ 300705b261ecSmrg CursorPtr pCursor; 300805b261ecSmrg int res; 300905b261ecSmrg 301005b261ecSmrg REQUEST(xCreateGlyphCursorReq); 301105b261ecSmrg 301205b261ecSmrg REQUEST_SIZE_MATCH(xCreateGlyphCursorReq); 301305b261ecSmrg LEGAL_NEW_RESOURCE(stuff->cid, client); 301405b261ecSmrg 301505b261ecSmrg res = AllocGlyphCursor(stuff->source, stuff->sourceChar, 3016f7df2e56Smrg stuff->mask, stuff->maskChar, 3017f7df2e56Smrg stuff->foreRed, stuff->foreGreen, stuff->foreBlue, 3018f7df2e56Smrg stuff->backRed, stuff->backGreen, stuff->backBlue, 3019f7df2e56Smrg &pCursor, client, stuff->cid); 302005b261ecSmrg if (res != Success) 3021f7df2e56Smrg return res; 3022f7df2e56Smrg if (AddResource(stuff->cid, RT_CURSOR, (void *) pCursor)) 3023f7df2e56Smrg return Success; 302405b261ecSmrg return BadAlloc; 302505b261ecSmrg} 302605b261ecSmrg 302705b261ecSmrgint 3028f7df2e56SmrgProcFreeCursor(ClientPtr client) 302905b261ecSmrg{ 303005b261ecSmrg CursorPtr pCursor; 30314642e01fSmrg int rc; 3032f7df2e56Smrg 303305b261ecSmrg REQUEST(xResourceReq); 303405b261ecSmrg 303505b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 3036f7df2e56Smrg rc = dixLookupResourceByType((void **) &pCursor, stuff->id, RT_CURSOR, 3037f7df2e56Smrg client, DixDestroyAccess); 3038f7df2e56Smrg if (rc == Success) { 3039f7df2e56Smrg FreeResource(stuff->id, RT_NONE); 3040f7df2e56Smrg return Success; 304105b261ecSmrg } 3042f7df2e56Smrg else { 3043f7df2e56Smrg client->errorValue = stuff->id; 3044f7df2e56Smrg return rc; 304505b261ecSmrg } 304605b261ecSmrg} 304705b261ecSmrg 304805b261ecSmrgint 3049f7df2e56SmrgProcQueryBestSize(ClientPtr client) 305005b261ecSmrg{ 3051f7df2e56Smrg xQueryBestSizeReply reply; 305205b261ecSmrg DrawablePtr pDraw; 305305b261ecSmrg ScreenPtr pScreen; 305405b261ecSmrg int rc; 3055f7df2e56Smrg 305605b261ecSmrg REQUEST(xQueryBestSizeReq); 305705b261ecSmrg REQUEST_SIZE_MATCH(xQueryBestSizeReq); 305805b261ecSmrg 3059f7df2e56Smrg if ((stuff->class != CursorShape) && 3060f7df2e56Smrg (stuff->class != TileShape) && (stuff->class != StippleShape)) { 3061f7df2e56Smrg client->errorValue = stuff->class; 30626747b715Smrg return BadValue; 306305b261ecSmrg } 306405b261ecSmrg 306505b261ecSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, 3066f7df2e56Smrg DixGetAttrAccess); 306705b261ecSmrg if (rc != Success) 3068f7df2e56Smrg return rc; 306905b261ecSmrg if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW) 3070f7df2e56Smrg return BadMatch; 307105b261ecSmrg pScreen = pDraw->pScreen; 30724642e01fSmrg rc = XaceHook(XACE_SCREEN_ACCESS, client, pScreen, DixGetAttrAccess); 30734642e01fSmrg if (rc != Success) 3074f7df2e56Smrg return rc; 3075f7df2e56Smrg (*pScreen->QueryBestSize) (stuff->class, &stuff->width, 3076f7df2e56Smrg &stuff->height, pScreen); 3077f7df2e56Smrg reply = (xQueryBestSizeReply) { 3078f7df2e56Smrg .type = X_Reply, 3079f7df2e56Smrg .sequenceNumber = client->sequence, 3080f7df2e56Smrg .length = 0, 3081f7df2e56Smrg .width = stuff->width, 3082f7df2e56Smrg .height = stuff->height 3083f7df2e56Smrg }; 308405b261ecSmrg WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply); 30856747b715Smrg return Success; 308605b261ecSmrg} 308705b261ecSmrg 308805b261ecSmrgint 3089f7df2e56SmrgProcSetScreenSaver(ClientPtr client) 309005b261ecSmrg{ 30914642e01fSmrg int rc, i, blankingOption, exposureOption; 3092f7df2e56Smrg 309305b261ecSmrg REQUEST(xSetScreenSaverReq); 309405b261ecSmrg REQUEST_SIZE_MATCH(xSetScreenSaverReq); 30954642e01fSmrg 30964642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) { 3097f7df2e56Smrg rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i], 3098f7df2e56Smrg DixSetAttrAccess); 3099f7df2e56Smrg if (rc != Success) 3100f7df2e56Smrg return rc; 31014642e01fSmrg } 31024642e01fSmrg 310305b261ecSmrg blankingOption = stuff->preferBlank; 310405b261ecSmrg if ((blankingOption != DontPreferBlanking) && 310505b261ecSmrg (blankingOption != PreferBlanking) && 3106f7df2e56Smrg (blankingOption != DefaultBlanking)) { 3107f7df2e56Smrg client->errorValue = blankingOption; 310805b261ecSmrg return BadValue; 310905b261ecSmrg } 311005b261ecSmrg exposureOption = stuff->allowExpose; 311105b261ecSmrg if ((exposureOption != DontAllowExposures) && 311205b261ecSmrg (exposureOption != AllowExposures) && 3113f7df2e56Smrg (exposureOption != DefaultExposures)) { 3114f7df2e56Smrg client->errorValue = exposureOption; 311505b261ecSmrg return BadValue; 311605b261ecSmrg } 3117f7df2e56Smrg if (stuff->timeout < -1) { 3118f7df2e56Smrg client->errorValue = stuff->timeout; 311905b261ecSmrg return BadValue; 312005b261ecSmrg } 3121f7df2e56Smrg if (stuff->interval < -1) { 3122f7df2e56Smrg client->errorValue = stuff->interval; 312305b261ecSmrg return BadValue; 312405b261ecSmrg } 312505b261ecSmrg 312605b261ecSmrg if (blankingOption == DefaultBlanking) 3127f7df2e56Smrg ScreenSaverBlanking = defaultScreenSaverBlanking; 312805b261ecSmrg else 3129f7df2e56Smrg ScreenSaverBlanking = blankingOption; 313005b261ecSmrg if (exposureOption == DefaultExposures) 3131f7df2e56Smrg ScreenSaverAllowExposures = defaultScreenSaverAllowExposures; 313205b261ecSmrg else 3133f7df2e56Smrg ScreenSaverAllowExposures = exposureOption; 313405b261ecSmrg 313505b261ecSmrg if (stuff->timeout >= 0) 3136f7df2e56Smrg ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND; 3137f7df2e56Smrg else 3138f7df2e56Smrg ScreenSaverTime = defaultScreenSaverTime; 313905b261ecSmrg if (stuff->interval >= 0) 3140f7df2e56Smrg ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND; 314105b261ecSmrg else 3142f7df2e56Smrg ScreenSaverInterval = defaultScreenSaverInterval; 314305b261ecSmrg 314405b261ecSmrg SetScreenSaverTimer(); 31456747b715Smrg return Success; 314605b261ecSmrg} 314705b261ecSmrg 314805b261ecSmrgint 314905b261ecSmrgProcGetScreenSaver(ClientPtr client) 315005b261ecSmrg{ 315105b261ecSmrg xGetScreenSaverReply rep; 31524642e01fSmrg int rc, i; 3153f7df2e56Smrg 315405b261ecSmrg REQUEST_SIZE_MATCH(xReq); 31554642e01fSmrg 31564642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) { 3157f7df2e56Smrg rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i], 3158f7df2e56Smrg DixGetAttrAccess); 3159f7df2e56Smrg if (rc != Success) 3160f7df2e56Smrg return rc; 3161f7df2e56Smrg } 3162f7df2e56Smrg 3163f7df2e56Smrg rep = (xGetScreenSaverReply) { 3164f7df2e56Smrg .type = X_Reply, 3165f7df2e56Smrg .sequenceNumber = client->sequence, 3166f7df2e56Smrg .length = 0, 3167f7df2e56Smrg .timeout = ScreenSaverTime / MILLI_PER_SECOND, 3168f7df2e56Smrg .interval = ScreenSaverInterval / MILLI_PER_SECOND, 3169f7df2e56Smrg .preferBlanking = ScreenSaverBlanking, 3170f7df2e56Smrg .allowExposures = ScreenSaverAllowExposures 3171f7df2e56Smrg }; 317205b261ecSmrg WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep); 31736747b715Smrg return Success; 317405b261ecSmrg} 317505b261ecSmrg 317605b261ecSmrgint 317705b261ecSmrgProcChangeHosts(ClientPtr client) 317805b261ecSmrg{ 317905b261ecSmrg REQUEST(xChangeHostsReq); 318005b261ecSmrg 318105b261ecSmrg REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength); 318205b261ecSmrg 3183f7df2e56Smrg if (stuff->mode == HostInsert) 3184f7df2e56Smrg return AddHost(client, (int) stuff->hostFamily, 3185f7df2e56Smrg stuff->hostLength, (void *) &stuff[1]); 31866747b715Smrg if (stuff->mode == HostDelete) 3187f7df2e56Smrg return RemoveHost(client, (int) stuff->hostFamily, 3188f7df2e56Smrg stuff->hostLength, (void *) &stuff[1]); 31896747b715Smrg client->errorValue = stuff->mode; 31906747b715Smrg return BadValue; 319105b261ecSmrg} 319205b261ecSmrg 319305b261ecSmrgint 319405b261ecSmrgProcListHosts(ClientPtr client) 319505b261ecSmrg{ 319605b261ecSmrg xListHostsReply reply; 3197f7df2e56Smrg int len, nHosts, result; 3198f7df2e56Smrg BOOL enabled; 3199f7df2e56Smrg void *pdata; 3200f7df2e56Smrg 320105b261ecSmrg /* REQUEST(xListHostsReq); */ 320205b261ecSmrg 320305b261ecSmrg REQUEST_SIZE_MATCH(xListHostsReq); 320405b261ecSmrg 320505b261ecSmrg /* untrusted clients can't list hosts */ 32064642e01fSmrg result = XaceHook(XACE_SERVER_ACCESS, client, DixReadAccess); 32074642e01fSmrg if (result != Success) 3208f7df2e56Smrg return result; 320905b261ecSmrg 3210f7df2e56Smrg result = GetHosts(&pdata, &nHosts, &len, &enabled); 321105b261ecSmrg if (result != Success) 3212f7df2e56Smrg return result; 3213f7df2e56Smrg 3214f7df2e56Smrg reply = (xListHostsReply) { 3215f7df2e56Smrg .type = X_Reply, 3216f7df2e56Smrg .enabled = enabled, 3217f7df2e56Smrg .sequenceNumber = client->sequence, 3218f7df2e56Smrg .length = bytes_to_int32(len), 3219f7df2e56Smrg .nHosts = nHosts 3220f7df2e56Smrg }; 322105b261ecSmrg WriteReplyToClient(client, sizeof(xListHostsReply), &reply); 3222f7df2e56Smrg if (nHosts) { 3223f7df2e56Smrg client->pSwapReplyFunc = (ReplySwapPtr) SLHostsExtend; 3224f7df2e56Smrg WriteSwappedDataToClient(client, len, pdata); 322505b261ecSmrg } 32266747b715Smrg free(pdata); 32276747b715Smrg return Success; 322805b261ecSmrg} 322905b261ecSmrg 323005b261ecSmrgint 323105b261ecSmrgProcChangeAccessControl(ClientPtr client) 323205b261ecSmrg{ 323305b261ecSmrg REQUEST(xSetAccessControlReq); 323405b261ecSmrg 323505b261ecSmrg REQUEST_SIZE_MATCH(xSetAccessControlReq); 3236f7df2e56Smrg if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess)) { 3237f7df2e56Smrg client->errorValue = stuff->mode; 323805b261ecSmrg return BadValue; 323905b261ecSmrg } 32406747b715Smrg return ChangeAccessControl(client, stuff->mode == EnableAccess); 324105b261ecSmrg} 324205b261ecSmrg 324305b261ecSmrg/********************* 324405b261ecSmrg * CloseDownRetainedResources 324505b261ecSmrg * 3246f7df2e56Smrg * Find all clients that are gone and have terminated in RetainTemporary 324705b261ecSmrg * and destroy their resources. 324805b261ecSmrg *********************/ 324905b261ecSmrg 325005b261ecSmrgstatic void 325105b261ecSmrgCloseDownRetainedResources(void) 325205b261ecSmrg{ 325305b261ecSmrg int i; 325405b261ecSmrg ClientPtr client; 325505b261ecSmrg 3256f7df2e56Smrg for (i = 1; i < currentMaxClients; i++) { 325705b261ecSmrg client = clients[i]; 325805b261ecSmrg if (client && (client->closeDownMode == RetainTemporary) 3259f7df2e56Smrg && (client->clientGone)) 3260f7df2e56Smrg CloseDownClient(client); 326105b261ecSmrg } 326205b261ecSmrg} 326305b261ecSmrg 326405b261ecSmrgint 326505b261ecSmrgProcKillClient(ClientPtr client) 326605b261ecSmrg{ 326705b261ecSmrg REQUEST(xResourceReq); 326805b261ecSmrg ClientPtr killclient; 326905b261ecSmrg int rc; 327005b261ecSmrg 327105b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 3272f7df2e56Smrg if (stuff->id == AllTemporary) { 3273f7df2e56Smrg CloseDownRetainedResources(); 32746747b715Smrg return Success; 327505b261ecSmrg } 327605b261ecSmrg 327705b261ecSmrg rc = dixLookupClient(&killclient, stuff->id, client, DixDestroyAccess); 327805b261ecSmrg if (rc == Success) { 3279f7df2e56Smrg CloseDownClient(killclient); 3280f7df2e56Smrg if (client == killclient) { 3281f7df2e56Smrg /* force yield and return Success, so that Dispatch() 3282f7df2e56Smrg * doesn't try to touch client 3283f7df2e56Smrg */ 3284f7df2e56Smrg isItTimeToYield = TRUE; 3285f7df2e56Smrg } 3286f7df2e56Smrg return Success; 328705b261ecSmrg } 328805b261ecSmrg else 3289f7df2e56Smrg return rc; 329005b261ecSmrg} 329105b261ecSmrg 329205b261ecSmrgint 329305b261ecSmrgProcSetFontPath(ClientPtr client) 329405b261ecSmrg{ 329505b261ecSmrg unsigned char *ptr; 329605b261ecSmrg unsigned long nbytes, total; 329705b261ecSmrg long nfonts; 32986747b715Smrg int n; 3299f7df2e56Smrg 330005b261ecSmrg REQUEST(xSetFontPathReq); 3301f7df2e56Smrg 330205b261ecSmrg REQUEST_AT_LEAST_SIZE(xSetFontPathReq); 3303f7df2e56Smrg 330405b261ecSmrg nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq); 330505b261ecSmrg total = nbytes; 3306f7df2e56Smrg ptr = (unsigned char *) &stuff[1]; 330705b261ecSmrg nfonts = stuff->nFonts; 3308f7df2e56Smrg while (--nfonts >= 0) { 3309f7df2e56Smrg if ((total == 0) || (total < (n = (*ptr + 1)))) 3310f7df2e56Smrg return BadLength; 3311f7df2e56Smrg total -= n; 3312f7df2e56Smrg ptr += n; 331305b261ecSmrg } 331405b261ecSmrg if (total >= 4) 3315f7df2e56Smrg return BadLength; 3316f7df2e56Smrg return SetFontPath(client, stuff->nFonts, (unsigned char *) &stuff[1]); 331705b261ecSmrg} 331805b261ecSmrg 331905b261ecSmrgint 332005b261ecSmrgProcGetFontPath(ClientPtr client) 332105b261ecSmrg{ 332205b261ecSmrg xGetFontPathReply reply; 33234642e01fSmrg int rc, stringLens, numpaths; 332405b261ecSmrg unsigned char *bufferStart; 3325f7df2e56Smrg 332605b261ecSmrg /* REQUEST (xReq); */ 332705b261ecSmrg 332805b261ecSmrg REQUEST_SIZE_MATCH(xReq); 33294642e01fSmrg rc = GetFontPath(client, &numpaths, &stringLens, &bufferStart); 33304642e01fSmrg if (rc != Success) 3331f7df2e56Smrg return rc; 333205b261ecSmrg 3333f7df2e56Smrg reply = (xGetFontPathReply) { 3334f7df2e56Smrg .type = X_Reply, 3335f7df2e56Smrg .sequenceNumber = client->sequence, 3336f7df2e56Smrg .length = bytes_to_int32(stringLens + numpaths), 3337f7df2e56Smrg .nPaths = numpaths 3338f7df2e56Smrg }; 333905b261ecSmrg 334005b261ecSmrg WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply); 334105b261ecSmrg if (stringLens || numpaths) 3342f7df2e56Smrg WriteToClient(client, stringLens + numpaths, bufferStart); 33436747b715Smrg return Success; 334405b261ecSmrg} 334505b261ecSmrg 334605b261ecSmrgint 334705b261ecSmrgProcChangeCloseDownMode(ClientPtr client) 334805b261ecSmrg{ 33494642e01fSmrg int rc; 3350f7df2e56Smrg 335105b261ecSmrg REQUEST(xSetCloseDownModeReq); 335205b261ecSmrg REQUEST_SIZE_MATCH(xSetCloseDownModeReq); 33534642e01fSmrg 33544642e01fSmrg rc = XaceHook(XACE_CLIENT_ACCESS, client, client, DixManageAccess); 33554642e01fSmrg if (rc != Success) 3356f7df2e56Smrg return rc; 33574642e01fSmrg 335805b261ecSmrg if ((stuff->mode == AllTemporary) || 3359f7df2e56Smrg (stuff->mode == RetainPermanent) || (stuff->mode == RetainTemporary)) { 3360f7df2e56Smrg client->closeDownMode = stuff->mode; 3361f7df2e56Smrg return Success; 336205b261ecSmrg } 3363f7df2e56Smrg else { 3364f7df2e56Smrg client->errorValue = stuff->mode; 3365f7df2e56Smrg return BadValue; 336605b261ecSmrg } 336705b261ecSmrg} 336805b261ecSmrg 3369f7df2e56Smrgint 3370f7df2e56SmrgProcForceScreenSaver(ClientPtr client) 3371f7df2e56Smrg{ 33724642e01fSmrg int rc; 3373f7df2e56Smrg 337405b261ecSmrg REQUEST(xForceScreenSaverReq); 337505b261ecSmrg 337605b261ecSmrg REQUEST_SIZE_MATCH(xForceScreenSaverReq); 3377f7df2e56Smrg 3378f7df2e56Smrg if ((stuff->mode != ScreenSaverReset) && (stuff->mode != ScreenSaverActive)) { 3379f7df2e56Smrg client->errorValue = stuff->mode; 338005b261ecSmrg return BadValue; 338105b261ecSmrg } 3382f7df2e56Smrg rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, (int) stuff->mode); 33834642e01fSmrg if (rc != Success) 3384f7df2e56Smrg return rc; 33856747b715Smrg return Success; 338605b261ecSmrg} 338705b261ecSmrg 3388f7df2e56Smrgint 3389f7df2e56SmrgProcNoOperation(ClientPtr client) 339005b261ecSmrg{ 339105b261ecSmrg REQUEST_AT_LEAST_SIZE(xReq); 3392f7df2e56Smrg 339305b261ecSmrg /* noop -- don't do anything */ 33946747b715Smrg return Success; 339505b261ecSmrg} 339605b261ecSmrg 339705b261ecSmrg/********************** 339805b261ecSmrg * CloseDownClient 339905b261ecSmrg * 340005b261ecSmrg * Client can either mark his resources destroy or retain. If retained and 340105b261ecSmrg * then killed again, the client is really destroyed. 340205b261ecSmrg *********************/ 340305b261ecSmrg 340405b261ecSmrgchar dispatchExceptionAtReset = DE_RESET; 340505b261ecSmrg 340605b261ecSmrgvoid 340705b261ecSmrgCloseDownClient(ClientPtr client) 340805b261ecSmrg{ 340905b261ecSmrg Bool really_close_down = client->clientGone || 3410f7df2e56Smrg client->closeDownMode == DestroyAll; 341105b261ecSmrg 3412f7df2e56Smrg if (!client->clientGone) { 3413f7df2e56Smrg /* ungrab server if grabbing client dies */ 3414f7df2e56Smrg if (grabState != GrabNone && grabClient == client) { 3415f7df2e56Smrg UngrabServer(client); 3416f7df2e56Smrg } 3417f7df2e56Smrg BITCLEAR(grabWaiters, client->index); 3418f7df2e56Smrg DeleteClientFromAnySelections(client); 3419f7df2e56Smrg ReleaseActiveGrabs(client); 3420f7df2e56Smrg DeleteClientFontStuff(client); 3421f7df2e56Smrg if (!really_close_down) { 3422f7df2e56Smrg /* This frees resources that should never be retained 3423f7df2e56Smrg * no matter what the close down mode is. Actually we 3424f7df2e56Smrg * could do this unconditionally, but it's probably 3425f7df2e56Smrg * better not to traverse all the client's resources 3426f7df2e56Smrg * twice (once here, once a few lines down in 3427f7df2e56Smrg * FreeClientResources) in the common case of 3428f7df2e56Smrg * really_close_down == TRUE. 3429f7df2e56Smrg */ 3430f7df2e56Smrg FreeClientNeverRetainResources(client); 3431f7df2e56Smrg client->clientState = ClientStateRetained; 3432f7df2e56Smrg if (ClientStateCallback) { 3433f7df2e56Smrg NewClientInfoRec clientinfo; 3434f7df2e56Smrg 3435f7df2e56Smrg clientinfo.client = client; 3436f7df2e56Smrg clientinfo.prefix = (xConnSetupPrefix *) NULL; 3437f7df2e56Smrg clientinfo.setup = (xConnSetup *) NULL; 3438f7df2e56Smrg CallCallbacks((&ClientStateCallback), (void *) &clientinfo); 3439f7df2e56Smrg } 3440f7df2e56Smrg } 3441f7df2e56Smrg client->clientGone = TRUE; /* so events aren't sent to client */ 3442f7df2e56Smrg if (ClientIsAsleep(client)) 3443f7df2e56Smrg ClientSignal(client); 3444f7df2e56Smrg ProcessWorkQueueZombies(); 3445f7df2e56Smrg CloseDownConnection(client); 34467e31ba66Smrg output_pending_clear(client); 34477e31ba66Smrg mark_client_not_ready(client); 3448f7df2e56Smrg 3449f7df2e56Smrg /* If the client made it to the Running stage, nClients has 3450f7df2e56Smrg * been incremented on its behalf, so we need to decrement it 3451f7df2e56Smrg * now. If it hasn't gotten to Running, nClients has *not* 3452f7df2e56Smrg * been incremented, so *don't* decrement it. 3453f7df2e56Smrg */ 3454f7df2e56Smrg if (client->clientState != ClientStateInitial) { 3455f7df2e56Smrg --nClients; 3456f7df2e56Smrg } 3457f7df2e56Smrg } 3458f7df2e56Smrg 3459f7df2e56Smrg if (really_close_down) { 3460f7df2e56Smrg if (client->clientState == ClientStateRunning && nClients == 0) 3461f7df2e56Smrg dispatchException |= dispatchExceptionAtReset; 3462f7df2e56Smrg 3463f7df2e56Smrg client->clientState = ClientStateGone; 3464f7df2e56Smrg if (ClientStateCallback) { 3465f7df2e56Smrg NewClientInfoRec clientinfo; 3466f7df2e56Smrg 3467f7df2e56Smrg clientinfo.client = client; 3468f7df2e56Smrg clientinfo.prefix = (xConnSetupPrefix *) NULL; 3469f7df2e56Smrg clientinfo.setup = (xConnSetup *) NULL; 3470f7df2e56Smrg CallCallbacks((&ClientStateCallback), (void *) &clientinfo); 3471f7df2e56Smrg } 3472f7df2e56Smrg TouchListenerGone(client->clientAsMask); 3473f7df2e56Smrg FreeClientResources(client); 3474f7df2e56Smrg /* Disable client ID tracking. This must be done after 3475f7df2e56Smrg * ClientStateCallback. */ 3476f7df2e56Smrg ReleaseClientIds(client); 347705b261ecSmrg#ifdef XSERVER_DTRACE 3478f7df2e56Smrg XSERVER_CLIENT_DISCONNECT(client->index); 3479f7df2e56Smrg#endif 3480f7df2e56Smrg if (client->index < nextFreeClientID) 3481f7df2e56Smrg nextFreeClientID = client->index; 3482f7df2e56Smrg clients[client->index] = NullClient; 3483f7df2e56Smrg SmartLastClient = NullClient; 3484f7df2e56Smrg dixFreeObjectWithPrivates(client, PRIVATE_CLIENT); 348505b261ecSmrg 3486f7df2e56Smrg while (!clients[currentMaxClients - 1]) 3487f7df2e56Smrg currentMaxClients--; 348805b261ecSmrg } 348905b261ecSmrg} 349005b261ecSmrg 349105b261ecSmrgstatic void 349205b261ecSmrgKillAllClients(void) 349305b261ecSmrg{ 349405b261ecSmrg int i; 3495f7df2e56Smrg 3496f7df2e56Smrg for (i = 1; i < currentMaxClients; i++) 349705b261ecSmrg if (clients[i]) { 349805b261ecSmrg /* Make sure Retained clients are released. */ 349905b261ecSmrg clients[i]->closeDownMode = DestroyAll; 3500f7df2e56Smrg CloseDownClient(clients[i]); 350105b261ecSmrg } 350205b261ecSmrg} 350305b261ecSmrg 3504f7df2e56Smrgvoid 3505f7df2e56SmrgInitClient(ClientPtr client, int i, void *ospriv) 350605b261ecSmrg{ 350705b261ecSmrg client->index = i; 35087e31ba66Smrg xorg_list_init(&client->ready); 35097e31ba66Smrg xorg_list_init(&client->output_pending); 3510f7df2e56Smrg client->clientAsMask = ((Mask) i) << CLIENTOFFSET; 35114642e01fSmrg client->closeDownMode = i ? DestroyAll : RetainPermanent; 351205b261ecSmrg client->requestVector = InitialVector; 351305b261ecSmrg client->osPrivate = ospriv; 3514f7df2e56Smrg QueryMinMaxKeyCodes(&client->minKC, &client->maxKC); 351505b261ecSmrg client->smart_start_tick = SmartScheduleTime; 351605b261ecSmrg client->smart_stop_tick = SmartScheduleTime; 3517f7df2e56Smrg client->clientIds = NULL; 351805b261ecSmrg} 351905b261ecSmrg 352005b261ecSmrg/************************ 352105b261ecSmrg * int NextAvailableClient(ospriv) 352205b261ecSmrg * 352305b261ecSmrg * OS dependent portion can't assign client id's because of CloseDownModes. 352405b261ecSmrg * Returns NULL if there are no free clients. 352505b261ecSmrg *************************/ 352605b261ecSmrg 3527f7df2e56SmrgClientPtr 3528f7df2e56SmrgNextAvailableClient(void *ospriv) 352905b261ecSmrg{ 353005b261ecSmrg int i; 353105b261ecSmrg ClientPtr client; 353205b261ecSmrg xReq data; 353305b261ecSmrg 353405b261ecSmrg i = nextFreeClientID; 3535f7df2e56Smrg if (i == LimitClients) 3536f7df2e56Smrg return (ClientPtr) NULL; 3537f7df2e56Smrg clients[i] = client = 3538f7df2e56Smrg dixAllocateObjectWithPrivates(ClientRec, PRIVATE_CLIENT); 353905b261ecSmrg if (!client) 3540f7df2e56Smrg return (ClientPtr) NULL; 354105b261ecSmrg InitClient(client, i, ospriv); 3542f7df2e56Smrg if (!InitClientResources(client)) { 3543f7df2e56Smrg dixFreeObjectWithPrivates(client, PRIVATE_CLIENT); 3544f7df2e56Smrg return (ClientPtr) NULL; 354505b261ecSmrg } 354605b261ecSmrg data.reqType = 1; 35476747b715Smrg data.length = bytes_to_int32(sz_xReq + sz_xConnClientPrefix); 3548f7df2e56Smrg if (!InsertFakeRequest(client, (char *) &data, sz_xReq)) { 3549f7df2e56Smrg FreeClientResources(client); 3550f7df2e56Smrg dixFreeObjectWithPrivates(client, PRIVATE_CLIENT); 3551f7df2e56Smrg return (ClientPtr) NULL; 355205b261ecSmrg } 355305b261ecSmrg if (i == currentMaxClients) 3554f7df2e56Smrg currentMaxClients++; 3555f7df2e56Smrg while ((nextFreeClientID < LimitClients) && clients[nextFreeClientID]) 3556f7df2e56Smrg nextFreeClientID++; 3557f7df2e56Smrg 3558f7df2e56Smrg /* Enable client ID tracking. This must be done before 3559f7df2e56Smrg * ClientStateCallback. */ 3560f7df2e56Smrg ReserveClientIds(client); 3561f7df2e56Smrg 3562f7df2e56Smrg if (ClientStateCallback) { 3563f7df2e56Smrg NewClientInfoRec clientinfo; 356405b261ecSmrg 3565f7df2e56Smrg clientinfo.client = client; 3566f7df2e56Smrg clientinfo.prefix = (xConnSetupPrefix *) NULL; 356705b261ecSmrg clientinfo.setup = (xConnSetup *) NULL; 3568f7df2e56Smrg CallCallbacks((&ClientStateCallback), (void *) &clientinfo); 3569f7df2e56Smrg } 35706747b715Smrg return client; 357105b261ecSmrg} 357205b261ecSmrg 357305b261ecSmrgint 357405b261ecSmrgProcInitialConnection(ClientPtr client) 357505b261ecSmrg{ 357605b261ecSmrg REQUEST(xReq); 357705b261ecSmrg xConnClientPrefix *prefix; 357805b261ecSmrg int whichbyte = 1; 3579f7df2e56Smrg char order; 358005b261ecSmrg 3581f7df2e56Smrg prefix = (xConnClientPrefix *) ((char *)stuff + sz_xReq); 3582f7df2e56Smrg order = prefix->byteOrder; 3583f7df2e56Smrg if (order != 'l' && order != 'B' && order != 'r' && order != 'R') 35846747b715Smrg return client->noClientException = -1; 3585f7df2e56Smrg if (((*(char *) &whichbyte) && (order == 'B' || order == 'R')) || 3586f7df2e56Smrg (!(*(char *) &whichbyte) && (order == 'l' || order == 'r'))) { 358705b261ecSmrg client->swapped = TRUE; 358805b261ecSmrg SwapConnClientPrefix(prefix); 358905b261ecSmrg } 359005b261ecSmrg stuff->reqType = 2; 35916747b715Smrg stuff->length += bytes_to_int32(prefix->nbytesAuthProto) + 3592f7df2e56Smrg bytes_to_int32(prefix->nbytesAuthString); 3593f7df2e56Smrg if (client->swapped) { 3594f7df2e56Smrg swaps(&stuff->length); 3595f7df2e56Smrg } 3596f7df2e56Smrg if (order == 'r' || order == 'R') { 3597f7df2e56Smrg client->local = FALSE; 359805b261ecSmrg } 359905b261ecSmrg ResetCurrentRequest(client); 36006747b715Smrg return Success; 360105b261ecSmrg} 360205b261ecSmrg 36034642e01fSmrgstatic int 3604f7df2e56SmrgSendConnSetup(ClientPtr client, const char *reason) 360505b261ecSmrg{ 360605b261ecSmrg xWindowRoot *root; 360705b261ecSmrg int i; 360805b261ecSmrg int numScreens; 3609f7df2e56Smrg char *lConnectionInfo; 3610f7df2e56Smrg xConnSetupPrefix *lconnSetupPrefix; 361105b261ecSmrg 3612f7df2e56Smrg if (reason) { 3613f7df2e56Smrg xConnSetupPrefix csp; 3614f7df2e56Smrg 3615f7df2e56Smrg csp.success = xFalse; 3616f7df2e56Smrg csp.lengthReason = strlen(reason); 3617f7df2e56Smrg csp.length = bytes_to_int32(csp.lengthReason); 3618f7df2e56Smrg csp.majorVersion = X_PROTOCOL; 3619f7df2e56Smrg csp.minorVersion = X_PROTOCOL_REVISION; 3620f7df2e56Smrg if (client->swapped) 3621f7df2e56Smrg WriteSConnSetupPrefix(client, &csp); 3622f7df2e56Smrg else 3623f7df2e56Smrg WriteToClient(client, sz_xConnSetupPrefix, &csp); 3624f7df2e56Smrg WriteToClient(client, (int) csp.lengthReason, reason); 3625f7df2e56Smrg return client->noClientException = -1; 362605b261ecSmrg } 362705b261ecSmrg 362805b261ecSmrg numScreens = screenInfo.numScreens; 362905b261ecSmrg lConnectionInfo = ConnectionInfo; 363005b261ecSmrg lconnSetupPrefix = &connSetupPrefix; 363105b261ecSmrg 363205b261ecSmrg /* We're about to start speaking X protocol back to the client by 363305b261ecSmrg * sending the connection setup info. This means the authorization 363405b261ecSmrg * step is complete, and we can count the client as an 363505b261ecSmrg * authorized one. 363605b261ecSmrg */ 363705b261ecSmrg nClients++; 363805b261ecSmrg 363905b261ecSmrg client->requestVector = client->swapped ? SwappedProcVector : ProcVector; 364005b261ecSmrg client->sequence = 0; 3641f7df2e56Smrg ((xConnSetup *) lConnectionInfo)->ridBase = client->clientAsMask; 3642f7df2e56Smrg ((xConnSetup *) lConnectionInfo)->ridMask = RESOURCE_ID_MASK; 364305b261ecSmrg#ifdef MATCH_CLIENT_ENDIAN 3644f7df2e56Smrg ((xConnSetup *) lConnectionInfo)->imageByteOrder = ClientOrder(client); 3645f7df2e56Smrg ((xConnSetup *) lConnectionInfo)->bitmapBitOrder = ClientOrder(client); 364605b261ecSmrg#endif 364705b261ecSmrg /* fill in the "currentInputMask" */ 3648f7df2e56Smrg root = (xWindowRoot *) (lConnectionInfo + connBlockScreenStart); 364905b261ecSmrg#ifdef PANORAMIX 365005b261ecSmrg if (noPanoramiXExtension) 3651f7df2e56Smrg numScreens = screenInfo.numScreens; 3652f7df2e56Smrg else 3653f7df2e56Smrg numScreens = ((xConnSetup *) ConnectionInfo)->numRoots; 365405b261ecSmrg#endif 365505b261ecSmrg 3656f7df2e56Smrg for (i = 0; i < numScreens; i++) { 3657f7df2e56Smrg unsigned int j; 3658f7df2e56Smrg xDepth *pDepth; 3659f7df2e56Smrg WindowPtr pRoot = screenInfo.screens[i]->root; 366005b261ecSmrg 36616747b715Smrg root->currentInputMask = pRoot->eventMask | wOtherEventMasks(pRoot); 3662f7df2e56Smrg pDepth = (xDepth *) (root + 1); 3663f7df2e56Smrg for (j = 0; j < root->nDepths; j++) { 3664f7df2e56Smrg pDepth = (xDepth *) (((char *) (pDepth + 1)) + 3665f7df2e56Smrg pDepth->nVisuals * sizeof(xVisualType)); 3666f7df2e56Smrg } 3667f7df2e56Smrg root = (xWindowRoot *) pDepth; 366805b261ecSmrg } 366905b261ecSmrg 3670f7df2e56Smrg if (client->swapped) { 3671f7df2e56Smrg WriteSConnSetupPrefix(client, lconnSetupPrefix); 3672f7df2e56Smrg WriteSConnectionInfo(client, 3673f7df2e56Smrg (unsigned long) (lconnSetupPrefix->length << 2), 3674f7df2e56Smrg lConnectionInfo); 367505b261ecSmrg } 3676f7df2e56Smrg else { 3677f7df2e56Smrg WriteToClient(client, sizeof(xConnSetupPrefix), lconnSetupPrefix); 3678f7df2e56Smrg WriteToClient(client, (int) (lconnSetupPrefix->length << 2), 3679f7df2e56Smrg lConnectionInfo); 368005b261ecSmrg } 368105b261ecSmrg client->clientState = ClientStateRunning; 3682f7df2e56Smrg if (ClientStateCallback) { 3683f7df2e56Smrg NewClientInfoRec clientinfo; 368405b261ecSmrg 3685f7df2e56Smrg clientinfo.client = client; 3686f7df2e56Smrg clientinfo.prefix = lconnSetupPrefix; 3687f7df2e56Smrg clientinfo.setup = (xConnSetup *) lConnectionInfo; 3688f7df2e56Smrg CallCallbacks((&ClientStateCallback), (void *) &clientinfo); 3689f7df2e56Smrg } 36906747b715Smrg return Success; 369105b261ecSmrg} 369205b261ecSmrg 369305b261ecSmrgint 369405b261ecSmrgProcEstablishConnection(ClientPtr client) 369505b261ecSmrg{ 3696f7df2e56Smrg const char *reason; 3697f7df2e56Smrg char *auth_proto, *auth_string; 369805b261ecSmrg xConnClientPrefix *prefix; 3699f7df2e56Smrg 370005b261ecSmrg REQUEST(xReq); 370105b261ecSmrg 3702f7df2e56Smrg prefix = (xConnClientPrefix *) ((char *) stuff + sz_xReq); 3703f7df2e56Smrg auth_proto = (char *) prefix + sz_xConnClientPrefix; 37046747b715Smrg auth_string = auth_proto + pad_to_int32(prefix->nbytesAuthProto); 37056e78d31fSmrg 37066e78d31fSmrg if ((client->req_len << 2) != sz_xReq + sz_xConnClientPrefix + 37076e78d31fSmrg pad_to_int32(prefix->nbytesAuthProto) + 37086e78d31fSmrg pad_to_int32(prefix->nbytesAuthString)) 37096e78d31fSmrg reason = "Bad length"; 37106e78d31fSmrg else if ((prefix->majorVersion != X_PROTOCOL) || 3711f7df2e56Smrg (prefix->minorVersion != X_PROTOCOL_REVISION)) 3712f7df2e56Smrg reason = "Protocol version mismatch"; 371305b261ecSmrg else 3714f7df2e56Smrg reason = ClientAuthorized(client, 3715f7df2e56Smrg (unsigned short) prefix->nbytesAuthProto, 3716f7df2e56Smrg auth_proto, 3717f7df2e56Smrg (unsigned short) prefix->nbytesAuthString, 3718f7df2e56Smrg auth_string); 3719f7df2e56Smrg 3720f7df2e56Smrg return (SendConnSetup(client, reason)); 372105b261ecSmrg} 372205b261ecSmrg 37236747b715Smrgvoid 3724f7df2e56SmrgSendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode, 372505b261ecSmrg XID resId, int errorCode) 372605b261ecSmrg{ 3727f7df2e56Smrg xError rep = { 3728f7df2e56Smrg .type = X_Error, 3729f7df2e56Smrg .errorCode = errorCode, 3730f7df2e56Smrg .resourceID = resId, 3731f7df2e56Smrg .minorCode = minorCode, 3732f7df2e56Smrg .majorCode = majorCode 3733f7df2e56Smrg }; 373405b261ecSmrg 3735f7df2e56Smrg WriteEventsToClient(client, 1, (xEvent *) &rep); 373605b261ecSmrg} 373705b261ecSmrg 373805b261ecSmrgvoid 373905b261ecSmrgMarkClientException(ClientPtr client) 374005b261ecSmrg{ 374105b261ecSmrg client->noClientException = -1; 374205b261ecSmrg} 37436747b715Smrg 37446747b715Smrg/* 37456747b715Smrg * This array encodes the answer to the question "what is the log base 2 37466747b715Smrg * of the number of pixels that fit in a scanline pad unit?" 37476747b715Smrg * Note that ~0 is an invalid entry (mostly for the benefit of the reader). 37486747b715Smrg */ 37496747b715Smrgstatic int answer[6][4] = { 3750f7df2e56Smrg /* pad pad pad pad */ 3751f7df2e56Smrg /* 8 16 32 64 */ 3752f7df2e56Smrg 3753f7df2e56Smrg {3, 4, 5, 6}, /* 1 bit per pixel */ 3754f7df2e56Smrg {1, 2, 3, 4}, /* 4 bits per pixel */ 3755f7df2e56Smrg {0, 1, 2, 3}, /* 8 bits per pixel */ 3756f7df2e56Smrg {~0, 0, 1, 2}, /* 16 bits per pixel */ 3757f7df2e56Smrg {~0, ~0, 0, 1}, /* 24 bits per pixel */ 3758f7df2e56Smrg {~0, ~0, 0, 1} /* 32 bits per pixel */ 37596747b715Smrg}; 37606747b715Smrg 37616747b715Smrg/* 37626747b715Smrg * This array gives the answer to the question "what is the first index for 37636747b715Smrg * the answer array above given the number of bits per pixel?" 37646747b715Smrg * Note that ~0 is an invalid entry (mostly for the benefit of the reader). 37656747b715Smrg */ 3766f7df2e56Smrgstatic int indexForBitsPerPixel[33] = { 3767f7df2e56Smrg ~0, 0, ~0, ~0, /* 1 bit per pixel */ 3768f7df2e56Smrg 1, ~0, ~0, ~0, /* 4 bits per pixel */ 3769f7df2e56Smrg 2, ~0, ~0, ~0, /* 8 bits per pixel */ 3770f7df2e56Smrg ~0, ~0, ~0, ~0, 3771f7df2e56Smrg 3, ~0, ~0, ~0, /* 16 bits per pixel */ 3772f7df2e56Smrg ~0, ~0, ~0, ~0, 3773f7df2e56Smrg 4, ~0, ~0, ~0, /* 24 bits per pixel */ 3774f7df2e56Smrg ~0, ~0, ~0, ~0, 3775f7df2e56Smrg 5 /* 32 bits per pixel */ 37766747b715Smrg}; 37776747b715Smrg 37786747b715Smrg/* 37796747b715Smrg * This array gives the bytesperPixel value for cases where the number 37806747b715Smrg * of bits per pixel is a multiple of 8 but not a power of 2. 37816747b715Smrg */ 3782f7df2e56Smrgstatic int answerBytesPerPixel[33] = { 3783f7df2e56Smrg ~0, 0, ~0, ~0, /* 1 bit per pixel */ 3784f7df2e56Smrg 0, ~0, ~0, ~0, /* 4 bits per pixel */ 3785f7df2e56Smrg 0, ~0, ~0, ~0, /* 8 bits per pixel */ 3786f7df2e56Smrg ~0, ~0, ~0, ~0, 3787f7df2e56Smrg 0, ~0, ~0, ~0, /* 16 bits per pixel */ 3788f7df2e56Smrg ~0, ~0, ~0, ~0, 3789f7df2e56Smrg 3, ~0, ~0, ~0, /* 24 bits per pixel */ 3790f7df2e56Smrg ~0, ~0, ~0, ~0, 3791f7df2e56Smrg 0 /* 32 bits per pixel */ 37926747b715Smrg}; 37936747b715Smrg 37946747b715Smrg/* 37956747b715Smrg * This array gives the answer to the question "what is the second index for 37966747b715Smrg * the answer array above given the number of bits per scanline pad unit?" 37976747b715Smrg * Note that ~0 is an invalid entry (mostly for the benefit of the reader). 37986747b715Smrg */ 3799f7df2e56Smrgstatic int indexForScanlinePad[65] = { 3800f7df2e56Smrg ~0, ~0, ~0, ~0, 3801f7df2e56Smrg ~0, ~0, ~0, ~0, 3802f7df2e56Smrg 0, ~0, ~0, ~0, /* 8 bits per scanline pad unit */ 3803f7df2e56Smrg ~0, ~0, ~0, ~0, 3804f7df2e56Smrg 1, ~0, ~0, ~0, /* 16 bits per scanline pad unit */ 3805f7df2e56Smrg ~0, ~0, ~0, ~0, 3806f7df2e56Smrg ~0, ~0, ~0, ~0, 3807f7df2e56Smrg ~0, ~0, ~0, ~0, 3808f7df2e56Smrg 2, ~0, ~0, ~0, /* 32 bits per scanline pad unit */ 3809f7df2e56Smrg ~0, ~0, ~0, ~0, 3810f7df2e56Smrg ~0, ~0, ~0, ~0, 3811f7df2e56Smrg ~0, ~0, ~0, ~0, 3812f7df2e56Smrg ~0, ~0, ~0, ~0, 3813f7df2e56Smrg ~0, ~0, ~0, ~0, 3814f7df2e56Smrg ~0, ~0, ~0, ~0, 3815f7df2e56Smrg ~0, ~0, ~0, ~0, 3816f7df2e56Smrg 3 /* 64 bits per scanline pad unit */ 38176747b715Smrg}; 38186747b715Smrg 38196747b715Smrg/* 38206747b715Smrg grow the array of screenRecs if necessary. 38216747b715Smrg call the device-supplied initialization procedure 38226747b715Smrgwith its screen number, a pointer to its ScreenRec, argc, and argv. 38236747b715Smrg return the number of successfully installed screens. 38246747b715Smrg 38256747b715Smrg*/ 38266747b715Smrg 3827f7df2e56Smrgstatic int init_screen(ScreenPtr pScreen, int i, Bool gpu) 38286747b715Smrg{ 38296747b715Smrg int scanlinepad, format, depth, bitsPerPixel, j, k; 38306747b715Smrg 3831f7df2e56Smrg dixInitScreenSpecificPrivates(pScreen); 38326747b715Smrg 38336747b715Smrg if (!dixAllocatePrivates(&pScreen->devPrivates, PRIVATE_SCREEN)) { 3834f7df2e56Smrg return -1; 38356747b715Smrg } 38366747b715Smrg pScreen->myNum = i; 3837f7df2e56Smrg if (gpu) { 3838f7df2e56Smrg pScreen->myNum += GPU_SCREEN_OFFSET; 3839f7df2e56Smrg pScreen->isGPU = TRUE; 3840f7df2e56Smrg } 3841f7df2e56Smrg pScreen->totalPixmapSize = 0; /* computed in CreateScratchPixmapForScreen */ 3842f7df2e56Smrg pScreen->ClipNotify = 0; /* for R4 ddx compatibility */ 38436747b715Smrg pScreen->CreateScreenResources = 0; 38446747b715Smrg 3845f7df2e56Smrg xorg_list_init(&pScreen->pixmap_dirty_list); 38467e31ba66Smrg xorg_list_init(&pScreen->slave_list); 3847f7df2e56Smrg 38486747b715Smrg /* 38496747b715Smrg * This loop gets run once for every Screen that gets added, 38506747b715Smrg * but thats ok. If the ddx layer initializes the formats 38516747b715Smrg * one at a time calling AddScreen() after each, then each 38526747b715Smrg * iteration will make it a little more accurate. Worst case 38536747b715Smrg * we do this loop N * numPixmapFormats where N is # of screens. 38546747b715Smrg * Anyway, this must be called after InitOutput and before the 38556747b715Smrg * screen init routine is called. 38566747b715Smrg */ 3857f7df2e56Smrg for (format = 0; format < screenInfo.numPixmapFormats; format++) { 3858f7df2e56Smrg depth = screenInfo.formats[format].depth; 3859f7df2e56Smrg bitsPerPixel = screenInfo.formats[format].bitsPerPixel; 3860f7df2e56Smrg scanlinepad = screenInfo.formats[format].scanlinePad; 3861f7df2e56Smrg j = indexForBitsPerPixel[bitsPerPixel]; 3862f7df2e56Smrg k = indexForScanlinePad[scanlinepad]; 3863f7df2e56Smrg PixmapWidthPaddingInfo[depth].padPixelsLog2 = answer[j][k]; 3864f7df2e56Smrg PixmapWidthPaddingInfo[depth].padRoundUp = 3865f7df2e56Smrg (scanlinepad / bitsPerPixel) - 1; 3866f7df2e56Smrg j = indexForBitsPerPixel[8]; /* bits per byte */ 3867f7df2e56Smrg PixmapWidthPaddingInfo[depth].padBytesLog2 = answer[j][k]; 3868f7df2e56Smrg PixmapWidthPaddingInfo[depth].bitsPerPixel = bitsPerPixel; 3869f7df2e56Smrg if (answerBytesPerPixel[bitsPerPixel]) { 3870f7df2e56Smrg PixmapWidthPaddingInfo[depth].notPower2 = 1; 3871f7df2e56Smrg PixmapWidthPaddingInfo[depth].bytesPerPixel = 3872f7df2e56Smrg answerBytesPerPixel[bitsPerPixel]; 3873f7df2e56Smrg } 3874f7df2e56Smrg else { 3875f7df2e56Smrg PixmapWidthPaddingInfo[depth].notPower2 = 0; 3876f7df2e56Smrg } 38776747b715Smrg } 3878f7df2e56Smrg return 0; 3879f7df2e56Smrg} 3880f7df2e56Smrg 3881f7df2e56Smrgint 3882f7df2e56SmrgAddScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ , 3883f7df2e56Smrg int /*argc */ , 3884f7df2e56Smrg char ** /*argv */ 3885f7df2e56Smrg ), int argc, char **argv) 3886f7df2e56Smrg{ 3887f7df2e56Smrg 3888f7df2e56Smrg int i; 3889f7df2e56Smrg ScreenPtr pScreen; 3890f7df2e56Smrg Bool ret; 3891f7df2e56Smrg 3892f7df2e56Smrg i = screenInfo.numScreens; 3893f7df2e56Smrg if (i == MAXSCREENS) 3894f7df2e56Smrg return -1; 3895f7df2e56Smrg 3896f7df2e56Smrg pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec)); 3897f7df2e56Smrg if (!pScreen) 3898f7df2e56Smrg return -1; 38996747b715Smrg 3900f7df2e56Smrg ret = init_screen(pScreen, i, FALSE); 3901f7df2e56Smrg if (ret != 0) { 3902f7df2e56Smrg free(pScreen); 3903f7df2e56Smrg return ret; 3904f7df2e56Smrg } 39056747b715Smrg /* This is where screen specific stuff gets initialized. Load the 39066747b715Smrg screen structure, call the hardware, whatever. 39076747b715Smrg This is also where the default colormap should be allocated and 39086747b715Smrg also pixel values for blackPixel, whitePixel, and the cursor 39096747b715Smrg Note that InitScreen is NOT allowed to modify argc, argv, or 39106747b715Smrg any of the strings pointed to by argv. They may be passed to 39116747b715Smrg multiple screens. 3912f7df2e56Smrg */ 39136747b715Smrg screenInfo.screens[i] = pScreen; 39146747b715Smrg screenInfo.numScreens++; 3915f7df2e56Smrg if (!(*pfnInit) (pScreen, argc, argv)) { 3916f7df2e56Smrg dixFreeScreenSpecificPrivates(pScreen); 3917f7df2e56Smrg dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN); 3918f7df2e56Smrg free(pScreen); 3919f7df2e56Smrg screenInfo.numScreens--; 3920f7df2e56Smrg return -1; 39216747b715Smrg } 39226747b715Smrg 3923f7df2e56Smrg update_desktop_dimensions(); 3924f7df2e56Smrg 3925f7df2e56Smrg dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen, PRIVATE_CURSOR, 3926f7df2e56Smrg 0); 39276747b715Smrg 39286747b715Smrg return i; 39296747b715Smrg} 3930f7df2e56Smrg 3931f7df2e56Smrgint 3932f7df2e56SmrgAddGPUScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ , 3933f7df2e56Smrg int /*argc */ , 3934f7df2e56Smrg char ** /*argv */ 3935f7df2e56Smrg ), 3936f7df2e56Smrg int argc, char **argv) 3937f7df2e56Smrg{ 3938f7df2e56Smrg int i; 3939f7df2e56Smrg ScreenPtr pScreen; 3940f7df2e56Smrg Bool ret; 3941f7df2e56Smrg 3942f7df2e56Smrg i = screenInfo.numGPUScreens; 3943f7df2e56Smrg if (i == MAXGPUSCREENS) 3944f7df2e56Smrg return -1; 3945f7df2e56Smrg 3946f7df2e56Smrg pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec)); 3947f7df2e56Smrg if (!pScreen) 3948f7df2e56Smrg return -1; 3949f7df2e56Smrg 3950f7df2e56Smrg ret = init_screen(pScreen, i, TRUE); 3951f7df2e56Smrg if (ret != 0) { 3952f7df2e56Smrg free(pScreen); 3953f7df2e56Smrg return ret; 3954f7df2e56Smrg } 3955f7df2e56Smrg 3956f7df2e56Smrg /* This is where screen specific stuff gets initialized. Load the 3957f7df2e56Smrg screen structure, call the hardware, whatever. 3958f7df2e56Smrg This is also where the default colormap should be allocated and 3959f7df2e56Smrg also pixel values for blackPixel, whitePixel, and the cursor 3960f7df2e56Smrg Note that InitScreen is NOT allowed to modify argc, argv, or 3961f7df2e56Smrg any of the strings pointed to by argv. They may be passed to 3962f7df2e56Smrg multiple screens. 3963f7df2e56Smrg */ 3964f7df2e56Smrg screenInfo.gpuscreens[i] = pScreen; 3965f7df2e56Smrg screenInfo.numGPUScreens++; 3966f7df2e56Smrg if (!(*pfnInit) (pScreen, argc, argv)) { 3967f7df2e56Smrg dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN); 3968f7df2e56Smrg free(pScreen); 3969f7df2e56Smrg screenInfo.numGPUScreens--; 3970f7df2e56Smrg return -1; 3971f7df2e56Smrg } 3972f7df2e56Smrg 3973f7df2e56Smrg update_desktop_dimensions(); 3974f7df2e56Smrg 39757e31ba66Smrg /* 39767e31ba66Smrg * We cannot register the Screen PRIVATE_CURSOR key if cursors are already 39777e31ba66Smrg * created, because dix/privates.c does not have relocation code for 39787e31ba66Smrg * PRIVATE_CURSOR. Once this is fixed the if() can be removed and we can 39797e31ba66Smrg * register the Screen PRIVATE_CURSOR key unconditionally. 39807e31ba66Smrg */ 39817e31ba66Smrg if (!dixPrivatesCreated(PRIVATE_CURSOR)) 39827e31ba66Smrg dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen, 39837e31ba66Smrg PRIVATE_CURSOR, 0); 39847e31ba66Smrg 3985f7df2e56Smrg return i; 3986f7df2e56Smrg} 3987f7df2e56Smrg 3988f7df2e56Smrgvoid 3989f7df2e56SmrgRemoveGPUScreen(ScreenPtr pScreen) 3990f7df2e56Smrg{ 3991f7df2e56Smrg int idx, j; 3992f7df2e56Smrg if (!pScreen->isGPU) 3993f7df2e56Smrg return; 3994f7df2e56Smrg 3995f7df2e56Smrg idx = pScreen->myNum - GPU_SCREEN_OFFSET; 3996f7df2e56Smrg for (j = idx; j < screenInfo.numGPUScreens - 1; j++) { 3997f7df2e56Smrg screenInfo.gpuscreens[j] = screenInfo.gpuscreens[j + 1]; 3998f7df2e56Smrg screenInfo.gpuscreens[j]->myNum = j + GPU_SCREEN_OFFSET; 3999f7df2e56Smrg } 4000f7df2e56Smrg screenInfo.numGPUScreens--; 4001f7df2e56Smrg 4002f7df2e56Smrg /* this gets freed later in the resource list, but without 4003f7df2e56Smrg * the screen existing it causes crashes - so remove it here */ 4004f7df2e56Smrg if (pScreen->defColormap) 4005f7df2e56Smrg FreeResource(pScreen->defColormap, RT_COLORMAP); 4006f7df2e56Smrg free(pScreen); 4007f7df2e56Smrg 4008f7df2e56Smrg} 4009f7df2e56Smrg 4010f7df2e56Smrgvoid 4011f7df2e56SmrgAttachUnboundGPU(ScreenPtr pScreen, ScreenPtr new) 4012f7df2e56Smrg{ 4013f7df2e56Smrg assert(new->isGPU); 4014f7df2e56Smrg assert(!new->current_master); 40157e31ba66Smrg xorg_list_add(&new->slave_head, &pScreen->slave_list); 4016f7df2e56Smrg new->current_master = pScreen; 4017f7df2e56Smrg} 4018f7df2e56Smrg 4019f7df2e56Smrgvoid 4020f7df2e56SmrgDetachUnboundGPU(ScreenPtr slave) 4021f7df2e56Smrg{ 4022f7df2e56Smrg assert(slave->isGPU); 40237e31ba66Smrg assert(!slave->is_output_slave); 40247e31ba66Smrg assert(!slave->is_offload_slave); 40257e31ba66Smrg xorg_list_del(&slave->slave_head); 4026f7df2e56Smrg slave->current_master = NULL; 4027f7df2e56Smrg} 4028f7df2e56Smrg 4029f7df2e56Smrgvoid 4030f7df2e56SmrgAttachOutputGPU(ScreenPtr pScreen, ScreenPtr new) 4031f7df2e56Smrg{ 4032f7df2e56Smrg assert(new->isGPU); 40337e31ba66Smrg assert(!new->is_output_slave); 40347e31ba66Smrg assert(new->current_master == pScreen); 40357e31ba66Smrg new->is_output_slave = TRUE; 40367e31ba66Smrg new->current_master->output_slaves++; 4037f7df2e56Smrg} 4038f7df2e56Smrg 4039f7df2e56Smrgvoid 4040f7df2e56SmrgDetachOutputGPU(ScreenPtr slave) 4041f7df2e56Smrg{ 4042f7df2e56Smrg assert(slave->isGPU); 40437e31ba66Smrg assert(slave->is_output_slave); 40447e31ba66Smrg slave->current_master->output_slaves--; 40457e31ba66Smrg slave->is_output_slave = FALSE; 4046f7df2e56Smrg} 4047f7df2e56Smrg 4048f7df2e56Smrgvoid 4049f7df2e56SmrgAttachOffloadGPU(ScreenPtr pScreen, ScreenPtr new) 4050f7df2e56Smrg{ 4051f7df2e56Smrg assert(new->isGPU); 40527e31ba66Smrg assert(!new->is_offload_slave); 40537e31ba66Smrg assert(new->current_master == pScreen); 40547e31ba66Smrg new->is_offload_slave = TRUE; 4055f7df2e56Smrg} 4056f7df2e56Smrg 4057f7df2e56Smrgvoid 4058f7df2e56SmrgDetachOffloadGPU(ScreenPtr slave) 4059f7df2e56Smrg{ 4060f7df2e56Smrg assert(slave->isGPU); 40617e31ba66Smrg assert(slave->is_offload_slave); 40627e31ba66Smrg slave->is_offload_slave = FALSE; 4063f7df2e56Smrg} 4064f7df2e56Smrg 4065