6 #include "GL/os2mesa.h"
10 #include <mmioos2.h> /* It is from MMPM toolkit */
15 #include "os2mesadef.h"
23 extern unsigned __glutMenuButton
;
24 extern GLUTidleCB __glutIdleFunc
;
25 extern GLUTtimer
*__glutTimerList
;
26 extern void handleTimeouts(void);
27 extern GLUTmenuItem
*__glutGetUniqueMenuItem(GLUTmenu
* menu
, int unique
);
28 static HMENU __glutHMenu
;
32 extern void _mesa_ResizeBuffersMESA( void );
35 MRESULT EXPENTRY
GlutWindowProc( HWND hwnd
, ULONG msg
, MPARAM mp1
, MPARAM mp2
);
36 MRESULT EXPENTRY
GlutWindowChildProc( HWND hwnd
, ULONG msg
, MPARAM mp1
, MPARAM mp2
);
37 void updateWindowState(GLUTwindow
*window
, int visState
);
39 volatile extern HAB hab
; /* PM anchor block handle */
40 volatile extern HPS hpsCurrent
;
45 MRESULT EXPENTRY
GlutWindowChildProc( HWND hwnd
, ULONG msg
, MPARAM mp1
, MPARAM mp2
)
47 rc
= GlutWindowProc(hwnd
, msg
, mp1
, mp2
);
51 MRESULT EXPENTRY
GlutWindowProc( HWND hwnd
, ULONG msg
, MPARAM mp1
, MPARAM mp2
)
53 HPS hps
= NULLHANDLE
; /* presentation space handle */
54 GLUTwindow
* window
; /* GLUT window associated with message. */
55 GLUTmenu
* menu
; /* GLUT menu associated with message. */
58 int button
= -1,rc
,key
;
61 /* Process the message. */
67 SIZEL sizl
= { 0L, 0L };
71 /*+-----------------------------------------------------------------+*/
72 /*| The client window is being created. Create the semaphore to |*/
73 /*| control access to the presentation space. Then create the |*/
74 /*| thread that will draw the lines. |*/
75 /*+-----------------------------------------------------------------+*/
76 // DosCreateMutexSem( (PSZ)NULL, &hmtxPS, 0UL, FALSE );
78 hdc
= WinOpenWindowDC(hwnd
);
80 /*+-----------------------------------------------------------------+*/
81 /*| Create a non-cached presentation space. We will not release |*/
82 /*| this PS, as we will be Selecting a Palette to this PS and then |*/
83 /*| animating the palette. Upon releasing a PS the palette is no |*/
84 /*| longer selected for obvious reasons. |*/
85 /*+-----------------------------------------------------------------+*/
86 hpsCurrent
= GpiCreatePS( hab
,
89 PU_PELS
| GPIF_DEFAULT
|
90 GPIT_MICRO
| GPIA_ASSOC
);
91 // DevQueryCaps( hdc, lStart, lCount, alCaps );
92 // fPaletteCaps = alCaps[CAPS_ADDITIONAL_GRAPHICS] & CAPS_PALETTE_MANAGER;
94 /* ¯¥p¥¢®¤ hpsBuffer ¢ p¥¦¨¬ RGB color table */
96 GpiCreateLogColorTable(hpsCurrent
,0 ,LCOLF_RGB
,0,0,NULL
);
97 GpiSetPattern(hpsCurrent
,PATSYM_SOLID
);
98 GpiSetPatternSet(hpsCurrent
,LCID_DEFAULT
);
105 WinPostMsg( hwnd
, WM_QUIT
, NULL
, NULL
);
110 window
= __glutGetWindow(hwnd
);
114 // hps = WinBeginPaint(hwnd,NULLHANDLE,&rclClient);
115 hps
= WinBeginPaint(hwnd
,NULLHANDLE
,&rclClient
);
116 // blit Dive buffer to screen.
119 SWP swp
; // Window position
120 POINTL pointl
; // Point to offset from Desktop
122 // Convert the point to offset from desktop lower left.
125 WinMapWindowPoints ( hwnd
, HWND_DESKTOP
, &pointl
, 1 );
128 // ctx = window->ctx;
129 // ctx->xDiveScr = pointl.x;
130 // ctx->yDiveScr = pointl.y;
132 // rc = DiveBlitImage (ctx->hDive,
133 // ctx->ulDiveBufferNumber,
134 // DIVE_BUFFER_SCREEN );
137 if (window
->win
== hwnd
) {
138 __glutPostRedisplay(window
, GLUT_REPAIR_WORK
);
139 } else if (window
->overlay
&& window
->overlay
->win
== hwnd
) {
140 __glutPostRedisplay(window
, GLUT_OVERLAY_REPAIR_WORK
);
145 hps
= WinBeginPaint(hwnd
,NULLHANDLE
,&rclClient
);
146 WinFillRect(hps
, &rclClient
, CLR_WHITE
);
153 // pwinData->fDataInProcess = TRUE;
154 // DiveSetupBlitter ( pwinData->hDive, 0 );
155 // pwinData->fVrnDisabled = TRUE;
159 { HRGN hrgn
; /* Region handle */
160 RGNRECT rgnCtl
; /* Processing control structure */
164 // pwinData->fDataInProcess = TRUE;
165 hps
= WinGetPS ( hwnd
);
168 hrgn
= GpiCreateRegion ( hps
, 0L, NULL
);
170 { /* NOTE: If mp1 is zero, then this was just a move message.
171 ** Illustrate the visible region on a WM_VRNENABLE.
173 WinQueryVisibleRegion ( hwnd
, hrgn
);
176 rgnCtl
.ulDirection
= 1;
178 /* Get the all ORed rectangles */
179 if ( GpiQueryRegionRects ( hps
, hrgn
, NULL
,
182 ulNumRcls
= rgnCtl
.crcReturned
;
184 /* Now find the window position and size, relative to parent.
186 // WinQueryWindowPos ( pwinData->hwndClient, &pwinData->swp );
191 /* Convert the point to offset from desktop lower left.
193 // pointl.x = pwinData->swp.x;
194 // pointl.y = pwinData->swp.y;
196 // WinMapWindowPoints ( pwinData->hwndFrame,
197 // HWND_DESKTOP, &pointl, 1 );
199 // pwinData->cxWindowPos = pointl.x;
200 // pwinData->cyWindowPos = pointl.y;
203 GpiDestroyRegion( hps
, hrgn
);
211 window
= __glutGetWindow(hwnd
);
214 width
= SHORT1FROMMP(mp2
);
215 height
= SHORT2FROMMP(mp2
);
216 if (width
!= window
->width
|| height
!= window
->height
) {
217 #if 0 /* Win32 GLUT does not support overlays for now. */
218 if (window
->overlay
) {
219 XResizeWindow(__glutDisplay
, window
->overlay
->win
, width
, height
);
222 window
->width
= width
;
223 window
->height
= height
;
224 __glutSetWindow(window
);
225 if(width
<= 0 || height
<= 0)
227 _mesa_ResizeBuffersMESA();
229 /* Do not execute OpenGL out of sequence with respect
230 to the SetWindowPos request! */
231 window
->reshape(width
, height
);
232 window
->forceReshape
= FALSE
;
233 /* A reshape should be considered like posting a
235 __glutPostRedisplay(window
, GLUT_REPAIR_WORK
);
240 window
= __glutGetWindow(hwnd
);
243 visState
= SHORT1FROMMP( mp1
);
244 updateWindowState(window
, visState
);
249 window
= __glutGetWindow(hwnd
);
250 // /* Make sure we re-select the correct palette if needed. */
251 // if (LOWORD(wParam)) {
252 // PostMessage(hwnd, WM_PALETTECHANGED, 0, 0);
256 visState
= SHORT1FROMMP( mp1
);
257 updateWindowState(window
, visState
);
263 window
= __glutGetWindow(hwnd
);
267 fsflags
= SHORT1FROMMP(mp1
);
269 if((fsflags
& KC_KEYUP
) ) /* ¨£®p¨p㥬 ®â¦ ⨥ ª®¯ª¨, p¥ £¨p㥬 ⮫쪮 ¦ ⨥ */
271 ///////////////////////////////////////////////////
272 if(!(fsflags
& KC_CHAR
) )
274 if (!(fsflags
& KC_VIRTUALKEY
))
277 /* Get the virtual key from mp2. */
278 switch (SHORT2FROMMP(mp2
))
280 /* directional keys */
281 case VK_LEFT
: key
= GLUT_KEY_LEFT
; break;
282 case VK_UP
: key
= GLUT_KEY_UP
; break;
283 case VK_RIGHT
: key
= GLUT_KEY_RIGHT
; break;
284 case VK_DOWN
: key
= GLUT_KEY_DOWN
; break;
286 case VK_PAGEUP
: key
= GLUT_KEY_PAGE_UP
; break;
287 case VK_PAGEDOWN
:key
= GLUT_KEY_PAGE_DOWN
; break;
288 case VK_HOME
: key
= GLUT_KEY_HOME
;break;
289 case VK_END
: key
= GLUT_KEY_END
; break;
290 case VK_INSERT
: key
= GLUT_KEY_INSERT
; break;
293 case VK_F1
: key
= GLUT_KEY_F1
; break;
294 case VK_F2
: key
= GLUT_KEY_F2
; break;
295 case VK_F3
: key
= GLUT_KEY_F3
; break;
296 case VK_F4
: key
= GLUT_KEY_F4
; break;
297 case VK_F5
: key
= GLUT_KEY_F5
; break;
298 case VK_F6
: key
= GLUT_KEY_F6
; break;
299 case VK_F7
: key
= GLUT_KEY_F7
; break;
300 case VK_F8
: key
= GLUT_KEY_F8
; break;
301 case VK_F9
: key
= GLUT_KEY_F9
; break;
302 case VK_F10
: key
= GLUT_KEY_F10
;break;
303 case VK_F11
: key
= GLUT_KEY_F11
; break;
304 case VK_F12
: key
= GLUT_KEY_F12
; break;
305 case VK_ESC
: key
= -1; break; /* Character codes */
306 case VK_SPACE
: key
= -1; break;
307 case VK_TAB
: key
= -1; break;
310 { break; /* Key Not implemented */
313 { if (!window
->special
) /* ¥ ãáâ ®¢«¥® ®¡à ¡®â稪 */
316 WinQueryPointerPos(HWND_DESKTOP
,&point
);
317 ScreenToClient(window
->win
, &point
);
318 __glutSetWindow(window
);
319 __glutModifierMask
= 0;
320 if(WinGetKeyState(HWND_DESKTOP
,VK_SHIFT
) & 0x8000) /* high order bit is on */
321 __glutModifierMask
|= ShiftMask
;
322 if(WinGetKeyState(HWND_DESKTOP
,VK_CTRL
) & 0x8000)
323 __glutModifierMask
|= ControlMask
;
324 if(WinGetKeyState(HWND_DESKTOP
,VK_MENU
) & 0x8000)
325 __glutModifierMask
|= Mod1Mask
;
326 window
->special(key
, point
.x
, point
.y
);
327 __glutModifierMask
= (unsigned int) ~0;
332 /////////////////////////////////////////////////////
333 /* If we are ignoring auto repeated key strokes for the window, bail. */
334 if (window
->ignoreKeyRepeat
&& (CHAR3FROMMP(mp1
)) )
336 if(!((unsigned char)SHORT1FROMMP(mp2
)) ) /* ¨£®p¨p㥬 ¥á¨¬¢®«ìë¥ ª®¤ë */
338 if (window
->keyboard
) {
339 WinQueryPointerPos(HWND_DESKTOP
,&point
);
341 ScreenToClient(window
->win
, &point
);
342 __glutSetWindow(window
);
343 __glutModifierMask
= 0;
344 if(WinGetKeyState(HWND_DESKTOP
,VK_SHIFT
) & 0x8000) /* high order bit is on */
345 __glutModifierMask
|= ShiftMask
;
346 if(WinGetKeyState(HWND_DESKTOP
,VK_CTRL
) & 0x8000)
347 __glutModifierMask
|= ControlMask
;
348 if(WinGetKeyState(HWND_DESKTOP
,VK_MENU
) & 0x8000)
349 __glutModifierMask
|= Mod1Mask
;
350 window
->keyboard((unsigned char)SHORT1FROMMP(mp2
), point
.x
, point
.y
);
351 __glutModifierMask
= (unsigned int) ~0;
354 } /* endof case WM_CHAR: */
355 ////////////////////////////////////////////////
357 button
= GLUT_LEFT_BUTTON
;
360 button
= GLUT_MIDDLE_BUTTON
;
363 button
= GLUT_RIGHT_BUTTON
;
365 psh
= *((POINTS
*)&mp1
);
369 /* finish the menu if we get a button down message (user must have
370 cancelled the menu). */
371 if (__glutMappedMenu
) {
372 /* TODO: take this out once the menu on middle mouse stuff works
374 if (button
== GLUT_MIDDLE_BUTTON
)
376 /* get current mouse pointer position */
377 // WinQueryPointerPos(HWND_DESKTOP,&point);
378 /* map from desktop to client window */
379 // WinMapWindowPoints(HWND_DESKTOP, hwnd, &point, 1);
380 __glutItemSelected
= NULL
;
381 __glutFinishMenu(hwnd
, point
.x
, point
.y
);
384 window
= __glutGetWindow(hwnd
);
386 window
->buttonDownState
= button
+1;
387 menu
= __glutGetMenuByNum(window
->menu
[button
]);
390 // __glutMenuButton = button == GLUT_RIGHT_BUTTON ? TPM_RIGHTBUTTON :
391 // button == GLUT_LEFT_BUTTON ? TPM_LEFTBUTTON :
393 // __glutStartMenu(menu, window, point.x, point.y, x, y);
394 } else if (window
->mouse
) {
396 __glutSetWindow(window
);
397 __glutModifierMask
= 0;
398 if (WinGetKeyState(HWND_DESKTOP
,VK_SHIFT
) & 0x8000) /* < 0 = high order bit is on. */
399 __glutModifierMask
|= ShiftMask
;
400 if (WinGetKeyState(HWND_DESKTOP
,VK_CTRL
) & 0x8000)
401 __glutModifierMask
|= ControlMask
;
402 if (WinGetKeyState(HWND_DESKTOP
,VK_MENU
) & 0x8000)
403 __glutModifierMask
|= Mod1Mask
;
404 window
->mouse(button
, GLUT_DOWN
, point
.x
, point
.y
);
405 __glutModifierMask
= (unsigned int)~0;
407 /* Stray mouse events. Ignore. */
413 /********************************************/
415 button
= GLUT_LEFT_BUTTON
;
418 button
= GLUT_MIDDLE_BUTTON
;
421 button
= GLUT_RIGHT_BUTTON
;
423 psh
= *((POINTS
*)&mp1
);
427 /* Bail out if we're processing a menu. */
428 /* Bail out = ¢ë¡à®á¨âìáï á ¯ à èã⮬ */
429 if (__glutMappedMenu
) {
430 WinQueryPointerPos(HWND_DESKTOP
,&point
);
431 WinMapWindowPoints(HWND_DESKTOP
, hwnd
, &point
, 1);
432 /* if we're getting the middle button up signal, then something
433 on the menu was selected. */
434 if (button
== GLUT_MIDDLE_BUTTON
) {
436 /* For some reason, the code below always returns -1 even
437 though the point IS IN THE ITEM! Therefore, just bail out if
438 we get a middle mouse up. The user must select using the
439 left mouse button. Stupid Win32. */
441 int item
= MenuItemFromPoint(hwnd
, __glutHMenu
, point
);
443 __glutItemSelected
= (GLUTmenuItem
*)GetMenuItemID(__glutHMenu
, item
);
445 __glutItemSelected
= NULL
;
446 __glutFinishMenu(hwnd
, point
.x
, point
.y
);
449 __glutItemSelected
= NULL
;
450 __glutFinishMenu(hwnd
, point
.x
, point
.y
);
455 window
= __glutGetWindow(hwnd
);
457 window
->buttonDownState
= 0;
459 if (window
&& window
->mouse
) {
460 __glutSetWindow(window
);
461 __glutModifierMask
= 0;
462 if (WinGetKeyState(HWND_DESKTOP
,VK_SHIFT
) & 0x8000) /* < 0 = high order bit is on */
463 __glutModifierMask
|= ShiftMask
;
464 if (WinGetKeyState(HWND_DESKTOP
,VK_CTRL
) & 0x8000)
465 __glutModifierMask
|= ControlMask
;
466 if (WinGetKeyState(HWND_DESKTOP
,VK_MENU
) & 0x8000)
467 __glutModifierMask
|= Mod1Mask
;
468 window
->mouse(button
, GLUT_UP
, point
.x
, point
.y
);
470 __glutModifierMask
= (unsigned int)~0;
472 /* Window might have been destroyed and all the
473 events for the window may not yet be received. */
479 //////////////////////////////////////////////////
481 window
= __glutGetWindow(hwnd
);
483 { if (window
->wm_command
)
484 window
->wm_command(hwnd
,mp1
,mp2
);
489 if (!__glutMappedMenu
) {
490 window
= __glutGetWindow(hwnd
);
492 /* If motion function registered _and_ buttons held *
493 down, call motion function... */
495 psh
= *((POINTS
*)&mp1
);
500 if (window
->motion
&& window
->buttonDownState
) {
501 __glutSetWindow(window
);
502 window
->motion(point
.x
, point
.y
);
504 /* If passive motion function registered _and_
505 buttons not held down, call passive motion
507 else if (window
->passive
&& !window
->buttonDownState
) {
508 __glutSetWindow(window
);
509 window
->passive(point
.x
, point
.y
);
513 /* Motion events are thrown away when a pop up menu is
520 /* For all other messages, let the default window procedure process them. */
521 return ( WinDefWindowProc( hwnd
, msg
, mp1
, mp2
) );
523 } //endof switch( msg )
524 return ( WinDefWindowProc( hwnd
, msg
, mp1
, mp2
) );
528 void APIENTRY
glutCommandFunc(GLUTcommandCB Func
)
530 extern GLUTwindow
*__glutCurrentWindow
;
531 __glutCurrentWindow
->wm_command
= Func
;
538 updateWindowState(GLUTwindow
*window
, int visState
)
542 /* XXX shownState and visState are the same in Win32. */
543 window
->shownState
= visState
;
544 if (visState
!= window
->visState
) {
545 if (window
->windowStatus
) {
546 window
->visState
= visState
;
547 __glutSetWindow(window
);
548 window
->windowStatus(visState
);
551 /* Since Win32 only sends an activate for the toplevel window,
552 update the visibility for all the child windows. */
553 child
= window
->children
;
555 updateWindowState(child
, visState
);
556 child
= child
->siblings
;
563 __glutWindowProc(HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
565 POINT point
; /* Point structure. */
566 PAINTSTRUCT ps
; /* Paint structure. */
567 LPMINMAXINFO minmax
; /* Minimum/maximum info structure. */
568 GLUTwindow
* window
; /* GLUT window associated with message. */
569 GLUTmenu
* menu
; /* GLUT menu associated with message. */
570 int x
, y
, width
, height
, key
;
581 /* XXX NVidia's NT OpenGL can have problems closing down
582 its OpenGL internal data structures if we just allow
583 the process to terminate without unbinding and deleting
584 the windows context. Apparently, DirectDraw unloads
585 before OPENGL32.DLL in the close down sequence, but
586 NVidia's NT OpenGL needs DirectDraw to close down its
588 window
= __glutGetWindow(hwnd
);
591 wglMakeCurrent(NULL
, NULL
);
592 wglDeleteContext(window
->ctx
);
600 window
= __glutGetWindow(hwnd
);
604 /* Win32 is dumb and sends these messages only to the parent
605 window. Therefore, find out if we're in a child window and
606 call the child windows keyboard callback if we are. */
607 if (window
->parent
) {
608 GetCursorPos(&point
);
609 ScreenToClient(hwnd
, &point
);
610 hwnd
= ChildWindowFromPoint(hwnd
, point
);
611 window
= __glutGetWindow(hwnd
);
613 if (window
->specialUp
|| window
->keyboardUp
) {
614 GetCursorPos(&point
);
615 ScreenToClient(window
->win
, &point
);
616 __glutSetWindow(window
);
617 __glutModifierMask
= 0;
618 if (GetKeyState(VK_SHIFT
) < 0) /* < 0 = high order bit is on */
619 __glutModifierMask
|= ShiftMask
;
620 if (GetKeyState(VK_SHIFT
) < 0) /* < 0 = high order bit is on */
621 __glutModifierMask
|= ControlMask
;
622 if (GetKeyState(VK_MENU
) < 0)
623 __glutModifierMask
|= Mod1Mask
;
626 case VK_F1
: key
= GLUT_KEY_F1
; break;
627 case VK_F2
: key
= GLUT_KEY_F2
; break;
628 case VK_F3
: key
= GLUT_KEY_F3
; break;
629 case VK_F4
: key
= GLUT_KEY_F4
; break;
630 case VK_F5
: key
= GLUT_KEY_F5
; break;
631 case VK_F6
: key
= GLUT_KEY_F6
; break;
632 case VK_F7
: key
= GLUT_KEY_F7
; break;
633 case VK_F8
: key
= GLUT_KEY_F8
; break;
634 case VK_F9
: key
= GLUT_KEY_F9
; break;
635 case VK_F10
: key
= GLUT_KEY_F10
; break;
636 case VK_F11
: key
= GLUT_KEY_F11
; break;
637 case VK_F12
: key
= GLUT_KEY_F12
; break;
638 case VK_LEFT
: key
= GLUT_KEY_LEFT
; break;
639 case VK_UP
: key
= GLUT_KEY_UP
; break;
640 case VK_RIGHT
: key
= GLUT_KEY_RIGHT
; break;
641 case VK_DOWN
: key
= GLUT_KEY_DOWN
; break;
642 case VK_PRIOR
: key
= GLUT_KEY_PAGE_UP
; break;
643 case VK_NEXT
: key
= GLUT_KEY_PAGE_DOWN
; break;
644 case VK_HOME
: key
= GLUT_KEY_HOME
; break;
645 case VK_END
: key
= GLUT_KEY_END
; break;
646 case VK_INSERT
: key
= GLUT_KEY_INSERT
; break;
648 /* Delete is an ASCII character. */
649 if (window
->keyboardUp
) {
650 window
->keyboardUp((unsigned char) 127, point
.x
, point
.y
);
655 if (window
->keyboardUp
) {
656 key
= MapVirtualKey(wParam
, 2); /* Map to ASCII. */
657 if (isascii(key
) && (key
!= 0)) {
659 /* XXX Attempt to determine modified ASCII character
660 is quite incomplete. Digits, symbols, CapsLock,
661 Ctrl, and numeric keypad are all ignored. Fix this. */
663 if (!(__glutModifierMask
& ShiftMask
))
665 window
->keyboardUp((unsigned char) key
, point
.x
, point
.y
);
668 __glutModifierMask
= (unsigned int) ~0;
671 if (window
->specialUp
) {
672 window
->specialUp(key
, point
.x
, point
.y
);
674 __glutModifierMask
= (unsigned int) ~0;
680 window
= __glutGetWindow(hwnd
);
685 /* Bit 30 of lParam is set if key already held down. If
686 we are ignoring auto repeated key strokes for the window, bail. */
687 if (window
->ignoreKeyRepeat
&& (lParam
& (1 << 30)) ) {
691 /* Win32 is dumb and sends these messages only to the parent
692 window. Therefore, find out if we're in a child window and
693 call the child windows keyboard callback if we are. */
694 if (window
->parent
) {
695 GetCursorPos(&point
);
696 ScreenToClient(hwnd
, &point
);
697 hwnd
= ChildWindowFromPoint(hwnd
, point
);
698 window
= __glutGetWindow(hwnd
);
700 if (window
->keyboard
) {
701 GetCursorPos(&point
);
702 ScreenToClient(window
->win
, &point
);
703 __glutSetWindow(window
);
704 __glutModifierMask
= 0;
705 if (GetKeyState(VK_SHIFT
) < 0) /* < 0 = high order bit is on */
706 __glutModifierMask
|= ShiftMask
;
707 if (GetKeyState(VK_CONTROL
) < 0)
708 __glutModifierMask
|= ControlMask
;
709 if (GetKeyState(VK_MENU
) < 0)
710 __glutModifierMask
|= Mod1Mask
;
711 window
->keyboard((unsigned char)wParam
, point
.x
, point
.y
);
712 __glutModifierMask
= (unsigned int) ~0;
718 window
= __glutGetWindow(hwnd
);
723 /* Bit 30 of lParam is set if key already held down. If
724 we are ignoring auto repeated key strokes for the window, bail. */
725 if (window
->ignoreKeyRepeat
&& (lParam
& (1 << 30)) ) {
729 /* Win32 is dumb and sends these messages only to the parent
730 window. Therefore, find out if we're in a child window and
731 call the child windows keyboard callback if we are. */
732 if (window
->parent
) {
733 GetCursorPos(&point
);
734 ScreenToClient(hwnd
, &point
);
735 hwnd
= ChildWindowFromPoint(hwnd
, point
);
736 window
= __glutGetWindow(hwnd
);
738 if (window
->special
) {
742 case VK_F1
: key
= GLUT_KEY_F1
; break;
743 case VK_F2
: key
= GLUT_KEY_F2
; break;
744 case VK_F3
: key
= GLUT_KEY_F3
; break;
745 case VK_F4
: key
= GLUT_KEY_F4
; break;
746 case VK_F5
: key
= GLUT_KEY_F5
; break;
747 case VK_F6
: key
= GLUT_KEY_F6
; break;
748 case VK_F7
: key
= GLUT_KEY_F7
; break;
749 case VK_F8
: key
= GLUT_KEY_F8
; break;
750 case VK_F9
: key
= GLUT_KEY_F9
; break;
751 case VK_F10
: key
= GLUT_KEY_F10
; break;
752 case VK_F11
: key
= GLUT_KEY_F11
; break;
753 case VK_F12
: key
= GLUT_KEY_F12
; break;
754 /* directional keys */
755 case VK_LEFT
: key
= GLUT_KEY_LEFT
; break;
756 case VK_UP
: key
= GLUT_KEY_UP
; break;
757 case VK_RIGHT
: key
= GLUT_KEY_RIGHT
; break;
758 case VK_DOWN
: key
= GLUT_KEY_DOWN
; break;
762 /* VK_PRIOR is Win32's Page Up */
763 key
= GLUT_KEY_PAGE_UP
;
766 /* VK_NEXT is Win32's Page Down */
767 key
= GLUT_KEY_PAGE_DOWN
;
776 key
= GLUT_KEY_INSERT
;
783 GetCursorPos(&point
);
784 ScreenToClient(window
->win
, &point
);
785 __glutSetWindow(window
);
786 __glutModifierMask
= 0;
787 if (GetKeyState(VK_SHIFT
) < 0) /* < 0 = high order bit is on */
788 __glutModifierMask
|= ShiftMask
;
789 if (GetKeyState(VK_CONTROL
) < 0)
790 __glutModifierMask
|= ControlMask
;
791 if (GetKeyState(VK_MENU
) < 0)
792 __glutModifierMask
|= Mod1Mask
;
793 window
->special(key
, point
.x
, point
.y
);
794 __glutModifierMask
= (unsigned int) ~0;
795 } else if (window
->keyboard
) {
796 /* Specially handle any keys that match ASCII values but
797 do not generate Windows WM_SYSCHAR or WM_CHAR messages. */
801 /* Delete is an ASCII character. */
802 GetCursorPos(&point
);
803 ScreenToClient(window
->win
, &point
);
804 __glutSetWindow(window
);
805 __glutModifierMask
= 0;
806 if (GetKeyState(VK_SHIFT
) < 0) /* < 0 = high order bit is on */
807 __glutModifierMask
|= ShiftMask
;
808 if (GetKeyState(VK_CONTROL
) < 0)
809 __glutModifierMask
|= ControlMask
;
810 if (GetKeyState(VK_MENU
) < 0)
811 __glutModifierMask
|= Mod1Mask
;
812 window
->keyboard((unsigned char) 127, point
.x
, point
.y
);
813 __glutModifierMask
= (unsigned int) ~0;
816 /* Let the following WM_SYSCHAR or WM_CHAR message generate
817 the keyboard callback. */
824 button
= GLUT_LEFT_BUTTON
;
827 button
= GLUT_MIDDLE_BUTTON
;
830 button
= GLUT_RIGHT_BUTTON
;
832 /* finish the menu if we get a button down message (user must have
833 cancelled the menu). */
834 if (__glutMappedMenu
) {
835 /* TODO: take this out once the menu on middle mouse stuff works
837 if (button
== GLUT_MIDDLE_BUTTON
)
839 GetCursorPos(&point
);
840 ScreenToClient(hwnd
, &point
);
841 __glutItemSelected
= NULL
;
842 __glutFinishMenu(hwnd
, point
.x
, point
.y
);
846 /* set the capture so we can get mouse events outside the window */
849 /* Win32 doesn't return the same numbers as X does when the mouse
850 goes beyond the upper or left side of the window. roll the
851 Win32's 0..2^16 pointer co-ord range to 0 +/- 2^15. */
854 if(x
& 1 << 15) x
-= (1 << 16);
855 if(y
& 1 << 15) y
-= (1 << 16);
857 window
= __glutGetWindow(hwnd
);
859 menu
= __glutGetMenuByNum(window
->menu
[button
]);
861 point
.x
= LOWORD(lParam
); point
.y
= HIWORD(lParam
);
862 ClientToScreen(window
->win
, &point
);
863 __glutMenuButton
= button
== GLUT_RIGHT_BUTTON
? TPM_RIGHTBUTTON
:
864 button
== GLUT_LEFT_BUTTON
? TPM_LEFTBUTTON
:
866 __glutStartMenu(menu
, window
, point
.x
, point
.y
, x
, y
);
867 } else if (window
->mouse
) {
869 __glutSetWindow(window
);
870 __glutModifierMask
= 0;
871 if (GetKeyState(VK_SHIFT
) < 0) /* < 0 = high order bit is on. */
872 __glutModifierMask
|= ShiftMask
;
873 if (GetKeyState(VK_CONTROL
) < 0)
874 __glutModifierMask
|= ControlMask
;
875 if (GetKeyState(VK_MENU
) < 0)
876 __glutModifierMask
|= Mod1Mask
;
877 window
->mouse(button
, GLUT_DOWN
, x
, y
);
878 __glutModifierMask
= (unsigned int)~0;
880 /* Stray mouse events. Ignore. */
886 button
= GLUT_LEFT_BUTTON
;
889 button
= GLUT_MIDDLE_BUTTON
;
892 button
= GLUT_RIGHT_BUTTON
;
894 /* Bail out if we're processing a menu. */
895 if (__glutMappedMenu
) {
896 GetCursorPos(&point
);
897 ScreenToClient(hwnd
, &point
);
898 /* if we're getting the middle button up signal, then something
899 on the menu was selected. */
900 if (button
== GLUT_MIDDLE_BUTTON
) {
902 /* For some reason, the code below always returns -1 even
903 though the point IS IN THE ITEM! Therefore, just bail out if
904 we get a middle mouse up. The user must select using the
905 left mouse button. Stupid Win32. */
907 int item
= MenuItemFromPoint(hwnd
, __glutHMenu
, point
);
909 __glutItemSelected
= (GLUTmenuItem
*)GetMenuItemID(__glutHMenu
, item
);
911 __glutItemSelected
= NULL
;
912 __glutFinishMenu(hwnd
, point
.x
, point
.y
);
915 __glutItemSelected
= NULL
;
916 __glutFinishMenu(hwnd
, point
.x
, point
.y
);
921 /* Release the mouse capture. */
924 window
= __glutGetWindow(hwnd
);
925 if (window
&& window
->mouse
) {
926 /* Win32 doesn't return the same numbers as X does when the
927 mouse goes beyond the upper or left side of the window. roll
928 the Win32's 0..2^16 pointer co-ord range to 0 +/- 2^15. */
931 if(x
& 1 << 15) x
-= (1 << 16);
932 if(y
& 1 << 15) y
-= (1 << 16);
934 __glutSetWindow(window
);
935 __glutModifierMask
= 0;
936 if (GetKeyState(VK_SHIFT
) < 0) /* < 0 = high order bit is on */
937 __glutModifierMask
|= ShiftMask
;
938 if (GetKeyState(VK_CONTROL
) < 0)
939 __glutModifierMask
|= ControlMask
;
940 if (GetKeyState(VK_MENU
) < 0)
941 __glutModifierMask
|= Mod1Mask
;
942 window
->mouse(button
, GLUT_UP
, x
, y
);
943 __glutModifierMask
= (unsigned int)~0;
945 /* Window might have been destroyed and all the
946 events for the window may not yet be received. */
950 case WM_ENTERMENULOOP
:
951 /* KLUDGE: create a timer that fires every 100 ms when we start a
952 menu so that we can still process the idle & timer events (that
953 way, the timers will fire during a menu pick and so will the
955 SetTimer(hwnd
, 1, 1, NULL
);
960 /* If the timer id is 2, then this is the timer that is set up in
961 the main glut message processing loop, and we don't want to do
962 anything but acknowledge that we got it. It is used to prevent
963 CPU spiking when an idle function is installed. */
968 /* only worry about the idle function and the timeouts, since
969 these are the only events we expect to process during
970 processing of a menu. */
971 /* we no longer process the idle functions (as outlined in the
972 README), since drawing can't be done until the menu has
973 finished...it's pretty lame when the animation goes on, but
974 doesn't update, so you get this weird jerkiness. */
983 case WM_EXITMENULOOP
:
984 /* nuke the above created timer...we don't need it anymore, since
985 the menu is gone now. */
991 __glutHMenu
= (HMENU
)lParam
;
995 if (__glutMappedMenu
) {
996 if (GetSubMenu(__glutHMenu
, LOWORD(wParam
)))
997 __glutItemSelected
= NULL
;
1000 __glutGetUniqueMenuItem(__glutMappedMenu
, LOWORD(wParam
));
1001 GetCursorPos(&point
);
1002 ScreenToClient(hwnd
, &point
);
1003 __glutFinishMenu(hwnd
, point
.x
, point
.y
);
1008 if (!__glutMappedMenu
) {
1009 window
= __glutGetWindow(hwnd
);
1011 /* If motion function registered _and_ buttons held *
1012 down, call motion function... */
1016 /* Win32 doesn't return the same numbers as X does when the
1017 mouse goes beyond the upper or left side of the window.
1018 roll the Win32's 0..2^16 pointer co-ord range to 0..+/-2^15. */
1019 if(x
& 1 << 15) x
-= (1 << 16);
1020 if(y
& 1 << 15) y
-= (1 << 16);
1022 if (window
->motion
&& wParam
&
1023 (MK_LBUTTON
| MK_MBUTTON
| MK_RBUTTON
)) {
1024 __glutSetWindow(window
);
1025 window
->motion(x
, y
);
1027 /* If passive motion function registered _and_
1028 buttons not held down, call passive motion
1030 else if (window
->passive
&&
1032 (MK_LBUTTON
| MK_MBUTTON
| MK_RBUTTON
)) ==
1034 __glutSetWindow(window
);
1035 window
->passive(x
, y
);
1039 /* Motion events are thrown away when a pop up menu is
1044 case WM_GETMINMAXINFO
:
1045 /* this voodoo is brought to you by Win32 (again). It allows the
1046 window to be bigger than the screen, and smaller than 100x100
1047 (although it doesn't seem to help the y minimum). */
1048 minmax
= (LPMINMAXINFO
)lParam
;
1049 minmax
->ptMaxSize
.x
= __glutScreenWidth
;
1050 minmax
->ptMaxSize
.y
= __glutScreenHeight
;
1051 minmax
->ptMinTrackSize
.x
= 0;
1052 minmax
->ptMinTrackSize
.y
= 0;
1053 minmax
->ptMaxTrackSize
.x
= __glutScreenWidth
+
1054 GetSystemMetrics(SM_CXSIZE
) * 2;
1055 minmax
->ptMaxTrackSize
.y
= __glutScreenHeight
+
1056 GetSystemMetrics(SM_CXSIZE
) * 2 + GetSystemMetrics(SM_CYCAPTION
);
1060 window
= __glutGetWindow(hwnd
);
1062 width
= LOWORD(lParam
);
1063 height
= HIWORD(lParam
);
1064 if (width
!= window
->width
|| height
!= window
->height
) {
1065 #if 0 /* Win32 GLUT does not support overlays for now. */
1066 if (window
->overlay
) {
1067 XResizeWindow(__glutDisplay
, window
->overlay
->win
, width
, height
);
1070 window
->width
= width
;
1071 window
->height
= height
;
1072 __glutSetWindow(window
);
1073 /* Do not execute OpenGL out of sequence with respect
1074 to the SetWindowPos request! */
1076 window
->reshape(width
, height
);
1077 window
->forceReshape
= FALSE
;
1078 /* A reshape should be considered like posting a
1080 __glutPostRedisplay(window
, GLUT_REPAIR_WORK
);
1086 /* If the cursor is not in the client area, then we want to send
1087 this message to the default window procedure ('cause its
1088 probably in the border or title, and we don't handle that
1089 cursor. otherwise, set our cursor. Win32 makes us set the
1090 cursor every time the mouse moves (DUMB!). */
1091 if(LOWORD(lParam
) != HTCLIENT
) {
1094 window
= __glutGetWindow(hwnd
);
1096 __glutSetCursor(window
);
1098 /* TODO: check out the info in DevStudio on WM_SETCURSOR in the
1099 DefaultAction section. */
1103 window
= __glutGetWindow(hwnd
);
1105 window
->entryState
= WM_SETFOCUS
;
1106 if (window
->entry
) {
1107 __glutSetWindow(window
);
1108 window
->entry(GLUT_ENTERED
);
1109 /* XXX Generation of fake passive notify? See how much
1110 work the X11 code does to support fake passive notify
1113 if (window
->joystick
&& __glutCurrentWindow
) {
1114 if (__glutCurrentWindow
->joyPollInterval
> 0) {
1117 /* Because Win32 will only let one window capture the
1118 joystick at a time, we must capture it when we get the
1119 focus and release it when we lose the focus. */
1120 result
= joySetCapture(__glutCurrentWindow
->win
,
1121 JOYSTICKID1
, 0, TRUE
);
1122 if (result
!= JOYERR_NOERROR
) {
1125 (void) joySetThreshold(JOYSTICKID1
,
1126 __glutCurrentWindow
->joyPollInterval
);
1133 window
= __glutGetWindow(hwnd
);
1135 window
->entryState
= WM_KILLFOCUS
;
1136 if (window
->entry
) {
1137 __glutSetWindow(window
);
1138 window
->entry(GLUT_LEFT
);
1140 if (window
->joystick
&& __glutCurrentWindow
) {
1141 if (__glutCurrentWindow
->joyPollInterval
> 0) {
1142 /* Because Win32 will only let one window capture the
1143 joystick at a time, we must capture it when we get the
1144 focus and release it when we lose the focus. */
1145 (void) joyReleaseCapture(JOYSTICKID1
);
1151 window
= __glutGetWindow(hwnd
);
1152 /* Make sure we re-select the correct palette if needed. */
1153 if (LOWORD(wParam
)) {
1154 PostMessage(hwnd
, WM_PALETTECHANGED
, 0, 0);
1159 /* HIWORD(wParam) is the minimized flag. */
1160 visState
= !HIWORD(wParam
);
1161 updateWindowState(window
, visState
);
1165 /* Colour Palette Management */
1166 case WM_PALETTECHANGED
:
1167 if (hwnd
== (HWND
)wParam
) {
1168 /* Don't respond to the message that we sent! */
1171 /* fall through to WM_QUERYNEWPALETTE */
1173 case WM_QUERYNEWPALETTE
:
1174 window
= __glutGetWindow(hwnd
);
1175 if (window
&& window
->colormap
) {
1176 UnrealizeObject(window
->colormap
->cmap
);
1177 SelectPalette(window
->hdc
, window
->colormap
->cmap
, FALSE
);
1178 RealizePalette(window
->hdc
);
1185 window
= __glutGetWindow(hwnd
);
1186 if (window
->joystick
) {
1190 /* Because WIN32 only supports messages for X, Y, and Z
1191 translations, we must poll for the rest */
1192 jix
.dwSize
= sizeof(jix
);
1193 jix
.dwFlags
= JOY_RETURNALL
;
1194 joyGetPosEx(JOYSTICKID1
,&jix
);
1196 #define SCALE(v) ((int) ((v - 32767)/32.768))
1198 /* Convert to integer for scaling. */
1202 window
->joystick(jix
.dwButtons
, SCALE(x
), SCALE(y
), SCALE(z
));
1207 case MM_JOY1BUTTONDOWN
:
1208 case MM_JOY1BUTTONUP
:
1209 window
= __glutGetWindow(hwnd
);
1210 if (window
->joystick
) {
1213 /* Because WIN32 only supports messages for X, Y, and Z
1214 translations, we must poll for the rest */
1215 jix
.dwSize
= sizeof(jix
);
1216 jix
.dwFlags
= JOY_RETURNALL
;
1217 joyGetPosEx(JOYSTICKID1
,&jix
);
1224 /* Miscellaneous messages (don't really need to enumerate them,
1225 but it's good to know what you're not getting sometimes). */
1226 case WM_DISPLAYCHANGE
:
1229 /* This event is generated by every mouse move event. */
1231 case WM_NCMOUSEMOVE
:
1243 case WM_NCLBUTTONDOWN
:
1249 case WM_ACTIVATEAPP
:
1255 case WM_WINDOWPOSCHANGING
:
1257 case WM_WINDOWPOSCHANGED
:
1259 case WM_MOUSEACTIVATE
:
1269 case WM_CAPTURECHANGED
:
1273 case WM_ENTERSIZEMOVE
:
1284 return DefWindowProc(hwnd
, msg
, wParam
, lParam
);
1289 #if defined(__OS2PM__)
1290 Bool
__glutSetWindowText(Window window
, char *text
)
1292 return WinSetWindowText(window
, (PCSZ
)text
);