1 /* $XFree86: xc/programs/Xserver/GL/dri/xf86dri.c,v 1.10 2000/12/07 20:26:14 dawes Exp $ */
2 /**************************************************************************
3
4 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
5 Copyright 2000 VA Linux Systems, Inc.
6 Copyright (c) 2002 Apple Computer, Inc.
7 All Rights Reserved.
8
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sub license, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial portions
19 of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
24 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
25 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29 **************************************************************************/
30
31 #define NEED_REPLIES
32 #define NEED_EVENTS
33 #include "X.h"
34 #include "Xproto.h"
35 #include "misc.h"
36 #include "dixstruct.h"
37 #include "extnsionst.h"
38 #include "colormapst.h"
39 #include "cursorstr.h"
40 #include "scrnintstr.h"
41 #include "servermd.h"
42 #define _APPLEWM_SERVER_
43 #include "applewmstr.h"
44 #include "swaprep.h"
45 #include "rootless-common.h"
46 #include "X11Application.h"
47
48 static int WMErrorBase;
49
50 static DISPATCH_PROC(ProcAppleWMDispatch);
51 static DISPATCH_PROC(SProcAppleWMDispatch);
52
53 static void AppleWMResetProc(ExtensionEntry* extEntry);
54
55 static unsigned char WMReqCode = 0;
56 static int WMEventBase = 0;
57
58 static RESTYPE ClientType, EventType; /* resource types for event masks */
59 static XID eventResource;
60
61 /* Currently selected events */
62 static unsigned int eventMask = 0;
63
64 extern void AppleWMExtensionInit(void);
65
66 static int WMFreeClient (pointer data, XID id);
67 static int WMFreeEvents (pointer data, XID id);
68 static void SNotifyEvent(xAppleWMNotifyEvent *from, xAppleWMNotifyEvent *to);
69
70 typedef struct _WMEvent *WMEventPtr;
71 typedef struct _WMEvent {
72 WMEventPtr next;
73 ClientPtr client;
74 XID clientResource;
75 unsigned int mask;
76 } WMEventRec;
77
78 static inline BoxRec
make_box(int x,int y,int w,int h)79 make_box (int x, int y, int w, int h)
80 {
81 BoxRec r;
82 r.x1 = x;
83 r.y1 = y;
84 r.x2 = x + w;
85 r.y2 = y + h;
86 return r;
87 }
88
89 void
AppleWMExtensionInit(void)90 AppleWMExtensionInit(void)
91 {
92 ExtensionEntry* extEntry;
93
94 ClientType = CreateNewResourceType(WMFreeClient);
95 EventType = CreateNewResourceType(WMFreeEvents);
96 eventResource = FakeClientID(0);
97
98 if (ClientType && EventType &&
99 (extEntry = AddExtension(APPLEWMNAME,
100 AppleWMNumberEvents,
101 AppleWMNumberErrors,
102 ProcAppleWMDispatch,
103 SProcAppleWMDispatch,
104 AppleWMResetProc,
105 StandardMinorOpcode))) {
106 WMReqCode = (unsigned char)extEntry->base;
107 WMErrorBase = extEntry->errorBase;
108 WMEventBase = extEntry->eventBase;
109 EventSwapVector[WMEventBase] = (EventSwapPtr) SNotifyEvent;
110 }
111 }
112
113 /*ARGSUSED*/
114 static void
AppleWMResetProc(ExtensionEntry * extEntry)115 AppleWMResetProc (
116 ExtensionEntry* extEntry
117 )
118 {
119 }
120
121 static int
ProcAppleWMQueryVersion(register ClientPtr client)122 ProcAppleWMQueryVersion(
123 register ClientPtr client
124 )
125 {
126 xAppleWMQueryVersionReply rep;
127 register int n;
128
129 REQUEST_SIZE_MATCH(xAppleWMQueryVersionReq);
130 rep.type = X_Reply;
131 rep.length = 0;
132 rep.sequenceNumber = client->sequence;
133 rep.majorVersion = APPLE_WM_MAJOR_VERSION;
134 rep.minorVersion = APPLE_WM_MINOR_VERSION;
135 rep.patchVersion = APPLE_WM_PATCH_VERSION;
136 if (client->swapped) {
137 swaps(&rep.sequenceNumber, n);
138 swapl(&rep.length, n);
139 }
140 WriteToClient(client, sizeof(xAppleWMQueryVersionReply), (char *)&rep);
141 return (client->noClientException);
142 }
143
144
145 /* events */
146
147 static inline void
updateEventMask(WMEventPtr * pHead)148 updateEventMask (WMEventPtr *pHead)
149 {
150 WMEventPtr pCur;
151
152 eventMask = 0;
153 for (pCur = *pHead; pCur != NULL; pCur = pCur->next)
154 eventMask |= pCur->mask;
155 }
156
157 /*ARGSUSED*/
158 static int
WMFreeClient(data,id)159 WMFreeClient (data, id)
160 pointer data;
161 XID id;
162 {
163 WMEventPtr pEvent;
164 WMEventPtr *pHead, pCur, pPrev;
165
166 pEvent = (WMEventPtr) data;
167 pHead = (WMEventPtr *) LookupIDByType(eventResource, EventType);
168 if (pHead) {
169 pPrev = 0;
170 for (pCur = *pHead; pCur && pCur != pEvent; pCur=pCur->next)
171 pPrev = pCur;
172 if (pCur)
173 {
174 if (pPrev)
175 pPrev->next = pEvent->next;
176 else
177 *pHead = pEvent->next;
178 }
179 updateEventMask (pHead);
180 }
181 xfree ((pointer) pEvent);
182 return 1;
183 }
184
185 /*ARGSUSED*/
186 static int
WMFreeEvents(data,id)187 WMFreeEvents (data, id)
188 pointer data;
189 XID id;
190 {
191 WMEventPtr *pHead, pCur, pNext;
192
193 pHead = (WMEventPtr *) data;
194 for (pCur = *pHead; pCur; pCur = pNext) {
195 pNext = pCur->next;
196 FreeResource (pCur->clientResource, ClientType);
197 xfree ((pointer) pCur);
198 }
199 xfree ((pointer) pHead);
200 eventMask = 0;
201 return 1;
202 }
203
204 static int
ProcAppleWMSelectInput(client)205 ProcAppleWMSelectInput (client)
206 register ClientPtr client;
207 {
208 REQUEST(xAppleWMSelectInputReq);
209 WMEventPtr pEvent, pNewEvent, *pHead;
210 XID clientResource;
211
212 REQUEST_SIZE_MATCH (xAppleWMSelectInputReq);
213 pHead = (WMEventPtr *)SecurityLookupIDByType(client,
214 eventResource, EventType, SecurityWriteAccess);
215 if (stuff->mask != 0) {
216 if (pHead) {
217 /* check for existing entry. */
218 for (pEvent = *pHead; pEvent; pEvent = pEvent->next)
219 {
220 if (pEvent->client == client)
221 {
222 pEvent->mask = stuff->mask;
223 updateEventMask (pHead);
224 return Success;
225 }
226 }
227 }
228
229 /* build the entry */
230 pNewEvent = (WMEventPtr) xalloc (sizeof (WMEventRec));
231 if (!pNewEvent)
232 return BadAlloc;
233 pNewEvent->next = 0;
234 pNewEvent->client = client;
235 pNewEvent->mask = stuff->mask;
236 /*
237 * add a resource that will be deleted when
238 * the client goes away
239 */
240 clientResource = FakeClientID (client->index);
241 pNewEvent->clientResource = clientResource;
242 if (!AddResource (clientResource, ClientType, (pointer)pNewEvent))
243 return BadAlloc;
244 /*
245 * create a resource to contain a pointer to the list
246 * of clients selecting input. This must be indirect as
247 * the list may be arbitrarily rearranged which cannot be
248 * done through the resource database.
249 */
250 if (!pHead)
251 {
252 pHead = (WMEventPtr *) xalloc (sizeof (WMEventPtr));
253 if (!pHead ||
254 !AddResource (eventResource, EventType, (pointer)pHead))
255 {
256 FreeResource (clientResource, RT_NONE);
257 return BadAlloc;
258 }
259 *pHead = 0;
260 }
261 pNewEvent->next = *pHead;
262 *pHead = pNewEvent;
263 updateEventMask (pHead);
264 } else if (stuff->mask == 0) {
265 /* delete the interest */
266 if (pHead) {
267 pNewEvent = 0;
268 for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
269 if (pEvent->client == client)
270 break;
271 pNewEvent = pEvent;
272 }
273 if (pEvent) {
274 FreeResource (pEvent->clientResource, ClientType);
275 if (pNewEvent)
276 pNewEvent->next = pEvent->next;
277 else
278 *pHead = pEvent->next;
279 xfree (pEvent);
280 updateEventMask (pHead);
281 }
282 }
283 } else {
284 client->errorValue = stuff->mask;
285 return BadValue;
286 }
287 return Success;
288 }
289
290 /*
291 * deliver the event
292 */
293
294 void
AppleWMSendEvent(type,mask,which,arg)295 AppleWMSendEvent (type, mask, which, arg)
296 int type, which, arg;
297 unsigned int mask;
298 {
299 WMEventPtr *pHead, pEvent;
300 ClientPtr client;
301 xAppleWMNotifyEvent se;
302
303 pHead = (WMEventPtr *) LookupIDByType(eventResource, EventType);
304 if (!pHead)
305 return;
306 for (pEvent = *pHead; pEvent; pEvent = pEvent->next) {
307 client = pEvent->client;
308 if ((pEvent->mask & mask) == 0
309 || client == serverClient || client->clientGone)
310 {
311 continue;
312 }
313 se.type = type + WMEventBase;
314 se.kind = which;
315 se.arg = arg;
316 se.sequenceNumber = client->sequence;
317 se.time = currentTime.milliseconds;
318 WriteEventsToClient (client, 1, (xEvent *) &se);
319 }
320 }
321
322 /* Safe to call from any thread. */
323 unsigned int
AppleWMSelectedEvents(void)324 AppleWMSelectedEvents (void)
325 {
326 return eventMask;
327 }
328
329
330 /* general utility functions */
331
332 static int
ProcAppleWMDisableUpdate(register ClientPtr client)333 ProcAppleWMDisableUpdate(
334 register ClientPtr client
335 )
336 {
337 REQUEST_SIZE_MATCH(xAppleWMDisableUpdateReq);
338
339 xp_disable_update ();
340
341 return (client->noClientException);
342 }
343
344 static int
ProcAppleWMReenableUpdate(register ClientPtr client)345 ProcAppleWMReenableUpdate(
346 register ClientPtr client
347 )
348 {
349 REQUEST_SIZE_MATCH(xAppleWMReenableUpdateReq);
350
351 xp_reenable_update ();
352
353 return (client->noClientException);
354 }
355
356
357 /* window functions */
358
359 static int
ProcAppleWMSetWindowMenu(register ClientPtr client)360 ProcAppleWMSetWindowMenu(
361 register ClientPtr client
362 )
363 {
364 const char *bytes, **items;
365 char *shortcuts;
366 int max_len, nitems, i, j;
367 REQUEST(xAppleWMSetWindowMenuReq);
368
369 REQUEST_AT_LEAST_SIZE(xAppleWMSetWindowMenuReq);
370
371 nitems = stuff->nitems;
372 items = alloca (sizeof (char *) * nitems);
373 shortcuts = alloca (sizeof (char) * nitems);
374
375 max_len = (stuff->length << 2) - sizeof(xAppleWMSetWindowMenuReq);
376 bytes = (char *) &stuff[1];
377
378 for (i = j = 0; i < max_len && j < nitems;)
379 {
380 shortcuts[j] = bytes[i++];
381 items[j++] = bytes + i;
382
383 while (i < max_len)
384 {
385 if (bytes[i++] == 0)
386 break;
387 }
388 }
389
390 X11ApplicationSetWindowMenu (nitems, items, shortcuts);
391
392 return (client->noClientException);
393 }
394
395 static int
ProcAppleWMSetWindowMenuCheck(register ClientPtr client)396 ProcAppleWMSetWindowMenuCheck(
397 register ClientPtr client
398 )
399 {
400 REQUEST(xAppleWMSetWindowMenuCheckReq);
401
402 REQUEST_SIZE_MATCH(xAppleWMSetWindowMenuCheckReq);
403
404 X11ApplicationSetWindowMenuCheck (stuff->index);
405
406 return (client->noClientException);
407 }
408
409 static int
ProcAppleWMSetFrontProcess(register ClientPtr client)410 ProcAppleWMSetFrontProcess(
411 register ClientPtr client
412 )
413 {
414 REQUEST_SIZE_MATCH(xAppleWMSetFrontProcessReq);
415
416 X11ApplicationSetFrontProcess ();
417
418 return (client->noClientException);
419 }
420
421 static int
ProcAppleWMSetWindowLevel(register ClientPtr client)422 ProcAppleWMSetWindowLevel(
423 register ClientPtr client
424 )
425 {
426 REQUEST(xAppleWMSetWindowLevelReq);
427 WindowPtr pWin;
428
429 REQUEST_SIZE_MATCH(xAppleWMSetWindowLevelReq);
430
431 if (!(pWin = SecurityLookupWindow((Drawable)stuff->window,
432 client, SecurityReadAccess))) {
433 return BadValue;
434 }
435
436 if (stuff->level < 0 || stuff->level >= AppleWMNumWindowLevels) {
437 return BadValue;
438 }
439
440 RootlessSetWindowLevel (pWin, stuff->level);
441
442 return (client->noClientException);
443 }
444
445 static int
ProcAppleWMSetCanQuit(register ClientPtr client)446 ProcAppleWMSetCanQuit(
447 register ClientPtr client
448 )
449 {
450 REQUEST(xAppleWMSetCanQuitReq);
451
452 REQUEST_SIZE_MATCH(xAppleWMSetCanQuitReq);
453
454 X11ApplicationSetCanQuit (stuff->state);
455
456 return (client->noClientException);
457 }
458
459
460 /* frame functions */
461
462 static int
ProcAppleWMFrameGetRect(register ClientPtr client)463 ProcAppleWMFrameGetRect(
464 register ClientPtr client
465 )
466 {
467 xAppleWMFrameGetRectReply rep;
468 BoxRec ir, or, rr;
469 REQUEST(xAppleWMFrameGetRectReq);
470
471 REQUEST_SIZE_MATCH(xAppleWMFrameGetRectReq);
472 rep.type = X_Reply;
473 rep.length = 0;
474 rep.sequenceNumber = client->sequence;
475
476 ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih);
477 or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh);
478
479 if (xp_frame_get_rect (stuff->frame_rect,
480 stuff->frame_class,
481 &or, &ir, &rr) != Success) {
482 return BadValue;
483 }
484
485 rep.x = rr.x1;
486 rep.y = rr.y1;
487 rep.w = rr.x2 - rr.x1;
488 rep.h = rr.y2 - rr.y1;
489
490 WriteToClient(client, sizeof(xAppleWMFrameGetRectReply), (char *)&rep);
491 return (client->noClientException);
492 }
493
494 static int
ProcAppleWMFrameHitTest(register ClientPtr client)495 ProcAppleWMFrameHitTest(
496 register ClientPtr client
497 )
498 {
499 xAppleWMFrameHitTestReply rep;
500 BoxRec ir, or;
501 int ret;
502 REQUEST(xAppleWMFrameHitTestReq);
503
504 REQUEST_SIZE_MATCH(xAppleWMFrameHitTestReq);
505 rep.type = X_Reply;
506 rep.length = 0;
507 rep.sequenceNumber = client->sequence;
508
509 ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih);
510 or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh);
511
512 if (xp_frame_hit_test (stuff->frame_class, stuff->px,
513 stuff->py, &or, &ir, &ret) != Success)
514 {
515 return BadValue;
516 }
517
518 rep.ret = ret;
519
520 WriteToClient(client, sizeof(xAppleWMFrameHitTestReply), (char *)&rep);
521 return (client->noClientException);
522 }
523
524 static int
ProcAppleWMFrameDraw(register ClientPtr client)525 ProcAppleWMFrameDraw(
526 register ClientPtr client
527 )
528 {
529 BoxRec ir, or;
530 unsigned int title_length, title_max;
531 unsigned char *title_bytes;
532 REQUEST(xAppleWMFrameDrawReq);
533 WindowPtr pWin;
534 xp_window_id wid;
535
536 REQUEST_AT_LEAST_SIZE(xAppleWMFrameDrawReq);
537
538 if (!(pWin = SecurityLookupWindow((Drawable)stuff->window,
539 client, SecurityReadAccess))) {
540 return BadValue;
541 }
542
543 ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih);
544 or = make_box (stuff->ox, stuff->oy, stuff->ow, stuff->oh);
545
546 title_length = stuff->title_length;
547 title_max = (stuff->length << 2) - sizeof(xAppleWMFrameDrawReq);
548
549 if (title_max < title_length)
550 return BadValue;
551
552 title_bytes = (unsigned char *) &stuff[1];
553
554 wid = RootlessGetPhysicalWindow (pWin, FALSE);
555 if (wid == 0)
556 return BadWindow;
557
558 if (xp_frame_draw (wid, stuff->frame_class,
559 stuff->frame_attr, &or, &ir,
560 title_length, title_bytes) != Success) {
561 return BadValue;
562 }
563
564 return (client->noClientException);
565 }
566
567
568 /* dispatch */
569
570 static int
ProcAppleWMDispatch(register ClientPtr client)571 ProcAppleWMDispatch (
572 register ClientPtr client
573 )
574 {
575 REQUEST(xReq);
576
577 switch (stuff->data)
578 {
579 case X_AppleWMQueryVersion:
580 return ProcAppleWMQueryVersion(client);
581 }
582
583 if (!LocalClient(client))
584 return WMErrorBase + AppleWMClientNotLocal;
585
586 switch (stuff->data)
587 {
588 case X_AppleWMSelectInput:
589 return ProcAppleWMSelectInput(client);
590 case X_AppleWMDisableUpdate:
591 return ProcAppleWMDisableUpdate(client);
592 case X_AppleWMReenableUpdate:
593 return ProcAppleWMReenableUpdate(client);
594 case X_AppleWMSetWindowMenu:
595 return ProcAppleWMSetWindowMenu(client);
596 case X_AppleWMSetWindowMenuCheck:
597 return ProcAppleWMSetWindowMenuCheck(client);
598 case X_AppleWMSetFrontProcess:
599 return ProcAppleWMSetFrontProcess(client);
600 case X_AppleWMSetWindowLevel:
601 return ProcAppleWMSetWindowLevel(client);
602 case X_AppleWMSetCanQuit:
603 return ProcAppleWMSetCanQuit(client);
604 case X_AppleWMFrameGetRect:
605 return ProcAppleWMFrameGetRect(client);
606 case X_AppleWMFrameHitTest:
607 return ProcAppleWMFrameHitTest(client);
608 case X_AppleWMFrameDraw:
609 return ProcAppleWMFrameDraw(client);
610 default:
611 return BadRequest;
612 }
613 }
614
615 static void
SNotifyEvent(from,to)616 SNotifyEvent(from, to)
617 xAppleWMNotifyEvent *from, *to;
618 {
619 to->type = from->type;
620 to->kind = from->kind;
621 cpswaps (from->sequenceNumber, to->sequenceNumber);
622 cpswapl (from->time, to->time);
623 cpswapl (from->arg, to->arg);
624 }
625
626 static int
SProcAppleWMQueryVersion(register ClientPtr client)627 SProcAppleWMQueryVersion(
628 register ClientPtr client
629 )
630 {
631 register int n;
632 REQUEST(xAppleWMQueryVersionReq);
633 swaps(&stuff->length, n);
634 return ProcAppleWMQueryVersion(client);
635 }
636
637 static int
SProcAppleWMDispatch(register ClientPtr client)638 SProcAppleWMDispatch (
639 register ClientPtr client
640 )
641 {
642 REQUEST(xReq);
643
644 /* It is bound to be non-local when there is byte swapping */
645 if (!LocalClient(client))
646 return WMErrorBase + AppleWMClientNotLocal;
647
648 /* only local clients are allowed WM access */
649 switch (stuff->data)
650 {
651 case X_AppleWMQueryVersion:
652 return SProcAppleWMQueryVersion(client);
653 default:
654 return BadRequest;
655 }
656 }
657