llmediactrl.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:28k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /**
  2.  * @file LLMediaCtrl.cpp
  3.  * @brief Web browser UI control
  4.  *
  5.  * $LicenseInfo:firstyear=2006&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2006-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llmediactrl.h"
  34. // viewer includes
  35. #include "llfloaterworldmap.h"
  36. #include "lluictrlfactory.h"
  37. #include "llurldispatcher.h"
  38. #include "llviewborder.h"
  39. #include "llviewercontrol.h"
  40. #include "llviewermedia.h"
  41. #include "llviewertexture.h"
  42. #include "llviewerwindow.h"
  43. #include "llnotificationsutil.h"
  44. #include "llweb.h"
  45. #include "llrender.h"
  46. #include "llpluginclassmedia.h"
  47. #include "llslurl.h"
  48. #include "lluictrlfactory.h" // LLDefaultChildRegistry
  49. #include "llkeyboard.h"
  50. // linden library includes
  51. #include "llfocusmgr.h"
  52. extern BOOL gRestoreGL;
  53. static LLDefaultChildRegistry::Register<LLMediaCtrl> r("web_browser");
  54. LLMediaCtrl::Params::Params()
  55. : start_url("start_url"),
  56. border_visible("border_visible", true),
  57. ignore_ui_scale("ignore_ui_scale", true),
  58. hide_loading("hide_loading", false),
  59. decouple_texture_size("decouple_texture_size", false),
  60. texture_width("texture_width", 1024),
  61. texture_height("texture_height", 1024),
  62. caret_color("caret_color")
  63. {
  64. tab_stop(false);
  65. }
  66. LLMediaCtrl::LLMediaCtrl( const Params& p) :
  67. LLPanel( p ),
  68. mTextureDepthBytes( 4 ),
  69. mBorder(NULL),
  70. mFrequentUpdates( true ),
  71. mForceUpdate( false ),
  72. mOpenLinksInExternalBrowser( false ),
  73. mOpenLinksInInternalBrowser( false ),
  74. mTrusted( false ),
  75. mHomePageUrl( "" ),
  76. mIgnoreUIScale( true ),
  77. mAlwaysRefresh( false ),
  78. mMediaSource( 0 ),
  79. mTakeFocusOnClick( true ),
  80. mCurrentNavUrl( "" ),
  81. mStretchToFill( true ),
  82. mMaintainAspectRatio ( true ),
  83. mHideLoading (false),
  84. mHidingInitialLoad (false),
  85. mDecoupleTextureSize ( false ),
  86. mTextureWidth ( 1024 ),
  87. mTextureHeight ( 1024 ),
  88. mClearCache(false)
  89. {
  90. {
  91. LLColor4 color = p.caret_color().get();
  92. setCaretColor( (unsigned int)color.mV[0], (unsigned int)color.mV[1], (unsigned int)color.mV[2] );
  93. }
  94. setIgnoreUIScale(p.ignore_ui_scale);
  95. setHomePageUrl(p.start_url);
  96. setBorderVisible(p.border_visible);
  97. mHideLoading = p.hide_loading;
  98. setDecoupleTextureSize(p.decouple_texture_size);
  99. setTextureSize(p.texture_width, p.texture_height);
  100. if(!getDecoupleTextureSize())
  101. {
  102. S32 screen_width = mIgnoreUIScale ? 
  103. llround((F32)getRect().getWidth() * LLUI::sGLScaleFactor.mV[VX]) : getRect().getWidth();
  104. S32 screen_height = mIgnoreUIScale ? 
  105. llround((F32)getRect().getHeight() * LLUI::sGLScaleFactor.mV[VY]) : getRect().getHeight();
  106. setTextureSize(screen_width, screen_height);
  107. }
  108. mMediaTextureID.generate();
  109. // We don't need to create the media source up front anymore unless we have a non-empty home URL to navigate to.
  110. if(!mHomePageUrl.empty())
  111. {
  112. navigateHome();
  113. }
  114. // FIXME: How do we create a bevel now?
  115. // LLRect border_rect( 0, getRect().getHeight() + 2, getRect().getWidth() + 2, 0 );
  116. // mBorder = new LLViewBorder( std::string("web control border"), border_rect, LLViewBorder::BEVEL_IN );
  117. // addChild( mBorder );
  118. }
  119. ////////////////////////////////////////////////////////////////////////////////
  120. // note: this is now a singleton and destruction happens via initClass() now
  121. LLMediaCtrl::~LLMediaCtrl()
  122. {
  123. if (mMediaSource)
  124. {
  125. mMediaSource->remObserver( this );
  126. mMediaSource = NULL;
  127. }
  128. }
  129. ////////////////////////////////////////////////////////////////////////////////
  130. //
  131. void LLMediaCtrl::setBorderVisible( BOOL border_visible )
  132. {
  133. if ( mBorder )
  134. {
  135. mBorder->setVisible( border_visible );
  136. };
  137. };
  138. ////////////////////////////////////////////////////////////////////////////////
  139. //
  140. void LLMediaCtrl::setTakeFocusOnClick( bool take_focus )
  141. {
  142. mTakeFocusOnClick = take_focus;
  143. }
  144. ////////////////////////////////////////////////////////////////////////////////
  145. // set flag that forces the embedded browser to open links in the external system browser
  146. void LLMediaCtrl::setOpenInExternalBrowser( bool valIn )
  147. {
  148. mOpenLinksInExternalBrowser = valIn;
  149. };
  150. ////////////////////////////////////////////////////////////////////////////////
  151. // set flag that forces the embedded browser to open links in the internal browser floater
  152. void LLMediaCtrl::setOpenInInternalBrowser( bool valIn )
  153. {
  154. mOpenLinksInInternalBrowser = valIn;
  155. };
  156. ////////////////////////////////////////////////////////////////////////////////
  157. void LLMediaCtrl::setTrusted( bool valIn )
  158. {
  159. mTrusted = valIn;
  160. }
  161. ////////////////////////////////////////////////////////////////////////////////
  162. //
  163. BOOL LLMediaCtrl::handleHover( S32 x, S32 y, MASK mask )
  164. {
  165. convertInputCoords(x, y);
  166. if (mMediaSource)
  167. {
  168. mMediaSource->mouseMove(x, y, mask);
  169. gViewerWindow->setCursor(mMediaSource->getLastSetCursor());
  170. }
  171. return TRUE;
  172. }
  173. ////////////////////////////////////////////////////////////////////////////////
  174. //
  175. BOOL LLMediaCtrl::handleScrollWheel( S32 x, S32 y, S32 clicks )
  176. {
  177. if (mMediaSource && mMediaSource->hasMedia())
  178. mMediaSource->getMediaPlugin()->scrollEvent(0, clicks, gKeyboard->currentMask(TRUE));
  179. return TRUE;
  180. }
  181. ////////////////////////////////////////////////////////////////////////////////
  182. //
  183. BOOL LLMediaCtrl::handleMouseUp( S32 x, S32 y, MASK mask )
  184. {
  185. convertInputCoords(x, y);
  186. if (mMediaSource)
  187. {
  188. mMediaSource->mouseUp(x, y, mask);
  189. // *HACK: LLMediaImplLLMozLib automatically takes focus on mouseup,
  190. // in addition to the onFocusReceived() call below.  Undo this. JC
  191. if (!mTakeFocusOnClick)
  192. {
  193. mMediaSource->focus(false);
  194. gViewerWindow->focusClient();
  195. }
  196. }
  197. gFocusMgr.setMouseCapture( NULL );
  198. return TRUE;
  199. }
  200. ////////////////////////////////////////////////////////////////////////////////
  201. //
  202. BOOL LLMediaCtrl::handleMouseDown( S32 x, S32 y, MASK mask )
  203. {
  204. convertInputCoords(x, y);
  205. if (mMediaSource)
  206. mMediaSource->mouseDown(x, y, mask);
  207. gFocusMgr.setMouseCapture( this );
  208. if (mTakeFocusOnClick)
  209. {
  210. setFocus( TRUE );
  211. }
  212. return TRUE;
  213. }
  214. ////////////////////////////////////////////////////////////////////////////////
  215. //
  216. BOOL LLMediaCtrl::handleRightMouseUp( S32 x, S32 y, MASK mask )
  217. {
  218. convertInputCoords(x, y);
  219. if (mMediaSource)
  220. {
  221. mMediaSource->mouseUp(x, y, mask, 1);
  222. // *HACK: LLMediaImplLLMozLib automatically takes focus on mouseup,
  223. // in addition to the onFocusReceived() call below.  Undo this. JC
  224. if (!mTakeFocusOnClick)
  225. {
  226. mMediaSource->focus(false);
  227. gViewerWindow->focusClient();
  228. }
  229. }
  230. gFocusMgr.setMouseCapture( NULL );
  231. return TRUE;
  232. }
  233. ////////////////////////////////////////////////////////////////////////////////
  234. //
  235. BOOL LLMediaCtrl::handleRightMouseDown( S32 x, S32 y, MASK mask )
  236. {
  237. convertInputCoords(x, y);
  238. if (mMediaSource)
  239. mMediaSource->mouseDown(x, y, mask, 1);
  240. gFocusMgr.setMouseCapture( this );
  241. if (mTakeFocusOnClick)
  242. {
  243. setFocus( TRUE );
  244. }
  245. return TRUE;
  246. }
  247. ////////////////////////////////////////////////////////////////////////////////
  248. //
  249. BOOL LLMediaCtrl::handleDoubleClick( S32 x, S32 y, MASK mask )
  250. {
  251. convertInputCoords(x, y);
  252. if (mMediaSource)
  253. mMediaSource->mouseDoubleClick( x, y, mask);
  254. gFocusMgr.setMouseCapture( this );
  255. if (mTakeFocusOnClick)
  256. {
  257. setFocus( TRUE );
  258. }
  259. return TRUE;
  260. }
  261. ////////////////////////////////////////////////////////////////////////////////
  262. //
  263. void LLMediaCtrl::onFocusReceived()
  264. {
  265. if (mMediaSource)
  266. {
  267. mMediaSource->focus(true);
  268. // Set focus for edit menu items
  269. LLEditMenuHandler::gEditMenuHandler = mMediaSource;
  270. }
  271. LLPanel::onFocusReceived();
  272. }
  273. ////////////////////////////////////////////////////////////////////////////////
  274. //
  275. void LLMediaCtrl::onFocusLost()
  276. {
  277. if (mMediaSource)
  278. {
  279. mMediaSource->focus(false);
  280. if( LLEditMenuHandler::gEditMenuHandler == mMediaSource )
  281. {
  282. // Clear focus for edit menu items
  283. LLEditMenuHandler::gEditMenuHandler = NULL;
  284. }
  285. }
  286. gViewerWindow->focusClient();
  287. LLPanel::onFocusLost();
  288. }
  289. ////////////////////////////////////////////////////////////////////////////////
  290. //
  291. BOOL LLMediaCtrl::postBuild ()
  292. {
  293. setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChange, this, _2));
  294. return TRUE;
  295. }
  296. ////////////////////////////////////////////////////////////////////////////////
  297. //
  298. BOOL LLMediaCtrl::handleKeyHere( KEY key, MASK mask )
  299. {
  300. BOOL result = FALSE;
  301. if (mMediaSource)
  302. {
  303. result = mMediaSource->handleKeyHere(key, mask);
  304. }
  305. return result;
  306. }
  307. ////////////////////////////////////////////////////////////////////////////////
  308. //
  309. void LLMediaCtrl::handleVisibilityChange ( BOOL new_visibility )
  310. {
  311. llinfos << "visibility changed to " << (new_visibility?"true":"false") << llendl;
  312. if(mMediaSource)
  313. {
  314. mMediaSource->setVisible( new_visibility );
  315. }
  316. }
  317. ////////////////////////////////////////////////////////////////////////////////
  318. //
  319. BOOL LLMediaCtrl::handleUnicodeCharHere(llwchar uni_char)
  320. {
  321. BOOL result = FALSE;
  322. if (mMediaSource)
  323. {
  324. result = mMediaSource->handleUnicodeCharHere(uni_char);
  325. }
  326. return result;
  327. }
  328. ////////////////////////////////////////////////////////////////////////////////
  329. //
  330. void LLMediaCtrl::onVisibilityChange ( const LLSD& new_visibility )
  331. {
  332. // set state of frequent updates automatically if visibility changes
  333. if ( new_visibility.asBoolean() )
  334. {
  335. mFrequentUpdates = true;
  336. }
  337. else
  338. {
  339. mFrequentUpdates = false;
  340. }
  341. }
  342. ////////////////////////////////////////////////////////////////////////////////
  343. //
  344. void LLMediaCtrl::reshape( S32 width, S32 height, BOOL called_from_parent )
  345. {
  346. if(!getDecoupleTextureSize())
  347. {
  348. S32 screen_width = mIgnoreUIScale ? llround((F32)width * LLUI::sGLScaleFactor.mV[VX]) : width;
  349. S32 screen_height = mIgnoreUIScale ? llround((F32)height * LLUI::sGLScaleFactor.mV[VY]) : height;
  350. // when floater is minimized, these sizes are negative
  351. if ( screen_height > 0 && screen_width > 0 )
  352. {
  353. setTextureSize(screen_width, screen_height);
  354. }
  355. }
  356. LLUICtrl::reshape( width, height, called_from_parent );
  357. }
  358. ////////////////////////////////////////////////////////////////////////////////
  359. //
  360. void LLMediaCtrl::navigateBack()
  361. {
  362. if (mMediaSource && mMediaSource->hasMedia())
  363. {
  364. mMediaSource->getMediaPlugin()->browse_back();
  365. }
  366. }
  367. ////////////////////////////////////////////////////////////////////////////////
  368. //
  369. void LLMediaCtrl::navigateForward()
  370. {
  371. if (mMediaSource && mMediaSource->hasMedia())
  372. {
  373. mMediaSource->getMediaPlugin()->browse_forward();
  374. }
  375. }
  376. ////////////////////////////////////////////////////////////////////////////////
  377. //
  378. bool LLMediaCtrl::canNavigateBack()
  379. {
  380. if (mMediaSource)
  381. return mMediaSource->canNavigateBack();
  382. else
  383. return false;
  384. }
  385. ////////////////////////////////////////////////////////////////////////////////
  386. //
  387. bool LLMediaCtrl::canNavigateForward()
  388. {
  389. if (mMediaSource)
  390. return mMediaSource->canNavigateForward();
  391. else
  392. return false;
  393. }
  394. ////////////////////////////////////////////////////////////////////////////////
  395. //
  396. void LLMediaCtrl::set404RedirectUrl( std::string redirect_url )
  397. {
  398. if(mMediaSource && mMediaSource->hasMedia())
  399. mMediaSource->getMediaPlugin()->set_status_redirect( 404, redirect_url );
  400. }
  401. ////////////////////////////////////////////////////////////////////////////////
  402. //
  403. void LLMediaCtrl::clr404RedirectUrl()
  404. {
  405. if(mMediaSource && mMediaSource->hasMedia())
  406. mMediaSource->getMediaPlugin()->set_status_redirect(404, "");
  407. }
  408. ////////////////////////////////////////////////////////////////////////////////
  409. //
  410. void LLMediaCtrl::clearCache()
  411. {
  412. if(mMediaSource)
  413. {
  414. mMediaSource->clearCache();
  415. }
  416. else
  417. {
  418. mClearCache = true;
  419. }
  420. }
  421. ////////////////////////////////////////////////////////////////////////////////
  422. //
  423. void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type)
  424. {
  425. // don't browse to anything that starts with secondlife:// or sl://
  426. const std::string protocol1 = "secondlife://";
  427. const std::string protocol2 = "sl://";
  428. if ((LLStringUtil::compareInsensitive(url_in.substr(0, protocol1.length()), protocol1) == 0) ||
  429.     (LLStringUtil::compareInsensitive(url_in.substr(0, protocol2.length()), protocol2) == 0))
  430. {
  431. // TODO: Print out/log this attempt?
  432. // llinfos << "Rejecting attempt to load restricted website :" << urlIn << llendl;
  433. return;
  434. }
  435. if (ensureMediaSourceExists())
  436. {
  437. mCurrentNavUrl = url_in;
  438. mMediaSource->setSize(mTextureWidth, mTextureHeight);
  439. mMediaSource->navigateTo(url_in, mime_type, mime_type.empty());
  440. }
  441. }
  442. ////////////////////////////////////////////////////////////////////////////////
  443. //
  444. void LLMediaCtrl::navigateToLocalPage( const std::string& subdir, const std::string& filename_in )
  445. {
  446. std::string language = LLUI::getLanguage();
  447. std::string delim = gDirUtilp->getDirDelimiter();
  448. std::string filename;
  449. filename += subdir;
  450. filename += delim;
  451. filename += filename_in;
  452. std::string expanded_filename = gDirUtilp->findSkinnedFilename("html", language, filename);
  453. if (! gDirUtilp->fileExists(expanded_filename))
  454. {
  455. if (language != "en")
  456. {
  457. expanded_filename = gDirUtilp->findSkinnedFilename("html", "en", filename);
  458. if (! gDirUtilp->fileExists(expanded_filename))
  459. {
  460. llwarns << "File " << subdir << delim << filename_in << "not found" << llendl;
  461. return;
  462. }
  463. }
  464. else
  465. {
  466. llwarns << "File " << subdir << delim << filename_in << "not found" << llendl;
  467. return;
  468. }
  469. }
  470. if (ensureMediaSourceExists())
  471. {
  472. mCurrentNavUrl = expanded_filename;
  473. mMediaSource->setSize(mTextureWidth, mTextureHeight);
  474. mMediaSource->navigateTo(expanded_filename, "text/html", false);
  475. }
  476. }
  477. ////////////////////////////////////////////////////////////////////////////////
  478. //
  479. void LLMediaCtrl::navigateHome()
  480. {
  481. if (ensureMediaSourceExists())
  482. {
  483. mMediaSource->setSize(mTextureWidth, mTextureHeight);
  484. mMediaSource->navigateHome();
  485. }
  486. }
  487. ////////////////////////////////////////////////////////////////////////////////
  488. //
  489. void LLMediaCtrl::setHomePageUrl( const std::string urlIn )
  490. {
  491. mHomePageUrl = urlIn;
  492. if (mMediaSource)
  493. {
  494. mMediaSource->setHomeURL(mHomePageUrl);
  495. }
  496. }
  497. ////////////////////////////////////////////////////////////////////////////////
  498. //
  499. bool LLMediaCtrl::setCaretColor(unsigned int red, unsigned int green, unsigned int blue)
  500. {
  501. //NOOP
  502. return false;
  503. }
  504. ////////////////////////////////////////////////////////////////////////////////
  505. //
  506. void LLMediaCtrl::setTextureSize(S32 width, S32 height)
  507. {
  508. mTextureWidth = width;
  509. mTextureHeight = height;
  510. if(mMediaSource)
  511. {
  512. mMediaSource->setSize(mTextureWidth, mTextureHeight);
  513. mForceUpdate = true;
  514. }
  515. }
  516. ////////////////////////////////////////////////////////////////////////////////
  517. //
  518. std::string LLMediaCtrl::getHomePageUrl()
  519. {
  520. return  mHomePageUrl;
  521. }
  522. ////////////////////////////////////////////////////////////////////////////////
  523. //
  524. bool LLMediaCtrl::ensureMediaSourceExists()
  525. {
  526. if(mMediaSource.isNull())
  527. {
  528. // If we don't already have a media source, try to create one.
  529. mMediaSource = LLViewerMedia::newMediaImpl(mMediaTextureID, mTextureWidth, mTextureHeight);
  530. if ( mMediaSource )
  531. {
  532. mMediaSource->setUsedInUI(true);
  533. mMediaSource->setHomeURL(mHomePageUrl);
  534. mMediaSource->setVisible( getVisible() );
  535. mMediaSource->addObserver( this );
  536. mMediaSource->setBackgroundColor( getBackgroundColor() );
  537. if(mClearCache)
  538. {
  539. mMediaSource->clearCache();
  540. mClearCache = false;
  541. }
  542. if(mHideLoading)
  543. {
  544. mHidingInitialLoad = true;
  545. }
  546. }
  547. else
  548. {
  549. llwarns << "media source create failed " << llendl;
  550. // return;
  551. }
  552. }
  553. return !mMediaSource.isNull();
  554. }
  555. ////////////////////////////////////////////////////////////////////////////////
  556. //
  557. void LLMediaCtrl::unloadMediaSource()
  558. {
  559. mMediaSource = NULL;
  560. }
  561. ////////////////////////////////////////////////////////////////////////////////
  562. //
  563. LLPluginClassMedia* LLMediaCtrl::getMediaPlugin()
  564. return mMediaSource.isNull() ? NULL : mMediaSource->getMediaPlugin(); 
  565. }
  566. ////////////////////////////////////////////////////////////////////////////////
  567. //
  568. void LLMediaCtrl::draw()
  569. {
  570. if ( gRestoreGL == 1 )
  571. {
  572. LLRect r = getRect();
  573. reshape( r.getWidth(), r.getHeight(), FALSE );
  574. return;
  575. }
  576. // NOTE: optimization needed here - probably only need to do this once
  577. // unless tearoffs change the parent which they probably do.
  578. const LLUICtrl* ptr = findRootMostFocusRoot();
  579. if ( ptr && ptr->hasFocus() )
  580. {
  581. setFrequentUpdates( true );
  582. }
  583. else
  584. {
  585. setFrequentUpdates( false );
  586. };
  587. bool draw_media = false;
  588. LLPluginClassMedia* media_plugin = NULL;
  589. LLViewerMediaTexture* media_texture = NULL;
  590. if(mMediaSource && mMediaSource->hasMedia())
  591. {
  592. media_plugin = mMediaSource->getMediaPlugin();
  593. if(media_plugin && (media_plugin->textureValid()))
  594. {
  595. media_texture = LLViewerTextureManager::findMediaTexture(mMediaTextureID);
  596. if(media_texture)
  597. {
  598. draw_media = true;
  599. }
  600. }
  601. }
  602. if(mHidingInitialLoad)
  603. {
  604. // If we're hiding loading, don't draw at all.
  605. draw_media = false;
  606. }
  607. bool background_visible = isBackgroundVisible();
  608. bool background_opaque = isBackgroundOpaque();
  609. if(draw_media)
  610. {
  611. // alpha off for this
  612. LLGLSUIDefault gls_ui;
  613. LLGLDisable gls_alphaTest( GL_ALPHA_TEST );
  614. gGL.pushMatrix();
  615. {
  616. if (mIgnoreUIScale)
  617. {
  618. glLoadIdentity();
  619. // font system stores true screen origin, need to scale this by UI scale factor
  620. // to get render origin for this view (with unit scale)
  621. gGL.translatef(floorf(LLFontGL::sCurOrigin.mX * LLUI::sGLScaleFactor.mV[VX]), 
  622. floorf(LLFontGL::sCurOrigin.mY * LLUI::sGLScaleFactor.mV[VY]), 
  623. LLFontGL::sCurOrigin.mZ);
  624. }
  625. // scale texture to fit the space using texture coords
  626. gGL.getTexUnit(0)->bind(media_texture);
  627. gGL.color4fv( LLColor4::white.mV );
  628. F32 max_u = ( F32 )media_plugin->getWidth() / ( F32 )media_plugin->getTextureWidth();
  629. F32 max_v = ( F32 )media_plugin->getHeight() / ( F32 )media_plugin->getTextureHeight();
  630. LLRect r = getRect();
  631. S32 width, height;
  632. S32 x_offset = 0;
  633. S32 y_offset = 0;
  634. if(mStretchToFill)
  635. {
  636. if(mMaintainAspectRatio)
  637. {
  638. F32 media_aspect = (F32)(media_plugin->getWidth()) / (F32)(media_plugin->getHeight());
  639. F32 view_aspect = (F32)(r.getWidth()) / (F32)(r.getHeight());
  640. if(media_aspect > view_aspect)
  641. {
  642. // max width, adjusted height
  643. width = r.getWidth();
  644. height = llmin(llmax(llround(width / media_aspect), 0), r.getHeight());
  645. }
  646. else
  647. {
  648. // max height, adjusted width
  649. height = r.getHeight();
  650. width = llmin(llmax(llround(height * media_aspect), 0), r.getWidth());
  651. }
  652. }
  653. else
  654. {
  655. width = r.getWidth();
  656. height = r.getHeight();
  657. }
  658. }
  659. else
  660. {
  661. width = llmin(media_plugin->getWidth(), r.getWidth());
  662. height = llmin(media_plugin->getHeight(), r.getHeight());
  663. }
  664. x_offset = (r.getWidth() - width) / 2;
  665. y_offset = (r.getHeight() - height) / 2;
  666. if(mIgnoreUIScale)
  667. {
  668. x_offset = llround((F32)x_offset * LLUI::sGLScaleFactor.mV[VX]);
  669. y_offset = llround((F32)y_offset * LLUI::sGLScaleFactor.mV[VY]);
  670. width = llround((F32)width * LLUI::sGLScaleFactor.mV[VX]);
  671. height = llround((F32)height * LLUI::sGLScaleFactor.mV[VY]);
  672. }
  673. // draw the browser
  674. gGL.setSceneBlendType(LLRender::BT_REPLACE);
  675. gGL.begin( LLRender::QUADS );
  676. if (! media_plugin->getTextureCoordsOpenGL())
  677. {
  678. // render using web browser reported width and height, instead of trying to invert GL scale
  679. gGL.texCoord2f( max_u, 0.f );
  680. gGL.vertex2i( x_offset + width, y_offset + height );
  681. gGL.texCoord2f( 0.f, 0.f );
  682. gGL.vertex2i( x_offset, y_offset + height );
  683. gGL.texCoord2f( 0.f, max_v );
  684. gGL.vertex2i( x_offset, y_offset );
  685. gGL.texCoord2f( max_u, max_v );
  686. gGL.vertex2i( x_offset + width, y_offset );
  687. }
  688. else
  689. {
  690. // render using web browser reported width and height, instead of trying to invert GL scale
  691. gGL.texCoord2f( max_u, max_v );
  692. gGL.vertex2i( x_offset + width, y_offset + height );
  693. gGL.texCoord2f( 0.f, max_v );
  694. gGL.vertex2i( x_offset, y_offset + height );
  695. gGL.texCoord2f( 0.f, 0.f );
  696. gGL.vertex2i( x_offset, y_offset );
  697. gGL.texCoord2f( max_u, 0.f );
  698. gGL.vertex2i( x_offset + width, y_offset );
  699. }
  700. gGL.end();
  701. gGL.setSceneBlendType(LLRender::BT_ALPHA);
  702. }
  703. gGL.popMatrix();
  704. }
  705. else
  706. {
  707. // Setting these will make LLPanel::draw draw the opaque background color.
  708. setBackgroundVisible(true);
  709. setBackgroundOpaque(true);
  710. }
  711. // highlight if keyboard focus here. (TODO: this needs some work)
  712. if ( mBorder && mBorder->getVisible() )
  713. mBorder->setKeyboardFocusHighlight( gFocusMgr.childHasKeyboardFocus( this ) );
  714. LLPanel::draw();
  715. // Restore the previous values
  716. setBackgroundVisible(background_visible);
  717. setBackgroundOpaque(background_opaque);
  718. }
  719. ////////////////////////////////////////////////////////////////////////////////
  720. //
  721. void LLMediaCtrl::convertInputCoords(S32& x, S32& y)
  722. {
  723. bool coords_opengl = false;
  724. if(mMediaSource && mMediaSource->hasMedia())
  725. {
  726. coords_opengl = mMediaSource->getMediaPlugin()->getTextureCoordsOpenGL();
  727. }
  728. x = mIgnoreUIScale ? llround((F32)x * LLUI::sGLScaleFactor.mV[VX]) : x;
  729. if ( ! coords_opengl )
  730. {
  731. y = mIgnoreUIScale ? llround((F32)(y) * LLUI::sGLScaleFactor.mV[VY]) : y;
  732. }
  733. else
  734. {
  735. y = mIgnoreUIScale ? llround((F32)(getRect().getHeight() - y) * LLUI::sGLScaleFactor.mV[VY]) : getRect().getHeight() - y;
  736. };
  737. }
  738. ////////////////////////////////////////////////////////////////////////////////
  739. // inherited from LLViewerMediaObserver
  740. //virtual 
  741. void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
  742. {
  743. switch(event)
  744. {
  745. case MEDIA_EVENT_CONTENT_UPDATED:
  746. {
  747. // LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CONTENT_UPDATED " << LL_ENDL;
  748. };
  749. break;
  750. case MEDIA_EVENT_TIME_DURATION_UPDATED:
  751. {
  752. // LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_TIME_DURATION_UPDATED, time is " << self->getCurrentTime() << " of " << self->getDuration() << LL_ENDL;
  753. };
  754. break;
  755. case MEDIA_EVENT_SIZE_CHANGED:
  756. {
  757. LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_SIZE_CHANGED " << LL_ENDL;
  758. LLRect r = getRect();
  759. reshape( r.getWidth(), r.getHeight(), FALSE );
  760. };
  761. break;
  762. case MEDIA_EVENT_CURSOR_CHANGED:
  763. {
  764. LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << self->getCursorName() << LL_ENDL;
  765. }
  766. break;
  767. case MEDIA_EVENT_NAVIGATE_BEGIN:
  768. {
  769. LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_NAVIGATE_BEGIN, url is " << self->getNavigateURI() << LL_ENDL;
  770. };
  771. break;
  772. case MEDIA_EVENT_NAVIGATE_COMPLETE:
  773. {
  774. LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_NAVIGATE_COMPLETE, result string is: " << self->getNavigateResultString() << LL_ENDL;
  775. if(mHidingInitialLoad)
  776. {
  777. mHidingInitialLoad = false;
  778. }
  779. };
  780. break;
  781. case MEDIA_EVENT_PROGRESS_UPDATED:
  782. {
  783. LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_PROGRESS_UPDATED, loading at " << self->getProgressPercent() << "%" << LL_ENDL;
  784. };
  785. break;
  786. case MEDIA_EVENT_STATUS_TEXT_CHANGED:
  787. {
  788. LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_STATUS_TEXT_CHANGED, new status text is: " << self->getStatusText() << LL_ENDL;
  789. };
  790. break;
  791. case MEDIA_EVENT_LOCATION_CHANGED:
  792. {
  793. LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_LOCATION_CHANGED, new uri is: " << self->getLocation() << LL_ENDL;
  794. };
  795. break;
  796. case MEDIA_EVENT_CLICK_LINK_HREF:
  797. {
  798. LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CLICK_LINK_HREF, target is "" << self->getClickTarget() << "", uri is " << self->getClickURL() << LL_ENDL;
  799. onClickLinkHref(self);
  800. };
  801. break;
  802. case MEDIA_EVENT_CLICK_LINK_NOFOLLOW:
  803. {
  804. LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is " << self->getClickURL() << LL_ENDL;
  805. onClickLinkNoFollow(self);
  806. };
  807. break;
  808. case MEDIA_EVENT_PLUGIN_FAILED:
  809. {
  810. LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_PLUGIN_FAILED" << LL_ENDL;
  811. };
  812. break;
  813. case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
  814. {
  815. LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << LL_ENDL;
  816. };
  817. break;
  818. case MEDIA_EVENT_NAME_CHANGED:
  819. {
  820. LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_NAME_CHANGED" << LL_ENDL;
  821. };
  822. break;
  823. };
  824. // chain all events to any potential observers of this object.
  825. emitEvent(self, event);
  826. }
  827. ////////////////////////////////////////////////////////////////////////////////
  828. // 
  829. void LLMediaCtrl::onClickLinkHref( LLPluginClassMedia* self )
  830. {
  831. // retrieve the event parameters
  832. std::string url = self->getClickURL();
  833. U32 target_type = self->getClickTargetType();
  834. // is there is a target specified for the link?
  835. if (target_type == LLPluginClassMedia::TARGET_EXTERNAL ||
  836. target_type == LLPluginClassMedia::TARGET_BLANK )
  837. {
  838. if (gSavedSettings.getBOOL("UseExternalBrowser"))
  839. {
  840. LLSD payload;
  841. payload["url"] = url;
  842. payload["target_type"] = LLSD::Integer(target_type);
  843. LLNotificationsUtil::add( "WebLaunchExternalTarget", LLSD(), payload, onClickLinkExternalTarget);
  844. }
  845. else
  846. {
  847. clickLinkWithTarget(url, target_type);
  848. }
  849. }
  850. else {
  851. const std::string protocol1( "http://" );
  852. const std::string protocol2( "https://" );
  853. if( mOpenLinksInExternalBrowser )
  854. {
  855. if ( !url.empty() )
  856. {
  857. if ( LLStringUtil::compareInsensitive( url.substr( 0, protocol1.length() ), protocol1 ) == 0 ||
  858. LLStringUtil::compareInsensitive( url.substr( 0, protocol2.length() ), protocol2 ) == 0 )
  859. {
  860. LLWeb::loadURLExternal( url );
  861. }
  862. }
  863. }
  864. else
  865. if( mOpenLinksInInternalBrowser )
  866. {
  867. if ( !url.empty() )
  868. {
  869. if ( LLStringUtil::compareInsensitive( url.substr( 0, protocol1.length() ), protocol1 ) == 0 ||
  870. LLStringUtil::compareInsensitive( url.substr( 0, protocol2.length() ), protocol2 ) == 0 )
  871. {
  872. llwarns << "Dead, unimplemented path that we used to send to the built-in browser long ago." << llendl;
  873. }
  874. }
  875. }
  876. }
  877. }
  878. ////////////////////////////////////////////////////////////////////////////////
  879. // static 
  880. bool LLMediaCtrl::onClickLinkExternalTarget(const LLSD& notification, const LLSD& response )
  881. {
  882. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  883. if ( 0 == option )
  884. {
  885. LLSD payload = notification["payload"];
  886. std::string url = payload["url"].asString();
  887. S32 target_type = payload["target_type"].asInteger();
  888. clickLinkWithTarget(url, target_type);
  889. }
  890. return false;
  891. }
  892. ////////////////////////////////////////////////////////////////////////////////
  893. // static 
  894. void LLMediaCtrl::clickLinkWithTarget(const std::string& url, const S32& target_type )
  895. {
  896. if (target_type == LLPluginClassMedia::TARGET_EXTERNAL)
  897. {
  898. // load target in an external browser
  899. LLWeb::loadURLExternal(url);
  900. }
  901. else if (target_type == LLPluginClassMedia::TARGET_BLANK)
  902. {
  903. // load target in the user's preferred browser
  904. LLWeb::loadURL(url);
  905. }
  906. else {
  907. // unsupported link target - shouldn't happen
  908. LL_WARNS("LinkTarget") << "Unsupported link target type" << LL_ENDL;
  909. }
  910. }
  911. ////////////////////////////////////////////////////////////////////////////////
  912. // 
  913. void LLMediaCtrl::onClickLinkNoFollow( LLPluginClassMedia* self )
  914. {
  915. // let the dispatcher handle blocking/throttling of SLURLs
  916. std::string url = self->getClickURL();
  917. LLURLDispatcher::dispatch(url, this, mTrusted);
  918. }
  919. ////////////////////////////////////////////////////////////////////////////////
  920. // 
  921. std::string LLMediaCtrl::getCurrentNavUrl()
  922. {
  923. return mCurrentNavUrl;
  924. }