*/
while( window )
{
- if ( FETCH_WCB( *window, Visibility ) )
+ if ( FETCH_WCB( *window, WindowStatus ) )
{
SFG_Window *current_window = fgStructure.CurrentWindow ;
- INVOKE_WCB( *window, Visibility, ( window->State.Visible ) );
+ INVOKE_WCB( *window, WindowStatus, ( window->State.Visible?GLUT_FULLY_RETAINED:GLUT_HIDDEN ) );
fgSetWindow( current_window );
}
( GetKeyState( VK_RMENU ) < 0 )) ? GLUT_ACTIVE_ALT : 0 );
}
-/*
- * The window procedure for handling Win32 events
- */
-LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
- LPARAM lParam )
+static LRESULT fghWindowProcKeyPress(SFG_Window *window, UINT uMsg, GLboolean keydown, WPARAM wParam, LPARAM lParam)
{
- static unsigned char lControl = 0, rControl = 0, lShift = 0,
- rShift = 0, lAlt = 0, rAlt = 0;
+ static unsigned char lControl = 0, lShift = 0, lAlt = 0,
+ rControl = 0, rShift = 0, rAlt = 0;
- SFG_Window *window, *child_window = NULL;
- PAINTSTRUCT ps;
- LRESULT lRet = 1;
+ int keypress = -1;
+
+ /* if keydown, check for repeat */
+ /* If repeat is globally switched off, it cannot be switched back on per window.
+ * But if it is globally switched on, it can be switched off per window. This matches
+ * GLUT's behavior on X11, but not Nate Robbins' win32 GLUT, as he didn't implement the
+ * global state switch.
+ */
+ if( keydown && ( fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE ) && (HIWORD(lParam) & KF_REPEAT) )
+ return 1;
+
+ /* Remember the current modifiers state so user can query it from their callback */
+ fgState.Modifiers = fgPlatformGetModifiers( );
- FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED ( "Event Handler" ) ;
+ /* Convert the Win32 keystroke codes to GLUTtish way */
+# define KEY(a,b) case a: keypress = b; break;
- window = fgWindowByHandle( hWnd );
+ switch( wParam )
+ {
+ KEY( VK_F1, GLUT_KEY_F1 );
+ KEY( VK_F2, GLUT_KEY_F2 );
+ KEY( VK_F3, GLUT_KEY_F3 );
+ KEY( VK_F4, GLUT_KEY_F4 );
+ KEY( VK_F5, GLUT_KEY_F5 );
+ KEY( VK_F6, GLUT_KEY_F6 );
+ KEY( VK_F7, GLUT_KEY_F7 );
+ KEY( VK_F8, GLUT_KEY_F8 );
+ KEY( VK_F9, GLUT_KEY_F9 );
+ KEY( VK_F10, GLUT_KEY_F10 );
+ KEY( VK_F11, GLUT_KEY_F11 );
+ KEY( VK_F12, GLUT_KEY_F12 );
+ KEY( VK_PRIOR, GLUT_KEY_PAGE_UP );
+ KEY( VK_NEXT, GLUT_KEY_PAGE_DOWN );
+ KEY( VK_HOME, GLUT_KEY_HOME );
+ KEY( VK_END, GLUT_KEY_END );
+ KEY( VK_LEFT, GLUT_KEY_LEFT );
+ KEY( VK_UP, GLUT_KEY_UP );
+ KEY( VK_RIGHT, GLUT_KEY_RIGHT );
+ KEY( VK_DOWN, GLUT_KEY_DOWN );
+ KEY( VK_INSERT, GLUT_KEY_INSERT );
+
+ /* handle control, alt and shift. For GLUT, we want to distinguish between left and right presses.
+ * The VK_L* & VK_R* left and right Alt, Ctrl and Shift virtual keys are however only used as parameters to GetAsyncKeyState() and GetKeyState()
+ * so when we get an alt, shift or control keypress here, we manually check whether it was the left or the right
+ */
+#define ASYNC_KEY_EVENT(winKey,glutKey,keyStateVar)\
+ if (!keyStateVar && GetAsyncKeyState ( winKey ))\
+ {\
+ keypress = glutKey;\
+ keyStateVar = 1;\
+ }\
+ else if (keyStateVar && !GetAsyncKeyState ( winKey ))\
+ {\
+ keypress = glutKey;\
+ keyStateVar = 0;\
+ }
+ case VK_CONTROL:
+ ASYNC_KEY_EVENT(VK_LCONTROL,GLUT_KEY_CTRL_L,lControl);
+ ASYNC_KEY_EVENT(VK_RCONTROL,GLUT_KEY_CTRL_R,rControl);
+ break;
+ case VK_SHIFT:
+ ASYNC_KEY_EVENT(VK_LSHIFT,GLUT_KEY_SHIFT_L,lShift);
+ ASYNC_KEY_EVENT(VK_RSHIFT,GLUT_KEY_SHIFT_R,rShift);
+ break;
+ case VK_MENU:
+ ASYNC_KEY_EVENT(VK_LMENU,GLUT_KEY_ALT_L,lAlt);
+ ASYNC_KEY_EVENT(VK_RMENU,GLUT_KEY_ALT_R,rAlt);
+ break;
+#undef ASYNC_KEY_EVENT
- if ( ( window == NULL ) && ( uMsg != WM_CREATE ) )
- return DefWindowProc( hWnd, uMsg, wParam, lParam );
+ case VK_DELETE:
+ /* The delete key should be treated as an ASCII keypress: */
+ if (keydown)
+ INVOKE_WCB( *window, Keyboard,
+ ( 127, window->State.MouseX, window->State.MouseY )
+ );
+ else
+ INVOKE_WCB( *window, KeyboardUp,
+ ( 127, window->State.MouseX, window->State.MouseY )
+ );
+ break;
- /* printf ( "Window %3d message <%04x> %12d %12d\n", window?window->ID:0,
- uMsg, wParam, lParam ); */
+#if !defined(_WIN32_WCE)
+ default:
+ /* keydown displayable characters are handled with WM_CHAR message, but no corresponding up is generated. So get that here. */
+ if (!keydown)
+ {
+ BYTE state[ 256 ];
+ WORD code[ 2 ];
+
+ GetKeyboardState( state );
+
+ if( ToAscii( (UINT)wParam, 0, state, code, 0 ) == 1 )
+ wParam=code[ 0 ];
+
+ INVOKE_WCB( *window, KeyboardUp,
+ ( (char)wParam,
+ window->State.MouseX, window->State.MouseY )
+ );
+ }
+#endif
+ }
+
+#if defined(_WIN32_WCE)
+ if(keydown && !(lParam & 0x40000000)) /* Prevent auto-repeat */
+ {
+ if(wParam==(unsigned)gxKeyList.vkRight)
+ keypress = GLUT_KEY_RIGHT;
+ else if(wParam==(unsigned)gxKeyList.vkLeft)
+ keypress = GLUT_KEY_LEFT;
+ else if(wParam==(unsigned)gxKeyList.vkUp)
+ keypress = GLUT_KEY_UP;
+ else if(wParam==(unsigned)gxKeyList.vkDown)
+ keypress = GLUT_KEY_DOWN;
+ else if(wParam==(unsigned)gxKeyList.vkA)
+ keypress = GLUT_KEY_F1;
+ else if(wParam==(unsigned)gxKeyList.vkB)
+ keypress = GLUT_KEY_F2;
+ else if(wParam==(unsigned)gxKeyList.vkC)
+ keypress = GLUT_KEY_F3;
+ else if(wParam==(unsigned)gxKeyList.vkStart)
+ keypress = GLUT_KEY_F4;
+ }
+#endif
+
+ if( keypress != -1 )
+ if (keydown)
+ INVOKE_WCB( *window, Special,
+ ( keypress,
+ window->State.MouseX, window->State.MouseY )
+ );
+ else
+ INVOKE_WCB( *window, SpecialUp,
+ ( keypress,
+ window->State.MouseX, window->State.MouseY )
+ );
+
+ fgState.Modifiers = INVALID_MODIFIERS;
- /* Some events only sent to main window. Check if the current window that
- * the mouse is over is a child window. Below when handling some messages,
- * we make sure that we process callbacks on the child window instead.
- * This mirrors how GLUT does things.
+ /* SYSKEY events should be sent to default window proc for system to handle them */
+ if (uMsg==WM_SYSKEYDOWN || uMsg==WM_SYSKEYUP)
+ return DefWindowProc( window->Window.Handle, uMsg, wParam, lParam );
+ else
+ return 1;
+}
+
+static SFG_Window* fghWindowUnderCursor(SFG_Window *window)
+{
+ /* Check if the current window that the mouse is over is a child window
+ * of the window the message was sent to. Some events only sent to main window,
+ * and when handling some messages, we need to make sure that we process
+ * callbacks on the child window instead. This mirrors how GLUT does things.
+ * returns either the original window or the found child.
*/
- if (window && window->Children.First)
+ if (window && window->Children.First) /* This window has childs */
{
- POINT mouse_pos;
SFG_WindowHandleType hwnd;
- SFG_Window* temp_window;
+ SFG_Window* child_window;
- GetCursorPos( &mouse_pos );
+ /* Get mouse position at time of message */
+ DWORD mouse_pos_dw = GetMessagePos();
+ POINT mouse_pos = {GET_X_LPARAM(mouse_pos_dw), GET_Y_LPARAM(mouse_pos_dw)};
ScreenToClient( window->Window.Handle, &mouse_pos );
+
hwnd = ChildWindowFromPoint(window->Window.Handle, mouse_pos);
- if (hwnd) /* can be NULL if mouse outside parent by the time we get here */
+ if (hwnd && hwnd!=window->Window.Handle) /* can be NULL if mouse outside parent by the time we get here, or can be same as parent if we didn't find a child */
{
- temp_window = fgWindowByHandle(hwnd);
- if (temp_window && temp_window->Parent) /* Verify we got a child window */
- child_window = temp_window;
+ child_window = fgWindowByHandle(hwnd);
+ if (child_window) /* Verify we got a FreeGLUT window */
+ {
+ /* ChildWindowFromPoint only searches immediate children, so search again to see if actually in grandchild or further descendant */
+ window = fghWindowUnderCursor(child_window);
+ }
}
}
- if ( window )
- {
- SFG_Window* temp_window = child_window?child_window:window;
-
- fgState.Modifiers = fgPlatformGetModifiers( );
-
- /* Checking for CTRL, ALT, and SHIFT key positions: Key Down! */
-#define SPECIAL_KEY_DOWN(winKey,glutKey,winProcVar)\
- if ( !winProcVar && GetAsyncKeyState ( winKey ) )\
- {\
- INVOKE_WCB ( *temp_window, Special,\
- ( glutKey, temp_window->State.MouseX, temp_window->State.MouseY )\
- );\
- winProcVar = 1;\
- }
-
- SPECIAL_KEY_DOWN(VK_LCONTROL,GLUT_KEY_CTRL_L ,lControl);
- SPECIAL_KEY_DOWN(VK_RCONTROL,GLUT_KEY_CTRL_R ,rControl);
- SPECIAL_KEY_DOWN(VK_LSHIFT ,GLUT_KEY_SHIFT_L,lShift);
- SPECIAL_KEY_DOWN(VK_RSHIFT ,GLUT_KEY_SHIFT_R,rShift);
- SPECIAL_KEY_DOWN(VK_LMENU ,GLUT_KEY_ALT_L ,lAlt);
- SPECIAL_KEY_DOWN(VK_RMENU ,GLUT_KEY_ALT_R ,rAlt);
-#undef SPECIAL_KEY_DOWN
-
- /* Checking for CTRL, ALT, and SHIFT key positions: Key Up! */
-#define SPECIAL_KEY_UP(winKey,glutKey,winProcVar)\
- if ( winProcVar && !GetAsyncKeyState ( winKey ) )\
- {\
- INVOKE_WCB ( *temp_window, SpecialUp,\
- ( glutKey, temp_window->State.MouseX, temp_window->State.MouseY )\
- );\
- winProcVar = 0;\
- }
-
- SPECIAL_KEY_UP(VK_LCONTROL,GLUT_KEY_CTRL_L ,lControl);
- SPECIAL_KEY_UP(VK_RCONTROL,GLUT_KEY_CTRL_R ,rControl);
- SPECIAL_KEY_UP(VK_LSHIFT ,GLUT_KEY_SHIFT_L,lShift);
- SPECIAL_KEY_UP(VK_RSHIFT ,GLUT_KEY_SHIFT_R,rShift);
- SPECIAL_KEY_UP(VK_LMENU ,GLUT_KEY_ALT_L ,lAlt);
- SPECIAL_KEY_UP(VK_RMENU ,GLUT_KEY_ALT_R ,rAlt);
-#undef SPECIAL_KEY_UP
-
- fgState.Modifiers = INVALID_MODIFIERS;
- }
+ return window;
+}
+
+/*
+ * The window procedure for handling Win32 events
+ */
+LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+ SFG_Window *window;
+ LRESULT lRet = 1;
+ static int setCaptureActive = 0;
+
+ FREEGLUT_INTERNAL_ERROR_EXIT_IF_NOT_INITIALISED ( "Event Handler" ) ;
+
+ window = fgWindowByHandle( hWnd );
+
+ if ( ( window == NULL ) && ( uMsg != WM_CREATE ) )
+ return DefWindowProc( hWnd, uMsg, wParam, lParam );
+
+ /* printf ( "Window %3d message <%04x> %12d %12d\n", window?window->ID:0,
+ uMsg, wParam, lParam ); */
switch( uMsg )
{
lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
- if (child_window)
- {
- /* If we're dealing with a child window, make sure it has input focus instead, set it here. */
- SetFocus(child_window->Window.Handle);
- SetActiveWindow( child_window->Window.Handle );
- INVOKE_WCB( *child_window, Entry, ( GLUT_ENTERED ) );
- UpdateWindow ( child_window->Window.Handle );
- }
- else
- {
- SetActiveWindow( window->Window.Handle );
- INVOKE_WCB( *window, Entry, ( GLUT_ENTERED ) );
- }
- /* Always request update on main window to be safe */
+ SetActiveWindow( window->Window.Handle );
UpdateWindow ( hWnd );
break;
case WM_KILLFOCUS:
{
- SFG_Window* saved_window = fgStructure.CurrentWindow;
/* printf("WM_KILLFOCUS: %p\n", window ); */
lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
- INVOKE_WCB( *window, Entry, ( GLUT_LEFT ) );
- fgSetWindow(saved_window);
/* Check if there are any open menus that need to be closed */
fgPlatformCheckMenuDeactivate();
#if 0
case WM_ACTIVATE:
+ //printf("WM_ACTIVATE: %x %d %d\n",lParam, HIWORD(wParam), LOWORD(wParam));
if (LOWORD(wParam) != WA_INACTIVE)
{
/* printf("WM_ACTIVATE: fgSetCursor( %p, %d)\n", window,
case WM_SETCURSOR:
/* printf ( "Cursor event %x %x %x %x\n", window, window->State.Cursor, lParam, wParam ) ; */
if( LOWORD( lParam ) == HTCLIENT )
- fgSetCursor ( window, window->State.Cursor ) ;
+ {
+ if (!window->State.pWState.MouseTracking)
+ {
+ TRACKMOUSEEVENT tme;
+
+ /* Cursor just entered window, set cursor look */
+ fgSetCursor ( window, window->State.Cursor ) ;
+
+ /* If an EntryFunc callback is specified by the user, also
+ * invoke that callback and start mouse tracking so that
+ * we get a WM_MOUSELEAVE message
+ */
+ if (FETCH_WCB( *window, Entry ))
+ {
+ INVOKE_WCB( *window, Entry, ( GLUT_ENTERED ) );
+
+ tme.cbSize = sizeof(TRACKMOUSEEVENT);
+ tme.dwFlags = TME_LEAVE;
+ tme.hwndTrack = window->Window.Handle;
+ TrackMouseEvent(&tme);
+
+ window->State.pWState.MouseTracking = GL_TRUE;
+ }
+ }
+ }
else
+ /* Only pass non-client WM_SETCURSOR to DefWindowProc, or we get WM_SETCURSOR on parents of children as well */
lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
break;
+ case WM_MOUSELEAVE:
+ {
+ /* NB: This message is only received when a EntryFunc callback
+ * is specified by the user, as that is the only condition under
+ * which mouse tracking is setup in WM_SETCURSOR handler above
+ */
+ SFG_Window* saved_window = fgStructure.CurrentWindow;
+ INVOKE_WCB( *window, Entry, ( GLUT_LEFT ) );
+ fgSetWindow(saved_window);
+
+ window->State.pWState.MouseTracking = GL_FALSE;
+ lRet = 0; /* As per docs, must return zero */
+ }
+ break;
+
case WM_SHOWWINDOW:
window->State.Visible = GL_TRUE;
window->State.Redisplay = GL_TRUE;
break;
case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
/* Turn on the visibility in case it was turned off somehow */
window->State.Visible = GL_TRUE;
InvalidateRect( hWnd, NULL, GL_FALSE ); /* Make sure whole window is repainted. Bit of a hack, but a safe one from what google turns up... */
BeginPaint( hWnd, &ps );
fghRedrawWindow( window );
EndPaint( hWnd, &ps );
- break;
+ }
+ break;
case WM_CLOSE:
fgDestroyWindow ( window );
window->State.MouseX, window->State.MouseY ) )
break;
- /* Set capture so that the window captures all the mouse messages */
- /*
- * XXX - Multiple button support: Under X11, the mouse is not released
- * XXX - from the window until all buttons have been released, even if the
- * XXX - user presses a button in another window. This will take more
- * XXX - code changes than I am up to at the moment (10/5/04). The present
- * XXX - is a 90 percent solution.
+ /* Set capture so that the window captures all the mouse messages
+ *
+ * The mouse is not released from the window until all buttons have
+ * been released, even if the user presses a button in another window.
+ * This is consistent with the behavior on X11.
*/
if ( pressed == GL_TRUE )
- SetCapture ( window->Window.Handle ) ;
- else
+ {
+ if (!setCaptureActive)
+ SetCapture ( window->Window.Handle ) ;
+ setCaptureActive = 1; /* Set to false in WM_CAPTURECHANGED handler */
+ }
+ else if (!GetAsyncKeyState(VK_LBUTTON) && !GetAsyncKeyState(VK_MBUTTON) && !GetAsyncKeyState(VK_RBUTTON))
+ /* Make sure all mouse buttons are released before releasing capture */
ReleaseCapture () ;
if( ! FETCH_WCB( *window, Mouse ) )
);
fgState.Modifiers = INVALID_MODIFIERS;
+
+ /* As per docs, should return zero */
+ lRet = 0;
}
break;
case WM_MOUSEWHEEL:
{
+ SFG_Window *child_window = NULL;
int wheel_number = LOWORD( wParam );
short ticks = ( short )HIWORD( wParam );
- fgState.MouseWheelTicks += ticks;
+ window = fghWindowUnderCursor(window);
+
+ fgState.MouseWheelTicks += ticks;
if ( abs ( fgState.MouseWheelTicks ) >= WHEEL_DELTA )
{
int direction = ( fgState.MouseWheelTicks > 0 ) ? 1 : -1;
case WM_SYSKEYDOWN:
case WM_KEYDOWN:
{
- int keypress = -1;
- POINT mouse_pos ;
-
- if (child_window)
- window = child_window;
-
- if( ( fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE ) && (HIWORD(lParam) & KF_REPEAT) )
- break;
-
- /*
- * Remember the current modifiers state. This is done here in order
- * to make sure the VK_DELETE keyboard callback is executed properly.
- */
- fgState.Modifiers = fgPlatformGetModifiers( );
-
- GetCursorPos( &mouse_pos );
- ScreenToClient( window->Window.Handle, &mouse_pos );
-
- window->State.MouseX = mouse_pos.x;
- window->State.MouseY = mouse_pos.y;
-
- /* Convert the Win32 keystroke codes to GLUTtish way */
-# define KEY(a,b) case a: keypress = b; break;
-
- switch( wParam )
- {
- KEY( VK_F1, GLUT_KEY_F1 );
- KEY( VK_F2, GLUT_KEY_F2 );
- KEY( VK_F3, GLUT_KEY_F3 );
- KEY( VK_F4, GLUT_KEY_F4 );
- KEY( VK_F5, GLUT_KEY_F5 );
- KEY( VK_F6, GLUT_KEY_F6 );
- KEY( VK_F7, GLUT_KEY_F7 );
- KEY( VK_F8, GLUT_KEY_F8 );
- KEY( VK_F9, GLUT_KEY_F9 );
- KEY( VK_F10, GLUT_KEY_F10 );
- KEY( VK_F11, GLUT_KEY_F11 );
- KEY( VK_F12, GLUT_KEY_F12 );
- KEY( VK_PRIOR, GLUT_KEY_PAGE_UP );
- KEY( VK_NEXT, GLUT_KEY_PAGE_DOWN );
- KEY( VK_HOME, GLUT_KEY_HOME );
- KEY( VK_END, GLUT_KEY_END );
- KEY( VK_LEFT, GLUT_KEY_LEFT );
- KEY( VK_UP, GLUT_KEY_UP );
- KEY( VK_RIGHT, GLUT_KEY_RIGHT );
- KEY( VK_DOWN, GLUT_KEY_DOWN );
- KEY( VK_INSERT, GLUT_KEY_INSERT );
-
- case VK_LCONTROL: case VK_RCONTROL: case VK_CONTROL:
- case VK_LSHIFT: case VK_RSHIFT: case VK_SHIFT:
- case VK_LMENU: case VK_RMENU: case VK_MENU:
- /* These keypresses and releases are handled earlier in the function */
- break;
-
- case VK_DELETE:
- /* The delete key should be treated as an ASCII keypress: */
- INVOKE_WCB( *window, Keyboard,
- ( 127, window->State.MouseX, window->State.MouseY )
- );
- }
-
-#if defined(_WIN32_WCE)
- if(!(lParam & 0x40000000)) /* Prevent auto-repeat */
- {
- if(wParam==(unsigned)gxKeyList.vkRight)
- keypress = GLUT_KEY_RIGHT;
- else if(wParam==(unsigned)gxKeyList.vkLeft)
- keypress = GLUT_KEY_LEFT;
- else if(wParam==(unsigned)gxKeyList.vkUp)
- keypress = GLUT_KEY_UP;
- else if(wParam==(unsigned)gxKeyList.vkDown)
- keypress = GLUT_KEY_DOWN;
- else if(wParam==(unsigned)gxKeyList.vkA)
- keypress = GLUT_KEY_F1;
- else if(wParam==(unsigned)gxKeyList.vkB)
- keypress = GLUT_KEY_F2;
- else if(wParam==(unsigned)gxKeyList.vkC)
- keypress = GLUT_KEY_F3;
- else if(wParam==(unsigned)gxKeyList.vkStart)
- keypress = GLUT_KEY_F4;
- }
-#endif
-
- if( keypress != -1 )
- INVOKE_WCB( *window, Special,
- ( keypress,
- window->State.MouseX, window->State.MouseY )
- );
-
- fgState.Modifiers = INVALID_MODIFIERS;
+ window = fghWindowUnderCursor(window);
+ lRet = fghWindowProcKeyPress(window,uMsg,GL_TRUE,wParam,lParam);
}
break;
case WM_SYSKEYUP:
case WM_KEYUP:
{
- int keypress = -1;
- POINT mouse_pos;
-
- if (child_window)
- window = child_window;
-
- /*
- * Remember the current modifiers state. This is done here in order
- * to make sure the VK_DELETE keyboard callback is executed properly.
- */
- fgState.Modifiers = fgPlatformGetModifiers( );
-
- GetCursorPos( &mouse_pos );
- ScreenToClient( window->Window.Handle, &mouse_pos );
-
- window->State.MouseX = mouse_pos.x;
- window->State.MouseY = mouse_pos.y;
-
- /*
- * Convert the Win32 keystroke codes to GLUTtish way.
- * "KEY(a,b)" was defined under "WM_KEYDOWN"
- */
-
- switch( wParam )
- {
- KEY( VK_F1, GLUT_KEY_F1 );
- KEY( VK_F2, GLUT_KEY_F2 );
- KEY( VK_F3, GLUT_KEY_F3 );
- KEY( VK_F4, GLUT_KEY_F4 );
- KEY( VK_F5, GLUT_KEY_F5 );
- KEY( VK_F6, GLUT_KEY_F6 );
- KEY( VK_F7, GLUT_KEY_F7 );
- KEY( VK_F8, GLUT_KEY_F8 );
- KEY( VK_F9, GLUT_KEY_F9 );
- KEY( VK_F10, GLUT_KEY_F10 );
- KEY( VK_F11, GLUT_KEY_F11 );
- KEY( VK_F12, GLUT_KEY_F12 );
- KEY( VK_PRIOR, GLUT_KEY_PAGE_UP );
- KEY( VK_NEXT, GLUT_KEY_PAGE_DOWN );
- KEY( VK_HOME, GLUT_KEY_HOME );
- KEY( VK_END, GLUT_KEY_END );
- KEY( VK_LEFT, GLUT_KEY_LEFT );
- KEY( VK_UP, GLUT_KEY_UP );
- KEY( VK_RIGHT, GLUT_KEY_RIGHT );
- KEY( VK_DOWN, GLUT_KEY_DOWN );
- KEY( VK_INSERT, GLUT_KEY_INSERT );
-
- case VK_LCONTROL: case VK_RCONTROL: case VK_CONTROL:
- case VK_LSHIFT: case VK_RSHIFT: case VK_SHIFT:
- case VK_LMENU: case VK_RMENU: case VK_MENU:
- /* These keypresses and releases are handled earlier in the function */
- break;
-
- case VK_DELETE:
- /* The delete key should be treated as an ASCII keypress: */
- INVOKE_WCB( *window, KeyboardUp,
- ( 127, window->State.MouseX, window->State.MouseY )
- );
- break;
-
- default:
- {
-#if !defined(_WIN32_WCE)
- BYTE state[ 256 ];
- WORD code[ 2 ];
-
- GetKeyboardState( state );
-
- if( ToAscii( (UINT)wParam, 0, state, code, 0 ) == 1 )
- wParam=code[ 0 ];
-
- INVOKE_WCB( *window, KeyboardUp,
- ( (char)wParam,
- window->State.MouseX, window->State.MouseY )
- );
-#endif /* !defined(_WIN32_WCE) */
- }
- }
-
- if( keypress != -1 )
- INVOKE_WCB( *window, SpecialUp,
- ( keypress,
- window->State.MouseX, window->State.MouseY )
- );
-
- fgState.Modifiers = INVALID_MODIFIERS;
+ window = fghWindowUnderCursor(window);
+ lRet = fghWindowProcKeyPress(window,uMsg,GL_FALSE,wParam,lParam);
}
break;
case WM_SYSCHAR:
case WM_CHAR:
{
- if (child_window)
- window = child_window;
+ window = fghWindowUnderCursor(window);
if( (fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE) && (HIWORD(lParam) & KF_REPEAT) )
break;
break;
case WM_CAPTURECHANGED:
- /* User has finished resizing the window, force a redraw */
- INVOKE_WCB( *window, Display, ( ) );
-
- /*lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); */
+ if (!lParam || !fgWindowByHandle((HWND)lParam))
+ /* Capture released or capture taken by non-FreeGLUT window */
+ setCaptureActive = 0;
+ /* Docs advise a redraw */
+ InvalidateRect( hWnd, NULL, GL_FALSE );
+ UpdateWindow(hWnd);
+ lRet = 0; /* Per docs, should return zero */
break;
/* Other messages that I have seen and which are not handled already */