2 * Copyright (c) 2003 Torrey T. Lyons. All Rights Reserved.
3 * Copyright (c) 2002-2012 Apple Inc. All rights reserved.
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:
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
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.
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.
31 #include "sanitizedCarbon.h"
33 #ifdef HAVE_DIX_CONFIG_H
34 #include <dix-config.h>
37 #include "quartzCommon.h"
40 #include "dixstruct.h"
42 #include "extnsionst.h"
43 #include "colormapst.h"
44 #include "cursorstr.h"
45 #include "scrnintstr.h"
46 #include "windowstr.h"
49 #include "propertyst.h"
50 #include <X11/Xatom.h>
52 #define _APPLEWM_SERVER_
53 #include <X11/extensions/applewmproto.h>
54 #include "applewmExt.h"
55 #include "X11Application.h"
56 #include "protocol-versions.h"
58 #define DEFINE_ATOM_HELPER(func, atom_name) \
59 static Atom func(void) { \
60 static int generation; \
62 if (generation != serverGeneration) { \
63 generation = serverGeneration; \
64 atom = MakeAtom(atom_name, strlen(atom_name), TRUE); \
69 DEFINE_ATOM_HELPER(xa_native_screen_origin
, "_NATIVE_SCREEN_ORIGIN")
70 DEFINE_ATOM_HELPER(xa_apple_no_order_in
, "_APPLE_NO_ORDER_IN")
72 static AppleWMProcsPtr appleWMProcs
;
74 static int WMErrorBase
;
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;
86 WMFreeClient(pointer data
, XID id
);
88 WMFreeEvents(pointer data
, XID id
);
90 SNotifyEvent(xAppleWMNotifyEvent
*from
, xAppleWMNotifyEvent
*to
);
92 typedef struct _WMEvent
*WMEventPtr
;
93 typedef struct _WMEvent
{
101 make_box(int x
, int y
, int w
, int h
)
111 /* Updates the _NATIVE_SCREEN_ORIGIN property on the given root window. */
113 AppleWMSetScreenOrigin(WindowPtr pWin
)
117 data
[0] = pWin
->drawable
.pScreen
->x
+ darwinMainScreenX
;
118 data
[1] = pWin
->drawable
.pScreen
->y
+ darwinMainScreenY
;
120 dixChangeWindowProperty(serverClient
, pWin
, xa_native_screen_origin(),
121 XA_INTEGER
, 32, PropModeReplace
, 2, data
, TRUE
);
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). */
129 AppleWMDoReorderWindow(WindowPtr pWin
)
135 atom
= xa_apple_no_order_in();
136 rc
= dixLookupProperty(&prop
, pWin
, atom
, serverClient
, DixReadAccess
);
138 if (Success
== rc
&& prop
->type
== atom
)
145 ProcAppleWMQueryVersion(register ClientPtr client
)
147 xAppleWMQueryVersionReply rep
;
149 REQUEST_SIZE_MATCH(xAppleWMQueryVersionReq
);
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
);
160 WriteToClient(client
, sizeof(xAppleWMQueryVersionReply
),&rep
);
167 updateEventMask(WMEventPtr
*pHead
)
172 for (pCur
= *pHead
; pCur
!= NULL
; pCur
= pCur
->next
)
173 eventMask
|= pCur
->mask
;
178 WMFreeClient(pointer data
, XID id
)
181 WMEventPtr
*pHead
, pCur
, pPrev
;
184 pEvent
= (WMEventPtr
)data
;
185 i
= dixLookupResourceByType(
186 (pointer
*)&pHead
, eventResource
, EventType
, serverClient
,
188 DixWriteAccess
| DixDestroyAccess
);
189 if (i
== Success
&& pHead
) {
191 for (pCur
= *pHead
; pCur
&& pCur
!= pEvent
; pCur
= pCur
->next
)
195 pPrev
->next
= pEvent
->next
;
197 *pHead
= pEvent
->next
;
199 updateEventMask(pHead
);
201 free((pointer
)pEvent
);
207 WMFreeEvents(pointer data
, XID id
)
209 WMEventPtr
*pHead
, pCur
, pNext
;
211 pHead
= (WMEventPtr
*)data
;
212 for (pCur
= *pHead
; pCur
; pCur
= pNext
) {
214 FreeResource(pCur
->clientResource
, ClientType
);
217 free((pointer
)pHead
);
223 ProcAppleWMSelectInput(register ClientPtr client
)
225 REQUEST(xAppleWMSelectInputReq
);
226 WMEventPtr pEvent
, pNewEvent
, *pHead
;
230 REQUEST_SIZE_MATCH(xAppleWMSelectInputReq
);
232 dixLookupResourceByType((pointer
*)&pHead
, eventResource
, EventType
,
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
);
247 /* build the entry */
248 pNewEvent
= (WMEventPtr
)malloc(sizeof(WMEventRec
));
252 pNewEvent
->client
= client
;
253 pNewEvent
->mask
= stuff
->mask
;
255 * add a resource that will be deleted when
256 * the client goes away
258 clientResource
= FakeClientID(client
->index
);
259 pNewEvent
->clientResource
= clientResource
;
260 if (!AddResource(clientResource
, ClientType
, (pointer
)pNewEvent
))
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.
268 if (i
!= Success
|| !pHead
) {
269 pHead
= (WMEventPtr
*)malloc(sizeof(WMEventPtr
));
271 !AddResource(eventResource
, EventType
, (pointer
)pHead
)) {
272 FreeResource(clientResource
, RT_NONE
);
277 pNewEvent
->next
= *pHead
;
279 updateEventMask(pHead
);
281 else if (stuff
->mask
== 0) {
282 /* delete the interest */
283 if (i
== Success
&& pHead
) {
285 for (pEvent
= *pHead
; pEvent
; pEvent
= pEvent
->next
) {
286 if (pEvent
->client
== client
)
291 FreeResource(pEvent
->clientResource
, ClientType
);
293 pNewEvent
->next
= pEvent
->next
;
295 *pHead
= pEvent
->next
;
297 updateEventMask(pHead
);
302 client
->errorValue
= stuff
->mask
;
313 AppleWMSendEvent(int type
, unsigned int mask
, int which
, int arg
)
315 WMEventPtr
*pHead
, pEvent
;
316 xAppleWMNotifyEvent se
;
320 dixLookupResourceByType((pointer
*)&pHead
, eventResource
, EventType
,
323 if (i
!= Success
|| !pHead
)
325 for (pEvent
= *pHead
; pEvent
; pEvent
= pEvent
->next
) {
326 if ((pEvent
->mask
& mask
) == 0)
328 se
.type
= type
+ WMEventBase
;
331 se
.time
= currentTime
.milliseconds
;
332 WriteEventsToClient(pEvent
->client
, 1, (xEvent
*)&se
);
336 /* Safe to call from any thread. */
338 AppleWMSelectedEvents(void)
343 /* general utility functions */
346 ProcAppleWMDisableUpdate(register ClientPtr client
)
348 REQUEST_SIZE_MATCH(xAppleWMDisableUpdateReq
);
350 appleWMProcs
->DisableUpdate();
356 ProcAppleWMReenableUpdate(register ClientPtr client
)
358 REQUEST_SIZE_MATCH(xAppleWMReenableUpdateReq
);
360 appleWMProcs
->EnableUpdate();
365 /* window functions */
368 ProcAppleWMSetWindowMenu(register ClientPtr client
)
370 const char *bytes
, **items
;
372 int max_len
, nitems
, i
, j
;
373 REQUEST(xAppleWMSetWindowMenuReq
);
375 REQUEST_AT_LEAST_SIZE(xAppleWMSetWindowMenuReq
);
377 nitems
= stuff
->nitems
;
378 items
= malloc(sizeof(char *) * nitems
);
379 shortcuts
= malloc(sizeof(char) * nitems
);
381 if (!items
|| !shortcuts
) {
388 max_len
= (stuff
->length
<< 2) - sizeof(xAppleWMSetWindowMenuReq
);
389 bytes
= (char *)&stuff
[1];
391 for (i
= j
= 0; i
< max_len
&& j
< nitems
;) {
392 shortcuts
[j
] = bytes
[i
++];
393 items
[j
++] = bytes
+ i
;
402 /* Check if we bailed out of the above loop due to a request that was too long */
410 X11ApplicationSetWindowMenu(nitems
, items
, shortcuts
);
418 ProcAppleWMSetWindowMenuCheck(register ClientPtr client
)
420 REQUEST(xAppleWMSetWindowMenuCheckReq
);
422 REQUEST_SIZE_MATCH(xAppleWMSetWindowMenuCheckReq
);
423 X11ApplicationSetWindowMenuCheck(stuff
->index
);
428 ProcAppleWMSetFrontProcess(register ClientPtr client
)
430 REQUEST_SIZE_MATCH(xAppleWMSetFrontProcessReq
);
432 X11ApplicationSetFrontProcess();
437 ProcAppleWMSetWindowLevel(register ClientPtr client
)
439 REQUEST(xAppleWMSetWindowLevelReq
);
443 REQUEST_SIZE_MATCH(xAppleWMSetWindowLevelReq
);
445 if (Success
!= dixLookupWindow(&pWin
, stuff
->window
, client
,
449 if (stuff
->level
>= AppleWMNumWindowLevels
) {
453 err
= appleWMProcs
->SetWindowLevel(pWin
, stuff
->level
);
454 if (err
!= Success
) {
462 ProcAppleWMSendPSN(register ClientPtr client
)
464 REQUEST(xAppleWMSendPSNReq
);
467 REQUEST_SIZE_MATCH(xAppleWMSendPSNReq
);
469 if (!appleWMProcs
->SendPSN
)
472 err
= appleWMProcs
->SendPSN(stuff
->psn_hi
, stuff
->psn_lo
);
473 if (err
!= Success
) {
481 ProcAppleWMAttachTransient(register ClientPtr client
)
483 WindowPtr pWinChild
, pWinParent
;
484 REQUEST(xAppleWMAttachTransientReq
);
487 REQUEST_SIZE_MATCH(xAppleWMAttachTransientReq
);
489 if (!appleWMProcs
->AttachTransient
)
493 dixLookupWindow(&pWinChild
, stuff
->child
, client
, DixReadAccess
))
498 dixLookupWindow(&pWinParent
, stuff
->parent
, client
, DixReadAccess
))
505 err
= appleWMProcs
->AttachTransient(pWinChild
, pWinParent
);
506 if (err
!= Success
) {
514 ProcAppleWMSetCanQuit(register ClientPtr client
)
516 REQUEST(xAppleWMSetCanQuitReq
);
518 REQUEST_SIZE_MATCH(xAppleWMSetCanQuitReq
);
520 X11ApplicationSetCanQuit(stuff
->state
);
524 /* frame functions */
527 ProcAppleWMFrameGetRect(register ClientPtr client
)
529 xAppleWMFrameGetRectReply rep
;
531 REQUEST(xAppleWMFrameGetRectReq
);
533 REQUEST_SIZE_MATCH(xAppleWMFrameGetRectReq
);
536 rep
.sequenceNumber
= client
->sequence
;
538 ir
= make_box(stuff
->ix
, stuff
->iy
, stuff
->iw
, stuff
->ih
);
539 or = make_box(stuff
->ox
, stuff
->oy
, stuff
->ow
, stuff
->oh
);
541 if (appleWMProcs
->FrameGetRect(stuff
->frame_rect
,
543 &or, &ir
, &rr
) != Success
) {
549 rep
.w
= rr
.x2
- rr
.x1
;
550 rep
.h
= rr
.y2
- rr
.y1
;
552 WriteToClient(client
, sizeof(xAppleWMFrameGetRectReply
),&rep
);
557 ProcAppleWMFrameHitTest(register ClientPtr client
)
559 xAppleWMFrameHitTestReply rep
;
562 REQUEST(xAppleWMFrameHitTestReq
);
564 REQUEST_SIZE_MATCH(xAppleWMFrameHitTestReq
);
567 rep
.sequenceNumber
= client
->sequence
;
569 ir
= make_box(stuff
->ix
, stuff
->iy
, stuff
->iw
, stuff
->ih
);
570 or = make_box(stuff
->ox
, stuff
->oy
, stuff
->ow
, stuff
->oh
);
572 if (appleWMProcs
->FrameHitTest(stuff
->frame_class
, stuff
->px
,
573 stuff
->py
, &or, &ir
, &ret
) != Success
) {
579 WriteToClient(client
, sizeof(xAppleWMFrameHitTestReply
),&rep
);
584 ProcAppleWMFrameDraw(register ClientPtr client
)
587 unsigned int title_length
, title_max
;
588 unsigned char *title_bytes
;
589 REQUEST(xAppleWMFrameDrawReq
);
592 REQUEST_AT_LEAST_SIZE(xAppleWMFrameDrawReq
);
594 if (Success
!= dixLookupWindow(&pWin
, stuff
->window
, client
,
598 ir
= make_box(stuff
->ix
, stuff
->iy
, stuff
->iw
, stuff
->ih
);
599 or = make_box(stuff
->ox
, stuff
->oy
, stuff
->ow
, stuff
->oh
);
601 title_length
= stuff
->title_length
;
602 title_max
= (stuff
->length
<< 2) - sizeof(xAppleWMFrameDrawReq
);
604 if (title_max
< title_length
)
607 title_bytes
= (unsigned char *)&stuff
[1];
609 errno
= appleWMProcs
->FrameDraw(pWin
, stuff
->frame_class
,
610 stuff
->frame_attr
, &or, &ir
,
611 title_length
, title_bytes
);
612 if (errno
!= Success
) {
622 ProcAppleWMDispatch(register ClientPtr client
)
626 switch (stuff
->data
) {
627 case X_AppleWMQueryVersion
:
628 return ProcAppleWMQueryVersion(client
);
632 return WMErrorBase
+ AppleWMClientNotLocal
;
634 switch (stuff
->data
) {
635 case X_AppleWMSelectInput
:
636 return ProcAppleWMSelectInput(client
);
638 case X_AppleWMDisableUpdate
:
639 return ProcAppleWMDisableUpdate(client
);
641 case X_AppleWMReenableUpdate
:
642 return ProcAppleWMReenableUpdate(client
);
644 case X_AppleWMSetWindowMenu
:
645 return ProcAppleWMSetWindowMenu(client
);
647 case X_AppleWMSetWindowMenuCheck
:
648 return ProcAppleWMSetWindowMenuCheck(client
);
650 case X_AppleWMSetFrontProcess
:
651 return ProcAppleWMSetFrontProcess(client
);
653 case X_AppleWMSetWindowLevel
:
654 return ProcAppleWMSetWindowLevel(client
);
656 case X_AppleWMSetCanQuit
:
657 return ProcAppleWMSetCanQuit(client
);
659 case X_AppleWMFrameGetRect
:
660 return ProcAppleWMFrameGetRect(client
);
662 case X_AppleWMFrameHitTest
:
663 return ProcAppleWMFrameHitTest(client
);
665 case X_AppleWMFrameDraw
:
666 return ProcAppleWMFrameDraw(client
);
668 case X_AppleWMSendPSN
:
669 return ProcAppleWMSendPSN(client
);
671 case X_AppleWMAttachTransient
:
672 return ProcAppleWMAttachTransient(client
);
680 SNotifyEvent(xAppleWMNotifyEvent
*from
, xAppleWMNotifyEvent
*to
)
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
);
690 SProcAppleWMQueryVersion(register ClientPtr client
)
692 REQUEST(xAppleWMQueryVersionReq
);
693 swaps(&stuff
->length
);
694 return ProcAppleWMQueryVersion(client
);
698 SProcAppleWMDispatch(register ClientPtr client
)
702 /* It is bound to be non-local when there is byte swapping */
704 return WMErrorBase
+ AppleWMClientNotLocal
;
706 /* only local clients are allowed WM access */
707 switch (stuff
->data
) {
708 case X_AppleWMQueryVersion
:
709 return SProcAppleWMQueryVersion(client
);
717 AppleWMExtensionInit(AppleWMProcsPtr procsPtr
)
719 ExtensionEntry
* extEntry
;
721 ClientType
= CreateNewResourceType(WMFreeClient
, "WMClient");
722 EventType
= CreateNewResourceType(WMFreeEvents
, "WMEvent");
723 eventResource
= FakeClientID(0);
725 if (ClientType
&& EventType
&&
726 (extEntry
= AddExtension(APPLEWMNAME
,
730 SProcAppleWMDispatch
,
732 StandardMinorOpcode
))) {
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
;