2 * freeglut_main_mswin.c
4 * The Windows-specific mouse cursor related stuff.
6 * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
7 * Written by John F. Fay, <fayjf@sourceforge.net>
8 * Creation date: Sat Jan 21, 2012
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
24 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #include <GL/freeglut.h>
29 #include "../fg_internal.h"
32 extern void fghRedrawWindow ( SFG_Window *window );
34 extern void fgNewWGLCreateContext( SFG_Window* window );
35 extern GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly,
36 unsigned char layer_type );
38 extern void fgPlatformCheckMenuDeactivate();
41 typedef BOOL (WINAPI *pGetTouchInputInfo)(HTOUCHINPUT,UINT,PTOUCHINPUT,int);
42 typedef BOOL (WINAPI *pCloseTouchInputHandle)(HTOUCHINPUT);
43 static pGetTouchInputInfo fghGetTouchInputInfo = (pGetTouchInputInfo)0xDEADBEEF;
44 static pCloseTouchInputHandle fghCloseTouchInputHandle = (pCloseTouchInputHandle)0xDEADBEEF;
48 typedef struct GXDisplayProperties GXDisplayProperties;
49 typedef struct GXKeyList GXKeyList;
52 typedef struct GXKeyList (*GXGETDEFAULTKEYS)(int);
53 typedef int (*GXOPENINPUT)();
55 GXGETDEFAULTKEYS GXGetDefaultKeys_ = NULL;
56 GXOPENINPUT GXOpenInput_ = NULL;
58 struct GXKeyList gxKeyList;
59 #endif /* _WIN32_WCE */
62 /* Get system time, taking special precautions against 32bit timer wrap.
63 We use timeGetTime and not GetTickCount because of its better stability,
64 and because we can increase its granularity (to 1 ms in
65 fgPlatformInitialize). For that reason we can't use GetTickCount64 which
66 wouldn't have the wrap issue.
67 Credit: this is based on code in glibc (https://mail.gnome.org/archives/commits-list/2011-November/msg04588.html)
69 static fg_time_t lastTime32 = 0;
70 static fg_time_t timeEpoch = 0;
71 void fgPlatformInitSystemTime()
73 #if defined(_WIN32_WCE)
74 lastTime32 = GetTickCount();
76 lastTime32 = timeGetTime();
79 fg_time_t fgPlatformSystemTime ( void )
82 #if defined(_WIN32_WCE)
83 currTime32 = GetTickCount();
85 currTime32 = timeGetTime();
87 /* Check if we just wrapped */
88 if (currTime32 < lastTime32)
91 lastTime32 = currTime32;
93 return currTime32 | timeEpoch << 32;
97 void fgPlatformSleepForEvents( fg_time_t msec )
99 MsgWaitForMultipleObjects( 0, NULL, FALSE, (DWORD) msec, QS_ALLINPUT );
103 void fgPlatformProcessSingleEvent ( void )
107 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMainLoopEvent" );
109 while( PeekMessage( &stMsg, NULL, 0, 0, PM_NOREMOVE ) )
111 if( GetMessage( &stMsg, NULL, 0, 0 ) == 0 )
113 if( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT )
118 else if( fgState.ActionOnWindowClose == GLUT_ACTION_GLUTMAINLOOP_RETURNS )
119 fgState.ExecState = GLUT_EXEC_STATE_STOP;
124 TranslateMessage( &stMsg );
125 DispatchMessage( &stMsg );
131 void fgPlatformMainLoopPreliminaryWork ( void )
133 SFG_Window *window = (SFG_Window *)fgStructure.Windows.First ;
136 * Processing before the main loop: If there is a window which is open and
137 * which has a visibility callback, call it. I know this is an ugly hack,
138 * but I'm not sure what else to do about it. Ideally we should leave
139 * something uninitialized in the create window code and initialize it in
140 * the main loop, and have that initialization create a "WM_ACTIVATE"
141 * message. Then we would put the visibility callback code in the
142 * "case WM_ACTIVATE" block below. - John Fay -- 10/24/02
146 if ( FETCH_WCB( *window, Visibility ) )
148 SFG_Window *current_window = fgStructure.CurrentWindow ;
150 INVOKE_WCB( *window, Visibility, ( window->State.Visible ) );
151 fgSetWindow( current_window );
154 window = (SFG_Window *)window->Node.Next ;
160 * Determine a GLUT modifier mask based on MS-WINDOWS system info.
162 static int fgPlatformGetModifiers (void)
165 ( ( ( GetKeyState( VK_LSHIFT ) < 0 ) ||
166 ( GetKeyState( VK_RSHIFT ) < 0 )) ? GLUT_ACTIVE_SHIFT : 0 ) |
167 ( ( ( GetKeyState( VK_LCONTROL ) < 0 ) ||
168 ( GetKeyState( VK_RCONTROL ) < 0 )) ? GLUT_ACTIVE_CTRL : 0 ) |
169 ( ( ( GetKeyState( VK_LMENU ) < 0 ) ||
170 ( GetKeyState( VK_RMENU ) < 0 )) ? GLUT_ACTIVE_ALT : 0 );
174 * The window procedure for handling Win32 events
176 LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
179 static unsigned char lControl = 0, rControl = 0, lShift = 0,
180 rShift = 0, lAlt = 0, rAlt = 0;
182 SFG_Window *window, *child_window = NULL;
186 FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED ( "Event Handler" ) ;
188 window = fgWindowByHandle( hWnd );
190 if ( ( window == NULL ) && ( uMsg != WM_CREATE ) )
191 return DefWindowProc( hWnd, uMsg, wParam, lParam );
193 /* printf ( "Window %3d message <%04x> %12d %12d\n", window?window->ID:0,
194 uMsg, wParam, lParam ); */
196 /* Some events only sent to main window. Check if the current window that
197 * the mouse is over is a child window. Below when handling some messages,
198 * we make sure that we process callbacks on the child window instead.
199 * This mirrors how GLUT does things.
201 if (window && window->Children.First)
204 SFG_WindowHandleType hwnd;
205 SFG_Window* temp_window;
207 GetCursorPos( &mouse_pos );
208 ScreenToClient( window->Window.Handle, &mouse_pos );
209 hwnd = ChildWindowFromPoint(window->Window.Handle, mouse_pos);
210 if (hwnd) /* can be NULL if mouse outside parent by the time we get here */
212 temp_window = fgWindowByHandle(hwnd);
213 if (temp_window && temp_window->Parent) /* Verify we got a child window */
214 child_window = temp_window;
220 SFG_Window* temp_window = child_window?child_window:window;
222 fgState.Modifiers = fgPlatformGetModifiers( );
224 /* Checking for CTRL, ALT, and SHIFT key positions: Key Down! */
225 #define SPECIAL_KEY_DOWN(winKey,glutKey,winProcVar)\
226 if ( !winProcVar && GetAsyncKeyState ( winKey ) )\
228 INVOKE_WCB ( *temp_window, Special,\
229 ( glutKey, temp_window->State.MouseX, temp_window->State.MouseY )\
234 SPECIAL_KEY_DOWN(VK_LCONTROL,GLUT_KEY_CTRL_L ,lControl);
235 SPECIAL_KEY_DOWN(VK_RCONTROL,GLUT_KEY_CTRL_R ,rControl);
236 SPECIAL_KEY_DOWN(VK_LSHIFT ,GLUT_KEY_SHIFT_L,lShift);
237 SPECIAL_KEY_DOWN(VK_RSHIFT ,GLUT_KEY_SHIFT_R,rShift);
238 SPECIAL_KEY_DOWN(VK_LMENU ,GLUT_KEY_ALT_L ,lAlt);
239 SPECIAL_KEY_DOWN(VK_RMENU ,GLUT_KEY_ALT_R ,rAlt);
240 #undef SPECIAL_KEY_DOWN
242 /* Checking for CTRL, ALT, and SHIFT key positions: Key Up! */
243 #define SPECIAL_KEY_UP(winKey,glutKey,winProcVar)\
244 if ( winProcVar && !GetAsyncKeyState ( winKey ) )\
246 INVOKE_WCB ( *temp_window, SpecialUp,\
247 ( glutKey, temp_window->State.MouseX, temp_window->State.MouseY )\
252 SPECIAL_KEY_UP(VK_LCONTROL,GLUT_KEY_CTRL_L ,lControl);
253 SPECIAL_KEY_UP(VK_RCONTROL,GLUT_KEY_CTRL_R ,rControl);
254 SPECIAL_KEY_UP(VK_LSHIFT ,GLUT_KEY_SHIFT_L,lShift);
255 SPECIAL_KEY_UP(VK_RSHIFT ,GLUT_KEY_SHIFT_R,rShift);
256 SPECIAL_KEY_UP(VK_LMENU ,GLUT_KEY_ALT_L ,lAlt);
257 SPECIAL_KEY_UP(VK_RMENU ,GLUT_KEY_ALT_R ,rAlt);
258 #undef SPECIAL_KEY_UP
260 fgState.Modifiers = INVALID_MODIFIERS;
266 /* The window structure is passed as the creation structure parameter... */
267 window = (SFG_Window *) (((LPCREATESTRUCT) lParam)->lpCreateParams);
268 FREEGLUT_INTERNAL_ERROR_EXIT ( ( window != NULL ), "Cannot create window",
269 "fgPlatformWindowProc" );
271 window->Window.Handle = hWnd;
272 window->Window.pContext.Device = GetDC( hWnd );
275 unsigned int current_DisplayMode = fgState.DisplayMode;
276 fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH;
277 #if !defined(_WIN32_WCE)
278 fgSetupPixelFormat( window, GL_FALSE, PFD_MAIN_PLANE );
280 fgState.DisplayMode = current_DisplayMode;
282 if( fgStructure.MenuContext )
283 wglMakeCurrent( window->Window.pContext.Device,
284 fgStructure.MenuContext->MContext
288 fgStructure.MenuContext =
289 (SFG_MenuContext *)malloc( sizeof(SFG_MenuContext) );
290 fgStructure.MenuContext->MContext =
291 wglCreateContext( window->Window.pContext.Device );
294 /* window->Window.Context = wglGetCurrentContext (); */
295 window->Window.Context = wglCreateContext( window->Window.pContext.Device );
299 #if !defined(_WIN32_WCE)
300 fgSetupPixelFormat( window, GL_FALSE, PFD_MAIN_PLANE );
303 if( ! fgState.UseCurrentContext )
304 window->Window.Context =
305 wglCreateContext( window->Window.pContext.Device );
308 window->Window.Context = wglGetCurrentContext( );
309 if( ! window->Window.Context )
310 window->Window.Context =
311 wglCreateContext( window->Window.pContext.Device );
314 #if !defined(_WIN32_WCE)
315 fgNewWGLCreateContext( window );
319 window->State.NeedToResize = GL_TRUE;
320 /* if we used CW_USEDEFAULT (thats a negative value) for the size
321 * of the window, query the window now for the size at which it
324 if( ( window->State.Width < 0 ) || ( window->State.Height < 0 ) )
326 SFG_Window *current_window = fgStructure.CurrentWindow;
328 fgSetWindow( window );
329 window->State.Width = glutGet( GLUT_WINDOW_WIDTH );
330 window->State.Height = glutGet( GLUT_WINDOW_HEIGHT );
331 fgSetWindow( current_window );
334 ReleaseDC( window->Window.Handle, window->Window.pContext.Device );
336 #if defined(_WIN32_WCE)
337 /* Take over button handling */
339 HINSTANCE dxDllLib=LoadLibrary(_T("gx.dll"));
342 GXGetDefaultKeys_=(GXGETDEFAULTKEYS)GetProcAddress(dxDllLib, _T("?GXGetDefaultKeys@@YA?AUGXKeyList@@H@Z"));
343 GXOpenInput_=(GXOPENINPUT)GetProcAddress(dxDllLib, _T("?GXOpenInput@@YAHXZ"));
348 if(GXGetDefaultKeys_)
349 gxKeyList = (*GXGetDefaultKeys_)(GX_LANDSCAPEKEYS);
352 #endif /* defined(_WIN32_WCE) */
357 * If the window is visible, then it is the user manually resizing it.
358 * If it is not, then it is the system sending us a dummy resize with
359 * zero dimensions on a "glutIconifyWindow" call.
361 if( window->State.Visible )
363 /* get old values first to compare to below */
364 int width = window->State.Width, height=window->State.Height;
365 #if defined(_WIN32_WCE)
366 window->State.Width = HIWORD(lParam);
367 window->State.Height = LOWORD(lParam);
369 window->State.Width = LOWORD(lParam);
370 window->State.Height = HIWORD(lParam);
371 #endif /* defined(_WIN32_WCE) */
373 if (width!=window->State.Width || height!=window->State.Height)
374 /* Something changed, need to resize */
375 window->State.NeedToResize = GL_TRUE;
382 SFG_Window* saved_window = fgStructure.CurrentWindow;
384 GetWindowRect( window->Window.Handle, &windowRect );
388 /* For child window, we should return relative to upper-left
389 * of parent's client area.
391 POINT topleft = {windowRect.left,windowRect.top};
393 ScreenToClient(window->Parent->Window.Handle,&topleft);
394 windowRect.left = topleft.x;
395 windowRect.top = topleft.y;
398 INVOKE_WCB( *window, Position, ( windowRect.left, windowRect.top ) );
399 fgSetWindow(saved_window);
404 /* printf("WM_SETFOCUS: %p\n", window ); */
406 lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
410 /* If we're dealing with a child window, make sure it has input focus instead, set it here. */
411 SetFocus(child_window->Window.Handle);
412 SetActiveWindow( child_window->Window.Handle );
413 INVOKE_WCB( *child_window, Entry, ( GLUT_ENTERED ) );
414 UpdateWindow ( child_window->Window.Handle );
418 SetActiveWindow( window->Window.Handle );
419 INVOKE_WCB( *window, Entry, ( GLUT_ENTERED ) );
421 /* Always request update on main window to be safe */
422 UpdateWindow ( hWnd );
428 SFG_Window* saved_window = fgStructure.CurrentWindow;
429 /* printf("WM_KILLFOCUS: %p\n", window ); */
430 lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
431 INVOKE_WCB( *window, Entry, ( GLUT_LEFT ) );
432 fgSetWindow(saved_window);
434 /* Check if there are any open menus that need to be closed */
435 fgPlatformCheckMenuDeactivate();
441 if (LOWORD(wParam) != WA_INACTIVE)
443 /* printf("WM_ACTIVATE: fgSetCursor( %p, %d)\n", window,
444 window->State.Cursor ); */
445 fgSetCursor( window, window->State.Cursor );
448 lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
453 /* printf ( "Cursor event %x %x %x %x\n", window, window->State.Cursor, lParam, wParam ) ; */
454 if( LOWORD( lParam ) == HTCLIENT )
455 fgSetCursor ( window, window->State.Cursor ) ;
457 lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
461 window->State.Visible = GL_TRUE;
462 window->State.Redisplay = GL_TRUE;
466 /* Turn on the visibility in case it was turned off somehow */
467 window->State.Visible = GL_TRUE;
468 InvalidateRect( hWnd, NULL, GL_FALSE ); /* Make sure whole window is repainted. Bit of a hack, but a safe one from what google turns up... */
469 BeginPaint( hWnd, &ps );
470 fghRedrawWindow( window );
471 EndPaint( hWnd, &ps );
475 fgDestroyWindow ( window );
476 if ( fgState.ActionOnWindowClose != GLUT_ACTION_CONTINUE_EXECUTION )
482 * The window already got destroyed, so don't bother with it.
488 #if defined(_WIN32_WCE)
489 window->State.MouseX = 320-HIWORD( lParam );
490 window->State.MouseY = LOWORD( lParam );
492 window->State.MouseX = LOWORD( lParam );
493 window->State.MouseY = HIWORD( lParam );
494 #endif /* defined(_WIN32_WCE) */
495 /* Restrict to [-32768, 32767] to match X11 behaviour */
496 /* See comment in "freeglut_developer" mailing list 10/4/04 */
497 if ( window->State.MouseX > 32767 ) window->State.MouseX -= 65536;
498 if ( window->State.MouseY > 32767 ) window->State.MouseY -= 65536;
500 if ( window->ActiveMenu )
502 fgUpdateMenuHighlight( window->ActiveMenu );
506 fgState.Modifiers = fgPlatformGetModifiers( );
508 if( ( wParam & MK_LBUTTON ) ||
509 ( wParam & MK_MBUTTON ) ||
510 ( wParam & MK_RBUTTON ) )
511 INVOKE_WCB( *window, Motion, ( window->State.MouseX,
512 window->State.MouseY ) );
514 INVOKE_WCB( *window, Passive, ( window->State.MouseX,
515 window->State.MouseY ) );
517 fgState.Modifiers = INVALID_MODIFIERS;
528 GLboolean pressed = GL_TRUE;
531 #if defined(_WIN32_WCE)
532 window->State.MouseX = 320-HIWORD( lParam );
533 window->State.MouseY = LOWORD( lParam );
535 window->State.MouseX = LOWORD( lParam );
536 window->State.MouseY = HIWORD( lParam );
537 #endif /* defined(_WIN32_WCE) */
539 /* Restrict to [-32768, 32767] to match X11 behaviour */
540 /* See comment in "freeglut_developer" mailing list 10/4/04 */
541 if ( window->State.MouseX > 32767 ) window->State.MouseX -= 65536;
542 if ( window->State.MouseY > 32767 ) window->State.MouseY -= 65536;
548 button = GLUT_LEFT_BUTTON;
552 button = GLUT_MIDDLE_BUTTON;
556 button = GLUT_RIGHT_BUTTON;
560 button = GLUT_LEFT_BUTTON;
564 button = GLUT_MIDDLE_BUTTON;
568 button = GLUT_RIGHT_BUTTON;
576 #if !defined(_WIN32_WCE)
577 if( GetSystemMetrics( SM_SWAPBUTTON ) )
579 if( button == GLUT_LEFT_BUTTON )
580 button = GLUT_RIGHT_BUTTON;
582 if( button == GLUT_RIGHT_BUTTON )
583 button = GLUT_LEFT_BUTTON;
585 #endif /* !defined(_WIN32_WCE) */
588 return DefWindowProc( hWnd, uMsg, lParam, wParam );
591 * Do not execute the application's mouse callback if a menu
592 * is hooked to this button. In that case an appropriate
593 * private call should be generated.
595 if( fgCheckActiveMenu( window, button, pressed,
596 window->State.MouseX, window->State.MouseY ) )
599 /* Set capture so that the window captures all the mouse messages */
601 * XXX - Multiple button support: Under X11, the mouse is not released
602 * XXX - from the window until all buttons have been released, even if the
603 * XXX - user presses a button in another window. This will take more
604 * XXX - code changes than I am up to at the moment (10/5/04). The present
605 * XXX - is a 90 percent solution.
607 if ( pressed == GL_TRUE )
608 SetCapture ( window->Window.Handle ) ;
612 if( ! FETCH_WCB( *window, Mouse ) )
615 fgSetWindow( window );
616 fgState.Modifiers = fgPlatformGetModifiers( );
621 pressed ? GLUT_DOWN : GLUT_UP,
622 window->State.MouseX,
627 fgState.Modifiers = INVALID_MODIFIERS;
633 int wheel_number = LOWORD( wParam );
634 short ticks = ( short )HIWORD( wParam );
635 fgState.MouseWheelTicks += ticks;
637 if ( abs ( fgState.MouseWheelTicks ) >= WHEEL_DELTA )
639 int direction = ( fgState.MouseWheelTicks > 0 ) ? 1 : -1;
641 if( ! FETCH_WCB( *window, MouseWheel ) &&
642 ! FETCH_WCB( *window, Mouse ) )
645 fgSetWindow( window );
646 fgState.Modifiers = fgPlatformGetModifiers( );
648 while( abs ( fgState.MouseWheelTicks ) >= WHEEL_DELTA )
650 if( FETCH_WCB( *window, MouseWheel ) )
651 INVOKE_WCB( *window, MouseWheel,
654 window->State.MouseX,
658 else /* No mouse wheel, call the mouse button callback twice */
661 * Map wheel zero to button 3 and 4; +1 to 3, -1 to 4
662 * " " one +1 to 5, -1 to 6, ...
664 * XXX The below assumes that you have no more than 3 mouse
665 * XXX buttons. Sorry.
667 int button = wheel_number * 2 + 3;
670 INVOKE_WCB( *window, Mouse,
672 window->State.MouseX, window->State.MouseY )
674 INVOKE_WCB( *window, Mouse,
676 window->State.MouseX, window->State.MouseY )
680 fgState.MouseWheelTicks -= WHEEL_DELTA * direction;
683 fgState.Modifiers = INVALID_MODIFIERS;
695 window = child_window;
697 if( ( fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE ) && (HIWORD(lParam) & KF_REPEAT) )
701 * Remember the current modifiers state. This is done here in order
702 * to make sure the VK_DELETE keyboard callback is executed properly.
704 fgState.Modifiers = fgPlatformGetModifiers( );
706 GetCursorPos( &mouse_pos );
707 ScreenToClient( window->Window.Handle, &mouse_pos );
709 window->State.MouseX = mouse_pos.x;
710 window->State.MouseY = mouse_pos.y;
712 /* Convert the Win32 keystroke codes to GLUTtish way */
713 # define KEY(a,b) case a: keypress = b; break;
717 KEY( VK_F1, GLUT_KEY_F1 );
718 KEY( VK_F2, GLUT_KEY_F2 );
719 KEY( VK_F3, GLUT_KEY_F3 );
720 KEY( VK_F4, GLUT_KEY_F4 );
721 KEY( VK_F5, GLUT_KEY_F5 );
722 KEY( VK_F6, GLUT_KEY_F6 );
723 KEY( VK_F7, GLUT_KEY_F7 );
724 KEY( VK_F8, GLUT_KEY_F8 );
725 KEY( VK_F9, GLUT_KEY_F9 );
726 KEY( VK_F10, GLUT_KEY_F10 );
727 KEY( VK_F11, GLUT_KEY_F11 );
728 KEY( VK_F12, GLUT_KEY_F12 );
729 KEY( VK_PRIOR, GLUT_KEY_PAGE_UP );
730 KEY( VK_NEXT, GLUT_KEY_PAGE_DOWN );
731 KEY( VK_HOME, GLUT_KEY_HOME );
732 KEY( VK_END, GLUT_KEY_END );
733 KEY( VK_LEFT, GLUT_KEY_LEFT );
734 KEY( VK_UP, GLUT_KEY_UP );
735 KEY( VK_RIGHT, GLUT_KEY_RIGHT );
736 KEY( VK_DOWN, GLUT_KEY_DOWN );
737 KEY( VK_INSERT, GLUT_KEY_INSERT );
739 case VK_LCONTROL: case VK_RCONTROL: case VK_CONTROL:
740 case VK_LSHIFT: case VK_RSHIFT: case VK_SHIFT:
741 case VK_LMENU: case VK_RMENU: case VK_MENU:
742 /* These keypresses and releases are handled earlier in the function */
746 /* The delete key should be treated as an ASCII keypress: */
747 INVOKE_WCB( *window, Keyboard,
748 ( 127, window->State.MouseX, window->State.MouseY )
752 #if defined(_WIN32_WCE)
753 if(!(lParam & 0x40000000)) /* Prevent auto-repeat */
755 if(wParam==(unsigned)gxKeyList.vkRight)
756 keypress = GLUT_KEY_RIGHT;
757 else if(wParam==(unsigned)gxKeyList.vkLeft)
758 keypress = GLUT_KEY_LEFT;
759 else if(wParam==(unsigned)gxKeyList.vkUp)
760 keypress = GLUT_KEY_UP;
761 else if(wParam==(unsigned)gxKeyList.vkDown)
762 keypress = GLUT_KEY_DOWN;
763 else if(wParam==(unsigned)gxKeyList.vkA)
764 keypress = GLUT_KEY_F1;
765 else if(wParam==(unsigned)gxKeyList.vkB)
766 keypress = GLUT_KEY_F2;
767 else if(wParam==(unsigned)gxKeyList.vkC)
768 keypress = GLUT_KEY_F3;
769 else if(wParam==(unsigned)gxKeyList.vkStart)
770 keypress = GLUT_KEY_F4;
775 INVOKE_WCB( *window, Special,
777 window->State.MouseX, window->State.MouseY )
780 fgState.Modifiers = INVALID_MODIFIERS;
791 window = child_window;
794 * Remember the current modifiers state. This is done here in order
795 * to make sure the VK_DELETE keyboard callback is executed properly.
797 fgState.Modifiers = fgPlatformGetModifiers( );
799 GetCursorPos( &mouse_pos );
800 ScreenToClient( window->Window.Handle, &mouse_pos );
802 window->State.MouseX = mouse_pos.x;
803 window->State.MouseY = mouse_pos.y;
806 * Convert the Win32 keystroke codes to GLUTtish way.
807 * "KEY(a,b)" was defined under "WM_KEYDOWN"
812 KEY( VK_F1, GLUT_KEY_F1 );
813 KEY( VK_F2, GLUT_KEY_F2 );
814 KEY( VK_F3, GLUT_KEY_F3 );
815 KEY( VK_F4, GLUT_KEY_F4 );
816 KEY( VK_F5, GLUT_KEY_F5 );
817 KEY( VK_F6, GLUT_KEY_F6 );
818 KEY( VK_F7, GLUT_KEY_F7 );
819 KEY( VK_F8, GLUT_KEY_F8 );
820 KEY( VK_F9, GLUT_KEY_F9 );
821 KEY( VK_F10, GLUT_KEY_F10 );
822 KEY( VK_F11, GLUT_KEY_F11 );
823 KEY( VK_F12, GLUT_KEY_F12 );
824 KEY( VK_PRIOR, GLUT_KEY_PAGE_UP );
825 KEY( VK_NEXT, GLUT_KEY_PAGE_DOWN );
826 KEY( VK_HOME, GLUT_KEY_HOME );
827 KEY( VK_END, GLUT_KEY_END );
828 KEY( VK_LEFT, GLUT_KEY_LEFT );
829 KEY( VK_UP, GLUT_KEY_UP );
830 KEY( VK_RIGHT, GLUT_KEY_RIGHT );
831 KEY( VK_DOWN, GLUT_KEY_DOWN );
832 KEY( VK_INSERT, GLUT_KEY_INSERT );
834 case VK_LCONTROL: case VK_RCONTROL: case VK_CONTROL:
835 case VK_LSHIFT: case VK_RSHIFT: case VK_SHIFT:
836 case VK_LMENU: case VK_RMENU: case VK_MENU:
837 /* These keypresses and releases are handled earlier in the function */
841 /* The delete key should be treated as an ASCII keypress: */
842 INVOKE_WCB( *window, KeyboardUp,
843 ( 127, window->State.MouseX, window->State.MouseY )
849 #if !defined(_WIN32_WCE)
853 GetKeyboardState( state );
855 if( ToAscii( (UINT)wParam, 0, state, code, 0 ) == 1 )
858 INVOKE_WCB( *window, KeyboardUp,
860 window->State.MouseX, window->State.MouseY )
862 #endif /* !defined(_WIN32_WCE) */
867 INVOKE_WCB( *window, SpecialUp,
869 window->State.MouseX, window->State.MouseY )
872 fgState.Modifiers = INVALID_MODIFIERS;
880 window = child_window;
882 if( (fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE) && (HIWORD(lParam) & KF_REPEAT) )
885 fgState.Modifiers = fgPlatformGetModifiers( );
886 INVOKE_WCB( *window, Keyboard,
888 window->State.MouseX, window->State.MouseY )
890 fgState.Modifiers = INVALID_MODIFIERS;
894 case WM_CAPTURECHANGED:
895 /* User has finished resizing the window, force a redraw */
896 INVOKE_WCB( *window, Display, ( ) );
898 /*lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); */
901 /* Other messages that I have seen and which are not handled already */
902 case WM_SETTEXT: /* 0x000c */
903 lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
904 /* Pass it on to "DefWindowProc" to set the window text */
907 case WM_GETTEXT: /* 0x000d */
908 /* Ideally we would copy the title of the window into "lParam" */
909 /* strncpy ( (char *)lParam, "Window Title", wParam );
910 lRet = ( wParam > 12 ) ? 12 : wParam; */
911 /* the number of characters copied */
912 lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
915 case WM_GETTEXTLENGTH: /* 0x000e */
916 /* Ideally we would get the length of the title of the window */
918 /* the number of characters in "Window Title\0" (see above) */
921 case WM_ERASEBKGND: /* 0x0014 */
922 lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
925 #if !defined(_WIN32_WCE)
926 case WM_SYNCPAINT: /* 0x0088 */
927 /* Another window has moved, need to update this one */
928 window->State.Redisplay = GL_TRUE;
929 lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
930 /* Help screen says this message must be passed to "DefWindowProc" */
933 case WM_NCPAINT: /* 0x0085 */
934 /* Need to update the border of this window */
935 lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
936 /* Pass it on to "DefWindowProc" to repaint a standard border */
939 case WM_SYSCOMMAND : /* 0x0112 */
942 * We have received a system command message. Try to act on it.
943 * The commands are passed in through the "wParam" parameter:
944 * The least significant digit seems to be which edge of the window
945 * is being used for a resize event:
949 * Congratulations and thanks to Richard Rauch for figuring this out..
951 switch ( wParam & 0xfff0 )
960 /* User has clicked on the "-" to minimize the window */
961 /* Turn off the visibility */
962 window->State.Visible = GL_FALSE ;
976 /* Followed very closely by a WM_CLOSE message */
1000 case SC_SCREENSAVE :
1006 #if(WINVER >= 0x0400)
1010 case SC_MONITORPOWER :
1013 case SC_CONTEXTHELP :
1015 #endif /* WINVER >= 0x0400 */
1019 fgWarning( "Unknown wParam type 0x%x", wParam );
1024 #endif /* !defined(_WIN32_WCE) */
1026 /* We need to pass the message on to the operating system as well */
1027 lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
1031 /* handle multi-touch messages */
1034 unsigned int numInputs = (unsigned int)wParam;
1036 TOUCHINPUT* ti = (TOUCHINPUT*)malloc( sizeof(TOUCHINPUT)*numInputs);
1038 if (fghGetTouchInputInfo == (pGetTouchInputInfo)0xDEADBEEF) {
1039 fghGetTouchInputInfo = (pGetTouchInputInfo)GetProcAddress(GetModuleHandle("user32"),"GetTouchInputInfo");
1040 fghCloseTouchInputHandle = (pCloseTouchInputHandle)GetProcAddress(GetModuleHandle("user32"),"CloseTouchInputHandle");
1043 if (!fghGetTouchInputInfo) {
1048 if (fghGetTouchInputInfo( (HTOUCHINPUT)lParam, numInputs, ti, sizeof(TOUCHINPUT) )) {
1049 /* Handle each contact point */
1050 for (i = 0; i < numInputs; ++i ) {
1053 tp.x = TOUCH_COORD_TO_PIXEL(ti[i].x);
1054 tp.y = TOUCH_COORD_TO_PIXEL(ti[i].y);
1055 ScreenToClient( hWnd, &tp );
1057 ti[i].dwID = ti[i].dwID * 2;
1059 if (ti[i].dwFlags & TOUCHEVENTF_DOWN) {
1060 INVOKE_WCB( *window, MultiEntry, ( ti[i].dwID, GLUT_ENTERED ) );
1061 INVOKE_WCB( *window, MultiButton, ( ti[i].dwID, tp.x, tp.y, 0, GLUT_DOWN ) );
1062 } else if (ti[i].dwFlags & TOUCHEVENTF_MOVE) {
1063 INVOKE_WCB( *window, MultiMotion, ( ti[i].dwID, tp.x, tp.y ) );
1064 } else if (ti[i].dwFlags & TOUCHEVENTF_UP) {
1065 INVOKE_WCB( *window, MultiButton, ( ti[i].dwID, tp.x, tp.y, 0, GLUT_UP ) );
1066 INVOKE_WCB( *window, MultiEntry, ( ti[i].dwID, GLUT_LEFT ) );
1070 fghCloseTouchInputHandle((HTOUCHINPUT)lParam);
1072 lRet = 0; /*DefWindowProc( hWnd, uMsg, wParam, lParam );*/
1077 /* Handle unhandled messages */
1078 lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );