1 /*
2  * Copyright (c) 2003 Torrey T. Lyons. All Rights Reserved.
3  * Copyright (c) 2002-2012 Apple Inc. All rights reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person
6  * obtaining a copy of this software and associated documentation files
7  * (the "Software"), to deal in the Software without restriction,
8  * including without limitation the rights to use, copy, modify, merge,
9  * publish, distribute, sublicense, and/or sell copies of the Software,
10  * and to permit persons to whom the Software is furnished to do so,
11  * subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT.  IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
20  * HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23  * DEALINGS IN THE SOFTWARE.
24  *
25  * Except as contained in this notice, the name(s) of the above
26  * copyright holders shall not be used in advertising or otherwise to
27  * promote the sale, use or other dealings in this Software without
28  * prior written authorization.
29  */
30 
31 #include "sanitizedCarbon.h"
32 
33 #ifdef HAVE_DIX_CONFIG_H
34 #include <dix-config.h>
35 #endif
36 
37 #include "quartz.h"
38 
39 #include "misc.h"
40 #include "dixstruct.h"
41 #include "globals.h"
42 #include "extnsionst.h"
43 #include "colormapst.h"
44 #include "cursorstr.h"
45 #include "scrnintstr.h"
46 #include "windowstr.h"
47 #include "servermd.h"
48 #include "swaprep.h"
49 #include "propertyst.h"
50 #include <X11/Xatom.h>
51 #include "darwin.h"
52 #define _APPLEWM_SERVER_
53 #include <X11/extensions/applewmproto.h>
54 #include "applewmExt.h"
55 #include "X11Application.h"
56 #include "protocol-versions.h"
57 
58 #define DEFINE_ATOM_HELPER(func, atom_name)                      \
59     static Atom func(void) {                                       \
60         static int generation;                                      \
61         static Atom atom;                                           \
62         if (generation != serverGeneration) {                       \
63             generation = serverGeneration;                          \
64             atom = MakeAtom(atom_name, strlen(atom_name), TRUE);  \
65         }                                                           \
66         return atom;                                                \
67     }
68 
69 DEFINE_ATOM_HELPER(xa_native_screen_origin, "_NATIVE_SCREEN_ORIGIN")
70 DEFINE_ATOM_HELPER(xa_apple_no_order_in, "_APPLE_NO_ORDER_IN")
71 
72 static AppleWMProcsPtr appleWMProcs;
73 
74 static int WMErrorBase;
75 
76 static unsigned char WMReqCode = 0;
77 static int WMEventBase = 0;
78 
79 static RESTYPE ClientType, EventType; /* resource types for event masks */
80 static XID eventResource;
81 
82 /* Currently selected events */
83 static unsigned int eventMask = 0;
84 
85 static int
86 WMFreeClient(void *data, XID id);
87 static int
88 WMFreeEvents(void *data, XID id);
89 static void
90 SNotifyEvent(xAppleWMNotifyEvent *from, xAppleWMNotifyEvent *to);
91 
92 typedef struct _WMEvent *WMEventPtr;
93 typedef struct _WMEvent {
94     WMEventPtr next;
95     ClientPtr client;
96     XID clientResource;
97     unsigned int mask;
98 } WMEventRec;
99 
100 static inline BoxRec
make_box(int x,int y,int w,int h)101 make_box(int x, int y, int w, int h)
102 {
103     BoxRec r;
104     r.x1 = x;
105     r.y1 = y;
106     r.x2 = x + w;
107     r.y2 = y + h;
108     return r;
109 }
110 
111 /* Updates the _NATIVE_SCREEN_ORIGIN property on the given root window. */
112 void
AppleWMSetScreenOrigin(WindowPtr pWin)113 AppleWMSetScreenOrigin(WindowPtr pWin)
114 {
115     int32_t data[2];
116 
117     data[0] = pWin->drawable.pScreen->x + darwinMainScreenX;
118     data[1] = pWin->drawable.pScreen->y + darwinMainScreenY;
119 
120     dixChangeWindowProperty(serverClient, pWin, xa_native_screen_origin(),
121                             XA_INTEGER, 32, PropModeReplace, 2, data, TRUE);
122 }
123 
124 /* Window managers can set the _APPLE_NO_ORDER_IN property on windows
125    that are being genie-restored from the Dock. We want them to
126    be mapped but remain ordered-out until the animation
127    completes (when the Dock will order them in). */
128 Bool
AppleWMDoReorderWindow(WindowPtr pWin)129 AppleWMDoReorderWindow(WindowPtr pWin)
130 {
131     Atom atom;
132     PropertyPtr prop;
133     int rc;
134 
135     atom = xa_apple_no_order_in();
136     rc = dixLookupProperty(&prop, pWin, atom, serverClient, DixReadAccess);
137 
138     if (Success == rc && prop->type == atom)
139         return 0;
140 
141     return 1;
142 }
143 
144 static int
ProcAppleWMQueryVersion(register ClientPtr client)145 ProcAppleWMQueryVersion(register ClientPtr client)
146 {
147     xAppleWMQueryVersionReply rep;
148 
149     REQUEST_SIZE_MATCH(xAppleWMQueryVersionReq);
150     rep.type = X_Reply;
151     rep.length = 0;
152     rep.sequenceNumber = client->sequence;
153     rep.majorVersion = SERVER_APPLEWM_MAJOR_VERSION;
154     rep.minorVersion = SERVER_APPLEWM_MINOR_VERSION;
155     rep.patchVersion = SERVER_APPLEWM_PATCH_VERSION;
156     if (client->swapped) {
157         swaps(&rep.sequenceNumber);
158         swapl(&rep.length);
159     }
160     WriteToClient(client, sizeof(xAppleWMQueryVersionReply),&rep);
161     return Success;
162 }
163 
164 /* events */
165 
166 static inline void
updateEventMask(WMEventPtr * pHead)167 updateEventMask(WMEventPtr *pHead)
168 {
169     WMEventPtr pCur;
170 
171     eventMask = 0;
172     for (pCur = *pHead; pCur != NULL; pCur = pCur->next)
173         eventMask |= pCur->mask;
174 }
175 
176 /*ARGSUSED*/
177 static int
WMFreeClient(void * data,XID id)178 WMFreeClient(void *data, XID id)
179 {
180     WMEventPtr pEvent;
181     WMEventPtr   *pHead, pCur, pPrev;
182     int i;
183 
184     pEvent = (WMEventPtr)data;
185     i = dixLookupResourceByType(
186         (void **)&pHead, eventResource, EventType, serverClient,
187         DixReadAccess |
188         DixWriteAccess | DixDestroyAccess);
189     if (i == Success && pHead) {
190         pPrev = 0;
191         for (pCur = *pHead; pCur && pCur != pEvent; pCur = pCur->next)
192             pPrev = pCur;
193         if (pCur) {
194             if (pPrev)
195                 pPrev->next = pEvent->next;
196             else
197                 *pHead = pEvent->next;
198         }
199         updateEventMask(pHead);
200     }
201     free((void *)pEvent);
202     return 1;
203 }
204 
205 /*ARGSUSED*/
206 static int
WMFreeEvents(void * data,XID id)207 WMFreeEvents(void *data, XID id)
208 {
209     WMEventPtr   *pHead, pCur, pNext;
210 
211     pHead = (WMEventPtr *)data;
212     for (pCur = *pHead; pCur; pCur = pNext) {
213         pNext = pCur->next;
214         FreeResource(pCur->clientResource, ClientType);
215         free((void *)pCur);
216     }
217     free((void *)pHead);
218     eventMask = 0;
219     return 1;
220 }
221 
222 static int
ProcAppleWMSelectInput(register ClientPtr client)223 ProcAppleWMSelectInput(register ClientPtr client)
224 {
225     REQUEST(xAppleWMSelectInputReq);
226     WMEventPtr pEvent, pNewEvent, *pHead;
227     XID clientResource;
228     int i;
229 
230     REQUEST_SIZE_MATCH(xAppleWMSelectInputReq);
231     i =
232         dixLookupResourceByType((void **)&pHead, eventResource, EventType,
233                                 client,
234                                 DixWriteAccess);
235     if (stuff->mask != 0) {
236         if (i == Success && pHead) {
237             /* check for existing entry. */
238             for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
239                 if (pEvent->client == client) {
240                     pEvent->mask = stuff->mask;
241                     updateEventMask(pHead);
242                     return Success;
243                 }
244             }
245         }
246 
247         /* build the entry */
248         pNewEvent = (WMEventPtr)malloc(sizeof(WMEventRec));
249         if (!pNewEvent)
250             return BadAlloc;
251         pNewEvent->next = 0;
252         pNewEvent->client = client;
253         pNewEvent->mask = stuff->mask;
254         /*
255          * add a resource that will be deleted when
256          * the client goes away
257          */
258         clientResource = FakeClientID(client->index);
259         pNewEvent->clientResource = clientResource;
260         if (!AddResource(clientResource, ClientType, (void *)pNewEvent))
261             return BadAlloc;
262         /*
263          * create a resource to contain a pointer to the list
264          * of clients selecting input.  This must be indirect as
265          * the list may be arbitrarily rearranged which cannot be
266          * done through the resource database.
267          */
268         if (i != Success || !pHead) {
269             pHead = (WMEventPtr *)malloc(sizeof(WMEventPtr));
270             if (!pHead ||
271                 !AddResource(eventResource, EventType, (void *)pHead)) {
272                 FreeResource(clientResource, RT_NONE);
273                 return BadAlloc;
274             }
275             *pHead = 0;
276         }
277         pNewEvent->next = *pHead;
278         *pHead = pNewEvent;
279         updateEventMask(pHead);
280     }
281     else if (stuff->mask == 0) {
282         /* delete the interest */
283         if (i == Success && pHead) {
284             pNewEvent = 0;
285             for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
286                 if (pEvent->client == client)
287                     break;
288                 pNewEvent = pEvent;
289             }
290             if (pEvent) {
291                 FreeResource(pEvent->clientResource, ClientType);
292                 if (pNewEvent)
293                     pNewEvent->next = pEvent->next;
294                 else
295                     *pHead = pEvent->next;
296                 free(pEvent);
297                 updateEventMask(pHead);
298             }
299         }
300     }
301     else {
302         client->errorValue = stuff->mask;
303         return BadValue;
304     }
305     return Success;
306 }
307 
308 /*
309  * deliver the event
310  */
311 
312 void
AppleWMSendEvent(int type,unsigned int mask,int which,int arg)313 AppleWMSendEvent(int type, unsigned int mask, int which, int arg)
314 {
315     WMEventPtr      *pHead, pEvent;
316     xAppleWMNotifyEvent se;
317     int i;
318 
319     i =
320         dixLookupResourceByType((void **)&pHead, eventResource, EventType,
321                                 serverClient,
322                                 DixReadAccess);
323     if (i != Success || !pHead)
324         return;
325     for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
326         if ((pEvent->mask & mask) == 0)
327             continue;
328         se.type = type + WMEventBase;
329         se.kind = which;
330         se.arg = arg;
331         se.time = currentTime.milliseconds;
332         WriteEventsToClient(pEvent->client, 1, (xEvent *)&se);
333     }
334 }
335 
336 /* Safe to call from any thread. */
337 unsigned int
AppleWMSelectedEvents(void)338 AppleWMSelectedEvents(void)
339 {
340     return eventMask;
341 }
342 
343 /* general utility functions */
344 
345 static int
ProcAppleWMDisableUpdate(register ClientPtr client)346 ProcAppleWMDisableUpdate(register ClientPtr client)
347 {
348     REQUEST_SIZE_MATCH(xAppleWMDisableUpdateReq);
349 
350     appleWMProcs->DisableUpdate();
351 
352     return Success;
353 }
354 
355 static int
ProcAppleWMReenableUpdate(register ClientPtr client)356 ProcAppleWMReenableUpdate(register ClientPtr client)
357 {
358     REQUEST_SIZE_MATCH(xAppleWMReenableUpdateReq);
359 
360     appleWMProcs->EnableUpdate();
361 
362     return Success;
363 }
364 
365 /* window functions */
366 
367 static int
ProcAppleWMSetWindowMenu(register ClientPtr client)368 ProcAppleWMSetWindowMenu(register ClientPtr client)
369 {
370     const char *bytes, **items;
371     char *shortcuts;
372     int max_len, nitems, i, j;
373     REQUEST(xAppleWMSetWindowMenuReq);
374 
375     REQUEST_AT_LEAST_SIZE(xAppleWMSetWindowMenuReq);
376 
377     nitems = stuff->nitems;
378     items = malloc(sizeof(char *) * nitems);
379     shortcuts = malloc(sizeof(char) * nitems);
380 
381     if (!items || !shortcuts) {
382         free(items);
383         free(shortcuts);
384 
385         return BadAlloc;
386     }
387 
388     max_len = (stuff->length << 2) - sizeof(xAppleWMSetWindowMenuReq);
389     bytes = (char *)&stuff[1];
390 
391     for (i = j = 0; i < max_len && j < nitems;) {
392         shortcuts[j] = bytes[i++];
393         items[j++] = bytes + i;
394 
395         while (i < max_len)
396         {
397             if (bytes[i++] == 0)
398                 break;
399         }
400     }
401 
402     /* Check if we bailed out of the above loop due to a request that was too long */
403     if (j < nitems) {
404         free(items);
405         free(shortcuts);
406 
407         return BadRequest;
408     }
409 
410     X11ApplicationSetWindowMenu(nitems, items, shortcuts);
411     free(items);
412     free(shortcuts);
413 
414     return Success;
415 }
416 
417 static int
ProcAppleWMSetWindowMenuCheck(register ClientPtr client)418 ProcAppleWMSetWindowMenuCheck(register ClientPtr client)
419 {
420     REQUEST(xAppleWMSetWindowMenuCheckReq);
421 
422     REQUEST_SIZE_MATCH(xAppleWMSetWindowMenuCheckReq);
423     X11ApplicationSetWindowMenuCheck(stuff->index);
424     return Success;
425 }
426 
427 static int
ProcAppleWMSetFrontProcess(register ClientPtr client)428 ProcAppleWMSetFrontProcess(register ClientPtr client)
429 {
430     REQUEST_SIZE_MATCH(xAppleWMSetFrontProcessReq);
431 
432     X11ApplicationSetFrontProcess();
433     return Success;
434 }
435 
436 static int
ProcAppleWMSetWindowLevel(register ClientPtr client)437 ProcAppleWMSetWindowLevel(register ClientPtr client)
438 {
439     REQUEST(xAppleWMSetWindowLevelReq);
440     WindowPtr pWin;
441     int err;
442 
443     REQUEST_SIZE_MATCH(xAppleWMSetWindowLevelReq);
444 
445     if (Success != dixLookupWindow(&pWin, stuff->window, client,
446                                    DixReadAccess))
447         return BadValue;
448 
449     if (stuff->level >= AppleWMNumWindowLevels) {
450         return BadValue;
451     }
452 
453     err = appleWMProcs->SetWindowLevel(pWin, stuff->level);
454     if (err != Success) {
455         return err;
456     }
457 
458     return Success;
459 }
460 
461 static int
ProcAppleWMSendPSN(register ClientPtr client)462 ProcAppleWMSendPSN(register ClientPtr client)
463 {
464     REQUEST(xAppleWMSendPSNReq);
465     int err;
466 
467     REQUEST_SIZE_MATCH(xAppleWMSendPSNReq);
468 
469     if (!appleWMProcs->SendPSN)
470         return BadRequest;
471 
472     err = appleWMProcs->SendPSN(stuff->psn_hi, stuff->psn_lo);
473     if (err != Success) {
474         return err;
475     }
476 
477     return Success;
478 }
479 
480 static int
ProcAppleWMAttachTransient(register ClientPtr client)481 ProcAppleWMAttachTransient(register ClientPtr client)
482 {
483     WindowPtr pWinChild, pWinParent;
484     REQUEST(xAppleWMAttachTransientReq);
485     int err;
486 
487     REQUEST_SIZE_MATCH(xAppleWMAttachTransientReq);
488 
489     if (!appleWMProcs->AttachTransient)
490         return BadRequest;
491 
492     if (Success !=
493         dixLookupWindow(&pWinChild, stuff->child, client, DixReadAccess))
494         return BadValue;
495 
496     if (stuff->parent) {
497         if (Success !=
498             dixLookupWindow(&pWinParent, stuff->parent, client, DixReadAccess))
499             return BadValue;
500     }
501     else {
502         pWinParent = NULL;
503     }
504 
505     err = appleWMProcs->AttachTransient(pWinChild, pWinParent);
506     if (err != Success) {
507         return err;
508     }
509 
510     return Success;
511 }
512 
513 static int
ProcAppleWMSetCanQuit(register ClientPtr client)514 ProcAppleWMSetCanQuit(register ClientPtr client)
515 {
516     REQUEST(xAppleWMSetCanQuitReq);
517 
518     REQUEST_SIZE_MATCH(xAppleWMSetCanQuitReq);
519 
520     X11ApplicationSetCanQuit(stuff->state);
521     return Success;
522 }
523 
524 /* frame functions */
525 
526 static int
ProcAppleWMFrameGetRect(register ClientPtr client)527 ProcAppleWMFrameGetRect(register ClientPtr client)
528 {
529     xAppleWMFrameGetRectReply rep;
530     BoxRec ir, or, rr;
531     REQUEST(xAppleWMFrameGetRectReq);
532 
533     REQUEST_SIZE_MATCH(xAppleWMFrameGetRectReq);
534     rep.type = X_Reply;
535     rep.length = 0;
536     rep.sequenceNumber = client->sequence;
537 
538     ir = make_box(stuff->ix, stuff->iy, stuff->iw, stuff->ih);
539     or = make_box(stuff->ox, stuff->oy, stuff->ow, stuff->oh);
540 
541     if (appleWMProcs->FrameGetRect(stuff->frame_rect,
542                                    stuff->frame_class,
543                                    &or, &ir, &rr) != Success) {
544         return BadValue;
545     }
546 
547     rep.x = rr.x1;
548     rep.y = rr.y1;
549     rep.w = rr.x2 - rr.x1;
550     rep.h = rr.y2 - rr.y1;
551 
552     WriteToClient(client, sizeof(xAppleWMFrameGetRectReply),&rep);
553     return Success;
554 }
555 
556 static int
ProcAppleWMFrameHitTest(register ClientPtr client)557 ProcAppleWMFrameHitTest(register ClientPtr client)
558 {
559     xAppleWMFrameHitTestReply rep;
560     BoxRec ir, or;
561     int ret;
562     REQUEST(xAppleWMFrameHitTestReq);
563 
564     REQUEST_SIZE_MATCH(xAppleWMFrameHitTestReq);
565     rep.type = X_Reply;
566     rep.length = 0;
567     rep.sequenceNumber = client->sequence;
568 
569     ir = make_box(stuff->ix, stuff->iy, stuff->iw, stuff->ih);
570     or = make_box(stuff->ox, stuff->oy, stuff->ow, stuff->oh);
571 
572     if (appleWMProcs->FrameHitTest(stuff->frame_class, stuff->px,
573                                    stuff->py, &or, &ir, &ret) != Success) {
574         return BadValue;
575     }
576 
577     rep.ret = ret;
578 
579     WriteToClient(client, sizeof(xAppleWMFrameHitTestReply),&rep);
580     return Success;
581 }
582 
583 static int
ProcAppleWMFrameDraw(register ClientPtr client)584 ProcAppleWMFrameDraw(register ClientPtr client)
585 {
586     BoxRec ir, or;
587     unsigned int title_length, title_max;
588     unsigned char *title_bytes;
589     REQUEST(xAppleWMFrameDrawReq);
590     WindowPtr pWin;
591 
592     REQUEST_AT_LEAST_SIZE(xAppleWMFrameDrawReq);
593 
594     if (Success != dixLookupWindow(&pWin, stuff->window, client,
595                                    DixReadAccess))
596         return BadValue;
597 
598     ir = make_box(stuff->ix, stuff->iy, stuff->iw, stuff->ih);
599     or = make_box(stuff->ox, stuff->oy, stuff->ow, stuff->oh);
600 
601     title_length = stuff->title_length;
602     title_max = (stuff->length << 2) - sizeof(xAppleWMFrameDrawReq);
603 
604     if (title_max < title_length)
605         return BadValue;
606 
607     title_bytes = (unsigned char *)&stuff[1];
608 
609     errno = appleWMProcs->FrameDraw(pWin, stuff->frame_class,
610                                     stuff->frame_attr, &or, &ir,
611                                     title_length, title_bytes);
612     if (errno != Success) {
613         return errno;
614     }
615 
616     return Success;
617 }
618 
619 /* dispatch */
620 
621 static int
ProcAppleWMDispatch(register ClientPtr client)622 ProcAppleWMDispatch(register ClientPtr client)
623 {
624     REQUEST(xReq);
625 
626     switch (stuff->data) {
627     case X_AppleWMQueryVersion:
628         return ProcAppleWMQueryVersion(client);
629     }
630 
631     if (!client->local)
632         return WMErrorBase + AppleWMClientNotLocal;
633 
634     switch (stuff->data) {
635     case X_AppleWMSelectInput:
636         return ProcAppleWMSelectInput(client);
637 
638     case X_AppleWMDisableUpdate:
639         return ProcAppleWMDisableUpdate(client);
640 
641     case X_AppleWMReenableUpdate:
642         return ProcAppleWMReenableUpdate(client);
643 
644     case X_AppleWMSetWindowMenu:
645         return ProcAppleWMSetWindowMenu(client);
646 
647     case X_AppleWMSetWindowMenuCheck:
648         return ProcAppleWMSetWindowMenuCheck(client);
649 
650     case X_AppleWMSetFrontProcess:
651         return ProcAppleWMSetFrontProcess(client);
652 
653     case X_AppleWMSetWindowLevel:
654         return ProcAppleWMSetWindowLevel(client);
655 
656     case X_AppleWMSetCanQuit:
657         return ProcAppleWMSetCanQuit(client);
658 
659     case X_AppleWMFrameGetRect:
660         return ProcAppleWMFrameGetRect(client);
661 
662     case X_AppleWMFrameHitTest:
663         return ProcAppleWMFrameHitTest(client);
664 
665     case X_AppleWMFrameDraw:
666         return ProcAppleWMFrameDraw(client);
667 
668     case X_AppleWMSendPSN:
669         return ProcAppleWMSendPSN(client);
670 
671     case X_AppleWMAttachTransient:
672         return ProcAppleWMAttachTransient(client);
673 
674     default:
675         return BadRequest;
676     }
677 }
678 
679 static void
SNotifyEvent(xAppleWMNotifyEvent * from,xAppleWMNotifyEvent * to)680 SNotifyEvent(xAppleWMNotifyEvent *from, xAppleWMNotifyEvent *to)
681 {
682     to->type = from->type;
683     to->kind = from->kind;
684     cpswaps(from->sequenceNumber, to->sequenceNumber);
685     cpswapl(from->time, to->time);
686     cpswapl(from->arg, to->arg);
687 }
688 
689 static int
SProcAppleWMQueryVersion(register ClientPtr client)690 SProcAppleWMQueryVersion(register ClientPtr client)
691 {
692     REQUEST(xAppleWMQueryVersionReq);
693     swaps(&stuff->length);
694     return ProcAppleWMQueryVersion(client);
695 }
696 
697 static int
SProcAppleWMDispatch(register ClientPtr client)698 SProcAppleWMDispatch(register ClientPtr client)
699 {
700     REQUEST(xReq);
701 
702     /* It is bound to be non-local when there is byte swapping */
703     if (!client->local)
704         return WMErrorBase + AppleWMClientNotLocal;
705 
706     /* only local clients are allowed WM access */
707     switch (stuff->data) {
708     case X_AppleWMQueryVersion:
709         return SProcAppleWMQueryVersion(client);
710 
711     default:
712         return BadRequest;
713     }
714 }
715 
716 void
AppleWMExtensionInit(AppleWMProcsPtr procsPtr)717 AppleWMExtensionInit(AppleWMProcsPtr procsPtr)
718 {
719     ExtensionEntry* extEntry;
720 
721     ClientType = CreateNewResourceType(WMFreeClient, "WMClient");
722     EventType = CreateNewResourceType(WMFreeEvents, "WMEvent");
723     eventResource = FakeClientID(0);
724 
725     if (ClientType && EventType &&
726         (extEntry = AddExtension(APPLEWMNAME,
727                                  AppleWMNumberEvents,
728                                  AppleWMNumberErrors,
729                                  ProcAppleWMDispatch,
730                                  SProcAppleWMDispatch,
731                                  NULL,
732                                  StandardMinorOpcode))) {
733         size_t i;
734         WMReqCode = (unsigned char)extEntry->base;
735         WMErrorBase = extEntry->errorBase;
736         WMEventBase = extEntry->eventBase;
737         for (i = 0; i < AppleWMNumberEvents; i++)
738             EventSwapVector[WMEventBase + i] = (EventSwapPtr)SNotifyEvent;
739         appleWMProcs = procsPtr;
740     }
741 }
742