Fixed bug #252: menu windows are drawn with immediate mode and the fixed
[freeglut] / src / fg_window.c
index 5c431ea..6efff54 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * freeglut_window.c
+ * fg_window.c
  *
  * Window management methods.
  *
@@ -56,24 +56,21 @@ extern void fgPlatformOpenWindow( SFG_Window* window, const char* title,
                                   GLboolean sizeUse, int w, int h,
                                   GLboolean gameMode, GLboolean isSubWindow );
 extern void fgPlatformCloseWindow( SFG_Window* window );
-extern void fgPlatformGlutShowWindow( void );
-extern void fgPlatformGlutHideWindow( void );
-extern void fgPlatformGlutIconifyWindow( void );
 extern void fgPlatformGlutSetWindowTitle( const char* title );
 extern void fgPlatformGlutSetIconTitle( const char* title );
-extern void fgPlatformGlutPositionWindow( int x, int y );
-extern void fgPlatformGlutPushWindow( void );
-extern void fgPlatformGlutPopWindow( void );
-extern void fgPlatformGlutFullScreen( SFG_Window *win );
-extern void fgPlatformGlutLeaveFullScreen( SFG_Window *win );
-extern void fgPlatformGlutFullScreenToggle( SFG_Window *win );
 
 
 /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
 
-int fghIsLegacyContextRequested( void )
+int fghIsLegacyContextRequested( SFG_Window *win )
 {
-    return fgState.MajorVersion < 2 || (fgState.MajorVersion == 2 && fgState.MinorVersion <= 1);
+       int vmajor = fgState.MajorVersion;
+       int vminor = fgState.MinorVersion;
+       /* XXX: menu windows are drawn with the fixed function pipeline, therefore
+        * the context created for them can't be a modern core-profile context.
+        * Force the traditional context creation for menu windows.
+        */
+    return vmajor < 2 || (vmajor == 2 && vminor <= 1) || win->IsMenu;
 }
 
 int fghNumberOfAuxBuffersRequested( void )
@@ -115,7 +112,7 @@ void fghContextCreationError( void )
  */
 void fgSetWindow ( SFG_Window *window )
 {
-       fgPlatformSetWindow ( window );
+    fgPlatformSetWindow ( window );
 
     fgStructure.CurrentWindow = window;
 }
@@ -129,27 +126,34 @@ void fgOpenWindow( SFG_Window* window, const char* title,
                    GLboolean sizeUse, int w, int h,
                    GLboolean gameMode, GLboolean isSubWindow )
 {
-       fgPlatformOpenWindow( window, title,
-                   positionUse, x, y,
-                   sizeUse, w, h,
-                   gameMode, isSubWindow );
+    fgPlatformOpenWindow( window, title,
+                          positionUse, x, y,
+                          sizeUse, w, h,
+                          gameMode, isSubWindow );
 
     fgSetWindow( window );
 
+#ifndef EGL_VERSION_1_0
     window->Window.DoubleBuffered =
         ( fgState.DisplayMode & GLUT_DOUBLE ) ? 1 : 0;
 
-#ifndef EGL_VERSION_1_0  /* No glDrawBuffer/glReadBuffer in GLES */
     if ( ! window->Window.DoubleBuffered )
     {
         glDrawBuffer ( GL_FRONT );
         glReadBuffer ( GL_FRONT );
     }
+#else
+    /* - EGL is always double-buffered */
+    /* - No glDrawBuffer/glReadBuffer in GLES */
+    window->Window.DoubleBuffered = 1;
 #endif
     window->Window.attribute_v_coord = -1;
     window->Window.attribute_v_normal = -1;
+    window->Window.attribute_v_texture = -1;
 
     fgInitGL2();
+
+    window->State.WorkMask |= GLUT_INIT_WORK;
 }
 
 /*
@@ -164,7 +168,7 @@ void fgCloseWindow( SFG_Window* window )
     if (fgStructure.GameModeWindow != NULL && fgStructure.GameModeWindow->ID==window->ID)
         glutLeaveGameMode();
 
-       fgPlatformCloseWindow ( window );
+    fgPlatformCloseWindow ( window );
 }
 
 
@@ -179,12 +183,12 @@ int FGAPIENTRY glutCreateWindow( const char* title )
      * XXX application has not already done so.  The "freeglut" community
      * XXX decided not to go this route (freeglut-developer e-mail from
      * XXX Steve Baker, 12/16/04, 4:22 PM CST, "Re: [Freeglut-developer]
-     * XXX Desired 'freeglut' behaviour when there is no current window"
+     * XXX Desired 'freeglut' behaviour when there is no current window")
      */
     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateWindow" );
 
-    return fgCreateWindow( NULL, title, fgState.Position.Use,
-                           fgState.Position.X, fgState.Position.Y,
+    return fgCreateWindow( NULL, title, 
+                           fgState.Position.Use, fgState.Position.X, fgState.Position.Y,
                            fgState.Size.Use, fgState.Size.X, fgState.Size.Y,
                            GL_FALSE, GL_FALSE )->ID;
 }
@@ -201,33 +205,51 @@ int FGAPIENTRY glutCreateSubWindow( int parentID, int x, int y, int w, int h )
     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutCreateSubWindow" );
     parent = fgWindowByID( parentID );
     freeglut_return_val_if_fail( parent != NULL, 0 );
-    if ( x < 0 )
-    {
-        x = parent->State.Width + x ;
-        if ( w >= 0 ) x -= w ;
-    }
 
-    if ( w < 0 ) w = parent->State.Width - x + w ;
-    if ( w < 0 )
+    if ( fgState.AllowNegativeWindowPosition )
     {
-        x += w ;
-        w = -w ;
-    }
+        /* XXX This results in different widths/heights than if AllowNegativeWindowPosition
+         * XXX was false. The "freeglut" community defined this logic.
+         * XXX (freeglut-developer e-mail from Diederick C. Niehorster, 11/15/2015, 4:06 PM EST.
+         * XXX "Re: [Freeglut-developer] glutInitWindowPosition with negative coordinate(s)")
+         */
 
-    if ( y < 0 )
-    {
-        y = parent->State.Height + y ;
-        if ( h >= 0 ) y -= h ;
+        if ( w < 0 ) w = parent->State.Width + w ;
+        if ( h < 0 ) h = parent->State.Height + h ;
     }
-
-    if ( h < 0 ) h = parent->State.Height - y + h ;
-    if ( h < 0 )
+    else
     {
-        y += h ;
-        h = -h ;
+        if ( ( x < 0 ) )
+        {
+            x = parent->State.Width + x ;
+            if ( w > 0 ) x -= w ;
+        }
+
+        if ( w < 0 ) w = parent->State.Width - x + w ;
+        if ( w < 0 )
+        {
+            x += w ;
+            w = -w ;
+        }
+
+        if ( ( y < 0 ) )
+        {
+            y = parent->State.Height + y ;
+            if ( h > 0 ) y -= h ;
+        }
+
+        if ( h < 0 ) h = parent->State.Height - y + h ;
+        if ( h < 0 )
+        {
+            y += h ;
+            h = -h ;
+        }
     }
 
-    window = fgCreateWindow( parent, "", GL_TRUE, x, y, GL_TRUE, w, h, GL_FALSE, GL_FALSE );
+    window = fgCreateWindow( parent, "", 
+                             GL_TRUE, x, y, 
+                             GL_TRUE, w, h, 
+                             GL_FALSE, GL_FALSE );
     ret = window->ID;
 
     return ret;
@@ -298,9 +320,10 @@ void FGAPIENTRY glutShowWindow( void )
     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutShowWindow" );
     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutShowWindow" );
 
-       fgPlatformGlutShowWindow ();
+    fgStructure.CurrentWindow->State.WorkMask |= GLUT_VISIBILITY_WORK;
+    fgStructure.CurrentWindow->State.DesiredVisibility = DesireNormalState;
 
-    fgStructure.CurrentWindow->State.Redisplay = GL_TRUE;
+    fgStructure.CurrentWindow->State.WorkMask |= GLUT_DISPLAY_WORK;
 }
 
 /*
@@ -311,9 +334,10 @@ void FGAPIENTRY glutHideWindow( void )
     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutHideWindow" );
     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutHideWindow" );
 
-       fgPlatformGlutHideWindow ();
+    fgStructure.CurrentWindow->State.WorkMask |= GLUT_VISIBILITY_WORK;
+    fgStructure.CurrentWindow->State.DesiredVisibility = DesireHiddenState;
 
-    fgStructure.CurrentWindow->State.Redisplay = GL_FALSE;
+    fgStructure.CurrentWindow->State.WorkMask &= ~GLUT_DISPLAY_WORK;
 }
 
 /*
@@ -324,11 +348,10 @@ void FGAPIENTRY glutIconifyWindow( void )
     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutIconifyWindow" );
     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutIconifyWindow" );
 
-    fgStructure.CurrentWindow->State.Visible   = GL_FALSE;
+    fgStructure.CurrentWindow->State.WorkMask |= GLUT_VISIBILITY_WORK;
+    fgStructure.CurrentWindow->State.DesiredVisibility = DesireIconicState;
 
-       fgPlatformGlutIconifyWindow ();
-
-    fgStructure.CurrentWindow->State.Redisplay = GL_FALSE;
+    fgStructure.CurrentWindow->State.WorkMask &= ~GLUT_DISPLAY_WORK;
 }
 
 /*
@@ -340,7 +363,7 @@ void FGAPIENTRY glutSetWindowTitle( const char* title )
     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutSetWindowTitle" );
     if( ! fgStructure.CurrentWindow->Parent )
     {
-               fgPlatformGlutSetWindowTitle ( title );
+        fgPlatformGlutSetWindowTitle ( title );
     }
 }
 
@@ -354,7 +377,7 @@ void FGAPIENTRY glutSetIconTitle( const char* title )
 
     if( ! fgStructure.CurrentWindow->Parent )
     {
-               fgPlatformGlutSetIconTitle ( title );
+        fgPlatformGlutSetIconTitle ( title );
     }
 }
 
@@ -372,9 +395,9 @@ void FGAPIENTRY glutReshapeWindow( int width, int height )
       glutLeaveFullScreen();
     }
 
-    fgStructure.CurrentWindow->State.NeedToResize = GL_TRUE;
-    fgStructure.CurrentWindow->State.Width  = width ;
-    fgStructure.CurrentWindow->State.Height = height;
+    fgStructure.CurrentWindow->State.WorkMask |= GLUT_SIZE_WORK;
+    fgStructure.CurrentWindow->State.DesiredWidth  = width ;
+    fgStructure.CurrentWindow->State.DesiredHeight = height;
 }
 
 /*
@@ -391,7 +414,9 @@ void FGAPIENTRY glutPositionWindow( int x, int y )
       glutLeaveFullScreen();
     }
 
-       fgPlatformGlutPositionWindow ( x, y );
+    fgStructure.CurrentWindow->State.WorkMask |= GLUT_POSITION_WORK;
+    fgStructure.CurrentWindow->State.DesiredXpos = x;
+    fgStructure.CurrentWindow->State.DesiredYpos = y;
 }
 
 /*
@@ -402,7 +427,8 @@ void FGAPIENTRY glutPushWindow( void )
     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPushWindow" );
     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPushWindow" );
 
-       fgPlatformGlutPushWindow ();
+    fgStructure.CurrentWindow->State.WorkMask |= GLUT_ZORDER_WORK;
+    fgStructure.CurrentWindow->State.DesiredZOrder = -1;
 }
 
 /*
@@ -413,7 +439,8 @@ void FGAPIENTRY glutPopWindow( void )
     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPopWindow" );
     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPopWindow" );
 
-       fgPlatformGlutPopWindow ();
+    fgStructure.CurrentWindow->State.WorkMask |= GLUT_ZORDER_WORK;
+    fgStructure.CurrentWindow->State.DesiredZOrder = 1;
 }
 
 /*
@@ -437,13 +464,16 @@ void FGAPIENTRY glutFullScreen( void )
         fgWarning("glutFullScreen called on a child window, ignoring...");
         return;
     }
-    else if (fgStructure.GameModeWindow != NULL && fgStructure.GameModeWindow->ID==win->ID)
+    else if (fgStructure.GameModeWindow != NULL && fgStructure.GameModeWindow->ID==win->ID && win->State.IsFullscreen)
     {
-        /* Ignore fullscreen call on GameMode window, those are always fullscreen already */
+        /* Ignore fullscreen call on GameMode window, those are always fullscreen already
+         * only exception is when first entering GameMode
+         */
         return;
     }
 
-       fgPlatformGlutFullScreen ( win );
+    if (!win->State.IsFullscreen)
+        win->State.WorkMask |= GLUT_FULL_SCREEN_WORK;
 }
 
 /*
@@ -451,14 +481,11 @@ void FGAPIENTRY glutFullScreen( void )
  */
 void FGAPIENTRY glutLeaveFullScreen( void )
 {
-    SFG_Window *win;
-
     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreen" );
     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreen" );
 
-    win = fgStructure.CurrentWindow;
-
-       fgPlatformGlutLeaveFullScreen ( win );
+    if (fgStructure.CurrentWindow->State.IsFullscreen)
+        fgStructure.CurrentWindow->State.WorkMask |= GLUT_FULL_SCREEN_WORK;
 }
 
 /*
@@ -466,14 +493,10 @@ void FGAPIENTRY glutLeaveFullScreen( void )
  */
 void FGAPIENTRY glutFullScreenToggle( void )
 {
-    SFG_Window *win;
-
     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreenToggle" );
     FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreenToggle" );
 
-    win = fgStructure.CurrentWindow;
-
-       fgPlatformGlutFullScreenToggle ( win );
+    fgStructure.CurrentWindow->State.WorkMask |= GLUT_FULL_SCREEN_WORK;
 }
 
 /*