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 );
39 typedef BOOL (WINAPI *pGetTouchInputInfo)(HTOUCHINPUT,UINT,PTOUCHINPUT,int);
40 typedef BOOL (WINAPI *pCloseTouchInputHandle)(HTOUCHINPUT);
41 static pGetTouchInputInfo fghGetTouchInputInfo = (pGetTouchInputInfo)0xDEADBEEF;
42 static pCloseTouchInputHandle fghCloseTouchInputHandle = (pCloseTouchInputHandle)0xDEADBEEF;
46 typedef struct GXDisplayProperties GXDisplayProperties;
47 typedef struct GXKeyList GXKeyList;
50 typedef struct GXKeyList (*GXGETDEFAULTKEYS)(int);
51 typedef int (*GXOPENINPUT)();
53 GXGETDEFAULTKEYS GXGetDefaultKeys_ = NULL;
54 GXOPENINPUT GXOpenInput_ = NULL;
56 struct GXKeyList gxKeyList;
57 #endif /* _WIN32_WCE */
60 * Helper functions for getting client area from the window rect
61 * and the window rect from the client area given the style of the window
62 * (or a valid window pointer from which the style can be queried).
64 extern void fghComputeWindowRectFromClientArea_QueryWindow( const SFG_Window *window, RECT *clientRect, BOOL posIsOutside );
65 extern RECT fghGetClientArea ( const SFG_Window *window, BOOL wantPosOutside );
68 void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height )
73 * For windowed mode, get the current position of the
74 * window and resize taking the size of the frame
75 * decorations into account.
78 /* "GetWindowRect" returns the pixel coordinates of the outside of the window */
79 GetWindowRect( window->Window.Handle, &windowRect );
81 /* Create rect in FreeGLUT format, (X,Y) topleft outside window, WxH of client area */
82 windowRect.right = windowRect.left+width;
83 windowRect.bottom = windowRect.top+height;
85 if (window->Parent == NULL)
86 /* get the window rect from this to feed to SetWindowPos, correct for window decorations */
87 fghComputeWindowRectFromClientArea_QueryWindow(window,&windowRect,TRUE);
90 /* correct rect for position client area of parent window
91 * (SetWindowPos input for child windows is in coordinates
92 * relative to the parent's client area).
93 * Child windows don't have decoration, so no need to correct
97 parentRect = fghGetClientArea( window->Parent, FALSE );
98 windowRect.left -= parentRect.left;
99 windowRect.right -= parentRect.left;
100 windowRect.top -= parentRect.top;
101 windowRect.bottom -= parentRect.top;
104 /* Do the actual resizing */
105 SetWindowPos( window->Window.Handle,
107 windowRect.left, windowRect.top,
108 windowRect.right - windowRect.left,
109 windowRect.bottom- windowRect.top,
110 SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING |
116 void fgPlatformDisplayWindow ( SFG_Window *window )
119 window->Window.Handle, NULL, NULL,
120 RDW_NOERASE | RDW_INTERNALPAINT | RDW_INVALIDATE | RDW_UPDATENOW
125 fg_time_t fgPlatformSystemTime ( void )
127 #if defined(_WIN32_WCE)
128 return GetTickCount();
130 /* TODO: do this with QueryPerformanceCounter as timeGetTime has
131 * insufficient resolution (only about 5 ms on system under low load).
133 * http://msdn.microsoft.com/en-us/library/windows/desktop/dd757629(v=vs.85).aspx
134 * Or maybe QueryPerformanceCounter is not a good idea either, see
135 * http://old.nabble.com/Re%3A-glutTimerFunc-does-not-detect-if-system-time-moved-backward-p33479674.html
136 * for some other ideas (at bottom)...
138 return timeGetTime();
143 void fgPlatformSleepForEvents( fg_time_t msec )
145 MsgWaitForMultipleObjects( 0, NULL, FALSE, (DWORD) msec, QS_ALLINPUT );
149 void fgPlatformProcessSingleEvent ( void )
153 FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutMainLoopEvent" );
155 while( PeekMessage( &stMsg, NULL, 0, 0, PM_NOREMOVE ) )
157 if( GetMessage( &stMsg, NULL, 0, 0 ) == 0 )
159 if( fgState.ActionOnWindowClose == GLUT_ACTION_EXIT )
164 else if( fgState.ActionOnWindowClose == GLUT_ACTION_GLUTMAINLOOP_RETURNS )
165 fgState.ExecState = GLUT_EXEC_STATE_STOP;
170 TranslateMessage( &stMsg );
171 DispatchMessage( &stMsg );
177 void fgPlatformMainLoopPreliminaryWork ( void )
179 SFG_Window *window = (SFG_Window *)fgStructure.Windows.First ;
182 * Processing before the main loop: If there is a window which is open and
183 * which has a visibility callback, call it. I know this is an ugly hack,
184 * but I'm not sure what else to do about it. Ideally we should leave
185 * something uninitialized in the create window code and initialize it in
186 * the main loop, and have that initialization create a "WM_ACTIVATE"
187 * message. Then we would put the visibility callback code in the
188 * "case WM_ACTIVATE" block below. - John Fay -- 10/24/02
192 if ( FETCH_WCB( *window, Visibility ) )
194 SFG_Window *current_window = fgStructure.CurrentWindow ;
196 INVOKE_WCB( *window, Visibility, ( window->State.Visible ) );
197 fgSetWindow( current_window );
200 window = (SFG_Window *)window->Node.Next ;
206 * Determine a GLUT modifer mask based on MS-WINDOWS system info.
208 static int fgPlatformGetModifiers (void)
211 ( ( ( GetKeyState( VK_LSHIFT ) < 0 ) ||
212 ( GetKeyState( VK_RSHIFT ) < 0 )) ? GLUT_ACTIVE_SHIFT : 0 ) |
213 ( ( ( GetKeyState( VK_LCONTROL ) < 0 ) ||
214 ( GetKeyState( VK_RCONTROL ) < 0 )) ? GLUT_ACTIVE_CTRL : 0 ) |
215 ( ( ( GetKeyState( VK_LMENU ) < 0 ) ||
216 ( GetKeyState( VK_RMENU ) < 0 )) ? GLUT_ACTIVE_ALT : 0 );
220 * The window procedure for handling Win32 events
222 LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
225 static unsigned char lControl = 0, rControl = 0, lShift = 0,
226 rShift = 0, lAlt = 0, rAlt = 0;
232 FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED ( "Event Handler" ) ;
234 window = fgWindowByHandle( hWnd );
236 if ( ( window == NULL ) && ( uMsg != WM_CREATE ) )
237 return DefWindowProc( hWnd, uMsg, wParam, lParam );
239 /* printf ( "Window %3d message <%04x> %12d %12d\n", window?window->ID:0,
240 uMsg, wParam, lParam ); */
242 /* events only sent to main window. Check if the current window that the mouse
243 is over is a child window and if so, make sure we call the callback on that
246 if (window && window->Children.First)
249 SFG_WindowHandleType hwnd;
251 GetCursorPos( &mouse_pos );
252 ScreenToClient( window->Window.Handle, &mouse_pos );
253 hwnd = ChildWindowFromPoint(window->Window.Handle, mouse_pos);
254 if (hwnd) /* can be NULL if mouse outside parent by the time we get here */
255 window = fgWindowByHandle(hwnd);
260 fgState.Modifiers = fgPlatformGetModifiers( );
262 /* Checking for CTRL, ALT, and SHIFT key positions: Key Down! */
263 if ( !lControl && GetAsyncKeyState ( VK_LCONTROL ) )
265 INVOKE_WCB ( *window, Special,
266 ( GLUT_KEY_CTRL_L, window->State.MouseX, window->State.MouseY )
272 if ( !rControl && GetAsyncKeyState ( VK_RCONTROL ) )
274 INVOKE_WCB ( *window, Special,
275 ( GLUT_KEY_CTRL_R, window->State.MouseX, window->State.MouseY )
281 if ( !lShift && GetAsyncKeyState ( VK_LSHIFT ) )
283 INVOKE_WCB ( *window, Special,
284 ( GLUT_KEY_SHIFT_L, window->State.MouseX, window->State.MouseY )
290 if ( !rShift && GetAsyncKeyState ( VK_RSHIFT ) )
292 INVOKE_WCB ( *window, Special,
293 ( GLUT_KEY_SHIFT_R, window->State.MouseX, window->State.MouseY )
299 if ( !lAlt && GetAsyncKeyState ( VK_LMENU ) )
301 INVOKE_WCB ( *window, Special,
302 ( GLUT_KEY_ALT_L, window->State.MouseX, window->State.MouseY )
308 if ( !rAlt && GetAsyncKeyState ( VK_RMENU ) )
310 INVOKE_WCB ( *window, Special,
311 ( GLUT_KEY_ALT_R, window->State.MouseX, window->State.MouseY )
317 /* Checking for CTRL, ALT, and SHIFT key positions: Key Up! */
318 if ( lControl && !GetAsyncKeyState ( VK_LCONTROL ) )
320 INVOKE_WCB ( *window, SpecialUp,
321 ( GLUT_KEY_CTRL_L, window->State.MouseX, window->State.MouseY )
327 if ( rControl && !GetAsyncKeyState ( VK_RCONTROL ) )
329 INVOKE_WCB ( *window, SpecialUp,
330 ( GLUT_KEY_CTRL_R, window->State.MouseX, window->State.MouseY )
336 if ( lShift && !GetAsyncKeyState ( VK_LSHIFT ) )
338 INVOKE_WCB ( *window, SpecialUp,
339 ( GLUT_KEY_SHIFT_L, window->State.MouseX, window->State.MouseY )
345 if ( rShift && !GetAsyncKeyState ( VK_RSHIFT ) )
347 INVOKE_WCB ( *window, SpecialUp,
348 ( GLUT_KEY_SHIFT_R, window->State.MouseX, window->State.MouseY )
354 if ( lAlt && !GetAsyncKeyState ( VK_LMENU ) )
356 INVOKE_WCB ( *window, SpecialUp,
357 ( GLUT_KEY_ALT_L, window->State.MouseX, window->State.MouseY )
363 if ( rAlt && !GetAsyncKeyState ( VK_RMENU ) )
365 INVOKE_WCB ( *window, SpecialUp,
366 ( GLUT_KEY_ALT_R, window->State.MouseX, window->State.MouseY )
372 fgState.Modifiers = INVALID_MODIFIERS;
378 /* The window structure is passed as the creation structure parameter... */
379 window = (SFG_Window *) (((LPCREATESTRUCT) lParam)->lpCreateParams);
380 FREEGLUT_INTERNAL_ERROR_EXIT ( ( window != NULL ), "Cannot create window",
381 "fgPlatformWindowProc" );
383 window->Window.Handle = hWnd;
384 window->Window.pContext.Device = GetDC( hWnd );
387 unsigned int current_DisplayMode = fgState.DisplayMode;
388 fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH;
389 #if !defined(_WIN32_WCE)
390 fgSetupPixelFormat( window, GL_FALSE, PFD_MAIN_PLANE );
392 fgState.DisplayMode = current_DisplayMode;
394 if( fgStructure.MenuContext )
395 wglMakeCurrent( window->Window.pContext.Device,
396 fgStructure.MenuContext->MContext
400 fgStructure.MenuContext =
401 (SFG_MenuContext *)malloc( sizeof(SFG_MenuContext) );
402 fgStructure.MenuContext->MContext =
403 wglCreateContext( window->Window.pContext.Device );
406 /* window->Window.Context = wglGetCurrentContext (); */
407 window->Window.Context = wglCreateContext( window->Window.pContext.Device );
411 #if !defined(_WIN32_WCE)
412 fgSetupPixelFormat( window, GL_FALSE, PFD_MAIN_PLANE );
415 if( ! fgState.UseCurrentContext )
416 window->Window.Context =
417 wglCreateContext( window->Window.pContext.Device );
420 window->Window.Context = wglGetCurrentContext( );
421 if( ! window->Window.Context )
422 window->Window.Context =
423 wglCreateContext( window->Window.pContext.Device );
426 #if !defined(_WIN32_WCE)
427 fgNewWGLCreateContext( window );
431 window->State.NeedToResize = GL_TRUE;
432 /* if we used CW_USEDEFAULT (thats a negative value) for the size
433 * of the window, query the window now for the size at which it
436 if( ( window->State.Width < 0 ) || ( window->State.Height < 0 ) )
438 SFG_Window *current_window = fgStructure.CurrentWindow;
440 fgSetWindow( window );
441 window->State.Width = glutGet( GLUT_WINDOW_WIDTH );
442 window->State.Height = glutGet( GLUT_WINDOW_HEIGHT );
443 fgSetWindow( current_window );
446 ReleaseDC( window->Window.Handle, window->Window.pContext.Device );
448 #if defined(_WIN32_WCE)
449 /* Take over button handling */
451 HINSTANCE dxDllLib=LoadLibrary(_T("gx.dll"));
454 GXGetDefaultKeys_=(GXGETDEFAULTKEYS)GetProcAddress(dxDllLib, _T("?GXGetDefaultKeys@@YA?AUGXKeyList@@H@Z"));
455 GXOpenInput_=(GXOPENINPUT)GetProcAddress(dxDllLib, _T("?GXOpenInput@@YAHXZ"));
460 if(GXGetDefaultKeys_)
461 gxKeyList = (*GXGetDefaultKeys_)(GX_LANDSCAPEKEYS);
464 #endif /* defined(_WIN32_WCE) */
469 * If the window is visible, then it is the user manually resizing it.
470 * If it is not, then it is the system sending us a dummy resize with
471 * zero dimensions on a "glutIconifyWindow" call.
473 if( window->State.Visible )
475 window->State.NeedToResize = GL_TRUE;
476 #if defined(_WIN32_WCE)
477 window->State.Width = HIWORD(lParam);
478 window->State.Height = LOWORD(lParam);
480 window->State.Width = LOWORD(lParam);
481 window->State.Height = HIWORD(lParam);
482 #endif /* defined(_WIN32_WCE) */
488 /* printf("WM_SETFOCUS: %p\n", window ); */
489 lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
490 INVOKE_WCB( *window, Entry, ( GLUT_ENTERED ) );
492 UpdateWindow ( hWnd );
497 SFG_Menu* menu = NULL;
498 /* printf("WM_KILLFOCUS (ismenu: %i): %p\n", window->IsMenu, window ); */
499 lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
500 INVOKE_WCB( *window, Entry, ( GLUT_LEFT ) );
502 /* If we have an open menu, see if the open menu should be closed
503 when focus was lost because user either switched
504 application or FreeGLUT window (if one is running multiple
505 windows). If so, close menu the active menu.
507 if ( fgStructure.CurrentMenu )
508 menu = fgGetActiveMenu();
512 SFG_Window* wnd = NULL;
513 HWND hwnd = GetForegroundWindow(); /* Get window with current focus */
515 /* See if its one of our windows */
516 wnd = fgWindowByHandle(hwnd);
519 /* User switched to another application*/
520 fgDeactivateMenu(menu->ParentWindow);
522 ( wnd->IsMenu && wnd->ActiveMenu && wnd->ActiveMenu->ParentWindow!=menu->ParentWindow) || /* Make sure we don't kill the menu when trying to enter a submenu */
523 (!wnd->IsMenu && wnd!=menu->ParentWindow)
525 /* User switched to another FreeGLUT window */
526 fgDeactivateMenu(menu->ParentWindow);
533 if (LOWORD(wParam) != WA_INACTIVE)
535 /* printf("WM_ACTIVATE: fgSetCursor( %p, %d)\n", window,
536 window->State.Cursor ); */
537 fgSetCursor( window, window->State.Cursor );
540 lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
545 /* printf ( "Cursor event %x %x %x %x\n", window, window->State.Cursor, lParam, wParam ) ; */
546 if( LOWORD( lParam ) == HTCLIENT )
547 fgSetCursor ( window, window->State.Cursor ) ;
549 lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
553 window->State.Visible = GL_TRUE;
554 window->State.Redisplay = GL_TRUE;
558 /* Turn on the visibility in case it was turned off somehow */
559 window->State.Visible = GL_TRUE;
560 BeginPaint( hWnd, &ps );
561 fghRedrawWindow( window );
562 EndPaint( hWnd, &ps );
566 fgDestroyWindow ( window );
567 if ( fgState.ActionOnWindowClose != GLUT_ACTION_CONTINUE_EXECUTION )
573 * The window already got destroyed, so don't bother with it.
579 #if defined(_WIN32_WCE)
580 window->State.MouseX = 320-HIWORD( lParam );
581 window->State.MouseY = LOWORD( lParam );
583 window->State.MouseX = LOWORD( lParam );
584 window->State.MouseY = HIWORD( lParam );
585 #endif /* defined(_WIN32_WCE) */
586 /* Restrict to [-32768, 32767] to match X11 behaviour */
587 /* See comment in "freeglut_developer" mailing list 10/4/04 */
588 if ( window->State.MouseX > 32767 ) window->State.MouseX -= 65536;
589 if ( window->State.MouseY > 32767 ) window->State.MouseY -= 65536;
591 if ( window->ActiveMenu )
593 fgUpdateMenuHighlight( window->ActiveMenu );
597 fgState.Modifiers = fgPlatformGetModifiers( );
599 if( ( wParam & MK_LBUTTON ) ||
600 ( wParam & MK_MBUTTON ) ||
601 ( wParam & MK_RBUTTON ) )
602 INVOKE_WCB( *window, Motion, ( window->State.MouseX,
603 window->State.MouseY ) );
605 INVOKE_WCB( *window, Passive, ( window->State.MouseX,
606 window->State.MouseY ) );
608 fgState.Modifiers = INVALID_MODIFIERS;
619 GLboolean pressed = GL_TRUE;
622 #if defined(_WIN32_WCE)
623 window->State.MouseX = 320-HIWORD( lParam );
624 window->State.MouseY = LOWORD( lParam );
626 window->State.MouseX = LOWORD( lParam );
627 window->State.MouseY = HIWORD( lParam );
628 #endif /* defined(_WIN32_WCE) */
630 /* Restrict to [-32768, 32767] to match X11 behaviour */
631 /* See comment in "freeglut_developer" mailing list 10/4/04 */
632 if ( window->State.MouseX > 32767 ) window->State.MouseX -= 65536;
633 if ( window->State.MouseY > 32767 ) window->State.MouseY -= 65536;
639 button = GLUT_LEFT_BUTTON;
643 button = GLUT_MIDDLE_BUTTON;
647 button = GLUT_RIGHT_BUTTON;
651 button = GLUT_LEFT_BUTTON;
655 button = GLUT_MIDDLE_BUTTON;
659 button = GLUT_RIGHT_BUTTON;
667 #if !defined(_WIN32_WCE)
668 if( GetSystemMetrics( SM_SWAPBUTTON ) )
670 if( button == GLUT_LEFT_BUTTON )
671 button = GLUT_RIGHT_BUTTON;
673 if( button == GLUT_RIGHT_BUTTON )
674 button = GLUT_LEFT_BUTTON;
676 #endif /* !defined(_WIN32_WCE) */
679 return DefWindowProc( hWnd, uMsg, lParam, wParam );
682 * Do not execute the application's mouse callback if a menu
683 * is hooked to this button. In that case an appropriate
684 * private call should be generated.
686 if( fgCheckActiveMenu( window, button, pressed,
687 window->State.MouseX, window->State.MouseY ) )
690 /* Set capture so that the window captures all the mouse messages */
692 * XXX - Multiple button support: Under X11, the mouse is not released
693 * XXX - from the window until all buttons have been released, even if the
694 * XXX - user presses a button in another window. This will take more
695 * XXX - code changes than I am up to at the moment (10/5/04). The present
696 * XXX - is a 90 percent solution.
698 if ( pressed == GL_TRUE )
699 SetCapture ( window->Window.Handle ) ;
703 if( ! FETCH_WCB( *window, Mouse ) )
706 fgSetWindow( window );
707 fgState.Modifiers = fgPlatformGetModifiers( );
712 pressed ? GLUT_DOWN : GLUT_UP,
713 window->State.MouseX,
718 fgState.Modifiers = INVALID_MODIFIERS;
724 int wheel_number = LOWORD( wParam );
725 short ticks = ( short )HIWORD( wParam );
726 fgState.MouseWheelTicks += ticks;
729 * XXX Should use WHEEL_DELTA instead of 120
731 if ( abs ( fgState.MouseWheelTicks ) >= 120 )
733 int direction = ( fgState.MouseWheelTicks > 0 ) ? 1 : -1;
735 if( ! FETCH_WCB( *window, MouseWheel ) &&
736 ! FETCH_WCB( *window, Mouse ) )
739 fgSetWindow( window );
740 fgState.Modifiers = fgPlatformGetModifiers( );
743 * XXX Should use WHEEL_DELTA instead of 120
745 while( abs ( fgState.MouseWheelTicks ) >= 120 )
747 if( FETCH_WCB( *window, MouseWheel ) )
748 INVOKE_WCB( *window, MouseWheel,
751 window->State.MouseX,
755 else /* No mouse wheel, call the mouse button callback twice */
758 * Map wheel zero to button 3 and 4; +1 to 3, -1 to 4
759 * " " one +1 to 5, -1 to 6, ...
761 * XXX The below assumes that you have no more than 3 mouse
762 * XXX buttons. Sorry.
764 int button = wheel_number * 2 + 3;
767 INVOKE_WCB( *window, Mouse,
769 window->State.MouseX, window->State.MouseY )
771 INVOKE_WCB( *window, Mouse,
773 window->State.MouseX, window->State.MouseY )
778 * XXX Should use WHEEL_DELTA instead of 120
780 fgState.MouseWheelTicks -= 120 * direction;
783 fgState.Modifiers = INVALID_MODIFIERS;
795 if( ( fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE ) && (HIWORD(lParam) & KF_REPEAT) )
799 * Remember the current modifiers state. This is done here in order
800 * to make sure the VK_DELETE keyboard callback is executed properly.
802 fgState.Modifiers = fgPlatformGetModifiers( );
804 GetCursorPos( &mouse_pos );
805 ScreenToClient( window->Window.Handle, &mouse_pos );
807 window->State.MouseX = mouse_pos.x;
808 window->State.MouseY = mouse_pos.y;
810 /* Convert the Win32 keystroke codes to GLUTtish way */
811 # define KEY(a,b) case a: keypress = b; break;
815 KEY( VK_F1, GLUT_KEY_F1 );
816 KEY( VK_F2, GLUT_KEY_F2 );
817 KEY( VK_F3, GLUT_KEY_F3 );
818 KEY( VK_F4, GLUT_KEY_F4 );
819 KEY( VK_F5, GLUT_KEY_F5 );
820 KEY( VK_F6, GLUT_KEY_F6 );
821 KEY( VK_F7, GLUT_KEY_F7 );
822 KEY( VK_F8, GLUT_KEY_F8 );
823 KEY( VK_F9, GLUT_KEY_F9 );
824 KEY( VK_F10, GLUT_KEY_F10 );
825 KEY( VK_F11, GLUT_KEY_F11 );
826 KEY( VK_F12, GLUT_KEY_F12 );
827 KEY( VK_PRIOR, GLUT_KEY_PAGE_UP );
828 KEY( VK_NEXT, GLUT_KEY_PAGE_DOWN );
829 KEY( VK_HOME, GLUT_KEY_HOME );
830 KEY( VK_END, GLUT_KEY_END );
831 KEY( VK_LEFT, GLUT_KEY_LEFT );
832 KEY( VK_UP, GLUT_KEY_UP );
833 KEY( VK_RIGHT, GLUT_KEY_RIGHT );
834 KEY( VK_DOWN, GLUT_KEY_DOWN );
835 KEY( VK_INSERT, GLUT_KEY_INSERT );
837 case VK_LCONTROL: case VK_RCONTROL: case VK_CONTROL:
838 case VK_LSHIFT: case VK_RSHIFT: case VK_SHIFT:
839 case VK_LMENU: case VK_RMENU: case VK_MENU:
840 /* These keypresses and releases are handled earlier in the function */
844 /* The delete key should be treated as an ASCII keypress: */
845 INVOKE_WCB( *window, Keyboard,
846 ( 127, window->State.MouseX, window->State.MouseY )
850 #if defined(_WIN32_WCE)
851 if(!(lParam & 0x40000000)) /* Prevent auto-repeat */
853 if(wParam==(unsigned)gxKeyList.vkRight)
854 keypress = GLUT_KEY_RIGHT;
855 else if(wParam==(unsigned)gxKeyList.vkLeft)
856 keypress = GLUT_KEY_LEFT;
857 else if(wParam==(unsigned)gxKeyList.vkUp)
858 keypress = GLUT_KEY_UP;
859 else if(wParam==(unsigned)gxKeyList.vkDown)
860 keypress = GLUT_KEY_DOWN;
861 else if(wParam==(unsigned)gxKeyList.vkA)
862 keypress = GLUT_KEY_F1;
863 else if(wParam==(unsigned)gxKeyList.vkB)
864 keypress = GLUT_KEY_F2;
865 else if(wParam==(unsigned)gxKeyList.vkC)
866 keypress = GLUT_KEY_F3;
867 else if(wParam==(unsigned)gxKeyList.vkStart)
868 keypress = GLUT_KEY_F4;
873 INVOKE_WCB( *window, Special,
875 window->State.MouseX, window->State.MouseY )
878 fgState.Modifiers = INVALID_MODIFIERS;
889 * Remember the current modifiers state. This is done here in order
890 * to make sure the VK_DELETE keyboard callback is executed properly.
892 fgState.Modifiers = fgPlatformGetModifiers( );
894 GetCursorPos( &mouse_pos );
895 ScreenToClient( window->Window.Handle, &mouse_pos );
897 window->State.MouseX = mouse_pos.x;
898 window->State.MouseY = mouse_pos.y;
901 * Convert the Win32 keystroke codes to GLUTtish way.
902 * "KEY(a,b)" was defined under "WM_KEYDOWN"
907 KEY( VK_F1, GLUT_KEY_F1 );
908 KEY( VK_F2, GLUT_KEY_F2 );
909 KEY( VK_F3, GLUT_KEY_F3 );
910 KEY( VK_F4, GLUT_KEY_F4 );
911 KEY( VK_F5, GLUT_KEY_F5 );
912 KEY( VK_F6, GLUT_KEY_F6 );
913 KEY( VK_F7, GLUT_KEY_F7 );
914 KEY( VK_F8, GLUT_KEY_F8 );
915 KEY( VK_F9, GLUT_KEY_F9 );
916 KEY( VK_F10, GLUT_KEY_F10 );
917 KEY( VK_F11, GLUT_KEY_F11 );
918 KEY( VK_F12, GLUT_KEY_F12 );
919 KEY( VK_PRIOR, GLUT_KEY_PAGE_UP );
920 KEY( VK_NEXT, GLUT_KEY_PAGE_DOWN );
921 KEY( VK_HOME, GLUT_KEY_HOME );
922 KEY( VK_END, GLUT_KEY_END );
923 KEY( VK_LEFT, GLUT_KEY_LEFT );
924 KEY( VK_UP, GLUT_KEY_UP );
925 KEY( VK_RIGHT, GLUT_KEY_RIGHT );
926 KEY( VK_DOWN, GLUT_KEY_DOWN );
927 KEY( VK_INSERT, GLUT_KEY_INSERT );
929 case VK_LCONTROL: case VK_RCONTROL: case VK_CONTROL:
930 case VK_LSHIFT: case VK_RSHIFT: case VK_SHIFT:
931 case VK_LMENU: case VK_RMENU: case VK_MENU:
932 /* These keypresses and releases are handled earlier in the function */
936 /* The delete key should be treated as an ASCII keypress: */
937 INVOKE_WCB( *window, KeyboardUp,
938 ( 127, window->State.MouseX, window->State.MouseY )
944 #if !defined(_WIN32_WCE)
948 GetKeyboardState( state );
950 if( ToAscii( (UINT)wParam, 0, state, code, 0 ) == 1 )
953 INVOKE_WCB( *window, KeyboardUp,
955 window->State.MouseX, window->State.MouseY )
957 #endif /* !defined(_WIN32_WCE) */
962 INVOKE_WCB( *window, SpecialUp,
964 window->State.MouseX, window->State.MouseY )
967 fgState.Modifiers = INVALID_MODIFIERS;
974 if( (fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE) && (HIWORD(lParam) & KF_REPEAT) )
977 fgState.Modifiers = fgPlatformGetModifiers( );
978 INVOKE_WCB( *window, Keyboard,
980 window->State.MouseX, window->State.MouseY )
982 fgState.Modifiers = INVALID_MODIFIERS;
986 case WM_CAPTURECHANGED:
987 /* User has finished resizing the window, force a redraw */
988 INVOKE_WCB( *window, Display, ( ) );
990 /*lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); */
993 /* Other messages that I have seen and which are not handled already */
994 case WM_SETTEXT: /* 0x000c */
995 lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
996 /* Pass it on to "DefWindowProc" to set the window text */
999 case WM_GETTEXT: /* 0x000d */
1000 /* Ideally we would copy the title of the window into "lParam" */
1001 /* strncpy ( (char *)lParam, "Window Title", wParam );
1002 lRet = ( wParam > 12 ) ? 12 : wParam; */
1003 /* the number of characters copied */
1004 lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
1007 case WM_GETTEXTLENGTH: /* 0x000e */
1008 /* Ideally we would get the length of the title of the window */
1010 /* the number of characters in "Window Title\0" (see above) */
1013 case WM_ERASEBKGND: /* 0x0014 */
1014 lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
1017 #if !defined(_WIN32_WCE)
1018 case WM_SYNCPAINT: /* 0x0088 */
1019 /* Another window has moved, need to update this one */
1020 window->State.Redisplay = GL_TRUE;
1021 lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
1022 /* Help screen says this message must be passed to "DefWindowProc" */
1025 case WM_NCPAINT: /* 0x0085 */
1026 /* Need to update the border of this window */
1027 lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
1028 /* Pass it on to "DefWindowProc" to repaint a standard border */
1031 case WM_SYSCOMMAND : /* 0x0112 */
1034 * We have received a system command message. Try to act on it.
1035 * The commands are passed in through the "wParam" parameter:
1036 * The least significant digit seems to be which edge of the window
1037 * is being used for a resize event:
1041 * Congratulations and thanks to Richard Rauch for figuring this out..
1043 switch ( wParam & 0xfff0 )
1052 /* User has clicked on the "-" to minimize the window */
1053 /* Turn off the visibility */
1054 window->State.Visible = GL_FALSE ;
1061 case SC_NEXTWINDOW :
1064 case SC_PREVWINDOW :
1068 /* Followed very closely by a WM_CLOSE message */
1092 case SC_SCREENSAVE :
1098 #if(WINVER >= 0x0400)
1102 case SC_MONITORPOWER :
1105 case SC_CONTEXTHELP :
1107 #endif /* WINVER >= 0x0400 */
1111 fgWarning( "Unknown wParam type 0x%x", wParam );
1116 #endif /* !defined(_WIN32_WCE) */
1118 /* We need to pass the message on to the operating system as well */
1119 lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
1123 /* handle multi-touch messages */
1126 unsigned int numInputs = (unsigned int)wParam;
1128 TOUCHINPUT* ti = (TOUCHINPUT*)malloc( sizeof(TOUCHINPUT)*numInputs);
1130 if (fghGetTouchInputInfo == (pGetTouchInputInfo)0xDEADBEEF) {
1131 fghGetTouchInputInfo = (pGetTouchInputInfo)GetProcAddress(GetModuleHandle("user32"),"GetTouchInputInfo");
1132 fghCloseTouchInputHandle = (pCloseTouchInputHandle)GetProcAddress(GetModuleHandle("user32"),"CloseTouchInputHandle");
1135 if (!fghGetTouchInputInfo) {
1140 if (fghGetTouchInputInfo( (HTOUCHINPUT)lParam, numInputs, ti, sizeof(TOUCHINPUT) )) {
1141 /* Handle each contact point */
1142 for (i = 0; i < numInputs; ++i ) {
1145 tp.x = TOUCH_COORD_TO_PIXEL(ti[i].x);
1146 tp.y = TOUCH_COORD_TO_PIXEL(ti[i].y);
1147 ScreenToClient( hWnd, &tp );
1149 ti[i].dwID = ti[i].dwID * 2;
1151 if (ti[i].dwFlags & TOUCHEVENTF_DOWN) {
1152 INVOKE_WCB( *window, MultiEntry, ( ti[i].dwID, GLUT_ENTERED ) );
1153 INVOKE_WCB( *window, MultiButton, ( ti[i].dwID, tp.x, tp.y, 0, GLUT_DOWN ) );
1154 } else if (ti[i].dwFlags & TOUCHEVENTF_MOVE) {
1155 INVOKE_WCB( *window, MultiMotion, ( ti[i].dwID, tp.x, tp.y ) );
1156 } else if (ti[i].dwFlags & TOUCHEVENTF_UP) {
1157 INVOKE_WCB( *window, MultiButton, ( ti[i].dwID, tp.x, tp.y, 0, GLUT_UP ) );
1158 INVOKE_WCB( *window, MultiEntry, ( ti[i].dwID, GLUT_LEFT ) );
1162 fghCloseTouchInputHandle((HTOUCHINPUT)lParam);
1164 lRet = 0; /*DefWindowProc( hWnd, uMsg, wParam, lParam );*/
1169 /* Handle unhandled messages */
1170 lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );