X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Fmswin%2Ffg_main_mswin.c;h=22a1d4413cc4c0a6c4c31db9cec8ad81ef9070fd;hb=25a96752f76c571c447b00e376f0002568389bad;hp=3e1a86f392c19ed9b801c8572e365d8bbfac4846;hpb=b6a12cbf5c40f2b0a4bdeb476d946d5eaa58476d;p=freeglut diff --git a/src/mswin/fg_main_mswin.c b/src/mswin/fg_main_mswin.c index 3e1a86f..22a1d44 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 */ @@ -203,7 +212,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 +234,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,135 +248,69 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, /* printf ( "Window %3d message <%04x> %12d %12d\n", window?window->ID:0, uMsg, wParam, lParam ); */ - /* events only sent to main window. Check if the current window that the mouse - is over is a child window and if so, make sure we call the callback on that - child instead. - */ + /* 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) { POINT mouse_pos; SFG_WindowHandleType hwnd; + SFG_Window* temp_window; 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 */ - window = fgWindowByHandle(hwnd); + { + temp_window = fgWindowByHandle(hwnd); + if (temp_window->Parent) /* Verify we got a child window */ + child_window = temp_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! */ - 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; +#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 ( !rShift && GetAsyncKeyState ( VK_RSHIFT ) ) - { - INVOKE_WCB ( *window, Special, - ( GLUT_KEY_SHIFT_R, window->State.MouseX, window->State.MouseY ) - ); - - rShift = 1; - } - - if ( !lAlt && GetAsyncKeyState ( VK_LMENU ) ) - { - INVOKE_WCB ( *window, Special, - ( GLUT_KEY_ALT_L, window->State.MouseX, window->State.MouseY ) - ); - - lAlt = 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; +#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 ( 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; - } - - if ( lAlt && !GetAsyncKeyState ( VK_LMENU ) ) - { - INVOKE_WCB ( *window, SpecialUp, - ( GLUT_KEY_ALT_L, window->State.MouseX, window->State.MouseY ) - ); - - lAlt = 0; - } - - if ( rAlt && !GetAsyncKeyState ( VK_RMENU ) ) - { - INVOKE_WCB ( *window, SpecialUp, - ( GLUT_KEY_ALT_R, window->State.MouseX, window->State.MouseY ) - ); - - rAlt = 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; } @@ -486,60 +429,37 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, 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: { - SFG_Menu* menu = NULL; - printf("WM_KILLFOCUS: %p\n", window ); + 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); - /* If we have an open menu, see if the open menu should be closed - when focus was lost because user either switched - application or FreeGLUT window (if one is running multiple - windows). If so, close menu the active menu. - */ - if ( fgStructure.Menus.First ) - menu = fgGetActiveMenu(); - - if ( menu ) - { - SFG_Window* wnd = NULL; - HWND hwnd = GetFocus(); /* Get window with current focus - NULL for non freeglut windows */ - printf(" hwnd: %p\n",hwnd); - if (hwnd) - /* See which of our windows it is */ - wnd = fgWindowByHandle(hwnd); - - //printf(" got menu: %p\n",menu); - - printf(" wnd: %p, wnd->AM->PW: %p, menu->PW: %p\n",wnd,wnd&&wnd->ActiveMenu?wnd->ActiveMenu->ParentWindow:0,menu->ParentWindow); - if (wnd) - printf(" wnd menu: %i, wnd->ActiveMenu: %p, wnd->Parent: %p\n",wnd->IsMenu,wnd->ActiveMenu,wnd->Parent); - - if (!hwnd || !wnd) - { - /* User switched to another application*/ - fgDeactivateMenu(menu->ParentWindow); - printf(" -> kill1\n"); - } - else if (!wnd->IsMenu && wnd!=menu->ParentWindow) - { - /* User switched to another FreeGLUT window */ - fgDeactivateMenu(menu->ParentWindow); - printf(" -> kill2\n"); - - } - else - { - printf(" -> survive\n"); - } - } + /* Check if there are any open menus that need to be closed */ + fgPlatformCheckMenuDeactivate(); } break; @@ -572,6 +492,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 ); @@ -806,6 +727,8 @@ 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; @@ -900,6 +823,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. @@ -986,6 +912,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;