llwebbrowserctrl.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #if LL_LIBXUL_ENABLED
00035 
00036 #include "llwebbrowserctrl.h"
00037 
00038 // viewer includes
00039 #include "llfloaterworldmap.h"
00040 #include "llurldispatcher.h"
00041 #include "llviewborder.h"
00042 #include "llviewerwindow.h"
00043 #include "llfloaterhtml.h"
00044 #include "llweb.h"
00045 #include "viewer.h"
00046 
00047 // linden library includes
00048 #include "llfocusmgr.h"
00049 
00050 // Setting the mozilla buffer width to 2048 exactly doesn't work, since it pads its rowbytes a bit, pushing the texture width over 2048.
00051 // 2000 should give enough headroom for any amount of padding it cares to add.
00052 const S32 MAX_DIMENSION = 2000;
00053 const S32 MAX_TEXTURE_DIMENSION = 2048;
00054 
00055 LLWebBrowserCtrl::LLWebBrowserCtrl( const std::string& name, const LLRect& rect ) :
00056         LLUICtrl( name, rect, FALSE, NULL, NULL ),
00057         mTextureDepthBytes( 4 ),
00058         mEmbeddedBrowserWindowId( 0 ),
00059         mBorder(NULL),
00060         mFrequentUpdates( true ),
00061         mOpenLinksInExternalBrowser( false ),
00062         mOpenLinksInInternalBrowser( false ),
00063         mOpenSLURLsInMap( true ),
00064         mOpenSLURLsViaTeleport( false ),
00065         mHomePageUrl( "" ),
00066         mIgnoreUIScale( true ),
00067         mAlwaysRefresh( false )
00068 {
00069         S32 screen_width = mIgnoreUIScale ? llround((F32)mRect.getWidth() * LLUI::sGLScaleFactor.mV[VX]) : llround((F32)mRect.getWidth() * gViewerWindow->getDisplayScale().mV[VX]);
00070         S32 screen_height = mIgnoreUIScale ? llround((F32)mRect.getHeight() * LLUI::sGLScaleFactor.mV[VY]) : llround((F32)mRect.getHeight() * gViewerWindow->getDisplayScale().mV[VY]);
00071 
00072         // create a new browser window
00073         {
00074 #if LL_LINUX
00075                 // Yuck, Mozilla init plays with the locale - push/pop
00076                 // the locale to protect it, as exotic/non-C locales
00077                 // causes our code lots of general critical weirdness
00078                 // and crashness. (SL-35450)
00079                 std::string saved_locale = setlocale(LC_ALL, NULL);
00080 #endif // LL_LINUX
00081                 mEmbeddedBrowserWindowId = LLMozLib::getInstance()->createBrowserWindow( gViewerWindow->getPlatformWindow(), screen_width, screen_height );
00082 #if LL_LINUX
00083                 setlocale(LC_ALL, saved_locale.c_str() );
00084 #endif // LL_LINUX
00085         }
00086 
00087         // change color to black so transisitons aren't so noticable (this should be in XML eventually)
00088         LLMozLib::getInstance()->setBackgroundColor( mEmbeddedBrowserWindowId, 0x00, 0x00, 0x00 );
00089 
00090         // observe the browser so we can trap HREF events)
00091         LLMozLib::getInstance()->addObserver( mEmbeddedBrowserWindowId, this );
00092 
00093         // create a new texture (based on LLDynamic texture) that will be used to display the output
00094         mWebBrowserImage = new LLWebBrowserTexture( screen_width, screen_height, this, mEmbeddedBrowserWindowId );
00095 
00096         LLRect border_rect( 0, mRect.getHeight() + 2, mRect.getWidth() + 2, 0 );
00097         mBorder = new LLViewBorder( "web control border", border_rect, LLViewBorder::BEVEL_IN );
00098         addChild( mBorder );
00099 }
00100 
00102 // note: this is now a singleton and destruction happens via initClass() now
00103 LLWebBrowserCtrl::~LLWebBrowserCtrl()
00104 {
00105         LLMozLib::getInstance()->remObserver( mEmbeddedBrowserWindowId, this );
00106 
00107         LLMozLib::getInstance()->destroyBrowserWindow( mEmbeddedBrowserWindowId );
00108 
00109         if ( mWebBrowserImage )
00110         {
00111                 delete mWebBrowserImage;
00112                 mWebBrowserImage = 0;
00113         };
00114 }
00115 
00117 //
00118 bool LLWebBrowserCtrl::addObserver( LLWebBrowserCtrlObserver* subjectIn )
00119 {
00120         return mEventEmitter.addObserver( subjectIn );
00121 }
00122 
00124 //
00125 bool LLWebBrowserCtrl::remObserver( LLWebBrowserCtrlObserver* subjectIn )
00126 {
00127         return mEventEmitter.remObserver( subjectIn );
00128 }
00129 
00131 //
00132 void LLWebBrowserCtrl::setBorderVisible( BOOL border_visible )
00133 {
00134         if ( mBorder )
00135         {
00136                 mBorder->setVisible( border_visible );
00137         };
00138 };
00139 
00141 // set flag that forces the embedded browser to open links in the external system browser
00142 void LLWebBrowserCtrl::setOpenInExternalBrowser( bool valIn )
00143 {
00144         mOpenLinksInExternalBrowser = valIn;
00145 };
00146 
00148 // set flag that forces the embedded browser to open links in the internal browser floater
00149 void LLWebBrowserCtrl::setOpenInInternalBrowser( bool valIn )
00150 {
00151         mOpenLinksInInternalBrowser = valIn;
00152 };
00153 
00155 // open secondlife:// links in map automatically or not
00156 void LLWebBrowserCtrl::setOpenSLURLsInMap( bool valIn )
00157 {
00158         mOpenSLURLsInMap = valIn;
00159 };
00160 
00162 // teleport directly to secondlife:// links
00163 void LLWebBrowserCtrl::setOpenSLURLsViaTeleport( bool valIn )
00164 {
00165         mOpenSLURLsViaTeleport = valIn;
00166 };
00167 
00169 //
00170 BOOL LLWebBrowserCtrl::handleHover( S32 x, S32 y, MASK mask )
00171 {
00172         convertInputCoords(x, y);
00173         LLMozLib::getInstance()->mouseMove( mEmbeddedBrowserWindowId, x, y );
00174 
00175         return TRUE;
00176 }
00177 
00179 //
00180 BOOL LLWebBrowserCtrl::handleScrollWheel( S32 x, S32 y, S32 clicks )
00181 {
00182         LLMozLib::getInstance()->scrollByLines( mEmbeddedBrowserWindowId, clicks );
00183 
00184         // note: this isn't really necessary right now since the page is updated
00185         // on a timer but if that becomes too burdensome and the page is only updated
00186         // once after load then this will be necessary
00187         LLMozLib::getInstance()->grabBrowserWindow( mEmbeddedBrowserWindowId );
00188 
00189         return TRUE;
00190 }
00191 
00193 //
00194 BOOL LLWebBrowserCtrl::handleMouseUp( S32 x, S32 y, MASK mask )
00195 {
00196         convertInputCoords(x, y);
00197         LLMozLib::getInstance()->mouseUp( mEmbeddedBrowserWindowId, x, y );
00198 
00199         gViewerWindow->setMouseCapture( NULL );
00200 
00201         return TRUE;
00202 }
00203 
00205 //
00206 BOOL LLWebBrowserCtrl::handleMouseDown( S32 x, S32 y, MASK mask )
00207 {
00208         convertInputCoords(x, y);
00209         LLMozLib::getInstance()->mouseDown( mEmbeddedBrowserWindowId, x, y );
00210 
00211         gViewerWindow->setMouseCapture( this );
00212 
00213         setFocus( TRUE );
00214 
00215         return TRUE;
00216 }
00217 
00219 //
00220 void LLWebBrowserCtrl::onFocusReceived()
00221 {
00222         LLMozLib::getInstance()->focusBrowser( mEmbeddedBrowserWindowId, true );
00223 
00224         LLUICtrl::onFocusReceived();
00225 }
00226 
00228 //
00229 void LLWebBrowserCtrl::onFocusLost()
00230 {
00231         LLMozLib::getInstance()->focusBrowser( mEmbeddedBrowserWindowId, false );
00232 
00233         gViewerWindow->focusClient();
00234 
00235         LLUICtrl::onFocusLost();
00236 }
00237 
00239 //
00240 BOOL LLWebBrowserCtrl::handleKey( KEY key, MASK mask, BOOL called_from_parent )
00241 {
00242         unsigned long nskey;
00243 
00244         // First, turn SL internal keycode enum into Mozilla keycode enum
00245 
00246         // We don't have to deal with printable characters here - they should
00247         // go through handleUnicodeChar().  This table could be more complete
00248         // than it is, but I think this covers all of the important
00249         // non-printables.
00250         switch (key)
00251         {
00252         case KEY_BACKSPACE:
00253                 nskey = LL_DOM_VK_BACK_SPACE; break;
00254         case KEY_TAB:
00255                 nskey = LL_DOM_VK_TAB; break;
00256         case KEY_RETURN:
00257                 nskey = LL_DOM_VK_RETURN; break;
00258         case KEY_PAD_RETURN:
00259                 nskey = LL_DOM_VK_ENTER; break;
00260         case KEY_ESCAPE:
00261                 nskey = LL_DOM_VK_ESCAPE; break;
00262         case KEY_PAGE_UP:
00263                 nskey = LL_DOM_VK_PAGE_UP; break;
00264         case KEY_PAGE_DOWN:
00265                 nskey = LL_DOM_VK_PAGE_DOWN; break;
00266         case KEY_END:
00267                 nskey = LL_DOM_VK_END; break;
00268         case KEY_HOME:
00269                 nskey = LL_DOM_VK_HOME; break;
00270         case KEY_LEFT:
00271                 nskey = LL_DOM_VK_LEFT; break;
00272         case KEY_UP:
00273                 nskey = LL_DOM_VK_UP; break;
00274         case KEY_RIGHT:
00275                 nskey = LL_DOM_VK_RIGHT; break;
00276         case KEY_DOWN:
00277                 nskey = LL_DOM_VK_DOWN; break;
00278         case KEY_INSERT:
00279                 nskey = LL_DOM_VK_INSERT; break;
00280         case KEY_DELETE:
00281                 nskey = LL_DOM_VK_DELETE; break;
00282         default:
00283                 llinfos << "Don't know how to map LL keycode " << U32(key)
00284                         << " to DOM key.  Ignoring." << llendl;
00285                 return FALSE; // don't know how to map this key.
00286         }
00287 
00288         LLMozLib::getInstance()->keyPress( mEmbeddedBrowserWindowId, nskey );
00289 
00290         return TRUE;
00291 }
00292 
00293 BOOL LLWebBrowserCtrl::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
00294 {
00295         // only accept 'printable' characters, sigh...
00296         if (uni_char >= 32 // discard 'control' characters
00297             && uni_char != 127) // SDL thinks this is 'delete' - yuck.
00298         {
00299                 LLMozLib::getInstance()->unicodeInput( mEmbeddedBrowserWindowId, uni_char );
00300         }
00301 
00302         return TRUE;
00303 }
00304 
00306 //
00307 void LLWebBrowserCtrl::onVisibilityChange ( BOOL new_visibility )
00308 {
00309         // set state of frequent updates automatically if visibility changes
00310         if ( new_visibility )
00311         {
00312                 mFrequentUpdates = true;
00313         }
00314         else
00315         {
00316                 mFrequentUpdates = false;
00317         }
00318         LLUICtrl::onVisibilityChange(new_visibility);
00319 }
00320 
00322 //
00323 void LLWebBrowserCtrl::reshape( S32 width, S32 height, BOOL called_from_parent )
00324 {
00325         S32 screen_width = mIgnoreUIScale ? llround((F32)width * LLUI::sGLScaleFactor.mV[VX]) : llround((F32)width * gViewerWindow->getDisplayScale().mV[VX]);
00326         S32 screen_height = mIgnoreUIScale ? llround((F32)height * LLUI::sGLScaleFactor.mV[VY]) : llround((F32)height * gViewerWindow->getDisplayScale().mV[VY]);
00327 
00328         // when floater is minimized, these sizes are negative
00329         if ( screen_height > 0 && screen_width > 0 )
00330         {
00331                 mWebBrowserImage->resize( screen_width, screen_height );
00332         }
00333 
00334         LLUICtrl::reshape( width, height, called_from_parent );
00335 }
00336 
00338 //
00339 void LLWebBrowserCtrl::navigateBack()
00340 {
00341         LLMozLib::getInstance()->navigateBack( mEmbeddedBrowserWindowId );
00342 }
00343 
00345 //
00346 void LLWebBrowserCtrl::navigateForward()
00347 {
00348         LLMozLib::getInstance()->navigateForward( mEmbeddedBrowserWindowId );
00349 }
00350 
00352 //
00353 bool LLWebBrowserCtrl::canNavigateBack()
00354 {
00355         return LLMozLib::getInstance()->canNavigateBack( mEmbeddedBrowserWindowId );
00356 }
00357 
00359 //
00360 bool LLWebBrowserCtrl::canNavigateForward()
00361 {
00362         return LLMozLib::getInstance()->canNavigateForward( mEmbeddedBrowserWindowId );
00363 }
00364 
00366 //
00367 bool LLWebBrowserCtrl::set404RedirectUrl(  std::string redirect_url )
00368 {
00369         return LLMozLib::getInstance()->set404RedirectUrl( mEmbeddedBrowserWindowId, redirect_url );
00370 }
00371 
00373 //
00374 bool LLWebBrowserCtrl::clr404RedirectUrl()
00375 {
00376         return LLMozLib::getInstance()->clr404RedirectUrl( mEmbeddedBrowserWindowId );
00377 }
00378 
00380 //
00381 void LLWebBrowserCtrl::navigateTo( std::string urlIn )
00382 {
00383         const std::string protocol( "secondlife://" );
00384         const std::string protocol2( "sl://" );
00385 
00386         // don't browse to anything that starts with secondlife://
00387         if ( urlIn.length() >= protocol.length() )
00388         {
00389                 if ( LLString::compareInsensitive( urlIn.substr( 0, protocol.length() ).c_str(), protocol.c_str() ) != 0 )
00390                 {
00391                         LLMozLib::getInstance()->navigateTo( mEmbeddedBrowserWindowId, urlIn );
00392                 }
00393         }
00394         else if ( urlIn.length() >= protocol2.length() )
00395         {
00396                 if ( LLString::compareInsensitive( urlIn.substr( 0, protocol2.length() ).c_str(), protocol2.c_str() ) != 0 )
00397                 {
00398                         LLMozLib::getInstance()->navigateTo( mEmbeddedBrowserWindowId, urlIn );
00399                 }
00400         }
00401         else
00402         {
00403                 LLMozLib::getInstance()->navigateTo( mEmbeddedBrowserWindowId, urlIn );
00404         }
00405 }
00406 
00408 //
00409 void LLWebBrowserCtrl::navigateHome()
00410 {
00411         if( mHomePageUrl.length() )
00412         {
00413                 LLMozLib::getInstance()->navigateTo( mEmbeddedBrowserWindowId, mHomePageUrl );
00414         };
00415 }
00416 
00418 //
00419 void LLWebBrowserCtrl::setHomePageUrl( const std::string urlIn )
00420 {
00421         mHomePageUrl = urlIn;
00422 }
00423 
00425 //
00426 std::string LLWebBrowserCtrl::getHomePageUrl()
00427 {
00428         return  mHomePageUrl;
00429 }
00430 
00432 //
00433 void LLWebBrowserCtrl::draw()
00434 {
00435         if ( ! getVisible() )
00436                 return;
00437 
00438         // NOTE: optimization needed here - probably only need to do this once
00439         // unless tearoffs change the parent which they probably do.
00440         LLUICtrl* ptr = (LLUICtrl*)findRootMostFocusRoot();
00441         if ( ptr && ptr->hasFocus() )
00442         {
00443                 setFrequentUpdates( true );
00444         }
00445         else
00446         {
00447                 setFrequentUpdates( false );
00448         };
00449 
00450         // alpha off for this
00451         LLGLSUIDefault gls_ui;
00452         LLGLDisable gls_alphaTest( GL_ALPHA_TEST );
00453 
00454         glPushMatrix();
00455         {
00456                 if (mIgnoreUIScale)
00457                 {
00458                         glLoadIdentity();
00459                         // font system stores true screen origin, need to scale this by UI scale factor
00460                         // to get render origin for this view (with unit scale)
00461                         glTranslatef(floorf(LLFontGL::sCurOrigin.mX * LLUI::sGLScaleFactor.mV[VX]), 
00462                                                 floorf(LLFontGL::sCurOrigin.mY * LLUI::sGLScaleFactor.mV[VY]), 
00463                                                 LLFontGL::sCurOrigin.mZ);
00464                 }
00465 
00466                 // scale texture to fit the space using texture coords
00467                 mWebBrowserImage->bindTexture();
00468                 glColor4fv( LLColor4::white.mV );
00469                 F32 max_u = ( F32 )mWebBrowserImage->getBrowserWidth() / ( F32 )mWebBrowserImage->getWidth();
00470                 F32 max_v = ( F32 )mWebBrowserImage->getBrowserHeight() / ( F32 )mWebBrowserImage->getHeight();
00471 
00472                 // draw the browser
00473                 glBlendFunc( GL_ONE, GL_ZERO );
00474                 glBegin( GL_QUADS );
00475                 {
00476                         // render using web browser reported width and height, instead of trying to invert GL scale
00477                         glTexCoord2f( max_u, 0.f );
00478                         glVertex2i( mWebBrowserImage->getBrowserWidth(), mWebBrowserImage->getBrowserHeight() );
00479 
00480                         glTexCoord2f( 0.f, 0.f );
00481                         glVertex2i( 0, mWebBrowserImage->getBrowserHeight() );
00482 
00483                         glTexCoord2f( 0.f, max_v );
00484                         glVertex2i( 0, 0 );
00485 
00486                         glTexCoord2f( max_u, max_v );
00487                         glVertex2i( mWebBrowserImage->getBrowserWidth(), 0 );
00488                 }
00489                 glEnd();
00490                 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA  );
00491         }
00492         glPopMatrix();
00493 
00494         // highlight if keyboard focus here. (TODO: this needs some work)
00495         if ( mBorder->getVisible() )
00496                 mBorder->setKeyboardFocusHighlight( gFocusMgr.childHasKeyboardFocus( this ) );
00497 
00498 
00499         LLUICtrl::draw();
00500 }
00501 
00502 void LLWebBrowserCtrl::convertInputCoords(S32& x, S32& y)
00503 {
00504         x = mIgnoreUIScale ? llround((F32)x * LLUI::sGLScaleFactor.mV[VX]) : llround((F32)x * gViewerWindow->getDisplayScale().mV[VX]);
00505         y = mIgnoreUIScale ? llround((F32)(mRect.getHeight() - y) * LLUI::sGLScaleFactor.mV[VY]) : llround((F32)(mRect.getHeight() - y) * gViewerWindow->getDisplayScale().mV[VY]);
00506 }
00507 
00509 // virtual
00510 void LLWebBrowserCtrl::onNavigateBegin( const EventType& eventIn )
00511 {
00512         LLWebBrowserCtrlEvent event;
00513         mEventEmitter.update( &LLWebBrowserCtrlObserver::onNavigateBegin, event );
00514 }
00515 
00517 // virtual
00518 void LLWebBrowserCtrl::onNavigateComplete( const EventType& eventIn )
00519 {
00520         // chain this event on to observers of an instance of LLWebBrowserCtrl
00521         LLWebBrowserCtrlEvent event;
00522         mEventEmitter.update( &LLWebBrowserCtrlObserver::onNavigateComplete, event );
00523 }
00524 
00526 // virtual
00527 void LLWebBrowserCtrl::onUpdateProgress( const EventType& eventIn )
00528 {
00529         // chain this event on to observers of an instance of LLWebBrowserCtrl
00530         LLWebBrowserCtrlEvent event( eventIn.getIntValue() );
00531         mEventEmitter.update( &LLWebBrowserCtrlObserver::onUpdateProgress, event );
00532 }
00533 
00535 // virtual
00536 void LLWebBrowserCtrl::onStatusTextChange( const EventType& eventIn )
00537 {
00538         // chain this event on to observers of an instance of LLWebBrowserCtrl
00539         LLWebBrowserCtrlEvent event( eventIn.getStringValue() );
00540         mEventEmitter.update( &LLWebBrowserCtrlObserver::onStatusTextChange, event );
00541 }
00542 
00544 // virtual
00545 void LLWebBrowserCtrl::onLocationChange( const EventType& eventIn )
00546 {
00547         // chain this event on to observers of an instance of LLWebBrowserCtrl
00548         LLWebBrowserCtrlEvent event( eventIn.getStringValue() );
00549         mEventEmitter.update( &LLWebBrowserCtrlObserver::onLocationChange, event );
00550 }
00551 
00553 // virtual
00554 void LLWebBrowserCtrl::onClickLinkHref( const EventType& eventIn )
00555 {
00556         const std::string protocol( "http://" );
00557 
00558         if( mOpenLinksInExternalBrowser )
00559         {
00560                 if ( eventIn.getStringValue().length() )
00561                 {
00562                         if ( LLString::compareInsensitive( eventIn.getStringValue().substr( 0, protocol.length() ).c_str(), protocol.c_str() ) == 0 )
00563                         {
00564                                 LLWeb::loadURL( eventIn.getStringValue() );
00565                         };
00566                 };
00567         }
00568         else
00569         if( mOpenLinksInInternalBrowser )
00570         {
00571                 if ( eventIn.getStringValue().length() )
00572                 {
00573                         if ( LLString::compareInsensitive( eventIn.getStringValue().substr( 0, protocol.length() ).c_str(), protocol.c_str() ) == 0 )
00574                         {
00575                                 LLFloaterHtml::getInstance()->show( eventIn.getStringValue(), "Second Life Browser");
00576                         };
00577                 };
00578         };
00579 
00580         // chain this event on to observers of an instance of LLWebBrowserCtrl
00581         LLWebBrowserCtrlEvent event( eventIn.getStringValue() );
00582         mEventEmitter.update( &LLWebBrowserCtrlObserver::onClickLinkHref, event );
00583 }
00584 
00586 // virtual
00587 void LLWebBrowserCtrl::onClickLinkSecondLife( const EventType& eventIn )
00588 {
00589         std::string url = eventIn.getStringValue();
00590         LLURLDispatcher::dispatch(url);
00591 
00592         // chain this event on to observers of an instance of LLWebBrowserCtrl
00593         LLWebBrowserCtrlEvent event( eventIn.getStringValue() );
00594         mEventEmitter.update( &LLWebBrowserCtrlObserver::onClickLinkSecondLife, event );
00595 }
00596 
00598 //
00599 LLWebBrowserTexture::LLWebBrowserTexture( S32 width, S32 height, LLWebBrowserCtrl* browserCtrl, int browserWindowId ) :
00600         LLDynamicTexture( 512, 512, 4, ORDER_FIRST, TRUE ),
00601         mLastBrowserDepth( 0 ),
00602         mWebBrowserCtrl( browserCtrl ),
00603         mEmbeddedBrowserWindowId( browserWindowId )
00604 {
00605         mElapsedTime.start();
00606 
00607         resize( width, height );
00608 }
00609 
00611 //
00612 LLWebBrowserTexture::~LLWebBrowserTexture()
00613 {
00614         mElapsedTime.stop();
00615 }
00616 
00618 //
00619 BOOL LLWebBrowserTexture::render()
00620 {
00621         // frequent updates turned on?
00622         if ( mWebBrowserCtrl->getFrequentUpdates() || mWebBrowserCtrl->getAlwaysRefresh() )
00623         {
00624                 // only update mozilla/texture occasionally
00625                 if ( mElapsedTime.getElapsedTimeF32() > ( 1.0f / 15.0f ) )
00626                 {
00627                         mElapsedTime.reset();
00628 
00629                         const unsigned char* pixels = LLMozLib::getInstance()->grabBrowserWindow( mEmbeddedBrowserWindowId );
00630 
00631                         S32 actual_rowspan = LLMozLib::getInstance()->getBrowserRowSpan( mEmbeddedBrowserWindowId );
00632                         S32 browser_depth = LLMozLib::getInstance()->getBrowserDepth( mEmbeddedBrowserWindowId );
00633 
00634                         // these are both invalid conditions and should never happen but SL-27583 indicates it does
00635                         if ( actual_rowspan < 1 || browser_depth < 2 )
00636                                 return FALSE;
00637 
00638                         // width can change after it's rendered - (Mozilla bug# 24721)
00639                         S32 pagebuffer_width = actual_rowspan / browser_depth;
00640 
00641                         // Browser depth hasn't changed.  
00642                         if(mLastBrowserDepth == browser_depth)
00643                         {
00644                                 // Just grab the pixels.
00645                                 mTexture->setSubImage( pixels,
00646                                                                                 pagebuffer_width, mBrowserHeight,
00647                                                                                         0, 0, pagebuffer_width, mBrowserHeight );
00648                         }
00649                         else
00650                         {
00651                                 // Browser depth has changed -- need to recreate texture to match.
00652                                 resize(mBrowserWidth, mBrowserHeight);
00653                         };
00654                 };
00655         };
00656 
00657         return TRUE;
00658 }
00659 
00661 //
00662 S32 LLWebBrowserTexture::getBrowserWidth()
00663 {
00664         return mBrowserWidth;
00665 }
00666 
00668 //
00669 S32 LLWebBrowserTexture::getBrowserHeight()
00670 {
00671         return mBrowserHeight;
00672 }
00673 
00674 
00676 //
00677 void LLWebBrowserTexture::resize( S32 new_width, S32 new_height )
00678 {
00679         F32 scale_ratio = 1.f;
00680         if (new_width > MAX_DIMENSION)
00681         {
00682                 scale_ratio = (F32)MAX_DIMENSION / (F32)new_width;
00683         }
00684         if (new_height > MAX_DIMENSION)
00685         {
00686                 scale_ratio = llmin(scale_ratio, (F32)MAX_DIMENSION / (F32)new_height);
00687         }
00688 
00689         mBrowserWidth = llround(scale_ratio * (F32)new_width);
00690         mBrowserHeight = llround(scale_ratio * (F32)new_height);
00691 
00692         LLMozLib::getInstance()->setSize( mEmbeddedBrowserWindowId, mBrowserWidth, mBrowserHeight );
00693 
00694         const unsigned char* pixels = LLMozLib::getInstance()->grabBrowserWindow( mEmbeddedBrowserWindowId );
00695 
00696         S32 actual_rowspan = LLMozLib::getInstance()->getBrowserRowSpan( mEmbeddedBrowserWindowId );
00697         S32 browser_depth = LLMozLib::getInstance()->getBrowserDepth( mEmbeddedBrowserWindowId );
00698 
00699         // these are both invalid conditions and should never happen but SL-27583 indicates it does
00700         if ( actual_rowspan < 1 || browser_depth < 2 )
00701                 return;
00702 
00703         releaseGLTexture();
00704         
00705         S32 pagebuffer_width = actual_rowspan / browser_depth;
00706 
00707         // calculate the next power of 2 bigger than reqquested size for width and height
00708         for ( mWidth = 1; mWidth < pagebuffer_width; mWidth <<= 1 )
00709         {
00710                 if ( mWidth >= MAX_TEXTURE_DIMENSION )
00711                 {
00712                         break;
00713                 };
00714         };
00715 
00716         for ( mHeight = 1; mHeight < mBrowserHeight; mHeight <<= 1 )
00717         {
00718                 if ( mHeight >= MAX_TEXTURE_DIMENSION )
00719                 {
00720                         break;
00721                 };
00722         };
00723         
00724         LLGLint internal_format;
00725         LLGLenum primary_format;
00726         LLGLenum type_format;
00727         BOOL     swap_bytes = FALSE;
00728 
00729         switch(browser_depth)
00730         {
00731                 default:
00732                 case 4:
00733                         internal_format = GL_RGBA8;
00734                         primary_format = GL_BGRA_EXT;
00735                 #if LL_DARWIN
00736                         #if LL_BIG_ENDIAN
00737                                 type_format = GL_UNSIGNED_INT_8_8_8_8_REV;
00738                         #else
00739                                 type_format = GL_UNSIGNED_INT_8_8_8_8;
00740                         #endif
00741                 #else   // windows or linux
00742                         type_format = GL_UNSIGNED_BYTE;
00743                 #endif
00744                 break;
00745                 
00746                 case 2:
00747                 #if LL_DARWIN
00748                         internal_format = GL_RGBA8;
00749                         primary_format = GL_BGRA_EXT;
00750                         type_format = GL_UNSIGNED_SHORT_1_5_5_5_REV;
00751                         #if LL_LITTLE_ENDIAN
00752                                 swap_bytes = TRUE;
00753                         #endif
00754                 #else   // windows or linux
00755                         // MBW -- XXX -- This is just a guess on my part.  Someone needs to verify which GL texture format matches the 16-bit format used on windows.
00756                         internal_format = GL_RGB8;
00757                         primary_format = GL_RGB;
00758                         type_format = GL_UNSIGNED_SHORT_5_6_5;
00759                 #endif
00760                 break;
00761         }
00762         
00763         // will create mWidth * mHeight sized texture, using BGR ordering
00764         LLDynamicTexture::generateGLTexture(internal_format, primary_format, type_format, swap_bytes);
00765         
00766         mTexture->setSubImage( pixels,
00767                 pagebuffer_width, mBrowserHeight,
00768                         0, 0, pagebuffer_width, mBrowserHeight );
00769         
00770         mLastBrowserDepth = browser_depth;
00771 }
00772 
00773 LLView* LLWebBrowserCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
00774 {
00775         LLString name("web_browser");
00776         node->getAttributeString("name", name);
00777 
00778         LLString start_url("start_url");
00779         node->getAttributeString("start_url", start_url );
00780 
00781         BOOL border_visible = true;
00782         node->getAttributeBOOL("border_visible", border_visible);
00783 
00784         LLRect rect;
00785         createRect(node, rect, parent, LLRect());
00786 
00787         LLWebBrowserCtrl* web_browser = new LLWebBrowserCtrl( name, rect );
00788 
00789         BOOL ignore_ui_scale = web_browser->getIgnoreUIScale();
00790         node->getAttributeBOOL("ignore_ui_scale", ignore_ui_scale);
00791         web_browser->setIgnoreUIScale((bool)ignore_ui_scale);
00792 
00793         web_browser->initFromXML(node, parent);
00794 
00795         web_browser->setHomePageUrl( start_url );
00796 
00797         web_browser->setBorderVisible( border_visible );
00798 
00799         web_browser->navigateHome();
00800 
00801         return web_browser;
00802 }
00803 
00804 #endif // LL_LIBXUL_ENABLED

Generated on Thu Jul 1 06:09:45 2010 for Second Life Viewer by  doxygen 1.4.7