X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Fmswin%2Ffg_main_mswin.c;h=4588ef60f2e1dbb77c9dd32eea0d22126a50cb92;hb=e5a04661cc5c65771163df9844ee02d2a46955f0;hp=d84940f17e903221295afb1d1811d876c677ebf5;hpb=5b3d339481bac6dbaeb599bffc1325f716585bfe;p=freeglut diff --git a/src/mswin/fg_main_mswin.c b/src/mswin/fg_main_mswin.c index d84940f..4588ef6 100644 --- a/src/mswin/fg_main_mswin.c +++ b/src/mswin/fg_main_mswin.c @@ -35,6 +35,8 @@ extern void fgNewWGLCreateContext( SFG_Window* window ); extern GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly, unsigned char layer_type ); +extern void fgPlatformCheckMenuDeactivate(); + #ifdef WM_TOUCH typedef BOOL (WINAPI *pGetTouchInputInfo)(HTOUCHINPUT,UINT,PTOUCHINPUT,int); typedef BOOL (WINAPI *pCloseTouchInputHandle)(HTOUCHINPUT); @@ -61,8 +63,8 @@ struct GXKeyList gxKeyList; * and the window rect from the client area given the style of the window * (or a valid window pointer from which the style can be queried). */ -extern void fghComputeWindowRectFromClientArea_QueryWindow( const SFG_Window *window, RECT *clientRect, BOOL posIsOutside ); -extern RECT fghGetClientArea ( const SFG_Window *window, BOOL wantPosOutside ); +extern void fghComputeWindowRectFromClientArea_QueryWindow( RECT *clientRect, const SFG_Window *window, BOOL posIsOutside ); +extern void fghGetClientArea ( RECT *clientRect, const SFG_Window *window, BOOL wantPosOutside ); void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height ) @@ -73,6 +75,16 @@ void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height ) * For windowed mode, get the current position of the * window and resize taking the size of the frame * decorations into account. + * + * Note on maximizing behavior of Windows: the resize borders are off + * the screen such that the client area extends all the way from the + * leftmost corner to the rightmost corner to maximize screen real + * estate. A caption is still shown however to allow interaction with + * the window controls. This is default behavior of Windows that + * FreeGLUT sticks with. To alter, one would have to check if + * WS_MAXIMIZE style is set when a resize event is triggered, and + * then manually correct the windowRect to put the borders back on + * screen. */ /* "GetWindowRect" returns the pixel coordinates of the outside of the window */ @@ -84,7 +96,7 @@ void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height ) if (window->Parent == NULL) /* get the window rect from this to feed to SetWindowPos, correct for window decorations */ - fghComputeWindowRectFromClientArea_QueryWindow(window,&windowRect,TRUE); + fghComputeWindowRectFromClientArea_QueryWindow(&windowRect,window,TRUE); else { /* correct rect for position client area of parent window @@ -94,11 +106,8 @@ void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height ) * for them. */ RECT parentRect; - parentRect = fghGetClientArea( window->Parent, FALSE ); - windowRect.left -= parentRect.left; - windowRect.right -= parentRect.left; - windowRect.top -= parentRect.top; - windowRect.bottom -= parentRect.top; + fghGetClientArea( &parentRect, window->Parent, FALSE ); + OffsetRect(&windowRect,-parentRect.left,-parentRect.top); } /* Do the actual resizing */ @@ -110,6 +119,10 @@ void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height ) SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_NOZORDER ); + + /* Set new width and height so we can test for that in WM_SIZE message handler and don't do anything if not needed */ + window->State.Width = width; + window->State.Height = height; } @@ -203,7 +216,7 @@ void fgPlatformMainLoopPreliminaryWork ( void ) /* - * Determine a GLUT modifer mask based on MS-WINDOWS system info. + * Determine a GLUT modifier mask based on MS-WINDOWS system info. */ static int fgPlatformGetModifiers (void) { @@ -225,7 +238,7 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, static unsigned char lControl = 0, rControl = 0, lShift = 0, rShift = 0, lAlt = 0, rAlt = 0; - SFG_Window* window; + SFG_Window *window, *child_window = NULL; PAINTSTRUCT ps; LRESULT lRet = 1; @@ -239,117 +252,71 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, /* printf ( "Window %3d message <%04x> %12d %12d\n", window?window->ID:0, uMsg, wParam, lParam ); */ - if ( window ) + /* 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. + */ + if (window && window->Children.First) { - /* Checking for CTRL, ALT, and SHIFT key positions: Key Down! */ - if ( !lControl && GetAsyncKeyState ( VK_LCONTROL ) ) - { - INVOKE_WCB ( *window, Special, - ( GLUT_KEY_CTRL_L, window->State.MouseX, window->State.MouseY ) - ); - - lControl = 1; - } - - if ( !rControl && GetAsyncKeyState ( VK_RCONTROL ) ) - { - INVOKE_WCB ( *window, Special, - ( GLUT_KEY_CTRL_R, window->State.MouseX, window->State.MouseY ) - ); - - rControl = 1; - } - - if ( !lShift && GetAsyncKeyState ( VK_LSHIFT ) ) - { - INVOKE_WCB ( *window, Special, - ( GLUT_KEY_SHIFT_L, window->State.MouseX, window->State.MouseY ) - ); - - lShift = 1; - } + POINT mouse_pos; + SFG_WindowHandleType hwnd; + SFG_Window* temp_window; - if ( !rShift && GetAsyncKeyState ( VK_RSHIFT ) ) - { - INVOKE_WCB ( *window, Special, - ( GLUT_KEY_SHIFT_R, window->State.MouseX, window->State.MouseY ) - ); + GetCursorPos( &mouse_pos ); + 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 */ + { + temp_window = fgWindowByHandle(hwnd); + if (temp_window && temp_window->Parent) /* Verify we got a child window */ + child_window = temp_window; + } + } - rShift = 1; - } + if ( window ) + { + SFG_Window* temp_window = child_window?child_window:window; - if ( !lAlt && GetAsyncKeyState ( VK_LMENU ) ) - { - INVOKE_WCB ( *window, Special, - ( GLUT_KEY_ALT_L, window->State.MouseX, window->State.MouseY ) - ); + fgState.Modifiers = fgPlatformGetModifiers( ); - lAlt = 1; + /* 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;\ } - if ( !rAlt && GetAsyncKeyState ( VK_RMENU ) ) - { - INVOKE_WCB ( *window, Special, - ( GLUT_KEY_ALT_R, window->State.MouseX, window->State.MouseY ) - ); - - rAlt = 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! */ - if ( lControl && !GetAsyncKeyState ( VK_LCONTROL ) ) - { - INVOKE_WCB ( *window, SpecialUp, - ( GLUT_KEY_CTRL_L, window->State.MouseX, window->State.MouseY ) - ); - - lControl = 0; - } - - if ( rControl && !GetAsyncKeyState ( VK_RCONTROL ) ) - { - INVOKE_WCB ( *window, SpecialUp, - ( GLUT_KEY_CTRL_R, window->State.MouseX, window->State.MouseY ) - ); - - rControl = 0; - } - - if ( lShift && !GetAsyncKeyState ( VK_LSHIFT ) ) - { - INVOKE_WCB ( *window, SpecialUp, - ( GLUT_KEY_SHIFT_L, window->State.MouseX, window->State.MouseY ) - ); - - lShift = 0; - } - - if ( rShift && !GetAsyncKeyState ( VK_RSHIFT ) ) - { - INVOKE_WCB ( *window, SpecialUp, - ( GLUT_KEY_SHIFT_R, window->State.MouseX, window->State.MouseY ) - ); - - rShift = 0; +#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;\ } - if ( lAlt && !GetAsyncKeyState ( VK_LMENU ) ) - { - INVOKE_WCB ( *window, SpecialUp, - ( GLUT_KEY_ALT_L, window->State.MouseX, window->State.MouseY ) - ); - - lAlt = 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 - if ( rAlt && !GetAsyncKeyState ( VK_RMENU ) ) - { - INVOKE_WCB ( *window, SpecialUp, - ( GLUT_KEY_ALT_R, window->State.MouseX, window->State.MouseY ) - ); - - rAlt = 0; - } + fgState.Modifiers = INVALID_MODIFIERS; } switch( uMsg ) @@ -452,7 +419,8 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, */ if( window->State.Visible ) { - window->State.NeedToResize = GL_TRUE; + /* get old values first to compare to below */ + int width = window->State.Width, height=window->State.Height; #if defined(_WIN32_WCE) window->State.Width = HIWORD(lParam); window->State.Height = LOWORD(lParam); @@ -460,27 +428,71 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, window->State.Width = LOWORD(lParam); window->State.Height = HIWORD(lParam); #endif /* defined(_WIN32_WCE) */ + + if (width!=window->State.Width || height!=window->State.Height) + /* Something changed, need to resize */ + window->State.NeedToResize = GL_TRUE; } break; + case WM_MOVE: + { + SFG_Window* saved_window = fgStructure.CurrentWindow; + RECT windowRect; + GetWindowRect( window->Window.Handle, &windowRect ); + + if (window->Parent) + { + /* For child window, we should return relative to upper-left + * of parent's client area. + */ + POINT topleft = {windowRect.left,windowRect.top}; + + ScreenToClient(window->Parent->Window.Handle,&topleft); + windowRect.left = topleft.x; + windowRect.top = topleft.y; + } + + INVOKE_WCB( *window, Position, ( windowRect.left, windowRect.top ) ); + fgSetWindow(saved_window); + } + break; + case WM_SETFOCUS: /* printf("WM_SETFOCUS: %p\n", window ); */ + lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); - INVOKE_WCB( *window, Entry, ( GLUT_ENTERED ) ); - UpdateWindow ( hWnd ); + 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 */ + UpdateWindow ( hWnd ); + break; case WM_KILLFOCUS: -/* printf("WM_KILLFOCUS: %p\n", window ); */ - lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); - INVOKE_WCB( *window, Entry, ( GLUT_LEFT ) ); - - if( window->IsMenu && - window->ActiveMenu && window->ActiveMenu->IsActive ) - fgUpdateMenuHighlight( window->ActiveMenu ); + { + 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(); + } break; #if 0 @@ -512,6 +524,7 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, case WM_PAINT: /* 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 ); @@ -548,7 +561,6 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, fgUpdateMenuHighlight( window->ActiveMenu ); break; } - SetFocus(window->Window.Handle); fgState.Modifiers = fgPlatformGetModifiers( ); @@ -675,17 +687,13 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, } break; - case 0x020a: - /* Should be WM_MOUSEWHEEL but my compiler doesn't recognize it */ + case WM_MOUSEWHEEL: { int wheel_number = LOWORD( wParam ); short ticks = ( short )HIWORD( wParam ); fgState.MouseWheelTicks += ticks; - /* - * XXX Should use WHEEL_DELTA instead of 120 - */ - if ( abs ( fgState.MouseWheelTicks ) > 120 ) + if ( abs ( fgState.MouseWheelTicks ) >= WHEEL_DELTA ) { int direction = ( fgState.MouseWheelTicks > 0 ) ? 1 : -1; @@ -696,10 +704,7 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, fgSetWindow( window ); fgState.Modifiers = fgPlatformGetModifiers( ); - /* - * XXX Should use WHEEL_DELTA instead of 120 - */ - while( abs ( fgState.MouseWheelTicks ) > 120 ) + while( abs ( fgState.MouseWheelTicks ) >= WHEEL_DELTA ) { if( FETCH_WCB( *window, MouseWheel ) ) INVOKE_WCB( *window, MouseWheel, @@ -731,10 +736,7 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, ); } - /* - * XXX Should use WHEEL_DELTA instead of 120 - */ - fgState.MouseWheelTicks -= 120 * direction; + fgState.MouseWheelTicks -= WHEEL_DELTA * direction; } fgState.Modifiers = INVALID_MODIFIERS; @@ -748,6 +750,9 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, 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; @@ -789,12 +794,12 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, KEY( VK_RIGHT, GLUT_KEY_RIGHT ); KEY( VK_DOWN, GLUT_KEY_DOWN ); KEY( VK_INSERT, GLUT_KEY_INSERT ); - KEY( VK_LCONTROL, GLUT_KEY_CTRL_L ); - KEY( VK_RCONTROL, GLUT_KEY_CTRL_R ); - KEY( VK_LSHIFT, GLUT_KEY_SHIFT_L ); - KEY( VK_RSHIFT, GLUT_KEY_SHIFT_R ); - KEY( VK_LMENU, GLUT_KEY_ALT_L ); - KEY( VK_RMENU, GLUT_KEY_ALT_R ); + + 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: */ @@ -841,6 +846,9 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, 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. @@ -881,12 +889,12 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, KEY( VK_RIGHT, GLUT_KEY_RIGHT ); KEY( VK_DOWN, GLUT_KEY_DOWN ); KEY( VK_INSERT, GLUT_KEY_INSERT ); - KEY( VK_LCONTROL, GLUT_KEY_CTRL_L ); - KEY( VK_RCONTROL, GLUT_KEY_CTRL_R ); - KEY( VK_LSHIFT, GLUT_KEY_SHIFT_L ); - KEY( VK_RSHIFT, GLUT_KEY_SHIFT_R ); - KEY( VK_LMENU, GLUT_KEY_ALT_L ); - KEY( VK_RMENU, GLUT_KEY_ALT_R ); + + 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: */ @@ -927,6 +935,9 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, case WM_SYSCHAR: case WM_CHAR: { + if (child_window) + window = child_window; + if( (fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE) && (HIWORD(lParam) & KF_REPEAT) ) break;