/indra/newview/llmediactrl.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 1139 lines · 832 code · 172 blank · 135 comment · 97 complexity · df42e761caa94004d94f0750496b0e64 MD5 · raw file

  1. /**
  2. * @file LLMediaCtrl.cpp
  3. * @brief Web browser UI control
  4. *
  5. * $LicenseInfo:firstyear=2006&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "lltooltip.h"
  28. #include "llmediactrl.h"
  29. // viewer includes
  30. #include "llfloaterworldmap.h"
  31. #include "lluictrlfactory.h"
  32. #include "llurldispatcher.h"
  33. #include "llviewborder.h"
  34. #include "llviewercontrol.h"
  35. #include "llviewermedia.h"
  36. #include "llviewertexture.h"
  37. #include "llviewerwindow.h"
  38. #include "lldebugmessagebox.h"
  39. #include "llweb.h"
  40. #include "llrender.h"
  41. #include "llpluginclassmedia.h"
  42. #include "llslurl.h"
  43. #include "lluictrlfactory.h" // LLDefaultChildRegistry
  44. #include "llkeyboard.h"
  45. #include "llviewermenu.h"
  46. // linden library includes
  47. #include "llfocusmgr.h"
  48. #include "llsdutil.h"
  49. #include "lllayoutstack.h"
  50. #include "lliconctrl.h"
  51. #include "lltextbox.h"
  52. #include "llbutton.h"
  53. #include "llcheckboxctrl.h"
  54. #include "llnotifications.h"
  55. #include "lllineeditor.h"
  56. #include "llfloaterwebcontent.h"
  57. #include "llwindowshade.h"
  58. extern BOOL gRestoreGL;
  59. static LLDefaultChildRegistry::Register<LLMediaCtrl> r("web_browser");
  60. LLMediaCtrl::Params::Params()
  61. : start_url("start_url"),
  62. border_visible("border_visible", true),
  63. decouple_texture_size("decouple_texture_size", false),
  64. texture_width("texture_width", 1024),
  65. texture_height("texture_height", 1024),
  66. caret_color("caret_color"),
  67. initial_mime_type("initial_mime_type"),
  68. error_page_url("error_page_url"),
  69. media_id("media_id"),
  70. trusted_content("trusted_content", false),
  71. focus_on_click("focus_on_click", true)
  72. {
  73. }
  74. LLMediaCtrl::LLMediaCtrl( const Params& p) :
  75. LLPanel( p ),
  76. LLInstanceTracker<LLMediaCtrl, LLUUID>(LLUUID::generateNewID()),
  77. mTextureDepthBytes( 4 ),
  78. mBorder(NULL),
  79. mFrequentUpdates( true ),
  80. mForceUpdate( false ),
  81. mHomePageUrl( "" ),
  82. mAlwaysRefresh( false ),
  83. mMediaSource( 0 ),
  84. mTakeFocusOnClick( p.focus_on_click ),
  85. mCurrentNavUrl( "" ),
  86. mStretchToFill( true ),
  87. mMaintainAspectRatio ( true ),
  88. mDecoupleTextureSize ( false ),
  89. mTextureWidth ( 1024 ),
  90. mTextureHeight ( 1024 ),
  91. mClearCache(false),
  92. mHomePageMimeType(p.initial_mime_type),
  93. mErrorPageURL(p.error_page_url),
  94. mTrusted(p.trusted_content),
  95. mWindowShade(NULL),
  96. mHoverTextChanged(false),
  97. mContextMenu(NULL)
  98. {
  99. {
  100. LLColor4 color = p.caret_color().get();
  101. setCaretColor( (unsigned int)color.mV[0], (unsigned int)color.mV[1], (unsigned int)color.mV[2] );
  102. }
  103. setHomePageUrl(p.start_url, p.initial_mime_type);
  104. setBorderVisible(p.border_visible);
  105. setDecoupleTextureSize(p.decouple_texture_size);
  106. setTextureSize(p.texture_width, p.texture_height);
  107. if(!getDecoupleTextureSize())
  108. {
  109. S32 screen_width = llround((F32)getRect().getWidth() * LLUI::sGLScaleFactor.mV[VX]);
  110. S32 screen_height = llround((F32)getRect().getHeight() * LLUI::sGLScaleFactor.mV[VY]);
  111. setTextureSize(screen_width, screen_height);
  112. }
  113. mMediaTextureID = getKey();
  114. // We don't need to create the media source up front anymore unless we have a non-empty home URL to navigate to.
  115. if(!mHomePageUrl.empty())
  116. {
  117. navigateHome();
  118. }
  119. LLWindowShade::Params params;
  120. params.name = "notification_shade";
  121. params.rect = getLocalRect();
  122. params.follows.flags = FOLLOWS_ALL;
  123. params.modal = true;
  124. mWindowShade = LLUICtrlFactory::create<LLWindowShade>(params);
  125. addChild(mWindowShade);
  126. }
  127. LLMediaCtrl::~LLMediaCtrl()
  128. {
  129. if (mMediaSource)
  130. {
  131. mMediaSource->remObserver( this );
  132. mMediaSource = NULL;
  133. }
  134. }
  135. ////////////////////////////////////////////////////////////////////////////////
  136. //
  137. void LLMediaCtrl::setBorderVisible( BOOL border_visible )
  138. {
  139. if ( mBorder )
  140. {
  141. mBorder->setVisible( border_visible );
  142. };
  143. };
  144. ////////////////////////////////////////////////////////////////////////////////
  145. //
  146. void LLMediaCtrl::setTakeFocusOnClick( bool take_focus )
  147. {
  148. mTakeFocusOnClick = take_focus;
  149. }
  150. ////////////////////////////////////////////////////////////////////////////////
  151. //
  152. BOOL LLMediaCtrl::handleHover( S32 x, S32 y, MASK mask )
  153. {
  154. if (LLPanel::handleHover(x, y, mask)) return TRUE;
  155. convertInputCoords(x, y);
  156. if (mMediaSource)
  157. {
  158. mMediaSource->mouseMove(x, y, mask);
  159. gViewerWindow->setCursor(mMediaSource->getLastSetCursor());
  160. }
  161. // TODO: Is this the right way to handle hover text changes driven by the plugin?
  162. if(mHoverTextChanged)
  163. {
  164. mHoverTextChanged = false;
  165. handleToolTip(x, y, mask);
  166. }
  167. return TRUE;
  168. }
  169. ////////////////////////////////////////////////////////////////////////////////
  170. //
  171. BOOL LLMediaCtrl::handleScrollWheel( S32 x, S32 y, S32 clicks )
  172. {
  173. if (LLPanel::handleScrollWheel(x, y, clicks)) return TRUE;
  174. if (mMediaSource && mMediaSource->hasMedia())
  175. mMediaSource->getMediaPlugin()->scrollEvent(0, clicks, gKeyboard->currentMask(TRUE));
  176. return TRUE;
  177. }
  178. ////////////////////////////////////////////////////////////////////////////////
  179. // virtual
  180. BOOL LLMediaCtrl::handleToolTip(S32 x, S32 y, MASK mask)
  181. {
  182. std::string hover_text;
  183. if (mMediaSource && mMediaSource->hasMedia())
  184. hover_text = mMediaSource->getMediaPlugin()->getHoverText();
  185. if(hover_text.empty())
  186. {
  187. return FALSE;
  188. }
  189. else
  190. {
  191. S32 screen_x, screen_y;
  192. localPointToScreen(x, y, &screen_x, &screen_y);
  193. LLRect sticky_rect_screen;
  194. sticky_rect_screen.setCenterAndSize(screen_x, screen_y, 20, 20);
  195. LLToolTipMgr::instance().show(LLToolTip::Params()
  196. .message(hover_text)
  197. .sticky_rect(sticky_rect_screen));
  198. }
  199. return TRUE;
  200. }
  201. ////////////////////////////////////////////////////////////////////////////////
  202. //
  203. BOOL LLMediaCtrl::handleMouseUp( S32 x, S32 y, MASK mask )
  204. {
  205. if (LLPanel::handleMouseUp(x, y, mask)) return TRUE;
  206. convertInputCoords(x, y);
  207. if (mMediaSource)
  208. {
  209. mMediaSource->mouseUp(x, y, mask);
  210. }
  211. gFocusMgr.setMouseCapture( NULL );
  212. return TRUE;
  213. }
  214. ////////////////////////////////////////////////////////////////////////////////
  215. //
  216. BOOL LLMediaCtrl::handleMouseDown( S32 x, S32 y, MASK mask )
  217. {
  218. if (LLPanel::handleMouseDown(x, y, mask)) return TRUE;
  219. convertInputCoords(x, y);
  220. if (mMediaSource)
  221. mMediaSource->mouseDown(x, y, mask);
  222. gFocusMgr.setMouseCapture( this );
  223. if (mTakeFocusOnClick)
  224. {
  225. setFocus( TRUE );
  226. }
  227. return TRUE;
  228. }
  229. ////////////////////////////////////////////////////////////////////////////////
  230. //
  231. BOOL LLMediaCtrl::handleRightMouseUp( S32 x, S32 y, MASK mask )
  232. {
  233. if (LLPanel::handleRightMouseUp(x, y, mask)) return TRUE;
  234. convertInputCoords(x, y);
  235. if (mMediaSource)
  236. {
  237. mMediaSource->mouseUp(x, y, mask, 1);
  238. // *HACK: LLMediaImplLLMozLib automatically takes focus on mouseup,
  239. // in addition to the onFocusReceived() call below. Undo this. JC
  240. if (!mTakeFocusOnClick)
  241. {
  242. mMediaSource->focus(false);
  243. gViewerWindow->focusClient();
  244. }
  245. }
  246. gFocusMgr.setMouseCapture( NULL );
  247. return TRUE;
  248. }
  249. ////////////////////////////////////////////////////////////////////////////////
  250. //
  251. BOOL LLMediaCtrl::handleRightMouseDown( S32 x, S32 y, MASK mask )
  252. {
  253. if (LLPanel::handleRightMouseDown(x, y, mask)) return TRUE;
  254. S32 media_x = x, media_y = y;
  255. convertInputCoords(media_x, media_y);
  256. if (mMediaSource)
  257. mMediaSource->mouseDown(media_x, media_y, mask, 1);
  258. gFocusMgr.setMouseCapture( this );
  259. if (mTakeFocusOnClick)
  260. {
  261. setFocus( TRUE );
  262. }
  263. if (mContextMenu)
  264. {
  265. // hide/show debugging options
  266. bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging");
  267. mContextMenu->setItemVisible("open_webinspector", media_plugin_debugging_enabled );
  268. mContextMenu->setItemVisible("debug_separator", media_plugin_debugging_enabled );
  269. mContextMenu->show(x, y);
  270. LLMenuGL::showPopup(this, mContextMenu, x, y);
  271. }
  272. return TRUE;
  273. }
  274. ////////////////////////////////////////////////////////////////////////////////
  275. //
  276. BOOL LLMediaCtrl::handleDoubleClick( S32 x, S32 y, MASK mask )
  277. {
  278. if (LLPanel::handleDoubleClick(x, y, mask)) return TRUE;
  279. convertInputCoords(x, y);
  280. if (mMediaSource)
  281. mMediaSource->mouseDoubleClick( x, y, mask);
  282. gFocusMgr.setMouseCapture( this );
  283. if (mTakeFocusOnClick)
  284. {
  285. setFocus( TRUE );
  286. }
  287. return TRUE;
  288. }
  289. ////////////////////////////////////////////////////////////////////////////////
  290. //
  291. void LLMediaCtrl::onFocusReceived()
  292. {
  293. if (mMediaSource)
  294. {
  295. mMediaSource->focus(true);
  296. // Set focus for edit menu items
  297. LLEditMenuHandler::gEditMenuHandler = mMediaSource;
  298. }
  299. LLPanel::onFocusReceived();
  300. }
  301. ////////////////////////////////////////////////////////////////////////////////
  302. //
  303. void LLMediaCtrl::onFocusLost()
  304. {
  305. if (mMediaSource)
  306. {
  307. mMediaSource->focus(false);
  308. if( LLEditMenuHandler::gEditMenuHandler == mMediaSource )
  309. {
  310. // Clear focus for edit menu items
  311. LLEditMenuHandler::gEditMenuHandler = NULL;
  312. }
  313. }
  314. gViewerWindow->focusClient();
  315. LLPanel::onFocusLost();
  316. }
  317. ////////////////////////////////////////////////////////////////////////////////
  318. //
  319. BOOL LLMediaCtrl::postBuild ()
  320. {
  321. LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registar;
  322. registar.add("Open.WebInspector", boost::bind(&LLMediaCtrl::onOpenWebInspector, this));
  323. mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
  324. "menu_media_ctrl.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
  325. setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChange, this, _2));
  326. return TRUE;
  327. }
  328. void LLMediaCtrl::onOpenWebInspector()
  329. {
  330. if (mMediaSource && mMediaSource->hasMedia())
  331. mMediaSource->getMediaPlugin()->showWebInspector( true );
  332. }
  333. ////////////////////////////////////////////////////////////////////////////////
  334. //
  335. BOOL LLMediaCtrl::handleKeyHere( KEY key, MASK mask )
  336. {
  337. BOOL result = FALSE;
  338. if (mMediaSource)
  339. {
  340. result = mMediaSource->handleKeyHere(key, mask);
  341. }
  342. if ( ! result )
  343. result = LLPanel::handleKeyHere(key, mask);
  344. return result;
  345. }
  346. ////////////////////////////////////////////////////////////////////////////////
  347. //
  348. void LLMediaCtrl::handleVisibilityChange ( BOOL new_visibility )
  349. {
  350. llinfos << "visibility changed to " << (new_visibility?"true":"false") << llendl;
  351. if(mMediaSource)
  352. {
  353. mMediaSource->setVisible( new_visibility );
  354. }
  355. }
  356. ////////////////////////////////////////////////////////////////////////////////
  357. //
  358. BOOL LLMediaCtrl::handleUnicodeCharHere(llwchar uni_char)
  359. {
  360. BOOL result = FALSE;
  361. if (mMediaSource)
  362. {
  363. result = mMediaSource->handleUnicodeCharHere(uni_char);
  364. }
  365. if ( ! result )
  366. result = LLPanel::handleUnicodeCharHere(uni_char);
  367. return result;
  368. }
  369. ////////////////////////////////////////////////////////////////////////////////
  370. //
  371. void LLMediaCtrl::onVisibilityChange ( const LLSD& new_visibility )
  372. {
  373. // set state of frequent updates automatically if visibility changes
  374. if ( new_visibility.asBoolean() )
  375. {
  376. mFrequentUpdates = true;
  377. }
  378. else
  379. {
  380. mFrequentUpdates = false;
  381. }
  382. }
  383. ////////////////////////////////////////////////////////////////////////////////
  384. //
  385. void LLMediaCtrl::reshape( S32 width, S32 height, BOOL called_from_parent )
  386. {
  387. if(!getDecoupleTextureSize())
  388. {
  389. S32 screen_width = llround((F32)width * LLUI::sGLScaleFactor.mV[VX]);
  390. S32 screen_height = llround((F32)height * LLUI::sGLScaleFactor.mV[VY]);
  391. // when floater is minimized, these sizes are negative
  392. if ( screen_height > 0 && screen_width > 0 )
  393. {
  394. setTextureSize(screen_width, screen_height);
  395. }
  396. }
  397. LLUICtrl::reshape( width, height, called_from_parent );
  398. }
  399. ////////////////////////////////////////////////////////////////////////////////
  400. //
  401. void LLMediaCtrl::navigateBack()
  402. {
  403. if (mMediaSource && mMediaSource->hasMedia())
  404. {
  405. mMediaSource->getMediaPlugin()->browse_back();
  406. }
  407. }
  408. ////////////////////////////////////////////////////////////////////////////////
  409. //
  410. void LLMediaCtrl::navigateForward()
  411. {
  412. if (mMediaSource && mMediaSource->hasMedia())
  413. {
  414. mMediaSource->getMediaPlugin()->browse_forward();
  415. }
  416. }
  417. ////////////////////////////////////////////////////////////////////////////////
  418. //
  419. bool LLMediaCtrl::canNavigateBack()
  420. {
  421. if (mMediaSource)
  422. return mMediaSource->canNavigateBack();
  423. else
  424. return false;
  425. }
  426. ////////////////////////////////////////////////////////////////////////////////
  427. //
  428. bool LLMediaCtrl::canNavigateForward()
  429. {
  430. if (mMediaSource)
  431. return mMediaSource->canNavigateForward();
  432. else
  433. return false;
  434. }
  435. ////////////////////////////////////////////////////////////////////////////////
  436. //
  437. void LLMediaCtrl::clearCache()
  438. {
  439. if(mMediaSource)
  440. {
  441. mMediaSource->clearCache();
  442. }
  443. else
  444. {
  445. mClearCache = true;
  446. }
  447. }
  448. ////////////////////////////////////////////////////////////////////////////////
  449. //
  450. void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type)
  451. {
  452. // don't browse to anything that starts with secondlife:// or sl://
  453. const std::string protocol1 = "secondlife://";
  454. const std::string protocol2 = "sl://";
  455. if ((LLStringUtil::compareInsensitive(url_in.substr(0, protocol1.length()), protocol1) == 0) ||
  456. (LLStringUtil::compareInsensitive(url_in.substr(0, protocol2.length()), protocol2) == 0))
  457. {
  458. // TODO: Print out/log this attempt?
  459. // llinfos << "Rejecting attempt to load restricted website :" << urlIn << llendl;
  460. return;
  461. }
  462. if (ensureMediaSourceExists())
  463. {
  464. mCurrentNavUrl = url_in;
  465. mMediaSource->setSize(mTextureWidth, mTextureHeight);
  466. mMediaSource->navigateTo(url_in, mime_type, mime_type.empty());
  467. }
  468. }
  469. ////////////////////////////////////////////////////////////////////////////////
  470. //
  471. void LLMediaCtrl::navigateToLocalPage( const std::string& subdir, const std::string& filename_in )
  472. {
  473. std::string language = LLUI::getLanguage();
  474. std::string delim = gDirUtilp->getDirDelimiter();
  475. std::string filename;
  476. filename += subdir;
  477. filename += delim;
  478. filename += filename_in;
  479. std::string expanded_filename = gDirUtilp->findSkinnedFilename("html", language, filename);
  480. if (! gDirUtilp->fileExists(expanded_filename))
  481. {
  482. if (language != "en")
  483. {
  484. expanded_filename = gDirUtilp->findSkinnedFilename("html", "en", filename);
  485. if (! gDirUtilp->fileExists(expanded_filename))
  486. {
  487. llwarns << "File " << subdir << delim << filename_in << "not found" << llendl;
  488. return;
  489. }
  490. }
  491. else
  492. {
  493. llwarns << "File " << subdir << delim << filename_in << "not found" << llendl;
  494. return;
  495. }
  496. }
  497. if (ensureMediaSourceExists())
  498. {
  499. mCurrentNavUrl = expanded_filename;
  500. mMediaSource->setSize(mTextureWidth, mTextureHeight);
  501. mMediaSource->navigateTo(expanded_filename, "text/html", false);
  502. }
  503. }
  504. ////////////////////////////////////////////////////////////////////////////////
  505. //
  506. void LLMediaCtrl::navigateHome()
  507. {
  508. if (ensureMediaSourceExists())
  509. {
  510. mMediaSource->setSize(mTextureWidth, mTextureHeight);
  511. mMediaSource->navigateHome();
  512. }
  513. }
  514. ////////////////////////////////////////////////////////////////////////////////
  515. //
  516. void LLMediaCtrl::setHomePageUrl( const std::string& urlIn, const std::string& mime_type )
  517. {
  518. mHomePageUrl = urlIn;
  519. if (mMediaSource)
  520. {
  521. mMediaSource->setHomeURL(mHomePageUrl, mime_type);
  522. }
  523. }
  524. void LLMediaCtrl::setTarget(const std::string& target)
  525. {
  526. mTarget = target;
  527. if (mMediaSource)
  528. {
  529. mMediaSource->setTarget(mTarget);
  530. }
  531. }
  532. void LLMediaCtrl::setErrorPageURL(const std::string& url)
  533. {
  534. mErrorPageURL = url;
  535. }
  536. const std::string& LLMediaCtrl::getErrorPageURL()
  537. {
  538. return mErrorPageURL;
  539. }
  540. ////////////////////////////////////////////////////////////////////////////////
  541. //
  542. bool LLMediaCtrl::setCaretColor(unsigned int red, unsigned int green, unsigned int blue)
  543. {
  544. //NOOP
  545. return false;
  546. }
  547. ////////////////////////////////////////////////////////////////////////////////
  548. //
  549. void LLMediaCtrl::setTextureSize(S32 width, S32 height)
  550. {
  551. mTextureWidth = width;
  552. mTextureHeight = height;
  553. if(mMediaSource)
  554. {
  555. mMediaSource->setSize(mTextureWidth, mTextureHeight);
  556. mForceUpdate = true;
  557. }
  558. }
  559. ////////////////////////////////////////////////////////////////////////////////
  560. //
  561. std::string LLMediaCtrl::getHomePageUrl()
  562. {
  563. return mHomePageUrl;
  564. }
  565. ////////////////////////////////////////////////////////////////////////////////
  566. //
  567. bool LLMediaCtrl::ensureMediaSourceExists()
  568. {
  569. if(mMediaSource.isNull())
  570. {
  571. // If we don't already have a media source, try to create one.
  572. mMediaSource = LLViewerMedia::newMediaImpl(mMediaTextureID, mTextureWidth, mTextureHeight);
  573. if ( mMediaSource )
  574. {
  575. mMediaSource->setUsedInUI(true);
  576. mMediaSource->setHomeURL(mHomePageUrl, mHomePageMimeType);
  577. mMediaSource->setTarget(mTarget);
  578. mMediaSource->setVisible( getVisible() );
  579. mMediaSource->addObserver( this );
  580. mMediaSource->setBackgroundColor( getBackgroundColor() );
  581. mMediaSource->setTrustedBrowser(mTrusted);
  582. mMediaSource->setPageZoomFactor( LLUI::sGLScaleFactor.mV[ VX ] );
  583. if(mClearCache)
  584. {
  585. mMediaSource->clearCache();
  586. mClearCache = false;
  587. }
  588. }
  589. else
  590. {
  591. llwarns << "media source create failed " << llendl;
  592. // return;
  593. }
  594. }
  595. return !mMediaSource.isNull();
  596. }
  597. ////////////////////////////////////////////////////////////////////////////////
  598. //
  599. void LLMediaCtrl::unloadMediaSource()
  600. {
  601. mMediaSource = NULL;
  602. }
  603. ////////////////////////////////////////////////////////////////////////////////
  604. //
  605. LLPluginClassMedia* LLMediaCtrl::getMediaPlugin()
  606. {
  607. return mMediaSource.isNull() ? NULL : mMediaSource->getMediaPlugin();
  608. }
  609. ////////////////////////////////////////////////////////////////////////////////
  610. //
  611. void LLMediaCtrl::draw()
  612. {
  613. F32 alpha = getDrawContext().mAlpha;
  614. if ( gRestoreGL == 1 )
  615. {
  616. LLRect r = getRect();
  617. reshape( r.getWidth(), r.getHeight(), FALSE );
  618. return;
  619. }
  620. // NOTE: optimization needed here - probably only need to do this once
  621. // unless tearoffs change the parent which they probably do.
  622. const LLUICtrl* ptr = findRootMostFocusRoot();
  623. if ( ptr && ptr->hasFocus() )
  624. {
  625. setFrequentUpdates( true );
  626. }
  627. else
  628. {
  629. setFrequentUpdates( false );
  630. };
  631. bool draw_media = false;
  632. LLPluginClassMedia* media_plugin = NULL;
  633. LLViewerMediaTexture* media_texture = NULL;
  634. if(mMediaSource && mMediaSource->hasMedia())
  635. {
  636. media_plugin = mMediaSource->getMediaPlugin();
  637. if(media_plugin && (media_plugin->textureValid()))
  638. {
  639. media_texture = LLViewerTextureManager::findMediaTexture(mMediaTextureID);
  640. if(media_texture)
  641. {
  642. draw_media = true;
  643. }
  644. }
  645. }
  646. bool background_visible = isBackgroundVisible();
  647. bool background_opaque = isBackgroundOpaque();
  648. if(draw_media)
  649. {
  650. gGL.pushUIMatrix();
  651. {
  652. mMediaSource->setPageZoomFactor( LLUI::sGLScaleFactor.mV[ VX ] );
  653. // scale texture to fit the space using texture coords
  654. gGL.getTexUnit(0)->bind(media_texture);
  655. LLColor4 media_color = LLColor4::white % alpha;
  656. gGL.color4fv( media_color.mV );
  657. F32 max_u = ( F32 )media_plugin->getWidth() / ( F32 )media_plugin->getTextureWidth();
  658. F32 max_v = ( F32 )media_plugin->getHeight() / ( F32 )media_plugin->getTextureHeight();
  659. LLRect r = getRect();
  660. S32 width, height;
  661. S32 x_offset = 0;
  662. S32 y_offset = 0;
  663. if(mStretchToFill)
  664. {
  665. if(mMaintainAspectRatio)
  666. {
  667. F32 media_aspect = (F32)(media_plugin->getWidth()) / (F32)(media_plugin->getHeight());
  668. F32 view_aspect = (F32)(r.getWidth()) / (F32)(r.getHeight());
  669. if(media_aspect > view_aspect)
  670. {
  671. // max width, adjusted height
  672. width = r.getWidth();
  673. height = llmin(llmax(llround(width / media_aspect), 0), r.getHeight());
  674. }
  675. else
  676. {
  677. // max height, adjusted width
  678. height = r.getHeight();
  679. width = llmin(llmax(llround(height * media_aspect), 0), r.getWidth());
  680. }
  681. }
  682. else
  683. {
  684. width = r.getWidth();
  685. height = r.getHeight();
  686. }
  687. }
  688. else
  689. {
  690. width = llmin(media_plugin->getWidth(), r.getWidth());
  691. height = llmin(media_plugin->getHeight(), r.getHeight());
  692. }
  693. x_offset = (r.getWidth() - width) / 2;
  694. y_offset = (r.getHeight() - height) / 2;
  695. // draw the browser
  696. gGL.begin( LLRender::QUADS );
  697. if (! media_plugin->getTextureCoordsOpenGL())
  698. {
  699. // render using web browser reported width and height, instead of trying to invert GL scale
  700. gGL.texCoord2f( max_u, 0.f );
  701. gGL.vertex2i( x_offset + width, y_offset + height );
  702. gGL.texCoord2f( 0.f, 0.f );
  703. gGL.vertex2i( x_offset, y_offset + height );
  704. gGL.texCoord2f( 0.f, max_v );
  705. gGL.vertex2i( x_offset, y_offset );
  706. gGL.texCoord2f( max_u, max_v );
  707. gGL.vertex2i( x_offset + width, y_offset );
  708. }
  709. else
  710. {
  711. // render using web browser reported width and height, instead of trying to invert GL scale
  712. gGL.texCoord2f( max_u, max_v );
  713. gGL.vertex2i( x_offset + width, y_offset + height );
  714. gGL.texCoord2f( 0.f, max_v );
  715. gGL.vertex2i( x_offset, y_offset + height );
  716. gGL.texCoord2f( 0.f, 0.f );
  717. gGL.vertex2i( x_offset, y_offset );
  718. gGL.texCoord2f( max_u, 0.f );
  719. gGL.vertex2i( x_offset + width, y_offset );
  720. }
  721. gGL.end();
  722. }
  723. gGL.popUIMatrix();
  724. }
  725. else
  726. {
  727. // Setting these will make LLPanel::draw draw the opaque background color.
  728. setBackgroundVisible(true);
  729. setBackgroundOpaque(true);
  730. }
  731. // highlight if keyboard focus here. (TODO: this needs some work)
  732. if ( mBorder && mBorder->getVisible() )
  733. mBorder->setKeyboardFocusHighlight( gFocusMgr.childHasKeyboardFocus( this ) );
  734. LLPanel::draw();
  735. // Restore the previous values
  736. setBackgroundVisible(background_visible);
  737. setBackgroundOpaque(background_opaque);
  738. }
  739. ////////////////////////////////////////////////////////////////////////////////
  740. //
  741. void LLMediaCtrl::convertInputCoords(S32& x, S32& y)
  742. {
  743. bool coords_opengl = false;
  744. if(mMediaSource && mMediaSource->hasMedia())
  745. {
  746. coords_opengl = mMediaSource->getMediaPlugin()->getTextureCoordsOpenGL();
  747. }
  748. x = llround((F32)x * LLUI::sGLScaleFactor.mV[VX]);
  749. if ( ! coords_opengl )
  750. {
  751. y = llround((F32)(y) * LLUI::sGLScaleFactor.mV[VY]);
  752. }
  753. else
  754. {
  755. y = llround((F32)(getRect().getHeight() - y) * LLUI::sGLScaleFactor.mV[VY]);
  756. };
  757. }
  758. ////////////////////////////////////////////////////////////////////////////////
  759. // inherited from LLViewerMediaObserver
  760. //virtual
  761. void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
  762. {
  763. switch(event)
  764. {
  765. case MEDIA_EVENT_CONTENT_UPDATED:
  766. {
  767. // LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CONTENT_UPDATED " << LL_ENDL;
  768. };
  769. break;
  770. case MEDIA_EVENT_TIME_DURATION_UPDATED:
  771. {
  772. // LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_TIME_DURATION_UPDATED, time is " << self->getCurrentTime() << " of " << self->getDuration() << LL_ENDL;
  773. };
  774. break;
  775. case MEDIA_EVENT_SIZE_CHANGED:
  776. {
  777. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_SIZE_CHANGED " << LL_ENDL;
  778. LLRect r = getRect();
  779. reshape( r.getWidth(), r.getHeight(), FALSE );
  780. };
  781. break;
  782. case MEDIA_EVENT_CURSOR_CHANGED:
  783. {
  784. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << self->getCursorName() << LL_ENDL;
  785. }
  786. break;
  787. case MEDIA_EVENT_NAVIGATE_BEGIN:
  788. {
  789. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_BEGIN, url is " << self->getNavigateURI() << LL_ENDL;
  790. hideNotification();
  791. };
  792. break;
  793. case MEDIA_EVENT_NAVIGATE_COMPLETE:
  794. {
  795. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_COMPLETE, result string is: " << self->getNavigateResultString() << LL_ENDL;
  796. if(mHidingInitialLoad)
  797. {
  798. mHidingInitialLoad = false;
  799. }
  800. };
  801. break;
  802. case MEDIA_EVENT_PROGRESS_UPDATED:
  803. {
  804. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PROGRESS_UPDATED, loading at " << self->getProgressPercent() << "%" << LL_ENDL;
  805. };
  806. break;
  807. case MEDIA_EVENT_STATUS_TEXT_CHANGED:
  808. {
  809. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_STATUS_TEXT_CHANGED, new status text is: " << self->getStatusText() << LL_ENDL;
  810. };
  811. break;
  812. case MEDIA_EVENT_LOCATION_CHANGED:
  813. {
  814. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_LOCATION_CHANGED, new uri is: " << self->getLocation() << LL_ENDL;
  815. };
  816. break;
  817. case MEDIA_EVENT_NAVIGATE_ERROR_PAGE:
  818. {
  819. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_ERROR_PAGE" << LL_ENDL;
  820. if ( mErrorPageURL.length() > 0 )
  821. {
  822. navigateTo(mErrorPageURL, "text/html");
  823. };
  824. };
  825. break;
  826. case MEDIA_EVENT_CLICK_LINK_HREF:
  827. {
  828. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << self->getClickTarget() << "\", uri is " << self->getClickURL() << LL_ENDL;
  829. // retrieve the event parameters
  830. std::string url = self->getClickURL();
  831. std::string target = self->getClickTarget();
  832. std::string uuid = self->getClickUUID();
  833. LLNotification::Params notify_params;
  834. notify_params.name = "PopupAttempt";
  835. notify_params.payload = LLSD().with("target", target).with("url", url).with("uuid", uuid).with("media_id", mMediaTextureID);
  836. notify_params.functor.function = boost::bind(&LLMediaCtrl::onPopup, this, _1, _2);
  837. if (mTrusted)
  838. {
  839. LLNotifications::instance().forceResponse(notify_params, 0);
  840. }
  841. else
  842. {
  843. LLNotifications::instance().add(notify_params);
  844. }
  845. break;
  846. };
  847. case MEDIA_EVENT_CLICK_LINK_NOFOLLOW:
  848. {
  849. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is " << self->getClickURL() << LL_ENDL;
  850. };
  851. break;
  852. case MEDIA_EVENT_PLUGIN_FAILED:
  853. {
  854. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED" << LL_ENDL;
  855. };
  856. break;
  857. case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
  858. {
  859. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << LL_ENDL;
  860. };
  861. break;
  862. case MEDIA_EVENT_NAME_CHANGED:
  863. {
  864. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAME_CHANGED" << LL_ENDL;
  865. };
  866. break;
  867. case MEDIA_EVENT_CLOSE_REQUEST:
  868. {
  869. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLOSE_REQUEST" << LL_ENDL;
  870. }
  871. break;
  872. case MEDIA_EVENT_PICK_FILE_REQUEST:
  873. {
  874. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PICK_FILE_REQUEST" << LL_ENDL;
  875. }
  876. break;
  877. case MEDIA_EVENT_GEOMETRY_CHANGE:
  878. {
  879. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_GEOMETRY_CHANGE, uuid is " << self->getClickUUID() << LL_ENDL;
  880. }
  881. break;
  882. case MEDIA_EVENT_AUTH_REQUEST:
  883. {
  884. LLNotification::Params auth_request_params;
  885. auth_request_params.name = "AuthRequest";
  886. // pass in host name and realm for site (may be zero length but will always exist)
  887. LLSD args;
  888. LLURL raw_url( self->getAuthURL().c_str() );
  889. args["HOST_NAME"] = raw_url.getAuthority();
  890. args["REALM"] = self->getAuthRealm();
  891. auth_request_params.substitutions = args;
  892. auth_request_params.payload = LLSD().with("media_id", mMediaTextureID);
  893. auth_request_params.functor.function = boost::bind(&LLViewerMedia::onAuthSubmit, _1, _2);
  894. LLNotifications::instance().add(auth_request_params);
  895. };
  896. break;
  897. case MEDIA_EVENT_LINK_HOVERED:
  898. {
  899. LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_LINK_HOVERED, hover text is: " << self->getHoverText() << LL_ENDL;
  900. mHoverTextChanged = true;
  901. };
  902. break;
  903. case MEDIA_EVENT_DEBUG_MESSAGE:
  904. {
  905. LL_INFOS("media") << self->getDebugMessageText() << LL_ENDL;
  906. };
  907. break;
  908. };
  909. // chain all events to any potential observers of this object.
  910. emitEvent(self, event);
  911. }
  912. ////////////////////////////////////////////////////////////////////////////////
  913. //
  914. std::string LLMediaCtrl::getCurrentNavUrl()
  915. {
  916. return mCurrentNavUrl;
  917. }
  918. void LLMediaCtrl::onPopup(const LLSD& notification, const LLSD& response)
  919. {
  920. if (response["open"])
  921. {
  922. LLWeb::loadURL(notification["payload"]["url"], notification["payload"]["target"], notification["payload"]["uuid"]);
  923. }
  924. else
  925. {
  926. // Make sure the opening instance knows its window open request was denied, so it can clean things up.
  927. LLViewerMedia::proxyWindowClosed(notification["payload"]["uuid"]);
  928. }
  929. }
  930. void LLMediaCtrl::showNotification(LLNotificationPtr notify)
  931. {
  932. LLWindowShade* shade = getChild<LLWindowShade>("notification_shade");
  933. if (notify->getIcon() == "Popup_Caution")
  934. {
  935. shade->setBackgroundImage(LLUI::getUIImage("Yellow_Gradient"));
  936. shade->setTextColor(LLColor4::black);
  937. shade->setCanClose(true);
  938. }
  939. else if (notify->getName() == "AuthRequest")
  940. {
  941. shade->setBackgroundImage(LLUI::getUIImage("Yellow_Gradient"));
  942. shade->setTextColor(LLColor4::black);
  943. shade->setCanClose(false);
  944. }
  945. else
  946. {
  947. //HACK: make this a property of the notification itself, "cancellable"
  948. shade->setCanClose(false);
  949. shade->setTextColor(LLUIColorTable::instance().getColor("LabelTextColor"));
  950. }
  951. mWindowShade->show(notify);
  952. }
  953. void LLMediaCtrl::hideNotification()
  954. {
  955. if (mWindowShade)
  956. {
  957. mWindowShade->hide();
  958. }
  959. }
  960. void LLMediaCtrl::setTrustedContent(bool trusted)
  961. {
  962. mTrusted = trusted;
  963. if (mMediaSource)
  964. {
  965. mMediaSource->setTrustedBrowser(trusted);
  966. }
  967. }