redisplay is now also on the work list instead of handled separately
[freeglut] / src / mswin / fg_main_mswin.c
index f1c6eb7..dccb8dd 100644 (file)
@@ -39,7 +39,7 @@ extern void fgNewWGLCreateContext( SFG_Window* window );
 extern GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly,
                                      unsigned char layer_type );
 
-extern void fgPlatformCheckMenuDeactivate();
+extern void fgPlatformCheckMenuDeactivate(HWND newFocusWnd);
 
 #ifdef WM_TOUCH
 typedef BOOL (WINAPI *pGetTouchInputInfo)(HTOUCHINPUT,UINT,PTOUCHINPUT,int);
@@ -893,9 +893,9 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
              * force redisplay so display keeps running during dragging.
              * Screen still wont update when not moving the cursor though...
              */
-            /* PRECT prect = (PRECT) lParam; */
             RECT rect;
-            /* printf("WM_SIZING: nc-area: %i,%i\n",prect->right-prect->left,prect->bottom-prect->top); */
+            /* PRECT prect = (PRECT) lParam;
+               printf("WM_SIZING: nc-area: %i,%i\n",prect->right-prect->left,prect->bottom-prect->top); */
             /* Get client area, the rect in lParam is including non-client area. */
             fghGetClientArea(&rect,window,FALSE);
 
@@ -969,20 +969,34 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
         lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
 
         /* Check if there are any open menus that need to be closed */
-        fgPlatformCheckMenuDeactivate();
+        fgPlatformCheckMenuDeactivate((HWND)wParam);
         break;
 
     case WM_MOUSEACTIVATE:
         /* Clicks should not activate the menu.
          * Especially important when clicking on a menu's submenu item which has no effect.
          */
-        printf("WM_MOUSEACTIVATE\n");
+        /*printf("WM_MOUSEACTIVATE\n");*/
         if (window->IsMenu)
             lRet = MA_NOACTIVATEANDEAT;
         else
             lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
         break;
 
+    case WM_NCLBUTTONDOWN:
+    case WM_NCMBUTTONDOWN:
+    case WM_NCRBUTTONDOWN:
+        {
+            SFG_Menu *menu;
+            if (fgState.ActiveMenus && (menu = fgGetActiveMenu()))
+                /* user clicked non-client area of window while a menu is open. Close menu */
+                fgDeactivateMenu(menu->ParentWindow);
+
+            /* and always pass to DefWindowProc */
+            lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
+        }
+        break;
+
 #if 0
     case WM_ACTIVATE:
         /* printf("WM_ACTIVATE: %x (ID: %i) %d %d\n",lParam, window->ID, HIWORD(wParam), LOWORD(wParam)); */
@@ -1052,12 +1066,12 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
         if (wParam)
         {
             fghPlatformOnWindowStatusNotify(window, GL_TRUE, GL_FALSE);
-            window->State.Redisplay = GL_TRUE;
+            window->State.WorkMask |= GLUT_DISPLAY_WORK;
         }
         else
         {
             fghPlatformOnWindowStatusNotify(window, GL_FALSE, GL_FALSE);
-            window->State.Redisplay = GL_FALSE;
+            window->State.WorkMask &= ~GLUT_DISPLAY_WORK;
         }
         break;
 
@@ -1078,7 +1092,7 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
             BeginPaint( hWnd, &ps );
             EndPaint( hWnd, &ps );
 
-            window->State.Redisplay = GL_TRUE;
+            window->State.WorkMask |= GLUT_DISPLAY_WORK;
         }
         lRet = 0;   /* As per docs, should return 0 */
     }
@@ -1370,7 +1384,7 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
 #if !defined(_WIN32_WCE)
     case WM_SYNCPAINT:  /* 0x0088 */
         /* Another window has moved, need to update this one */
-        window->State.Redisplay = GL_TRUE;
+        window->State.WorkMask |= GLUT_DISPLAY_WORK;
         lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
         /* Help screen says this message must be passed to "DefWindowProc" */
         break;
@@ -1534,6 +1548,8 @@ void fgPlatformProcessWork(SFG_Window *window)
     /* Now clear it so that any callback generated by the actions below can set work again */
     window->State.WorkMask = 0;
 
+    if (workMask&~GLUT_DISPLAY_WORK)    /* Display work is the common case, skip all the below at once */
+    {
     /* This is before the first display callback: call a few callbacks to inform user of window size, position, etc
      * we know this is before the first display callback of a window as for all windows GLUT_INIT_WORK is set when
      * they are opened, and work is done before displaying in the mainloop.
@@ -1753,8 +1769,8 @@ void fgPlatformProcessWork(SFG_Window *window)
                 win = win->Parent;
             break;
         case DesireNormalState:
-            if (win->IsMenu)
-                cmdShow = SW_SHOWNOACTIVATE;    /* Just show, don't activate if its a menu */
+            if (win->IsMenu && (!fgStructure.GameModeWindow || win->ActiveMenu->ParentWindow != fgStructure.GameModeWindow))
+                cmdShow = SW_SHOWNA;    /* Just show, don't activate window if its a menu. Only exception is when the parent is a gamemode window as the menu would pop under it when we do this... */
             else
                 cmdShow = SW_SHOW;
             break;
@@ -1762,4 +1778,14 @@ void fgPlatformProcessWork(SFG_Window *window)
 
         ShowWindow( win->Window.Handle, cmdShow );
     }
+    }
+
+    if (workMask & GLUT_DISPLAY_WORK)
+    {
+        if( window->State.Visible )
+            fghRedrawWindow ( window );
+
+        /* Strip out display work that might have ended up on work list now as some of the above genereates callbacks */
+        window->State.WorkMask &= ~GLUT_DISPLAY_WORK;
+    }
 }
\ No newline at end of file