r300/compiler: Handle loops in rc_get_readers()
[mesa.git] / src / glut / glx / win32_winproc.c
1
2 /* Copyright (c) Nate Robins, 1997. */
3 /* portions Copyright (c) Mark Kilgard, 1997, 1998. */
4
5 /* This program is freely distributable without licensing fees
6 and is provided without guarantee or warrantee expressed or
7 implied. This program is -not- in the public domain. */
8
9
10 #include "glutint.h"
11 #include <sys/timeb.h>
12 #ifdef __MINGW32__
13 #include <ctype.h>
14 #endif
15
16 #if defined(_WIN32) && !defined(__CYGWIN32__)
17 #include <mmsystem.h> /* Win32 Multimedia API header. */
18 #endif
19
20 extern unsigned __glutMenuButton;
21 extern GLUTidleCB __glutIdleFunc;
22 extern GLUTtimer *__glutTimerList;
23 extern GLUTmenuItem *__glutGetUniqueMenuItem(GLUTmenu * menu, UINT unique);
24 static HMENU __glutHMenu;
25
26 static void
27 updateWindowState(GLUTwindow *window, int visState)
28 {
29 GLUTwindow* child;
30
31 /* XXX shownState and visState are the same in Win32. */
32 window->shownState = visState;
33 if (visState != window->visState) {
34 if (window->windowStatus) {
35 window->visState = visState;
36 __glutSetWindow(window);
37 window->windowStatus(visState);
38 }
39 }
40 /* Since Win32 only sends an activate for the toplevel window,
41 update the visibility for all the child windows. */
42 child = window->children;
43 while (child) {
44 updateWindowState(child, visState);
45 child = child->siblings;
46 }
47 }
48
49 LONG WINAPI
50 __glutWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
51 {
52 POINT point; /* Point structure. */
53 PAINTSTRUCT ps; /* Paint structure. */
54 LPMINMAXINFO minmax; /* Minimum/maximum info structure. */
55 GLUTwindow* window; /* GLUT window associated with message. */
56 GLUTmenu* menu; /* GLUT menu associated with message. */
57 int x, y, width, height, key;
58 int button = -1;
59
60 switch(msg) {
61 case WM_CREATE:
62 return 0;
63 case WM_CLOSE:
64 if (__glutExitFunc) {
65 __glutExitFunc(0);
66 }
67 exit(0);
68 break;
69 #if 0
70 case WM_DESTROY:
71 /* XXX NVidia's NT OpenGL can have problems closing down
72 its OpenGL internal data structures if we just allow
73 the process to terminate without unbinding and deleting
74 the windows context. Apparently, DirectDraw unloads
75 before OPENGL32.DLL in the close down sequence, but
76 NVidia's NT OpenGL needs DirectDraw to close down its
77 data structures. */
78 window = __glutGetWindow(hwnd);
79 if (window) {
80 if (window->ctx) {
81 wglMakeCurrent(NULL, NULL);
82 wglDeleteContext(window->ctx);
83 }
84 }
85 return 0;
86 #endif
87 case WM_PAINT:
88 window = __glutGetWindow(hwnd);
89 if (window) {
90 BeginPaint(hwnd, &ps); /* Must have this for some Win32 reason. */
91 EndPaint(hwnd, &ps);
92 if (window->win == hwnd) {
93 __glutPostRedisplay(window, GLUT_REPAIR_WORK);
94 } else if (window->overlay && window->overlay->win == hwnd) {
95 __glutPostRedisplay(window, GLUT_OVERLAY_REPAIR_WORK);
96 }
97 }
98 return 0;
99
100 case WM_SYSKEYUP:
101 case WM_KEYUP:
102 window = __glutGetWindow(hwnd);
103 if (!window) {
104 break;
105 }
106 /* Win32 is dumb and sends these messages only to the parent
107 window. Therefore, find out if we're in a child window and
108 call the child windows keyboard callback if we are. */
109 if (window->parent) {
110 GetCursorPos(&point);
111 ScreenToClient(hwnd, &point);
112 hwnd = ChildWindowFromPoint(hwnd, point);
113 window = __glutGetWindow(hwnd);
114 }
115 if (window->specialUp || window->keyboardUp) {
116 GetCursorPos(&point);
117 ScreenToClient(window->win, &point);
118 __glutSetWindow(window);
119 __glutModifierMask = 0;
120 if (GetKeyState(VK_SHIFT) < 0) /* < 0 = high order bit is on */
121 __glutModifierMask |= ShiftMask;
122 if (GetKeyState(VK_SHIFT) < 0) /* < 0 = high order bit is on */
123 __glutModifierMask |= ControlMask;
124 if (GetKeyState(VK_MENU) < 0)
125 __glutModifierMask |= Mod1Mask;
126 switch (wParam) {
127 /* *INDENT-OFF* */
128 case VK_F1: key = GLUT_KEY_F1; break;
129 case VK_F2: key = GLUT_KEY_F2; break;
130 case VK_F3: key = GLUT_KEY_F3; break;
131 case VK_F4: key = GLUT_KEY_F4; break;
132 case VK_F5: key = GLUT_KEY_F5; break;
133 case VK_F6: key = GLUT_KEY_F6; break;
134 case VK_F7: key = GLUT_KEY_F7; break;
135 case VK_F8: key = GLUT_KEY_F8; break;
136 case VK_F9: key = GLUT_KEY_F9; break;
137 case VK_F10: key = GLUT_KEY_F10; break;
138 case VK_F11: key = GLUT_KEY_F11; break;
139 case VK_F12: key = GLUT_KEY_F12; break;
140 case VK_LEFT: key = GLUT_KEY_LEFT; break;
141 case VK_UP: key = GLUT_KEY_UP; break;
142 case VK_RIGHT: key = GLUT_KEY_RIGHT; break;
143 case VK_DOWN: key = GLUT_KEY_DOWN; break;
144 case VK_PRIOR: key = GLUT_KEY_PAGE_UP; break;
145 case VK_NEXT: key = GLUT_KEY_PAGE_DOWN; break;
146 case VK_HOME: key = GLUT_KEY_HOME; break;
147 case VK_END: key = GLUT_KEY_END; break;
148 case VK_INSERT: key = GLUT_KEY_INSERT; break;
149 case VK_DELETE:
150 /* Delete is an ASCII character. */
151 if (window->keyboardUp) {
152 window->keyboardUp((unsigned char) 127, point.x, point.y);
153 }
154 return 0;
155 /* *INDENT-ON* */
156 default:
157 if (window->keyboardUp) {
158 key = MapVirtualKey(wParam, 2); /* Map to ASCII. */
159 if (isascii(key) && (key != 0)) {
160
161 /* XXX Attempt to determine modified ASCII character
162 is quite incomplete. Digits, symbols, CapsLock,
163 Ctrl, and numeric keypad are all ignored. Fix this. */
164
165 if (!(__glutModifierMask & ShiftMask))
166 key = tolower(key);
167 window->keyboardUp((unsigned char) key, point.x, point.y);
168 }
169 }
170 __glutModifierMask = (unsigned int) ~0;
171 return 0;
172 }
173 if (window->specialUp) {
174 window->specialUp(key, point.x, point.y);
175 }
176 __glutModifierMask = (unsigned int) ~0;
177 }
178 return 0;
179
180 case WM_SYSCHAR:
181 case WM_CHAR:
182 window = __glutGetWindow(hwnd);
183 if (!window) {
184 break;
185 }
186
187 /* Bit 30 of lParam is set if key already held down. If
188 we are ignoring auto repeated key strokes for the window, bail. */
189 if (window->ignoreKeyRepeat && (lParam & (1 << 30)) ) {
190 break;
191 }
192
193 /* Win32 is dumb and sends these messages only to the parent
194 window. Therefore, find out if we're in a child window and
195 call the child windows keyboard callback if we are. */
196 if (window->parent) {
197 GetCursorPos(&point);
198 ScreenToClient(hwnd, &point);
199 hwnd = ChildWindowFromPoint(hwnd, point);
200 window = __glutGetWindow(hwnd);
201 }
202 if (window->keyboard) {
203 GetCursorPos(&point);
204 ScreenToClient(window->win, &point);
205 __glutSetWindow(window);
206 __glutModifierMask = 0;
207 if (GetKeyState(VK_SHIFT) < 0) /* < 0 = high order bit is on */
208 __glutModifierMask |= ShiftMask;
209 if (GetKeyState(VK_CONTROL) < 0)
210 __glutModifierMask |= ControlMask;
211 if (GetKeyState(VK_MENU) < 0)
212 __glutModifierMask |= Mod1Mask;
213 window->keyboard((unsigned char)wParam, point.x, point.y);
214 __glutModifierMask = (unsigned int) ~0;
215 }
216 return 0;
217
218 case WM_SYSKEYDOWN:
219 case WM_KEYDOWN:
220 window = __glutGetWindow(hwnd);
221 if (!window) {
222 break;
223 }
224
225 /* Bit 30 of lParam is set if key already held down. If
226 we are ignoring auto repeated key strokes for the window, bail. */
227 if (window->ignoreKeyRepeat && (lParam & (1 << 30)) ) {
228 break;
229 }
230
231 /* Win32 is dumb and sends these messages only to the parent
232 window. Therefore, find out if we're in a child window and
233 call the child windows keyboard callback if we are. */
234 if (window->parent) {
235 GetCursorPos(&point);
236 ScreenToClient(hwnd, &point);
237 hwnd = ChildWindowFromPoint(hwnd, point);
238 window = __glutGetWindow(hwnd);
239 }
240 if (window->special) {
241 switch (wParam) {
242 /* *INDENT-OFF* */
243 /* function keys */
244 case VK_F1: key = GLUT_KEY_F1; break;
245 case VK_F2: key = GLUT_KEY_F2; break;
246 case VK_F3: key = GLUT_KEY_F3; break;
247 case VK_F4: key = GLUT_KEY_F4; break;
248 case VK_F5: key = GLUT_KEY_F5; break;
249 case VK_F6: key = GLUT_KEY_F6; break;
250 case VK_F7: key = GLUT_KEY_F7; break;
251 case VK_F8: key = GLUT_KEY_F8; break;
252 case VK_F9: key = GLUT_KEY_F9; break;
253 case VK_F10: key = GLUT_KEY_F10; break;
254 case VK_F11: key = GLUT_KEY_F11; break;
255 case VK_F12: key = GLUT_KEY_F12; break;
256 /* directional keys */
257 case VK_LEFT: key = GLUT_KEY_LEFT; break;
258 case VK_UP: key = GLUT_KEY_UP; break;
259 case VK_RIGHT: key = GLUT_KEY_RIGHT; break;
260 case VK_DOWN: key = GLUT_KEY_DOWN; break;
261 /* *INDENT-ON* */
262
263 case VK_PRIOR:
264 /* VK_PRIOR is Win32's Page Up */
265 key = GLUT_KEY_PAGE_UP;
266 break;
267 case VK_NEXT:
268 /* VK_NEXT is Win32's Page Down */
269 key = GLUT_KEY_PAGE_DOWN;
270 break;
271 case VK_HOME:
272 key = GLUT_KEY_HOME;
273 break;
274 case VK_END:
275 key = GLUT_KEY_END;
276 break;
277 case VK_INSERT:
278 key = GLUT_KEY_INSERT;
279 break;
280 case VK_DELETE:
281 goto handleDelete;
282 default:
283 goto defproc;
284 }
285 GetCursorPos(&point);
286 ScreenToClient(window->win, &point);
287 __glutSetWindow(window);
288 __glutModifierMask = 0;
289 if (GetKeyState(VK_SHIFT) < 0) /* < 0 = high order bit is on */
290 __glutModifierMask |= ShiftMask;
291 if (GetKeyState(VK_CONTROL) < 0)
292 __glutModifierMask |= ControlMask;
293 if (GetKeyState(VK_MENU) < 0)
294 __glutModifierMask |= Mod1Mask;
295 window->special(key, point.x, point.y);
296 __glutModifierMask = (unsigned int) ~0;
297 } else if (window->keyboard) {
298 /* Specially handle any keys that match ASCII values but
299 do not generate Windows WM_SYSCHAR or WM_CHAR messages. */
300 switch (wParam) {
301 case VK_DELETE:
302 handleDelete:
303 /* Delete is an ASCII character. */
304 GetCursorPos(&point);
305 ScreenToClient(window->win, &point);
306 __glutSetWindow(window);
307 __glutModifierMask = 0;
308 if (GetKeyState(VK_SHIFT) < 0) /* < 0 = high order bit is on */
309 __glutModifierMask |= ShiftMask;
310 if (GetKeyState(VK_CONTROL) < 0)
311 __glutModifierMask |= ControlMask;
312 if (GetKeyState(VK_MENU) < 0)
313 __glutModifierMask |= Mod1Mask;
314 window->keyboard((unsigned char) 127, point.x, point.y);
315 __glutModifierMask = (unsigned int) ~0;
316 return 0;
317 default:
318 /* Let the following WM_SYSCHAR or WM_CHAR message generate
319 the keyboard callback. */
320 break;
321 }
322 }
323 return 0;
324
325 case WM_LBUTTONDOWN:
326 button = GLUT_LEFT_BUTTON;
327 case WM_MBUTTONDOWN:
328 if (button < 0)
329 button = GLUT_MIDDLE_BUTTON;
330 case WM_RBUTTONDOWN:
331 if (button < 0)
332 button = GLUT_RIGHT_BUTTON;
333
334 /* finish the menu if we get a button down message (user must have
335 cancelled the menu). */
336 if (__glutMappedMenu) {
337 /* TODO: take this out once the menu on middle mouse stuff works
338 properly. */
339 if (button == GLUT_MIDDLE_BUTTON)
340 return 0;
341 GetCursorPos(&point);
342 ScreenToClient(hwnd, &point);
343 __glutItemSelected = NULL;
344 __glutFinishMenu(hwnd, point.x, point.y);
345 return 0;
346 }
347
348 /* set the capture so we can get mouse events outside the window */
349 SetCapture(hwnd);
350
351 /* Win32 doesn't return the same numbers as X does when the mouse
352 goes beyond the upper or left side of the window. roll the
353 Win32's 0..2^16 pointer co-ord range to 0 +/- 2^15. */
354 x = LOWORD(lParam);
355 y = HIWORD(lParam);
356 if(x & 1 << 15) x -= (1 << 16);
357 if(y & 1 << 15) y -= (1 << 16);
358
359 window = __glutGetWindow(hwnd);
360 if (window) {
361 menu = __glutGetMenuByNum(window->menu[button]);
362 if (menu) {
363 point.x = LOWORD(lParam); point.y = HIWORD(lParam);
364 ClientToScreen(window->win, &point);
365 __glutMenuButton = button == GLUT_RIGHT_BUTTON ? TPM_RIGHTBUTTON :
366 button == GLUT_LEFT_BUTTON ? TPM_LEFTBUTTON :
367 0x0001;
368 __glutStartMenu(menu, window, point.x, point.y, x, y);
369 } else if (window->mouse) {
370
371 __glutSetWindow(window);
372 __glutModifierMask = 0;
373 if (GetKeyState(VK_SHIFT) < 0) /* < 0 = high order bit is on. */
374 __glutModifierMask |= ShiftMask;
375 if (GetKeyState(VK_CONTROL) < 0)
376 __glutModifierMask |= ControlMask;
377 if (GetKeyState(VK_MENU) < 0)
378 __glutModifierMask |= Mod1Mask;
379 window->mouse(button, GLUT_DOWN, x, y);
380 __glutModifierMask = (unsigned int)~0;
381 } else {
382 /* Stray mouse events. Ignore. */
383 }
384 }
385 return 0;
386
387 case WM_LBUTTONUP:
388 button = GLUT_LEFT_BUTTON;
389 case WM_MBUTTONUP:
390 if (button < 0)
391 button = GLUT_MIDDLE_BUTTON;
392 case WM_RBUTTONUP:
393 if (button < 0)
394 button = GLUT_RIGHT_BUTTON;
395
396 /* Bail out if we're processing a menu. */
397 if (__glutMappedMenu) {
398 GetCursorPos(&point);
399 ScreenToClient(hwnd, &point);
400 /* if we're getting the middle button up signal, then something
401 on the menu was selected. */
402 if (button == GLUT_MIDDLE_BUTTON) {
403 return 0;
404 /* For some reason, the code below always returns -1 even
405 though the point IS IN THE ITEM! Therefore, just bail out if
406 we get a middle mouse up. The user must select using the
407 left mouse button. Stupid Win32. */
408 #if 0
409 int item = MenuItemFromPoint(hwnd, __glutHMenu, point);
410 if (item != -1)
411 __glutItemSelected = (GLUTmenuItem*)GetMenuItemID(__glutHMenu, item);
412 else
413 __glutItemSelected = NULL;
414 __glutFinishMenu(hwnd, point.x, point.y);
415 #endif
416 } else {
417 __glutItemSelected = NULL;
418 __glutFinishMenu(hwnd, point.x, point.y);
419 }
420 return 0;
421 }
422
423 /* Release the mouse capture. */
424 ReleaseCapture();
425
426 window = __glutGetWindow(hwnd);
427 if (window && window->mouse) {
428 /* Win32 doesn't return the same numbers as X does when the
429 mouse goes beyond the upper or left side of the window. roll
430 the Win32's 0..2^16 pointer co-ord range to 0 +/- 2^15. */
431 x = LOWORD(lParam);
432 y = HIWORD(lParam);
433 if(x & 1 << 15) x -= (1 << 16);
434 if(y & 1 << 15) y -= (1 << 16);
435
436 __glutSetWindow(window);
437 __glutModifierMask = 0;
438 if (GetKeyState(VK_SHIFT) < 0) /* < 0 = high order bit is on */
439 __glutModifierMask |= ShiftMask;
440 if (GetKeyState(VK_CONTROL) < 0)
441 __glutModifierMask |= ControlMask;
442 if (GetKeyState(VK_MENU) < 0)
443 __glutModifierMask |= Mod1Mask;
444 window->mouse(button, GLUT_UP, x, y);
445 __glutModifierMask = (unsigned int)~0;
446 } else {
447 /* Window might have been destroyed and all the
448 events for the window may not yet be received. */
449 }
450 return 0;
451
452 case WM_ENTERMENULOOP:
453 /* KLUDGE: create a timer that fires every 100 ms when we start a
454 menu so that we can still process the idle & timer events (that
455 way, the timers will fire during a menu pick and so will the
456 idle func. */
457 SetTimer(hwnd, 1, 1, NULL);
458 return 0;
459
460 case WM_TIMER:
461 #if 0
462 /* If the timer id is 2, then this is the timer that is set up in
463 the main glut message processing loop, and we don't want to do
464 anything but acknowledge that we got it. It is used to prevent
465 CPU spiking when an idle function is installed. */
466 if (wParam == 2)
467 return 0;
468 #endif
469
470 /* only worry about the idle function and the timeouts, since
471 these are the only events we expect to process during
472 processing of a menu. */
473 /* we no longer process the idle functions (as outlined in the
474 README), since drawing can't be done until the menu has
475 finished...it's pretty lame when the animation goes on, but
476 doesn't update, so you get this weird jerkiness. */
477 #if 0
478 if (__glutIdleFunc)
479 __glutIdleFunc();
480 #endif
481 if (__glutTimerList)
482 handleTimeouts();
483 return 0;
484
485 case WM_EXITMENULOOP:
486 /* nuke the above created timer...we don't need it anymore, since
487 the menu is gone now. */
488 KillTimer(hwnd, 1);
489 return 0;
490
491 case WM_MENUSELECT:
492 if (lParam != 0)
493 __glutHMenu = (HMENU)lParam;
494 return 0;
495
496 case WM_COMMAND:
497 if (__glutMappedMenu) {
498 if (GetSubMenu(__glutHMenu, LOWORD(wParam)))
499 __glutItemSelected = NULL;
500 else
501 __glutItemSelected =
502 __glutGetUniqueMenuItem(__glutMappedMenu, LOWORD(wParam));
503 GetCursorPos(&point);
504 ScreenToClient(hwnd, &point);
505 __glutFinishMenu(hwnd, point.x, point.y);
506 }
507 return 0;
508
509 case WM_MOUSEMOVE:
510 if (!__glutMappedMenu) {
511 window = __glutGetWindow(hwnd);
512 if (window) {
513 /* If motion function registered _and_ buttons held *
514 down, call motion function... */
515 x = LOWORD(lParam);
516 y = HIWORD(lParam);
517
518 /* Win32 doesn't return the same numbers as X does when the
519 mouse goes beyond the upper or left side of the window.
520 roll the Win32's 0..2^16 pointer co-ord range to 0..+/-2^15. */
521 if(x & 1 << 15) x -= (1 << 16);
522 if(y & 1 << 15) y -= (1 << 16);
523
524 if (window->motion && wParam &
525 (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) {
526 __glutSetWindow(window);
527 window->motion(x, y);
528 }
529 /* If passive motion function registered _and_
530 buttons not held down, call passive motion
531 function... */
532 else if (window->passive &&
533 ((wParam &
534 (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) ==
535 0)) {
536 __glutSetWindow(window);
537 window->passive(x, y);
538 }
539 }
540 } else {
541 /* Motion events are thrown away when a pop up menu is
542 active. */
543 }
544 return 0;
545
546 case WM_GETMINMAXINFO:
547 /* this voodoo is brought to you by Win32 (again). It allows the
548 window to be bigger than the screen, and smaller than 100x100
549 (although it doesn't seem to help the y minimum). */
550 minmax = (LPMINMAXINFO)lParam;
551 #if 0
552 /* These two lines are disabled to fix incorrect handling of
553 * window maximization on Vista. See bug 23182.
554 */
555 minmax->ptMaxSize.x = __glutScreenWidth;
556 minmax->ptMaxSize.y = __glutScreenHeight;
557 #endif
558 minmax->ptMinTrackSize.x = 0;
559 minmax->ptMinTrackSize.y = 0;
560 minmax->ptMaxTrackSize.x = __glutScreenWidth +
561 GetSystemMetrics(SM_CXSIZE) * 2;
562 minmax->ptMaxTrackSize.y = __glutScreenHeight +
563 GetSystemMetrics(SM_CXSIZE) * 2 + GetSystemMetrics(SM_CYCAPTION);
564 return 0;
565
566 case WM_SIZE:
567 window = __glutGetWindow(hwnd);
568 if (window) {
569 width = LOWORD(lParam);
570 height = HIWORD(lParam);
571 if (width != window->width || height != window->height) {
572 #if 0 /* Win32 GLUT does not support overlays for now. */
573 if (window->overlay) {
574 XResizeWindow(__glutDisplay, window->overlay->win, width, height);
575 }
576 #endif
577 window->width = width;
578 window->height = height;
579 __glutSetWindow(window);
580 /* Do not execute OpenGL out of sequence with respect
581 to the SetWindowPos request! */
582 GdiFlush();
583 window->reshape(width, height);
584 window->forceReshape = FALSE;
585 /* A reshape should be considered like posting a
586 repair request. */
587 __glutPostRedisplay(window, GLUT_REPAIR_WORK);
588 }
589 }
590 return 0;
591
592 case WM_SETCURSOR:
593 /* If the cursor is not in the client area, then we want to send
594 this message to the default window procedure ('cause its
595 probably in the border or title, and we don't handle that
596 cursor. otherwise, set our cursor. Win32 makes us set the
597 cursor every time the mouse moves (DUMB!). */
598 if(LOWORD(lParam) != HTCLIENT) {
599 goto defproc;
600 }
601 window = __glutGetWindow(hwnd);
602 if (window) {
603 __glutSetCursor(window);
604 }
605 /* TODO: check out the info in DevStudio on WM_SETCURSOR in the
606 DefaultAction section. */
607 return 1;
608
609 case WM_SETFOCUS:
610 window = __glutGetWindow(hwnd);
611 if (window) {
612 window->entryState = WM_SETFOCUS;
613 if (window->entry) {
614 __glutSetWindow(window);
615 window->entry(GLUT_ENTERED);
616 /* XXX Generation of fake passive notify? See how much
617 work the X11 code does to support fake passive notify
618 callbacks. */
619 }
620 if (window->joystick && __glutCurrentWindow) {
621 if (__glutCurrentWindow->joyPollInterval > 0) {
622 MMRESULT result;
623
624 /* Because Win32 will only let one window capture the
625 joystick at a time, we must capture it when we get the
626 focus and release it when we lose the focus. */
627 result = joySetCapture(__glutCurrentWindow->win,
628 JOYSTICKID1, 0, TRUE);
629 if (result != JOYERR_NOERROR) {
630 return 0;
631 }
632 (void) joySetThreshold(JOYSTICKID1,
633 __glutCurrentWindow->joyPollInterval);
634 }
635 }
636 }
637 return 0;
638
639 case WM_KILLFOCUS:
640 window = __glutGetWindow(hwnd);
641 if (window) {
642 window->entryState = WM_KILLFOCUS;
643 if (window->entry) {
644 __glutSetWindow(window);
645 window->entry(GLUT_LEFT);
646 }
647 if (window->joystick && __glutCurrentWindow) {
648 if (__glutCurrentWindow->joyPollInterval > 0) {
649 /* Because Win32 will only let one window capture the
650 joystick at a time, we must capture it when we get the
651 focus and release it when we lose the focus. */
652 (void) joyReleaseCapture(JOYSTICKID1);
653 }
654 }
655 }
656 return 0;
657 case WM_ACTIVATE:
658 window = __glutGetWindow(hwnd);
659 /* Make sure we re-select the correct palette if needed. */
660 if (LOWORD(wParam)) {
661 PostMessage(hwnd, WM_PALETTECHANGED, 0, 0);
662 }
663 if (window) {
664 int visState;
665
666 /* HIWORD(wParam) is the minimized flag. */
667 visState = !HIWORD(wParam);
668 updateWindowState(window, visState);
669 }
670 return 0;
671
672 /* Colour Palette Management */
673 case WM_PALETTECHANGED:
674 if (hwnd == (HWND)wParam) {
675 /* Don't respond to the message that we sent! */
676 break;
677 }
678 /* fall through to WM_QUERYNEWPALETTE */
679
680 case WM_QUERYNEWPALETTE:
681 window = __glutGetWindow(hwnd);
682 if (window && window->colormap) {
683 UnrealizeObject(window->colormap->cmap);
684 SelectPalette(window->hdc, window->colormap->cmap, FALSE);
685 RealizePalette(window->hdc);
686 return TRUE;
687 }
688 return FALSE;
689
690 case MM_JOY1MOVE:
691 case MM_JOY1ZMOVE:
692 window = __glutGetWindow(hwnd);
693 if (window->joystick) {
694 JOYINFOEX jix;
695 int x, y, z;
696
697 /* Because WIN32 only supports messages for X, Y, and Z
698 translations, we must poll for the rest */
699 jix.dwSize = sizeof(jix);
700 jix.dwFlags = JOY_RETURNALL;
701 joyGetPosEx(JOYSTICKID1,&jix);
702
703 #define SCALE(v) ((int) ((v - 32767)/32.768))
704
705 /* Convert to integer for scaling. */
706 x = jix.dwXpos;
707 y = jix.dwYpos;
708 z = jix.dwZpos;
709 window->joystick(jix.dwButtons, SCALE(x), SCALE(y), SCALE(z));
710
711 return TRUE;
712 }
713 return FALSE;
714 case MM_JOY1BUTTONDOWN:
715 case MM_JOY1BUTTONUP:
716 window = __glutGetWindow(hwnd);
717 if (window->joystick) {
718 JOYINFOEX jix;
719
720 /* Because WIN32 only supports messages for X, Y, and Z
721 translations, we must poll for the rest */
722 jix.dwSize = sizeof(jix);
723 jix.dwFlags = JOY_RETURNALL;
724 joyGetPosEx(JOYSTICKID1,&jix);
725
726 return TRUE;
727 }
728 return FALSE;
729
730 #if 0
731 /* Miscellaneous messages (don't really need to enumerate them,
732 but it's good to know what you're not getting sometimes). */
733 case WM_DISPLAYCHANGE:
734 break;
735 case WM_NCHITTEST:
736 /* This event is generated by every mouse move event. */
737 goto defproc;
738 case WM_NCMOUSEMOVE:
739 goto defproc;
740 case WM_NCACTIVATE:
741 goto defproc;
742 case WM_NCPAINT:
743 goto defproc;
744 case WM_NCCALCSIZE:
745 goto defproc;
746 case WM_NCCREATE:
747 goto defproc;
748 case WM_NCDESTROY:
749 goto defproc;
750 case WM_NCLBUTTONDOWN:
751 goto defproc;
752 case WM_SETTEXT:
753 goto defproc;
754 case WM_GETTEXT:
755 goto defproc;
756 case WM_ACTIVATEAPP:
757 goto defproc;
758 case WM_GETICON:
759 goto defproc;
760 case WM_ERASEBKGND:
761 goto defproc;
762 case WM_WINDOWPOSCHANGING:
763 goto defproc;
764 case WM_WINDOWPOSCHANGED:
765 goto defproc;
766 case WM_MOUSEACTIVATE:
767 goto defproc;
768 case WM_SHOWWINDOW:
769 goto defproc;
770 case WM_MOVING:
771 goto defproc;
772 case WM_MOVE:
773 goto defproc;
774 case WM_KEYUP:
775 goto defproc;
776 case WM_CAPTURECHANGED:
777 goto defproc;
778 case WM_SYSCOMMAND:
779 goto defproc;
780 case WM_ENTERSIZEMOVE:
781 goto defproc;
782 case WM_ENTERIDLE:
783 goto defproc;
784 #endif
785
786 default:
787 goto defproc;
788 }
789
790 defproc:
791 return DefWindowProc(hwnd, msg, wParam, lParam);
792 }