X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Ffg_main.c;h=82f708c615cabc9d2eaacf89d8cde7c82f779f49;hb=99d53f15a4216240088132f6af9cb194b519b1cc;hp=fd94e0efd0b747e1884c3e72013865df68bfb2fc;hpb=f50219f3ee035143ce9a056e4362959bef5c91cc;p=freeglut diff --git a/src/fg_main.c b/src/fg_main.c index fd94e0e..82f708c 100644 --- a/src/fg_main.c +++ b/src/fg_main.c @@ -54,8 +54,7 @@ # define MIN(a,b) (((a)<(b)) ? (a) : (b)) #endif -extern void fgPlatformReshapeWindow ( SFG_Window *window, int width, int height ); -extern void fgPlatformDisplayWindow ( SFG_Window *window ); +extern void fgPlatformProcessWork ( SFG_Window *window ); extern fg_time_t fgPlatformSystemTime ( void ); extern void fgPlatformSleepForEvents( fg_time_t msec ); extern void fgPlatformProcessSingleEvent ( void ); @@ -66,77 +65,118 @@ extern void fgPlatformMainLoopPreliminaryWork ( void ); /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ -static void fghReshapeWindow ( SFG_Window *window, int width, int height ) +void fghOnReshapeNotify(SFG_Window *window, int width, int height, GLboolean forceNotify) { - SFG_Window *current_window = fgStructure.CurrentWindow; + GLboolean notify = GL_FALSE; - freeglut_return_if_fail( window != NULL ); + if( width != window->State.Width || + height != window->State.Height ) + { + window->State.Width = width; + window->State.Height = height; - fgPlatformReshapeWindow ( window, width, height ); + notify = GL_TRUE; + } - if( FETCH_WCB( *window, Reshape ) ) - INVOKE_WCB( *window, Reshape, ( width, height ) ); - else + if (notify || forceNotify) { - fgSetWindow( window ); - glViewport( 0, 0, width, height ); + SFG_Window *saved_window = fgStructure.CurrentWindow; + + INVOKE_WCB( *window, Reshape, ( width, height ) ); + + /* + * Force a window redraw. In Windows at least this is only a partial + * solution: if the window is increasing in size in either dimension, + * the already-drawn part does not get drawn again and things look funny. + * But without this we get this bad behaviour whenever we resize the + * window. + * DN: Hmm.. the above sounds like a concern only in single buffered mode... + */ + glutPostRedisplay( ); + if( window->IsMenu ) + fgSetWindow( saved_window ); } +} - /* - * Force a window redraw. In Windows at least this is only a partial - * solution: if the window is increasing in size in either dimension, - * the already-drawn part does not get drawn again and things look funny. - * But without this we get this bad behaviour whenever we resize the - * window. - * DN: Hmm.. the above sounds like a concern only in single buffered mode... - */ - window->State.Redisplay = GL_TRUE; +void fghOnPositionNotify(SFG_Window *window, int x, int y, GLboolean forceNotify) +{ + GLboolean notify = GL_FALSE; + + if( x != window->State.Xpos || + y != window->State.Ypos ) + { + window->State.Xpos = x; + window->State.Ypos = y; - if( window->IsMenu ) - fgSetWindow( current_window ); + notify = GL_TRUE; + } + + if (notify || forceNotify) + { + SFG_Window *saved_window = fgStructure.CurrentWindow; + INVOKE_WCB( *window, Position, ( x, y ) ); + fgSetWindow( saved_window ); + } } /* * Calls a window's redraw method. This is used when - * a redraw is forced by the incoming window messages. + * a redraw is forced by the incoming window messages, + * or if a redisplay is otherwise pending. + * this is lean and mean without checks as it is + * currently only called from fghcbDisplayWindow which + * only calls this if the window is visible and needs + * a redisplay. + * Note that the fgSetWindow call on Windows makes the + * right device context current on windows, allowing + * direct drawing without BeginPaint/EndPaint in the + * WM_PAINT handler. */ void fghRedrawWindow ( SFG_Window *window ) { SFG_Window *current_window = fgStructure.CurrentWindow; - freeglut_return_if_fail( window ); + fgSetWindow( window ); + INVOKE_WCB( *window, Display, ( ) ); - if( window->State.NeedToInitContext ) { - INVOKE_WCB( *window, InitContext, ()); - window->State.NeedToInitContext = GL_FALSE; - } + fgSetWindow( current_window ); +} - freeglut_return_if_fail( FETCH_WCB ( *window, Display ) ); +void fghRedrawWindowAndChildren ( SFG_Window *window ) +{ + SFG_Window* child; - window->State.Redisplay = GL_FALSE; + fghRedrawWindow(window); - freeglut_return_if_fail( window->State.Visible ); + for( child = ( SFG_Window * )window->Children.First; + child; + child = ( SFG_Window * )child->Node.Next ) + { + fghRedrawWindowAndChildren(child); + } +} - fgSetWindow( window ); - if( window->State.NeedToResize ) - { - /* Set need to resize to false before calling fghReshapeWindow, otherwise - in the case the user's reshape callback calls glutReshapeWindow, - his request would get canceled after fghReshapeWindow gets called. - */ - window->State.NeedToResize = GL_FALSE; +static void fghcbProcessWork( SFG_Window *window, + SFG_Enumerator *enumerator ) +{ + if( window->State.WorkMask ) + fgPlatformProcessWork ( window ); - fghReshapeWindow( - window, - window->State.Width, - window->State.Height - ); - } + fgEnumSubWindows( window, fghcbProcessWork, enumerator ); +} - INVOKE_WCB( *window, Display, ( ) ); +/* + * Make all windows process their work list + */ +static void fghProcessWork( void ) +{ + SFG_Enumerator enumerator; - fgSetWindow( current_window ); + enumerator.found = GL_FALSE; + enumerator.data = NULL; + + fgEnumWindows( fghcbProcessWork, &enumerator ); } @@ -147,7 +187,7 @@ static void fghcbDisplayWindow( SFG_Window *window, window->State.Visible ) { window->State.Redisplay = GL_FALSE; - fgPlatformDisplayWindow ( window ); + fghRedrawWindow ( window ); } fgEnumSubWindows( window, fghcbDisplayWindow, enumerator ); @@ -221,6 +261,7 @@ static void fghCheckTimers( void ) SFG_Timer *timer = fgState.Timers.First; if( timer->TriggerTime > checkTime ) + /* XXX: are timers always sorted by triggerTime? If not, this and fghNextTimer are wrong */ break; fgListRemove( &fgState.Timers, &timer->Node ); @@ -316,13 +357,11 @@ void fgWarning( const char *fmt, ... ) /* - * Indicates whether Joystick events are being used by ANY window. + * Indicates whether a redisplay is pending for ANY window. * * The current mechanism is to walk all of the windows and ask if - * there is a joystick callback. We have a short-circuit early - * return if we find any joystick handler registered. - * - * + * a redisplay is pending. We have a short-circuit early + * return if we find any. */ static void fghHavePendingRedisplaysCallback( SFG_Window* w, SFG_Enumerator* e) { @@ -330,6 +369,7 @@ static void fghHavePendingRedisplaysCallback( SFG_Window* w, SFG_Enumerator* e) { e->found = GL_TRUE; e->data = w; + return; } fgEnumSubWindows( w, fghHavePendingRedisplaysCallback, e ); } @@ -384,12 +424,18 @@ static void fghSleepForEvents( void ) */ void FGAPIENTRY glutMainLoopEvent( void ) { + /* Process input */ fgPlatformProcessSingleEvent (); if( fgState.Timers.First ) fghCheckTimers( ); if (fgState.NumActiveJoysticks>0) /* If zero, don't poll joysticks */ fghCheckJoystickPolls( ); + + /* Perform work on the window (position, reshape, etc) */ + fghProcessWork( ); + + /* Display */ fghDisplayAll( ); fgCloseWindows( );