Imported Upstream version 1.11.4
[ubuntu-omap:xserver.git] / hw / xwin / winwindowswm.c
1 /* WindowsWM extension is based on AppleWM extension */
2 /**************************************************************************
3
4 Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved.
5 Copyright (c) 2003 Torrey T. Lyons. All Rights Reserved.
6
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:
14
15 The above copyright notice and this permission notice (including the
16 next paragraph) shall be included in all copies or substantial portions
17 of the Software.
18
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.
26
27 **************************************************************************/
28
29 #ifdef HAVE_XWIN_CONFIG_H
30 #include <xwin-config.h>
31 #endif
32 #include "win.h"
33
34 #include "misc.h"
35 #include "dixstruct.h"
36 #include "extnsionst.h"
37 #include "colormapst.h"
38 #include "cursorstr.h"
39 #include "scrnintstr.h"
40 #include "servermd.h"
41 #include "swaprep.h"
42 #define _WINDOWSWM_SERVER_
43 #include <X11/extensions/windowswmstr.h>
44 #include "protocol-versions.h"
45
46 static int WMErrorBase;
47 static unsigned char WMReqCode = 0;
48 static int WMEventBase = 0;
49
50 static RESTYPE ClientType, eventResourceType; /* resource types for event masks */
51 static XID eventResource;
52
53 /* Currently selected events */
54 static unsigned int eventMask = 0;
55
56 static int WMFreeClient (pointer data, XID id);
57 static int WMFreeEvents (pointer data, XID id);
58 static void SNotifyEvent(xWindowsWMNotifyEvent *from, xWindowsWMNotifyEvent *to);
59
60 typedef struct _WMEvent *WMEventPtr;
61 typedef struct _WMEvent {
62   WMEventPtr      next;
63   ClientPtr         client;
64   XID               clientResource;
65   unsigned int    mask;
66 } WMEventRec;
67
68 static inline BoxRec
69 make_box (int x, int y, int w, int h)
70 {
71   BoxRec r;
72   r.x1 = x;
73   r.y1 = y;
74   r.x2 = x + w;
75   r.y2 = y + h;
76   return r;
77 }
78
79 static int
80 ProcWindowsWMQueryVersion(ClientPtr client)
81 {
82   xWindowsWMQueryVersionReply rep;
83   int n;
84
85   REQUEST_SIZE_MATCH(xWindowsWMQueryVersionReq);
86   rep.type = X_Reply;
87   rep.length = 0;
88   rep.sequenceNumber = client->sequence;
89   rep.majorVersion = SERVER_WINDOWSWM_MAJOR_VERSION;
90   rep.minorVersion = SERVER_WINDOWSWM_MINOR_VERSION;
91   rep.patchVersion = SERVER_WINDOWSWM_PATCH_VERSION;
92   if (client->swapped)
93     {
94       swaps(&rep.sequenceNumber, n);
95       swapl(&rep.length, n);
96     }
97   WriteToClient(client, sizeof(xWindowsWMQueryVersionReply), (char *)&rep);
98   return Success;
99 }
100
101
102 /* events */
103
104 static inline void
105 updateEventMask (WMEventPtr *pHead)
106 {
107   WMEventPtr pCur;
108
109   eventMask = 0;
110   for (pCur = *pHead; pCur != NULL; pCur = pCur->next)
111     eventMask |= pCur->mask;
112 }
113
114 /*ARGSUSED*/
115 static int
116 WMFreeClient (pointer data, XID id)
117 {
118   WMEventPtr   pEvent;
119   WMEventPtr   *pHead, pCur, pPrev;
120
121   pEvent = (WMEventPtr) data;
122   dixLookupResourceByType((pointer) &pHead, eventResource, eventResourceType,
123                                 NullClient, DixUnknownAccess);
124   if (pHead)
125     {
126       pPrev = 0;
127       for (pCur = *pHead; pCur && pCur != pEvent; pCur=pCur->next)
128         pPrev = pCur;
129       if (pCur)
130         {
131           if (pPrev)
132             pPrev->next = pEvent->next;
133           else
134             *pHead = pEvent->next;
135         }
136       updateEventMask (pHead);
137     }
138   free((pointer) pEvent);
139   return 1;
140 }
141
142 /*ARGSUSED*/
143 static int
144 WMFreeEvents (pointer data, XID id)
145 {
146   WMEventPtr   *pHead, pCur, pNext;
147   
148   pHead = (WMEventPtr *) data;
149   for (pCur = *pHead; pCur; pCur = pNext)
150     {
151       pNext = pCur->next;
152       FreeResource (pCur->clientResource, ClientType);
153       free((pointer) pCur);
154     }
155   free((pointer) pHead);
156   eventMask = 0;
157   return 1;
158 }
159
160 static int
161 ProcWindowsWMSelectInput (ClientPtr client)
162 {
163   REQUEST(xWindowsWMSelectInputReq);
164   WMEventPtr            pEvent, pNewEvent, *pHead;
165   XID                   clientResource;
166
167   REQUEST_SIZE_MATCH (xWindowsWMSelectInputReq);
168   dixLookupResourceByType((pointer) &pHead, eventResource, eventResourceType, client, DixWriteAccess);
169   if (stuff->mask != 0)
170     {
171       if (pHead)
172         {
173           /* check for existing entry. */
174           for (pEvent = *pHead; pEvent; pEvent = pEvent->next)
175             {
176               if (pEvent->client == client)
177                 {
178                   pEvent->mask = stuff->mask;
179                   updateEventMask (pHead);
180                   return Success;
181                 }
182             }
183         }
184       
185       /* build the entry */
186       pNewEvent = (WMEventPtr) malloc(sizeof (WMEventRec));
187       if (!pNewEvent)
188         return BadAlloc;
189       pNewEvent->next = 0;
190       pNewEvent->client = client;
191       pNewEvent->mask = stuff->mask;
192       /*
193        * add a resource that will be deleted when
194        * the client goes away
195        */
196       clientResource = FakeClientID (client->index);
197       pNewEvent->clientResource = clientResource;
198       if (!AddResource (clientResource, ClientType, (pointer)pNewEvent))
199         return BadAlloc;
200       /*
201        * create a resource to contain a pointer to the list
202        * of clients selecting input.  This must be indirect as
203        * the list may be arbitrarily rearranged which cannot be
204        * done through the resource database.
205        */
206       if (!pHead)
207         {
208           pHead = (WMEventPtr *) malloc(sizeof (WMEventPtr));
209           if (!pHead ||
210               !AddResource (eventResource, eventResourceType, (pointer)pHead))
211             {
212               FreeResource (clientResource, RT_NONE);
213               return BadAlloc;
214             }
215           *pHead = 0;
216         }
217       pNewEvent->next = *pHead;
218       *pHead = pNewEvent;
219       updateEventMask (pHead);
220     }
221   else if (stuff->mask == 0)
222     {
223       /* delete the interest */
224       if (pHead)
225         {
226           pNewEvent = 0;
227           for (pEvent = *pHead; pEvent; pEvent = pEvent->next)
228             {
229               if (pEvent->client == client)
230                 break;
231               pNewEvent = pEvent;
232             }
233           if (pEvent)
234             {
235               FreeResource (pEvent->clientResource, ClientType);
236               if (pNewEvent)
237                 pNewEvent->next = pEvent->next;
238               else
239                 *pHead = pEvent->next;
240               free(pEvent);
241               updateEventMask (pHead);
242             }
243         }
244     }
245   else
246     {
247       client->errorValue = stuff->mask;
248       return BadValue;
249     }
250   return Success;
251 }
252
253 /*
254  * deliver the event
255  */
256
257 void
258 winWindowsWMSendEvent (int type, unsigned int mask, int which, int arg,
259                        Window window, int x, int y, int w, int h)
260 {
261   WMEventPtr            *pHead, pEvent;
262   ClientPtr             client;
263   xWindowsWMNotifyEvent se;
264 #if CYGMULTIWINDOW_DEBUG
265   ErrorF ("winWindowsWMSendEvent %d %d %d %d,  %d %d - %d %d\n",
266           type, mask, which, arg, x, y, w, h);
267 #endif
268   dixLookupResourceByType((pointer) &pHead, eventResource, eventResourceType,
269                                 NullClient, DixUnknownAccess);
270   if (!pHead)
271     return;
272   for (pEvent = *pHead; pEvent; pEvent = pEvent->next)
273     {
274       client = pEvent->client;
275 #if CYGMULTIWINDOW_DEBUG
276       ErrorF ("winWindowsWMSendEvent - x%08x\n", (int) client);
277 #endif
278       if ((pEvent->mask & mask) == 0)
279         {
280           continue;
281         }
282 #if CYGMULTIWINDOW_DEBUG 
283       ErrorF ("winWindowsWMSendEvent - send\n");
284 #endif
285       se.type = type + WMEventBase;
286       se.kind = which;
287       se.window = window;
288       se.arg = arg;
289       se.x = x;
290       se.y = y;
291       se.w = w;
292       se.h = h;
293       se.time = currentTime.milliseconds;
294       WriteEventsToClient (client, 1, (xEvent *) &se);
295     }
296 }
297
298 /* general utility functions */
299
300 static int
301 ProcWindowsWMDisableUpdate (ClientPtr client)
302 {
303   REQUEST_SIZE_MATCH(xWindowsWMDisableUpdateReq);
304
305   //winDisableUpdate();
306
307   return Success;
308 }
309
310 static int
311 ProcWindowsWMReenableUpdate (ClientPtr client)
312 {
313   REQUEST_SIZE_MATCH(xWindowsWMReenableUpdateReq);
314
315   //winEnableUpdate(); 
316
317   return Success;
318 }
319
320
321 /* window functions */
322
323 static int
324 ProcWindowsWMSetFrontProcess (ClientPtr client)
325 {
326   REQUEST_SIZE_MATCH(xWindowsWMSetFrontProcessReq);
327   
328   //QuartzMessageMainThread(kWindowsSetFrontProcess, NULL, 0);
329   
330   return Success;
331 }
332
333
334 /* frame functions */
335
336 static int
337 ProcWindowsWMFrameGetRect (ClientPtr client)
338 {
339   xWindowsWMFrameGetRectReply rep;
340   BoxRec ir;
341   RECT rcNew;
342   REQUEST(xWindowsWMFrameGetRectReq);
343
344 #if CYGMULTIWINDOW_DEBUG
345   ErrorF ("ProcWindowsWMFrameGetRect %d %d\n",
346           (sizeof(xWindowsWMFrameGetRectReq) >> 2), (int) client->req_len);
347 #endif
348   
349   REQUEST_SIZE_MATCH(xWindowsWMFrameGetRectReq);
350   rep.type = X_Reply;
351   rep.length = 0;
352   rep.sequenceNumber = client->sequence;
353
354   ir = make_box (stuff->ix, stuff->iy, stuff->iw, stuff->ih);
355
356   if (stuff->frame_rect != 0)
357     {
358       ErrorF ("ProcWindowsWMFrameGetRect - stuff->frame_rect != 0\n");
359       return BadValue;
360     }
361
362   /* Store the origin, height, and width in a rectangle structure */
363   SetRect (&rcNew, stuff->ix, stuff->iy,
364            stuff->ix + stuff->iw, stuff->iy + stuff->ih);
365     
366 #if CYGMULTIWINDOW_DEBUG
367   ErrorF ("ProcWindowsWMFrameGetRect - %d %d %d %d\n",
368           stuff->ix, stuff->iy, stuff->ix + stuff->iw, stuff->iy + stuff->ih);
369 #endif
370
371   /*
372    * Calculate the required size of the Windows window rectangle,
373    * given the size of the Windows window client area.
374    */
375   AdjustWindowRectEx (&rcNew, stuff->frame_style, FALSE, stuff->frame_style_ex);
376   rep.x = rcNew.left;
377   rep.y = rcNew.top;
378   rep.w = rcNew.right - rcNew.left;
379   rep.h = rcNew.bottom - rcNew.top;
380 #if CYGMULTIWINDOW_DEBUG
381   ErrorF ("ProcWindowsWMFrameGetRect - %d %d %d %d\n",
382           rep.x, rep.y, rep.w, rep.h);
383 #endif
384
385   WriteToClient(client, sizeof(xWindowsWMFrameGetRectReply), (char *)&rep);
386   return Success;
387 }
388
389
390 static int
391 ProcWindowsWMFrameDraw (ClientPtr client)
392 {
393   REQUEST(xWindowsWMFrameDrawReq);
394   WindowPtr pWin;
395   win32RootlessWindowPtr pRLWinPriv;
396   RECT rcNew;
397   int nCmdShow, rc;
398   RegionRec newShape;
399
400   REQUEST_SIZE_MATCH (xWindowsWMFrameDrawReq);
401
402 #if CYGMULTIWINDOW_DEBUG
403   ErrorF ("ProcWindowsWMFrameDraw\n");
404 #endif
405   rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
406   if (rc != Success)
407       return rc;
408 #if CYGMULTIWINDOW_DEBUG
409   ErrorF ("ProcWindowsWMFrameDraw - Window found\n");
410 #endif
411
412   pRLWinPriv = (win32RootlessWindowPtr) RootlessFrameForWindow (pWin, TRUE);
413   if (pRLWinPriv == 0) return BadWindow;
414
415 #if CYGMULTIWINDOW_DEBUG
416   ErrorF ("ProcWindowsWMFrameDraw - HWND 0x%08x 0x%08x 0x%08x\n",
417           (int) pRLWinPriv->hWnd, (int) stuff->frame_style,
418           (int) stuff->frame_style_ex);
419   ErrorF ("ProcWindowsWMFrameDraw - %d %d %d %d\n",
420           stuff->ix, stuff->iy, stuff->iw, stuff->ih);
421 #endif
422
423   /* Store the origin, height, and width in a rectangle structure */
424   SetRect (&rcNew, stuff->ix, stuff->iy,
425            stuff->ix + stuff->iw, stuff->iy + stuff->ih);
426
427   /*
428    * Calculate the required size of the Windows window rectangle,
429    * given the size of the Windows window client area.
430    */
431   AdjustWindowRectEx (&rcNew, stuff->frame_style, FALSE, stuff->frame_style_ex);
432   
433   /* Set the window extended style flags */
434   if (!SetWindowLongPtr (pRLWinPriv->hWnd, GWL_EXSTYLE, stuff->frame_style_ex))
435     {
436       return BadValue;
437     }
438
439   /* Set the window standard style flags */
440   if (!SetWindowLongPtr (pRLWinPriv->hWnd, GWL_STYLE, stuff->frame_style))
441     {
442       return BadValue;
443     }
444
445   /* Flush the window style */
446   if (!SetWindowPos (pRLWinPriv->hWnd, NULL,
447                      rcNew.left, rcNew.top,
448                      rcNew.right - rcNew.left, rcNew.bottom - rcNew.top,
449                      SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE))
450     {
451       return BadValue;
452     }
453   if (!IsWindowVisible(pRLWinPriv->hWnd))
454     nCmdShow = SW_HIDE;
455   else 
456     nCmdShow = SW_SHOWNA;
457
458   ShowWindow (pRLWinPriv->hWnd, nCmdShow);
459
460   winMWExtWMUpdateIcon (pWin->drawable.id);
461
462   if (wBoundingShape(pWin) != NULL)
463     {
464       /* wBoundingShape is relative to *inner* origin of window.
465          Translate by borderWidth to get the outside-relative position. */
466       
467       RegionNull(&newShape);
468       RegionCopy(&newShape, wBoundingShape(pWin));
469       RegionTranslate(&newShape, pWin->borderWidth, pWin->borderWidth);
470       winMWExtWMReshapeFrame (pRLWinPriv, &newShape);
471       RegionUninit(&newShape);
472     }
473 #if CYGMULTIWINDOW_DEBUG
474   ErrorF ("ProcWindowsWMFrameDraw - done\n");
475 #endif
476
477   return Success;
478 }
479
480 static int
481 ProcWindowsWMFrameSetTitle(ClientPtr client)
482 {
483   unsigned int title_length, title_max;
484   char *title_bytes;
485   REQUEST(xWindowsWMFrameSetTitleReq);
486   WindowPtr pWin;
487   win32RootlessWindowPtr pRLWinPriv;
488   int rc;
489
490 #if CYGMULTIWINDOW_DEBUG
491   ErrorF ("ProcWindowsWMFrameSetTitle\n");
492 #endif
493
494   REQUEST_AT_LEAST_SIZE(xWindowsWMFrameSetTitleReq);
495
496   rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
497   if (rc != Success)
498       return rc;
499 #if CYGMULTIWINDOW_DEBUG
500   ErrorF ("ProcWindowsWMFrameSetTitle - Window found\n");
501 #endif
502
503   title_length = stuff->title_length;
504   title_max = (stuff->length << 2) - sizeof(xWindowsWMFrameSetTitleReq);
505
506   if (title_max < title_length)
507     return BadValue;
508
509 #if CYGMULTIWINDOW_DEBUG
510   ErrorF ("ProcWindowsWMFrameSetTitle - length is valid\n");
511 #endif
512
513   title_bytes = malloc (title_length+1);
514   strncpy (title_bytes, (unsigned char *) &stuff[1], title_length);
515   title_bytes[title_length] = '\0';
516
517   pRLWinPriv = (win32RootlessWindowPtr) RootlessFrameForWindow (pWin, FALSE);
518
519   if (pRLWinPriv == 0)
520     {
521       free (title_bytes);
522       return BadWindow;
523     }
524     
525   /* Flush the window style */
526   SetWindowText (pRLWinPriv->hWnd, title_bytes);
527
528   free (title_bytes);
529
530 #if CYGMULTIWINDOW_DEBUG
531   ErrorF ("ProcWindowsWMFrameSetTitle - done\n");
532 #endif
533
534   return Success;
535 }
536
537
538 /* dispatch */
539
540 static int
541 ProcWindowsWMDispatch (ClientPtr client)
542 {
543   REQUEST(xReq);
544
545   switch (stuff->data)
546     {
547     case X_WindowsWMQueryVersion:
548       return ProcWindowsWMQueryVersion(client);
549     }
550
551   if (!LocalClient(client))
552     return WMErrorBase + WindowsWMClientNotLocal;
553
554   switch (stuff->data)
555     {
556     case X_WindowsWMSelectInput:
557       return ProcWindowsWMSelectInput(client);
558     case X_WindowsWMDisableUpdate:
559       return ProcWindowsWMDisableUpdate(client);
560     case X_WindowsWMReenableUpdate:
561       return ProcWindowsWMReenableUpdate(client);
562     case X_WindowsWMSetFrontProcess:
563       return ProcWindowsWMSetFrontProcess(client);
564     case X_WindowsWMFrameGetRect:
565       return ProcWindowsWMFrameGetRect(client);
566     case X_WindowsWMFrameDraw:
567       return ProcWindowsWMFrameDraw(client);
568     case X_WindowsWMFrameSetTitle:
569       return ProcWindowsWMFrameSetTitle(client);
570     default:
571       return BadRequest;
572     }
573 }
574
575 static void
576 SNotifyEvent (xWindowsWMNotifyEvent *from, xWindowsWMNotifyEvent *to)
577 {
578   to->type = from->type;
579   to->kind = from->kind;
580   cpswaps (from->sequenceNumber, to->sequenceNumber);
581   cpswapl (from->window, to->window);
582   cpswapl (from->time, to->time);
583   cpswapl (from->arg, to->arg);
584 }
585
586 static int
587 SProcWindowsWMQueryVersion (ClientPtr client)
588 {
589   int n;
590   REQUEST(xWindowsWMQueryVersionReq);
591   swaps(&stuff->length, n);
592   return ProcWindowsWMQueryVersion(client);
593 }
594
595 static int
596 SProcWindowsWMDispatch (ClientPtr client)
597 {
598   REQUEST(xReq);
599
600   /* It is bound to be non-local when there is byte swapping */
601   if (!LocalClient(client))
602     return WMErrorBase + WindowsWMClientNotLocal;
603
604   /* only local clients are allowed WM access */
605   switch (stuff->data)
606     {
607     case X_WindowsWMQueryVersion:
608       return SProcWindowsWMQueryVersion(client);
609     default:
610       return BadRequest;
611     }
612 }
613
614 void
615 winWindowsWMExtensionInit (void)
616 {
617   ExtensionEntry* extEntry;
618
619   ClientType = CreateNewResourceType(WMFreeClient, "WMClient");
620   eventResourceType = CreateNewResourceType(WMFreeEvents, "WMEvent");
621   eventResource = FakeClientID(0);
622
623   if (ClientType && eventResourceType &&
624       (extEntry = AddExtension(WINDOWSWMNAME,
625                                WindowsWMNumberEvents,
626                                WindowsWMNumberErrors,
627                                ProcWindowsWMDispatch,
628                                SProcWindowsWMDispatch,
629                                NULL,
630                                StandardMinorOpcode)))
631     {
632       size_t i;
633       WMReqCode = (unsigned char)extEntry->base;
634       WMErrorBase = extEntry->errorBase;
635       WMEventBase = extEntry->eventBase;
636       for (i=0; i < WindowsWMNumberEvents; i++)
637         EventSwapVector[WMEventBase + i] = (EventSwapPtr) SNotifyEvent;
638     }
639 }