improved comments and mouse coord adjustments (John Fay)
[freeglut] / src / freeglut_main.c
index 5ad233c..d5e34fc 100644 (file)
@@ -84,12 +84,10 @@ struct GXKeyList gxKeyList;
  * callback is hooked, the viewport size is updated to
  * match the new window size.
  */
-static void fghReshapeWindowByHandle ( SFG_WindowHandleType handle,
-                                       int width, int height )
+static void fghReshapeWindow ( SFG_Window *window, int width, int height )
 {
     SFG_Window *current_window = fgStructure.Window;
 
-    SFG_Window* window = fgWindowByHandle( handle );
     freeglut_return_if_fail( window != NULL );
 
 
@@ -184,9 +182,10 @@ static void fghReshapeWindowByHandle ( SFG_WindowHandleType handle,
  * Calls a window's redraw method. This is used when
  * a redraw is forced by the incoming window messages.
  */
-static void fghRedrawWindowByHandle ( SFG_WindowHandleType handle )
+static void fghRedrawWindow ( SFG_Window *window )
 {
-    SFG_Window* window = fgWindowByHandle( handle );
+    SFG_Window *current_window = fgStructure.Window;
+
     freeglut_return_if_fail( window );
     freeglut_return_if_fail( FETCH_WCB ( *window, Display ) );
 
@@ -194,23 +193,22 @@ static void fghRedrawWindowByHandle ( SFG_WindowHandleType handle )
 
     freeglut_return_if_fail( window->State.Visible );
 
+    fgSetWindow( window );
+
     if( window->State.NeedToResize )
     {
-        SFG_Window *current_window = fgStructure.Window;
-
-        fgSetWindow( window );
-
-        fghReshapeWindowByHandle(
-            window->Window.Handle,
+        fghReshapeWindow(
+            window,
             window->State.Width,
             window->State.Height
         );
 
         window->State.NeedToResize = GL_FALSE;
-        fgSetWindow( current_window );
     }
 
     INVOKE_WCB( *window, Display, ( ) );
+
+    fgSetWindow( current_window );
 }
 
 /*
@@ -219,34 +217,13 @@ static void fghRedrawWindowByHandle ( SFG_WindowHandleType handle )
 static void fghcbDisplayWindow( SFG_Window *window,
                                 SFG_Enumerator *enumerator )
 {
-    if( window->State.NeedToResize )
-    {
-        SFG_Window *current_window = fgStructure.Window;
-
-        fgSetWindow( window );
-
-        fghReshapeWindowByHandle(
-            window->Window.Handle,
-            window->State.Width,
-            window->State.Height
-        );
-
-        window->State.NeedToResize = GL_FALSE;
-        fgSetWindow ( current_window );
-    }
-
     if( window->State.Redisplay &&
         window->State.Visible )
     {
         window->State.Redisplay = GL_FALSE;
 
 #if TARGET_HOST_UNIX_X11
-        {
-            SFG_Window *current_window = fgStructure.Window;
-
-            INVOKE_WCB( *window, Display, ( ) );
-            fgSetWindow( current_window );
-        }
+        fghRedrawWindow ( window ) ;
 #elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
         RedrawWindow(
             window->Window.Handle, NULL, NULL,
@@ -413,44 +390,44 @@ void fgWarning( const char *fmt, ... )
  * and all other "joystick timer" code can be yanked.
  *
  */
-static void fgCheckJoystickCallback( SFG_Window* w, SFG_Enumerator* e)
+static void fghCheckJoystickCallback( SFG_Window* w, SFG_Enumerator* e)
 {
     if( FETCH_WCB( *w, Joystick ) )
     {
         e->found = GL_TRUE;
         e->data = w;
     }
-    fgEnumSubWindows( w, fgCheckJoystickCallback, e );
+    fgEnumSubWindows( w, fghCheckJoystickCallback, e );
 }
-static int fgHaveJoystick( void )
+static int fghHaveJoystick( void )
 {
     SFG_Enumerator enumerator;
     enumerator.found = GL_FALSE;
     enumerator.data = NULL;
-    fgEnumWindows( fgCheckJoystickCallback, &enumerator );
+    fgEnumWindows( fghCheckJoystickCallback, &enumerator );
     return !!enumerator.data;
 }
-static void fgHavePendingRedisplaysCallback( SFG_Window* w, SFG_Enumerator* e)
+static void fghHavePendingRedisplaysCallback( SFG_Window* w, SFG_Enumerator* e)
 {
     if( w->State.Redisplay )
     {
         e->found = GL_TRUE;
         e->data = w;
     }
-    fgEnumSubWindows( w, fgHavePendingRedisplaysCallback, e );
+    fgEnumSubWindows( w, fghHavePendingRedisplaysCallback, e );
 }
-static int fgHavePendingRedisplays (void)
+static int fghHavePendingRedisplays (void)
 {
     SFG_Enumerator enumerator;
     enumerator.found = GL_FALSE;
     enumerator.data = NULL;
-    fgEnumWindows( fgHavePendingRedisplaysCallback, &enumerator );
+    fgEnumWindows( fghHavePendingRedisplaysCallback, &enumerator );
     return !!enumerator.data;
 }
 /*
  * Returns the number of GLUT ticks (milliseconds) till the next timer event.
  */
-static long fgNextTimer( void )
+static long fghNextTimer( void )
 {
     long ret = INT_MAX;
     SFG_Timer *timer = fgState.Timers.First;
@@ -466,16 +443,16 @@ static long fgNextTimer( void )
  * Does the magic required to relinquish the CPU until something interesting
  * happens.
  */
-static void fgSleepForEvents( void )
+static void fghSleepForEvents( void )
 {
     long msec;
 
-    if( fgState.IdleCallback || fgHavePendingRedisplays( ) )
+    if( fgState.IdleCallback || fghHavePendingRedisplays( ) )
         return;
 
-    msec = fgNextTimer( );
-    if( fgHaveJoystick( ) )     /* XXX Use GLUT timers for joysticks... */
-        msec = MIN( msec, 10 ); /* XXX Dumb; forces granularity to .01sec */
+    msec = fghNextTimer( );
+    if( fghHaveJoystick( ) )     /* XXX Use GLUT timers for joysticks... */
+        msec = MIN( msec, 10 );  /* XXX Dumb; forces granularity to .01sec */
 
 #if TARGET_HOST_UNIX_X11
     /*
@@ -502,7 +479,7 @@ static void fgSleepForEvents( void )
         err = select( socket+1, &fdset, NULL, NULL, &wait );
 
         if( -1 == err )
-            fgWarning ( "freeglut select() error: %d\n", errno );
+            fgWarning ( "freeglut select() error: %d", errno );
     }
 #elif TARGET_HOST_WIN32 || TARGET_HOST_WINCE
     MsgWaitForMultipleObjects( 0, NULL, FALSE, msec, QS_ALLEVENTS );
@@ -513,7 +490,7 @@ static void fgSleepForEvents( void )
 /*
  * Returns GLUT modifier mask for an XEvent.
  */
-int fgGetXModifiers( XEvent *event )
+static int fghGetXModifiers( XEvent *event )
 {
     int ret = 0;
 
@@ -696,7 +673,7 @@ void FGAPIENTRY glutMainLoopEvent( void )
                 break;
 
             default:
-                fgWarning( "Uknown X visibility state: %d",
+                fgWarning( "Unknown X visibility state: %d",
                            event.xvisibility.state );
                 break;
             }
@@ -871,7 +848,7 @@ void FGAPIENTRY glutMainLoopEvent( void )
                 ! FETCH_WCB( *window, MouseWheel ) )
                 break;
 
-            fgState.Modifiers = fgGetXModifiers( &event );
+            fgState.Modifiers = fghGetXModifiers( &event );
 
             /*
              * Finally execute the mouse or mouse wheel callback
@@ -967,9 +944,7 @@ void FGAPIENTRY glutMainLoopEvent( void )
                 special_cb  = FETCH_WCB( *window, SpecialUp  );
             }
 
-            /*
-             * Is there a keyboard/special callback hooked for this window?
-             */
+            /* Is there a keyboard/special callback hooked for this window? */
             if( keyboard_cb || special_cb )
             {
                 XComposeStatus composeStatus;
@@ -977,25 +952,19 @@ void FGAPIENTRY glutMainLoopEvent( void )
                 KeySym keySym;
                 int len;
 
-                /*
-                 * Check for the ASCII/KeySym codes associated with the event:
-                 */
+                /* Check for the ASCII/KeySym codes associated with the event: */
                 len = XLookupString( &event.xkey, asciiCode, sizeof(asciiCode),
                                      &keySym, &composeStatus
                 );
 
-                /*
-                 * GLUT API tells us to have two separate callbacks...
-                 */
+                /* GLUT API tells us to have two separate callbacks... */
                 if( len > 0 )
                 {
-                    /*
-                     * ...one for the ASCII translateable keypresses...
-                     */
+                    /* ...one for the ASCII translateable keypresses... */
                     if( keyboard_cb )
                     {
                         fgSetWindow( window );
-                        fgState.Modifiers = fgGetXModifiers( &event );
+                        fgState.Modifiers = fghGetXModifiers( &event );
                         keyboard_cb( asciiCode[ 0 ],
                                      event.xkey.x, event.xkey.y
                         );
@@ -1049,7 +1018,7 @@ void FGAPIENTRY glutMainLoopEvent( void )
                     if( special_cb && (special != -1) )
                     {
                         fgSetWindow( window );
-                        fgState.Modifiers = fgGetXModifiers( &event );
+                        fgState.Modifiers = fghGetXModifiers( &event );
                         special_cb( special, event.xkey.x, event.xkey.y );
                         fgState.Modifiers = 0xffffffff;
                     }
@@ -1160,7 +1129,7 @@ void FGAPIENTRY glutMainLoop( void )
             if( fgState.IdleCallback )
                 fgState.IdleCallback( );
 
-            fgSleepForEvents( );
+            fghSleepForEvents( );
         }
     }
 
@@ -1189,7 +1158,7 @@ void FGAPIENTRY glutLeaveMainLoop( void )
 /*
  * Determine a GLUT modifer mask based on MS-WINDOWS system info.
  */
-int fgGetWin32Modifiers (void)
+static int fghGetWin32Modifiers (void)
 {
     return
         ( ( ( GetKeyState( VK_LSHIFT   ) < 0 ) ||
@@ -1334,7 +1303,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
          * XXX function (or perhaps invoke glutSetCursor())?
          * XXX That is, why are we duplicating code, here, from
          * XXX glutSetCursor()?  The WIN32 code should be able to just
-         * XXX call glutSetCurdsor() instead of defining two macros
+         * XXX call glutSetCursor() instead of defining two macros
          * XXX and implementing a nested case in-line.
          */
     case WM_SETCURSOR:
@@ -1382,7 +1351,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
         /* Turn on the visibility in case it was turned off somehow */
         window->State.Visible = GL_TRUE;
         BeginPaint( hWnd, &ps );
-        fghRedrawWindowByHandle( hWnd );
+        fghRedrawWindow( window );
         EndPaint( hWnd, &ps );
         break;
 
@@ -1407,6 +1376,10 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
         window->State.MouseX = LOWORD( lParam );
         window->State.MouseY = HIWORD( lParam );
 #endif /* TARGET_HOST_WINCE */
+        /* Restrict to [-32768, 32767] to match X11 behaviour       */
+        /* See comment in "freeglut_developer" mailing list 10/4/04 */
+        if ( window->State.MouseX > 32767 ) window->State.MouseX -= 65536;
+        if ( window->State.MouseY > 32767 ) window->State.MouseY -= 65536;
 
         if ( window->ActiveMenu )
         {
@@ -1415,7 +1388,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
             break;
         }
 
-        fgState.Modifiers = fgGetWin32Modifiers( );
+        fgState.Modifiers = fghGetWin32Modifiers( );
 
         if( ( wParam & MK_LBUTTON ) ||
             ( wParam & MK_MBUTTON ) ||
@@ -1448,6 +1421,11 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
         window->State.MouseY = HIWORD( lParam );
 #endif /* TARGET_HOST_WINCE */
 
+        /* Restrict to [-32768, 32767] to match X11 behaviour       */
+        /* See comment in "freeglut_developer" mailing list 10/4/04 */
+        if ( window->State.MouseX > 32767 ) window->State.MouseX -= 65536;
+        if ( window->State.MouseY > 32767 ) window->State.MouseY -= 65536;
+
         switch( uMsg )
         {
         case WM_LBUTTONDOWN:
@@ -1563,11 +1541,24 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
             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.
+         */
+        if ( pressed == GL_TRUE )
+          SetCapture ( window->Window.Handle ) ;
+        else
+          ReleaseCapture () ;
+
         if( ! FETCH_WCB( *window, Mouse ) )
             break;
 
         fgSetWindow( window );
-        fgState.Modifiers = fgGetWin32Modifiers( );
+        fgState.Modifiers = fghGetWin32Modifiers( );
 
         INVOKE_WCB(
             *window, Mouse,
@@ -1612,7 +1603,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
             break;
 
         fgSetWindow( window );
-        fgState.Modifiers = fgGetWin32Modifiers( );
+        fgState.Modifiers = fghGetWin32Modifiers( );
 
         while( ticks-- )
             if( FETCH_WCB( *window, MouseWheel ) )
@@ -1659,7 +1650,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
          * Remember the current modifiers state. This is done here in order
          * to make sure the VK_DELETE keyboard callback is executed properly.
          */
-        fgState.Modifiers = fgGetWin32Modifiers( );
+        fgState.Modifiers = fghGetWin32Modifiers( );
 
         GetCursorPos( &mouse_pos );
         ScreenToClient( window->Window.Handle, &mouse_pos );
@@ -1667,9 +1658,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
         window->State.MouseX = mouse_pos.x;
         window->State.MouseY = mouse_pos.y;
 
-        /*
-         * Convert the Win32 keystroke codes to GLUTtish way
-         */
+        /* Convert the Win32 keystroke codes to GLUTtish way */
 #       define KEY(a,b) case a: keypress = b; break;
 
         switch( wParam )
@@ -1697,9 +1686,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
             KEY( VK_INSERT, GLUT_KEY_INSERT    );
 
         case VK_DELETE:
-            /*
-             * The delete key should be treated as an ASCII keypress:
-             */
+            /* The delete key should be treated as an ASCII keypress: */
             INVOKE_WCB( *window, Keyboard,
                         ( 127, window->State.MouseX, window->State.MouseY )
             );
@@ -1747,7 +1734,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
          * Remember the current modifiers state. This is done here in order
          * to make sure the VK_DELETE keyboard callback is executed properly.
          */
-        fgState.Modifiers = fgGetWin32Modifiers( );
+        fgState.Modifiers = fghGetWin32Modifiers( );
 
         GetCursorPos( &mouse_pos );
         ScreenToClient( window->Window.Handle, &mouse_pos );
@@ -1785,9 +1772,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
             KEY( VK_INSERT, GLUT_KEY_INSERT    );
 
           case VK_DELETE:
-              /*
-               * The delete key should be treated as an ASCII keypress:
-               */
+              /* The delete key should be treated as an ASCII keypress: */
               INVOKE_WCB( *window, KeyboardUp,
                           ( 127, window->State.MouseX, window->State.MouseY )
               );
@@ -1828,7 +1813,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
       if( (fgState.KeyRepeat==GLUT_KEY_REPEAT_OFF || window->State.IgnoreKeyRepeat==GL_TRUE) && (HIWORD(lParam) & KF_REPEAT) )
             break;
 
-        fgState.Modifiers = fgGetWin32Modifiers( );
+        fgState.Modifiers = fghGetWin32Modifiers( );
         INVOKE_WCB( *window, Keyboard,
                     ( (char)wParam,
                       window->State.MouseX, window->State.MouseY )
@@ -1844,9 +1829,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
         /*lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); */
         break;
 
-        /*
-         * Other messages that I have seen and which are not handled already
-         */
+        /* Other messages that I have seen and which are not handled already */
     case WM_SETTEXT:  /* 0x000c */
         lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
         /* Pass it on to "DefWindowProc" to set the window text */
@@ -1953,7 +1936,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
 
             default:
 #if _DEBUG
-                fgWarning( "Unknown wParam type 0x%x\n", wParam );
+                fgWarning( "Unknown wParam type 0x%x", wParam );
 #endif
                 break;
             }
@@ -1965,9 +1948,7 @@ LRESULT CALLBACK fgWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam,
         break;
 
     default:
-        /*
-         * Handle unhandled messages
-         */
+        /* Handle unhandled messages */
         lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );
         break;
     }