1
/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/applewm.c,v 1.2 2003/09/16 00:36:13 torrey Exp $ */
2
/**************************************************************************
4
Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved.
5
Copyright (c) 2003 Torrey T. Lyons. All Rights Reserved.
7
Permission is hereby granted, free of charge, to any person obtaining a
8
copy of this software and associated documentation files (the
9
"Software"), to deal in the Software without restriction, including
10
without limitation the rights to use, copy, modify, merge, publish,
11
distribute, sub license, and/or sell copies of the Software, and to
12
permit persons to whom the Software is furnished to do so, subject to
13
the following conditions:
15
The above copyright notice and this permission notice (including the
16
next paragraph) shall be included in all copies or substantial portions
19
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22
IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
23
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
**************************************************************************/
29
#include "quartzCommon.h"
34
#include "dixstruct.h"
36
#include "extnsionst.h"
37
#include "colormapst.h"
38
#include "cursorstr.h"
39
#include "scrnintstr.h"
40
#include "windowstr.h"
43
#include "propertyst.h"
44
#include <X11/Xatom.h>
46
#define _APPLEWM_SERVER_
47
#include "applewmstr.h"
48
#include "applewmExt.h"
50
#define DEFINE_ATOM_HELPER(func,atom_name) \
51
static Atom func (void) { \
52
static int generation; \
54
if (generation != serverGeneration) { \
55
generation = serverGeneration; \
56
atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \
61
DEFINE_ATOM_HELPER(xa_native_screen_origin, "_NATIVE_SCREEN_ORIGIN")
62
DEFINE_ATOM_HELPER (xa_apple_no_order_in, "_APPLE_NO_ORDER_IN")
64
static AppleWMProcsPtr appleWMProcs;
66
static int WMErrorBase;
68
static DISPATCH_PROC(ProcAppleWMDispatch);
69
static DISPATCH_PROC(SProcAppleWMDispatch);
71
static void AppleWMResetProc(ExtensionEntry* extEntry);
73
static unsigned char WMReqCode = 0;
74
static int WMEventBase = 0;
76
static RESTYPE ClientType, EventType; /* resource types for event masks */
77
static XID eventResource;
79
/* Currently selected events */
80
static unsigned int eventMask = 0;
82
static int WMFreeClient (pointer data, XID id);
83
static int WMFreeEvents (pointer data, XID id);
84
static void SNotifyEvent(xAppleWMNotifyEvent *from, xAppleWMNotifyEvent *to);
86
typedef struct _WMEvent *WMEventPtr;
87
typedef struct _WMEvent {
95
make_box (int x, int y, int w, int h)
106
AppleWMExtensionInit(
107
AppleWMProcsPtr procsPtr)
109
ExtensionEntry* extEntry;
111
ClientType = CreateNewResourceType(WMFreeClient);
112
EventType = CreateNewResourceType(WMFreeEvents);
113
eventResource = FakeClientID(0);
115
if (ClientType && EventType &&
116
(extEntry = AddExtension(APPLEWMNAME,
120
SProcAppleWMDispatch,
122
StandardMinorOpcode)))
124
WMReqCode = (unsigned char)extEntry->base;
125
WMErrorBase = extEntry->errorBase;
126
WMEventBase = extEntry->eventBase;
127
EventSwapVector[WMEventBase] = (EventSwapPtr) SNotifyEvent;
128
appleWMProcs = procsPtr;
135
ExtensionEntry* extEntry
140
/* Updates the _NATIVE_SCREEN_ORIGIN property on the given root window. */
142
AppleWMSetScreenOrigin(
148
data[0] = (dixScreenOrigins[pWin->drawable.pScreen->myNum].x
149
+ darwinMainScreenX);
150
data[1] = (dixScreenOrigins[pWin->drawable.pScreen->myNum].y
151
+ darwinMainScreenY);
153
ChangeWindowProperty(pWin, xa_native_screen_origin(), XA_INTEGER,
154
32, PropModeReplace, 2, data, TRUE);
157
/* Window managers can set the _APPLE_NO_ORDER_IN property on windows
158
that are being genie-restored from the Dock. We want them to
159
be mapped but remain ordered-out until the animation
160
completes (when the Dock will order them in). */
162
AppleWMDoReorderWindow(
169
atom = xa_apple_no_order_in();
170
for (prop = wUserProps(pWin); prop != NULL; prop = prop->next)
172
if (prop->propertyName == atom && prop->type == atom)
181
ProcAppleWMQueryVersion(
182
register ClientPtr client
185
xAppleWMQueryVersionReply rep;
188
REQUEST_SIZE_MATCH(xAppleWMQueryVersionReq);
191
rep.sequenceNumber = client->sequence;
192
rep.majorVersion = APPLE_WM_MAJOR_VERSION;
193
rep.minorVersion = APPLE_WM_MINOR_VERSION;
194
rep.patchVersion = APPLE_WM_PATCH_VERSION;
195
if (client->swapped) {
196
swaps(&rep.sequenceNumber, n);
197
swapl(&rep.length, n);
199
WriteToClient(client, sizeof(xAppleWMQueryVersionReply), (char *)&rep);
200
return (client->noClientException);
207
updateEventMask (WMEventPtr *pHead)
212
for (pCur = *pHead; pCur != NULL; pCur = pCur->next)
213
eventMask |= pCur->mask;
218
WMFreeClient (data, id)
223
WMEventPtr *pHead, pCur, pPrev;
225
pEvent = (WMEventPtr) data;
226
pHead = (WMEventPtr *) LookupIDByType(eventResource, EventType);
229
for (pCur = *pHead; pCur && pCur != pEvent; pCur=pCur->next)
233
pPrev->next = pEvent->next;
235
*pHead = pEvent->next;
237
updateEventMask (pHead);
239
xfree ((pointer) pEvent);
245
WMFreeEvents (data, id)
249
WMEventPtr *pHead, pCur, pNext;
251
pHead = (WMEventPtr *) data;
252
for (pCur = *pHead; pCur; pCur = pNext) {
254
FreeResource (pCur->clientResource, ClientType);
255
xfree ((pointer) pCur);
257
xfree ((pointer) pHead);
263
ProcAppleWMSelectInput (client)
264
register ClientPtr client;
266
REQUEST(xAppleWMSelectInputReq);
267
WMEventPtr pEvent, pNewEvent, *pHead;
270
REQUEST_SIZE_MATCH (xAppleWMSelectInputReq);
271
pHead = (WMEventPtr *)SecurityLookupIDByType(client,
272
eventResource, EventType, SecurityWriteAccess);
273
if (stuff->mask != 0) {
275
/* check for existing entry. */
276
for (pEvent = *pHead; pEvent; pEvent = pEvent->next)
278
if (pEvent->client == client)
280
pEvent->mask = stuff->mask;
281
updateEventMask (pHead);
287
/* build the entry */
288
pNewEvent = (WMEventPtr) xalloc (sizeof (WMEventRec));
292
pNewEvent->client = client;
293
pNewEvent->mask = stuff->mask;
295
* add a resource that will be deleted when
296
* the client goes away
298
clientResource = FakeClientID (client->index);
299
pNewEvent->clientResource = clientResource;
300
if (!AddResource (clientResource, ClientType, (pointer)pNewEvent))
303
* create a resource to contain a pointer to the list
304
* of clients selecting input. This must be indirect as
305
* the list may be arbitrarily rearranged which cannot be
306
* done through the resource database.
310
pHead = (WMEventPtr *) xalloc (sizeof (WMEventPtr));
312
!AddResource (eventResource, EventType, (pointer)pHead))
314
FreeResource (clientResource, RT_NONE);
319
pNewEvent->next = *pHead;
321
updateEventMask (pHead);
322
} else if (stuff->mask == 0) {
323
/* delete the interest */
326
for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
327
if (pEvent->client == client)
332
FreeResource (pEvent->clientResource, ClientType);
334
pNewEvent->next = pEvent->next;
336
*pHead = pEvent->next;
338
updateEventMask (pHead);
342
client->errorValue = stuff->mask;
353
AppleWMSendEvent (type, mask, which, arg)
354
int type, which, arg;
357
WMEventPtr *pHead, pEvent;
359
xAppleWMNotifyEvent se;
361
pHead = (WMEventPtr *) LookupIDByType(eventResource, EventType);
364
for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
365
client = pEvent->client;
366
if ((pEvent->mask & mask) == 0
367
|| client == serverClient || client->clientGone)
371
se.type = type + WMEventBase;
374
se.sequenceNumber = client->sequence;
375
se.time = currentTime.milliseconds;
376
WriteEventsToClient (client, 1, (xEvent *) &se);
380
/* Safe to call from any thread. */
382
AppleWMSelectedEvents (void)
388
/* general utility functions */
391
ProcAppleWMDisableUpdate(
392
register ClientPtr client
395
REQUEST_SIZE_MATCH(xAppleWMDisableUpdateReq);
397
appleWMProcs->DisableUpdate();
399
return (client->noClientException);
403
ProcAppleWMReenableUpdate(
404
register ClientPtr client
407
REQUEST_SIZE_MATCH(xAppleWMReenableUpdateReq);
409
appleWMProcs->EnableUpdate();
411
return (client->noClientException);
415
/* window functions */
418
ProcAppleWMSetWindowMenu(
419
register ClientPtr client
422
const char *bytes, **items;
424
int max_len, nitems, i, j;
425
REQUEST(xAppleWMSetWindowMenuReq);
427
REQUEST_AT_LEAST_SIZE(xAppleWMSetWindowMenuReq);
429
nitems = stuff->nitems;
430
items = xalloc (sizeof (char *) * nitems);
431
shortcuts = xalloc (sizeof (char) * nitems);
433
max_len = (stuff->length << 2) - sizeof(xAppleWMSetWindowMenuReq);
434
bytes = (char *) &stuff[1];
436
for (i = j = 0; i < max_len && j < nitems;)
438
shortcuts[j] = bytes[i++];
439
items[j++] = bytes + i;
448
QuartzSetWindowMenu (nitems, items, shortcuts);
453
return (client->noClientException);
457
ProcAppleWMSetWindowMenuCheck(
458
register ClientPtr client
461
REQUEST(xAppleWMSetWindowMenuCheckReq);
463
REQUEST_SIZE_MATCH(xAppleWMSetWindowMenuCheckReq);
465
QuartzMessageMainThread(kQuartzSetWindowMenuCheck, &stuff->index,
466
sizeof(stuff->index));
468
return (client->noClientException);
472
ProcAppleWMSetFrontProcess(
473
register ClientPtr client
476
REQUEST_SIZE_MATCH(xAppleWMSetFrontProcessReq);
478
QuartzMessageMainThread(kQuartzSetFrontProcess, NULL, 0);
480
return (client->noClientException);
484
ProcAppleWMSetWindowLevel(
485
register ClientPtr client
488
REQUEST(xAppleWMSetWindowLevelReq);
492
REQUEST_SIZE_MATCH(xAppleWMSetWindowLevelReq);
494
if (!(pWin = SecurityLookupWindow((Drawable)stuff->window,
495
client, SecurityReadAccess)))
500
if (stuff->level < 0 || stuff->level >= AppleWMNumWindowLevels) {
504
errno = appleWMProcs->SetWindowLevel(pWin, stuff->level);
505
if (errno != Success) {
509
return (client->noClientException);
513
ProcAppleWMSetCanQuit(
514
register ClientPtr client
517
REQUEST(xAppleWMSetCanQuitReq);
519
REQUEST_SIZE_MATCH(xAppleWMSetCanQuitReq);
521
QuartzMessageMainThread(kQuartzSetCanQuit, &stuff->state,
522
sizeof(stuff->state));
524
return (client->noClientException);
528
/* frame functions */
531
ProcAppleWMFrameGetRect(
532
register ClientPtr client
535
xAppleWMFrameGetRectReply rep;
537
REQUEST(xAppleWMFrameGetRectReq);
539
REQUEST_SIZE_MATCH(xAppleWMFrameGetRectReq);
542
rep.sequenceNumber = client->sequence;
544
ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih);
545
or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh);
547
if (appleWMProcs->FrameGetRect(stuff->frame_rect,
549
&or, &ir, &rr) != Success)
556
rep.w = rr.x2 - rr.x1;
557
rep.h = rr.y2 - rr.y1;
559
WriteToClient(client, sizeof(xAppleWMFrameGetRectReply), (char *)&rep);
560
return (client->noClientException);
564
ProcAppleWMFrameHitTest(
565
register ClientPtr client
568
xAppleWMFrameHitTestReply rep;
571
REQUEST(xAppleWMFrameHitTestReq);
573
REQUEST_SIZE_MATCH(xAppleWMFrameHitTestReq);
576
rep.sequenceNumber = client->sequence;
578
ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih);
579
or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh);
581
if (appleWMProcs->FrameHitTest(stuff->frame_class, stuff->px,
582
stuff->py, &or, &ir, &ret) != Success)
589
WriteToClient(client, sizeof(xAppleWMFrameHitTestReply), (char *)&rep);
590
return (client->noClientException);
594
ProcAppleWMFrameDraw(
595
register ClientPtr client
599
unsigned int title_length, title_max;
600
unsigned char *title_bytes;
601
REQUEST(xAppleWMFrameDrawReq);
604
REQUEST_AT_LEAST_SIZE(xAppleWMFrameDrawReq);
606
if (!(pWin = SecurityLookupWindow((Drawable)stuff->window,
607
client, SecurityReadAccess)))
612
ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih);
613
or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh);
615
title_length = stuff->title_length;
616
title_max = (stuff->length << 2) - sizeof(xAppleWMFrameDrawReq);
618
if (title_max < title_length)
621
title_bytes = (unsigned char *) &stuff[1];
623
errno = appleWMProcs->FrameDraw(pWin, stuff->frame_class,
624
stuff->frame_attr, &or, &ir,
625
title_length, title_bytes);
626
if (errno != Success) {
630
return (client->noClientException);
637
ProcAppleWMDispatch (
638
register ClientPtr client
645
case X_AppleWMQueryVersion:
646
return ProcAppleWMQueryVersion(client);
649
if (!LocalClient(client))
650
return WMErrorBase + AppleWMClientNotLocal;
654
case X_AppleWMSelectInput:
655
return ProcAppleWMSelectInput(client);
656
case X_AppleWMDisableUpdate:
657
return ProcAppleWMDisableUpdate(client);
658
case X_AppleWMReenableUpdate:
659
return ProcAppleWMReenableUpdate(client);
660
case X_AppleWMSetWindowMenu:
661
return ProcAppleWMSetWindowMenu(client);
662
case X_AppleWMSetWindowMenuCheck:
663
return ProcAppleWMSetWindowMenuCheck(client);
664
case X_AppleWMSetFrontProcess:
665
return ProcAppleWMSetFrontProcess(client);
666
case X_AppleWMSetWindowLevel:
667
return ProcAppleWMSetWindowLevel(client);
668
case X_AppleWMSetCanQuit:
669
return ProcAppleWMSetCanQuit(client);
670
case X_AppleWMFrameGetRect:
671
return ProcAppleWMFrameGetRect(client);
672
case X_AppleWMFrameHitTest:
673
return ProcAppleWMFrameHitTest(client);
674
case X_AppleWMFrameDraw:
675
return ProcAppleWMFrameDraw(client);
682
SNotifyEvent(from, to)
683
xAppleWMNotifyEvent *from, *to;
685
to->type = from->type;
686
to->kind = from->kind;
687
cpswaps (from->sequenceNumber, to->sequenceNumber);
688
cpswapl (from->time, to->time);
689
cpswapl (from->arg, to->arg);
693
SProcAppleWMQueryVersion(
694
register ClientPtr client
698
REQUEST(xAppleWMQueryVersionReq);
699
swaps(&stuff->length, n);
700
return ProcAppleWMQueryVersion(client);
704
SProcAppleWMDispatch (
705
register ClientPtr client
710
/* It is bound to be non-local when there is byte swapping */
711
if (!LocalClient(client))
712
return WMErrorBase + AppleWMClientNotLocal;
714
/* only local clients are allowed WM access */
717
case X_AppleWMQueryVersion:
718
return SProcAppleWMQueryVersion(client);