1 /**************************************************************************
3 Copyright (c) 2002-2007 Apple Inc. All Rights Reserved.
4 Copyright (c) 2003 Torrey T. Lyons. All Rights Reserved.
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sub license, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
14 The above copyright notice and this permission notice (including the
15 next paragraph) shall be included in all copies or substantial portions
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
22 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
28 #include "sanitizedCarbon.h"
30 #ifdef HAVE_DIX_CONFIG_H
31 #include <dix-config.h>
34 #include "quartzCommon.h"
37 #include "dixstruct.h"
39 #include "extnsionst.h"
40 #include "colormapst.h"
41 #include "cursorstr.h"
42 #include "scrnintstr.h"
43 #include "windowstr.h"
46 #include "propertyst.h"
47 #include <X11/Xatom.h>
49 #define _APPLEWM_SERVER_
50 #include <X11/extensions/applewmproto.h>
51 #include "applewmExt.h"
52 #include "X11Application.h"
53 #include "protocol-versions.h"
55 #define DEFINE_ATOM_HELPER(func,atom_name) \
56 static Atom func (void) { \
57 static int generation; \
59 if (generation != serverGeneration) { \
60 generation = serverGeneration; \
61 atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \
66 DEFINE_ATOM_HELPER(xa_native_screen_origin, "_NATIVE_SCREEN_ORIGIN")
67 DEFINE_ATOM_HELPER (xa_apple_no_order_in, "_APPLE_NO_ORDER_IN")
69 static AppleWMProcsPtr appleWMProcs;
71 static int WMErrorBase;
73 static DISPATCH_PROC(ProcAppleWMDispatch);
74 static DISPATCH_PROC(SProcAppleWMDispatch);
76 static unsigned char WMReqCode = 0;
77 static int WMEventBase = 0;
79 static RESTYPE ClientType, EventType; /* resource types for event masks */
80 static XID eventResource;
82 /* Currently selected events */
83 static unsigned int eventMask = 0;
85 static int WMFreeClient (pointer data, XID id);
86 static int WMFreeEvents (pointer data, XID id);
87 static void SNotifyEvent(xAppleWMNotifyEvent *from, xAppleWMNotifyEvent *to);
89 typedef struct _WMEvent *WMEventPtr;
90 typedef struct _WMEvent {
98 make_box (int x, int y, int w, int h)
109 AppleWMExtensionInit(
110 AppleWMProcsPtr procsPtr)
112 ExtensionEntry* extEntry;
114 ClientType = CreateNewResourceType(WMFreeClient, "WMClient");
115 EventType = CreateNewResourceType(WMFreeEvents, "WMEvent");
116 eventResource = FakeClientID(0);
118 if (ClientType && EventType &&
119 (extEntry = AddExtension(APPLEWMNAME,
123 SProcAppleWMDispatch,
125 StandardMinorOpcode)))
127 WMReqCode = (unsigned char)extEntry->base;
128 WMErrorBase = extEntry->errorBase;
129 WMEventBase = extEntry->eventBase;
130 EventSwapVector[WMEventBase] = (EventSwapPtr) SNotifyEvent;
131 appleWMProcs = procsPtr;
135 /* Updates the _NATIVE_SCREEN_ORIGIN property on the given root window. */
137 AppleWMSetScreenOrigin(
143 data[0] = pWin->drawable.pScreen->x + darwinMainScreenX;
144 data[1] = pWin->drawable.pScreen->y + darwinMainScreenY;
146 dixChangeWindowProperty(serverClient, pWin, xa_native_screen_origin(),
147 XA_INTEGER, 32, PropModeReplace, 2, data, TRUE);
150 /* Window managers can set the _APPLE_NO_ORDER_IN property on windows
151 that are being genie-restored from the Dock. We want them to
152 be mapped but remain ordered-out until the animation
153 completes (when the Dock will order them in). */
155 AppleWMDoReorderWindow(
163 atom = xa_apple_no_order_in();
164 rc = dixLookupProperty(&prop, pWin, atom, serverClient, DixReadAccess);
166 if(Success == rc && prop->type == atom)
174 ProcAppleWMQueryVersion(
175 register ClientPtr client
178 xAppleWMQueryVersionReply rep;
181 REQUEST_SIZE_MATCH(xAppleWMQueryVersionReq);
184 rep.sequenceNumber = client->sequence;
185 rep.majorVersion = SERVER_APPLEWM_MAJOR_VERSION;
186 rep.minorVersion = SERVER_APPLEWM_MINOR_VERSION;
187 rep.patchVersion = SERVER_APPLEWM_PATCH_VERSION;
188 if (client->swapped) {
189 swaps(&rep.sequenceNumber, n);
190 swapl(&rep.length, n);
192 WriteToClient(client, sizeof(xAppleWMQueryVersionReply), (char *)&rep);
200 updateEventMask (WMEventPtr *pHead)
205 for (pCur = *pHead; pCur != NULL; pCur = pCur->next)
206 eventMask |= pCur->mask;
211 WMFreeClient (pointer data, XID id) {
213 WMEventPtr *pHead, pCur, pPrev;
216 pEvent = (WMEventPtr) data;
217 i = dixLookupResourceByType((pointer *)&pHead, eventResource, EventType, serverClient, DixReadAccess | DixWriteAccess | DixDestroyAccess);
218 if (i == Success && pHead) {
220 for (pCur = *pHead; pCur && pCur != pEvent; pCur=pCur->next)
224 pPrev->next = pEvent->next;
226 *pHead = pEvent->next;
228 updateEventMask (pHead);
230 free((pointer) pEvent);
236 WMFreeEvents (pointer data, XID id) {
237 WMEventPtr *pHead, pCur, pNext;
239 pHead = (WMEventPtr *) data;
240 for (pCur = *pHead; pCur; pCur = pNext) {
242 FreeResource (pCur->clientResource, ClientType);
243 free((pointer) pCur);
245 free((pointer) pHead);
251 ProcAppleWMSelectInput (register ClientPtr client)
253 REQUEST(xAppleWMSelectInputReq);
254 WMEventPtr pEvent, pNewEvent, *pHead;
258 REQUEST_SIZE_MATCH (xAppleWMSelectInputReq);
259 i = dixLookupResourceByType((pointer *)&pHead, eventResource, EventType, client, DixWriteAccess);
260 if (stuff->mask != 0) {
261 if (i == Success && pHead) {
262 /* check for existing entry. */
263 for (pEvent = *pHead; pEvent; pEvent = pEvent->next)
265 if (pEvent->client == client)
267 pEvent->mask = stuff->mask;
268 updateEventMask (pHead);
274 /* build the entry */
275 pNewEvent = (WMEventPtr) malloc(sizeof (WMEventRec));
279 pNewEvent->client = client;
280 pNewEvent->mask = stuff->mask;
282 * add a resource that will be deleted when
283 * the client goes away
285 clientResource = FakeClientID (client->index);
286 pNewEvent->clientResource = clientResource;
287 if (!AddResource (clientResource, ClientType, (pointer)pNewEvent))
290 * create a resource to contain a pointer to the list
291 * of clients selecting input. This must be indirect as
292 * the list may be arbitrarily rearranged which cannot be
293 * done through the resource database.
295 if (i != Success || !pHead)
297 pHead = (WMEventPtr *) malloc(sizeof (WMEventPtr));
299 !AddResource (eventResource, EventType, (pointer)pHead))
301 FreeResource (clientResource, RT_NONE);
306 pNewEvent->next = *pHead;
308 updateEventMask (pHead);
309 } else if (stuff->mask == 0) {
310 /* delete the interest */
311 if (i == Success && pHead) {
313 for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
314 if (pEvent->client == client)
319 FreeResource (pEvent->clientResource, ClientType);
321 pNewEvent->next = pEvent->next;
323 *pHead = pEvent->next;
325 updateEventMask (pHead);
329 client->errorValue = stuff->mask;
340 AppleWMSendEvent (int type, unsigned int mask, int which, int arg) {
341 WMEventPtr *pHead, pEvent;
342 xAppleWMNotifyEvent se;
345 i = dixLookupResourceByType((pointer *)&pHead, eventResource, EventType, serverClient, DixReadAccess);
346 if (i != Success || !pHead)
348 for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
349 if ((pEvent->mask & mask) == 0)
351 se.type = type + WMEventBase;
354 se.time = currentTime.milliseconds;
355 WriteEventsToClient (pEvent->client, 1, (xEvent *) &se);
359 /* Safe to call from any thread. */
361 AppleWMSelectedEvents (void)
367 /* general utility functions */
370 ProcAppleWMDisableUpdate(
371 register ClientPtr client
374 REQUEST_SIZE_MATCH(xAppleWMDisableUpdateReq);
376 appleWMProcs->DisableUpdate();
382 ProcAppleWMReenableUpdate(
383 register ClientPtr client
386 REQUEST_SIZE_MATCH(xAppleWMReenableUpdateReq);
388 appleWMProcs->EnableUpdate();
394 /* window functions */
397 ProcAppleWMSetWindowMenu(
398 register ClientPtr client
401 const char *bytes, **items;
403 int max_len, nitems, i, j;
404 REQUEST(xAppleWMSetWindowMenuReq);
406 REQUEST_AT_LEAST_SIZE(xAppleWMSetWindowMenuReq);
408 nitems = stuff->nitems;
409 items = malloc(sizeof (char *) * nitems);
410 shortcuts = malloc(sizeof (char) * nitems);
412 max_len = (stuff->length << 2) - sizeof(xAppleWMSetWindowMenuReq);
413 bytes = (char *) &stuff[1];
415 for (i = j = 0; i < max_len && j < nitems;)
417 shortcuts[j] = bytes[i++];
418 items[j++] = bytes + i;
426 X11ApplicationSetWindowMenu (nitems, items, shortcuts);
434 ProcAppleWMSetWindowMenuCheck(
435 register ClientPtr client
438 REQUEST(xAppleWMSetWindowMenuCheckReq);
440 REQUEST_SIZE_MATCH(xAppleWMSetWindowMenuCheckReq);
441 X11ApplicationSetWindowMenuCheck(stuff->index);
446 ProcAppleWMSetFrontProcess(
447 register ClientPtr client
450 REQUEST_SIZE_MATCH(xAppleWMSetFrontProcessReq);
452 X11ApplicationSetFrontProcess();
457 ProcAppleWMSetWindowLevel(register ClientPtr client)
459 REQUEST(xAppleWMSetWindowLevelReq);
463 REQUEST_SIZE_MATCH(xAppleWMSetWindowLevelReq);
465 if (Success != dixLookupWindow(&pWin, stuff->window, client,
469 if (stuff->level < 0 || stuff->level >= AppleWMNumWindowLevels) {
473 err = appleWMProcs->SetWindowLevel(pWin, stuff->level);
474 if (err != Success) {
482 ProcAppleWMSendPSN(register ClientPtr client)
484 REQUEST(xAppleWMSendPSNReq);
487 REQUEST_SIZE_MATCH(xAppleWMSendPSNReq);
489 if(!appleWMProcs->SendPSN)
492 err = appleWMProcs->SendPSN(stuff->psn_hi, stuff->psn_lo);
493 if (err != Success) {
501 ProcAppleWMAttachTransient(register ClientPtr client)
503 WindowPtr pWinChild, pWinParent;
504 REQUEST(xAppleWMAttachTransientReq);
507 REQUEST_SIZE_MATCH(xAppleWMAttachTransientReq);
509 if(!appleWMProcs->AttachTransient)
512 if (Success != dixLookupWindow(&pWinChild, stuff->child, client, DixReadAccess))
516 if(Success != dixLookupWindow(&pWinParent, stuff->parent, client, DixReadAccess))
522 err = appleWMProcs->AttachTransient(pWinChild, pWinParent);
523 if (err != Success) {
531 ProcAppleWMSetCanQuit(
532 register ClientPtr client
535 REQUEST(xAppleWMSetCanQuitReq);
537 REQUEST_SIZE_MATCH(xAppleWMSetCanQuitReq);
539 X11ApplicationSetCanQuit(stuff->state);
544 /* frame functions */
547 ProcAppleWMFrameGetRect(
548 register ClientPtr client
551 xAppleWMFrameGetRectReply rep;
553 REQUEST(xAppleWMFrameGetRectReq);
555 REQUEST_SIZE_MATCH(xAppleWMFrameGetRectReq);
558 rep.sequenceNumber = client->sequence;
560 ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih);
561 or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh);
563 if (appleWMProcs->FrameGetRect(stuff->frame_rect,
565 &or, &ir, &rr) != Success)
572 rep.w = rr.x2 - rr.x1;
573 rep.h = rr.y2 - rr.y1;
575 WriteToClient(client, sizeof(xAppleWMFrameGetRectReply), (char *)&rep);
580 ProcAppleWMFrameHitTest(
581 register ClientPtr client
584 xAppleWMFrameHitTestReply rep;
587 REQUEST(xAppleWMFrameHitTestReq);
589 REQUEST_SIZE_MATCH(xAppleWMFrameHitTestReq);
592 rep.sequenceNumber = client->sequence;
594 ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih);
595 or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh);
597 if (appleWMProcs->FrameHitTest(stuff->frame_class, stuff->px,
598 stuff->py, &or, &ir, &ret) != Success)
605 WriteToClient(client, sizeof(xAppleWMFrameHitTestReply), (char *)&rep);
610 ProcAppleWMFrameDraw(
611 register ClientPtr client
615 unsigned int title_length, title_max;
616 unsigned char *title_bytes;
617 REQUEST(xAppleWMFrameDrawReq);
620 REQUEST_AT_LEAST_SIZE(xAppleWMFrameDrawReq);
622 if (Success != dixLookupWindow(&pWin, stuff->window, client,
626 ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih);
627 or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh);
629 title_length = stuff->title_length;
630 title_max = (stuff->length << 2) - sizeof(xAppleWMFrameDrawReq);
632 if (title_max < title_length)
635 title_bytes = (unsigned char *) &stuff[1];
637 errno = appleWMProcs->FrameDraw(pWin, stuff->frame_class,
638 stuff->frame_attr, &or, &ir,
639 title_length, title_bytes);
640 if (errno != Success) {
651 ProcAppleWMDispatch (
652 register ClientPtr client
659 case X_AppleWMQueryVersion:
660 return ProcAppleWMQueryVersion(client);
663 if (!LocalClient(client))
664 return WMErrorBase + AppleWMClientNotLocal;
668 case X_AppleWMSelectInput:
669 return ProcAppleWMSelectInput(client);
670 case X_AppleWMDisableUpdate:
671 return ProcAppleWMDisableUpdate(client);
672 case X_AppleWMReenableUpdate:
673 return ProcAppleWMReenableUpdate(client);
674 case X_AppleWMSetWindowMenu:
675 return ProcAppleWMSetWindowMenu(client);
676 case X_AppleWMSetWindowMenuCheck:
677 return ProcAppleWMSetWindowMenuCheck(client);
678 case X_AppleWMSetFrontProcess:
679 return ProcAppleWMSetFrontProcess(client);
680 case X_AppleWMSetWindowLevel:
681 return ProcAppleWMSetWindowLevel(client);
682 case X_AppleWMSetCanQuit:
683 return ProcAppleWMSetCanQuit(client);
684 case X_AppleWMFrameGetRect:
685 return ProcAppleWMFrameGetRect(client);
686 case X_AppleWMFrameHitTest:
687 return ProcAppleWMFrameHitTest(client);
688 case X_AppleWMFrameDraw:
689 return ProcAppleWMFrameDraw(client);
690 case X_AppleWMSendPSN:
691 return ProcAppleWMSendPSN(client);
692 case X_AppleWMAttachTransient:
693 return ProcAppleWMAttachTransient(client);
700 SNotifyEvent(xAppleWMNotifyEvent *from, xAppleWMNotifyEvent *to) {
701 to->type = from->type;
702 to->kind = from->kind;
703 cpswaps (from->sequenceNumber, to->sequenceNumber);
704 cpswapl (from->time, to->time);
705 cpswapl (from->arg, to->arg);
709 SProcAppleWMQueryVersion(
710 register ClientPtr client
714 REQUEST(xAppleWMQueryVersionReq);
715 swaps(&stuff->length, n);
716 return ProcAppleWMQueryVersion(client);
720 SProcAppleWMDispatch (
721 register ClientPtr client
726 /* It is bound to be non-local when there is byte swapping */
727 if (!LocalClient(client))
728 return WMErrorBase + AppleWMClientNotLocal;
730 /* only local clients are allowed WM access */
733 case X_AppleWMQueryVersion:
734 return SProcAppleWMQueryVersion(client);