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