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