Further work on experiment llmozlib/geko based embedded web browser

This commit is contained in:
Robert Osfield
2008-11-14 16:48:07 +00:00
parent d75cc7f84d
commit b62cb79c7e
6 changed files with 799 additions and 311 deletions

View File

@@ -17,7 +17,8 @@ ADD_DEFINITIONS(-DMOZILLA_INTERNAL_API)
# MESSAGE("XUL_LIBRARIES = " ${XUL_LIBRARIES})
# MESSAGE("XUL_INCLUDE_DIRS = " ${XUL_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(
INCLUDE_DIRECTORIES( ${GLUT_INCLUDE_DIR}
${GTK_INCLUDE_DIRS} ${GTKGL_INCLUDE_DIRS}
${XUL_INCLUDE_DIRS}
/usr/include/xulrunner/locale
/usr/include/xulrunner/view
@@ -36,7 +37,7 @@ INCLUDE_DIRECTORIES(
/usr/include/xulrunner/xulapp
)
LINK_DIRECTORIES( ${XUL_LIB_DIRS})
SET(TARGET_EXTERNAL_LIBRARIES ${XUL_LIBRARIES})
SET(TARGET_EXTERNAL_LIBRARIES ${XUL_LIBRARIES} ${GLUT_glut_LIBRARY})
#### end var setup ###
SETUP_EXAMPLE(osgbrowser)

View File

@@ -38,11 +38,11 @@
// Windows specific switches
#ifdef WIN32
// appears to be required by LibXUL/Mozilla code to avoid crashes in debug versions of their code (undef'd at end of this file)
#ifdef _DEBUG
#define DEBUG 1
#endif
#endif // WIN32
// appears to be required by LibXUL/Mozilla code to avoid crashes in debug versions of their code (undef'd at end of this file)
#ifdef _DEBUG
#define DEBUG 1
#endif
#endif // WIN32
#include <iostream>
@@ -50,9 +50,9 @@
#include "llembeddedbrowserwindow.h"
#ifdef WIN32
#pragma warning( disable : 4265 ) // "class has virtual functions, but destructor is not virtual"
#pragma warning( disable : 4291 ) // (no matching operator delete found; memory will not be freed if initialization throws an exception)
#endif // WIN32
#pragma warning( disable : 4265 ) // "class has virtual functions, but destructor is not virtual"
#pragma warning( disable : 4291 ) // (no matching operator delete found; memory will not be freed if initialization throws an exception)
#endif // WIN32
#include "nsBuildID.h"
#include "nsICacheService.h"
@@ -75,8 +75,8 @@ LLEmbeddedBrowser* LLEmbeddedBrowser::sInstance = 0;
////////////////////////////////////////////////////////////////////////////////
//
LLEmbeddedBrowser::LLEmbeddedBrowser() :
mErrorNum( 0 ),
mNativeWindowHandle( 0 )
mErrorNum( 0 ),
mNativeWindowHandle( 0 )
{
}
@@ -95,267 +95,281 @@ LLEmbeddedBrowser* LLEmbeddedBrowser::getInstance()
sInstance = new LLEmbeddedBrowser;
};
return sInstance;
return sInstance;
};
////////////////////////////////////////////////////////////////////////////////
//
void LLEmbeddedBrowser::setLastError( int errorNumIn )
{
mErrorNum = errorNumIn;
mErrorNum = errorNumIn;
}
////////////////////////////////////////////////////////////////////////////////
//
void LLEmbeddedBrowser::clearLastError()
{
mErrorNum = 0x0000;
mErrorNum = 0x0000;
}
////////////////////////////////////////////////////////////////////////////////
//
int LLEmbeddedBrowser::getLastError()
{
return mErrorNum;
return mErrorNum;
}
////////////////////////////////////////////////////////////////////////////////
//
std::string LLEmbeddedBrowser::getGREVersion()
{
// take the string directly from Mozilla
return std::string( GRE_BUILD_ID );
// take the string directly from Mozilla
return std::string( GRE_BUILD_ID );
}
////////////////////////////////////////////////////////////////////////////////
//
bool LLEmbeddedBrowser::init( std::string applicationDir,
std::string componentDir,
std::string profileDir,
void* nativeWindowHandleIn )
std::string componentDir,
std::string profileDir,
void* nativeWindowHandleIn )
{
mNativeWindowHandle = nativeWindowHandleIn;
mNativeWindowHandle = nativeWindowHandleIn;
std::cout<<"applicationDir "<<applicationDir<<std::endl;
std::cout<<"componentDir "<<componentDir<<std::endl;
std::cout<<"profileDir "<<profileDir<<std::endl;
NS_ConvertUTF8toUTF16 applicationDirUTF16(applicationDir.c_str());
NS_ConvertUTF8toUTF16 componentDirUTF16(componentDir.c_str());
NS_ConvertUTF8toUTF16 profileDirUTF16(profileDir.c_str());
NS_ConvertUTF8toUTF16 profileDirUTF16(profileDir.c_str());
nsCOMPtr< nsILocalFile > applicationDirNative;
nsresult result = NS_NewLocalFile( applicationDirUTF16, PR_FALSE, getter_AddRefs( applicationDirNative ) );
if ( NS_FAILED( result ) )
{
setLastError( 0x1000 );
return false;
};
nsCOMPtr< nsILocalFile > applicationDirNative;
nsresult result = NS_NewLocalFile( applicationDirUTF16, PR_FALSE, getter_AddRefs( applicationDirNative ) );
if ( NS_FAILED( result ) )
{
std::cout<<"NS_NewLocalFile failed"<<std::endl;
setLastError( 0x1000 );
return false;
};
nsCOMPtr< nsILocalFile > componentDirNative;
result = NS_NewLocalFile( componentDirUTF16 , PR_FALSE, getter_AddRefs( componentDirNative ) );
if ( NS_FAILED( result ) )
{
setLastError( 0x1001 );
return false;
};
nsCOMPtr< nsILocalFile > componentDirNative;
result = NS_NewLocalFile( componentDirUTF16 , PR_FALSE, getter_AddRefs( componentDirNative ) );
if ( NS_FAILED( result ) )
{
std::cout<<"NS_NewLocalFile failed 2"<<std::endl;
result = XRE_InitEmbedding( componentDirNative, applicationDirNative, nsnull, nsnull, 0 );
if ( NS_FAILED( result ) )
{
setLastError( 0x1002 );
return false;
};
setLastError( 0x1001 );
return false;
};
nsCOMPtr< nsILocalFile > profileDirNative;
result = NS_NewLocalFile( profileDirUTF16 , PR_TRUE, getter_AddRefs( profileDirNative ) );
if ( NS_FAILED( result ) )
{
setLastError( 0x1007 );
return false;
};
result = XRE_InitEmbedding( componentDirNative, applicationDirNative, nsnull, nsnull, 0 );
if ( NS_FAILED( result ) )
{
std::cout<<"XRE_InitEmbedding failed"<<std::endl;
setLastError( 0x1002 );
return false;
};
std::cout<<"XRE_InitEmbedding succeeded"<<std::endl;
nsCOMPtr< nsILocalFile > profileDirNative;
result = NS_NewLocalFile( profileDirUTF16 , PR_TRUE, getter_AddRefs( profileDirNative ) );
if ( NS_FAILED( result ) )
{
setLastError( 0x1007 );
return false;
};
#if 0
nsCOMPtr< nsProfileDirServiceProvider > locProvider;
NS_NewProfileDirServiceProvider( PR_TRUE, getter_AddRefs( locProvider ) );
if ( ! locProvider )
{
setLastError( 0x1003 );
XRE_TermEmbedding();
return PR_FALSE;
};
result = locProvider->Register();
if ( NS_FAILED( result ) )
{
setLastError( 0x1004 );
XRE_TermEmbedding();
return PR_FALSE;
};
nsCOMPtr< nsProfileDirServiceProvider > locProvider;
NS_NewProfileDirServiceProvider( PR_TRUE, getter_AddRefs( locProvider ) );
if ( ! locProvider )
{
setLastError( 0x1003 );
XRE_TermEmbedding();
return PR_FALSE;
};
result = locProvider->Register();
if ( NS_FAILED( result ) )
{
setLastError( 0x1004 );
XRE_TermEmbedding();
return PR_FALSE;
};
result = locProvider->SetProfileDir( profileDirNative );
if ( NS_FAILED( result ) )
{
setLastError( 0x1005 );
XRE_TermEmbedding();
return PR_FALSE;
};
result = locProvider->SetProfileDir( profileDirNative );
if ( NS_FAILED( result ) )
{
setLastError( 0x1005 );
XRE_TermEmbedding();
return PR_FALSE;
};
#endif
nsCOMPtr<nsIPref> pref = do_CreateInstance( NS_PREF_CONTRACTID );
if ( pref )
{
pref->SetBoolPref( "security.warn_entering_secure", PR_FALSE );
pref->SetBoolPref( "security.warn_entering_weak", PR_FALSE );
pref->SetBoolPref( "security.warn_leaving_secure", PR_FALSE );
pref->SetBoolPref( "security.warn_submit_insecure", PR_FALSE );
pref->SetBoolPref( "network.protocol-handler.warn-external-default", PR_FALSE );
}
else
{
setLastError( 0x1006 );
};
nsCOMPtr<nsIPref> pref = do_CreateInstance( NS_PREF_CONTRACTID );
if ( pref )
{
pref->SetBoolPref( "security.warn_entering_secure", PR_FALSE );
pref->SetBoolPref( "security.warn_entering_weak", PR_FALSE );
pref->SetBoolPref( "security.warn_leaving_secure", PR_FALSE );
pref->SetBoolPref( "security.warn_submit_insecure", PR_FALSE );
pref->SetBoolPref( "network.protocol-handler.warn-external-default", PR_FALSE );
}
else
{
setLastError( 0x1006 );
};
// disable proxy by default
enableProxy( false, "", 0 );
// disable proxy by default
enableProxy( false, "", 0 );
// Originally from Linux version but seems to help other platforms too
nsresult rv;
nsCOMPtr<nsIAppShell> appShell;
NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
appShell = do_CreateInstance(kAppShellCID, &rv);
if (!appShell)
{
setLastError( 0x1008 );
return PR_FALSE;
}
sAppShell = appShell.get();
NS_ADDREF(sAppShell);
sAppShell->Create(0, nsnull);
sAppShell->Spinup();
nsresult rv;
nsCOMPtr<nsIAppShell> appShell;
NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
appShell = do_CreateInstance(kAppShellCID, &rv);
if (!appShell)
{
setLastError( 0x1008 );
return PR_FALSE;
}
sAppShell = appShell.get();
NS_ADDREF(sAppShell);
sAppShell->Create(0, nsnull);
sAppShell->Spinup();
clearLastError();
clearLastError();
return true;
std::cout<<"LLEmbeddedBrowser::init() succeeded"<<std::endl;
return true;
}
////////////////////////////////////////////////////////////////////////////////
//
bool LLEmbeddedBrowser::reset()
{
XRE_TermEmbedding();
XRE_TermEmbedding();
return true;
return true;
}
////////////////////////////////////////////////////////////////////////////////
//
bool LLEmbeddedBrowser::clearCache()
{
nsCOMPtr< nsICacheService > cacheService = do_GetService( NS_CACHESERVICE_CONTRACTID );
if (! cacheService)
return false;
nsCOMPtr< nsICacheService > cacheService = do_GetService( NS_CACHESERVICE_CONTRACTID );
if (! cacheService)
return false;
cacheService->EvictEntries( nsICache::STORE_ANYWHERE );
cacheService->EvictEntries( nsICache::STORE_ANYWHERE );
return true;
return true;
}
////////////////////////////////////////////////////////////////////////////////
//
bool LLEmbeddedBrowser::enableProxy( bool proxyEnabledIn, std::string proxyHostNameIn, int proxyPortIn )
{
nsCOMPtr<nsIPref> pref = do_CreateInstance( NS_PREF_CONTRACTID );
if ( pref )
{
if ( proxyEnabledIn )
pref->SetIntPref( "network.proxy.type", 1 );
else
pref->SetIntPref( "network.proxy.type", 0 );
nsCOMPtr<nsIPref> pref = do_CreateInstance( NS_PREF_CONTRACTID );
if ( pref )
{
if ( proxyEnabledIn )
pref->SetIntPref( "network.proxy.type", 1 );
else
pref->SetIntPref( "network.proxy.type", 0 );
pref->SetCharPref( "network.proxy.ssl", proxyHostNameIn.c_str() );
pref->SetIntPref( "network.proxy.ssl_port", proxyPortIn );
pref->SetCharPref( "network.proxy.ssl", proxyHostNameIn.c_str() );
pref->SetIntPref( "network.proxy.ssl_port", proxyPortIn );
pref->SetCharPref( "network.proxy.ftp", proxyHostNameIn.c_str() );
pref->SetIntPref( "network.proxy.ftp_port", proxyPortIn );
pref->SetCharPref( "network.proxy.ftp", proxyHostNameIn.c_str() );
pref->SetIntPref( "network.proxy.ftp_port", proxyPortIn );
pref->SetCharPref( "network.proxy.gopher", proxyHostNameIn.c_str() );
pref->SetIntPref( "network.proxy.gopher_port", proxyPortIn );
pref->SetCharPref( "network.proxy.gopher", proxyHostNameIn.c_str() );
pref->SetIntPref( "network.proxy.gopher_port", proxyPortIn );
pref->SetCharPref( "network.proxy.http", proxyHostNameIn.c_str() );
pref->SetIntPref( "network.proxy.http_port", proxyPortIn );
pref->SetCharPref( "network.proxy.http", proxyHostNameIn.c_str() );
pref->SetIntPref( "network.proxy.http_port", proxyPortIn );
pref->SetBoolPref( "network.proxy.share_proxy_settings", true );
pref->SetBoolPref( "network.proxy.share_proxy_settings", true );
return true;
};
return true;
};
return false;
return false;
}
////////////////////////////////////////////////////////////////////////////////
//
bool LLEmbeddedBrowser::enableCookies( bool enabledIn )
{
nsCOMPtr<nsIPref> pref = do_CreateInstance( NS_PREF_CONTRACTID );
if ( pref )
{
if ( enabledIn )
pref->SetIntPref( "network.cookie.cookieBehavior", 0 );
else
pref->SetIntPref( "network.cookie.cookieBehavior", 2 );
nsCOMPtr<nsIPref> pref = do_CreateInstance( NS_PREF_CONTRACTID );
if ( pref )
{
if ( enabledIn )
pref->SetIntPref( "network.cookie.cookieBehavior", 0 );
else
pref->SetIntPref( "network.cookie.cookieBehavior", 2 );
return true;
}
return true;
}
return false;
return false;
}
////////////////////////////////////////////////////////////////////////////////
//
bool LLEmbeddedBrowser::clearAllCookies()
{
nsCOMPtr< nsICookieManager > cookieManager = do_GetService( NS_COOKIEMANAGER_CONTRACTID );
if ( ! cookieManager )
return false;
nsCOMPtr< nsICookieManager > cookieManager = do_GetService( NS_COOKIEMANAGER_CONTRACTID );
if ( ! cookieManager )
return false;
cookieManager->RemoveAll();
cookieManager->RemoveAll();
return true;
return true;
}
////////////////////////////////////////////////////////////////////////////////
//
bool LLEmbeddedBrowser::enablePlugins( bool enabledIn )
{
nsCOMPtr<nsIPref> pref = do_CreateInstance( NS_PREF_CONTRACTID );
if ( pref )
{
if ( enabledIn )
{
pref->SetBoolPref( "plugin.scan.plid.all", PR_TRUE );
pref->SetBoolPref( "xpinstall-enabled", PR_TRUE );
}
else
{
pref->SetBoolPref( "plugin.scan.plid.all", PR_FALSE );
pref->SetBoolPref( "xpinstall-enabled", PR_FALSE );
pref->SetBoolPref( "plugin.scan.4xPluginFolder", PR_FALSE );
pref->SetCharPref( "plugin.scan.Quicktime", "20.0" );
pref->SetCharPref( "plugin.scan.Acrobat", "99.0" );
pref->SetCharPref( "plugin.scan.SunJRE", "99.0" );
pref->SetCharPref( "plugin.scan.WindowsMediaPlayer", "99.0" );
};
nsCOMPtr<nsIPref> pref = do_CreateInstance( NS_PREF_CONTRACTID );
if ( pref )
{
if ( enabledIn )
{
pref->SetBoolPref( "plugin.scan.plid.all", PR_TRUE );
pref->SetBoolPref( "xpinstall-enabled", PR_TRUE );
}
else
{
pref->SetBoolPref( "plugin.scan.plid.all", PR_FALSE );
pref->SetBoolPref( "xpinstall-enabled", PR_FALSE );
pref->SetBoolPref( "plugin.scan.4xPluginFolder", PR_FALSE );
pref->SetCharPref( "plugin.scan.Quicktime", "20.0" );
pref->SetCharPref( "plugin.scan.Acrobat", "99.0" );
pref->SetCharPref( "plugin.scan.SunJRE", "99.0" );
pref->SetCharPref( "plugin.scan.WindowsMediaPlayer", "99.0" );
};
return true;
};
return true;
};
return false;
return false;
}
////////////////////////////////////////////////////////////////////////////////
//
void LLEmbeddedBrowser::setBrowserAgentId( std::string idIn )
{
nsCOMPtr<nsIPref> pref = do_CreateInstance( NS_PREF_CONTRACTID );
if ( pref )
{
pref->SetCharPref( "general.useragent.extra.* ", idIn.c_str() );
};
nsCOMPtr<nsIPref> pref = do_CreateInstance( NS_PREF_CONTRACTID );
if ( pref )
{
pref->SetCharPref( "general.useragent.extra.* ", idIn.c_str() );
};
}
////////////////////////////////////////////////////////////////////////////////
@@ -364,43 +378,45 @@ LLEmbeddedBrowserWindow* LLEmbeddedBrowser::createBrowserWindow( int browserWidt
{
nsCOMPtr< nsIWebBrowserChrome > chrome;
LLEmbeddedBrowserWindow* newWin = new LLEmbeddedBrowserWindow();
if ( ! newWin )
{
return 0;
};
LLEmbeddedBrowserWindow* newWin = new LLEmbeddedBrowserWindow();
if ( ! newWin )
{
std::cout<<"createBrowserWindow !newNew"<<std::endl;
return 0;
};
nsIWebBrowserChrome** aNewWindow = getter_AddRefs( chrome );
nsIWebBrowserChrome** aNewWindow = getter_AddRefs( chrome );
CallQueryInterface( NS_STATIC_CAST( nsIWebBrowserChrome*, newWin ), aNewWindow );
CallQueryInterface( NS_STATIC_CAST( nsIWebBrowserChrome*, newWin ), aNewWindow );
NS_ADDREF( *aNewWindow );
NS_ADDREF( *aNewWindow );
newWin->SetChromeFlags( nsIWebBrowserChrome::CHROME_ALL );
newWin->SetChromeFlags( nsIWebBrowserChrome::CHROME_ALL );
nsCOMPtr< nsIWebBrowser > newBrowser;
nsCOMPtr< nsIWebBrowser > newBrowser;
newWin->createBrowser( mNativeWindowHandle, browserWidthIn, browserHeightIn, getter_AddRefs( newBrowser ) );
if ( ! newBrowser )
{
return 0;
};
newWin->createBrowser( mNativeWindowHandle, browserWidthIn, browserHeightIn, getter_AddRefs( newBrowser ) );
if ( ! newBrowser )
{
std::cout<<"createBrowserWindow !newBrowser"<<std::endl;
return 0;
};
if ( newWin && chrome )
{
newWin->setParent( this );
newWin->setParent( this );
nsCOMPtr< nsIWebBrowser > newBrowser;
chrome->GetWebBrowser( getter_AddRefs( newBrowser ) );
nsCOMPtr< nsIWebNavigation > webNav( do_QueryInterface ( newBrowser ) );
webNav->LoadURI( NS_ConvertUTF8toUTF16( "about:blank" ).get(), nsIWebNavigation::LOAD_FLAGS_NONE, nsnull, nsnull, nsnull );
webNav->LoadURI( NS_ConvertUTF8toUTF16( "about:blank" ).get(), nsIWebNavigation::LOAD_FLAGS_NONE, nsnull, nsnull, nsnull );
clearLastError();
clearLastError();
return newWin;
return newWin;
};
setLastError( 0x2001 );
return 0;
setLastError( 0x2001 );
return 0;
};
@@ -408,44 +424,44 @@ LLEmbeddedBrowserWindow* LLEmbeddedBrowser::createBrowserWindow( int browserWidt
//
bool LLEmbeddedBrowser::destroyBrowserWindow( LLEmbeddedBrowserWindow* browserWindowIn )
{
nsCOMPtr< nsIWebBrowser > webBrowser;
nsCOMPtr< nsIWebNavigation > webNavigation;
nsCOMPtr< nsIWebBrowser > webBrowser;
nsCOMPtr< nsIWebNavigation > webNavigation;
browserWindowIn->GetWebBrowser( getter_AddRefs( webBrowser ) );
webNavigation = do_QueryInterface( webBrowser );
if ( webNavigation )
{
webNavigation->Stop( nsIWebNavigation::STOP_ALL );
};
browserWindowIn->GetWebBrowser( getter_AddRefs( webBrowser ) );
webNavigation = do_QueryInterface( webBrowser );
if ( webNavigation )
{
webNavigation->Stop( nsIWebNavigation::STOP_ALL );
};
nsCOMPtr< nsIWebBrowser > browser = nsnull;
browserWindowIn->GetWebBrowser( getter_AddRefs( browser ) );
nsCOMPtr< nsIBaseWindow > browserAsWin = do_QueryInterface( browser );
if ( browserAsWin )
{
browserAsWin->Destroy();
};
nsCOMPtr< nsIWebBrowser > browser = nsnull;
browserWindowIn->GetWebBrowser( getter_AddRefs( browser ) );
nsCOMPtr< nsIBaseWindow > browserAsWin = do_QueryInterface( browser );
if ( browserAsWin )
{
browserAsWin->Destroy();
};
browserWindowIn->SetWebBrowser( nsnull );
browserWindowIn->SetWebBrowser( nsnull );
NS_RELEASE( browserWindowIn );
NS_RELEASE( browserWindowIn );
delete browserWindowIn;
delete browserWindowIn;
clearLastError();
clearLastError();
return true;
return true;
}
// Windows specific switches
#ifdef WIN32
#pragma warning( 3 : 4291 ) // (no matching operator delete found; memory will not be freed if initialization throws an exception)
#pragma warning( 3 : 4265 ) // "class has virtual functions, but destructor is not virtual"
#pragma warning( 3 : 4291 ) // (no matching operator delete found; memory will not be freed if initialization throws an exception)
#pragma warning( 3 : 4265 ) // "class has virtual functions, but destructor is not virtual"
// #define required by this file for LibXUL/Mozilla code to avoid crashes in their debug code
#ifdef _DEBUG
#undef DEBUG
#endif
// #define required by this file for LibXUL/Mozilla code to avoid crashes in their debug code
#ifdef _DEBUG
#undef DEBUG
#endif
#endif // WIN32
#endif // WIN32

View File

@@ -157,6 +157,8 @@ nsresult LLEmbeddedBrowserWindow::createBrowser( void* nativeWindowHandleIn, PRI
mWebBrowser = do_CreateInstance( NS_WEBBROWSER_CONTRACTID, &rv );
if ( ! mWebBrowser )
{
std::cout<<"createBrowser ! mWebBrowser at start"<<std::endl;
return NS_ERROR_FAILURE;
}
@@ -185,6 +187,7 @@ nsresult LLEmbeddedBrowserWindow::createBrowser( void* nativeWindowHandleIn, PRI
mWebNav = do_QueryInterface( mWebBrowser, &result );
if ( NS_FAILED( result ) || ! mWebNav )
{
std::cout<<"createBrowser ! do_QueryInterface"<<std::endl;
return NS_ERROR_FAILURE;
};
@@ -198,6 +201,8 @@ nsresult LLEmbeddedBrowserWindow::createBrowser( void* nativeWindowHandleIn, PRI
return NS_OK;
};
std::cout<<"createBrowser ! mWebBrowser"<<std::endl;
return NS_ERROR_FAILURE;
}
@@ -214,7 +219,9 @@ NS_INTERFACE_MAP_BEGIN( LLEmbeddedBrowserWindow )
NS_INTERFACE_MAP_ENTRY( nsIWebBrowserChrome )
NS_INTERFACE_MAP_ENTRY( nsIWebProgressListener )
NS_INTERFACE_MAP_ENTRY( nsIURIContentListener )
#ifdef SUPPORTS_WEAK_REFENCE
NS_INTERFACE_MAP_ENTRY( nsISupportsWeakReference )
#endif
#ifdef NS_DECL_NSITOOLKITOBSERVER
NS_INTERFACE_MAP_ENTRY( nsIToolkitObserver )
#endif
@@ -583,19 +590,26 @@ NS_IMETHODIMP LLEmbeddedBrowserWindow::OnSecurityChange( nsIWebProgress* aWebPro
// need to make this work with arbitrary rects (i.e. the dirty rect)
unsigned char* LLEmbeddedBrowserWindow::grabWindow( int xIn, int yIn, int widthIn, int heightIn )
{
std::cout<<"grabWindow("<<xIn<<", "<<yIn<<", "<<widthIn<<", "<<heightIn<<")"<<std::endl;
// sanity check
if ( ! mWebBrowser )
return 0;
std::cout<<"grabWindow() A"<<std::endl;
// only grab the window if it's enabled
if ( ! mEnabled )
return false;
std::cout<<"grabWindow() B"<<std::endl;
// get the docshell
nsCOMPtr< nsIDocShell > docShell = do_GetInterface( mWebBrowser );
if ( ! docShell )
return PR_FALSE;
std::cout<<"grabWindow() C"<<std::endl;
// get pres context
nsCOMPtr< nsPresContext > presContext;
@@ -603,6 +617,8 @@ unsigned char* LLEmbeddedBrowserWindow::grabWindow( int xIn, int yIn, int widthI
if ( NS_FAILED( result ) || ( ! presContext ) )
return PR_FALSE;
std::cout<<"grabWindow() D"<<std::endl;
// get view manager
nsIViewManager* viewManager = presContext->GetViewManager();
if ( ! viewManager )
@@ -622,6 +638,8 @@ unsigned char* LLEmbeddedBrowserWindow::grabWindow( int xIn, int yIn, int widthI
if ( rect.IsEmpty() )
return 0;
std::cout<<"grabWindow() E"<<std::endl;
float p2t = presContext->PixelsToTwips();
rect.width = NSIntPixelsToTwips( widthIn, p2t );
rect.height = NSIntPixelsToTwips( heightIn, p2t );
@@ -632,12 +650,16 @@ unsigned char* LLEmbeddedBrowserWindow::grabWindow( int xIn, int yIn, int widthI
if ( NS_FAILED( result ) )
return 0;
std::cout<<"grabWindow() F"<<std::endl;
// retrieve the surface we rendered to
nsIDrawingSurface* surface = nsnull;
context->GetDrawingSurface( &surface );
if ( ! surface )
return 0;
std::cout<<"grabWindow() G"<<std::endl;
// lock the surface and retrieve a pointer to the rendered data and current row span
PRUint8* data;
PRInt32 rowLen;
@@ -646,6 +668,8 @@ unsigned char* LLEmbeddedBrowserWindow::grabWindow( int xIn, int yIn, int widthI
if ( NS_FAILED ( result ) )
return 0;
std::cout<<"grabWindow() H "<< mBrowserRowSpan * mBrowserHeight<<std::endl;
// save row span - it *can* change during the life of the app
mBrowserDepth = rowLen / mBrowserWidth;
@@ -653,6 +677,8 @@ unsigned char* LLEmbeddedBrowserWindow::grabWindow( int xIn, int yIn, int widthI
if ( ! mPageBuffer )
mPageBuffer = new unsigned char[ mBrowserRowSpan * mBrowserHeight ];
std::cout<<"grabWindow() I "<<mBrowserRowSpan<<","<<mBrowserHeight<<" "<<(void*)mPageBuffer<<std::endl;
// save the pixels and optionally invert them
// (it's useful the SL client to get bitmaps that are inverted compared
// to the way that Mozilla renders them - allow to optionally flip

View File

@@ -137,7 +137,9 @@ class LLEmbeddedBrowserWindow :
public nsIWebBrowserChrome,
public nsIWebProgressListener,
public nsIURIContentListener,
#ifdef SUPPORTS_WEAK_REFENCE
public nsSupportsWeakReference,
#endif
public nsIDOMEventListener
#ifdef NS_DECL_NSITOOLKITOBSERVER
,public nsIToolkitObserver
@@ -156,6 +158,7 @@ class LLEmbeddedBrowserWindow :
#ifdef NS_DECL_NSITOOLKITOBSERVER
NS_DECL_NSITOOLKITOBSERVER
#endif
// housekeeping
nsresult createBrowser( void* nativeWindowHandleIn, PRInt32 widthIn, PRInt32 heightIn, nsIWebBrowser** aBrowser );
void setParent( LLEmbeddedBrowser* parentIn ) { mParent = parentIn; };

View File

@@ -78,9 +78,9 @@ LLMozLib::~LLMozLib()
bool LLMozLib::init( std::string applicationDir, std::string componentDir, std::string profileDir, void* nativeWindowHandleIn )
{
return LLEmbeddedBrowser::getInstance()->init( applicationDir,
componentDir,
profileDir,
nativeWindowHandleIn );
componentDir,
profileDir,
nativeWindowHandleIn );
}
////////////////////////////////////////////////////////////////////////////////
@@ -408,8 +408,11 @@ const unsigned char* LLMozLib::getBrowserWindowPixels( int browserWindowIdIn )
LLEmbeddedBrowserWindow* browserWindow = getBrowserWindowFromWindowId( browserWindowIdIn );
if ( browserWindow )
{
std::cout<<"Returning browserWindow->getPageBuffer() "<<std::endl;
return browserWindow->getPageBuffer();
};
std::cout<<"No browserWindow"<<std::endl;
return 0;
}

View File

@@ -11,111 +11,550 @@
#include <osgDB/ReadFile>
class HttpImage : public osg::Image
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Linden Lab Inc. (http://lindenlab.com) code.
*
* The Initial Developer of the Original Code is:
* Callum Prentice (callum@ubrowser.com)
*
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Callum Prentice (callum@ubrowser.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include <iostream>
#include <GL/glut.h>
#include "llmozlib2.h"
////////////////////////////////////////////////////////////////////////////////
// Implementation of the test app - implemented as a class and derrives from
// the observer so we can catch events emitted by LLMozLib
//
class testGL :
public LLEmbeddedBrowserWindowObserver
{
public:
HttpImage() {}
bool open(const std::string& filename)
{
osg::notify(osg::NOTICE)<<"open("<<filename<<")"<<std::endl;
public:
testGL() :
mAppWindowWidth( 800 ), // dimensions of the app window - can be anything
mAppWindowHeight( 600 ),
mBrowserWindowWidth( mAppWindowWidth ), // dimensions of the embedded browser - can be anything
mBrowserWindowHeight( mAppWindowHeight ), // but looks best when it's the same as the app window
mAppTextureWidth( -1 ), // dimensions of the texture that the browser is rendered into
mAppTextureHeight( -1 ), // calculated at initialization
mAppTexture( 0 ),
mNeedsUpdate( true ), // flag to indicate if browser texture needs an update
mBrowserWindowId( 0 ),
mAppWindowName( "testGL" ),
mHomeUrl( "http://www.google.com" )
{
std::cout << "LLMozLib version: " << LLMozLib::getInstance()->getVersion() << std::endl;
};
int width = 1024;
int height = 1024;
////////////////////////////////////////////////////////////////////////////////
//
void init( char* arg0 )
{
// OpenGL initialization
glClearColor( 0.0f, 0.0f, 0.0f, 0.5f);
glEnable( GL_COLOR_MATERIAL );
glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
glEnable( GL_TEXTURE_2D );
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
glEnable( GL_CULL_FACE );
allocateImage(width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE);
setPixelFormat(GL_BGRA);
setDataVariance(osg::Object::DYNAMIC);
setOrigin(osg::Image::TOP_LEFT);
// calculate texture size required (next power of two above browser window size
for ( mAppTextureWidth = 1; mAppTextureWidth < mBrowserWindowWidth; mAppTextureWidth <<= 1 )
{
};
return true;
}
virtual void sendPointerEvent(int x, int y, int buttonMask)
{
osg::notify(osg::NOTICE)<<"sendPointerEvent("<<x<<","<<y<<","<<buttonMask<<")"<<std::endl;
}
for ( mAppTextureHeight = 1; mAppTextureHeight < mBrowserWindowHeight; mAppTextureHeight <<= 1 )
{
};
virtual void sendKeyEvent(int key, bool keyDown)
{
osg::notify(osg::NOTICE)<<"sendKeyEvent("<<key<<","<<keyDown<<")"<<std::endl;
}
// create the texture used to display the browser data
glGenTextures( 1, &mAppTexture );
glBindTexture( GL_TEXTURE_2D, mAppTexture );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexImage2D( GL_TEXTURE_2D, 0,
GL_RGB,
mAppTextureWidth, mAppTextureHeight,
0, GL_RGB, GL_UNSIGNED_BYTE, 0 );
// create a single browser window and set things up.
std::string applicationDir = osgDB::getFilePath(arg0);
if (applicationDir.empty()) applicationDir = osgDB::getRealPath(".");
else applicationDir = osgDB::getRealPath(applicationDir);
std::string componentDir = "/usr/lib/xulrunner";
std::string profileDir = applicationDir + "/" + "testGL_profile";
LLMozLib::getInstance()->init( applicationDir, componentDir, profileDir, getNativeWindowHandle() );
mBrowserWindowId = LLMozLib::getInstance()->createBrowserWindow( mBrowserWindowWidth, mBrowserWindowHeight );
std::cout<<"after createBrowserWindow("<<mBrowserWindowWidth<<", "<<mBrowserWindowHeight<<") mBrowserWindowId = "<<mBrowserWindowId<<std::endl;
// tell LLMozLib about the size of the browser window
LLMozLib::getInstance()->setSize( mBrowserWindowId, mBrowserWindowWidth, mBrowserWindowHeight );
// observer events that LLMozLib emits
LLMozLib::getInstance()->addObserver( mBrowserWindowId, this );
// append details to agent string
LLMozLib::getInstance()->setBrowserAgentId( mAppWindowName );
// don't flip bitmap
LLMozLib::getInstance()->flipWindow( mBrowserWindowId, false );
// go to the "home page"
LLMozLib::getInstance()->navigateTo( mBrowserWindowId, mHomeUrl );
};
////////////////////////////////////////////////////////////////////////////////
//
void reset( void )
{
// unhook observer
LLMozLib::getInstance()->remObserver( mBrowserWindowId, this );
// clean up
LLMozLib::getInstance()->reset();
};
////////////////////////////////////////////////////////////////////////////////
//
void reshape( int widthIn, int heightIn )
{
if ( heightIn == 0 )
heightIn = 1;
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glViewport( 0, 0, widthIn, heightIn );
glOrtho( 0.0f, widthIn, heightIn, 0.0f, -1.0f, 1.0f );
// we use these elsewhere so save
mAppWindowWidth = widthIn;
mAppWindowHeight = heightIn;
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glutPostRedisplay();
};
////////////////////////////////////////////////////////////////////////////////
//
void idle()
{
//std::cout<<"idle()"<<std::endl;
// onPageChanged event sets this
// if ( mNeedsUpdate )
// grab a page but don't reset 'needs update' flag until we've written it to the texture in display()
LLMozLib::getInstance()->grabBrowserWindow( mBrowserWindowId );
// lots of updates for smooth motion
glutPostRedisplay();
};
////////////////////////////////////////////////////////////////////////////////
//
void display()
{
//std::cout<<"display() mBrowserWindowId = "<<mBrowserWindowId<<std::endl;
// clear screen
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glLoadIdentity();
// use the browser texture
glBindTexture( GL_TEXTURE_2D, mAppTexture );
// valid window ?
if ( mBrowserWindowId )
{
// needs to be updated?
if ( mNeedsUpdate )
{
// grab the page
std::cout<<"mNeedsUpdate = true"<<std::endl;
const unsigned char* pixels = LLMozLib::getInstance()->getBrowserWindowPixels( mBrowserWindowId );
if ( pixels )
{
std::cout<<"Texture subload "<<LLMozLib::getInstance()->getBrowserRowSpan( mBrowserWindowId ) / LLMozLib::getInstance()->getBrowserDepth( mBrowserWindowId )<<", "<<mBrowserWindowHeight<<std::endl;
// write them into the texture
glTexSubImage2D( GL_TEXTURE_2D, 0,
0, 0,
// because sometimes the rowspan != width * bytes per pixel (mBrowserWindowWidth)
LLMozLib::getInstance()->getBrowserRowSpan( mBrowserWindowId ) / LLMozLib::getInstance()->getBrowserDepth( mBrowserWindowId ),
mBrowserWindowHeight,
LLMozLib::getInstance()->getBrowserDepth( mBrowserWindowId ) == 3 ? GL_BGR_EXT : GL_BGRA_EXT,
GL_UNSIGNED_BYTE,
pixels );
}
else
{
std::cout<<"No data to subload"<<std::endl;
}
// flag as already updated
// mNeedsUpdate = false;
};
};
// scale the texture so that it fits the screen
GLfloat textureScaleX = ( GLfloat )mBrowserWindowWidth / ( GLfloat )mAppTextureWidth;
GLfloat textureScaleY = ( GLfloat )mBrowserWindowHeight / ( GLfloat )mAppTextureHeight;
// draw the single quad full screen (orthographic)
glMatrixMode( GL_TEXTURE );
glPushMatrix();
glScalef( textureScaleX, textureScaleY, 1.0f );
glEnable( GL_TEXTURE_2D );
glColor3f( 1.0f, 1.0f, 1.0f );
glBegin( GL_QUADS );
glTexCoord2f( 1.0f, 0.0f );
glVertex2d( mAppWindowWidth*0.8, 0 );
glTexCoord2f( 0.0f, 0.0f );
glVertex2d( 0, 0 );
glTexCoord2f( 0.0f, 1.0f );
glVertex2d( 0, mAppWindowHeight*0.8 );
glTexCoord2f( 1.0f, 1.0f );
glVertex2d( mAppWindowWidth*0.8, mAppWindowHeight*0.8 );
glEnd();
glMatrixMode( GL_TEXTURE );
glPopMatrix();
glutSwapBuffers();
};
////////////////////////////////////////////////////////////////////////////////
//
void mouseButton( int button, int state, int xIn, int yIn )
{
// texture is scaled to fit the screen so we scale mouse coords in the same way
xIn = ( xIn * mBrowserWindowWidth ) / mAppWindowWidth;
yIn = ( yIn * mBrowserWindowHeight ) / mAppWindowHeight;
if ( button == GLUT_LEFT_BUTTON )
{
if ( state == GLUT_DOWN )
{
// send event to LLMozLib
LLMozLib::getInstance()->mouseDown( mBrowserWindowId, xIn, yIn );
}
else
if ( state == GLUT_UP )
{
// send event to LLMozLib
LLMozLib::getInstance()->mouseUp( mBrowserWindowId, xIn, yIn );
// this seems better than sending focus on mouse down (still need to improve this)
LLMozLib::getInstance()->focusBrowser( mBrowserWindowId, true );
};
};
// force a GLUT update
glutPostRedisplay();
}
////////////////////////////////////////////////////////////////////////////////
//
void mouseMove( int xIn , int yIn )
{
// texture is scaled to fit the screen so we scale mouse coords in the same way
xIn = ( xIn * mBrowserWindowWidth ) / mAppWindowWidth;
yIn = ( yIn * mBrowserWindowHeight ) / mAppWindowHeight;
// send event to LLMozLib
LLMozLib::getInstance()->mouseMove( mBrowserWindowId, xIn, yIn );
// force a GLUT update
glutPostRedisplay();
};
////////////////////////////////////////////////////////////////////////////////
//
void keyboard( unsigned char keyIn, int xIn, int yIn )
{
if (keyIn=='a')
{
// go to the "home page"
LLMozLib::getInstance()->navigateTo( mBrowserWindowId, "http://www.linuxtoday.org" );
std::cout<<"new browse to"<<std::endl;
}
// ESC key exits
if ( keyIn == 27 )
{
reset();
exit( 0 );
};
// send event to LLMozLib
LLMozLib::getInstance()->keyPress( mBrowserWindowId, keyIn );
};
////////////////////////////////////////////////////////////////////////////////
// virtual
void onPageChanged( const EventType& eventIn )
{
// flag that an update is required - page grab happens in idle() so we don't stall
mNeedsUpdate = true;
};
////////////////////////////////////////////////////////////////////////////////
// virtual
void onNavigateBegin( const EventType& eventIn )
{
std::cout << "Event: begin navigation to " << eventIn.getEventUri() << std::endl;
};
////////////////////////////////////////////////////////////////////////////////
// virtual
void onNavigateComplete( const EventType& eventIn )
{
std::cout << "Event: end navigation to " << eventIn.getEventUri() << " with response status of " << eventIn.getIntValue() << std::endl;
};
////////////////////////////////////////////////////////////////////////////////
// virtual
void onUpdateProgress( const EventType& eventIn )
{
std::cout << "Event: progress value updated to " << eventIn.getIntValue() << std::endl;
};
////////////////////////////////////////////////////////////////////////////////
// virtual
void onStatusTextChange( const EventType& eventIn )
{
std::cout << "Event: status updated to " << eventIn.getStringValue() << std::endl;
};
////////////////////////////////////////////////////////////////////////////////
// virtual
void onLocationChange( const EventType& eventIn )
{
std::cout << "Event: location changed to " << eventIn.getStringValue() << std::endl;
};
////////////////////////////////////////////////////////////////////////////////
// virtual
void onClickLinkHref( const EventType& eventIn )
{
std::cout << "Event: clicked on link to " << eventIn.getStringValue() << std::endl;
};
////////////////////////////////////////////////////////////////////////////////
//
int getAppWindowWidth()
{
return mAppWindowWidth;
};
////////////////////////////////////////////////////////////////////////////////
//
int getAppWindowHeight()
{
return mAppWindowHeight;
};
////////////////////////////////////////////////////////////////////////////////
//
std::string getAppWindowName()
{
return mAppWindowName;
};
////////////////////////////////////////////////////////////////////////////////
//
void* getNativeWindowHandle();
private:
int mAppWindowWidth;
int mAppWindowHeight;
int mBrowserWindowWidth;
int mBrowserWindowHeight;
int mAppTextureWidth;
int mAppTextureHeight;
GLuint mAppTexture;
int mBrowserWindowId;
std::string mAppWindowName;
std::string mHomeUrl;
bool mNeedsUpdate;
};
osg::Node* createInteractiveQuad(const osg::Vec3& origin, osg::Vec3& widthAxis, osg::Vec3& heightAxis,
osg::Image* image)
testGL* theApp;
////////////////////////////////////////////////////////////////////////////////
//
#ifdef _WINDOWS
void* testGL::getNativeWindowHandle()
{
bool flip = image->getOrigin()==osg::Image::TOP_LEFT;
// My implementation of the embedded browser needs a native window handle
// Can't get this via GLUT so had to use this hack
return FindWindow( NULL, mAppWindowName.c_str() );
}
#else
osg::Geometry* pictureQuad = osg::createTexturedQuadGeometry(origin, widthAxis, heightAxis,
0.0f, flip ? 1.0f : 0.0f , 1.0f, flip ? 0.0f : 1.0f);
#include <gtk/gtk.h>
osg::Texture2D* texture = new osg::Texture2D(image);
texture->setResizeNonPowerOfTwoHint(false);
texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0,
texture,
osg::StateAttribute::ON);
pictureQuad->setEventCallback(new osgViewer::InteractiveImageHandler(image));
void* testGL::getNativeWindowHandle()
{
gtk_disable_setlocale();
gtk_init(NULL, NULL);
osg::Geode* geode = new osg::Geode;
geode->addDrawable(pictureQuad);
return geode;
GtkWidget *win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_widget_realize(win);
gtk_window_set_title(GTK_WINDOW(win), "Raw gecko window");
GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(win), GTK_NO_WINDOW);
return win;
};
#endif
////////////////////////////////////////////////////////////////////////////////
//
void glutReshape( int widthIn, int heightIn )
{
if ( theApp )
theApp->reshape( widthIn, heightIn );
};
////////////////////////////////////////////////////////////////////////////////
//
void glutDisplay()
{
if ( theApp )
theApp->display();
};
////////////////////////////////////////////////////////////////////////////////
//
void glutIdle()
{
if ( theApp )
theApp->idle();
};
////////////////////////////////////////////////////////////////////////////////
//
void glutKeyboard( unsigned char keyIn, int xIn, int yIn )
{
if ( keyIn == 27 )
{
if ( theApp )
theApp->reset();
exit( 0 );
};
if ( theApp )
theApp->keyboard( keyIn, xIn, yIn );
};
////////////////////////////////////////////////////////////////////////////////
//
void glutMouseMove( int xIn , int yIn )
{
if ( theApp )
theApp->mouseMove( xIn, yIn );
}
int main(int argc,char** argv)
////////////////////////////////////////////////////////////////////////////////
//
void glutMouseButton( int buttonIn, int stateIn, int xIn, int yIn )
{
osg::ArgumentParser arguments(&argc, argv);
osgViewer::Viewer viewer(arguments);
typedef std::list< osg::ref_ptr<osg::Image> > Images;
Images images;
for(int i=1; i<arguments.argc(); ++i)
{
if (!arguments.isOption(i))
{
osg::ref_ptr<HttpImage> httpImage= new HttpImage;
if (httpImage->open(arguments[i]))
{
images.push_back(httpImage.get());
}
}
}
bool xyPlane = false;
osg::Group* group = new osg::Group;
osg::Vec3 origin = osg::Vec3(0.0f,0.0f,0.0f);
for(Images::iterator itr = images.begin();
itr != images.end();
++itr)
{
osg::Image* image = itr->get();
float width = 1.0;
float height = float(image->t())/float(image->s());
osg::Vec3 widthAxis = osg::Vec3(width,0.0f,0.0f);
osg::Vec3 heightAxis = xyPlane ? osg::Vec3(0.0f,height,0.0f) : osg::Vec3(0.0f,0.0f,height);
group->addChild(createInteractiveQuad(origin, widthAxis, heightAxis, image));
origin += widthAxis*1.1f;
}
viewer.setSceneData(group);
viewer.addEventHandler(new osgViewer::StatsHandler);
//viewer.addEventHandler(new PageHandler);
return viewer.run();
if ( theApp )
theApp->mouseButton( buttonIn, stateIn, xIn, yIn );
}
static void on_destroy(GtkWidget * widget, gpointer data) {
gtk_main_quit ();
}
////////////////////////////////////////////////////////////////////////////////
//
int main( int argc, char* argv[] )
{
// implementation in a class so we can observer events
// means we need this painful GLUT <--> class shim...
theApp = new testGL;
if ( theApp )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB );
glutInitWindowPosition( 80, 0 );
glutInitWindowSize( theApp->getAppWindowWidth(), theApp->getAppWindowHeight() );
glutCreateWindow( theApp->getAppWindowName().c_str() );
theApp->init( argv[ 0 ] );
glutKeyboardFunc( glutKeyboard );
glutMouseFunc( glutMouseButton );
glutPassiveMotionFunc( glutMouseMove );
glutMotionFunc( glutMouseMove );
glutDisplayFunc( glutDisplay );
glutReshapeFunc( glutReshape );
glutIdleFunc( glutIdle );
glutMainLoop();
delete theApp;
};
return 0;
}