Commit | Line | Data |
---|---|---|
a09e091a JB |
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, | |
59 | xWindowsWMNotifyEvent * to); | |
60 | ||
61 | typedef struct _WMEvent *WMEventPtr; | |
62 | typedef struct _WMEvent { | |
63 | WMEventPtr next; | |
64 | ClientPtr client; | |
65 | XID clientResource; | |
66 | unsigned int mask; | |
67 | } WMEventRec; | |
68 | ||
69 | static int | |
70 | ProcWindowsWMQueryVersion(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 | ||
91 | static inline void | |
92 | updateEventMask(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 | |
102 | WMFreeClient(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 | |
127 | WMFreeEvents(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 | ||
142 | static int | |
143 | ProcWindowsWMSelectInput(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 | ||
230 | void | |
231 | winWindowsWMSendEvent(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 | ||
272 | static int | |
273 | ProcWindowsWMDisableUpdate(ClientPtr client) | |
274 | { | |
275 | REQUEST_SIZE_MATCH(xWindowsWMDisableUpdateReq); | |
276 | ||
277 | //winDisableUpdate(); | |
278 | ||
279 | return Success; | |
280 | } | |
281 | ||
282 | static int | |
283 | ProcWindowsWMReenableUpdate(ClientPtr client) | |
284 | { | |
285 | REQUEST_SIZE_MATCH(xWindowsWMReenableUpdateReq); | |
286 | ||
287 | //winEnableUpdate(); | |
288 | ||
289 | return Success; | |
290 | } | |
291 | ||
292 | /* window functions */ | |
293 | ||
294 | static int | |
295 | ProcWindowsWMSetFrontProcess(ClientPtr client) | |
296 | { | |
297 | REQUEST_SIZE_MATCH(xWindowsWMSetFrontProcessReq); | |
298 | ||
299 | //QuartzMessageMainThread(kWindowsSetFrontProcess, NULL, 0); | |
300 | ||
301 | return Success; | |
302 | } | |
303 | ||
304 | /* frame functions */ | |
305 | ||
306 | static int | |
307 | ProcWindowsWMFrameGetRect(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 | ||
357 | static int | |
358 | ProcWindowsWMFrameDraw(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 | ||
443 | static int | |
444 | ProcWindowsWMFrameSetTitle(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 | ||
502 | static int | |
503 | ProcWindowsWMDispatch(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 | ||
535 | static void | |
536 | SNotifyEvent(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 | ||
546 | static int | |
547 | SProcWindowsWMQueryVersion(ClientPtr client) | |
548 | { | |
549 | REQUEST(xWindowsWMQueryVersionReq); | |
550 | swaps(&stuff->length); | |
551 | return ProcWindowsWMQueryVersion(client); | |
552 | } | |
553 | ||
554 | static int | |
555 | SProcWindowsWMDispatch(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 | ||
572 | void | |
573 | winWindowsWMExtensionInit(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 | } |