llwebbrowserctrl.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 
00035 #include "llwebbrowserctrl.h"
00036 
00037 // viewer includes
00038 #include "llfloaterhtml.h"
00039 #include "llfloaterworldmap.h"
00040 #include "lluictrlfactory.h"
00041 #include "llurldispatcher.h"
00042 #include "llurlsimstring.h"
00043 #include "llviewborder.h"
00044 #include "llviewercontrol.h"
00045 #include "llviewerwindow.h"
00046 #include "llweb.h"
00047 #include "llglimmediate.h"
00048 
00049 // linden library includes
00050 #include "llfocusmgr.h"
00051 
00052 // Setting the mozilla buffer width to 2048 exactly doesn't work, since it pads its rowbytes a bit, pushing the texture width over 2048.
00053 // 2000 should give enough headroom for any amount of padding it cares to add.
00054 const S32 MAX_DIMENSION = 2000;
00055 const S32 MAX_TEXTURE_DIMENSION = 2048;
00056 
00057 static LLRegisterWidget<LLWebBrowserCtrl> r("web_browser");
00058 
00059 LLWebBrowserCtrl::LLWebBrowserCtrl( const std::string& name, const LLRect& rect ) :
00060         LLUICtrl( name, rect, FALSE, NULL, NULL ),
00061         mTextureDepthBytes( 4 ),
00062         mWebBrowserImage( 0 ),
00063         mEmbeddedBrowserWindowId( 0 ),
00064         mBorder(NULL),
00065         mFrequentUpdates( true ),
00066         mForceUpdate( false ),
00067         mOpenLinksInExternalBrowser( false ),
00068         mOpenLinksInInternalBrowser( false ),
00069         mOpenAppSLURLs( false ),
00070         mHomePageUrl( "" ),
00071         mIgnoreUIScale( true ),
00072         mAlwaysRefresh( false ),
00073         mExternalUrl( "" ),
00074         mMediaSource( 0 ),
00075         mTakeFocusOnClick( true )
00076 {
00077         S32 screen_width = mIgnoreUIScale ? 
00078                 llround((F32)getRect().getWidth() * LLUI::sGLScaleFactor.mV[VX]) : getRect().getWidth();
00079         S32 screen_height = mIgnoreUIScale ? 
00080                 llround((F32)getRect().getHeight() * LLUI::sGLScaleFactor.mV[VY]) : getRect().getHeight();
00081 
00082 
00083         LLMediaManager *mgr = LLMediaManager::getInstance();
00084 
00085         if (!mgr)
00086         {
00087                 llwarns << "cannot get media manager" << llendl;
00088                 return;
00089         }
00090                 
00091         mMediaSource = mgr->createSourceFromMimeType("http", "text/html" );
00092         if ( !mMediaSource )
00093         {
00094                 llwarns << "media source create failed " << llendl;
00095                 // return;
00096         }
00097         else
00098         {
00099 
00100                 // mMediaSource->init();
00101                 mMediaSource->addCommand( LLMediaBase::COMMAND_START );
00102 
00103                 // observe the browser so we can trap HREF events)
00104                 mMediaSource->addObserver(this);
00105 
00106                 // create a new texture (based on LLDynamic texture) that will be used to display the output
00107                 mWebBrowserImage = new LLWebBrowserTexture( screen_width, screen_height, this, mMediaSource );
00108         }
00109 
00110         LLRect border_rect( 0, getRect().getHeight() + 2, getRect().getWidth() + 2, 0 );
00111         mBorder = new LLViewBorder( "web control border", border_rect, LLViewBorder::BEVEL_IN );
00112         addChild( mBorder );
00113 }
00114 
00116 // note: this is now a singleton and destruction happens via initClass() now
00117 LLWebBrowserCtrl::~LLWebBrowserCtrl()
00118 {
00119         LLMediaManager *mgr = LLMediaManager::getInstance();
00120 
00121         if (!mgr)
00122         {
00123                 llwarns << "cannot get media manager" << llendl;
00124                 return;
00125         }
00126 
00127         if (mMediaSource)
00128         {
00129                 mgr->destroySource(mMediaSource);
00130                 mMediaSource = NULL;
00131         }
00132 
00133         if ( mWebBrowserImage )
00134         {
00135                 delete mWebBrowserImage;
00136                 mWebBrowserImage = 0;
00137         };
00138 }
00139 
00141 //
00142 bool LLWebBrowserCtrl::addObserver( LLWebBrowserCtrlObserver* subjectIn )
00143 {
00144         return mEventEmitter.addObserver( subjectIn );
00145 }
00146 
00148 //
00149 bool LLWebBrowserCtrl::remObserver( LLWebBrowserCtrlObserver* subjectIn )
00150 {
00151         return mEventEmitter.remObserver( subjectIn );
00152 }
00153 
00155 //
00156 void LLWebBrowserCtrl::setBorderVisible( BOOL border_visible )
00157 {
00158         if ( mBorder )
00159         {
00160                 mBorder->setVisible( border_visible );
00161         };
00162 };
00163 
00165 //
00166 void LLWebBrowserCtrl::setTakeFocusOnClick( bool take_focus )
00167 {
00168         mTakeFocusOnClick = take_focus;
00169 }
00170 
00172 // set flag that forces the embedded browser to open links in the external system browser
00173 void LLWebBrowserCtrl::setOpenInExternalBrowser( bool valIn )
00174 {
00175         mOpenLinksInExternalBrowser = valIn;
00176 };
00177 
00179 // set flag that forces the embedded browser to open links in the internal browser floater
00180 void LLWebBrowserCtrl::setOpenInInternalBrowser( bool valIn )
00181 {
00182         mOpenLinksInInternalBrowser = valIn;
00183 };
00184 
00186 void LLWebBrowserCtrl::setOpenAppSLURLs( bool valIn )
00187 {
00188         mOpenAppSLURLs = valIn;
00189 };
00190 
00192 //
00193 BOOL LLWebBrowserCtrl::handleHover( S32 x, S32 y, MASK mask )
00194 {
00195         convertInputCoords(x, y);
00196 
00197         if (mMediaSource)
00198                 mMediaSource->mouseMove(x, y);
00199 
00200         return TRUE;
00201 }
00202 
00204 //
00205 BOOL LLWebBrowserCtrl::handleScrollWheel( S32 x, S32 y, S32 clicks )
00206 {
00207         if (mMediaSource)
00208                 mMediaSource->scrollByLines(clicks);
00209 
00210         return TRUE;
00211 }
00212 
00214 //
00215 BOOL LLWebBrowserCtrl::handleMouseUp( S32 x, S32 y, MASK mask )
00216 {
00217         convertInputCoords(x, y);
00218 
00219         if (mMediaSource)
00220         {
00221                 mMediaSource->mouseUp(x, y);
00222 
00223                 // *HACK: LLMediaImplLLMozLib automatically takes focus on mouseup,
00224                 // in addition to the onFocusReceived() call below.  Undo this. JC
00225                 if (!mTakeFocusOnClick)
00226                 {
00227                         mMediaSource->focus(false);
00228                         gViewerWindow->focusClient();
00229                 }
00230         }
00231         
00232         gViewerWindow->setMouseCapture( NULL );
00233 
00234         return TRUE;
00235 }
00236 
00238 //
00239 BOOL LLWebBrowserCtrl::handleMouseDown( S32 x, S32 y, MASK mask )
00240 {
00241         convertInputCoords(x, y);
00242 
00243         if (mMediaSource)
00244                 mMediaSource->mouseDown(x, y);
00245         
00246         gViewerWindow->setMouseCapture( this );
00247 
00248         if (mTakeFocusOnClick)
00249         {
00250                 setFocus( TRUE );
00251         }
00252 
00253         return TRUE;
00254 }
00255 
00257 //
00258 BOOL LLWebBrowserCtrl::handleDoubleClick( S32 x, S32 y, MASK mask )
00259 {
00260         convertInputCoords(x, y);
00261 
00262         if (mMediaSource)
00263                 mMediaSource->mouseLeftDoubleClick( x, y );
00264 
00265         gViewerWindow->setMouseCapture( this );
00266 
00267         if (mTakeFocusOnClick)
00268         {
00269                 setFocus( TRUE );
00270         }
00271 
00272         return TRUE;
00273 }
00274 
00276 //
00277 void LLWebBrowserCtrl::onFocusReceived()
00278 {
00279         if (mMediaSource)
00280                 mMediaSource->focus(true);
00281         
00282 
00283         LLUICtrl::onFocusReceived();
00284 }
00285 
00287 //
00288 void LLWebBrowserCtrl::onFocusLost()
00289 {
00290         if (mMediaSource)
00291                 mMediaSource->focus(false);
00292 
00293         gViewerWindow->focusClient();
00294 
00295         LLUICtrl::onFocusLost();
00296 }
00297 
00299 //
00300 BOOL LLWebBrowserCtrl::handleKeyHere( KEY key, MASK mask )
00301 {
00302         unsigned long media_key;
00303 
00304         // First, turn SL internal keycode enum into Mozilla keycode enum
00305 
00306         // We don't have to deal with printable characters here - they should
00307         // go through handleUnicodeChar().  This table could be more complete
00308         // than it is, but I think this covers all of the important
00309         // non-printables.
00310 
00311         switch (key)
00312         {
00313         case KEY_BACKSPACE:
00314                 media_key = LL_MEDIA_KEY_BACKSPACE; break;
00315         case KEY_TAB:
00316                 media_key = LL_MEDIA_KEY_TAB; break;
00317         case KEY_RETURN:
00318                 media_key = LL_MEDIA_KEY_RETURN; break;
00319         case KEY_PAD_RETURN:
00320                 media_key = LL_MEDIA_KEY_PAD_RETURN; break;
00321         case KEY_ESCAPE:
00322                 media_key = LL_MEDIA_KEY_ESCAPE; break;
00323         case KEY_PAGE_UP:
00324                 media_key = LL_MEDIA_KEY_PAGE_UP; break;
00325         case KEY_PAGE_DOWN:
00326                 media_key = LL_MEDIA_KEY_PAGE_DOWN; break;
00327         case KEY_END:
00328                 media_key = LL_MEDIA_KEY_END; break;
00329         case KEY_HOME:
00330                 media_key = LL_MEDIA_KEY_HOME; break;
00331         case KEY_LEFT:
00332                 media_key = LL_MEDIA_KEY_LEFT; break;
00333         case KEY_UP:
00334                 media_key = LL_MEDIA_KEY_UP; break;
00335         case KEY_RIGHT:
00336                 media_key = LL_MEDIA_KEY_RIGHT; break;
00337         case KEY_DOWN:
00338                 media_key = LL_MEDIA_KEY_DOWN; break;
00339         case KEY_INSERT:
00340                 media_key = LL_MEDIA_KEY_INSERT; break;
00341         case KEY_DELETE:
00342                 media_key = LL_MEDIA_KEY_DELETE; break;
00343         default:
00344                 llinfos << "Don't know how to map LL keycode " << U32(key)
00345                         << " to DOM key.  Ignoring." << llendl;
00346                 return FALSE; // don't know how to map this key.
00347         }
00348 
00349         if (mMediaSource)
00350                 mMediaSource->keyPress(media_key);
00351         
00352         return TRUE;
00353 }
00354 
00355 BOOL LLWebBrowserCtrl::handleUnicodeCharHere(llwchar uni_char)
00356 {
00357         // only accept 'printable' characters, sigh...
00358         if (uni_char >= 32 // discard 'control' characters
00359             && uni_char != 127) // SDL thinks this is 'delete' - yuck.
00360         {
00361                 if (mMediaSource)
00362                         mMediaSource->unicodeInput(uni_char);
00363         }
00364 
00365         return TRUE;
00366 }
00367 
00369 //
00370 void LLWebBrowserCtrl::onVisibilityChange ( BOOL new_visibility )
00371 {
00372         // set state of frequent updates automatically if visibility changes
00373         if ( new_visibility )
00374         {
00375                 mFrequentUpdates = true;
00376         }
00377         else
00378         {
00379                 mFrequentUpdates = false;
00380         }
00381         LLUICtrl::onVisibilityChange(new_visibility);
00382 }
00383 
00385 //
00386 void LLWebBrowserCtrl::reshape( S32 width, S32 height, BOOL called_from_parent )
00387 {
00388         S32 screen_width = mIgnoreUIScale ? llround((F32)width * LLUI::sGLScaleFactor.mV[VX]) : width;
00389         S32 screen_height = mIgnoreUIScale ? llround((F32)height * LLUI::sGLScaleFactor.mV[VY]) : height;
00390 
00391         // when floater is minimized, these sizes are negative
00392         if ( mWebBrowserImage && screen_height > 0 && screen_width > 0 )
00393         {
00394                 mWebBrowserImage->resize( screen_width, screen_height );
00395                 mForceUpdate = true;
00396         }
00397 
00398         LLUICtrl::reshape( width, height, called_from_parent );
00399 }
00400 
00402 //
00403 void LLWebBrowserCtrl::navigateBack()
00404 {
00405         if (mMediaSource)
00406                 mMediaSource->navigateBack();
00407 }
00408 
00410 //
00411 void LLWebBrowserCtrl::navigateForward()
00412 {
00413         if (mMediaSource)
00414                 mMediaSource->navigateForward();
00415 }
00416 
00418 //
00419 bool LLWebBrowserCtrl::canNavigateBack()
00420 {
00421         if (mMediaSource)
00422                 return mMediaSource->canNavigateBack();
00423         else
00424                 return false;
00425 }
00426 
00428 //
00429 bool LLWebBrowserCtrl::canNavigateForward()
00430 {
00431         if (mMediaSource)
00432                 return mMediaSource->canNavigateForward();
00433         else
00434                 return false;
00435 }
00436 
00438 //
00439 bool LLWebBrowserCtrl::set404RedirectUrl( std::string redirect_url )
00440 {
00441         if(mMediaSource)
00442                 return mMediaSource->set404RedirectUrl( redirect_url );
00443         else
00444                 return false;
00445 }
00446 
00448 //
00449 bool LLWebBrowserCtrl::clr404RedirectUrl()
00450 {
00451         if(mMediaSource)
00452                 return mMediaSource->clr404RedirectUrl();
00453         else
00454                 return false;
00455 }
00456 
00458 //
00459 void LLWebBrowserCtrl::navigateTo( std::string urlIn )
00460 {
00461         // don't browse to anything that starts with secondlife:// or sl://
00462         const std::string protocol1 = "secondlife://";
00463         const std::string protocol2 = "sl://";
00464         if ((LLString::compareInsensitive(urlIn.substr(0, protocol1.length()).c_str(), protocol1.c_str()) == 0) ||
00465             (LLString::compareInsensitive(urlIn.substr(0, protocol2.length()).c_str(), protocol2.c_str()) == 0))
00466         {
00467                 // TODO: Print out/log this attempt?
00468                 // llinfos << "Rejecting attempt to load restricted website :" << urlIn << llendl;
00469                 return;
00470         }
00471         
00472         if (mMediaSource)
00473                 mMediaSource->navigateTo(urlIn);
00474 }
00475 
00476 
00477 void LLWebBrowserCtrl::navigateToLocalPage( const std::string& subdir, const std::string& filename_in )
00478 {
00479         std::string language = gSavedSettings.getString("Language");
00480         
00481         if(language == "default")
00482         {
00483                 language = gSavedSettings.getString("SystemLanguage");
00484         }
00485 
00486         std::string delim = gDirUtilp->getDirDelimiter();
00487         std::string filename;
00488 
00489         filename += subdir;
00490         filename += delim;
00491         filename += filename_in;
00492 
00493         std::string expanded_filename = gDirUtilp->getExpandedFilename(LL_PATH_HTML, language, filename);
00494 
00495         if (gDirUtilp->fileExists(expanded_filename))
00496         {
00497                 navigateTo(expanded_filename);
00498                 return;
00499         }
00500         if (language != "en-us")
00501         {
00502                 expanded_filename = gDirUtilp->getExpandedFilename(LL_PATH_HTML, "en-us", filename);
00503                 if (gDirUtilp->fileExists(expanded_filename))
00504                 {
00505                         navigateTo(expanded_filename);
00506                         return;
00507                 }
00508         }
00509 
00510         llwarns << "File " << subdir << delim << filename_in << "not found" << llendl;
00511 }
00512 
00513 
00515 //
00516 void LLWebBrowserCtrl::navigateHome()
00517 {
00518         if( mHomePageUrl.length() )
00519         {
00520                 if (mMediaSource)
00521                         mMediaSource->navigateTo(mHomePageUrl);
00522         };
00523 }
00524 
00526 //
00527 void LLWebBrowserCtrl::setHomePageUrl( const std::string urlIn )
00528 {
00529         mHomePageUrl = urlIn;
00530 }
00531 
00533 //
00534 bool LLWebBrowserCtrl::setCaretColor(unsigned int red, unsigned int green, unsigned int blue)
00535 {
00536         if (mMediaSource)
00537                 return mMediaSource->setCaretColor(red, green, blue);
00538         else
00539                 return false;
00540 }
00542 //
00543 std::string LLWebBrowserCtrl::getHomePageUrl()
00544 {
00545         return  mHomePageUrl;
00546 }
00547 
00549 //
00550 void LLWebBrowserCtrl::draw()
00551 {
00552         if ( ! mWebBrowserImage )
00553                 return;
00554 
00555         // NOTE: optimization needed here - probably only need to do this once
00556         // unless tearoffs change the parent which they probably do.
00557         const LLUICtrl* ptr = findRootMostFocusRoot();
00558         if ( ptr && ptr->hasFocus() )
00559         {
00560                 setFrequentUpdates( true );
00561         }
00562         else
00563         {
00564                 setFrequentUpdates( false );
00565         };
00566 
00567         // alpha off for this
00568         LLGLSUIDefault gls_ui;
00569         LLGLDisable gls_alphaTest( GL_ALPHA_TEST );
00570 
00571         gGL.pushMatrix();
00572         {
00573                 if (mIgnoreUIScale)
00574                 {
00575                         glLoadIdentity();
00576                         // font system stores true screen origin, need to scale this by UI scale factor
00577                         // to get render origin for this view (with unit scale)
00578                         gGL.translatef(floorf(LLFontGL::sCurOrigin.mX * LLUI::sGLScaleFactor.mV[VX]), 
00579                                                 floorf(LLFontGL::sCurOrigin.mY * LLUI::sGLScaleFactor.mV[VY]), 
00580                                                 LLFontGL::sCurOrigin.mZ);
00581                 }
00582 
00583                 // scale texture to fit the space using texture coords
00584                 mWebBrowserImage->bindTexture();
00585                 gGL.color4fv( LLColor4::white.mV );
00586                 F32 max_u = ( F32 )mWebBrowserImage->getBrowserWidth() / ( F32 )mWebBrowserImage->getWidth();
00587                 F32 max_v = ( F32 )mWebBrowserImage->getBrowserHeight() / ( F32 )mWebBrowserImage->getHeight();
00588 
00589                 // draw the browser
00590                 gGL.blendFunc( GL_ONE, GL_ZERO );
00591                 gGL.begin( LLVertexBuffer::QUADS );
00592                 {
00593                         // render using web browser reported width and height, instead of trying to invert GL scale
00594                         gGL.texCoord2f( max_u, max_v );
00595                         gGL.vertex2i( mWebBrowserImage->getBrowserWidth(), mWebBrowserImage->getBrowserHeight() );
00596 
00597                         gGL.texCoord2f( 0.f, max_v );
00598                         gGL.vertex2i( 0, mWebBrowserImage->getBrowserHeight() );
00599 
00600                         gGL.texCoord2f( 0.f, 0.f );
00601                         gGL.vertex2i( 0, 0 );
00602 
00603                         gGL.texCoord2f( max_u, 0.f );
00604                         gGL.vertex2i( mWebBrowserImage->getBrowserWidth(), 0 );
00605                 }
00606                 gGL.end();
00607                 gGL.blendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA  );
00608         }
00609         gGL.popMatrix();
00610 
00611         // highlight if keyboard focus here. (TODO: this needs some work)
00612         if ( mBorder->getVisible() )
00613                 mBorder->setKeyboardFocusHighlight( gFocusMgr.childHasKeyboardFocus( this ) );
00614 
00615         
00616         LLUICtrl::draw();
00617 }
00618 
00619 void LLWebBrowserCtrl::convertInputCoords(S32& x, S32& y)
00620 {
00621         x = mIgnoreUIScale ? llround((F32)x * LLUI::sGLScaleFactor.mV[VX]) : x;
00622         y = mIgnoreUIScale ? llround((F32)(getRect().getHeight() - y) * LLUI::sGLScaleFactor.mV[VY]) : getRect().getHeight() - y;
00623 }
00624 
00626 // virtual
00627 void LLWebBrowserCtrl::onNavigateBegin( const EventType& eventIn )
00628 {
00629         LLWebBrowserCtrlEvent event( eventIn.getStringValue() );
00630         mEventEmitter.update( &LLWebBrowserCtrlObserver::onNavigateBegin, event );
00631 }
00632 
00634 // virtual
00635 void LLWebBrowserCtrl::onNavigateComplete( const EventType& eventIn )
00636 {
00637         // chain this event on to observers of an instance of LLWebBrowserCtrl
00638         LLWebBrowserCtrlEvent event( eventIn.getStringValue() );
00639         mEventEmitter.update( &LLWebBrowserCtrlObserver::onNavigateComplete, event );
00640 }
00641 
00643 // virtual
00644 void LLWebBrowserCtrl::onUpdateProgress( const EventType& eventIn )
00645 {
00646         // chain this event on to observers of an instance of LLWebBrowserCtrl
00647         LLWebBrowserCtrlEvent event( eventIn.getIntValue() );
00648         mEventEmitter.update( &LLWebBrowserCtrlObserver::onUpdateProgress, event );
00649 }
00650 
00652 // virtual
00653 void LLWebBrowserCtrl::onStatusTextChange( const EventType& eventIn )
00654 {
00655         // chain this event on to observers of an instance of LLWebBrowserCtrl
00656         LLWebBrowserCtrlEvent event( eventIn.getStringValue() );
00657         mEventEmitter.update( &LLWebBrowserCtrlObserver::onStatusTextChange, event );
00658 }
00659 
00661 // virtual
00662 void LLWebBrowserCtrl::onLocationChange( const EventType& eventIn )
00663 {
00664         const LLURI url(eventIn.getStringValue());
00665         LLSD queryMap(url.queryMap());
00666         std::string redirect_http_hack = queryMap["redirect-http-hack"].asString();
00667         if (!redirect_http_hack.empty())
00668         {
00669                 const bool from_external_browser = false;
00670                 LLURLDispatcher::dispatch(redirect_http_hack, from_external_browser);
00671                 return;
00672         }
00673         
00674         // chain this event on to observers of an instance of LLWebBrowserCtrl
00675         LLWebBrowserCtrlEvent event( eventIn.getStringValue() );
00676         mEventEmitter.update( &LLWebBrowserCtrlObserver::onLocationChange, event );
00677 }
00678 
00680 // virtual
00681 void LLWebBrowserCtrl::onMediaContentsChange( const EventType& event_in )
00682 {
00683         if ( mWebBrowserImage )
00684         {
00685                 mWebBrowserImage->setNeedsUpdate();
00686                 mForceUpdate = true;
00687         }
00688 }
00689 
00691 // static 
00692 void LLWebBrowserCtrl::onClickLinkExternalTarget( S32 option, void* userdata )
00693 {
00694         if ( 0 == option )
00695         {
00696                 // open in external browser because we don't support 
00697                 // creation of our own secondary browser windows
00698                 LLWeb::loadURLExternal( ((LLWebBrowserCtrl*)userdata)->mExternalUrl );
00699         };
00700 }
00701 
00703 // virtual
00704 void LLWebBrowserCtrl::onClickLinkHref( const EventType& eventIn )
00705 {
00706         // if there is a value for the target (passed in stringValueEx)
00707         if ( eventIn.getStringValueEx().length() )
00708         {
00709                 // if the target = "_new"
00710                 if ( eventIn.getStringValueEx() == "_external" )                {
00711                         mExternalUrl = eventIn.getStringValue();
00712                         gViewerWindow->alertXml( "WebLaunchExternalTarget", onClickLinkExternalTarget, (void*)this );
00713                         return;
00714                 };
00715         };
00716 
00717         const std::string protocol1( "http://" );
00718         const std::string protocol2( "https://" );
00719         if( mOpenLinksInExternalBrowser )
00720         {
00721                 if ( eventIn.getStringValue().length() )
00722                 {
00723                         if ( LLString::compareInsensitive( eventIn.getStringValue().substr( 0, protocol1.length() ).c_str(), protocol1.c_str() ) == 0 ||
00724                                  LLString::compareInsensitive( eventIn.getStringValue().substr( 0, protocol2.length() ).c_str(), protocol2.c_str() ) == 0 )
00725                         {
00726                                 LLWeb::loadURLExternal( eventIn.getStringValue() );
00727                         };
00728                 };
00729         }
00730         else
00731         if( mOpenLinksInInternalBrowser )
00732         {
00733                 if ( eventIn.getStringValue().length() )
00734                 {
00735                         if ( LLString::compareInsensitive( eventIn.getStringValue().substr( 0, protocol1.length() ).c_str(), protocol1.c_str() ) == 0 ||
00736                                  LLString::compareInsensitive( eventIn.getStringValue().substr( 0, protocol2.length() ).c_str(), protocol2.c_str() ) == 0 )
00737                         {
00738                                 // If we spawn a new LLFloaterHTML, assume we want it to
00739                                 // follow this LLWebBrowserCtrl's setting for whether or
00740                                 // not to open secondlife:///app/ links. JC.
00741                                 const bool open_links_externally = false;
00742                                 LLFloaterHtml::getInstance()->show( 
00743                                         eventIn.getStringValue(), 
00744                                                 "Second Life Browser",
00745                                                         open_links_externally,
00746                                                                 mOpenAppSLURLs);
00747                         };
00748                 };
00749         };
00750 
00751         // chain this event on to observers of an instance of LLWebBrowserCtrl
00752         LLWebBrowserCtrlEvent event( eventIn.getStringValue(), eventIn.getStringValueEx() );
00753         mEventEmitter.update( &LLWebBrowserCtrlObserver::onClickLinkHref, event );
00754 }
00755 
00757 // virtual
00758 void LLWebBrowserCtrl::onClickLinkNoFollow( const EventType& eventIn )
00759 {
00760         std::string url = eventIn.getStringValue();
00761         if (LLURLDispatcher::isSLURLCommand(url)
00762                 && !mOpenAppSLURLs)
00763         {
00764                 // block handling of this secondlife:///app/ URL
00765                 return;
00766         }
00767 
00768         const bool from_external_browser = false;
00769         LLURLDispatcher::dispatch(url, from_external_browser);
00770 
00771         // chain this event on to observers of an instance of LLWebBrowserCtrl
00772         LLWebBrowserCtrlEvent event( eventIn.getStringValue() );
00773         mEventEmitter.update( &LLWebBrowserCtrlObserver::onClickLinkNoFollow, event );
00774 }
00775 
00777 //
00778 LLWebBrowserTexture::LLWebBrowserTexture( S32 width, S32 height, LLWebBrowserCtrl* browserCtrl, LLMediaBase *media_source ) :
00779         LLDynamicTexture( 512, 512, 4, ORDER_FIRST, TRUE ),
00780         mLastBrowserDepth( 0 ),
00781         mNeedsUpdate( true ),
00782         mWebBrowserCtrl( browserCtrl ),
00783         mMediaSource(media_source)
00784 {
00785         mElapsedTime.start();
00786 
00787         resize( width, height );
00788 }
00789 
00791 //
00792 LLWebBrowserTexture::~LLWebBrowserTexture()
00793 {
00794         mElapsedTime.stop();
00795 }
00796 
00798 //
00799 BOOL LLWebBrowserTexture::needsRender()
00800 {
00801         if ( mWebBrowserCtrl->getFrequentUpdates() || 
00802                 mWebBrowserCtrl->getAlwaysRefresh() ||
00803                 mWebBrowserCtrl->getForceUpdate() )
00804         {
00805                 // only update mozilla/texture occasionally
00806                 if ( mElapsedTime.getElapsedTimeF32() > ( 1.0f / 15.0f ) )
00807                 {
00808                         return TRUE;
00809                 }
00810         }
00811 
00812         return FALSE;
00813 }
00814 
00816 //
00817 BOOL LLWebBrowserTexture::render()
00818 {
00819         if (!mMediaSource)
00820                 return FALSE;
00821         
00822         // frequent updates turned on?
00823         if ( mWebBrowserCtrl->getFrequentUpdates() || 
00824                 mWebBrowserCtrl->getAlwaysRefresh() ||
00825                 mWebBrowserCtrl->getForceUpdate() )
00826         {
00827 
00828                 if ( mNeedsUpdate )
00829                 {
00830 
00831                         const unsigned char* pixels = mMediaSource->getMediaData();
00832                         if ( ! pixels )
00833                                 return FALSE;
00834                         
00835                         mNeedsUpdate = false;
00836                         mWebBrowserCtrl->setForceUpdate(false);
00837 
00838                         S32 media_depth  = mMediaSource->getMediaDepth();
00839                         S32 media_width  = mMediaSource->getMediaWidth();
00840                         S32 media_height = mMediaSource->getMediaHeight();
00841                         
00842                         // these are both invalid conditions and should never happen but SL-27583 indicates it does
00843                         if ((media_width < 1) || (media_depth < 2))
00844                                 return FALSE;
00845 
00846                         // Browser depth hasn't changed.  
00847                         if(mLastBrowserDepth == media_depth)
00848                         {
00849                                 S32 width  = llmin(media_width, mBrowserWidth);
00850                                 S32 height = llmin(media_height, mBrowserHeight);
00851 
00852                                 S32 media_data_width  = mMediaSource->getMediaDataWidth();
00853                                 S32 media_data_height = mMediaSource->getMediaDataHeight();
00854 
00855                                 // Just grab the pixels.
00856                                 if ( media_data_width > 0 && media_data_height > 0 &&
00857                                                 media_data_width < MAX_DIMENSION && media_data_height < MAX_DIMENSION )
00858                                 {
00859                                         mTexture->setSubImage( pixels, 
00860                                                                                         media_data_width, media_data_height,
00861                                                                                                 0, 0, 
00862                                                                                                         width, height );
00863                                 };
00864                         }
00865                         else
00866                         {
00867                                 // Browser depth has changed -- need to recreate texture to match.
00868                                 resize(mBrowserWidth, mBrowserHeight);
00869                         };
00870                 };
00871         };
00872 
00873         return TRUE;
00874 }
00875 
00877 //
00878 S32 LLWebBrowserTexture::getBrowserWidth()
00879 {
00880         return mBrowserWidth;
00881 }
00882 
00884 //
00885 S32 LLWebBrowserTexture::getBrowserHeight()
00886 {
00887         return mBrowserHeight;
00888 }
00889 
00891 //
00892 void LLWebBrowserTexture::setNeedsUpdate()
00893 {
00894         mNeedsUpdate = true;
00895 }
00896 
00898 //
00899 void LLWebBrowserTexture::resize( S32 new_width, S32 new_height )
00900 {
00901         if (!mMediaSource)
00902                 return;
00903         
00904         F32 scale_ratio = 1.f;
00905         if (new_width > MAX_DIMENSION)
00906         {
00907                 scale_ratio = (F32)MAX_DIMENSION / (F32)new_width;
00908         }
00909         if (new_height > MAX_DIMENSION)
00910         {
00911                 scale_ratio = llmin(scale_ratio, (F32)MAX_DIMENSION / (F32)new_height);
00912         }
00913 
00914         mBrowserWidth = llround(scale_ratio * (F32)new_width);
00915         mBrowserHeight = llround(scale_ratio * (F32)new_height);
00916 
00917         mMediaSource->setRequestedMediaSize(mBrowserWidth, mBrowserHeight);
00918 
00919         // HACK - this code is executing a render - resize should call render() instead
00920         // (and render() should be refactored so it doesn't call resize())
00921         
00922         const unsigned char* pixels = mMediaSource->getMediaData();
00923 
00924         S32 media_width  = mMediaSource->getMediaWidth();
00925         S32 media_height = mMediaSource->getMediaHeight();
00926         S32 media_depth  = mMediaSource->getMediaDepth();
00927 
00928         // these are both invalid conditions and should never happen but SL-27583 indicates it does
00929         if ( media_width < 1 || media_depth < 2 )
00930                 return;
00931         
00932         releaseGLTexture();
00933 
00934         // calculate the next power of 2 bigger than reqquested size for width and height
00935         for ( mWidth = 1; mWidth < mBrowserWidth; mWidth <<= 1 )
00936         {
00937                 if ( mWidth >= MAX_TEXTURE_DIMENSION )
00938                 {
00939                         break;
00940                 };
00941         };
00942 
00943         for ( mHeight = 1; mHeight < mBrowserHeight; mHeight <<= 1 )
00944         {
00945                 if ( mHeight >= MAX_TEXTURE_DIMENSION )
00946                 {
00947                         break;
00948                 };
00949         };
00950         
00951         LLGLint internal_format;
00952         LLGLenum primary_format;
00953         LLGLenum type_format;
00954         BOOL     swap_bytes = FALSE;
00955 
00956         switch(media_depth)
00957         {
00958                 default:
00959                 case 4:
00960                         internal_format = GL_RGBA8;
00961                         primary_format = GL_BGRA_EXT;
00962                 #if LL_DARWIN
00963                         #if LL_BIG_ENDIAN
00964                                 type_format = GL_UNSIGNED_INT_8_8_8_8_REV;
00965                         #else
00966                                 type_format = GL_UNSIGNED_INT_8_8_8_8;
00967                         #endif
00968                 #else   // windows or linux
00969                         type_format = GL_UNSIGNED_BYTE;
00970                 #endif
00971                 break;
00972                 
00973                 case 2:
00974                 #if LL_DARWIN
00975                         internal_format = GL_RGBA8;
00976                         primary_format = GL_BGRA_EXT;
00977                         type_format = GL_UNSIGNED_SHORT_1_5_5_5_REV;
00978                         #if LL_LITTLE_ENDIAN
00979                                 swap_bytes = TRUE;
00980                         #endif
00981                 #else   // windows or linux
00982                         // 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.
00983                         internal_format = GL_RGB8;
00984                         primary_format = GL_RGB;
00985                         type_format = GL_UNSIGNED_SHORT_5_6_5;
00986                 #endif
00987                 break;
00988         }
00989         
00990         // will create mWidth * mHeight sized texture, using BGR ordering
00991         LLDynamicTexture::generateGLTexture(internal_format, primary_format, type_format, swap_bytes);
00992 
00993 
00994         S32 width  = llmin(media_width, mBrowserWidth);
00995         S32 height = llmin(media_height, mBrowserHeight);
00996 
00997         S32 media_data_width  = mMediaSource->getMediaDataWidth();
00998         S32 media_data_height = mMediaSource->getMediaDataHeight();
00999 
01000         if (pixels)
01001         {
01002                 mTexture->setSubImage( pixels, media_data_width, media_data_height,
01003                                                            0, 0, width, height );
01004         }
01005         
01006         mLastBrowserDepth = media_depth;
01007 }
01008 
01009 LLView* LLWebBrowserCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
01010 {
01011         LLString name("web_browser");
01012         node->getAttributeString("name", name);
01013 
01014         LLString start_url("start_url");
01015         node->getAttributeString("start_url", start_url );
01016 
01017         BOOL border_visible = true;
01018         node->getAttributeBOOL("border_visible", border_visible);
01019 
01020         LLRect rect;
01021         createRect(node, rect, parent, LLRect());
01022 
01023         LLWebBrowserCtrl* web_browser = new LLWebBrowserCtrl( name, rect );
01024 
01025         if(node->hasAttribute("caret_color"))
01026         {
01027                 LLColor4 color;
01028                 LLUICtrlFactory::getAttributeColor(node, "caret_color", color);
01029                 LLColor4U colorU = LLColor4U(color);
01030                 web_browser->setCaretColor( colorU.mV[0], colorU.mV[1], colorU.mV[2] );
01031         }
01032 
01033         BOOL ignore_ui_scale = web_browser->getIgnoreUIScale();
01034         node->getAttributeBOOL("ignore_ui_scale", ignore_ui_scale);
01035         web_browser->setIgnoreUIScale((bool)ignore_ui_scale);
01036 
01037         web_browser->initFromXML(node, parent);
01038 
01039         web_browser->setHomePageUrl( start_url );
01040 
01041         web_browser->setBorderVisible( border_visible );
01042 
01043         web_browser->navigateHome();
01044 
01045         return web_browser;
01046 }
01047 
01048 

Generated on Fri May 16 08:34:25 2008 for SecondLife by  doxygen 1.5.5