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