Merge commit 'origin/gallium-0.1'
[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 minmax->ptMaxSize.x = __glutScreenWidth;
552 minmax->ptMaxSize.y = __glutScreenHeight;
553 minmax->ptMinTrackSize.x = 0;
554 minmax->ptMinTrackSize.y = 0;
555 minmax->ptMaxTrackSize.x = __glutScreenWidth +
556 GetSystemMetrics(SM_CXSIZE) * 2;
557 minmax->ptMaxTrackSize.y = __glutScreenHeight +
558 GetSystemMetrics(SM_CXSIZE) * 2 + GetSystemMetrics(SM_CYCAPTION);
559 return 0;
560
561 case WM_SIZE:
562 window = __glutGetWindow(hwnd);
563 if (window) {
564 width = LOWORD(lParam);
565 height = HIWORD(lParam);
566 if (width != window->width || height != window->height) {
567 #if 0 /* Win32 GLUT does not support overlays for now. */
568 if (window->overlay) {
569 XResizeWindow(__glutDisplay, window->overlay->win, width, height);
570 }
571 #endif
572 window->width = width;
573 window->height = height;
574 __glutSetWindow(window);
575 /* Do not execute OpenGL out of sequence with respect
576 to the SetWindowPos request! */
577 GdiFlush();
578 window->reshape(width, height);
579 window->forceReshape = FALSE;
580 /* A reshape should be considered like posting a
581 repair request. */
582 __glutPostRedisplay(window, GLUT_REPAIR_WORK);
583 }
584 }
585 return 0;
586
587 case WM_SETCURSOR:
588 /* If the cursor is not in the client area, then we want to send
589 this message to the default window procedure ('cause its
590 probably in the border or title, and we don't handle that
591 cursor. otherwise, set our cursor. Win32 makes us set the
592 cursor every time the mouse moves (DUMB!). */
593 if(LOWORD(lParam) != HTCLIENT) {
594 goto defproc;
595 }
596 window = __glutGetWindow(hwnd);
597 if (window) {
598 __glutSetCursor(window);
599 }
600 /* TODO: check out the info in DevStudio on WM_SETCURSOR in the
601 DefaultAction section. */
602 return 1;
603
604 case WM_SETFOCUS:
605 window = __glutGetWindow(hwnd);
606 if (window) {
607 window->entryState = WM_SETFOCUS;
608 if (window->entry) {
609 __glutSetWindow(window);
610 window->entry(GLUT_ENTERED);
611 /* XXX Generation of fake passive notify? See how much
612 work the X11 code does to support fake passive notify
613 callbacks. */
614 }
615 if (window->joystick && __glutCurrentWindow) {
616 if (__glutCurrentWindow->joyPollInterval > 0) {
617 MMRESULT result;
618
619 /* Because Win32 will only let one window capture the
620 joystick at a time, we must capture it when we get the
621 focus and release it when we lose the focus. */
622 result = joySetCapture(__glutCurrentWindow->win,
623 JOYSTICKID1, 0, TRUE);
624 if (result != JOYERR_NOERROR) {
625 return 0;
626 }
627 (void) joySetThreshold(JOYSTICKID1,
628 __glutCurrentWindow->joyPollInterval);
629 }
630 }
631 }
632 return 0;
633
634 case WM_KILLFOCUS:
635 window = __glutGetWindow(hwnd);
636 if (window) {
637 window->entryState = WM_KILLFOCUS;
638 if (window->entry) {
639 __glutSetWindow(window);
640 window->entry(GLUT_LEFT);
641 }
642 if (window->joystick && __glutCurrentWindow) {
643 if (__glutCurrentWindow->joyPollInterval > 0) {
644 /* Because Win32 will only let one window capture the
645 joystick at a time, we must capture it when we get the
646 focus and release it when we lose the focus. */
647 (void) joyReleaseCapture(JOYSTICKID1);
648 }
649 }
650 }
651 return 0;
652 case WM_ACTIVATE:
653 window = __glutGetWindow(hwnd);
654 /* Make sure we re-select the correct palette if needed. */
655 if (LOWORD(wParam)) {
656 PostMessage(hwnd, WM_PALETTECHANGED, 0, 0);
657 }
658 if (window) {
659 int visState;
660
661 /* HIWORD(wParam) is the minimized flag. */
662 visState = !HIWORD(wParam);
663 updateWindowState(window, visState);
664 }
665 return 0;
666
667 /* Colour Palette Management */
668 case WM_PALETTECHANGED:
669 if (hwnd == (HWND)wParam) {
670 /* Don't respond to the message that we sent! */
671 break;
672 }
673 /* fall through to WM_QUERYNEWPALETTE */
674
675 case WM_QUERYNEWPALETTE:
676 window = __glutGetWindow(hwnd);
677 if (window && window->colormap) {
678 UnrealizeObject(window->colormap->cmap);
679 SelectPalette(window->hdc, window->colormap->cmap, FALSE);
680 RealizePalette(window->hdc);
681 return TRUE;
682 }
683 return FALSE;
684
685 case MM_JOY1MOVE:
686 case MM_JOY1ZMOVE:
687 window = __glutGetWindow(hwnd);
688 if (window->joystick) {
689 JOYINFOEX jix;
690 int x, y, z;
691
692 /* Because WIN32 only supports messages for X, Y, and Z
693 translations, we must poll for the rest */
694 jix.dwSize = sizeof(jix);
695 jix.dwFlags = JOY_RETURNALL;
696 joyGetPosEx(JOYSTICKID1,&jix);
697
698 #define SCALE(v) ((int) ((v - 32767)/32.768))
699
700 /* Convert to integer for scaling. */
701 x = jix.dwXpos;
702 y = jix.dwYpos;
703 z = jix.dwZpos;
704 window->joystick(jix.dwButtons, SCALE(x), SCALE(y), SCALE(z));
705
706 return TRUE;
707 }
708 return FALSE;
709 case MM_JOY1BUTTONDOWN:
710 case MM_JOY1BUTTONUP:
711 window = __glutGetWindow(hwnd);
712 if (window->joystick) {
713 JOYINFOEX jix;
714
715 /* Because WIN32 only supports messages for X, Y, and Z
716 translations, we must poll for the rest */
717 jix.dwSize = sizeof(jix);
718 jix.dwFlags = JOY_RETURNALL;
719 joyGetPosEx(JOYSTICKID1,&jix);
720
721 return TRUE;
722 }
723 return FALSE;
724
725 #if 0
726 /* Miscellaneous messages (don't really need to enumerate them,
727 but it's good to know what you're not getting sometimes). */
728 case WM_DISPLAYCHANGE:
729 break;
730 case WM_NCHITTEST:
731 /* This event is generated by every mouse move event. */
732 goto defproc;
733 case WM_NCMOUSEMOVE:
734 goto defproc;
735 case WM_NCACTIVATE:
736 goto defproc;
737 case WM_NCPAINT:
738 goto defproc;
739 case WM_NCCALCSIZE:
740 goto defproc;
741 case WM_NCCREATE:
742 goto defproc;
743 case WM_NCDESTROY:
744 goto defproc;
745 case WM_NCLBUTTONDOWN:
746 goto defproc;
747 case WM_SETTEXT:
748 goto defproc;
749 case WM_GETTEXT:
750 goto defproc;
751 case WM_ACTIVATEAPP:
752 goto defproc;
753 case WM_GETICON:
754 goto defproc;
755 case WM_ERASEBKGND:
756 goto defproc;
757 case WM_WINDOWPOSCHANGING:
758 goto defproc;
759 case WM_WINDOWPOSCHANGED:
760 goto defproc;
761 case WM_MOUSEACTIVATE:
762 goto defproc;
763 case WM_SHOWWINDOW:
764 goto defproc;
765 case WM_MOVING:
766 goto defproc;
767 case WM_MOVE:
768 goto defproc;
769 case WM_KEYUP:
770 goto defproc;
771 case WM_CAPTURECHANGED:
772 goto defproc;
773 case WM_SYSCOMMAND:
774 goto defproc;
775 case WM_ENTERSIZEMOVE:
776 goto defproc;
777 case WM_ENTERIDLE:
778 goto defproc;
779 #endif
780
781 default:
782 goto defproc;
783 }
784
785 defproc:
786 return DefWindowProc(hwnd, msg, wParam, lParam);
787 }