1706f2543Smrg/**************************************************************************
2706f2543Smrg
3706f2543SmrgCopyright (c) 2002-2007 Apple Inc. All Rights Reserved.
4706f2543SmrgCopyright (c) 2003 Torrey T. Lyons. All Rights Reserved.
5706f2543Smrg
6706f2543SmrgPermission is hereby granted, free of charge, to any person obtaining a
7706f2543Smrgcopy of this software and associated documentation files (the
8706f2543Smrg"Software"), to deal in the Software without restriction, including
9706f2543Smrgwithout limitation the rights to use, copy, modify, merge, publish,
10706f2543Smrgdistribute, sub license, and/or sell copies of the Software, and to
11706f2543Smrgpermit persons to whom the Software is furnished to do so, subject to
12706f2543Smrgthe following conditions:
13706f2543Smrg
14706f2543SmrgThe above copyright notice and this permission notice (including the
15706f2543Smrgnext paragraph) shall be included in all copies or substantial portions
16706f2543Smrgof the Software.
17706f2543Smrg
18706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19706f2543SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20706f2543SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21706f2543SmrgIN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
22706f2543SmrgANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23706f2543SmrgTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24706f2543SmrgSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25706f2543Smrg
26706f2543Smrg**************************************************************************/
27706f2543Smrg
28706f2543Smrg#include "sanitizedCarbon.h"
29706f2543Smrg
30706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
31706f2543Smrg#include <dix-config.h>
32706f2543Smrg#endif
33706f2543Smrg
34706f2543Smrg#include "quartzCommon.h"
35706f2543Smrg
36706f2543Smrg#include "misc.h"
37706f2543Smrg#include "dixstruct.h"
38706f2543Smrg#include "globals.h"
39706f2543Smrg#include "extnsionst.h"
40706f2543Smrg#include "colormapst.h"
41706f2543Smrg#include "cursorstr.h"
42706f2543Smrg#include "scrnintstr.h"
43706f2543Smrg#include "windowstr.h"
44706f2543Smrg#include "servermd.h"
45706f2543Smrg#include "swaprep.h"
46706f2543Smrg#include "propertyst.h"
47706f2543Smrg#include <X11/Xatom.h>
48706f2543Smrg#include "darwin.h"
49706f2543Smrg#define _APPLEWM_SERVER_
50706f2543Smrg#include <X11/extensions/applewmproto.h>
51706f2543Smrg#include "applewmExt.h"
52706f2543Smrg#include "X11Application.h"
53706f2543Smrg#include "protocol-versions.h"
54706f2543Smrg
55706f2543Smrg#define DEFINE_ATOM_HELPER(func,atom_name)                      \
56706f2543Smrgstatic Atom func (void) {                                       \
57706f2543Smrg    static int generation;                                      \
58706f2543Smrg    static Atom atom;                                           \
59706f2543Smrg    if (generation != serverGeneration) {                       \
60706f2543Smrg        generation = serverGeneration;                          \
61706f2543Smrg        atom = MakeAtom (atom_name, strlen (atom_name), TRUE);  \
62706f2543Smrg    }                                                           \
63706f2543Smrg    return atom;                                                \
64706f2543Smrg}
65706f2543Smrg
66706f2543SmrgDEFINE_ATOM_HELPER(xa_native_screen_origin, "_NATIVE_SCREEN_ORIGIN")
67706f2543SmrgDEFINE_ATOM_HELPER (xa_apple_no_order_in, "_APPLE_NO_ORDER_IN")
68706f2543Smrg
69706f2543Smrgstatic AppleWMProcsPtr appleWMProcs;
70706f2543Smrg
71706f2543Smrgstatic int WMErrorBase;
72706f2543Smrg
73706f2543Smrg
74706f2543Smrgstatic unsigned char WMReqCode = 0;
75706f2543Smrgstatic int WMEventBase = 0;
76706f2543Smrg
77706f2543Smrgstatic RESTYPE ClientType, EventType; /* resource types for event masks */
78706f2543Smrgstatic XID eventResource;
79706f2543Smrg
80706f2543Smrg/* Currently selected events */
81706f2543Smrgstatic unsigned int eventMask = 0;
82706f2543Smrg
83706f2543Smrgstatic int WMFreeClient (pointer data, XID id);
84706f2543Smrgstatic int WMFreeEvents (pointer data, XID id);
85706f2543Smrgstatic void SNotifyEvent(xAppleWMNotifyEvent *from, xAppleWMNotifyEvent *to);
86706f2543Smrg
87706f2543Smrgtypedef struct _WMEvent *WMEventPtr;
88706f2543Smrgtypedef struct _WMEvent {
89706f2543Smrg    WMEventPtr      next;
90706f2543Smrg    ClientPtr       client;
91706f2543Smrg    XID             clientResource;
92706f2543Smrg    unsigned int    mask;
93706f2543Smrg} WMEventRec;
94706f2543Smrg
95706f2543Smrgstatic inline BoxRec
96706f2543Smrgmake_box (int x, int y, int w, int h)
97706f2543Smrg{
98706f2543Smrg    BoxRec r;
99706f2543Smrg    r.x1 = x;
100706f2543Smrg    r.y1 = y;
101706f2543Smrg    r.x2 = x + w;
102706f2543Smrg    r.y2 = y + h;
103706f2543Smrg    return r;
104706f2543Smrg}
105706f2543Smrg
106706f2543Smrg/* Updates the _NATIVE_SCREEN_ORIGIN property on the given root window. */
107706f2543Smrgvoid
108706f2543SmrgAppleWMSetScreenOrigin(
109706f2543Smrg    WindowPtr pWin
110706f2543Smrg)
111706f2543Smrg{
112706f2543Smrg    int32_t data[2];
113706f2543Smrg
114706f2543Smrg    data[0] = pWin->drawable.pScreen->x + darwinMainScreenX;
115706f2543Smrg    data[1] = pWin->drawable.pScreen->y + darwinMainScreenY;
116706f2543Smrg
117706f2543Smrg    dixChangeWindowProperty(serverClient, pWin, xa_native_screen_origin(),
118706f2543Smrg			    XA_INTEGER, 32, PropModeReplace, 2, data, TRUE);
119706f2543Smrg}
120706f2543Smrg
121706f2543Smrg/* Window managers can set the _APPLE_NO_ORDER_IN property on windows
122706f2543Smrg   that are being genie-restored from the Dock. We want them to
123706f2543Smrg   be mapped but remain ordered-out until the animation
124706f2543Smrg   completes (when the Dock will order them in). */
125706f2543SmrgBool
126706f2543SmrgAppleWMDoReorderWindow(
127706f2543Smrg    WindowPtr pWin
128706f2543Smrg)
129706f2543Smrg{
130706f2543Smrg    Atom atom;
131706f2543Smrg    PropertyPtr prop;
132706f2543Smrg    int rc;
133706f2543Smrg
134706f2543Smrg    atom = xa_apple_no_order_in();
135706f2543Smrg    rc = dixLookupProperty(&prop, pWin, atom, serverClient, DixReadAccess);
136706f2543Smrg
137706f2543Smrg    if(Success == rc && prop->type == atom)
138706f2543Smrg	return 0;
139706f2543Smrg
140706f2543Smrg    return 1;
141706f2543Smrg}
142706f2543Smrg
143706f2543Smrg
144706f2543Smrgstatic int
145706f2543SmrgProcAppleWMQueryVersion(
146706f2543Smrg    register ClientPtr client
147706f2543Smrg)
148706f2543Smrg{
149706f2543Smrg    xAppleWMQueryVersionReply rep;
150706f2543Smrg    register int n;
151706f2543Smrg
152706f2543Smrg    REQUEST_SIZE_MATCH(xAppleWMQueryVersionReq);
153706f2543Smrg    rep.type = X_Reply;
154706f2543Smrg    rep.length = 0;
155706f2543Smrg    rep.sequenceNumber = client->sequence;
156706f2543Smrg    rep.majorVersion = SERVER_APPLEWM_MAJOR_VERSION;
157706f2543Smrg    rep.minorVersion = SERVER_APPLEWM_MINOR_VERSION;
158706f2543Smrg    rep.patchVersion = SERVER_APPLEWM_PATCH_VERSION;
159706f2543Smrg    if (client->swapped) {
160706f2543Smrg        swaps(&rep.sequenceNumber, n);
161706f2543Smrg        swapl(&rep.length, n);
162706f2543Smrg    }
163706f2543Smrg    WriteToClient(client, sizeof(xAppleWMQueryVersionReply), (char *)&rep);
164706f2543Smrg    return Success;
165706f2543Smrg}
166706f2543Smrg
167706f2543Smrg
168706f2543Smrg/* events */
169706f2543Smrg
170706f2543Smrgstatic inline void
171706f2543SmrgupdateEventMask (WMEventPtr *pHead)
172706f2543Smrg{
173706f2543Smrg    WMEventPtr pCur;
174706f2543Smrg
175706f2543Smrg    eventMask = 0;
176706f2543Smrg    for (pCur = *pHead; pCur != NULL; pCur = pCur->next)
177706f2543Smrg        eventMask |= pCur->mask;
178706f2543Smrg}
179706f2543Smrg
180706f2543Smrg/*ARGSUSED*/
181706f2543Smrgstatic int
182706f2543SmrgWMFreeClient (pointer data, XID id) {
183706f2543Smrg    WMEventPtr   pEvent;
184706f2543Smrg    WMEventPtr   *pHead, pCur, pPrev;
185706f2543Smrg    int i;
186706f2543Smrg
187706f2543Smrg    pEvent = (WMEventPtr) data;
188706f2543Smrg    i = dixLookupResourceByType((pointer *)&pHead, eventResource, EventType, serverClient, DixReadAccess | DixWriteAccess | DixDestroyAccess);
189706f2543Smrg    if (i == Success && pHead) {
190706f2543Smrg        pPrev = 0;
191706f2543Smrg        for (pCur = *pHead; pCur && pCur != pEvent; pCur=pCur->next)
192706f2543Smrg            pPrev = pCur;
193706f2543Smrg        if (pCur) {
194706f2543Smrg            if (pPrev)
195706f2543Smrg                pPrev->next = pEvent->next;
196706f2543Smrg            else
197706f2543Smrg                *pHead = pEvent->next;
198706f2543Smrg        }
199706f2543Smrg        updateEventMask (pHead);
200706f2543Smrg    }
201706f2543Smrg    free((pointer) pEvent);
202706f2543Smrg    return 1;
203706f2543Smrg}
204706f2543Smrg
205706f2543Smrg/*ARGSUSED*/
206706f2543Smrgstatic int
207706f2543SmrgWMFreeEvents (pointer data, XID id) {
208706f2543Smrg    WMEventPtr   *pHead, pCur, pNext;
209706f2543Smrg
210706f2543Smrg    pHead = (WMEventPtr *) data;
211706f2543Smrg    for (pCur = *pHead; pCur; pCur = pNext) {
212706f2543Smrg        pNext = pCur->next;
213706f2543Smrg        FreeResource (pCur->clientResource, ClientType);
214706f2543Smrg        free((pointer) pCur);
215706f2543Smrg    }
216706f2543Smrg    free((pointer) pHead);
217706f2543Smrg    eventMask = 0;
218706f2543Smrg    return 1;
219706f2543Smrg}
220706f2543Smrg
221706f2543Smrgstatic int
222706f2543SmrgProcAppleWMSelectInput (register ClientPtr client)
223706f2543Smrg{
224706f2543Smrg    REQUEST(xAppleWMSelectInputReq);
225706f2543Smrg    WMEventPtr      pEvent, pNewEvent, *pHead;
226706f2543Smrg    XID             clientResource;
227706f2543Smrg    int             i;
228706f2543Smrg
229706f2543Smrg    REQUEST_SIZE_MATCH (xAppleWMSelectInputReq);
230706f2543Smrg    i = dixLookupResourceByType((pointer *)&pHead, eventResource, EventType, client, DixWriteAccess);
231706f2543Smrg    if (stuff->mask != 0) {
232706f2543Smrg        if (i == Success && pHead) {
233706f2543Smrg            /* check for existing entry. */
234706f2543Smrg            for (pEvent = *pHead; pEvent; pEvent = pEvent->next)
235706f2543Smrg            {
236706f2543Smrg                if (pEvent->client == client)
237706f2543Smrg                {
238706f2543Smrg                    pEvent->mask = stuff->mask;
239706f2543Smrg                    updateEventMask (pHead);
240706f2543Smrg                    return Success;
241706f2543Smrg                }
242706f2543Smrg            }
243706f2543Smrg        }
244706f2543Smrg
245706f2543Smrg        /* build the entry */
246706f2543Smrg        pNewEvent = (WMEventPtr) malloc(sizeof (WMEventRec));
247706f2543Smrg        if (!pNewEvent)
248706f2543Smrg            return BadAlloc;
249706f2543Smrg        pNewEvent->next = 0;
250706f2543Smrg        pNewEvent->client = client;
251706f2543Smrg        pNewEvent->mask = stuff->mask;
252706f2543Smrg        /*
253706f2543Smrg         * add a resource that will be deleted when
254706f2543Smrg         * the client goes away
255706f2543Smrg         */
256706f2543Smrg        clientResource = FakeClientID (client->index);
257706f2543Smrg        pNewEvent->clientResource = clientResource;
258706f2543Smrg        if (!AddResource (clientResource, ClientType, (pointer)pNewEvent))
259706f2543Smrg            return BadAlloc;
260706f2543Smrg        /*
261706f2543Smrg         * create a resource to contain a pointer to the list
262706f2543Smrg         * of clients selecting input.  This must be indirect as
263706f2543Smrg         * the list may be arbitrarily rearranged which cannot be
264706f2543Smrg         * done through the resource database.
265706f2543Smrg         */
266706f2543Smrg        if (i != Success || !pHead)
267706f2543Smrg        {
268706f2543Smrg            pHead = (WMEventPtr *) malloc(sizeof (WMEventPtr));
269706f2543Smrg            if (!pHead ||
270706f2543Smrg                !AddResource (eventResource, EventType, (pointer)pHead))
271706f2543Smrg            {
272706f2543Smrg                FreeResource (clientResource, RT_NONE);
273706f2543Smrg                return BadAlloc;
274706f2543Smrg            }
275706f2543Smrg            *pHead = 0;
276706f2543Smrg        }
277706f2543Smrg        pNewEvent->next = *pHead;
278706f2543Smrg        *pHead = pNewEvent;
279706f2543Smrg        updateEventMask (pHead);
280706f2543Smrg    } else if (stuff->mask == 0) {
281706f2543Smrg        /* delete the interest */
282706f2543Smrg        if (i == Success && pHead) {
283706f2543Smrg            pNewEvent = 0;
284706f2543Smrg            for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
285706f2543Smrg                if (pEvent->client == client)
286706f2543Smrg                    break;
287706f2543Smrg                pNewEvent = pEvent;
288706f2543Smrg            }
289706f2543Smrg            if (pEvent) {
290706f2543Smrg                FreeResource (pEvent->clientResource, ClientType);
291706f2543Smrg                if (pNewEvent)
292706f2543Smrg                    pNewEvent->next = pEvent->next;
293706f2543Smrg                else
294706f2543Smrg                    *pHead = pEvent->next;
295706f2543Smrg                free(pEvent);
296706f2543Smrg                updateEventMask (pHead);
297706f2543Smrg            }
298706f2543Smrg        }
299706f2543Smrg    } else {
300706f2543Smrg        client->errorValue = stuff->mask;
301706f2543Smrg        return BadValue;
302706f2543Smrg    }
303706f2543Smrg    return Success;
304706f2543Smrg}
305706f2543Smrg
306706f2543Smrg/*
307706f2543Smrg * deliver the event
308706f2543Smrg */
309706f2543Smrg
310706f2543Smrgvoid
311706f2543SmrgAppleWMSendEvent (int type, unsigned int mask, int which, int arg) {
312706f2543Smrg    WMEventPtr      *pHead, pEvent;
313706f2543Smrg    xAppleWMNotifyEvent se;
314706f2543Smrg    int             i;
315706f2543Smrg
316706f2543Smrg    i = dixLookupResourceByType((pointer *)&pHead, eventResource, EventType, serverClient, DixReadAccess);
317706f2543Smrg    if (i != Success || !pHead)
318706f2543Smrg        return;
319706f2543Smrg    for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
320706f2543Smrg        if ((pEvent->mask & mask) == 0)
321706f2543Smrg            continue;
322706f2543Smrg        se.type = type + WMEventBase;
323706f2543Smrg        se.kind = which;
324706f2543Smrg        se.arg = arg;
325706f2543Smrg        se.time = currentTime.milliseconds;
326706f2543Smrg        WriteEventsToClient (pEvent->client, 1, (xEvent *) &se);
327706f2543Smrg    }
328706f2543Smrg}
329706f2543Smrg
330706f2543Smrg/* Safe to call from any thread. */
331706f2543Smrgunsigned int
332706f2543SmrgAppleWMSelectedEvents (void)
333706f2543Smrg{
334706f2543Smrg    return eventMask;
335706f2543Smrg}
336706f2543Smrg
337706f2543Smrg
338706f2543Smrg/* general utility functions */
339706f2543Smrg
340706f2543Smrgstatic int
341706f2543SmrgProcAppleWMDisableUpdate(
342706f2543Smrg    register ClientPtr client
343706f2543Smrg)
344706f2543Smrg{
345706f2543Smrg    REQUEST_SIZE_MATCH(xAppleWMDisableUpdateReq);
346706f2543Smrg
347706f2543Smrg    appleWMProcs->DisableUpdate();
348706f2543Smrg
349706f2543Smrg    return Success;
350706f2543Smrg}
351706f2543Smrg
352706f2543Smrgstatic int
353706f2543SmrgProcAppleWMReenableUpdate(
354706f2543Smrg    register ClientPtr client
355706f2543Smrg)
356706f2543Smrg{
357706f2543Smrg    REQUEST_SIZE_MATCH(xAppleWMReenableUpdateReq);
358706f2543Smrg
359706f2543Smrg    appleWMProcs->EnableUpdate();
360706f2543Smrg
361706f2543Smrg    return Success;
362706f2543Smrg}
363706f2543Smrg
364706f2543Smrg
365706f2543Smrg/* window functions */
366706f2543Smrg
367706f2543Smrgstatic int
368706f2543SmrgProcAppleWMSetWindowMenu(
369706f2543Smrg    register ClientPtr client
370706f2543Smrg)
371706f2543Smrg{
372706f2543Smrg    const char *bytes, **items;
373706f2543Smrg    char *shortcuts;
374706f2543Smrg    int max_len, nitems, i, j;
375706f2543Smrg    REQUEST(xAppleWMSetWindowMenuReq);
376706f2543Smrg
377706f2543Smrg    REQUEST_AT_LEAST_SIZE(xAppleWMSetWindowMenuReq);
378706f2543Smrg
379706f2543Smrg    nitems = stuff->nitems;
380706f2543Smrg    items = malloc(sizeof (char *) * nitems);
381706f2543Smrg    shortcuts = malloc(sizeof (char) * nitems);
382706f2543Smrg
383706f2543Smrg    max_len = (stuff->length << 2) - sizeof(xAppleWMSetWindowMenuReq);
384706f2543Smrg    bytes = (char *) &stuff[1];
385706f2543Smrg
386706f2543Smrg    for (i = j = 0; i < max_len && j < nitems;)
387706f2543Smrg    {
388706f2543Smrg        shortcuts[j] = bytes[i++];
389706f2543Smrg        items[j++] = bytes + i;
390706f2543Smrg
391706f2543Smrg        while (i < max_len)
392706f2543Smrg        {
393706f2543Smrg            if (bytes[i++] == 0)
394706f2543Smrg                break;
395706f2543Smrg        }
396706f2543Smrg    }
397706f2543Smrg    X11ApplicationSetWindowMenu (nitems, items, shortcuts);
398706f2543Smrg    free(items);
399706f2543Smrg    free(shortcuts);
400706f2543Smrg
401706f2543Smrg    return Success;
402706f2543Smrg}
403706f2543Smrg
404706f2543Smrgstatic int
405706f2543SmrgProcAppleWMSetWindowMenuCheck(
406706f2543Smrg    register ClientPtr client
407706f2543Smrg)
408706f2543Smrg{
409706f2543Smrg    REQUEST(xAppleWMSetWindowMenuCheckReq);
410706f2543Smrg
411706f2543Smrg    REQUEST_SIZE_MATCH(xAppleWMSetWindowMenuCheckReq);
412706f2543Smrg    X11ApplicationSetWindowMenuCheck(stuff->index);
413706f2543Smrg    return Success;
414706f2543Smrg}
415706f2543Smrg
416706f2543Smrgstatic int
417706f2543SmrgProcAppleWMSetFrontProcess(
418706f2543Smrg    register ClientPtr client
419706f2543Smrg)
420706f2543Smrg{
421706f2543Smrg    REQUEST_SIZE_MATCH(xAppleWMSetFrontProcessReq);
422706f2543Smrg
423706f2543Smrg    X11ApplicationSetFrontProcess();
424706f2543Smrg    return Success;
425706f2543Smrg}
426706f2543Smrg
427706f2543Smrgstatic int
428706f2543SmrgProcAppleWMSetWindowLevel(register ClientPtr client)
429706f2543Smrg{
430706f2543Smrg    REQUEST(xAppleWMSetWindowLevelReq);
431706f2543Smrg    WindowPtr pWin;
432706f2543Smrg    int err;
433706f2543Smrg
434706f2543Smrg    REQUEST_SIZE_MATCH(xAppleWMSetWindowLevelReq);
435706f2543Smrg
436706f2543Smrg    if (Success != dixLookupWindow(&pWin, stuff->window, client,
437706f2543Smrg				   DixReadAccess))
438706f2543Smrg        return BadValue;
439706f2543Smrg
440706f2543Smrg    if (stuff->level < 0 || stuff->level >= AppleWMNumWindowLevels) {
441706f2543Smrg        return BadValue;
442706f2543Smrg    }
443706f2543Smrg
444706f2543Smrg     err = appleWMProcs->SetWindowLevel(pWin, stuff->level);
445706f2543Smrg     if (err != Success) {
446706f2543Smrg        return err;
447706f2543Smrg    }
448706f2543Smrg
449706f2543Smrg    return Success;
450706f2543Smrg}
451706f2543Smrg
452706f2543Smrgstatic int
453706f2543SmrgProcAppleWMSendPSN(register ClientPtr client)
454706f2543Smrg{
455706f2543Smrg    REQUEST(xAppleWMSendPSNReq);
456706f2543Smrg    int err;
457706f2543Smrg
458706f2543Smrg    REQUEST_SIZE_MATCH(xAppleWMSendPSNReq);
459706f2543Smrg
460706f2543Smrg    if(!appleWMProcs->SendPSN)
461706f2543Smrg        return BadRequest;
462706f2543Smrg
463706f2543Smrg    err = appleWMProcs->SendPSN(stuff->psn_hi, stuff->psn_lo);
464706f2543Smrg    if (err != Success) {
465706f2543Smrg        return err;
466706f2543Smrg    }
467706f2543Smrg
468706f2543Smrg    return Success;
469706f2543Smrg}
470706f2543Smrg
471706f2543Smrgstatic int
472706f2543SmrgProcAppleWMAttachTransient(register ClientPtr client)
473706f2543Smrg{
474706f2543Smrg    WindowPtr pWinChild, pWinParent;
475706f2543Smrg    REQUEST(xAppleWMAttachTransientReq);
476706f2543Smrg    int err;
477706f2543Smrg
478706f2543Smrg    REQUEST_SIZE_MATCH(xAppleWMAttachTransientReq);
479706f2543Smrg
480706f2543Smrg    if(!appleWMProcs->AttachTransient)
481706f2543Smrg        return BadRequest;
482706f2543Smrg
483706f2543Smrg    if (Success != dixLookupWindow(&pWinChild, stuff->child, client, DixReadAccess))
484706f2543Smrg        return BadValue;
485706f2543Smrg
486706f2543Smrg    if(stuff->parent) {
487706f2543Smrg        if(Success != dixLookupWindow(&pWinParent, stuff->parent, client, DixReadAccess))
488706f2543Smrg            return BadValue;
489706f2543Smrg    } else {
490706f2543Smrg        pWinParent = NULL;
491706f2543Smrg    }
492706f2543Smrg
493706f2543Smrg    err = appleWMProcs->AttachTransient(pWinChild, pWinParent);
494706f2543Smrg    if (err != Success) {
495706f2543Smrg        return err;
496706f2543Smrg    }
497706f2543Smrg
498706f2543Smrg    return Success;
499706f2543Smrg}
500706f2543Smrg
501706f2543Smrgstatic int
502706f2543SmrgProcAppleWMSetCanQuit(
503706f2543Smrg    register ClientPtr client
504706f2543Smrg)
505706f2543Smrg{
506706f2543Smrg    REQUEST(xAppleWMSetCanQuitReq);
507706f2543Smrg
508706f2543Smrg    REQUEST_SIZE_MATCH(xAppleWMSetCanQuitReq);
509706f2543Smrg
510706f2543Smrg    X11ApplicationSetCanQuit(stuff->state);
511706f2543Smrg    return Success;
512706f2543Smrg}
513706f2543Smrg
514706f2543Smrg
515706f2543Smrg/* frame functions */
516706f2543Smrg
517706f2543Smrgstatic int
518706f2543SmrgProcAppleWMFrameGetRect(
519706f2543Smrg    register ClientPtr client
520706f2543Smrg)
521706f2543Smrg{
522706f2543Smrg    xAppleWMFrameGetRectReply rep;
523706f2543Smrg    BoxRec ir, or, rr;
524706f2543Smrg    REQUEST(xAppleWMFrameGetRectReq);
525706f2543Smrg
526706f2543Smrg    REQUEST_SIZE_MATCH(xAppleWMFrameGetRectReq);
527706f2543Smrg    rep.type = X_Reply;
528706f2543Smrg    rep.length = 0;
529706f2543Smrg    rep.sequenceNumber = client->sequence;
530706f2543Smrg
531706f2543Smrg    ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih);
532706f2543Smrg    or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh);
533706f2543Smrg
534706f2543Smrg    if (appleWMProcs->FrameGetRect(stuff->frame_rect,
535706f2543Smrg                                   stuff->frame_class,
536706f2543Smrg                                   &or, &ir, &rr) != Success)
537706f2543Smrg    {
538706f2543Smrg        return BadValue;
539706f2543Smrg    }
540706f2543Smrg
541706f2543Smrg    rep.x = rr.x1;
542706f2543Smrg    rep.y = rr.y1;
543706f2543Smrg    rep.w = rr.x2 - rr.x1;
544706f2543Smrg    rep.h = rr.y2 - rr.y1;
545706f2543Smrg
546706f2543Smrg    WriteToClient(client, sizeof(xAppleWMFrameGetRectReply), (char *)&rep);
547706f2543Smrg    return Success;
548706f2543Smrg}
549706f2543Smrg
550706f2543Smrgstatic int
551706f2543SmrgProcAppleWMFrameHitTest(
552706f2543Smrg    register ClientPtr client
553706f2543Smrg)
554706f2543Smrg{
555706f2543Smrg    xAppleWMFrameHitTestReply rep;
556706f2543Smrg    BoxRec ir, or;
557706f2543Smrg    int ret;
558706f2543Smrg    REQUEST(xAppleWMFrameHitTestReq);
559706f2543Smrg
560706f2543Smrg    REQUEST_SIZE_MATCH(xAppleWMFrameHitTestReq);
561706f2543Smrg    rep.type = X_Reply;
562706f2543Smrg    rep.length = 0;
563706f2543Smrg    rep.sequenceNumber = client->sequence;
564706f2543Smrg
565706f2543Smrg    ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih);
566706f2543Smrg    or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh);
567706f2543Smrg
568706f2543Smrg    if (appleWMProcs->FrameHitTest(stuff->frame_class, stuff->px,
569706f2543Smrg                                   stuff->py, &or, &ir, &ret) != Success)
570706f2543Smrg    {
571706f2543Smrg        return BadValue;
572706f2543Smrg    }
573706f2543Smrg
574706f2543Smrg    rep.ret = ret;
575706f2543Smrg
576706f2543Smrg    WriteToClient(client, sizeof(xAppleWMFrameHitTestReply), (char *)&rep);
577706f2543Smrg    return Success;
578706f2543Smrg}
579706f2543Smrg
580706f2543Smrgstatic int
581706f2543SmrgProcAppleWMFrameDraw(
582706f2543Smrg    register ClientPtr client
583706f2543Smrg)
584706f2543Smrg{
585706f2543Smrg    BoxRec ir, or;
586706f2543Smrg    unsigned int title_length, title_max;
587706f2543Smrg    unsigned char *title_bytes;
588706f2543Smrg    REQUEST(xAppleWMFrameDrawReq);
589706f2543Smrg    WindowPtr pWin;
590706f2543Smrg
591706f2543Smrg    REQUEST_AT_LEAST_SIZE(xAppleWMFrameDrawReq);
592706f2543Smrg
593706f2543Smrg    if (Success != dixLookupWindow(&pWin, stuff->window, client,
594706f2543Smrg				   DixReadAccess))
595706f2543Smrg        return BadValue;
596706f2543Smrg
597706f2543Smrg    ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih);
598706f2543Smrg    or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh);
599706f2543Smrg
600706f2543Smrg    title_length = stuff->title_length;
601706f2543Smrg    title_max = (stuff->length << 2) - sizeof(xAppleWMFrameDrawReq);
602706f2543Smrg
603706f2543Smrg    if (title_max < title_length)
604706f2543Smrg        return BadValue;
605706f2543Smrg
606706f2543Smrg    title_bytes = (unsigned char *) &stuff[1];
607706f2543Smrg
608706f2543Smrg    errno = appleWMProcs->FrameDraw(pWin, stuff->frame_class,
609706f2543Smrg                                    stuff->frame_attr, &or, &ir,
610706f2543Smrg                                    title_length, title_bytes);
611706f2543Smrg    if (errno != Success) {
612706f2543Smrg        return errno;
613706f2543Smrg    }
614706f2543Smrg
615706f2543Smrg    return Success;
616706f2543Smrg}
617706f2543Smrg
618706f2543Smrg
619706f2543Smrg/* dispatch */
620706f2543Smrg
621706f2543Smrgstatic int
622706f2543SmrgProcAppleWMDispatch (
623706f2543Smrg    register ClientPtr  client
624706f2543Smrg)
625706f2543Smrg{
626706f2543Smrg    REQUEST(xReq);
627706f2543Smrg
628706f2543Smrg    switch (stuff->data)
629706f2543Smrg    {
630706f2543Smrg    case X_AppleWMQueryVersion:
631706f2543Smrg        return ProcAppleWMQueryVersion(client);
632706f2543Smrg    }
633706f2543Smrg
634706f2543Smrg    if (!LocalClient(client))
635706f2543Smrg        return WMErrorBase + AppleWMClientNotLocal;
636706f2543Smrg
637706f2543Smrg    switch (stuff->data)
638706f2543Smrg    {
639706f2543Smrg    case X_AppleWMSelectInput:
640706f2543Smrg        return ProcAppleWMSelectInput(client);
641706f2543Smrg    case X_AppleWMDisableUpdate:
642706f2543Smrg        return ProcAppleWMDisableUpdate(client);
643706f2543Smrg    case X_AppleWMReenableUpdate:
644706f2543Smrg        return ProcAppleWMReenableUpdate(client);
645706f2543Smrg    case X_AppleWMSetWindowMenu:
646706f2543Smrg        return ProcAppleWMSetWindowMenu(client);
647706f2543Smrg    case X_AppleWMSetWindowMenuCheck:
648706f2543Smrg        return ProcAppleWMSetWindowMenuCheck(client);
649706f2543Smrg    case X_AppleWMSetFrontProcess:
650706f2543Smrg        return ProcAppleWMSetFrontProcess(client);
651706f2543Smrg    case X_AppleWMSetWindowLevel:
652706f2543Smrg        return ProcAppleWMSetWindowLevel(client);
653706f2543Smrg    case X_AppleWMSetCanQuit:
654706f2543Smrg        return ProcAppleWMSetCanQuit(client);
655706f2543Smrg    case X_AppleWMFrameGetRect:
656706f2543Smrg        return ProcAppleWMFrameGetRect(client);
657706f2543Smrg    case X_AppleWMFrameHitTest:
658706f2543Smrg        return ProcAppleWMFrameHitTest(client);
659706f2543Smrg    case X_AppleWMFrameDraw:
660706f2543Smrg        return ProcAppleWMFrameDraw(client);
661706f2543Smrg    case X_AppleWMSendPSN:
662706f2543Smrg        return ProcAppleWMSendPSN(client);
663706f2543Smrg    case X_AppleWMAttachTransient:
664706f2543Smrg        return ProcAppleWMAttachTransient(client);
665706f2543Smrg    default:
666706f2543Smrg        return BadRequest;
667706f2543Smrg    }
668706f2543Smrg}
669706f2543Smrg
670706f2543Smrgstatic void
671706f2543SmrgSNotifyEvent(xAppleWMNotifyEvent *from, xAppleWMNotifyEvent *to) {
672706f2543Smrg    to->type = from->type;
673706f2543Smrg    to->kind = from->kind;
674706f2543Smrg    cpswaps (from->sequenceNumber, to->sequenceNumber);
675706f2543Smrg    cpswapl (from->time, to->time);
676706f2543Smrg    cpswapl (from->arg, to->arg);
677706f2543Smrg}
678706f2543Smrg
679706f2543Smrgstatic int
680706f2543SmrgSProcAppleWMQueryVersion(
681706f2543Smrg    register ClientPtr  client
682706f2543Smrg)
683706f2543Smrg{
684706f2543Smrg    register int n;
685706f2543Smrg    REQUEST(xAppleWMQueryVersionReq);
686706f2543Smrg    swaps(&stuff->length, n);
687706f2543Smrg    return ProcAppleWMQueryVersion(client);
688706f2543Smrg}
689706f2543Smrg
690706f2543Smrgstatic int
691706f2543SmrgSProcAppleWMDispatch (
692706f2543Smrg    register ClientPtr  client
693706f2543Smrg)
694706f2543Smrg{
695706f2543Smrg    REQUEST(xReq);
696706f2543Smrg
697706f2543Smrg    /* It is bound to be non-local when there is byte swapping */
698706f2543Smrg    if (!LocalClient(client))
699706f2543Smrg        return WMErrorBase + AppleWMClientNotLocal;
700706f2543Smrg
701706f2543Smrg    /* only local clients are allowed WM access */
702706f2543Smrg    switch (stuff->data)
703706f2543Smrg    {
704706f2543Smrg    case X_AppleWMQueryVersion:
705706f2543Smrg        return SProcAppleWMQueryVersion(client);
706706f2543Smrg    default:
707706f2543Smrg        return BadRequest;
708706f2543Smrg    }
709706f2543Smrg}
710706f2543Smrg
711706f2543Smrgvoid
712706f2543SmrgAppleWMExtensionInit(
713706f2543Smrg    AppleWMProcsPtr procsPtr)
714706f2543Smrg{
715706f2543Smrg    ExtensionEntry* extEntry;
716706f2543Smrg
717706f2543Smrg    ClientType = CreateNewResourceType(WMFreeClient, "WMClient");
718706f2543Smrg    EventType = CreateNewResourceType(WMFreeEvents, "WMEvent");
719706f2543Smrg    eventResource = FakeClientID(0);
720706f2543Smrg
721706f2543Smrg    if (ClientType && EventType &&
722706f2543Smrg        (extEntry = AddExtension(APPLEWMNAME,
723706f2543Smrg                                 AppleWMNumberEvents,
724706f2543Smrg                                 AppleWMNumberErrors,
725706f2543Smrg                                 ProcAppleWMDispatch,
726706f2543Smrg                                 SProcAppleWMDispatch,
727706f2543Smrg                                 NULL,
728706f2543Smrg                                 StandardMinorOpcode)))
729706f2543Smrg    {
730706f2543Smrg        size_t i;
731706f2543Smrg        WMReqCode = (unsigned char)extEntry->base;
732706f2543Smrg        WMErrorBase = extEntry->errorBase;
733706f2543Smrg        WMEventBase = extEntry->eventBase;
734706f2543Smrg        for (i=0; i < AppleWMNumberEvents; i++)
735706f2543Smrg            EventSwapVector[WMEventBase + i] = (EventSwapPtr) SNotifyEvent;
736706f2543Smrg        appleWMProcs = procsPtr;
737706f2543Smrg    }
738706f2543Smrg}
739