diff options
Diffstat (limited to 'indra/newview/llmediactrl.cpp')
-rw-r--r-- | indra/newview/llmediactrl.cpp | 326 |
1 files changed, 285 insertions, 41 deletions
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 7a4ed74c4c..e84c9152b1 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -2,31 +2,25 @@ * @file LLMediaCtrl.cpp * @brief Web browser UI control * - * $LicenseInfo:firstyear=2006&license=viewergpl$ - * - * Copyright (c) 2006-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * 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. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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 * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -44,7 +38,6 @@ #include "llviewermedia.h" #include "llviewertexture.h" #include "llviewerwindow.h" -#include "llnotificationsutil.h" #include "llweb.h" #include "llrender.h" #include "llpluginclassmedia.h" @@ -54,6 +47,13 @@ // linden library includes #include "llfocusmgr.h" +#include "llsdutil.h" +#include "lllayoutstack.h" +#include "lliconctrl.h" +#include "lltextbox.h" +#include "llbutton.h" +#include "llcheckboxctrl.h" +#include "llnotifications.h" extern BOOL gRestoreGL; @@ -67,19 +67,22 @@ LLMediaCtrl::Params::Params() decouple_texture_size("decouple_texture_size", false), texture_width("texture_width", 1024), texture_height("texture_height", 1024), - caret_color("caret_color") + caret_color("caret_color"), + initial_mime_type("initial_mime_type"), + media_id("media_id"), + trusted_content("trusted_content", false) { tab_stop(false); } LLMediaCtrl::LLMediaCtrl( const Params& p) : LLPanel( p ), + LLInstanceTracker<LLMediaCtrl, LLUUID>(LLUUID::generateNewID()), mTextureDepthBytes( 4 ), mBorder(NULL), mFrequentUpdates( true ), mForceUpdate( false ), mHomePageUrl( "" ), - mTrusted(false), mIgnoreUIScale( true ), mAlwaysRefresh( false ), mMediaSource( 0 ), @@ -92,7 +95,9 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : mDecoupleTextureSize ( false ), mTextureWidth ( 1024 ), mTextureHeight ( 1024 ), - mClearCache(false) + mClearCache(false), + mHomePageMimeType(p.initial_mime_type), + mTrusted(p.trusted_content) { { LLColor4 color = p.caret_color().get(); @@ -101,7 +106,7 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : setIgnoreUIScale(p.ignore_ui_scale); - setHomePageUrl(p.start_url); + setHomePageUrl(p.start_url, p.initial_mime_type); setBorderVisible(p.border_visible); @@ -165,19 +170,10 @@ void LLMediaCtrl::setTakeFocusOnClick( bool take_focus ) } //////////////////////////////////////////////////////////////////////////////// -void LLMediaCtrl::setTrusted( bool valIn ) -{ - if(mMediaSource) - { - mMediaSource->setTrustedBrowser(valIn); - } - mTrusted = valIn; -} - -//////////////////////////////////////////////////////////////////////////////// // BOOL LLMediaCtrl::handleHover( S32 x, S32 y, MASK mask ) { + if (LLPanel::handleHover(x, y, mask)) return TRUE; convertInputCoords(x, y); if (mMediaSource) @@ -193,6 +189,7 @@ BOOL LLMediaCtrl::handleHover( S32 x, S32 y, MASK mask ) // BOOL LLMediaCtrl::handleScrollWheel( S32 x, S32 y, S32 clicks ) { + if (LLPanel::handleScrollWheel(x, y, clicks)) return TRUE; if (mMediaSource && mMediaSource->hasMedia()) mMediaSource->getMediaPlugin()->scrollEvent(0, clicks, gKeyboard->currentMask(TRUE)); @@ -203,6 +200,7 @@ BOOL LLMediaCtrl::handleScrollWheel( S32 x, S32 y, S32 clicks ) // BOOL LLMediaCtrl::handleMouseUp( S32 x, S32 y, MASK mask ) { + if (LLPanel::handleMouseUp(x, y, mask)) return TRUE; convertInputCoords(x, y); if (mMediaSource) @@ -227,6 +225,7 @@ BOOL LLMediaCtrl::handleMouseUp( S32 x, S32 y, MASK mask ) // BOOL LLMediaCtrl::handleMouseDown( S32 x, S32 y, MASK mask ) { + if (LLPanel::handleMouseDown(x, y, mask)) return TRUE; convertInputCoords(x, y); if (mMediaSource) @@ -246,6 +245,7 @@ BOOL LLMediaCtrl::handleMouseDown( S32 x, S32 y, MASK mask ) // BOOL LLMediaCtrl::handleRightMouseUp( S32 x, S32 y, MASK mask ) { + if (LLPanel::handleRightMouseUp(x, y, mask)) return TRUE; convertInputCoords(x, y); if (mMediaSource) @@ -270,6 +270,7 @@ BOOL LLMediaCtrl::handleRightMouseUp( S32 x, S32 y, MASK mask ) // BOOL LLMediaCtrl::handleRightMouseDown( S32 x, S32 y, MASK mask ) { + if (LLPanel::handleRightMouseDown(x, y, mask)) return TRUE; convertInputCoords(x, y); if (mMediaSource) @@ -289,6 +290,7 @@ BOOL LLMediaCtrl::handleRightMouseDown( S32 x, S32 y, MASK mask ) // BOOL LLMediaCtrl::handleDoubleClick( S32 x, S32 y, MASK mask ) { + if (LLPanel::handleDoubleClick(x, y, mask)) return TRUE; convertInputCoords(x, y); if (mMediaSource) @@ -343,6 +345,85 @@ void LLMediaCtrl::onFocusLost() // BOOL LLMediaCtrl::postBuild () { + LLLayoutStack::Params layout_p; + layout_p.name = "notification_stack"; + layout_p.rect = LLRect(0,getLocalRect().mTop,getLocalRect().mRight, 30); + layout_p.follows.flags = FOLLOWS_ALL; + layout_p.mouse_opaque = false; + layout_p.orientation = "vertical"; + + LLLayoutStack* stackp = LLUICtrlFactory::create<LLLayoutStack>(layout_p); + addChild(stackp); + + LLLayoutPanel::Params panel_p; + panel_p.rect = LLRect(0, 30, 800, 0); + panel_p.min_height = 30; + panel_p.name = "notification_area"; + panel_p.visible = false; + panel_p.user_resize = false; + panel_p.background_visible = true; + panel_p.bg_alpha_image.name = "Yellow_Gradient"; + panel_p.auto_resize = false; + LLLayoutPanel* notification_panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p); + stackp->addChild(notification_panel); + + panel_p = LLUICtrlFactory::getDefaultParams<LLLayoutPanel>(); + panel_p.auto_resize = true; + panel_p.mouse_opaque = false; + LLLayoutPanel* dummy_panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p); + stackp->addChild(dummy_panel); + + layout_p = LLUICtrlFactory::getDefaultParams<LLLayoutStack>(); + layout_p.rect = LLRect(0, 30, 800, 0); + layout_p.follows.flags = FOLLOWS_ALL; + layout_p.orientation = "horizontal"; + stackp = LLUICtrlFactory::create<LLLayoutStack>(layout_p); + notification_panel->addChild(stackp); + + panel_p = LLUICtrlFactory::getDefaultParams<LLLayoutPanel>(); + panel_p.rect.height = 30; + LLLayoutPanel* panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p); + stackp->addChild(panel); + + LLIconCtrl::Params icon_p; + icon_p.name = "notification_icon"; + icon_p.rect = LLRect(5, 23, 21, 8); + panel->addChild(LLUICtrlFactory::create<LLIconCtrl>(icon_p)); + + LLTextBox::Params text_p; + text_p.rect = LLRect(31, 20, 430, 0); + text_p.text_color = LLColor4::black; + text_p.font = LLFontGL::getFontSansSerif(); + text_p.font.style = "BOLD"; + text_p.name = "notification_text"; + text_p.use_ellipses = true; + panel->addChild(LLUICtrlFactory::create<LLTextBox>(text_p)); + + panel_p = LLUICtrlFactory::getDefaultParams<LLLayoutPanel>(); + panel_p.auto_resize = false; + panel_p.user_resize = false; + panel_p.name="form_elements"; + panel_p.rect = LLRect(0, 30, 130, 0); + LLLayoutPanel* form_elements_panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p); + stackp->addChild(form_elements_panel); + + panel_p = LLUICtrlFactory::getDefaultParams<LLLayoutPanel>(); + panel_p.auto_resize = false; + panel_p.user_resize = false; + panel_p.rect = LLRect(0, 30, 25, 0); + LLLayoutPanel* close_panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p); + stackp->addChild(close_panel); + + LLButton::Params button_p; + button_p.name = "close_notification"; + button_p.rect = LLRect(5, 23, 21, 7); + button_p.image_color=LLUIColorTable::instance().getColor("DkGray_66"); + button_p.image_unselected.name="Icon_Close_Foreground"; + button_p.image_selected.name="Icon_Close_Press"; + button_p.click_callback.function = boost::bind(&LLMediaCtrl::onCloseNotification, this); + + close_panel->addChild(LLUICtrlFactory::create<LLButton>(button_p)); + setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChange, this, _2)); return TRUE; } @@ -351,6 +432,7 @@ BOOL LLMediaCtrl::postBuild () // BOOL LLMediaCtrl::handleKeyHere( KEY key, MASK mask ) { + if (LLPanel::handleKeyHere(key, mask)) return TRUE; BOOL result = FALSE; if (mMediaSource) @@ -376,6 +458,7 @@ void LLMediaCtrl::handleVisibilityChange ( BOOL new_visibility ) // BOOL LLMediaCtrl::handleUnicodeCharHere(llwchar uni_char) { + if (LLPanel::handleUnicodeCharHere(uni_char)) return TRUE; BOOL result = FALSE; if (mMediaSource) @@ -567,12 +650,21 @@ void LLMediaCtrl::navigateHome() //////////////////////////////////////////////////////////////////////////////// // -void LLMediaCtrl::setHomePageUrl( const std::string urlIn ) +void LLMediaCtrl::setHomePageUrl( const std::string& urlIn, const std::string& mime_type ) { mHomePageUrl = urlIn; if (mMediaSource) { - mMediaSource->setHomeURL(mHomePageUrl); + mMediaSource->setHomeURL(mHomePageUrl, mime_type); + } +} + +void LLMediaCtrl::setTarget(const std::string& target) +{ + mTarget = target; + if (mMediaSource) + { + mMediaSource->setTarget(mTarget); } } @@ -616,7 +708,8 @@ bool LLMediaCtrl::ensureMediaSourceExists() if ( mMediaSource ) { mMediaSource->setUsedInUI(true); - mMediaSource->setHomeURL(mHomePageUrl); + mMediaSource->setHomeURL(mHomePageUrl, mHomePageMimeType); + mMediaSource->setTarget(mTarget); mMediaSource->setVisible( getVisible() ); mMediaSource->addObserver( this ); mMediaSource->setBackgroundColor( getBackgroundColor() ); @@ -828,6 +921,10 @@ void LLMediaCtrl::draw() if ( mBorder && mBorder->getVisible() ) mBorder->setKeyboardFocusHighlight( gFocusMgr.childHasKeyboardFocus( this ) ); + if (mCurNotification && !mCurNotification->isActive()) + { + hideNotification(); + } LLPanel::draw(); @@ -894,6 +991,7 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) case MEDIA_EVENT_NAVIGATE_BEGIN: { LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_BEGIN, url is " << self->getNavigateURI() << LL_ENDL; + hideNotification(); }; break; @@ -928,9 +1026,27 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) case MEDIA_EVENT_CLICK_LINK_HREF: { LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << self->getClickTarget() << "\", uri is " << self->getClickURL() << LL_ENDL; + // retrieve the event parameters + std::string url = self->getClickURL(); + std::string target = self->getClickTarget(); + std::string uuid = self->getClickUUID(); + + LLNotification::Params notify_params; + notify_params.name = "PopupAttempt"; + notify_params.payload = LLSD().with("target", target).with("url", url).with("uuid", uuid).with("media_id", getKey()); + 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; }; - break; - + case MEDIA_EVENT_CLICK_LINK_NOFOLLOW: { LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is " << self->getClickURL() << LL_ENDL; @@ -954,6 +1070,24 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) 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; }; // chain all events to any potential observers of this object. @@ -967,3 +1101,113 @@ 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::proxyWindowClosed(notification["payload"]["uuid"]); + } + +} + +void LLMediaCtrl::onCloseNotification() +{ + LLNotifications::instance().cancel(mCurNotification); +} + +void LLMediaCtrl::onClickIgnore(LLUICtrl* ctrl) +{ + bool check = ctrl->getValue().asBoolean(); + if (mCurNotification && mCurNotification->getForm()->getIgnoreType() == LLNotificationForm::IGNORE_SHOW_AGAIN) + { + // question was "show again" so invert value to get "ignore" + check = !check; + } + mCurNotification->setIgnored(check); +} + +void LLMediaCtrl::onClickNotificationButton(const std::string& name) +{ + if (!mCurNotification) return; + + LLSD response = mCurNotification->getResponseTemplate(); + response[name] = true; + + mCurNotification->respond(response); +} + +void LLMediaCtrl::showNotification(LLNotificationPtr notify) +{ + mCurNotification = notify; + + // add popup here + LLSD payload = notify->getPayload(); + + LLNotificationFormPtr formp = notify->getForm(); + LLLayoutPanel& panel = getChildRef<LLLayoutPanel>("notification_area"); + panel.setVisible(true); + panel.getChild<LLUICtrl>("notification_icon")->setValue(notify->getIcon()); + panel.getChild<LLUICtrl>("notification_text")->setValue(notify->getMessage()); + panel.getChild<LLUICtrl>("notification_text")->setToolTip(notify->getMessage()); + LLNotificationForm::EIgnoreType ignore_type = formp->getIgnoreType(); + LLLayoutPanel& form_elements = panel.getChildRef<LLLayoutPanel>("form_elements"); + form_elements.deleteAllChildren(); + + const S32 FORM_PADDING_HORIZONTAL = 10; + const S32 FORM_PADDING_VERTICAL = 3; + S32 cur_x = FORM_PADDING_HORIZONTAL; + + if (ignore_type != LLNotificationForm::IGNORE_NO) + { + LLCheckBoxCtrl::Params checkbox_p; + checkbox_p.name = "ignore_check"; + checkbox_p.rect = LLRect(cur_x, form_elements.getRect().getHeight() - FORM_PADDING_VERTICAL, cur_x, FORM_PADDING_VERTICAL); + checkbox_p.label = formp->getIgnoreMessage(); + checkbox_p.label_text.text_color = LLColor4::black; + checkbox_p.commit_callback.function = boost::bind(&LLMediaCtrl::onClickIgnore, this, _1); + checkbox_p.initial_value = formp->getIgnored(); + + LLCheckBoxCtrl* check = LLUICtrlFactory::create<LLCheckBoxCtrl>(checkbox_p); + check->setRect(check->getBoundingRect()); + form_elements.addChild(check); + cur_x = check->getRect().mRight + FORM_PADDING_HORIZONTAL; + } + + for (S32 i = 0; i < formp->getNumElements(); i++) + { + LLSD form_element = formp->getElement(i); + if (form_element["type"].asString() == "button") + { + LLButton::Params button_p; + button_p.name = form_element["name"]; + button_p.label = form_element["text"]; + button_p.rect = LLRect(cur_x, form_elements.getRect().getHeight() - FORM_PADDING_VERTICAL, cur_x, FORM_PADDING_VERTICAL); + button_p.click_callback.function = boost::bind(&LLMediaCtrl::onClickNotificationButton, this, form_element["name"].asString()); + button_p.auto_resize = true; + + LLButton* button = LLUICtrlFactory::create<LLButton>(button_p); + button->autoResize(); + form_elements.addChild(button); + + cur_x = button->getRect().mRight + FORM_PADDING_HORIZONTAL; + } + } + + + form_elements.reshape(cur_x, form_elements.getRect().getHeight()); + + //LLWeb::loadURL(payload["url"], payload["target"]); +} + +void LLMediaCtrl::hideNotification() +{ + LLLayoutPanel& panel = getChildRef<LLLayoutPanel>("notification_area"); + panel.setVisible(FALSE); + + mCurNotification.reset(); +} |