Files
SingularityViewer/indra/llqtwebkit/tests/testgl/testgl.cpp
2012-09-08 02:03:07 -04:00

1003 lines
30 KiB
C++

/* Copyright (c) 2006-2010, Linden Research, Inc.
*
* LLQtWebKit Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in GPL-license.txt in this distribution, or online at
* http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/technology-programs/license-virtual-world/viewerlicensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
*/
#ifndef _WINDOWS
extern "C" {
#include <unistd.h>
}
#endif
#ifdef _WINDOWS
#include <windows.h>
#include <commdlg.h> // file choser dialog
#include <direct.h> // for local file access
#endif
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <fstream>
#include <vector>
#ifdef LL_OSX
// I'm not sure why STATIC_QT is getting defined, but the Q_IMPORT_PLUGIN thing doesn't seem to be necessary on the mac.
#undef STATIC_QT
#endif
#ifdef STATIC_QT
#include <QtPlugin>
Q_IMPORT_PLUGIN(qgif)
#endif
#ifdef LL_OSX
#include <OpenGL/gl.h>
#include <GLUT/glut.h>
#else
#define FREEGLUT_STATIC
#include "GL/glut.h"
#endif
#include "llqtwebkit.h"
#ifdef _WINDOWS
#define PATH_SEPARATOR "\\"
#else
#define PATH_SEPARATOR "/"
#endif
////////////////////////////////////////////////////////////////////////////////
//
std::string chooseFileName()
{
#ifdef _WINDOWS
OPENFILENAMEA ofn ;
static char szFile[_MAX_PATH] ;
ZeroMemory( &ofn , sizeof( ofn) );
ofn.lStructSize = sizeof ( ofn );
ofn.hwndOwner = NULL ;
ofn.lpstrFile = szFile ;
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof( szFile );
ofn.lpstrFilter = "All\0*.*\0Images\0*.jpg;*.png\0";
ofn.nFilterIndex =1;
ofn.lpstrFileTitle = NULL ;
ofn.nMaxFileTitle = 0 ;
ofn.lpstrInitialDir=NULL ;
ofn.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST ;
GetOpenFileNameA( &ofn );
return ofn.lpstrFile;
#else
return "";
#endif
}
////////////////////////////////////////////////////////////////////////////////
// Implementation of the test app - implemented as a class and derrives from
// the observer so we can catch events emitted by LLQtWebKit
//
class testGL :
public LLEmbeddedBrowserWindowObserver
{
public:
testGL() :
mAppWindowWidth( 800 ), // dimensions of the app window - can be anything
mAppWindowHeight( 900 ),
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 ),
mBrowserWindowId( 0 ),
mAppWindowName( "testGL" ),
mCwd(),
mHomeUrl(),
mNeedsUpdate( true ) // flag to indicate if browser texture needs an update
{
#ifdef _WINDOWS // to remove warning on Windows
mCwd = _getcwd(NULL, 1024);
#else
mCwd = getcwd(NULL, 1024);
#endif
mHomeUrl = "http://callum-linden.s3.amazonaws.com/browsertest.html";
std::cout << "LLQtWebKit version: " << LLQtWebKit::getInstance()->getVersion() << std::endl;
std::cout << "Current working directory is " << mCwd << std::endl;
};
////////////////////////////////////////////////////////////////////////////////
//
void init( const std::string argv0, const std::string argv1 )
{
// 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 );
// calculate texture size required (next power of two above browser window size
for ( mAppTextureWidth = 1; mAppTextureWidth < mBrowserWindowWidth; mAppTextureWidth <<= 1 )
{
};
for ( mAppTextureHeight = 1; mAppTextureHeight < mBrowserWindowHeight; mAppTextureHeight <<= 1 )
{
};
// 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.
mProfileDir = mCwd + PATH_SEPARATOR + "testGL_profile";
std::cout << "Profiles dir location is " << mProfileDir << std::endl;
mCookiePath = mProfileDir + PATH_SEPARATOR + "cookies.txt";
std::cout << "Cookies.txt file location is " << mCookiePath << std::endl;
LLQtWebKit::getInstance()->init( mApplicationDir, mApplicationDir, mProfileDir, getNativeWindowHandle() );
LLQtWebKit::getInstance()->enableQtMessageHandler( false );
// set host language test (in reality, string will be language code passed into client)
// IMPORTANT: must be called before createBrowserWindow(...)
LLQtWebKit::getInstance()->setHostLanguage( "EN-AB-CD-EF" );
// set up features
LLQtWebKit::getInstance()->enableJavaScript( true );
LLQtWebKit::getInstance()->enableCookies( true );
LLQtWebKit::getInstance()->enablePlugins( true );
// make a browser window
mBrowserWindowId = LLQtWebKit::getInstance()->createBrowserWindow( mBrowserWindowWidth, mBrowserWindowHeight );
// tell LLQtWebKit about the size of the browser window
LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mBrowserWindowWidth, mBrowserWindowHeight );
// observer events that LLQtWebKit emits
LLQtWebKit::getInstance()->addObserver( mBrowserWindowId, this );
// append details to agent string
LLQtWebKit::getInstance()->setBrowserAgentId( mAppWindowName );
// don't flip bitmap
LLQtWebKit::getInstance()->flipWindow( mBrowserWindowId, false );
// only "trust" pages whose host match this regex
LLQtWebKit::getInstance()->setWhiteListRegex( mBrowserWindowId, "^([^.]+\\.)*amazonaws\\.com$" );
LLQtWebKit::getInstance()->enableLoadingOverlay( mBrowserWindowId, true );
// Attempt to read cookies from the cookie file and send them to llqtwebkit.
{
std::ifstream cookie_file(mCookiePath.c_str(), std::ios_base::in);
std::string cookies;
while(cookie_file.good() && !cookie_file.eof())
{
std::string tmp;
std::getline(cookie_file, tmp);
cookies += tmp;
cookies += "\n";
}
if(!cookies.empty())
{
LLQtWebKit::getInstance()->setCookies(cookies);
}
}
#if 0
const std::vector<std::string> before=LLQtWebKit::getInstance()->getInstalledCertsList();
std::cout << "Certs before CA.pem load: " << before.size() << " items" << std::endl;
for(int i=0;i<before.size();++i)
{
std::cout << " " << before[i] << std::endl;
}
std::cout << "---- end of list ----" << std::endl;
#endif
// Tell llqtwebkit to look for a CA file in the application directory.
// If it can't find or parse the file, this should have no effect.
std::string ca_pem_file_loc = mCwd + PATH_SEPARATOR + "CA.pem";
LLQtWebKit::getInstance()->setCAFile( ca_pem_file_loc.c_str() );
std::cout << "Expected CA.pem file location is " << ca_pem_file_loc << std::endl;
#if 0
const std::vector<std::string> after=LLQtWebKit::getInstance()->getInstalledCertsList();
std::cout << "Certs after CA.pem load: " << after.size() << " items" << std::endl;
for(int i=0;i<after.size();++i)
{
std::cout << " " << after[i] << std::endl;
}
std::cout << "---- end of list ----" << std::endl;
#endif
// test Second Life viewer specific functions
LLQtWebKit::getInstance()->setSLObjectEnabled( true ); // true means the feature is turned on
LLQtWebKit::getInstance()->setAgentLanguage( "tst-en" ); // viewer language selected by agent
LLQtWebKit::getInstance()->setAgentRegion( "TestGL region" ); // name of region where agent is located
LLQtWebKit::getInstance()->setAgentLocation( 9.8, 7.6, 5.4 ); // agent's x,y,z location within a region
LLQtWebKit::getInstance()->setAgentGlobalLocation( 1234.5, 6789.0, 3456.7 ); // agent's x,y,z location within a region
LLQtWebKit::getInstance()->setAgentOrientation( 175.69 ); // direction (0..359) agent is facing
LLQtWebKit::getInstance()->setAgentMaturity( "Very immature" ); // selected maturity level of agent
// go to the "home page" or URL passed in via command line
if ( ! argv1.empty() )
LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, argv1 );
else
LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, mHomeUrl );
};
////////////////////////////////////////////////////////////////////////////////
//
void reset( void )
{
// Get cookies from this instance
std::string cookies = LLQtWebKit::getInstance()->getAllCookies();
// Dump cookies to stdout
// std::cout << "Cookies:" << std::endl;
// std::cout << cookies;
// and save them to cookies.txt in the profile directory
{
std::ofstream cookie_file(mCookiePath.c_str(), std::ios_base::out|std::ios_base::trunc);
if(cookie_file.good())
{
cookie_file << cookies;
}
cookie_file.close();
}
// unhook observer
LLQtWebKit::getInstance()->remObserver( mBrowserWindowId, this );
// clean up
LLQtWebKit::getInstance()->reset();
};
////////////////////////////////////////////////////////////////////////////////
//
void reshape( int widthIn, int heightIn )
{
if ( heightIn == 0 )
heightIn = 1;
LLQtWebKit::getInstance()->setSize(mBrowserWindowId, widthIn, heightIn );
mNeedsUpdate = true;
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;
mBrowserWindowWidth = widthIn;
mBrowserWindowHeight = heightIn;
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
mNeedsUpdate = true;
idle();
glutPostRedisplay();
};
void updateSLvariables()
{
if ( rand() % 2 )
LLQtWebKit::getInstance()->setAgentRegion( "Region Wibble" );
else
LLQtWebKit::getInstance()->setAgentRegion( "Region Flasm" );
LLQtWebKit::getInstance()->setAgentLocation( (rand()%25600)/100.0f, (rand()%25600)/100.0f, (rand()%25600)/100.0f );
LLQtWebKit::getInstance()->setAgentGlobalLocation( (rand()%25600)/10.0f, (rand()%25600)/10.0f, (rand()%25600)/10.0f );
LLQtWebKit::getInstance()->setAgentOrientation( (rand()%3600)/10.0f );
LLQtWebKit::getInstance()->emitLocation();
if ( rand() % 2 )
LLQtWebKit::getInstance()->setAgentLanguage( "One language" );
else
LLQtWebKit::getInstance()->setAgentLanguage( "Another language" );
LLQtWebKit::getInstance()->emitLanguage();
if ( rand() % 2 )
LLQtWebKit::getInstance()->setAgentMaturity( "Adults only" );
else
LLQtWebKit::getInstance()->setAgentMaturity( "Children only" );
LLQtWebKit::getInstance()->emitMaturity();
}
////////////////////////////////////////////////////////////////////////////////
//
void idle()
{
static time_t starttime = time( NULL );
if ( time( NULL ) - starttime )
{
updateSLvariables();
time( &starttime );
};
LLQtWebKit::getInstance()->pump(100);
// 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()
LLQtWebKit::getInstance()->grabBrowserWindow( mBrowserWindowId );
// lots of updates for smooth motion
glutPostRedisplay();
};
////////////////////////////////////////////////////////////////////////////////
//
void display()
{
// 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
const unsigned char* pixels = LLQtWebKit::getInstance()->getBrowserWindowPixels( mBrowserWindowId );
if ( pixels )
{
// write them into the texture
glTexSubImage2D( GL_TEXTURE_2D, 0,
0, 0,
// because sometimes the rowspan != width * bytes per pixel (mBrowserWindowWidth)
LLQtWebKit::getInstance()->getBrowserRowSpan( mBrowserWindowId ) / LLQtWebKit::getInstance()->getBrowserDepth( mBrowserWindowId ),
mBrowserWindowHeight,
#ifdef _WINDOWS
LLQtWebKit::getInstance()->getBrowserDepth(mBrowserWindowId ) == 3 ? GL_RGBA : GL_RGBA,
#elif defined(__APPLE__)
GL_RGBA,
#elif defined(LL_LINUX)
GL_RGBA,
#endif
GL_UNSIGNED_BYTE,
pixels );
};
// 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 );
glTexCoord2f( 0.0f, 0.0f );
glVertex2d( 0, 0 );
glTexCoord2f( 0.0f, 1.0f );
glVertex2d( 0, mAppWindowHeight );
glTexCoord2f( 1.0f, 1.0f );
glVertex2d( mAppWindowWidth, mAppWindowHeight );
glEnd();
glMatrixMode( GL_TEXTURE );
glPopMatrix();
glutSwapBuffers();
};
////////////////////////////////////////////////////////////////////////////////
// convert a GLUT keyboard modifier to an LLQtWebKit one
// (only valid in mouse and keyboard callbacks
LLQtWebKit::EKeyboardModifier getLLQtWebKitKeyboardModifierCode()
{
int result = LLQtWebKit::KM_MODIFIER_NONE;
int modifiers = glutGetModifiers();
if ( GLUT_ACTIVE_SHIFT & modifiers )
{
result |= LLQtWebKit::KM_MODIFIER_SHIFT;
}
if ( GLUT_ACTIVE_CTRL & modifiers )
result |= LLQtWebKit::KM_MODIFIER_CONTROL;
if ( GLUT_ACTIVE_ALT & modifiers )
result |= LLQtWebKit::KM_MODIFIER_ALT;
return (LLQtWebKit::EKeyboardModifier)result;
};
////////////////////////////////////////////////////////////////////////////////
//
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 LLQtWebKit
LLQtWebKit::getInstance()->mouseEvent( mBrowserWindowId,
LLQtWebKit::ME_MOUSE_DOWN,
LLQtWebKit::MB_MOUSE_BUTTON_LEFT,
xIn, yIn,
getLLQtWebKitKeyboardModifierCode() );
}
else
if ( state == GLUT_UP )
{
// send event to LLQtWebKit
LLQtWebKit::getInstance()->mouseEvent( mBrowserWindowId,
LLQtWebKit::ME_MOUSE_UP,
LLQtWebKit::MB_MOUSE_BUTTON_LEFT,
xIn, yIn,
getLLQtWebKitKeyboardModifierCode() );
// this seems better than sending focus on mouse down (still need to improve this)
LLQtWebKit::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 LLQtWebKit
LLQtWebKit::getInstance()->mouseEvent( mBrowserWindowId,
LLQtWebKit::ME_MOUSE_MOVE,
LLQtWebKit::MB_MOUSE_BUTTON_LEFT,
xIn, yIn,
LLQtWebKit::KM_MODIFIER_NONE );
// force a GLUT update
glutPostRedisplay();
};
////////////////////////////////////////////////////////////////////////////////
//
void keyboard( unsigned char keyIn, bool isDown)
{
// ESC key exits
if ( keyIn == 27 )
{
reset();
exit( 0 );
};
// Translate some keys
switch(keyIn)
{
case 127:
// Turn delete char into backspace
keyIn = LLQtWebKit::KEY_BACKSPACE;
break;
case '\r':
case '\n':
// Turn CR and NL into enter key
keyIn = LLQtWebKit::KEY_RETURN;
break;
case '\t':
keyIn = LLQtWebKit::KEY_TAB;
break;
default:
break;
}
// control-H goes home
if ( keyIn == 8 )
{
LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, mHomeUrl );
}
// control-B navigates back
else if ( keyIn == 2 )
{
LLQtWebKit::getInstance()->userAction(mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_BACK);
}
// control-F navigates forward
else if ( keyIn == 6 )
{
LLQtWebKit::getInstance()->userAction(mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_FORWARD);
}
// control-R reloads
else if ( keyIn == 18 )
{
LLQtWebKit::getInstance()->userAction(mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_RELOAD );
}
// control-I toggles inspector
else if ( keyIn == 23 )
{
LLQtWebKit::getInstance()->showWebInspector( true );
}
else if ( keyIn == '1' )
{
if ( getLLQtWebKitKeyboardModifierCode() == LLQtWebKit::KM_MODIFIER_CONTROL )
{
LLQtWebKit::getInstance()->setPageZoomFactor( 1.0 );
}
}
else if ( keyIn == '2' )
{
if ( getLLQtWebKitKeyboardModifierCode() == LLQtWebKit::KM_MODIFIER_CONTROL )
{
LLQtWebKit::getInstance()->setPageZoomFactor( 2.0 );
}
}
char text[2];
if(keyIn < 0x80)
{
text[0] = (char)keyIn;
}
else
{
text[0] = 0;
}
text[1] = 0;
std::cerr << "key " << (isDown?"down ":"up ") << (int)keyIn << ", modifiers = " << (int)getLLQtWebKitKeyboardModifierCode() << std::endl;
// send event to LLQtWebKit
LLQtWebKit::getInstance()->keyboardEvent(mBrowserWindowId, isDown?LLQtWebKit::KE_KEY_DOWN:LLQtWebKit::KE_KEY_UP, keyIn, text, getLLQtWebKitKeyboardModifierCode() );
};
////////////////////////////////////////////////////////////////////////////////
//
void keyboardSpecial( int specialIn, bool isDown)
{
uint32_t key = LLQtWebKit::KEY_NONE;
switch(specialIn)
{
case GLUT_KEY_F1: key = LLQtWebKit::KEY_F1; break;
case GLUT_KEY_F2: key = LLQtWebKit::KEY_F2; break;
case GLUT_KEY_F3: key = LLQtWebKit::KEY_F3; break;
case GLUT_KEY_F4: key = LLQtWebKit::KEY_F4; break;
case GLUT_KEY_F5: key = LLQtWebKit::KEY_F5; break;
case GLUT_KEY_F6: key = LLQtWebKit::KEY_F6; break;
case GLUT_KEY_F7: key = LLQtWebKit::KEY_F7; break;
case GLUT_KEY_F8: key = LLQtWebKit::KEY_F8; break;
case GLUT_KEY_F9: key = LLQtWebKit::KEY_F9; break;
case GLUT_KEY_F10: key = LLQtWebKit::KEY_F10; break;
case GLUT_KEY_F11: key = LLQtWebKit::KEY_F11; break;
case GLUT_KEY_F12: key = LLQtWebKit::KEY_F12; break;
case GLUT_KEY_LEFT: key = LLQtWebKit::KEY_LEFT; break;
case GLUT_KEY_UP: key = LLQtWebKit::KEY_UP; break;
case GLUT_KEY_RIGHT: key = LLQtWebKit::KEY_RIGHT; break;
case GLUT_KEY_DOWN: key = LLQtWebKit::KEY_DOWN; break;
case GLUT_KEY_PAGE_UP: key = LLQtWebKit::KEY_PAGE_UP; break;
case GLUT_KEY_PAGE_DOWN: key = LLQtWebKit::KEY_PAGE_DOWN;break;
case GLUT_KEY_HOME: key = LLQtWebKit::KEY_HOME; break;
case GLUT_KEY_END: key = LLQtWebKit::KEY_END; break;
case GLUT_KEY_INSERT: key = LLQtWebKit::KEY_INSERT; break;
default:
break;
}
if(key != LLQtWebKit::KEY_NONE)
{
keyboard(key, isDown);
}
};
////////////////////////////////////////////////////////////////////////////////
// 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() << 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 onTitleChange( const EventType& eventIn )
{
std::cout << "Event: title changed to " << eventIn.getStringValue() << std::endl;
glutSetWindowTitle( eventIn.getStringValue().c_str() );
};
////////////////////////////////////////////////////////////////////////////////
// virtual
void onLocationChange( const EventType& eventIn )
{
std::cout << "Event: location changed to " << eventIn.getStringValue() << std::endl;
};
////////////////////////////////////////////////////////////////////////////////
// virtual
void onClickLinkHref( const EventType& eventIn )
{
std::string uuid = eventIn.getStringValue2();
std::cout << "Event: clicked on link:" << std::endl;
std::cout << " URL:" << eventIn.getEventUri() << std::endl;
std::cout << " target:" << eventIn.getStringValue() << std::endl;
std::cout << " UUID:" << uuid << std::endl;
std::cout << std::endl;
// Since we never actually open the window, send a "proxy window closed" back to webkit to keep it from leaking.
LLQtWebKit::getInstance()->proxyWindowClosed(mBrowserWindowId, uuid);
};
// virtual
void onClickLinkNoFollow(const EventType& eventIn)
{
std::cout << "Clink link no-follow --" << std::endl;
std::cout << " URL:" << eventIn.getEventUri() << std::endl;
std::cout << " type:" << eventIn.getNavigationType() << std::endl;
std::cout << " trusted:" << eventIn.getTrustedHost() << std::endl;
}
////////////////////////////////////////////////////////////////////////////////
// virtual
void onCookieChanged( const EventType& eventIn )
{
int dead = eventIn.getIntValue();
std::cout << (dead?"deleting cookie: ":"setting cookie: ") << eventIn.getStringValue() << std::endl;
}
////////////////////////////////////////////////////////////////////////////////
// virtual
std::string onRequestFilePicker( const EventType& )
{
std::string fn = chooseFileName();
return fn;
}
////////////////////////////////////////////////////////////////////////////////
// virtual
bool onAuthRequest(const std::string &in_url, const std::string &in_realm, std::string &out_username, std::string &out_password)
{
std::cout << "Auth request, url = " << in_url << ", realm = " << in_realm << std::endl;
out_username = ""; // replace these temporarily with site username/password as required.
out_password = "";
return false;
}
////////////////////////////////////////////////////////////////////////////////
// virtual
bool onCertError(const std::string &in_url, const std::string &in_msg)
{
std::cout << "Cert error, url = " << in_url << ", message = " << in_msg << std::endl;
return false; // cancel (return true to ignore errors and continue)
}
virtual void onQtDebugMessage( const std::string& msg, const std::string& msg_type)
{
std::cout << "QtDebugMsg [" << msg_type << "]> " << msg << std::endl;
}
////////////////////////////////////////////////////////////////////////////////
// virtual
void onLinkHovered( const EventType& eventIn )
{
std::cout
<< "Link hovered, link = " << eventIn.getEventUri()
<< ", title = " << eventIn.getStringValue()
<< ", text = " << eventIn.getStringValue2()
<< std::endl;
};
////////////////////////////////////////////////////////////////////////////////
// virtual
void onWindowCloseRequested( const EventType& )
{
std::cout << "Event: window close requested" << std::endl;
};
////////////////////////////////////////////////////////////////////////////////
// virtual
void onNavigateErrorPage( const EventType& event )
{
std::cout << "Error page hit with code of " << event.getIntValue() << " - navigating to another URL" << std::endl;
LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "http://bestbuy.com" );
};
////////////////////////////////////////////////////////////////////////////////
// virtual
void onWindowGeometryChangeRequested( const EventType& eventIn)
{
int x, y, width, height;
eventIn.getRectValue(x, y, width, height);
std::cout << "Event: window geometry change requested" << std::endl;
std::cout << " uuid: " << eventIn.getStringValue() << std::endl;
std::cout << " location: (" << x << ", " << y << ")" << std::endl;
std::cout << " size: (" << width << ", " << height << ")" << std::endl;
};
////////////////////////////////////////////////////////////////////////////////
//
int getAppWindowWidth()
{
return mAppWindowWidth;
};
////////////////////////////////////////////////////////////////////////////////
//
int getAppWindowHeight()
{
return mAppWindowHeight;
};
////////////////////////////////////////////////////////////////////////////////
//
std::string getAppWindowName()
{
return mAppWindowName;
};
////////////////////////////////////////////////////////////////////////////////
//
void* getNativeWindowHandle()
{
// My implementation of the embedded browser needs a native window handle
// Can't get this via GLUT so had to use this hack
#ifdef _WINDOWS
return FindWindow( NULL, (LPCWSTR)mAppWindowName.c_str() );
#else
#ifdef LL_OSX
// not needed on osx
return 0;
#else
//#error "You will need an implementation of this method"
return 0;
#endif
#endif
};
private:
int mAppWindowWidth;
int mAppWindowHeight;
int mBrowserWindowWidth;
int mBrowserWindowHeight;
int mAppTextureWidth;
int mAppTextureHeight;
GLuint mAppTexture;
int mBrowserWindowId;
std::string mAppWindowName;
std::string mHomeUrl;
std::string mCwd;
bool mNeedsUpdate;
std::string mApplicationDir;
std::string mProfileDir;
std::string mCookiePath;
};
testGL* theApp;
////////////////////////////////////////////////////////////////////////////////
//
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 ( theApp )
{
theApp->keyboard( keyIn, true );
}
};
////////////////////////////////////////////////////////////////////////////////
//
void glutKeyboardUp( unsigned char keyIn, int /*xIn*/, int /*yIn*/ )
{
if ( theApp )
{
theApp->keyboard( keyIn, false );
}
};
////////////////////////////////////////////////////////////////////////////////
//
void glutSpecial( int specialIn, int /*xIn*/, int /*yIn*/ )
{
if ( theApp )
{
theApp->keyboardSpecial( specialIn, true );
}
};
////////////////////////////////////////////////////////////////////////////////
//
void glutSpecialUp( int specialIn, int /*xIn*/, int /*yIn*/ )
{
if ( theApp )
{
theApp->keyboardSpecial( specialIn, false );
}
};
////////////////////////////////////////////////////////////////////////////////
//
void glutMouseMove( int xIn , int yIn )
{
if ( theApp )
theApp->mouseMove( xIn, yIn );
}
////////////////////////////////////////////////////////////////////////////////
//
void glutMouseButton( int buttonIn, int stateIn, int xIn, int yIn )
{
if ( theApp )
theApp->mouseButton( buttonIn, stateIn, xIn, yIn );
}
////////////////////////////////////////////////////////////////////////////////
//
int main( int argc, char* argv[] )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB );
// implementation in a class so we can observer events
// means we need this painful GLUT <--> class shim...
theApp = new testGL;
if ( theApp )
{
glutInitWindowPosition( 80, 0 );
glutInitWindowSize( theApp->getAppWindowWidth(), theApp->getAppWindowHeight() );
glutCreateWindow( theApp->getAppWindowName().c_str() );
std::string url = "";
if ( 2 == argc )
url = std::string( argv[ 1 ] );
theApp->init( std::string( argv[ 0 ] ), url );
glutKeyboardFunc( glutKeyboard );
glutKeyboardUpFunc( glutKeyboardUp );
glutSpecialFunc( glutSpecial );
glutSpecialUpFunc( glutSpecialUp );
glutMouseFunc( glutMouseButton );
glutPassiveMotionFunc( glutMouseMove );
glutMotionFunc( glutMouseMove );
glutDisplayFunc( glutDisplay );
glutReshapeFunc( glutReshape );
glutIdleFunc( glutIdle );
glutMainLoop();
std::cout << "glutMainLoop returned" << std::endl;
delete theApp;
};
return 0;
}