1327 lines
38 KiB
C++
1327 lines
38 KiB
C++
/**
|
|
* @file LLMediaCtrl.cpp
|
|
* @brief Web browser UI control
|
|
*
|
|
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
|
|
* Second Life Viewer Source Code
|
|
* Copyright (C) 2010, Linden Research, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation;
|
|
* version 2.1 of the License only.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#include "llviewerprecompiledheaders.h"
|
|
#include "lltooltip.h"
|
|
|
|
#include "llmediactrl.h"
|
|
|
|
// viewer includes
|
|
#include "llfloaterworldmap.h"
|
|
#include "lluictrlfactory.h"
|
|
#include "llurldispatcher.h"
|
|
#include "llviewborder.h"
|
|
#include "llviewercontrol.h"
|
|
#include "llviewermedia.h"
|
|
#include "llviewertexture.h"
|
|
#include "llviewerwindow.h"
|
|
#include "lldebugmessagebox.h"
|
|
#include "llweb.h"
|
|
#include "llrender.h"
|
|
#include "llpluginclassmedia.h"
|
|
#include "llslurl.h"
|
|
#include "lluictrlfactory.h" // LLDefaultChildRegistry
|
|
#include "llkeyboard.h"
|
|
#include "llviewermenu.h"
|
|
#include "llviewermenufile.h" // LLFilePickerThread
|
|
|
|
// <FS:Zi> IME - International input compositing, i.e. for Japanese / Chinese text input
|
|
#if LL_SDL2
|
|
#include "llwindow.h"
|
|
#endif
|
|
// </FS:Zi>
|
|
|
|
// linden library includes
|
|
#include "llfocusmgr.h"
|
|
#include "llsdutil.h"
|
|
#include "lllayoutstack.h"
|
|
#include "lliconctrl.h"
|
|
#include "llhttpconstants.h"
|
|
#include "lltextbox.h"
|
|
#include "llbutton.h"
|
|
#include "llcheckboxctrl.h"
|
|
#include "llnotifications.h"
|
|
#include "llnotificationsutil.h"
|
|
#include "lllineeditor.h"
|
|
#include "llfloaterwebcontent.h"
|
|
#include "llwindowshade.h"
|
|
|
|
extern bool gRestoreGL;
|
|
|
|
static LLDefaultChildRegistry::Register<LLMediaCtrl> r("web_browser");
|
|
|
|
LLMediaCtrl::Params::Params()
|
|
: start_url("start_url"),
|
|
border_visible("border_visible", true),
|
|
decouple_texture_size("decouple_texture_size", false),
|
|
texture_width("texture_width", 1024),
|
|
texture_height("texture_height", 1024),
|
|
caret_color("caret_color"),
|
|
initial_mime_type("initial_mime_type"),
|
|
error_page_url("error_page_url"),
|
|
media_id("media_id"),
|
|
trusted_content("trusted_content", false),
|
|
focus_on_click("focus_on_click", true)
|
|
{
|
|
}
|
|
|
|
LLMediaCtrl::LLMediaCtrl( const Params& p) :
|
|
LLPanel( p ),
|
|
LLInstanceTracker<LLMediaCtrl, LLUUID>(LLUUID::generateNewID()),
|
|
mTextureDepthBytes( 4 ),
|
|
mBorder(NULL),
|
|
mFrequentUpdates( true ),
|
|
mForceUpdate( false ),
|
|
mHomePageUrl( "" ),
|
|
mAlwaysRefresh( false ),
|
|
mMediaSource( 0 ),
|
|
mTakeFocusOnClick( p.focus_on_click ),
|
|
mCurrentNavUrl( "" ),
|
|
mStretchToFill( true ),
|
|
mMaintainAspectRatio ( true ),
|
|
mDecoupleTextureSize ( false ),
|
|
mUpdateScrolls( false ),
|
|
mTextureWidth ( 1024 ),
|
|
mTextureHeight ( 1024 ),
|
|
mClearCache(false),
|
|
mHomePageMimeType(p.initial_mime_type),
|
|
mErrorPageURL(p.error_page_url),
|
|
mTrusted(p.trusted_content),
|
|
mWindowShade(NULL),
|
|
mHoverTextChanged(false),
|
|
mAllowFileDownload(false)
|
|
{
|
|
{
|
|
LLColor4 color = p.caret_color().get();
|
|
setCaretColor( (unsigned int)color.mV[0], (unsigned int)color.mV[1], (unsigned int)color.mV[2] );
|
|
}
|
|
|
|
setHomePageUrl(p.start_url, p.initial_mime_type);
|
|
|
|
setBorderVisible(p.border_visible);
|
|
|
|
setDecoupleTextureSize(p.decouple_texture_size);
|
|
|
|
setTextureSize(p.texture_width, p.texture_height);
|
|
|
|
if(!getDecoupleTextureSize())
|
|
{
|
|
S32 screen_width = ll_round((F32)getRect().getWidth() * LLUI::getScaleFactor().mV[VX]);
|
|
S32 screen_height = ll_round((F32)getRect().getHeight() * LLUI::getScaleFactor().mV[VY]);
|
|
|
|
setTextureSize(screen_width, screen_height);
|
|
}
|
|
|
|
mMediaTextureID = getKey();
|
|
|
|
// We don't need to create the media source up front anymore unless we have a non-empty home URL to navigate to.
|
|
if(!mHomePageUrl.empty())
|
|
{
|
|
navigateHome();
|
|
}
|
|
|
|
LLWindowShade::Params params;
|
|
params.name = "notification_shade";
|
|
params.rect = getLocalRect();
|
|
params.follows.flags = FOLLOWS_ALL;
|
|
params.modal = true;
|
|
|
|
mWindowShade = LLUICtrlFactory::create<LLWindowShade>(params);
|
|
|
|
addChild(mWindowShade);
|
|
}
|
|
|
|
LLMediaCtrl::~LLMediaCtrl()
|
|
{
|
|
auto menu = mContextMenuHandle.get();
|
|
if (menu)
|
|
{
|
|
menu->die();
|
|
mContextMenuHandle.markDead();
|
|
}
|
|
|
|
if (mMediaSource)
|
|
{
|
|
mMediaSource->remObserver( this );
|
|
mMediaSource = NULL;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
void LLMediaCtrl::setBorderVisible( bool border_visible )
|
|
{
|
|
if ( mBorder )
|
|
{
|
|
mBorder->setVisible( border_visible );
|
|
};
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
void LLMediaCtrl::setTakeFocusOnClick( bool take_focus )
|
|
{
|
|
mTakeFocusOnClick = take_focus;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
bool LLMediaCtrl::handleHover( S32 x, S32 y, MASK mask )
|
|
{
|
|
if (LLPanel::handleHover(x, y, mask)) return true;
|
|
convertInputCoords(x, y);
|
|
|
|
if (mMediaSource)
|
|
{
|
|
mMediaSource->mouseMove(x, y, mask);
|
|
gViewerWindow->setCursor(mMediaSource->getLastSetCursor());
|
|
}
|
|
|
|
// TODO: Is this the right way to handle hover text changes driven by the plugin?
|
|
if(mHoverTextChanged)
|
|
{
|
|
mHoverTextChanged = false;
|
|
handleToolTip(x, y, mask);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
bool LLMediaCtrl::handleScrollWheel( S32 x, S32 y, S32 clicks )
|
|
{
|
|
if (LLPanel::handleScrollWheel(x, y, clicks)) return true;
|
|
if (mMediaSource && mMediaSource->hasMedia())
|
|
{
|
|
convertInputCoords(x, y);
|
|
mMediaSource->scrollWheel(x, y, 0, clicks, gKeyboard->currentMask(true));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
bool LLMediaCtrl::handleScrollHWheel(S32 x, S32 y, S32 clicks)
|
|
{
|
|
if (LLPanel::handleScrollHWheel(x, y, clicks)) return true;
|
|
if (mMediaSource && mMediaSource->hasMedia())
|
|
{
|
|
convertInputCoords(x, y);
|
|
mMediaSource->scrollWheel(x, y, clicks, 0, gKeyboard->currentMask(true));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// virtual
|
|
bool LLMediaCtrl::handleToolTip(S32 x, S32 y, MASK mask)
|
|
{
|
|
std::string hover_text;
|
|
|
|
if (mMediaSource && mMediaSource->hasMedia())
|
|
hover_text = mMediaSource->getMediaPlugin()->getHoverText();
|
|
|
|
if(hover_text.empty())
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
S32 screen_x, screen_y;
|
|
|
|
localPointToScreen(x, y, &screen_x, &screen_y);
|
|
LLRect sticky_rect_screen;
|
|
sticky_rect_screen.setCenterAndSize(screen_x, screen_y, 20, 20);
|
|
|
|
LLToolTipMgr::instance().show(LLToolTip::Params()
|
|
.message(hover_text)
|
|
.sticky_rect(sticky_rect_screen));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
bool LLMediaCtrl::handleMouseUp( S32 x, S32 y, MASK mask )
|
|
{
|
|
if (LLPanel::handleMouseUp(x, y, mask)) return true;
|
|
convertInputCoords(x, y);
|
|
|
|
if (mMediaSource)
|
|
{
|
|
mMediaSource->mouseUp(x, y, mask);
|
|
}
|
|
|
|
gFocusMgr.setMouseCapture( NULL );
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
bool LLMediaCtrl::handleMouseDown( S32 x, S32 y, MASK mask )
|
|
{
|
|
if (LLPanel::handleMouseDown(x, y, mask)) return true;
|
|
convertInputCoords(x, y);
|
|
|
|
if (mMediaSource)
|
|
mMediaSource->mouseDown(x, y, mask);
|
|
|
|
gFocusMgr.setMouseCapture( this );
|
|
|
|
if (mTakeFocusOnClick)
|
|
{
|
|
setFocus( true );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
bool LLMediaCtrl::handleRightMouseUp( S32 x, S32 y, MASK mask )
|
|
{
|
|
if (LLPanel::handleRightMouseUp(x, y, mask)) return true;
|
|
convertInputCoords(x, y);
|
|
|
|
if (mMediaSource)
|
|
{
|
|
mMediaSource->mouseUp(x, y, mask, 1);
|
|
|
|
// *HACK: LLMediaImplLLMozLib automatically takes focus on mouseup,
|
|
// in addition to the onFocusReceived() call below. Undo this. JC
|
|
if (!mTakeFocusOnClick)
|
|
{
|
|
mMediaSource->focus(false);
|
|
gViewerWindow->focusClient();
|
|
}
|
|
}
|
|
|
|
gFocusMgr.setMouseCapture( NULL );
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
bool LLMediaCtrl::handleRightMouseDown( S32 x, S32 y, MASK mask )
|
|
{
|
|
if (LLPanel::handleRightMouseDown(x, y, mask)) return true;
|
|
|
|
S32 media_x = x, media_y = y;
|
|
convertInputCoords(media_x, media_y);
|
|
|
|
if (mMediaSource)
|
|
mMediaSource->mouseDown(media_x, media_y, mask, 1);
|
|
|
|
gFocusMgr.setMouseCapture( this );
|
|
|
|
if (mTakeFocusOnClick)
|
|
{
|
|
setFocus( true );
|
|
}
|
|
|
|
auto menu = mContextMenuHandle.get();
|
|
if (!menu)
|
|
{
|
|
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registar;
|
|
registar.add("Open.WebInspector", boost::bind(&LLMediaCtrl::onOpenWebInspector, this));
|
|
|
|
// stinson 05/05/2014 : use this as the parent of the context menu if the static menu
|
|
// container has yet to be created
|
|
LLPanel* menuParent = (LLMenuGL::sMenuContainer != NULL) ? dynamic_cast<LLPanel*>(LLMenuGL::sMenuContainer) : dynamic_cast<LLPanel*>(this);
|
|
llassert(menuParent != NULL);
|
|
menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
|
|
"menu_media_ctrl.xml", menuParent, LLViewerMenuHolderGL::child_registry_t::instance());
|
|
if (menu)
|
|
{
|
|
mContextMenuHandle = menu->getHandle();
|
|
}
|
|
}
|
|
|
|
if (menu)
|
|
{
|
|
// hide/show debugging options
|
|
bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging");
|
|
menu->setItemVisible("open_webinspector", media_plugin_debugging_enabled );
|
|
menu->setItemVisible("debug_separator", media_plugin_debugging_enabled );
|
|
|
|
menu->show(x, y);
|
|
LLMenuGL::showPopup(this, menu, x, y);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
bool LLMediaCtrl::handleDoubleClick( S32 x, S32 y, MASK mask )
|
|
{
|
|
if (LLPanel::handleDoubleClick(x, y, mask)) return true;
|
|
convertInputCoords(x, y);
|
|
|
|
if (mMediaSource)
|
|
mMediaSource->mouseDoubleClick( x, y, mask);
|
|
|
|
gFocusMgr.setMouseCapture( this );
|
|
|
|
if (mTakeFocusOnClick)
|
|
{
|
|
setFocus( true );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
void LLMediaCtrl::onFocusReceived()
|
|
{
|
|
if (mMediaSource)
|
|
{
|
|
mMediaSource->focus(true);
|
|
|
|
// Set focus for edit menu items
|
|
LLEditMenuHandler::gEditMenuHandler = mMediaSource;
|
|
}
|
|
|
|
LLPanel::onFocusReceived();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
void LLMediaCtrl::onFocusLost()
|
|
{
|
|
if (mMediaSource)
|
|
{
|
|
mMediaSource->focus(false);
|
|
|
|
if( LLEditMenuHandler::gEditMenuHandler == mMediaSource )
|
|
{
|
|
// Clear focus for edit menu items
|
|
LLEditMenuHandler::gEditMenuHandler = NULL;
|
|
}
|
|
}
|
|
|
|
gViewerWindow->focusClient();
|
|
|
|
LLPanel::onFocusLost();
|
|
}
|
|
|
|
// Ansariel: Workaround for FIRE-3814:
|
|
// Explicitely call the according event handlers
|
|
// so the context menu is shown properly.
|
|
// This might go away later.
|
|
void LLMediaCtrl::setFocus(bool b)
|
|
{
|
|
// <FS:Zi> IME - International input compositing, i.e. for Japanese / Chinese text input
|
|
#if LL_SDL2
|
|
// IME - International input compositing, i.e. for Japanese / Chinese text input
|
|
|
|
// Caveat: we currently don't know the position of the input cursor inside the
|
|
// media control box, so the IME will pop up somewhere at the top instead,
|
|
// which is not ideal and needs more research
|
|
|
|
if (b)
|
|
{
|
|
// Make sure the IME is in the right place, on top of the input line
|
|
LLRect screen_pos = calcScreenRect();
|
|
LLCoordGL ime_pos(screen_pos.mLeft, screen_pos.mTop + gSavedSettings.getS32("SDL2IMEMediaVerticalOffset"));
|
|
|
|
// shift by a few pixels so the IME doesn't pop to the left side when the nedia
|
|
// control is very close to the left edge
|
|
ime_pos.mX = (S32) (ime_pos.mX * LLUI::getScaleFactor().mV[VX]) + 5;
|
|
ime_pos.mY = (S32) (ime_pos.mY * LLUI::getScaleFactor().mV[VY]);
|
|
|
|
getWindow()->setLanguageTextInput(ime_pos);
|
|
}
|
|
|
|
// this floater is not an LLPreeditor but we are only interested in the pointer anyway
|
|
// so hopefully we will get away with this
|
|
getWindow()->allowLanguageTextInput((LLPreeditor*) this, b);
|
|
#endif
|
|
// </FS:Zi>
|
|
|
|
if (b)
|
|
{
|
|
onFocusReceived();
|
|
}
|
|
else
|
|
{
|
|
onFocusLost();
|
|
}
|
|
LLPanel::setFocus(b);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
bool LLMediaCtrl::postBuild ()
|
|
{
|
|
setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChanged, this, _2));
|
|
|
|
return true;
|
|
}
|
|
|
|
void LLMediaCtrl::onOpenWebInspector()
|
|
{
|
|
if (mMediaSource && mMediaSource->hasMedia())
|
|
mMediaSource->getMediaPlugin()->showWebInspector( true );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
bool LLMediaCtrl::handleKeyHere( KEY key, MASK mask )
|
|
{
|
|
bool result = false;
|
|
|
|
if (mMediaSource)
|
|
{
|
|
result = mMediaSource->handleKeyHere(key, mask);
|
|
}
|
|
|
|
if ( ! result )
|
|
result = LLPanel::handleKeyHere(key, mask);
|
|
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
bool LLMediaCtrl::handleKeyUpHere(KEY key, MASK mask)
|
|
{
|
|
bool result = false;
|
|
|
|
if (mMediaSource)
|
|
{
|
|
result = mMediaSource->handleKeyUpHere(key, mask);
|
|
}
|
|
|
|
if (!result)
|
|
result = LLPanel::handleKeyUpHere(key, mask);
|
|
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
void LLMediaCtrl::onVisibilityChange ( bool new_visibility )
|
|
{
|
|
LL_INFOS() << "visibility changed to " << (new_visibility?"true":"false") << LL_ENDL;
|
|
if(mMediaSource)
|
|
{
|
|
mMediaSource->setVisible( new_visibility );
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
bool LLMediaCtrl::handleUnicodeCharHere(llwchar uni_char)
|
|
{
|
|
bool result = false;
|
|
|
|
if (mMediaSource)
|
|
{
|
|
result = mMediaSource->handleUnicodeCharHere(uni_char);
|
|
}
|
|
|
|
if ( ! result )
|
|
result = LLPanel::handleUnicodeCharHere(uni_char);
|
|
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
void LLMediaCtrl::onVisibilityChanged ( const LLSD& new_visibility )
|
|
{
|
|
// set state of frequent updates automatically if visibility changes
|
|
if ( new_visibility.asBoolean() )
|
|
{
|
|
mFrequentUpdates = true;
|
|
}
|
|
else
|
|
{
|
|
mFrequentUpdates = false;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
void LLMediaCtrl::reshape( S32 width, S32 height, bool called_from_parent )
|
|
{
|
|
if(!getDecoupleTextureSize())
|
|
{
|
|
S32 screen_width = ll_round((F32)width * LLUI::getScaleFactor().mV[VX]);
|
|
S32 screen_height = ll_round((F32)height * LLUI::getScaleFactor().mV[VY]);
|
|
|
|
// when floater is minimized, these sizes are negative
|
|
if ( screen_height > 0 && screen_width > 0 )
|
|
{
|
|
setTextureSize(screen_width, screen_height);
|
|
}
|
|
}
|
|
|
|
LLUICtrl::reshape( width, height, called_from_parent );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
void LLMediaCtrl::navigateBack()
|
|
{
|
|
if (mMediaSource && mMediaSource->hasMedia())
|
|
{
|
|
mMediaSource->getMediaPlugin()->browse_back();
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
void LLMediaCtrl::navigateForward()
|
|
{
|
|
if (mMediaSource && mMediaSource->hasMedia())
|
|
{
|
|
mMediaSource->getMediaPlugin()->browse_forward();
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
void LLMediaCtrl::navigateStop()
|
|
{
|
|
if (mMediaSource && mMediaSource->hasMedia())
|
|
{
|
|
mMediaSource->getMediaPlugin()->browse_stop();
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
bool LLMediaCtrl::canNavigateBack()
|
|
{
|
|
if (mMediaSource)
|
|
return mMediaSource->canNavigateBack();
|
|
else
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
bool LLMediaCtrl::canNavigateForward()
|
|
{
|
|
if (mMediaSource)
|
|
return mMediaSource->canNavigateForward();
|
|
else
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
void LLMediaCtrl::clearCache()
|
|
{
|
|
if(mMediaSource)
|
|
{
|
|
mMediaSource->clearCache();
|
|
}
|
|
else
|
|
{
|
|
mClearCache = true;
|
|
}
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type, bool clean_browser)
|
|
{
|
|
// <AW>
|
|
// don't browse to slurls like "secondlife://" or "hop://"
|
|
LLSLURL is_slurl(url_in);
|
|
if(LLSLURL::INVALID != is_slurl.getType())
|
|
// </AW>
|
|
{
|
|
// TODO: Print out/log this attempt?
|
|
// LL_INFOS() << "Rejecting attempt to load restricted website :" << urlIn << LL_ENDL;
|
|
return;
|
|
}
|
|
|
|
if (ensureMediaSourceExists())
|
|
{
|
|
mCurrentNavUrl = url_in;
|
|
mMediaSource->setSize(mTextureWidth, mTextureHeight);
|
|
mMediaSource->navigateTo(url_in, mime_type, mime_type.empty(), false, clean_browser);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
void LLMediaCtrl::navigateToLocalPage( const std::string& subdir, const std::string& filename_in )
|
|
{
|
|
std::string filename(gDirUtilp->add(subdir, filename_in));
|
|
std::string expanded_filename = gDirUtilp->findSkinnedFilename("html", filename);
|
|
|
|
if (expanded_filename.empty())
|
|
{
|
|
LL_WARNS() << "File " << filename << "not found" << LL_ENDL;
|
|
return;
|
|
}
|
|
if (ensureMediaSourceExists())
|
|
{
|
|
mCurrentNavUrl = expanded_filename;
|
|
mMediaSource->setSize(mTextureWidth, mTextureHeight);
|
|
mMediaSource->navigateTo(expanded_filename, HTTP_CONTENT_TEXT_HTML, false);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
void LLMediaCtrl::navigateHome()
|
|
{
|
|
if (ensureMediaSourceExists())
|
|
{
|
|
mMediaSource->setSize(mTextureWidth, mTextureHeight);
|
|
mMediaSource->navigateHome();
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
void LLMediaCtrl::setHomePageUrl( const std::string& urlIn, const std::string& mime_type )
|
|
{
|
|
mHomePageUrl = urlIn;
|
|
if (mMediaSource)
|
|
{
|
|
mMediaSource->setHomeURL(mHomePageUrl, mime_type);
|
|
}
|
|
}
|
|
|
|
void LLMediaCtrl::setTarget(const std::string& target)
|
|
{
|
|
mTarget = target;
|
|
if (mMediaSource)
|
|
{
|
|
mMediaSource->setTarget(mTarget);
|
|
}
|
|
}
|
|
|
|
void LLMediaCtrl::setErrorPageURL(const std::string& url)
|
|
{
|
|
mErrorPageURL = url;
|
|
}
|
|
|
|
const std::string& LLMediaCtrl::getErrorPageURL()
|
|
{
|
|
return mErrorPageURL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
bool LLMediaCtrl::setCaretColor(unsigned int red, unsigned int green, unsigned int blue)
|
|
{
|
|
//NOOP
|
|
return false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
void LLMediaCtrl::setTextureSize(S32 width, S32 height)
|
|
{
|
|
mTextureWidth = width;
|
|
mTextureHeight = height;
|
|
|
|
if(mMediaSource)
|
|
{
|
|
mMediaSource->setSize(mTextureWidth, mTextureHeight);
|
|
mForceUpdate = true;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
std::string LLMediaCtrl::getHomePageUrl()
|
|
{
|
|
return mHomePageUrl;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
bool LLMediaCtrl::ensureMediaSourceExists()
|
|
{
|
|
if(mMediaSource.isNull())
|
|
{
|
|
// If we don't already have a media source, try to create one.
|
|
mMediaSource = LLViewerMedia::getInstance()->newMediaImpl(mMediaTextureID, mTextureWidth, mTextureHeight);
|
|
if ( mMediaSource )
|
|
{
|
|
mMediaSource->setUsedInUI(true);
|
|
mMediaSource->setHomeURL(mHomePageUrl, mHomePageMimeType);
|
|
mMediaSource->setTarget(mTarget);
|
|
mMediaSource->setVisible( getVisible() );
|
|
mMediaSource->addObserver( this );
|
|
mMediaSource->setBackgroundColor( getBackgroundColor() );
|
|
mMediaSource->setTrustedBrowser(mTrusted);
|
|
|
|
F32 scale_factor = LLUI::getScaleFactor().mV[ VX ];
|
|
if (scale_factor != mMediaSource->getPageZoomFactor())
|
|
{
|
|
mMediaSource->setPageZoomFactor( scale_factor );
|
|
mUpdateScrolls = true;
|
|
}
|
|
|
|
if(mClearCache)
|
|
{
|
|
mMediaSource->clearCache();
|
|
mClearCache = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LL_WARNS() << "media source create failed " << LL_ENDL;
|
|
// return;
|
|
}
|
|
}
|
|
|
|
return !mMediaSource.isNull();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
void LLMediaCtrl::unloadMediaSource()
|
|
{
|
|
mMediaSource = NULL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
LLPluginClassMedia* LLMediaCtrl::getMediaPlugin()
|
|
{
|
|
return mMediaSource.isNull() ? NULL : mMediaSource->getMediaPlugin();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
void LLMediaCtrl::draw()
|
|
{
|
|
F32 alpha = getDrawContext().mAlpha;
|
|
|
|
if ( gRestoreGL == 1 || mUpdateScrolls)
|
|
{
|
|
LLRect r = getRect();
|
|
reshape( r.getWidth(), r.getHeight(), false );
|
|
mUpdateScrolls = false;
|
|
return;
|
|
}
|
|
|
|
// NOTE: optimization needed here - probably only need to do this once
|
|
// unless tearoffs change the parent which they probably do.
|
|
const LLUICtrl* ptr = findRootMostFocusRoot();
|
|
if ( ptr && ptr->hasFocus() )
|
|
{
|
|
setFrequentUpdates( true );
|
|
}
|
|
else
|
|
{
|
|
setFrequentUpdates( false );
|
|
};
|
|
|
|
bool draw_media = false;
|
|
|
|
LLPluginClassMedia* media_plugin = NULL;
|
|
LLViewerMediaTexture* media_texture = NULL;
|
|
|
|
if(mMediaSource && mMediaSource->hasMedia())
|
|
{
|
|
media_plugin = mMediaSource->getMediaPlugin();
|
|
|
|
if(media_plugin && (media_plugin->textureValid()))
|
|
{
|
|
media_texture = LLViewerTextureManager::findMediaTexture(mMediaTextureID);
|
|
if(media_texture)
|
|
{
|
|
draw_media = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool background_visible = isBackgroundVisible();
|
|
bool background_opaque = isBackgroundOpaque();
|
|
|
|
if(draw_media)
|
|
{
|
|
gGL.pushUIMatrix();
|
|
{
|
|
F32 scale_factor = LLUI::getScaleFactor().mV[ VX ];
|
|
if (scale_factor != mMediaSource->getPageZoomFactor())
|
|
{
|
|
mMediaSource->setPageZoomFactor( scale_factor );
|
|
mUpdateScrolls = true;
|
|
}
|
|
|
|
// scale texture to fit the space using texture coords
|
|
gGL.getTexUnit(0)->bind(media_texture);
|
|
LLColor4 media_color = LLColor4::white % alpha;
|
|
gGL.color4fv( media_color.mV );
|
|
F32 max_u = ( F32 )media_plugin->getWidth() / ( F32 )media_plugin->getTextureWidth();
|
|
F32 max_v = ( F32 )media_plugin->getHeight() / ( F32 )media_plugin->getTextureHeight();
|
|
|
|
S32 x_offset, y_offset, width, height;
|
|
calcOffsetsAndSize(&x_offset, &y_offset, &width, &height);
|
|
|
|
// draw the browser
|
|
// <FS:Ansariel> Remove QUADS rendering mode
|
|
//gGL.begin( LLRender::QUADS );
|
|
gGL.begin( LLRender::TRIANGLES );
|
|
// </FS:Ansariel>
|
|
if (! media_plugin->getTextureCoordsOpenGL())
|
|
{
|
|
// render using web browser reported width and height, instead of trying to invert GL scale
|
|
gGL.texCoord2f( max_u, 0.f );
|
|
gGL.vertex2i( x_offset + width, y_offset + height );
|
|
|
|
gGL.texCoord2f( 0.f, 0.f );
|
|
gGL.vertex2i( x_offset, y_offset + height );
|
|
|
|
gGL.texCoord2f( 0.f, max_v );
|
|
gGL.vertex2i( x_offset, y_offset );
|
|
|
|
// <FS:Ansariel> Remove QUADS rendering mode
|
|
gGL.texCoord2f( max_u, 0.f );
|
|
gGL.vertex2i( x_offset + width, y_offset + height );
|
|
|
|
gGL.texCoord2f( 0.f, max_v );
|
|
gGL.vertex2i( x_offset, y_offset );
|
|
// </FS:Ansariel>
|
|
|
|
gGL.texCoord2f( max_u, max_v );
|
|
gGL.vertex2i( x_offset + width, y_offset );
|
|
}
|
|
else
|
|
{
|
|
// render using web browser reported width and height, instead of trying to invert GL scale
|
|
gGL.texCoord2f( max_u, max_v );
|
|
gGL.vertex2i( x_offset + width, y_offset + height );
|
|
|
|
gGL.texCoord2f( 0.f, max_v );
|
|
gGL.vertex2i( x_offset, y_offset + height );
|
|
|
|
gGL.texCoord2f( 0.f, 0.f );
|
|
gGL.vertex2i( x_offset, y_offset );
|
|
|
|
// <FS:Ansariel> Remove QUADS rendering mode
|
|
gGL.texCoord2f( max_u, max_v );
|
|
gGL.vertex2i( x_offset + width, y_offset + height );
|
|
|
|
gGL.texCoord2f( 0.f, 0.f );
|
|
gGL.vertex2i( x_offset, y_offset );
|
|
// </FS:Ansariel>
|
|
|
|
gGL.texCoord2f( max_u, 0.f );
|
|
gGL.vertex2i( x_offset + width, y_offset );
|
|
}
|
|
gGL.end();
|
|
}
|
|
gGL.popUIMatrix();
|
|
|
|
}
|
|
else
|
|
{
|
|
// Setting these will make LLPanel::draw draw the opaque background color.
|
|
setBackgroundVisible(true);
|
|
setBackgroundOpaque(true);
|
|
}
|
|
|
|
// highlight if keyboard focus here. (TODO: this needs some work)
|
|
if ( mBorder && mBorder->getVisible() )
|
|
mBorder->setKeyboardFocusHighlight( gFocusMgr.childHasKeyboardFocus( this ) );
|
|
|
|
LLPanel::draw();
|
|
|
|
// Restore the previous values
|
|
setBackgroundVisible(background_visible);
|
|
setBackgroundOpaque(background_opaque);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
void LLMediaCtrl::calcOffsetsAndSize(S32 *x_offset, S32 *y_offset, S32 *width, S32 *height)
|
|
{
|
|
const LLRect &r = getRect();
|
|
*x_offset = *y_offset = 0;
|
|
|
|
if (mStretchToFill)
|
|
{
|
|
if (mMaintainAspectRatio && mMediaSource && mMediaSource->getMediaPlugin())
|
|
{
|
|
F32 media_aspect = (F32)(mMediaSource->getMediaPlugin()->getWidth()) / (F32)(mMediaSource->getMediaPlugin()->getHeight());
|
|
F32 view_aspect = (F32)(r.getWidth()) / (F32)(r.getHeight());
|
|
if (media_aspect > view_aspect)
|
|
{
|
|
// max width, adjusted height
|
|
*width = r.getWidth();
|
|
*height = llmin(llmax(ll_round(*width / media_aspect), 0), r.getHeight());
|
|
}
|
|
else
|
|
{
|
|
// max height, adjusted width
|
|
*height = r.getHeight();
|
|
*width = llmin(llmax(ll_round(*height * media_aspect), 0), r.getWidth());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*width = r.getWidth();
|
|
*height = r.getHeight();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*width = llmin(mMediaSource->getMediaPlugin()->getWidth(), r.getWidth());
|
|
*height = llmin(mMediaSource->getMediaPlugin()->getHeight(), r.getHeight());
|
|
}
|
|
|
|
*x_offset = (r.getWidth() - *width) / 2;
|
|
*y_offset = (r.getHeight() - *height) / 2;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
void LLMediaCtrl::convertInputCoords(S32& x, S32& y)
|
|
{
|
|
S32 x_offset, y_offset, width, height;
|
|
calcOffsetsAndSize(&x_offset, &y_offset, &width, &height);
|
|
|
|
x -= x_offset;
|
|
y -= y_offset;
|
|
|
|
bool coords_opengl = false;
|
|
|
|
if(mMediaSource && mMediaSource->hasMedia())
|
|
{
|
|
coords_opengl = mMediaSource->getMediaPlugin()->getTextureCoordsOpenGL();
|
|
}
|
|
|
|
x = ll_round((F32)x * LLUI::getScaleFactor().mV[VX]);
|
|
if ( ! coords_opengl )
|
|
{
|
|
y = ll_round((F32)(y) * LLUI::getScaleFactor().mV[VY]);
|
|
}
|
|
else
|
|
{
|
|
y = ll_round((F32)(getRect().getHeight() - y) * LLUI::getScaleFactor().mV[VY]);
|
|
};
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// inherited from LLViewerMediaObserver
|
|
//virtual
|
|
void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
|
|
{
|
|
switch(event)
|
|
{
|
|
case MEDIA_EVENT_CONTENT_UPDATED:
|
|
{
|
|
// LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CONTENT_UPDATED " << LL_ENDL;
|
|
};
|
|
break;
|
|
|
|
case MEDIA_EVENT_TIME_DURATION_UPDATED:
|
|
{
|
|
// LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_TIME_DURATION_UPDATED, time is " << self->getCurrentTime() << " of " << self->getDuration() << LL_ENDL;
|
|
};
|
|
break;
|
|
|
|
case MEDIA_EVENT_SIZE_CHANGED:
|
|
{
|
|
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_SIZE_CHANGED " << LL_ENDL;
|
|
LLRect r = getRect();
|
|
reshape( r.getWidth(), r.getHeight(), false );
|
|
};
|
|
break;
|
|
|
|
case MEDIA_EVENT_CURSOR_CHANGED:
|
|
{
|
|
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << self->getCursorName() << LL_ENDL;
|
|
}
|
|
break;
|
|
|
|
case MEDIA_EVENT_NAVIGATE_BEGIN:
|
|
{
|
|
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_BEGIN, url is " << self->getNavigateURI() << LL_ENDL;
|
|
hideNotification();
|
|
};
|
|
break;
|
|
|
|
case MEDIA_EVENT_NAVIGATE_COMPLETE:
|
|
{
|
|
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_COMPLETE, result string is: " << self->getNavigateResultString() << LL_ENDL;
|
|
if(mHidingInitialLoad)
|
|
{
|
|
mHidingInitialLoad = false;
|
|
}
|
|
};
|
|
break;
|
|
|
|
case MEDIA_EVENT_PROGRESS_UPDATED:
|
|
{
|
|
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PROGRESS_UPDATED, loading at " << self->getProgressPercent() << "%" << LL_ENDL;
|
|
};
|
|
break;
|
|
|
|
case MEDIA_EVENT_STATUS_TEXT_CHANGED:
|
|
{
|
|
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_STATUS_TEXT_CHANGED, new status text is: " << self->getStatusText() << LL_ENDL;
|
|
};
|
|
break;
|
|
|
|
case MEDIA_EVENT_LOCATION_CHANGED:
|
|
{
|
|
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_LOCATION_CHANGED, new uri is: " << self->getLocation() << LL_ENDL;
|
|
};
|
|
break;
|
|
|
|
case MEDIA_EVENT_NAVIGATE_ERROR_PAGE:
|
|
{
|
|
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_ERROR_PAGE" << LL_ENDL;
|
|
if ( mErrorPageURL.length() > 0 )
|
|
{
|
|
navigateTo(mErrorPageURL, HTTP_CONTENT_TEXT_HTML);
|
|
};
|
|
};
|
|
break;
|
|
|
|
case MEDIA_EVENT_CLICK_LINK_HREF:
|
|
{
|
|
// retrieve the event parameters
|
|
std::string url = self->getClickURL();
|
|
std::string target = self->isOverrideClickTarget() ? self->getOverrideClickTarget() : self->getClickTarget();
|
|
std::string uuid = self->getClickUUID();
|
|
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << target << "\", uri is " << url << LL_ENDL;
|
|
|
|
// try as slurl first
|
|
if (!LLURLDispatcher::dispatch(url, "clicked", NULL, mTrusted))
|
|
{
|
|
LLWeb::loadURL(url, target, uuid);
|
|
}
|
|
|
|
// CP: removing this code because we no longer support popups so this breaks the flow.
|
|
// replaced with a bare call to LLWeb::LoadURL(...)
|
|
//LLNotification::Params notify_params;
|
|
//notify_params.name = "PopupAttempt";
|
|
//notify_params.payload = LLSD().with("target", target).with("url", url).with("uuid", uuid).with("media_id", mMediaTextureID);
|
|
//notify_params.functor.function = boost::bind(&LLMediaCtrl::onPopup, this, _1, _2);
|
|
|
|
//if (mTrusted)
|
|
//{
|
|
// LLNotifications::instance().forceResponse(notify_params, 0);
|
|
//}
|
|
//else
|
|
//{
|
|
// LLNotifications::instance().add(notify_params);
|
|
//}
|
|
break;
|
|
};
|
|
|
|
case MEDIA_EVENT_CLICK_LINK_NOFOLLOW:
|
|
{
|
|
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is " << self->getClickURL() << LL_ENDL;
|
|
};
|
|
break;
|
|
|
|
case MEDIA_EVENT_PLUGIN_FAILED:
|
|
{
|
|
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED" << LL_ENDL;
|
|
};
|
|
break;
|
|
|
|
case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
|
|
{
|
|
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << LL_ENDL;
|
|
};
|
|
break;
|
|
|
|
case MEDIA_EVENT_NAME_CHANGED:
|
|
{
|
|
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAME_CHANGED" << LL_ENDL;
|
|
};
|
|
break;
|
|
|
|
case MEDIA_EVENT_CLOSE_REQUEST:
|
|
{
|
|
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLOSE_REQUEST" << LL_ENDL;
|
|
}
|
|
break;
|
|
|
|
case MEDIA_EVENT_PICK_FILE_REQUEST:
|
|
{
|
|
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PICK_FILE_REQUEST" << LL_ENDL;
|
|
}
|
|
break;
|
|
|
|
case MEDIA_EVENT_GEOMETRY_CHANGE:
|
|
{
|
|
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_GEOMETRY_CHANGE, uuid is " << self->getClickUUID() << LL_ENDL;
|
|
}
|
|
break;
|
|
|
|
case MEDIA_EVENT_AUTH_REQUEST:
|
|
{
|
|
LLNotification::Params auth_request_params;
|
|
auth_request_params.name = "AuthRequest";
|
|
|
|
// pass in host name and realm for site (may be zero length but will always exist)
|
|
LLSD args;
|
|
LLURL raw_url( self->getAuthURL().c_str() );
|
|
args["HOST_NAME"] = raw_url.getAuthority();
|
|
args["REALM"] = self->getAuthRealm();
|
|
auth_request_params.substitutions = args;
|
|
|
|
auth_request_params.payload = LLSD().with("media_id", mMediaTextureID);
|
|
auth_request_params.functor.function = boost::bind(&LLViewerMedia::authSubmitCallback, _1, _2);
|
|
LLNotifications::instance().add(auth_request_params);
|
|
};
|
|
break;
|
|
|
|
case MEDIA_EVENT_LINK_HOVERED:
|
|
{
|
|
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_LINK_HOVERED, hover text is: " << self->getHoverText() << LL_ENDL;
|
|
mHoverTextChanged = true;
|
|
};
|
|
break;
|
|
|
|
case MEDIA_EVENT_FILE_DOWNLOAD:
|
|
{
|
|
if (mAllowFileDownload)
|
|
{
|
|
// pick a file from SAVE FILE dialog
|
|
// for now the only thing that should be allowed to save is 360s
|
|
std::string suggested_filename = self->getFileDownloadFilename();
|
|
LLFilePicker::ESaveFilter filter = LLFilePicker::FFSAVE_ALL;
|
|
if (suggested_filename.find(".jpg") != std::string::npos || suggested_filename.find(".jpeg") != std::string::npos)
|
|
filter = LLFilePicker::FFSAVE_JPEG;
|
|
if (suggested_filename.find(".png") != std::string::npos)
|
|
filter = LLFilePicker::FFSAVE_PNG;
|
|
|
|
(new LLMediaFilePicker(self, filter, suggested_filename))->getFile();
|
|
}
|
|
else
|
|
{
|
|
// Media might be blocked, waiting for a file,
|
|
// send an empty response to unblock it
|
|
const std::vector<std::string> empty_response;
|
|
self->sendPickFileResponse(empty_response);
|
|
|
|
LLNotificationsUtil::add("MediaFileDownloadUnsupported");
|
|
}
|
|
};
|
|
break;
|
|
|
|
case MEDIA_EVENT_DEBUG_MESSAGE:
|
|
{
|
|
LL_INFOS("media") << self->getDebugMessageText() << LL_ENDL;
|
|
};
|
|
break;
|
|
};
|
|
|
|
// chain all events to any potential observers of this object.
|
|
emitEvent(self, event);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
std::string LLMediaCtrl::getCurrentNavUrl()
|
|
{
|
|
return mCurrentNavUrl;
|
|
}
|
|
|
|
void LLMediaCtrl::onPopup(const LLSD& notification, const LLSD& response)
|
|
{
|
|
if (response["open"])
|
|
{
|
|
LLWeb::loadURL(notification["payload"]["url"], notification["payload"]["target"], notification["payload"]["uuid"]);
|
|
}
|
|
else
|
|
{
|
|
// Make sure the opening instance knows its window open request was denied, so it can clean things up.
|
|
LLViewerMedia::getInstance()->proxyWindowClosed(notification["payload"]["uuid"]);
|
|
}
|
|
}
|
|
|
|
void LLMediaCtrl::showNotification(LLNotificationPtr notify)
|
|
{
|
|
LLWindowShade* shade = getChild<LLWindowShade>("notification_shade");
|
|
|
|
if (notify->getIcon() == "Popup_Caution")
|
|
{
|
|
shade->setBackgroundImage(LLUI::getUIImage("Yellow_Gradient"));
|
|
shade->setTextColor(LLColor4::black);
|
|
shade->setCanClose(true);
|
|
}
|
|
else if (notify->getName() == "AuthRequest")
|
|
{
|
|
shade->setBackgroundImage(LLUI::getUIImage("Yellow_Gradient"));
|
|
shade->setTextColor(LLColor4::black);
|
|
shade->setCanClose(false);
|
|
}
|
|
else
|
|
{
|
|
//HACK: make this a property of the notification itself, "cancellable"
|
|
shade->setCanClose(false);
|
|
shade->setTextColor(LLUIColorTable::instance().getColor("LabelTextColor"));
|
|
}
|
|
|
|
mWindowShade->show(notify);
|
|
}
|
|
|
|
void LLMediaCtrl::hideNotification()
|
|
{
|
|
if (mWindowShade)
|
|
{
|
|
mWindowShade->hide();
|
|
}
|
|
}
|
|
|
|
void LLMediaCtrl::setTrustedContent(bool trusted)
|
|
{
|
|
mTrusted = trusted;
|
|
if (mMediaSource)
|
|
{
|
|
mMediaSource->setTrustedBrowser(trusted);
|
|
}
|
|
}
|
|
|
|
bool LLMediaCtrl::wantsKeyUpKeyDown() const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool LLMediaCtrl::wantsReturnKey() const
|
|
{
|
|
return true;
|
|
}
|